2017-10-09 10:52:25 -05:00
|
|
|
import React from 'react';
|
2018-01-02 07:52:30 -06:00
|
|
|
import config from 'app/core/config';
|
|
|
|
import { PanelModel } from '../panel_model';
|
2018-01-03 06:33:54 -06:00
|
|
|
import { DashboardModel } from '../dashboard_model';
|
2018-06-19 14:25:57 -05:00
|
|
|
import { getAngularLoader, AngularComponent } from 'app/core/services/angular_loader';
|
2018-01-02 07:52:30 -06:00
|
|
|
import { DashboardRow } from './DashboardRow';
|
|
|
|
import { AddPanelPanel } from './AddPanelPanel';
|
2018-07-09 11:17:51 -05:00
|
|
|
import { importPluginModule } from 'app/features/plugins/plugin_loader';
|
2018-07-09 15:24:15 -05:00
|
|
|
import { PluginExports, PanelPlugin } from 'app/types/plugins';
|
2018-06-19 07:51:57 -05:00
|
|
|
import { PanelChrome } from './PanelChrome';
|
2018-07-09 11:17:51 -05:00
|
|
|
import { PanelEditor } from './PanelEditor';
|
2017-10-09 10:52:25 -05:00
|
|
|
|
2018-07-05 15:10:39 -05:00
|
|
|
export interface Props {
|
2018-08-25 14:22:50 -05:00
|
|
|
panelType: string;
|
2017-10-10 02:34:14 -05:00
|
|
|
panel: PanelModel;
|
2018-01-03 06:33:54 -06:00
|
|
|
dashboard: DashboardModel;
|
2017-10-09 10:52:25 -05:00
|
|
|
}
|
|
|
|
|
2018-07-05 15:10:39 -05:00
|
|
|
export interface State {
|
|
|
|
pluginExports: PluginExports;
|
|
|
|
}
|
|
|
|
|
|
|
|
export class DashboardPanel extends React.Component<Props, State> {
|
2017-10-10 02:34:14 -05:00
|
|
|
element: any;
|
2018-06-19 14:25:57 -05:00
|
|
|
angularPanel: AngularComponent;
|
2018-01-02 07:52:30 -06:00
|
|
|
pluginInfo: any;
|
|
|
|
specialPanels = {};
|
2017-10-09 10:52:25 -05:00
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2018-07-09 15:24:15 -05:00
|
|
|
|
|
|
|
this.state = {
|
|
|
|
pluginExports: null,
|
|
|
|
};
|
2018-01-02 07:52:30 -06:00
|
|
|
|
|
|
|
this.specialPanels['row'] = this.renderRow.bind(this);
|
|
|
|
this.specialPanels['add-panel'] = this.renderAddPanel.bind(this);
|
2017-10-09 10:52:25 -05:00
|
|
|
}
|
|
|
|
|
2018-01-02 07:52:30 -06:00
|
|
|
isSpecial() {
|
|
|
|
return this.specialPanels[this.props.panel.type];
|
|
|
|
}
|
|
|
|
|
|
|
|
renderRow() {
|
2018-01-03 06:33:54 -06:00
|
|
|
return <DashboardRow panel={this.props.panel} dashboard={this.props.dashboard} />;
|
2018-01-02 07:52:30 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
renderAddPanel() {
|
2018-01-03 06:33:54 -06:00
|
|
|
return <AddPanelPanel panel={this.props.panel} dashboard={this.props.dashboard} />;
|
2018-01-02 07:52:30 -06:00
|
|
|
}
|
|
|
|
|
2018-07-09 15:24:15 -05:00
|
|
|
onPluginTypeChanged = (plugin: PanelPlugin) => {
|
|
|
|
this.props.panel.changeType(plugin.id);
|
|
|
|
this.loadPlugin();
|
|
|
|
};
|
|
|
|
|
2018-08-25 14:22:50 -05:00
|
|
|
onAngularPluginTypeChanged = () => {
|
|
|
|
this.loadPlugin();
|
|
|
|
};
|
|
|
|
|
2018-07-09 11:17:51 -05:00
|
|
|
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) {
|
2018-08-25 14:22:50 -05:00
|
|
|
this.cleanUpAngularPanel();
|
2018-07-09 11:17:51 -05:00
|
|
|
this.setState({ pluginExports: this.pluginInfo.exports });
|
|
|
|
} else {
|
|
|
|
importPluginModule(this.pluginInfo.module).then(pluginExports => {
|
2018-08-25 14:22:50 -05:00
|
|
|
this.cleanUpAngularPanel();
|
2018-07-09 15:24:15 -05:00
|
|
|
// cache plugin exports (saves a promise async cycle next time)
|
|
|
|
this.pluginInfo.exports = pluginExports;
|
|
|
|
// update panel state
|
2018-07-09 11:17:51 -05:00
|
|
|
this.setState({ pluginExports: pluginExports });
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
this.loadPlugin();
|
|
|
|
}
|
|
|
|
|
2018-06-19 07:51:57 -05:00
|
|
|
componentDidUpdate() {
|
2018-07-09 11:17:51 -05:00
|
|
|
this.loadPlugin();
|
|
|
|
|
|
|
|
// handle angular plugin loading
|
2018-06-19 14:25:57 -05:00
|
|
|
if (!this.element || this.angularPanel) {
|
2018-06-19 07:51:57 -05:00
|
|
|
return;
|
2017-10-16 02:55:55 -05:00
|
|
|
}
|
2017-10-13 10:01:38 -05:00
|
|
|
|
2018-09-10 08:42:36 -05:00
|
|
|
const loader = getAngularLoader();
|
|
|
|
const template = '<plugin-component type="panel" class="panel-height-helper"></plugin-component>';
|
|
|
|
const scopeProps = { panel: this.props.panel, dashboard: this.props.dashboard };
|
2018-06-19 14:25:57 -05:00
|
|
|
this.angularPanel = loader.load(this.element, scopeProps, template);
|
2017-10-09 10:52:25 -05:00
|
|
|
}
|
2018-06-19 01:42:41 -05:00
|
|
|
|
2018-08-25 14:22:50 -05:00
|
|
|
cleanUpAngularPanel() {
|
2018-06-19 14:25:57 -05:00
|
|
|
if (this.angularPanel) {
|
|
|
|
this.angularPanel.destroy();
|
2018-08-25 14:22:50 -05:00
|
|
|
this.angularPanel = null;
|
2018-06-19 01:42:41 -05:00
|
|
|
}
|
|
|
|
}
|
2018-01-03 06:03:26 -06:00
|
|
|
|
2018-08-25 14:22:50 -05:00
|
|
|
componentWillUnmount() {
|
|
|
|
this.cleanUpAngularPanel();
|
|
|
|
}
|
|
|
|
|
2018-07-09 11:17:51 -05:00
|
|
|
renderReactPanel() {
|
2018-07-05 15:10:39 -05:00
|
|
|
const { pluginExports } = this.state;
|
2018-07-09 11:17:51 -05:00
|
|
|
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
|
|
|
|
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">
|
2018-07-09 15:24:15 -05:00
|
|
|
<PanelEditor
|
|
|
|
panel={this.props.panel}
|
|
|
|
panelType={this.props.panel.type}
|
|
|
|
dashboard={this.props.dashboard}
|
|
|
|
onTypeChanged={this.onPluginTypeChanged}
|
2018-07-11 14:11:21 -05:00
|
|
|
pluginExports={pluginExports}
|
2018-07-09 15:24:15 -05:00
|
|
|
/>
|
2018-07-09 11:17:51 -05:00
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
2018-07-05 15:10:39 -05:00
|
|
|
|
2018-07-09 11:17:51 -05:00
|
|
|
render() {
|
2018-06-19 07:51:57 -05:00
|
|
|
if (this.isSpecial()) {
|
|
|
|
return this.specialPanels[this.props.panel.type]();
|
|
|
|
}
|
2018-06-19 01:42:41 -05:00
|
|
|
|
2018-07-09 11:17:51 -05:00
|
|
|
if (!this.state.pluginExports) {
|
2018-06-19 07:51:57 -05:00
|
|
|
return null;
|
|
|
|
}
|
2018-06-19 01:42:41 -05:00
|
|
|
|
2018-07-09 11:17:51 -05:00
|
|
|
if (this.state.pluginExports.PanelComponent) {
|
|
|
|
return this.renderReactPanel();
|
2018-06-19 07:51:57 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// legacy angular rendering
|
|
|
|
return <div ref={element => (this.element = element)} className="panel-height-helper" />;
|
2018-06-19 01:42:41 -05:00
|
|
|
}
|
|
|
|
}
|