react panels: working on changing type

pull/13578/head
Torkel Ödegaard 7 years ago
parent e052e165e9
commit 761283231c
  1. 12
      public/app/core/config.ts
  2. 1
      public/app/features/dashboard/dashgrid/DashboardGrid.tsx
  3. 81
      public/app/features/dashboard/dashgrid/DashboardPanel.tsx
  4. 47
      public/app/features/dashboard/dashgrid/PanelChrome.tsx
  5. 6
      public/app/features/dashboard/dashgrid/PanelEditor.tsx
  6. 14
      public/app/features/dashboard/dashgrid/PanelHeader.tsx
  7. 3
      public/app/features/dashboard/dashgrid/VizTypePicker.tsx
  8. 5
      public/app/features/dashboard/panel_model.ts
  9. 2
      public/app/features/plugins/built_in_plugins.ts
  10. 11
      public/app/features/plugins/plugin_loader.ts
  11. 5
      public/app/plugins/panel/graph2/README.md
  12. 186
      public/app/plugins/panel/graph2/img/icn-graph-panel.svg
  13. 21
      public/app/plugins/panel/graph2/module.tsx
  14. 17
      public/app/plugins/panel/graph2/plugin.json
  15. 2
      public/app/plugins/panel/text2/module.tsx
  16. 20
      public/app/types/plugins.ts
  17. 9
      public/sass/pages/_dashboard.scss

