123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- 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<P extends object = any, F extends object = any>(props: PanelRendererProps<P, F>) {
- 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 <div>Failed to load plugin: {error.message}</div>;
- }
- if (pluginIsLoading(loading, plugin, pluginId)) {
- return <div>Loading plugin panel...</div>;
- }
- if (!plugin || !plugin.panel) {
- return <div>Seems like the plugin you are trying to load does not have a panel component.</div>;
- }
- if (!dataWithOverrides) {
- return <div>No panel data</div>;
- }
- const PanelComponent = plugin.panel;
- return (
- <ErrorBoundaryAlert dependencies={[plugin, data]}>
- <PanelComponent
- id={1}
- data={dataWithOverrides}
- title={title}
- timeRange={dataWithOverrides.timeRange}
- timeZone={timeZone}
- options={optionsWithDefaults!.options}
- fieldConfig={localFieldConfig}
- transparent={false}
- width={width}
- height={height}
- renderCounter={0}
- replaceVariables={(str: string) => str}
- onOptionsChange={onOptionsChange}
- onFieldConfigChange={setFieldConfig}
- onChangeTimeRange={onChangeTimeRange}
- eventBus={appEvents}
- />
- </ErrorBoundaryAlert>
- );
- }
- function useOptionDefaults<P extends object = any, F extends object = any>(
- plugin: PanelPlugin | undefined,
- options: P,
- fieldConfig: FieldConfigSource<F>
- ): 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<any, any> | undefined, pluginId: string) {
- return loading || plugin?.meta.id !== pluginId;
- }
|