Skip to content

Commit

Permalink
feat(echarts): threshold support
Browse files Browse the repository at this point in the history
  • Loading branch information
corteggiano committed Aug 15, 2023
1 parent 4cae31f commit 2d7ccfe
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 5 deletions.
9 changes: 7 additions & 2 deletions packages/react-components/src/components/chart/baseChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ const Chart = ({ viewport, queries, size = { width: 500, height: 500 }, ...optio
const chartId = useChartId(options.id);

// convert TimeSeriesDataQuery to TimeSeriesData
const { isLoading, dataStreams } = useVisualizedDataStreams(queries, viewport);
const { isLoading, dataStreams, thresholds: queryThresholds } = useVisualizedDataStreams(queries, viewport);
const allThresholds = [...queryThresholds, ...(options.thresholds ?? [])];

// Setup resize container and calculate size for echarts
const { width, height, chartWidth, onResize, minConstraints, maxConstraints } = useResizeableEChart(chartRef, size);
Expand All @@ -64,7 +65,11 @@ const Chart = ({ viewport, queries, size = { width: 500, height: 500 }, ...optio
const [styleSettingsMap] = useChartStyleSettings(dataStreams, options);

// adapt datastreams into echarts series and yAxis data
const { series, yAxis } = useSeriesAndYAxis(dataStreams, { styleSettings: styleSettingsMap, axis: options.axis });
const { series, yAxis } = useSeriesAndYAxis(dataStreams, {
styleSettings: styleSettingsMap,
axis: options.axis,
thresholds: allThresholds,
});

const { handleContextMenu, showContextMenu, contextMenuPos, setShowContextMenu, keyMap } = useContextMenu();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useMemo } from 'react';
import { DataStream } from '@iot-app-kit/core';
import { DataStream, Threshold } from '@iot-app-kit/core';
import { SeriesOption, YAXisComponentOption } from 'echarts';

import { ChartAxisOptions, ChartStyleSettingsOptions } from '../types';
import { convertDataPoint } from './convertDataPoint';
import { StyleSettingsMap, getChartStyleSettingsFromMap } from './convertStyles';
import { convertYAxis as convertChartYAxis } from './convertAxis';
import { convertThresholds } from './convertThresholds';

const stepTypes: NonNullable<ChartStyleSettingsOptions['visualizationType']>[] = [
'step-end',
Expand Down Expand Up @@ -132,10 +133,15 @@ export const reduceSeriesAndYAxis = (
*/
export const useSeriesAndYAxis = (
datastreams: DataStream[],
{ styleSettings, axis }: { styleSettings: StyleSettingsMap; axis?: ChartAxisOptions }
{
styleSettings,
axis,
thresholds,
}: { styleSettings: StyleSettingsMap; thresholds: Threshold[]; axis?: ChartAxisOptions }
) => {
const defaultSeries: SeriesOption[] = [];
const defaultYAxis: YAXisComponentOption[] = useMemo(() => [convertChartYAxis(axis)], [axis]);
const convertedThresholds = convertThresholds(thresholds);

const getStyles = getChartStyleSettingsFromMap(styleSettings);

Expand All @@ -147,5 +153,10 @@ export const useSeriesAndYAxis = (
return { series: mappedSeries, yAxis: mappedYAxis };
}, [datastreams, styleSettings, defaultYAxis]);

if (series.length > 0) {
series[0].markArea = convertedThresholds.markArea;
series[0].markLine = convertedThresholds.markLine;
}

return { series, yAxis };
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { AnnotationValue, COMPARISON_OPERATOR, ComparisonOperator, Threshold } from '@iot-app-kit/core';
import { COMPARATOR_MAP } from '../../../common/constants';

const comparisonOperatorToLowerYAxis = (comparisonOperator: ComparisonOperator, value: AnnotationValue) => {
switch (comparisonOperator) {
case COMPARISON_OPERATOR.GT:
case COMPARISON_OPERATOR.GTE:
case COMPARISON_OPERATOR.EQ:
return value;
case COMPARISON_OPERATOR.LT:
case COMPARISON_OPERATOR.LTE:
return 0;
default:
return undefined;
}
};

const comparisonOperatorToUpperYAxis = (comparisonOperator: ComparisonOperator, value: AnnotationValue) => {
switch (comparisonOperator) {
case COMPARISON_OPERATOR.LT:
case COMPARISON_OPERATOR.LTE:
case COMPARISON_OPERATOR.EQ:
return value;
default:
return undefined;
}
};

export const convertThresholds = (thresholds?: Threshold[]) => {
if (!thresholds || !thresholds.length) return {};
return {
markLine: {
silent: true,
symbol: 'none',
lineStyle: 'dashOffset',
animation: false,
data: thresholds
.filter((t) => typeof t.value === 'number')
.map((t) => ({
label: {
formatter: `${COMPARATOR_MAP[t.comparisonOperator]} ${t.value}`,
},
lineStyle: {
color: t.color,
},
yAxis: t.value,
})),
},
markArea: {
silent: true,
animation: false,
data: thresholds
.filter((t) => typeof t.value === 'number')
.map(({ comparisonOperator, value, color }) => [
{
yAxis: comparisonOperatorToLowerYAxis(comparisonOperator, value),
itemStyle: {
color: color,
opacity: 0.1,
},
},
{
yAxis: comparisonOperatorToUpperYAxis(comparisonOperator, value),
},
]),
},
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { convertOptions } from './convertOptions';
import { convertSeriesAndYAxis } from './convertSeriesAndYAxis';
import { convertTooltip } from './convertTooltip';
import { convertStyles } from './convertStyles';
import { convertThresholds } from './convertThresholds';

const MOCK_AXIS = {
yAxisLabel: 'Y Value',
Expand Down Expand Up @@ -175,3 +176,39 @@ describe('testing converters', () => {
if (valueFormatter) expect(valueFormatter([300, 10, 20000])).toBe('300, 10, 20000');
});
});

it('converts thresholds to echarts markLine and markArea', async () => {
const convertedThresholds = convertThresholds([
{
comparisonOperator: 'EQ',
color: 'red',
value: 10,
},
{
comparisonOperator: 'CONTAINS',
color: 'blue',
value: 'SomeString',
},
{
comparisonOperator: 'LTE',
color: 'green',
value: 15,
},
{
comparisonOperator: 'GT',
color: 'green',
value: 5,
},
]);

expect(convertedThresholds).toHaveProperty('markLine.data[0].yAxis', 10);
expect(convertedThresholds).toHaveProperty('markLine.data[1].yAxis', 15);
expect(convertedThresholds).toHaveProperty('markLine.data[2].yAxis', 5);

expect(convertedThresholds).toHaveProperty('markArea.data[0][0].yAxis', 10);
expect(convertedThresholds).toHaveProperty('markArea.data[0][1].yAxis', 10);
expect(convertedThresholds).toHaveProperty('markArea.data[1][0].yAxis', 0);
expect(convertedThresholds).toHaveProperty('markArea.data[1][1].yAxis', 15);
expect(convertedThresholds).toHaveProperty('markArea.data[2][0].yAxis', 5);
expect(convertedThresholds).toHaveProperty('markArea.data[2][1].yAxis', undefined);
});
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const useVisualizedDataStreams = (queries: TimeSeriesDataQuery[], passedI

const utilizedViewport = passedInViewport || viewport || DEFAULT_VIEWPORT; // explicitly passed in viewport overrides viewport group

const { dataStreams } = useTimeSeriesData({
const { dataStreams, thresholds } = useTimeSeriesData({
viewport: utilizedViewport,
queries,
settings: {
Expand All @@ -36,5 +36,6 @@ export const useVisualizedDataStreams = (queries: TimeSeriesDataQuery[], passedI
hasError,
isLoading,
dataStreams: dataStreamsWithoutAlarms,
thresholds,
};
};

0 comments on commit 2d7ccfe

Please sign in to comment.