@ -1,4 +1,5 @@
import _ from 'lodash';
import { PanelPlugin } from 'app/types/plugins';
export interface BuildInfo {
version: string;
@ -7,17 +8,6 @@ export interface BuildInfo {
env: string;
}
export interface PanelPlugin {
id: string;
name: string;
meta: any;
hideFromList: boolean;
module: string;
baseUrl: string;
info: any;
sort: number;
}
export class Settings {
datasources: any;
panels: PanelPlugin[];

@ -171,6 +171,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
renderPanels() {
const panelElements = [];
console.log('render panels');
for (let panel of this.props.dashboard.panels) {
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 { DashboardRow } from './DashboardRow';
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 { PanelEditor } from './PanelEditor';
export interface Props {
panel: PanelModel;
@ -29,15 +31,11 @@ export class DashboardPanel extends React.Component<Props, State> {
this.specialPanels['row'] = this.renderRow.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()) {
this.pluginInfo = config.panels[this.props.panel.type];
// load panel plugin
importPluginModule(this.pluginInfo.module).then(pluginExports => {
this.setState({ pluginExports: pluginExports });
});
}
triggerForceUpdate() {
this.forceUpdate();
}
isSpecial() {
@ -52,8 +50,33 @@ export class DashboardPanel extends React.Component<Props, State> {
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() {
// 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) {
return;
}
@ -70,25 +93,43 @@ export class DashboardPanel extends React.Component<Props, State> {
}
}
render() {
renderReactPanel() {
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()) {
return this.specialPanels[this.props.panel.type]();
}
if (!pluginExports) {
if (!this.state.pluginExports) {
return null;
}
if (pluginExports.PanelComponent) {
return (
<PanelChrome
component={pluginExports.PanelComponent}
panel={this.props.panel}
dashboard={this.props.dashboard}
/>
);
if (this.state.pluginExports.PanelComponent) {
return this.renderReactPanel();
}
// legacy angular rendering

@ -2,23 +2,16 @@ import React, { ComponentClass } from 'react';
import $ from 'jquery';
import { PanelModel } from '../panel_model';
import { DashboardModel } from '../dashboard_model';
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN } from 'app/core/constants';
import { PanelHeader } from './PanelHeader';
import { PanelEditor } from './PanelEditor';
import { DataPanel, PanelProps, DataPanelWrapper } from './DataPanel';
const TITLE_HEIGHT = 27;
const PANEL_BORDER = 2;
export interface Props {
panel: PanelModel;
dashboard: DashboardModel;
component: ComponentClass<PanelProps>;
}
interface State {
height: number;
}
interface State {}
export class PanelChrome extends React.Component<Props, State> {
panelComponent: DataPanel;
@ -26,20 +19,9 @@ export class PanelChrome extends React.Component<Props, State> {
constructor(props) {
super(props);
this.state = {
height: this.getPanelHeight(),
};
this.panelComponent = DataPanelWrapper(this.props.component);
this.props.panel.events.on('panel-size-changed', this.onPanelSizeChanged);
}
onPanelSizeChanged = () => {
this.setState({
height: this.getPanelHeight(),
});
};
componentDidMount() {
console.log('panel chrome mounted');
}
@ -48,31 +30,10 @@ export class PanelChrome extends React.Component<Props, State> {
let PanelComponent = this.panelComponent;
return (
<div className="panel-editor-container">
<div className="panel-container">
<PanelHeader panel={this.props.panel} dashboard={this.props.dashboard} />
<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 className="panel-container">
<PanelHeader panel={this.props.panel} dashboard={this.props.dashboard} />
<div className="panel-content">{<PanelComponent type={'test'} queries={[]} isVisible={true} />}</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 { observer } from 'mobx-react';
import { QueriesTab } from './QueriesTab';
import { PanelPlugin } from 'app/core/config';
import { PanelPlugin } from 'app/types/plugins';
import { VizTypePicker } from './VizTypePicker';
interface PanelEditorProps {
@ -50,8 +50,8 @@ export class PanelEditor extends React.Component<PanelEditorProps, any> {
}
onVizTypeChanged = (plugin: PanelPlugin) => {
this.props.panel.type = plugin.id;
this.forceUpdate();
console.log('changing type to ', plugin.id);
this.props.panel.changeType(plugin.id);
};
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() {
let isFullscreen = false;
let isLoading = false;
@ -52,7 +62,9 @@ export class PanelHeader extends React.Component<PanelHeaderProps, any> {
</a>
</li>
<li>
<a href="asd">asd</a>
<a onClick={this.onViewPanel}>
<i className="fa fa-fw fa-eye" /> View
</a>
</li>
</ul>
</span>

@ -1,6 +1,7 @@
import React, { PureComponent } from 'react';
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';
interface Props {

@ -97,6 +97,11 @@ export class PanelModel {
this.events.emit('panel-init-edit-mode');
}
changeType(newType: string) {
this.type = newType;
this.events.emit('panel-size-changed');
}
destroy() {
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 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 dashListPanel from 'app/plugins/panel/dashlist/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/text2/module': text2Panel,
'app/plugins/panel/graph2/module': graph2Panel,
'app/plugins/panel/graph/module': graphPanel,
'app/plugins/panel/dashlist/module': dashListPanel,
'app/plugins/panel/pluginlist/module': pluginsListPanel,

@ -18,6 +18,7 @@ import config from 'app/core/config';
import TimeSeries from 'app/core/time_series2';
import TableModel from 'app/core/table_model';
import { coreModule, appEvents, contextSrv } from 'app/core/core';
import { PluginExports } from 'app/types/plugins';
import * as datemath from 'app/core/utils/datemath';
import * as fileExport from 'app/core/utils/file_export';
import * as flatten from 'app/core/utils/flatten';
@ -143,16 +144,6 @@ for (let flotDep of flotDeps) {
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> {
let builtIn = builtInPlugins[path];
if (builtIn) {

@ -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.

@ -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

@ -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 };

@ -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;
}
return <h2>I am a react value: {value}</h2>;
return <h2>Text Panel {value}</h2>;
}
}

@ -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%;
}
.panel-editor-container__panel {
height: 35%;
}
.panel-editor-container__editor {
height: 65%;
}
.panel-container {
background-color: $panel-bg;
border: $panel-border;
position: relative;
border-radius: 3px;
height: 100%;
&.panel-transparent {
background-color: transparent;

Loading…
Cancel
Save