|
|
@ -4,13 +4,12 @@ import { Series } from '../models/series'; |
|
|
|
import { BarSeries } from '../models/barSeries'; |
|
|
|
import { BarSeries } from '../models/barSeries'; |
|
|
|
|
|
|
|
|
|
|
|
import { PanelOptions, Pod } from '../types'; |
|
|
|
import { PanelOptions, Pod } from '../types'; |
|
|
|
|
|
|
|
import { formatValue, getGrafanaSeriesList, getLastMetricValue } from '../utils'; |
|
|
|
import { DataProcessor } from '../grafana/data_processor'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import { ChartwerkGaugePod } from '@chartwerk/gauge-pod'; |
|
|
|
import { ChartwerkGaugePod } from '@chartwerk/gauge-pod'; |
|
|
|
import { ChartwerkBarPod } from '@chartwerk/bar-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 { VizLegend } from '@grafana/ui'; |
|
|
|
import { LegendDisplayMode } from '@grafana/schema'; |
|
|
|
import { LegendDisplayMode } from '@grafana/schema'; |
|
|
|
|
|
|
|
|
|
|
@ -25,7 +24,6 @@ export function Panel({ options, data, width, height, timeRange, onChangeTimeRan |
|
|
|
const podContainerRef = useRef<HTMLDivElement>(null); |
|
|
|
const podContainerRef = useRef<HTMLDivElement>(null); |
|
|
|
|
|
|
|
|
|
|
|
const podContainer = useMemo(() => { |
|
|
|
const podContainer = useMemo(() => { |
|
|
|
const chartHeight = height - 20; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const chartClickHandler = (event: React.MouseEvent<HTMLDivElement>) => { |
|
|
|
const chartClickHandler = (event: React.MouseEvent<HTMLDivElement>) => { |
|
|
|
event.preventDefault(); |
|
|
|
event.preventDefault(); |
|
|
@ -37,19 +35,29 @@ export function Panel({ options, data, width, height, timeRange, onChangeTimeRan |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const isLinkActive = options.gauge.link !== undefined && options.gauge.link !== ''; |
|
|
|
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 ( |
|
|
|
return ( |
|
|
|
<div |
|
|
|
<div |
|
|
|
ref={podContainerRef} |
|
|
|
ref={podContainerRef} |
|
|
|
className={css` |
|
|
|
className={css` |
|
|
|
width: ${width}px; |
|
|
|
width: ${width}px; |
|
|
|
height: ${chartHeight}px; |
|
|
|
height: ${containerHeight}px; |
|
|
|
cursor: ${isLinkActive ? 'pointer' : 'default'}; |
|
|
|
cursor: ${isLinkActive ? 'pointer' : 'default'}; |
|
|
|
`}
|
|
|
|
`}
|
|
|
|
onClick={chartClickHandler} |
|
|
|
onClick={chartClickHandler} |
|
|
|
></div> |
|
|
|
></div> |
|
|
|
); |
|
|
|
); |
|
|
|
}, [width, height, options.gauge.link, replaceVariables]); |
|
|
|
}, [width, height, options, replaceVariables]); |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
useEffect(() => { |
|
|
|
let pod; |
|
|
|
let pod; |
|
|
@ -68,26 +76,56 @@ export function Panel({ options, data, width, height, timeRange, onChangeTimeRan |
|
|
|
pod = new ChartwerkBarPod(podContainerRef.current, barSeries, chartwerkBarOptions); |
|
|
|
pod = new ChartwerkBarPod(podContainerRef.current, barSeries, chartwerkBarOptions); |
|
|
|
break; |
|
|
|
break; |
|
|
|
default: |
|
|
|
default: |
|
|
|
throw new Error(`Unknown visualization type: ${options.visualizationType}`); |
|
|
|
console.warn(`Unknown visualization type: ${options.visualizationType}`); |
|
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
pod.render(); |
|
|
|
pod.render(); |
|
|
|
}, [podContainer, grafanaSeriesList, onChangeTimeRange, options]); |
|
|
|
}, [podContainer, grafanaSeriesList, onChangeTimeRange, options]); |
|
|
|
|
|
|
|
|
|
|
|
const legendItems = useMemo( |
|
|
|
switch (options.visualizationType) { |
|
|
|
() => |
|
|
|
case Pod.GAUGE: |
|
|
|
_.map(grafanaSeriesList, (serie) => { |
|
|
|
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 = <div |
|
|
|
|
|
|
|
className={css` |
|
|
|
|
|
|
|
width: ${width}px; |
|
|
|
|
|
|
|
height: ${additionalInfoConfig.size + 8}px; |
|
|
|
|
|
|
|
font-size: ${additionalInfoConfig.size}px; |
|
|
|
|
|
|
|
color: ${additionalInfoConfig.color}; |
|
|
|
|
|
|
|
display: flex; |
|
|
|
|
|
|
|
justify-content: center; |
|
|
|
|
|
|
|
align-items: center; |
|
|
|
|
|
|
|
`}
|
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
{additionalInfoConfig.prefix} {value !== undefined ? formatValue(value, additionalInfoConfig) : '-'} |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return ( |
|
|
|
|
|
|
|
<div> |
|
|
|
|
|
|
|
{podContainer} |
|
|
|
|
|
|
|
{additionalInfo && additionalInfo} |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
case Pod.BAR: |
|
|
|
|
|
|
|
const legendItems = _.map(grafanaSeriesList, (serie) => { |
|
|
|
return { |
|
|
|
return { |
|
|
|
label: serie.alias, |
|
|
|
label: serie.alias, |
|
|
|
color: serie.color, |
|
|
|
color: serie.color, |
|
|
|
yAxis: 1, |
|
|
|
yAxis: 1, |
|
|
|
}; |
|
|
|
}; |
|
|
|
}), |
|
|
|
}); |
|
|
|
[grafanaSeriesList] |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (options.visualizationType) { |
|
|
|
|
|
|
|
case Pod.LINE: |
|
|
|
|
|
|
|
case Pod.BAR: |
|
|
|
|
|
|
|
return ( |
|
|
|
return ( |
|
|
|
<div> |
|
|
|
<div> |
|
|
|
{podContainer} |
|
|
|
{podContainer} |
|
|
@ -95,21 +133,8 @@ export function Panel({ options, data, width, height, timeRange, onChangeTimeRan |
|
|
|
<VizLegend placement={'bottom'} items={legendItems} displayMode={LegendDisplayMode.List} /> |
|
|
|
<VizLegend placement={'bottom'} items={legendItems} displayMode={LegendDisplayMode.List} /> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
); |
|
|
|
); |
|
|
|
case Pod.GAUGE: |
|
|
|
|
|
|
|
return ( |
|
|
|
|
|
|
|
<div> |
|
|
|
|
|
|
|
{podContainer} |
|
|
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
default: |
|
|
|
default: |
|
|
|
throw new Error(`Unknown visualization type: ${options.visualizationType}`); |
|
|
|
console.warn(`Unknown visualization type: ${options.visualizationType}`); |
|
|
|
} |
|
|
|
return <div>This visualization is not supported</div>; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function getGrafanaSeriesList(grafanaData: PanelData, timeRange: TimeRange): any[] { |
|
|
|
|
|
|
|
const processor = new DataProcessor({}); |
|
|
|
|
|
|
|
return processor.getSeriesList({ |
|
|
|
|
|
|
|
dataList: grafanaData.series, |
|
|
|
|
|
|
|
range: timeRange, |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|