diff --git a/src/components/Panel.tsx b/src/components/Panel.tsx index 6cc1e1d..db5cc29 100644 --- a/src/components/Panel.tsx +++ b/src/components/Panel.tsx @@ -14,69 +14,96 @@ import { PanelData, TimeRange, PanelProps } from '@grafana/data'; import { VizLegend } from '@grafana/ui'; import { LegendDisplayMode } from '@grafana/schema'; -import React, { useCallback, useRef } from 'react'; +import React, { useRef, useEffect, useMemo } from 'react'; import { css } from 'emotion'; import * as _ from 'lodash'; interface Props extends PanelProps {} export function Panel({ options, data, width, height, timeRange, onChangeTimeRange, replaceVariables }: Props) { - const grafanaSeriesList = getGrafanaSeriesList(data, timeRange); - let chartContainer = useRef(null); + const grafanaSeriesList = useMemo(() => getGrafanaSeriesList(data, timeRange), [data, timeRange]); + const podContainerRef = useRef(null); - // we request animation frame here because we need an existing DOM-element at the moment we render the pod - window.requestAnimationFrame(() => { + const podContainer = useMemo(() => { + const chartHeight = height - 20; + + const chartClickHandler = (event: React.MouseEvent) => { + event.preventDefault(); + if (options.gauge.link === undefined || options.gauge.link === '') { + return; + } + const link = replaceVariables(options.gauge.link); + window.open(link, '_self'); + }; + + const isLinkActive = options.gauge.link !== undefined && options.gauge.link !== ''; + + return ( +
+ ); + }, [width, height, options.gauge.link, replaceVariables]); + + useEffect(() => { let pod; + if (podContainerRef.current === null) { + return; + } switch (options.visualizationType) { case Pod.GAUGE: const series = new Series(grafanaSeriesList, options.gauge.value).getChartwerkSeries(); const chartwerkGaugeOptions = new GaugeOptions(grafanaSeriesList, options).getChartwerkOptions(); - pod = new ChartwerkGaugePod((chartContainer as any).current, series, chartwerkGaugeOptions); + pod = new ChartwerkGaugePod(podContainerRef.current, series, chartwerkGaugeOptions); break; case Pod.BAR: const barSeries = new BarSeries(grafanaSeriesList).getChartwerkSeries(); const chartwerkBarOptions = new BarOptions(grafanaSeriesList, onChangeTimeRange).getChartwerkOptions(); - pod = new ChartwerkBarPod((chartContainer as any).current, barSeries, chartwerkBarOptions); + pod = new ChartwerkBarPod(podContainerRef.current, barSeries, chartwerkBarOptions); break; default: throw new Error(`Unknown visualization type: ${options.visualizationType}`); } pod.render(); - }); + }, [podContainer, grafanaSeriesList, onChangeTimeRange, options]); - const isLinkActive = !_.isEmpty(options.gauge.link); - const chartClickHandler = useCallback((event: React.MouseEvent) => { - event.preventDefault(); - if (!isLinkActive) { - return; - } - const link = replaceVariables(options.gauge.link as string); - window.open(link, '_self'); - }, [options.gauge.link]); - const legendItems = _.map(grafanaSeriesList, (serie) => { - return { - label: serie.alias, - color: serie.color, - yAxis: 1, - }; - }); - const chartHeight = options.visualizationType !== Pod.GAUGE ? height - 20 : height; - return ( -
-
- {options.visualizationType !== Pod.GAUGE && ( - - )} -
+ const legendItems = useMemo( + () => + _.map(grafanaSeriesList, (serie) => { + return { + label: serie.alias, + color: serie.color, + yAxis: 1, + }; + }), + [grafanaSeriesList] ); + + switch (options.visualizationType) { + case Pod.LINE: + case Pod.BAR: + return ( +
+ {podContainer} + + +
+ ); + case Pod.GAUGE: + return ( +
+ {podContainer} +
+ ); + default: + throw new Error(`Unknown visualization type: ${options.visualizationType}`); + } } function getGrafanaSeriesList(grafanaData: PanelData, timeRange: TimeRange): any[] {