// Libraries import React, { PureComponent } from 'react'; // Utils & Services import { AngularComponent, getAngularLoader } from 'app/core/services/AngularLoader'; import { connectWithStore } from 'app/core/utils/connectWithReduxStore'; import { StoreState } from 'app/types'; import { updateLocation } from 'app/core/actions'; // Components import { EditorTabBody, EditorToolbarView } from './EditorTabBody'; import { VizTypePicker } from './VizTypePicker'; import { PluginHelp } from 'app/core/components/PluginHelp/PluginHelp'; import { FadeIn } from 'app/core/components/Animations/FadeIn'; // Types import { PanelModel } from '../state/PanelModel'; import { DashboardModel } from '../state/DashboardModel'; import { PanelPlugin } from 'app/types/plugins'; import { FilterInput } from 'app/core/components/FilterInput/FilterInput'; interface Props { panel: PanelModel; dashboard: DashboardModel; plugin: PanelPlugin; angularPanel?: AngularComponent; onTypeChanged: (newType: PanelPlugin) => void; updateLocation: typeof updateLocation; urlOpenVizPicker: boolean; } interface State { isVizPickerOpen: boolean; searchQuery: string; scrollTop: number; } export class VisualizationTab extends PureComponent { element: HTMLElement; angularOptions: AngularComponent; searchInput: HTMLElement; constructor(props) { super(props); this.state = { isVizPickerOpen: this.props.urlOpenVizPicker, searchQuery: '', scrollTop: 0, }; } getPanelDefaultOptions = () => { const { panel, plugin } = this.props; if (plugin.exports.PanelDefaults) { return panel.getOptions(plugin.exports.PanelDefaults); } return panel.getOptions({}); }; renderPanelOptions() { const { plugin, angularPanel } = this.props; const { PanelOptions } = plugin.exports; if (angularPanel) { return
(this.element = element)} />; } return ( <> {PanelOptions ? ( ) : (

Visualization has no options

)} ); } componentDidMount() { if (this.shouldLoadAngularOptions()) { this.loadAngularOptions(); } } componentDidUpdate(prevProps: Props) { if (this.props.plugin !== prevProps.plugin) { this.cleanUpAngularOptions(); } if (this.shouldLoadAngularOptions()) { this.loadAngularOptions(); } } shouldLoadAngularOptions() { return this.props.angularPanel && this.element && !this.angularOptions; } loadAngularOptions() { const { angularPanel } = this.props; const scope = angularPanel.getScope(); // When full page reloading in edit mode the angular panel has on fully compiled & instantiated yet if (!scope.$$childHead) { setTimeout(() => { this.forceUpdate(); }); return; } const panelCtrl = scope.$$childHead.ctrl; panelCtrl.initEditMode(); let template = ''; for (let i = 0; i < panelCtrl.editorTabs.length; i++) { template += `
` + (i > 0 ? `
{{ctrl.editorTabs[${i}].title}}
` : '') + `
`; } const loader = getAngularLoader(); const scopeProps = { ctrl: panelCtrl }; this.angularOptions = loader.load(this.element, scopeProps, template); } componentWillUnmount() { this.cleanUpAngularOptions(); } cleanUpAngularOptions() { if (this.angularOptions) { this.angularOptions.destroy(); this.angularOptions = null; } } clearQuery = () => { this.setState({ searchQuery: '' }); }; onPanelOptionsChanged = (options: any) => { this.props.panel.updateOptions(options); this.forceUpdate(); }; onOpenVizPicker = () => { this.setState({ isVizPickerOpen: true, scrollTop: 0 }); }; onCloseVizPicker = () => { if (this.props.urlOpenVizPicker) { this.props.updateLocation({ query: { openVizPicker: null }, partial: true }); } this.setState({ isVizPickerOpen: false }); }; onSearchQueryChange = (value: string) => { this.setState({ searchQuery: value, }); }; renderToolbar = (): JSX.Element => { const { plugin } = this.props; const { searchQuery } = this.state; if (this.state.isVizPickerOpen) { return ( <> elem && elem.focus()} /> ); } else { return (
{plugin.name}
); } }; onTypeChanged = (plugin: PanelPlugin) => { if (plugin.id === this.props.plugin.id) { this.setState({ isVizPickerOpen: false }); } else { this.props.onTypeChanged(plugin); } }; renderHelp = () => ; setScrollTop = (event: React.MouseEvent) => { const target = event.target as HTMLElement; this.setState({ scrollTop: target.scrollTop }); }; render() { const { plugin } = this.props; const { isVizPickerOpen, searchQuery, scrollTop } = this.state; const pluginHelp: EditorToolbarView = { heading: 'Help', icon: 'fa fa-question', render: this.renderHelp, }; return ( <> {this.renderPanelOptions()} ); } } const mapStateToProps = (state: StoreState) => ({ urlOpenVizPicker: !!state.location.query.openVizPicker, }); const mapDispatchToProps = { updateLocation, }; export default connectWithStore(VisualizationTab, mapStateToProps, mapDispatchToProps);