mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
react panels: working on changing type
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import { PanelPlugin } from 'app/types/plugins';
|
||||||
|
|
||||||
export interface BuildInfo {
|
export interface BuildInfo {
|
||||||
version: string;
|
version: string;
|
||||||
@@ -7,17 +8,6 @@ export interface BuildInfo {
|
|||||||
env: string;
|
env: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PanelPlugin {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
meta: any;
|
|
||||||
hideFromList: boolean;
|
|
||||||
module: string;
|
|
||||||
baseUrl: string;
|
|
||||||
info: any;
|
|
||||||
sort: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Settings {
|
export class Settings {
|
||||||
datasources: any;
|
datasources: any;
|
||||||
panels: PanelPlugin[];
|
panels: PanelPlugin[];
|
||||||
|
|||||||
@@ -171,6 +171,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
|
|||||||
|
|
||||||
renderPanels() {
|
renderPanels() {
|
||||||
const panelElements = [];
|
const panelElements = [];
|
||||||
|
console.log('render panels');
|
||||||
|
|
||||||
for (let panel of this.props.dashboard.panels) {
|
for (let panel of this.props.dashboard.panels) {
|
||||||
const panelClasses = classNames({ panel: true, 'panel--fullscreen': panel.fullscreen });
|
const panelClasses = classNames({ panel: true, 'panel--fullscreen': panel.fullscreen });
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ import { DashboardModel } from '../dashboard_model';
|
|||||||
import { getAngularLoader, AngularComponent } from 'app/core/services/angular_loader';
|
import { getAngularLoader, AngularComponent } from 'app/core/services/angular_loader';
|
||||||
import { DashboardRow } from './DashboardRow';
|
import { DashboardRow } from './DashboardRow';
|
||||||
import { AddPanelPanel } from './AddPanelPanel';
|
import { AddPanelPanel } from './AddPanelPanel';
|
||||||
import { importPluginModule, PluginExports } from 'app/features/plugins/plugin_loader';
|
import { importPluginModule } from 'app/features/plugins/plugin_loader';
|
||||||
|
import { PluginExports } from 'app/types/plugins';
|
||||||
import { PanelChrome } from './PanelChrome';
|
import { PanelChrome } from './PanelChrome';
|
||||||
|
import { PanelEditor } from './PanelEditor';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
panel: PanelModel;
|
panel: PanelModel;
|
||||||
@@ -29,15 +31,11 @@ export class DashboardPanel extends React.Component<Props, State> {
|
|||||||
|
|
||||||
this.specialPanels['row'] = this.renderRow.bind(this);
|
this.specialPanels['row'] = this.renderRow.bind(this);
|
||||||
this.specialPanels['add-panel'] = this.renderAddPanel.bind(this);
|
this.specialPanels['add-panel'] = this.renderAddPanel.bind(this);
|
||||||
|
this.props.panel.events.on('panel-size-changed', this.triggerForceUpdate.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.isSpecial()) {
|
triggerForceUpdate() {
|
||||||
this.pluginInfo = config.panels[this.props.panel.type];
|
this.forceUpdate();
|
||||||
|
|
||||||
// load panel plugin
|
|
||||||
importPluginModule(this.pluginInfo.module).then(pluginExports => {
|
|
||||||
this.setState({ pluginExports: pluginExports });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isSpecial() {
|
isSpecial() {
|
||||||
@@ -52,8 +50,33 @@ export class DashboardPanel extends React.Component<Props, State> {
|
|||||||
return <AddPanelPanel panel={this.props.panel} dashboard={this.props.dashboard} />;
|
return <AddPanelPanel panel={this.props.panel} dashboard={this.props.dashboard} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadPlugin() {
|
||||||
|
if (this.isSpecial()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle plugin loading & changing of plugin type
|
||||||
|
if (!this.pluginInfo || this.pluginInfo.id !== this.props.panel.type) {
|
||||||
|
this.pluginInfo = config.panels[this.props.panel.type];
|
||||||
|
|
||||||
|
if (this.pluginInfo.exports) {
|
||||||
|
this.setState({ pluginExports: this.pluginInfo.exports });
|
||||||
|
} else {
|
||||||
|
importPluginModule(this.pluginInfo.module).then(pluginExports => {
|
||||||
|
this.setState({ pluginExports: pluginExports });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.loadPlugin();
|
||||||
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
// skip loading angular component if we have no element or we have already loaded it
|
this.loadPlugin();
|
||||||
|
|
||||||
|
// handle angular plugin loading
|
||||||
if (!this.element || this.angularPanel) {
|
if (!this.element || this.angularPanel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -70,25 +93,43 @@ export class DashboardPanel extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
renderReactPanel() {
|
||||||
const { pluginExports } = this.state;
|
const { pluginExports } = this.state;
|
||||||
|
const containerClass = this.props.panel.isEditing ? 'panel-editor-container' : 'panel-height-helper';
|
||||||
|
const panelWrapperClass = this.props.panel.isEditing ? 'panel-editor-container__panel' : 'panel-height-helper';
|
||||||
|
|
||||||
|
// this might look strange with these classes that change when edit, but
|
||||||
|
// I want to try to keep markup (parents) for panel the same in edit mode to avoide unmount / new mount of panel
|
||||||
|
// plugin component
|
||||||
|
return (
|
||||||
|
<div className={containerClass}>
|
||||||
|
<div className={panelWrapperClass}>
|
||||||
|
<PanelChrome
|
||||||
|
component={pluginExports.PanelComponent}
|
||||||
|
panel={this.props.panel}
|
||||||
|
dashboard={this.props.dashboard}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{this.props.panel.isEditing && (
|
||||||
|
<div className="panel-editor-container__editor">
|
||||||
|
<PanelEditor panel={this.props.panel} dashboard={this.props.dashboard} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
if (this.isSpecial()) {
|
if (this.isSpecial()) {
|
||||||
return this.specialPanels[this.props.panel.type]();
|
return this.specialPanels[this.props.panel.type]();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pluginExports) {
|
if (!this.state.pluginExports) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pluginExports.PanelComponent) {
|
if (this.state.pluginExports.PanelComponent) {
|
||||||
return (
|
return this.renderReactPanel();
|
||||||
<PanelChrome
|
|
||||||
component={pluginExports.PanelComponent}
|
|
||||||
panel={this.props.panel}
|
|
||||||
dashboard={this.props.dashboard}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// legacy angular rendering
|
// legacy angular rendering
|
||||||
|
|||||||
@@ -2,23 +2,16 @@ import React, { ComponentClass } from 'react';
|
|||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import { PanelModel } from '../panel_model';
|
import { PanelModel } from '../panel_model';
|
||||||
import { DashboardModel } from '../dashboard_model';
|
import { DashboardModel } from '../dashboard_model';
|
||||||
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN } from 'app/core/constants';
|
|
||||||
import { PanelHeader } from './PanelHeader';
|
import { PanelHeader } from './PanelHeader';
|
||||||
import { PanelEditor } from './PanelEditor';
|
|
||||||
import { DataPanel, PanelProps, DataPanelWrapper } from './DataPanel';
|
import { DataPanel, PanelProps, DataPanelWrapper } from './DataPanel';
|
||||||
|
|
||||||
const TITLE_HEIGHT = 27;
|
|
||||||
const PANEL_BORDER = 2;
|
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
panel: PanelModel;
|
panel: PanelModel;
|
||||||
dashboard: DashboardModel;
|
dashboard: DashboardModel;
|
||||||
component: ComponentClass<PanelProps>;
|
component: ComponentClass<PanelProps>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {}
|
||||||
height: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PanelChrome extends React.Component<Props, State> {
|
export class PanelChrome extends React.Component<Props, State> {
|
||||||
panelComponent: DataPanel;
|
panelComponent: DataPanel;
|
||||||
@@ -26,20 +19,9 @@ export class PanelChrome extends React.Component<Props, State> {
|
|||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
|
||||||
height: this.getPanelHeight(),
|
|
||||||
};
|
|
||||||
|
|
||||||
this.panelComponent = DataPanelWrapper(this.props.component);
|
this.panelComponent = DataPanelWrapper(this.props.component);
|
||||||
this.props.panel.events.on('panel-size-changed', this.onPanelSizeChanged);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onPanelSizeChanged = () => {
|
|
||||||
this.setState({
|
|
||||||
height: this.getPanelHeight(),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
console.log('panel chrome mounted');
|
console.log('panel chrome mounted');
|
||||||
}
|
}
|
||||||
@@ -48,31 +30,10 @@ export class PanelChrome extends React.Component<Props, State> {
|
|||||||
let PanelComponent = this.panelComponent;
|
let PanelComponent = this.panelComponent;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="panel-editor-container">
|
<div className="panel-container">
|
||||||
<div className="panel-container">
|
<PanelHeader panel={this.props.panel} dashboard={this.props.dashboard} />
|
||||||
<PanelHeader panel={this.props.panel} dashboard={this.props.dashboard} />
|
<div className="panel-content">{<PanelComponent type={'test'} queries={[]} isVisible={true} />}</div>
|
||||||
<div className="panel-content" style={{ height: this.state.height }}>
|
|
||||||
{<PanelComponent type={'test'} queries={[]} isVisible={true} />}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{this.props.panel.isEditing && <PanelEditor panel={this.props.panel} dashboard={this.props.dashboard} />}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPanelHeight() {
|
|
||||||
const panel = this.props.panel;
|
|
||||||
let height = 0;
|
|
||||||
|
|
||||||
if (panel.fullscreen) {
|
|
||||||
var docHeight = $(window).height();
|
|
||||||
var editHeight = Math.floor(docHeight * 0.3);
|
|
||||||
var fullscreenHeight = Math.floor(docHeight * 0.8);
|
|
||||||
height = panel.isEditing ? editHeight : fullscreenHeight;
|
|
||||||
} else {
|
|
||||||
height = panel.gridPos.h * GRID_CELL_HEIGHT + (panel.gridPos.h - 1) * GRID_CELL_VMARGIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
return height - (PANEL_BORDER + TITLE_HEIGHT);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { DashboardModel } from '../dashboard_model';
|
|||||||
import { store } from 'app/stores/store';
|
import { store } from 'app/stores/store';
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import { QueriesTab } from './QueriesTab';
|
import { QueriesTab } from './QueriesTab';
|
||||||
import { PanelPlugin } from 'app/core/config';
|
import { PanelPlugin } from 'app/types/plugins';
|
||||||
import { VizTypePicker } from './VizTypePicker';
|
import { VizTypePicker } from './VizTypePicker';
|
||||||
|
|
||||||
interface PanelEditorProps {
|
interface PanelEditorProps {
|
||||||
@@ -50,8 +50,8 @@ export class PanelEditor extends React.Component<PanelEditorProps, any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onVizTypeChanged = (plugin: PanelPlugin) => {
|
onVizTypeChanged = (plugin: PanelPlugin) => {
|
||||||
this.props.panel.type = plugin.id;
|
console.log('changing type to ', plugin.id);
|
||||||
this.forceUpdate();
|
this.props.panel.changeType(plugin.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
onChangeTab = (tab: PanelEditorTab) => {
|
onChangeTab = (tab: PanelEditorTab) => {
|
||||||
|
|||||||
@@ -21,6 +21,16 @@ export class PanelHeader extends React.Component<PanelHeaderProps, any> {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onViewPanel = () => {
|
||||||
|
store.view.updateQuery(
|
||||||
|
{
|
||||||
|
panelId: this.props.panel.id,
|
||||||
|
fullscreen: true,
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let isFullscreen = false;
|
let isFullscreen = false;
|
||||||
let isLoading = false;
|
let isLoading = false;
|
||||||
@@ -52,7 +62,9 @@ export class PanelHeader extends React.Component<PanelHeaderProps, any> {
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="asd">asd</a>
|
<a onClick={this.onViewPanel}>
|
||||||
|
<i className="fa fa-fw fa-eye" /> View
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import config, { PanelPlugin } from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
|
import { PanelPlugin } from 'app/types/plugins';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|||||||
@@ -97,6 +97,11 @@ export class PanelModel {
|
|||||||
this.events.emit('panel-init-edit-mode');
|
this.events.emit('panel-init-edit-mode');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changeType(newType: string) {
|
||||||
|
this.type = newType;
|
||||||
|
this.events.emit('panel-size-changed');
|
||||||
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
this.events.removeAllListeners();
|
this.events.removeAllListeners();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import * as mssqlPlugin from 'app/plugins/datasource/mssql/module';
|
|||||||
|
|
||||||
import * as textPanel from 'app/plugins/panel/text/module';
|
import * as textPanel from 'app/plugins/panel/text/module';
|
||||||
import * as text2Panel from 'app/plugins/panel/text2/module';
|
import * as text2Panel from 'app/plugins/panel/text2/module';
|
||||||
|
import * as graph2Panel from 'app/plugins/panel/graph2/module';
|
||||||
import * as graphPanel from 'app/plugins/panel/graph/module';
|
import * as graphPanel from 'app/plugins/panel/graph/module';
|
||||||
import * as dashListPanel from 'app/plugins/panel/dashlist/module';
|
import * as dashListPanel from 'app/plugins/panel/dashlist/module';
|
||||||
import * as pluginsListPanel from 'app/plugins/panel/pluginlist/module';
|
import * as pluginsListPanel from 'app/plugins/panel/pluginlist/module';
|
||||||
@@ -41,6 +42,7 @@ const builtInPlugins = {
|
|||||||
|
|
||||||
'app/plugins/panel/text/module': textPanel,
|
'app/plugins/panel/text/module': textPanel,
|
||||||
'app/plugins/panel/text2/module': text2Panel,
|
'app/plugins/panel/text2/module': text2Panel,
|
||||||
|
'app/plugins/panel/graph2/module': graph2Panel,
|
||||||
'app/plugins/panel/graph/module': graphPanel,
|
'app/plugins/panel/graph/module': graphPanel,
|
||||||
'app/plugins/panel/dashlist/module': dashListPanel,
|
'app/plugins/panel/dashlist/module': dashListPanel,
|
||||||
'app/plugins/panel/pluginlist/module': pluginsListPanel,
|
'app/plugins/panel/pluginlist/module': pluginsListPanel,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import config from 'app/core/config';
|
|||||||
import TimeSeries from 'app/core/time_series2';
|
import TimeSeries from 'app/core/time_series2';
|
||||||
import TableModel from 'app/core/table_model';
|
import TableModel from 'app/core/table_model';
|
||||||
import { coreModule, appEvents, contextSrv } from 'app/core/core';
|
import { coreModule, appEvents, contextSrv } from 'app/core/core';
|
||||||
|
import { PluginExports } from 'app/types/plugins';
|
||||||
import * as datemath from 'app/core/utils/datemath';
|
import * as datemath from 'app/core/utils/datemath';
|
||||||
import * as fileExport from 'app/core/utils/file_export';
|
import * as fileExport from 'app/core/utils/file_export';
|
||||||
import * as flatten from 'app/core/utils/flatten';
|
import * as flatten from 'app/core/utils/flatten';
|
||||||
@@ -143,16 +144,6 @@ for (let flotDep of flotDeps) {
|
|||||||
exposeToPlugin(flotDep, { fakeDep: 1 });
|
exposeToPlugin(flotDep, { fakeDep: 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PluginExports {
|
|
||||||
PanelCtrl?;
|
|
||||||
any;
|
|
||||||
PanelComponent?: any;
|
|
||||||
Datasource?: any;
|
|
||||||
QueryCtrl?: any;
|
|
||||||
ConfigCtrl?: any;
|
|
||||||
AnnotationsQueryCtrl?: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function importPluginModule(path: string): Promise<PluginExports> {
|
export function importPluginModule(path: string): Promise<PluginExports> {
|
||||||
let builtIn = builtInPlugins[path];
|
let builtIn = builtInPlugins[path];
|
||||||
if (builtIn) {
|
if (builtIn) {
|
||||||
|
|||||||
5
public/app/plugins/panel/graph2/README.md
Normal file
5
public/app/plugins/panel/graph2/README.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Text Panel - Native Plugin
|
||||||
|
|
||||||
|
The Text Panel is **included** with Grafana.
|
||||||
|
|
||||||
|
The Text Panel is a very simple panel that displays text. The source text is written in the Markdown syntax meaning you can format the text. Read [GitHub's Mastering Markdown](https://guides.github.com/features/mastering-markdown/) to learn more.
|
||||||
186
public/app/plugins/panel/graph2/img/icn-graph-panel.svg
Normal file
186
public/app/plugins/panel/graph2/img/icn-graph-panel.svg
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="100px" height="100px" viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
|
||||||
|
<polyline style="fill:none;stroke:#898989;stroke-width:2;stroke-miterlimit:10;" points="4.734,34.349 36.05,19.26 64.876,36.751
|
||||||
|
96.308,6.946 "/>
|
||||||
|
<circle style="fill:#898989;" cx="4.885" cy="33.929" r="4.885"/>
|
||||||
|
<circle style="fill:#898989;" cx="35.95" cy="19.545" r="4.885"/>
|
||||||
|
<circle style="fill:#898989;" cx="65.047" cy="36.046" r="4.885"/>
|
||||||
|
<circle style="fill:#898989;" cx="94.955" cy="7.135" r="4.885"/>
|
||||||
|
<g>
|
||||||
|
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="5" y1="103.7019" x2="5" y2="32.0424">
|
||||||
|
<stop offset="0" style="stop-color:#FFF33B"/>
|
||||||
|
<stop offset="0" style="stop-color:#FFD53F"/>
|
||||||
|
<stop offset="0" style="stop-color:#FBBC40"/>
|
||||||
|
<stop offset="0" style="stop-color:#F7A840"/>
|
||||||
|
<stop offset="0" style="stop-color:#F59B40"/>
|
||||||
|
<stop offset="0" style="stop-color:#F3933F"/>
|
||||||
|
<stop offset="0" style="stop-color:#F3903F"/>
|
||||||
|
<stop offset="0.8423" style="stop-color:#ED683C"/>
|
||||||
|
<stop offset="1" style="stop-color:#E93E3A"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_1_);" d="M9.001,48.173H0.999C0.447,48.173,0,48.62,0,49.172V100h10V49.172
|
||||||
|
C10,48.62,9.553,48.173,9.001,48.173z"/>
|
||||||
|
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="5" y1="98.9423" x2="5" y2="53.1961">
|
||||||
|
<stop offset="0" style="stop-color:#FEBC11"/>
|
||||||
|
<stop offset="1" style="stop-color:#F99B1C"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_2_);" d="M0,69.173v30.563h10V69.173"/>
|
||||||
|
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="5" y1="99.4343" x2="5" y2="74.4359">
|
||||||
|
<stop offset="0" style="stop-color:#FEBC11"/>
|
||||||
|
<stop offset="1" style="stop-color:#FFDE17"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_3_);" d="M0,83.166v16.701h10V83.166"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="20" y1="103.7019" x2="20" y2="32.0424">
|
||||||
|
<stop offset="0" style="stop-color:#FFF33B"/>
|
||||||
|
<stop offset="0" style="stop-color:#FFD53F"/>
|
||||||
|
<stop offset="0" style="stop-color:#FBBC40"/>
|
||||||
|
<stop offset="0" style="stop-color:#F7A840"/>
|
||||||
|
<stop offset="0" style="stop-color:#F59B40"/>
|
||||||
|
<stop offset="0" style="stop-color:#F3933F"/>
|
||||||
|
<stop offset="0" style="stop-color:#F3903F"/>
|
||||||
|
<stop offset="0.8423" style="stop-color:#ED683C"/>
|
||||||
|
<stop offset="1" style="stop-color:#E93E3A"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_4_);" d="M24.001,40.769h-8.002c-0.552,0-0.999,0.447-0.999,0.999V100h10V41.768
|
||||||
|
C25,41.216,24.553,40.769,24.001,40.769z"/>
|
||||||
|
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="20" y1="98.9423" x2="20" y2="53.1961">
|
||||||
|
<stop offset="0" style="stop-color:#FEBC11"/>
|
||||||
|
<stop offset="1" style="stop-color:#F99B1C"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_5_);" d="M15,64.716v35.02h10v-35.02"/>
|
||||||
|
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="20" y1="99.4343" x2="20" y2="74.4359">
|
||||||
|
<stop offset="0" style="stop-color:#FEBC11"/>
|
||||||
|
<stop offset="1" style="stop-color:#FFDE17"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_6_);" d="M15,80.731v19.137h10V80.731"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="35" y1="103.7019" x2="35" y2="32.0424">
|
||||||
|
<stop offset="0" style="stop-color:#FFF33B"/>
|
||||||
|
<stop offset="0" style="stop-color:#FFD53F"/>
|
||||||
|
<stop offset="0" style="stop-color:#FBBC40"/>
|
||||||
|
<stop offset="0" style="stop-color:#F7A840"/>
|
||||||
|
<stop offset="0" style="stop-color:#F59B40"/>
|
||||||
|
<stop offset="0" style="stop-color:#F3933F"/>
|
||||||
|
<stop offset="0" style="stop-color:#F3903F"/>
|
||||||
|
<stop offset="0.8423" style="stop-color:#ED683C"/>
|
||||||
|
<stop offset="1" style="stop-color:#E93E3A"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_7_);" d="M39.001,34.423h-8.002c-0.552,0-0.999,0.447-0.999,0.999V100h10V35.422
|
||||||
|
C40,34.87,39.553,34.423,39.001,34.423z"/>
|
||||||
|
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="35" y1="98.9423" x2="35" y2="53.1961">
|
||||||
|
<stop offset="0" style="stop-color:#FEBC11"/>
|
||||||
|
<stop offset="1" style="stop-color:#F99B1C"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_8_);" d="M30,60.895v38.84h10v-38.84"/>
|
||||||
|
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="35" y1="99.4343" x2="35" y2="74.4359">
|
||||||
|
<stop offset="0" style="stop-color:#FEBC11"/>
|
||||||
|
<stop offset="1" style="stop-color:#FFDE17"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_9_);" d="M30,78.643v21.225h10V78.643"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="50" y1="103.7019" x2="50" y2="32.0424">
|
||||||
|
<stop offset="0" style="stop-color:#FFF33B"/>
|
||||||
|
<stop offset="0" style="stop-color:#FFD53F"/>
|
||||||
|
<stop offset="0" style="stop-color:#FBBC40"/>
|
||||||
|
<stop offset="0" style="stop-color:#F7A840"/>
|
||||||
|
<stop offset="0" style="stop-color:#F59B40"/>
|
||||||
|
<stop offset="0" style="stop-color:#F3933F"/>
|
||||||
|
<stop offset="0" style="stop-color:#F3903F"/>
|
||||||
|
<stop offset="0.8423" style="stop-color:#ED683C"/>
|
||||||
|
<stop offset="1" style="stop-color:#E93E3A"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_10_);" d="M54.001,41.827h-8.002c-0.552,0-0.999,0.447-0.999,0.999V100h10V42.826
|
||||||
|
C55,42.274,54.553,41.827,54.001,41.827z"/>
|
||||||
|
<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="50" y1="98.9423" x2="50" y2="53.1961">
|
||||||
|
<stop offset="0" style="stop-color:#FEBC11"/>
|
||||||
|
<stop offset="1" style="stop-color:#F99B1C"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_11_);" d="M45,65.352v34.383h10V65.352"/>
|
||||||
|
<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="50" y1="99.4343" x2="50" y2="74.4359">
|
||||||
|
<stop offset="0" style="stop-color:#FEBC11"/>
|
||||||
|
<stop offset="1" style="stop-color:#FFDE17"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_12_);" d="M45,81.079v18.789h10V81.079"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="65" y1="103.8575" x2="65" y2="29.1875">
|
||||||
|
<stop offset="0" style="stop-color:#FFF33B"/>
|
||||||
|
<stop offset="0" style="stop-color:#FFD53F"/>
|
||||||
|
<stop offset="0" style="stop-color:#FBBC40"/>
|
||||||
|
<stop offset="0" style="stop-color:#F7A840"/>
|
||||||
|
<stop offset="0" style="stop-color:#F59B40"/>
|
||||||
|
<stop offset="0" style="stop-color:#F3933F"/>
|
||||||
|
<stop offset="0" style="stop-color:#F3903F"/>
|
||||||
|
<stop offset="0.8423" style="stop-color:#ED683C"/>
|
||||||
|
<stop offset="1" style="stop-color:#E93E3A"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_13_);" d="M69.001,50.404h-8.002c-0.552,0-0.999,0.447-0.999,0.999V100h10V51.403
|
||||||
|
C70,50.851,69.553,50.404,69.001,50.404z"/>
|
||||||
|
<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="65" y1="98.8979" x2="65" y2="51.2298">
|
||||||
|
<stop offset="0" style="stop-color:#FEBC11"/>
|
||||||
|
<stop offset="1" style="stop-color:#F99B1C"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_14_);" d="M60,70.531v29.193h10V70.531"/>
|
||||||
|
<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="65" y1="99.4105" x2="65" y2="73.3619">
|
||||||
|
<stop offset="0" style="stop-color:#FEBC11"/>
|
||||||
|
<stop offset="1" style="stop-color:#FFDE17"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_15_);" d="M60,83.909v15.953h10V83.909"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<linearGradient id="SVGID_16_" gradientUnits="userSpaceOnUse" x1="80" y1="104.4108" x2="80" y2="19.0293">
|
||||||
|
<stop offset="0" style="stop-color:#FFF33B"/>
|
||||||
|
<stop offset="0" style="stop-color:#FFD53F"/>
|
||||||
|
<stop offset="0" style="stop-color:#FBBC40"/>
|
||||||
|
<stop offset="0" style="stop-color:#F7A840"/>
|
||||||
|
<stop offset="0" style="stop-color:#F59B40"/>
|
||||||
|
<stop offset="0" style="stop-color:#F3933F"/>
|
||||||
|
<stop offset="0" style="stop-color:#F3903F"/>
|
||||||
|
<stop offset="0.8423" style="stop-color:#ED683C"/>
|
||||||
|
<stop offset="1" style="stop-color:#E93E3A"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_16_);" d="M84.001,40.769h-8.002c-0.552,0-0.999,0.447-0.999,0.999V100h10V41.768
|
||||||
|
C85,41.216,84.553,40.769,84.001,40.769z"/>
|
||||||
|
<linearGradient id="SVGID_17_" gradientUnits="userSpaceOnUse" x1="80" y1="98.9423" x2="80" y2="53.1961">
|
||||||
|
<stop offset="0" style="stop-color:#FEBC11"/>
|
||||||
|
<stop offset="1" style="stop-color:#F99B1C"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_17_);" d="M75,64.716v35.02h10v-35.02"/>
|
||||||
|
<linearGradient id="SVGID_18_" gradientUnits="userSpaceOnUse" x1="80" y1="99.4343" x2="80" y2="74.4359">
|
||||||
|
<stop offset="0" style="stop-color:#FEBC11"/>
|
||||||
|
<stop offset="1" style="stop-color:#FFDE17"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_18_);" d="M75,80.731v19.137h10V80.731"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<linearGradient id="SVGID_19_" gradientUnits="userSpaceOnUse" x1="95" y1="103.5838" x2="95" y2="34.2115">
|
||||||
|
<stop offset="0" style="stop-color:#FFF33B"/>
|
||||||
|
<stop offset="0" style="stop-color:#FFD53F"/>
|
||||||
|
<stop offset="0" style="stop-color:#FBBC40"/>
|
||||||
|
<stop offset="0" style="stop-color:#F7A840"/>
|
||||||
|
<stop offset="0" style="stop-color:#F59B40"/>
|
||||||
|
<stop offset="0" style="stop-color:#F3933F"/>
|
||||||
|
<stop offset="0" style="stop-color:#F3903F"/>
|
||||||
|
<stop offset="0.8423" style="stop-color:#ED683C"/>
|
||||||
|
<stop offset="1" style="stop-color:#E93E3A"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_19_);" d="M99.001,21.157h-8.002c-0.552,0-0.999,0.447-0.999,0.999V100h10V22.156
|
||||||
|
C100,21.604,99.553,21.157,99.001,21.157z"/>
|
||||||
|
<linearGradient id="SVGID_20_" gradientUnits="userSpaceOnUse" x1="95" y1="98.9761" x2="95" y2="54.69">
|
||||||
|
<stop offset="0" style="stop-color:#FEBC11"/>
|
||||||
|
<stop offset="1" style="stop-color:#F99B1C"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_20_);" d="M90,52.898v46.846h10V52.898"/>
|
||||||
|
<linearGradient id="SVGID_21_" gradientUnits="userSpaceOnUse" x1="95" y1="99.4524" x2="95" y2="75.2518">
|
||||||
|
<stop offset="0" style="stop-color:#FEBC11"/>
|
||||||
|
<stop offset="1" style="stop-color:#FFDE17"/>
|
||||||
|
</linearGradient>
|
||||||
|
<path style="fill:url(#SVGID_21_);" d="M90,74.272v25.6h10v-25.6"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 9.8 KiB |
21
public/app/plugins/panel/graph2/module.tsx
Normal file
21
public/app/plugins/panel/graph2/module.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
import { PanelProps } from 'app/features/dashboard/dashgrid/DataPanel';
|
||||||
|
|
||||||
|
export class ReactTestPanel extends PureComponent<PanelProps> {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { data } = this.props;
|
||||||
|
let value = 0;
|
||||||
|
|
||||||
|
if (data.length) {
|
||||||
|
value = data[0].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <h2>Graph Panel! {value}</h2>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { ReactTestPanel as PanelComponent };
|
||||||
17
public/app/plugins/panel/graph2/plugin.json
Normal file
17
public/app/plugins/panel/graph2/plugin.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"type": "panel",
|
||||||
|
"name": "React Graph",
|
||||||
|
"id": "graph2",
|
||||||
|
|
||||||
|
"info": {
|
||||||
|
"author": {
|
||||||
|
"name": "Grafana Project",
|
||||||
|
"url": "https://grafana.com"
|
||||||
|
},
|
||||||
|
"logos": {
|
||||||
|
"small": "img/icn-graph-panel.svg",
|
||||||
|
"large": "img/icn-graph-panel.svg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ export class ReactTestPanel extends PureComponent<PanelProps> {
|
|||||||
value = data[0].value;
|
value = data[0].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <h2>I am a react value: {value}</h2>;
|
return <h2>Text Panel {value}</h2>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
20
public/app/types/plugins.ts
Normal file
20
public/app/types/plugins.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
export interface PluginExports {
|
||||||
|
PanelCtrl?;
|
||||||
|
PanelComponent?: any;
|
||||||
|
Datasource?: any;
|
||||||
|
QueryCtrl?: any;
|
||||||
|
ConfigCtrl?: any;
|
||||||
|
AnnotationsQueryCtrl?: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PanelPlugin {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
meta: any;
|
||||||
|
hideFromList: boolean;
|
||||||
|
module: string;
|
||||||
|
baseUrl: string;
|
||||||
|
info: any;
|
||||||
|
sort: number;
|
||||||
|
exports?: PluginExports;
|
||||||
|
}
|
||||||
@@ -35,11 +35,20 @@ div.flot-text {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.panel-editor-container__panel {
|
||||||
|
height: 35%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-editor-container__editor {
|
||||||
|
height: 65%;
|
||||||
|
}
|
||||||
|
|
||||||
.panel-container {
|
.panel-container {
|
||||||
background-color: $panel-bg;
|
background-color: $panel-bg;
|
||||||
border: $panel-border;
|
border: $panel-border;
|
||||||
position: relative;
|
position: relative;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
&.panel-transparent {
|
&.panel-transparent {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|||||||
Reference in New Issue
Block a user