From 7a1889a13a9f2fadf9e307f0d7a9277fa2bd9f26 Mon Sep 17 00:00:00 2001 From: rozetko Date: Fri, 29 Mar 2024 16:49:24 +0300 Subject: [PATCH 1/6] refactor a bit --- src/components/Panel.tsx | 107 ++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 40 deletions(-) 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[] { From 93973cbc5f91e6c8deeaaa490078f7c0c7a34d2f Mon Sep 17 00:00:00 2001 From: rozetko Date: Fri, 29 Mar 2024 18:13:14 +0300 Subject: [PATCH 2/6] gauge: display additional info --- src/components/Panel.tsx | 87 +++++++++++++++++++----------- src/models/options/gaugeOptions.ts | 34 ++++-------- src/module.ts | 69 ++++++++++++++++++++++-- src/types.ts | 9 ++++ src/utils.ts | 32 +++++++++++ 5 files changed, 170 insertions(+), 61 deletions(-) diff --git a/src/components/Panel.tsx b/src/components/Panel.tsx index db5cc29..9a1eb2d 100644 --- a/src/components/Panel.tsx +++ b/src/components/Panel.tsx @@ -4,13 +4,12 @@ import { Series } from '../models/series'; import { BarSeries } from '../models/barSeries'; import { PanelOptions, Pod } from '../types'; - -import { DataProcessor } from '../grafana/data_processor'; +import { formatValue, getGrafanaSeriesList, getLastMetricValue } from '../utils'; import { ChartwerkGaugePod } from '@chartwerk/gauge-pod'; import { ChartwerkBarPod } from '@chartwerk/bar-pod'; -import { PanelData, TimeRange, PanelProps } from '@grafana/data'; +import { PanelProps } from '@grafana/data'; import { VizLegend } from '@grafana/ui'; import { LegendDisplayMode } from '@grafana/schema'; @@ -25,7 +24,6 @@ export function Panel({ options, data, width, height, timeRange, onChangeTimeRan const podContainerRef = useRef(null); const podContainer = useMemo(() => { - const chartHeight = height - 20; const chartClickHandler = (event: React.MouseEvent) => { event.preventDefault(); @@ -37,19 +35,29 @@ export function Panel({ options, data, width, height, timeRange, onChangeTimeRan }; const isLinkActive = options.gauge.link !== undefined && options.gauge.link !== ''; + let containerHeight = height; + if (options.visualizationType === Pod.BAR) { + containerHeight = height - 20; + } + if ( + options.visualizationType === Pod.GAUGE && + options.gauge.additionalInfo.display + ) { + containerHeight = height - options.gauge.additionalInfo.size - 8; + } return (
); - }, [width, height, options.gauge.link, replaceVariables]); + }, [width, height, options, replaceVariables]); useEffect(() => { let pod; @@ -68,26 +76,56 @@ export function Panel({ options, data, width, height, timeRange, onChangeTimeRan pod = new ChartwerkBarPod(podContainerRef.current, barSeries, chartwerkBarOptions); break; default: - throw new Error(`Unknown visualization type: ${options.visualizationType}`); + console.warn(`Unknown visualization type: ${options.visualizationType}`); + return; } pod.render(); }, [podContainer, grafanaSeriesList, onChangeTimeRange, options]); - const legendItems = useMemo( - () => - _.map(grafanaSeriesList, (serie) => { + switch (options.visualizationType) { + case Pod.GAUGE: + let additionalInfo; + const additionalInfoConfig = options.gauge.additionalInfo; + if (additionalInfoConfig.display) { + let value: number | undefined = undefined; + if (!additionalInfoConfig.value?.useMetric) { + value = additionalInfoConfig.value.value; + } else { + if (!_.isEmpty(additionalInfoConfig.value.metricName)) { + const aggregatedValue = getLastMetricValue(grafanaSeriesList, additionalInfoConfig.value.metricName, 'Max'); + value = aggregatedValue !== null ? aggregatedValue : undefined; + } + } + + additionalInfo =
+ {additionalInfoConfig.prefix} {value !== undefined ? formatValue(value, additionalInfoConfig) : '-'} +
+ } + return ( +
+ {podContainer} + {additionalInfo && additionalInfo} +
+ ); + case Pod.BAR: + const legendItems = _.map(grafanaSeriesList, (serie) => { return { label: serie.alias, color: serie.color, yAxis: 1, }; - }), - [grafanaSeriesList] - ); + }); - switch (options.visualizationType) { - case Pod.LINE: - case Pod.BAR: return (
{podContainer} @@ -95,21 +133,8 @@ export function Panel({ options, data, width, height, timeRange, onChangeTimeRan
); - case Pod.GAUGE: - return ( -
- {podContainer} -
- ); default: - throw new Error(`Unknown visualization type: ${options.visualizationType}`); + console.warn(`Unknown visualization type: ${options.visualizationType}`); + return
This visualization is not supported
; } } - -function getGrafanaSeriesList(grafanaData: PanelData, timeRange: TimeRange): any[] { - const processor = new DataProcessor({}); - return processor.getSeriesList({ - dataList: grafanaData.series, - range: timeRange, - }); -} diff --git a/src/models/options/gaugeOptions.ts b/src/models/options/gaugeOptions.ts index 5bc4698..9b7ccd4 100644 --- a/src/models/options/gaugeOptions.ts +++ b/src/models/options/gaugeOptions.ts @@ -1,8 +1,6 @@ -import { PanelOptions, Aggregation, Threshold, Icon, IconPosition, Condition } from 'types'; +import { PanelOptions, Threshold, Icon, IconPosition, Condition } from 'types'; -import { filterMetricListByAlias, getAggregatedValueFromSerie } from '../../utils'; - -import { getValueFormat } from '@grafana/data'; +import { formatValue, getLastMetricValue } from '../../utils'; import _ from 'lodash'; @@ -28,7 +26,7 @@ export class GaugeOptions { this.minValue = this.grafanaOptions.gauge.min.value; return; } - const aggregatedValue = this.getLastValueFromMetrics(this.grafanaOptions.gauge.min.metricName, 'Min'); + const aggregatedValue = getLastMetricValue(this.grafanaSeriesList, this.grafanaOptions.gauge.min.metricName, 'Min'); this.minValue = aggregatedValue ? aggregatedValue : undefined; } @@ -40,7 +38,7 @@ export class GaugeOptions { this.maxValue = this.grafanaOptions.gauge.max.value; return; } - const aggregatedValue = this.getLastValueFromMetrics(this.grafanaOptions.gauge.max.metricName, 'Max'); + const aggregatedValue = getLastMetricValue(this.grafanaSeriesList, this.grafanaOptions.gauge.max.metricName, 'Max'); this.maxValue = aggregatedValue ? aggregatedValue : undefined; } @@ -55,7 +53,7 @@ export class GaugeOptions { private _setThreshold(threshold: Threshold, idx: number): void { const value = threshold.useMetric - ? this.getLastValueFromMetrics(threshold.metricName, `Threshold ${idx + 1}`) + ? getLastMetricValue(this.grafanaSeriesList, threshold.metricName, `Threshold ${idx + 1}`) : threshold.value; if (value === null || value === undefined) { // TODO: may be throw an error @@ -67,12 +65,6 @@ export class GaugeOptions { }); } - private _valueFormatter(value: number): string { - const suffix = getValueFormat(this.grafanaOptions.gauge.unit)(0)?.suffix || ''; - const decimals = _.isNumber(this.grafanaOptions.gauge.decimals) ? this.grafanaOptions.gauge.decimals : 2; - return `${value.toFixed(decimals)} ${suffix}`; - } - private _setIcons(): void { if (_.isEmpty(this.grafanaOptions.gauge.icons)) { return; @@ -100,12 +92,12 @@ export class GaugeOptions { // check each condition and return false if something goes wrong for (let [conditionIdx, metric] of icon.metrics.entries()) { - const value = this.getLastValueFromMetrics(metric, `Icon ${iconIdx + 1}, Condition ${conditionIdx + 1}`); + const value = getLastMetricValue(this.grafanaSeriesList, metric, `Icon ${iconIdx + 1}, Condition ${conditionIdx + 1}`); if (value === null || value === undefined) { // TODO: may be throw an error return false; } - if (!this.checkIconCondition(value, icon.values[conditionIdx], icon.conditions[conditionIdx])) { + if (!this._checkIconCondition(value, icon.values[conditionIdx], icon.conditions[conditionIdx])) { return false; } } @@ -113,7 +105,7 @@ export class GaugeOptions { return true; } - private checkIconCondition(metricValue: number, inputValue: number, condition: Condition): boolean { + private _checkIconCondition(metricValue: number, inputValue: number, condition: Condition): boolean { if (inputValue === undefined || inputValue === null) { return true; } @@ -151,7 +143,7 @@ export class GaugeOptions { return { maxValue: this.maxValue, minValue: this.minValue, - valueFormatter: (val: number) => this._valueFormatter(val), + valueFormatter: (val: number) => formatValue(val, this.grafanaOptions.gauge), defaultColor: this.grafanaOptions.gauge.thresholds.defaultColor, valueArcBackgroundColor: this.grafanaOptions.gauge.thresholds.arcBackground, reversed: this.grafanaOptions.gauge.reversed, @@ -160,12 +152,4 @@ export class GaugeOptions { icons: this.icons, }; } - - getLastValueFromMetrics(metricName: string | undefined, optionName: string): number | null { - // optionName -> helper in Error, mb use option path instead - const filteredSeries = filterMetricListByAlias(this.grafanaSeriesList, metricName, optionName); - const serie = filteredSeries[0]; - // Last value for now - return getAggregatedValueFromSerie(serie, Aggregation.LAST); - } } diff --git a/src/module.ts b/src/module.ts index de92132..d04cb8f 100644 --- a/src/module.ts +++ b/src/module.ts @@ -23,14 +23,14 @@ export const plugin = new PanelPlugin(Panel).setPanelOptions((buil label: 'Gauge', value: Pod.GAUGE, }, - { - label: 'Line', - value: Pod.LINE, - }, { label: 'Bar', value: Pod.BAR, }, + { + label: 'Line', + value: Pod.LINE, + }, ], }, }) @@ -42,13 +42,72 @@ export const plugin = new PanelPlugin(Panel).setPanelOptions((buil showIf: (config) => config.visualizationType !== Pod.GAUGE, editor: NotSupportedText as any, }) - .addFieldNamePicker({ name: 'Metric', path: 'gauge.value.metricName', category: ['Value'], showIf: (config) => config.visualizationType === Pod.GAUGE, }) + + .addBooleanSwitch({ + path: 'gauge.additionalInfo.display', + name: 'Display', + defaultValue: false, + category: ['Additional Info'], + showIf: (config) => config.visualizationType === Pod.GAUGE, + }) + .addCustomEditor({ + id: 'additionalInfo', + name: 'Value', + path: 'gauge.additionalInfo.value', + category: ['Additional Info'], + defaultValue: { useMetric: false, value: 0 }, + showIf: (config) => config.visualizationType === Pod.GAUGE && config.gauge.additionalInfo?.display, + editor: UseMetricEditor as any, + }) + .addSliderInput({ + path: 'gauge.additionalInfo.size', + defaultValue: 20, + name: 'Size (px)', + settings: { + min: 1, + max: 50, + }, + category: ['Additional Info'], + showIf: (config) => config.visualizationType === Pod.GAUGE && config.gauge.additionalInfo?.display, + }) + .addTextInput({ + path: 'gauge.additionalInfo.prefix', + defaultValue: '', + name: 'Prefix', + category: ['Additional Info'], + showIf: (config) => config.visualizationType === Pod.GAUGE && config.gauge.additionalInfo?.display, + }) + .addColorPicker({ + path: 'gauge.additionalInfo.color', + defaultValue: 'white', + name: 'Text Color', + category: ['Additional Info'], + showIf: (config) => config.visualizationType === Pod.GAUGE && config.gauge.additionalInfo?.display, + }) + .addUnitPicker({ + path: 'gauge.additionalInfo.unit', + name: 'Unit', + category: ['Additional Info'], + showIf: (config) => config.visualizationType === Pod.GAUGE && config.gauge.additionalInfo?.display, + }) + .addNumberInput({ + path: 'gauge.additionalInfo.decimals', + name: 'Decimals', + settings: { + placeholder: 'auto', + min: 0, + max: 5, + }, + category: ['Additional Info'], + showIf: (config) => config.visualizationType === Pod.GAUGE && config.gauge.additionalInfo?.display, + }) + .addCustomEditor({ id: 'min', name: 'Min', diff --git a/src/types.ts b/src/types.ts index cf3f960..bdd344b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -15,6 +15,15 @@ export interface PanelOptions { decimals?: number; unit?: string; link?: string; + additionalInfo: { + display: boolean; + value: ExtremumOptions; + size: number; + color: number; + prefix: string; + unit: string; + decimals: number; + } }; } diff --git a/src/utils.ts b/src/utils.ts index 007f8d2..f4d63ef 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,8 +1,40 @@ import { Aggregation } from './types'; +import { DataProcessor } from './grafana/data_processor'; + +import { PanelData, TimeRange, getValueFormat } from '@grafana/data'; +import TimeSeries from 'grafana/app/core/time_series2'; + import * as _ from 'lodash'; +export function formatValue(value: number, options: { unit?: string, decimals?: number }): string { + const suffix = getValueFormat(options.unit)(0)?.suffix || ''; + const decimals = _.isNumber(options.decimals) ? options.decimals : 2; + return `${value.toFixed(decimals)} ${suffix}`; +} + +export function getGrafanaSeriesList(grafanaData: PanelData, timeRange: TimeRange): TimeSeries[] { + const processor = new DataProcessor({}); + return processor.getSeriesList({ + dataList: grafanaData.series, + range: timeRange, + }); +} + +export function getLastMetricValue( + grafanaSeriesList: TimeSeries[], + metricName: string | undefined, + optionName: string, +): number | null { + // optionName -> helper in Error, mb use option path instead + const filteredSeries = filterMetricListByAlias(grafanaSeriesList, metricName, optionName); + const serie = filteredSeries[0]; + // Last value for now + return getAggregatedValueFromSerie(serie, Aggregation.LAST); +} + export function filterMetricListByAlias(list: any[], alias: string | undefined, option: string): any[] { + console.log(list) const filteredSeries = _.filter(list, (serie) => serie.alias === alias); if (filteredSeries.length === 0) { throw new Error(`${option}: Can't find metric for ${alias} name.`); From 3c7c7428c38704c2db4eae0d216b6ffcc6348a27 Mon Sep 17 00:00:00 2001 From: rozetko Date: Fri, 29 Mar 2024 18:13:52 +0300 Subject: [PATCH 3/6] fix linter errors --- src/components/Panel.tsx | 34 ++++++++++++++---------------- src/models/options/gaugeOptions.ts | 6 +++++- src/types.ts | 2 +- src/utils.ts | 6 +++--- 4 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/components/Panel.tsx b/src/components/Panel.tsx index 9a1eb2d..36d538b 100644 --- a/src/components/Panel.tsx +++ b/src/components/Panel.tsx @@ -24,7 +24,6 @@ export function Panel({ options, data, width, height, timeRange, onChangeTimeRan const podContainerRef = useRef(null); const podContainer = useMemo(() => { - const chartClickHandler = (event: React.MouseEvent) => { event.preventDefault(); if (options.gauge.link === undefined || options.gauge.link === '') { @@ -39,10 +38,7 @@ export function Panel({ options, data, width, height, timeRange, onChangeTimeRan if (options.visualizationType === Pod.BAR) { containerHeight = height - 20; } - if ( - options.visualizationType === Pod.GAUGE && - options.gauge.additionalInfo.display - ) { + if (options.visualizationType === Pod.GAUGE && options.gauge.additionalInfo.display) { containerHeight = height - options.gauge.additionalInfo.size - 8; } @@ -97,19 +93,21 @@ export function Panel({ options, data, width, height, timeRange, onChangeTimeRan } } - additionalInfo =
- {additionalInfoConfig.prefix} {value !== undefined ? formatValue(value, additionalInfoConfig) : '-'} -
+ additionalInfo = ( +
+ {additionalInfoConfig.prefix} {value !== undefined ? formatValue(value, additionalInfoConfig) : '-'} +
+ ); } return (
diff --git a/src/models/options/gaugeOptions.ts b/src/models/options/gaugeOptions.ts index 9b7ccd4..0049b38 100644 --- a/src/models/options/gaugeOptions.ts +++ b/src/models/options/gaugeOptions.ts @@ -92,7 +92,11 @@ export class GaugeOptions { // check each condition and return false if something goes wrong for (let [conditionIdx, metric] of icon.metrics.entries()) { - const value = getLastMetricValue(this.grafanaSeriesList, metric, `Icon ${iconIdx + 1}, Condition ${conditionIdx + 1}`); + const value = getLastMetricValue( + this.grafanaSeriesList, + metric, + `Icon ${iconIdx + 1}, Condition ${conditionIdx + 1}` + ); if (value === null || value === undefined) { // TODO: may be throw an error return false; diff --git a/src/types.ts b/src/types.ts index bdd344b..4ca1d01 100644 --- a/src/types.ts +++ b/src/types.ts @@ -23,7 +23,7 @@ export interface PanelOptions { prefix: string; unit: string; decimals: number; - } + }; }; } diff --git a/src/utils.ts b/src/utils.ts index f4d63ef..be25040 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -7,7 +7,7 @@ import TimeSeries from 'grafana/app/core/time_series2'; import * as _ from 'lodash'; -export function formatValue(value: number, options: { unit?: string, decimals?: number }): string { +export function formatValue(value: number, options: { unit?: string; decimals?: number }): string { const suffix = getValueFormat(options.unit)(0)?.suffix || ''; const decimals = _.isNumber(options.decimals) ? options.decimals : 2; return `${value.toFixed(decimals)} ${suffix}`; @@ -24,7 +24,7 @@ export function getGrafanaSeriesList(grafanaData: PanelData, timeRange: TimeRang export function getLastMetricValue( grafanaSeriesList: TimeSeries[], metricName: string | undefined, - optionName: string, + optionName: string ): number | null { // optionName -> helper in Error, mb use option path instead const filteredSeries = filterMetricListByAlias(grafanaSeriesList, metricName, optionName); @@ -34,7 +34,7 @@ export function getLastMetricValue( } export function filterMetricListByAlias(list: any[], alias: string | undefined, option: string): any[] { - console.log(list) + console.log(list); const filteredSeries = _.filter(list, (serie) => serie.alias === alias); if (filteredSeries.length === 0) { throw new Error(`${option}: Can't find metric for ${alias} name.`); From 5d4180a2700437f28e28d2897a4829430bf56aab Mon Sep 17 00:00:00 2001 From: rozetko Date: Fri, 29 Mar 2024 19:12:25 +0300 Subject: [PATCH 4/6] rm console log --- src/utils.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils.ts b/src/utils.ts index be25040..1a29ba3 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -34,7 +34,6 @@ export function getLastMetricValue( } export function filterMetricListByAlias(list: any[], alias: string | undefined, option: string): any[] { - console.log(list); const filteredSeries = _.filter(list, (serie) => serie.alias === alias); if (filteredSeries.length === 0) { throw new Error(`${option}: Can't find metric for ${alias} name.`); From 59d02583c4a018327ac3bfeaaca3fb81e21e3de3 Mon Sep 17 00:00:00 2001 From: rozetko Date: Fri, 29 Mar 2024 19:25:10 +0300 Subject: [PATCH 5/6] todo --- src/components/Panel.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/Panel.tsx b/src/components/Panel.tsx index 36d538b..d4e4307 100644 --- a/src/components/Panel.tsx +++ b/src/components/Panel.tsx @@ -83,12 +83,13 @@ export function Panel({ options, data, width, height, timeRange, onChangeTimeRan let additionalInfo; const additionalInfoConfig = options.gauge.additionalInfo; if (additionalInfoConfig.display) { + // TODO: move `useMetric` handling to utils, as it's duplicated in gaugeOptions.ts let value: number | undefined = undefined; if (!additionalInfoConfig.value?.useMetric) { value = additionalInfoConfig.value.value; } else { if (!_.isEmpty(additionalInfoConfig.value.metricName)) { - const aggregatedValue = getLastMetricValue(grafanaSeriesList, additionalInfoConfig.value.metricName, 'Max'); + const aggregatedValue = getLastMetricValue(grafanaSeriesList, additionalInfoConfig.value.metricName, 'Additional Info'); value = aggregatedValue !== null ? aggregatedValue : undefined; } } From 4c56c05ce93041dccfc02c6e500dc85cf0fbcb49 Mon Sep 17 00:00:00 2001 From: rozetko Date: Fri, 29 Mar 2024 19:32:24 +0300 Subject: [PATCH 6/6] fix linter error --- src/components/Panel.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/Panel.tsx b/src/components/Panel.tsx index d4e4307..b2b2603 100644 --- a/src/components/Panel.tsx +++ b/src/components/Panel.tsx @@ -89,7 +89,11 @@ export function Panel({ options, data, width, height, timeRange, onChangeTimeRan value = additionalInfoConfig.value.value; } else { if (!_.isEmpty(additionalInfoConfig.value.metricName)) { - const aggregatedValue = getLastMetricValue(grafanaSeriesList, additionalInfoConfig.value.metricName, 'Additional Info'); + const aggregatedValue = getLastMetricValue( + grafanaSeriesList, + additionalInfoConfig.value.metricName, + 'Additional Info' + ); value = aggregatedValue !== null ? aggregatedValue : undefined; } }