import React, { useState, useMemo, useEffect, useRef } from 'react'; import { useAsync } from 'react-use'; import { applyFieldOverrides, FieldConfigSource, getTimeZone, PanelData, PanelPlugin } from '@grafana/data'; import { PanelRendererProps } from '@grafana/runtime'; import { ErrorBoundaryAlert, useTheme2 } from '@grafana/ui'; import { appEvents } from 'app/core/core'; import { getPanelOptionsWithDefaults, OptionDefaults } from '../../dashboard/state/getPanelOptionsWithDefaults'; import { importPanelPlugin } from '../../plugins/importPanelPlugin'; const defaultFieldConfig = { defaults: {}, overrides: [] }; export function PanelRenderer

(props: PanelRendererProps) { const { pluginId, data, timeZone = getTimeZone(), options = {}, width, height, title, onOptionsChange = () => {}, onChangeTimeRange = () => {}, fieldConfig: externalFieldConfig = defaultFieldConfig, } = props; const [localFieldConfig, setFieldConfig] = useState(externalFieldConfig); const { value: plugin, error, loading } = useAsync(() => importPanelPlugin(pluginId), [pluginId]); const optionsWithDefaults = useOptionDefaults(plugin, options, localFieldConfig); const dataWithOverrides = useFieldOverrides(plugin, optionsWithDefaults, data, timeZone); useEffect(() => { setFieldConfig((lfc) => ({ ...lfc, ...externalFieldConfig })); }, [externalFieldConfig]); if (error) { return

Failed to load plugin: {error.message}
; } if (pluginIsLoading(loading, plugin, pluginId)) { return
Loading plugin panel...
; } if (!plugin || !plugin.panel) { return
Seems like the plugin you are trying to load does not have a panel component.
; } if (!dataWithOverrides) { return
No panel data
; } const PanelComponent = plugin.panel; return ( str} onOptionsChange={onOptionsChange} onFieldConfigChange={setFieldConfig} onChangeTimeRange={onChangeTimeRange} eventBus={appEvents} /> ); } function useOptionDefaults

( plugin: PanelPlugin | undefined, options: P, fieldConfig: FieldConfigSource ): OptionDefaults | undefined { return useMemo(() => { if (!plugin) { return; } return getPanelOptionsWithDefaults({ plugin, currentOptions: options, currentFieldConfig: fieldConfig, isAfterPluginChange: false, }); }, [plugin, fieldConfig, options]); } function useFieldOverrides( plugin: PanelPlugin | undefined, defaultOptions: OptionDefaults | undefined, data: PanelData | undefined, timeZone: string ): PanelData | undefined { const fieldConfig = defaultOptions?.fieldConfig; const series = data?.series; const fieldConfigRegistry = plugin?.fieldConfigRegistry; const theme = useTheme2(); const structureRev = useRef(0); return useMemo(() => { if (!fieldConfigRegistry || !fieldConfig || !data) { return; } structureRev.current = structureRev.current + 1; return { ...data, series: applyFieldOverrides({ data: series, fieldConfig, fieldConfigRegistry, replaceVariables: (str: string) => str, theme, timeZone, }), structureRev: structureRev.current, }; }, [fieldConfigRegistry, fieldConfig, data, series, timeZone, theme]); } function pluginIsLoading(loading: boolean, plugin: PanelPlugin | undefined, pluginId: string) { return loading || plugin?.meta.id !== pluginId; }