@centreon/ui 23.10.61 → 23.10.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/package.json +1 -1
  2. package/src/Graph/Gauge/AnimatedPie.tsx +31 -20
  3. package/src/Graph/Gauge/Gauge.stories.tsx +97 -6
  4. package/src/Graph/Gauge/Gauge.tsx +4 -15
  5. package/src/Graph/Gauge/PieData.tsx +8 -24
  6. package/src/Graph/Gauge/ResponsiveGauge.tsx +11 -14
  7. package/src/Graph/Gauge/Thresholds.tsx +109 -56
  8. package/src/Graph/Gauge/models.ts +2 -3
  9. package/src/Graph/LineChart/BasicComponents/ThresholdLine.tsx +64 -0
  10. package/src/Graph/LineChart/BasicComponents/Thresholds.tsx +77 -0
  11. package/src/Graph/LineChart/BasicComponents/useFilterLines.ts +9 -7
  12. package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/index.tsx +2 -4
  13. package/src/Graph/LineChart/InteractiveComponents/interactionWithGraphAtoms.ts +1 -0
  14. package/src/Graph/LineChart/Legend/index.tsx +9 -4
  15. package/src/Graph/LineChart/Legend/useInteractiveValues.ts +13 -4
  16. package/src/Graph/LineChart/Legend/useLegend.ts +10 -13
  17. package/src/Graph/LineChart/LineChart.tsx +73 -8
  18. package/src/Graph/LineChart/graphAtoms.ts +0 -3
  19. package/src/Graph/LineChart/index.stories.tsx +101 -6
  20. package/src/Graph/LineChart/index.tsx +13 -3
  21. package/src/Graph/SingleBar/ResponsiveSingleBar.tsx +10 -8
  22. package/src/Graph/SingleBar/SingleBar.stories.tsx +119 -6
  23. package/src/Graph/SingleBar/ThresholdLine.tsx +74 -0
  24. package/src/Graph/SingleBar/Thresholds.tsx +28 -82
  25. package/src/Graph/SingleBar/models.ts +2 -4
  26. package/src/Graph/Text/Text.tsx +20 -16
  27. package/src/Graph/common/models.ts +12 -0
  28. package/src/Graph/common/timeSeries/index.ts +41 -8
  29. package/src/Graph/common/timeSeries/models.ts +3 -1
  30. package/src/Graph/common/utils.ts +59 -6
  31. package/src/api/useGraphQuery/index.ts +52 -21
  32. package/src/components/Modal/Modal.styles.ts +1 -2
  33. package/src/utils/index.ts +1 -0
  34. package/src/utils/useRefreshInterval.ts +21 -0
  35. package/src/utils/useThresholds.ts +0 -0
@@ -0,0 +1,77 @@
1
+ import { equals, isNil } from 'ramda';
2
+
3
+ import { getUnits, getYScale } from '../../common/timeSeries';
4
+ import { Line } from '../../common/timeSeries/models';
5
+ import { Thresholds } from '../../common/models';
6
+
7
+ import { ThresholdLine } from './ThresholdLine';
8
+
9
+ interface Props {
10
+ displayedLines: Array<Line>;
11
+ hideTooltip: () => void;
12
+ leftScale: (value: number) => number;
13
+ rightScale: (value: number) => number;
14
+ showTooltip: (props) => void;
15
+ thresholdUnit?: string;
16
+ thresholds: Thresholds;
17
+ width: number;
18
+ }
19
+
20
+ const Thresholds = ({
21
+ thresholds,
22
+ leftScale,
23
+ rightScale,
24
+ width,
25
+ displayedLines,
26
+ thresholdUnit,
27
+ showTooltip,
28
+ hideTooltip
29
+ }: Props): JSX.Element => {
30
+ const [firstUnit, secondUnit, thirdUnit] = getUnits(
31
+ displayedLines as Array<Line>
32
+ );
33
+
34
+ const shouldUseRightScale = equals(thresholdUnit, secondUnit);
35
+
36
+ const yScale = shouldUseRightScale
37
+ ? rightScale
38
+ : getYScale({
39
+ hasMoreThanTwoUnits: !isNil(thirdUnit),
40
+ invert: null,
41
+ leftScale,
42
+ rightScale,
43
+ secondUnit,
44
+ unit: firstUnit
45
+ });
46
+
47
+ return (
48
+ <>
49
+ {thresholds.warning.map(({ value, label }) => (
50
+ <ThresholdLine
51
+ hideTooltip={hideTooltip}
52
+ key={`warning-${value}`}
53
+ label={label}
54
+ showTooltip={showTooltip}
55
+ thresholdType="warning"
56
+ value={value}
57
+ width={width}
58
+ yScale={yScale}
59
+ />
60
+ ))}
61
+ {thresholds.critical.map(({ value, label }) => (
62
+ <ThresholdLine
63
+ hideTooltip={hideTooltip}
64
+ key={`critical-${value}`}
65
+ label={label}
66
+ showTooltip={showTooltip}
67
+ thresholdType="critical"
68
+ value={value}
69
+ width={width}
70
+ yScale={yScale}
71
+ />
72
+ ))}
73
+ </>
74
+ );
75
+ };
76
+
77
+ export default Thresholds;
@@ -1,9 +1,7 @@
1
- import { useEffect } from 'react';
1
+ import { Dispatch, SetStateAction, useEffect } from 'react';
2
2
 
3
- import { useAtom } from 'jotai';
4
3
  import { compose, equals, prop, propEq, reject, sortBy, toLower } from 'ramda';
5
4
 
6
- import { linesGraphAtom } from '../graphAtoms';
7
5
  import { Line } from '../../common/timeSeries/models';
8
6
 
9
7
  import {
@@ -15,6 +13,8 @@ import {
15
13
  interface UseFilterLines {
16
14
  displayThreshold?: boolean;
17
15
  lines: Array<Line>;
16
+ linesGraph: Array<Line> | null;
17
+ setLinesGraph: Dispatch<SetStateAction<Array<Line> | null>>;
18
18
  }
19
19
 
20
20
  interface Result {
@@ -24,10 +24,10 @@ interface Result {
24
24
 
25
25
  const useFilterLines = ({
26
26
  displayThreshold = false,
27
- lines
27
+ lines,
28
+ linesGraph,
29
+ setLinesGraph
28
30
  }: UseFilterLines): Result => {
29
- const [linesGraph, setLinesGraph] = useAtom(linesGraphAtom);
30
-
31
31
  const displayedLines = reject(propEq('display', false), linesGraph ?? lines);
32
32
  const filterLines = (): Array<Line> => {
33
33
  const lineOriginMetric = findLineOfOriginMetricThreshold(lines);
@@ -45,7 +45,9 @@ const useFilterLines = ({
45
45
 
46
46
  useEffect(() => {
47
47
  const filteredLines = filterLines();
48
- if (!lines || !displayThreshold || filteredLines.length <= 0) {
48
+ if (!lines || !displayThreshold) {
49
+ setLinesGraph(lines);
50
+
49
51
  return;
50
52
  }
51
53
 
@@ -8,14 +8,12 @@ interface Props {
8
8
 
9
9
  const Point = ({ lineColor, x, y }: Props): JSX.Element => (
10
10
  <circle
11
+ cx={x}
12
+ cy={y}
11
13
  fill={alpha(lineColor, 0.5)}
12
14
  r={4}
13
15
  stroke={lineColor}
14
16
  strokeWidth={2}
15
- style={{
16
- transform: `translate(${x}px, ${y}px)`,
17
- transition: 'transform 0.08s ease-out'
18
- }}
19
17
  />
20
18
  );
21
19
 
@@ -44,6 +44,7 @@ export const changeMousePositionAndTimeValueDerivedAtom = atom(
44
44
 
45
45
  return;
46
46
  }
47
+
47
48
  set(mousePositionAtom, position);
48
49
 
49
50
  set(timeValueAtom, timeValue);
@@ -1,4 +1,4 @@
1
- import { ReactNode } from 'react';
1
+ import { Dispatch, ReactNode, SetStateAction } from 'react';
2
2
 
3
3
  import { slice } from 'ramda';
4
4
  import { useAtomValue } from 'jotai';
@@ -28,8 +28,10 @@ interface Props {
28
28
  limitLegendRows?: boolean;
29
29
  lines: Array<Line>;
30
30
  renderExtraComponent?: ReactNode;
31
+ setLinesGraph: Dispatch<SetStateAction<Array<Line> | null>>;
31
32
  timeSeries: Array<TimeValue>;
32
33
  toggable?: boolean;
34
+ xScale;
33
35
  }
34
36
 
35
37
  const MainLegend = ({
@@ -39,18 +41,21 @@ const MainLegend = ({
39
41
  toggable = true,
40
42
  limitLegendRows = true,
41
43
  renderExtraComponent,
42
- displayAnchor = true
44
+ displayAnchor = true,
45
+ setLinesGraph,
46
+ xScale
43
47
  }: Props): JSX.Element => {
44
48
  const { classes, cx } = useStyles({ limitLegendRows });
45
49
  const theme = useTheme();
46
50
 
47
51
  const { selectMetricLine, clearHighlight, highlightLine, toggleMetricLine } =
48
- useLegend({ lines });
52
+ useLegend({ lines, setLinesGraph });
49
53
 
50
54
  const { getFormattedValue } = useInteractiveValues({
51
55
  base,
52
56
  lines,
53
- timeSeries
57
+ timeSeries,
58
+ xScale
54
59
  });
55
60
 
56
61
  const displayedLines = limitLegendRows
@@ -3,11 +3,12 @@ import { useMemo } from 'react';
3
3
  import { useAtomValue } from 'jotai';
4
4
  import { equals, find, isNil } from 'ramda';
5
5
 
6
- import { timeValueAtom } from '../InteractiveComponents/interactionWithGraphAtoms';
6
+ import { mousePositionAtom } from '../InteractiveComponents/interactionWithGraphAtoms';
7
7
  import {
8
8
  formatMetricValue,
9
9
  getLineForMetric,
10
- getMetrics
10
+ getMetrics,
11
+ getTimeValue
11
12
  } from '../../common/timeSeries';
12
13
  import { Line, TimeValue } from '../../common/timeSeries/models';
13
14
 
@@ -21,14 +22,22 @@ interface Props {
21
22
  base: number;
22
23
  lines: Array<Line>;
23
24
  timeSeries: Array<TimeValue>;
25
+ xScale;
24
26
  }
25
27
 
26
28
  const useInteractiveValues = ({
27
29
  timeSeries,
28
30
  lines,
29
- base
31
+ base,
32
+ xScale
30
33
  }: Props): InteractiveValues => {
31
- const timeValue = useAtomValue(timeValueAtom);
34
+ const mousePosition = useAtomValue(mousePositionAtom);
35
+
36
+ const timeValue = getTimeValue({
37
+ timeSeries,
38
+ x: mousePosition?.[0],
39
+ xScale
40
+ });
32
41
 
33
42
  const graphTimeValue = timeSeries?.find((item) =>
34
43
  equals(item.timeTick, timeValue?.timeTick)
@@ -1,6 +1,5 @@
1
- import { useEffect } from 'react';
1
+ import { Dispatch, SetStateAction, useEffect } from 'react';
2
2
 
3
- import { useSetAtom } from 'jotai';
4
3
  import {
5
4
  equals,
6
5
  find,
@@ -17,7 +16,6 @@ import {
17
16
  toLower
18
17
  } from 'ramda';
19
18
 
20
- import { linesGraphAtom } from '../graphAtoms';
21
19
  import { Line } from '../../common/timeSeries/models';
22
20
 
23
21
  interface LegendActions {
@@ -29,11 +27,10 @@ interface LegendActions {
29
27
 
30
28
  interface Props {
31
29
  lines: Array<Line>;
30
+ setLinesGraph: Dispatch<SetStateAction<Array<Line> | null>>;
32
31
  }
33
32
 
34
- const useLegend = ({ lines }: Props): LegendActions => {
35
- const setLines = useSetAtom(linesGraphAtom);
36
-
33
+ const useLegend = ({ lines, setLinesGraph }: Props): LegendActions => {
37
34
  const displayedLines = reject(propEq('display', false), lines);
38
35
  const getLineByMetric = (metric: string): Line =>
39
36
  find(propEq('metric', metric), lines) as Line;
@@ -41,7 +38,7 @@ const useLegend = ({ lines }: Props): LegendActions => {
41
38
  const toggleMetricLine = (metric): void => {
42
39
  const line = getLineByMetric(metric);
43
40
 
44
- setLines([
41
+ setLinesGraph([
45
42
  ...reject(propEq('metric', metric), lines),
46
43
  { ...line, display: !line.display }
47
44
  ]);
@@ -56,11 +53,11 @@ const useLegend = ({ lines }: Props): LegendActions => {
56
53
 
57
54
  const sortedData = sortBy(compose(toLower, prop('name')), data);
58
55
 
59
- setLines(sortedData);
56
+ setLinesGraph(sortedData);
60
57
  };
61
58
 
62
59
  const clearHighlight = (): void => {
63
- setLines(map((line) => ({ ...line, highlight: undefined }), lines));
60
+ setLinesGraph(map((line) => ({ ...line, highlight: undefined }), lines));
64
61
  };
65
62
 
66
63
  const selectMetricLine = (metric: string): void => {
@@ -71,7 +68,7 @@ const useLegend = ({ lines }: Props): LegendActions => {
71
68
  equals(displayedLines.length, 1) && isLineDisplayed;
72
69
 
73
70
  if (isOnlyLineDisplayed || isEmpty(displayedLines)) {
74
- setLines(
71
+ setLinesGraph(
75
72
  map(
76
73
  (line) => ({
77
74
  ...line,
@@ -84,7 +81,7 @@ const useLegend = ({ lines }: Props): LegendActions => {
84
81
  return;
85
82
  }
86
83
 
87
- setLines(
84
+ setLinesGraph(
88
85
  map(
89
86
  (line) => ({
90
87
  ...line,
@@ -105,8 +102,8 @@ const useLegend = ({ lines }: Props): LegendActions => {
105
102
  display: find(propEq('name', line.name), lines)?.display ?? true
106
103
  }));
107
104
 
108
- setLines(newLines);
109
- }, []);
105
+ setLinesGraph(newLines);
106
+ }, [lines]);
110
107
 
111
108
  return { clearHighlight, highlightLine, selectMetricLine, toggleMetricLine };
112
109
  };
@@ -1,11 +1,13 @@
1
- import { MutableRefObject, useMemo, useRef } from 'react';
1
+ import { MutableRefObject, useMemo, useRef, useState } from 'react';
2
2
 
3
- import { Group } from '@visx/visx';
4
- import { isNil } from 'ramda';
3
+ import { Group, Tooltip } from '@visx/visx';
4
+ import { flatten, isNil, pluck } from 'ramda';
5
5
 
6
- import { ClickAwayListener, Skeleton } from '@mui/material';
6
+ import { ClickAwayListener, Fade, Skeleton, useTheme } from '@mui/material';
7
7
 
8
8
  import { getLeftScale, getRightScale, getXScale } from '../common/timeSeries';
9
+ import { Line } from '../common/timeSeries/models';
10
+ import { Thresholds as ThresholdsModel } from '../common/models';
9
11
 
10
12
  import Axes from './BasicComponents/Axes';
11
13
  import Grids from './BasicComponents/Grids';
@@ -30,6 +32,7 @@ import {
30
32
  } from './models';
31
33
  import { useIntersection } from './useLineChartIntersection';
32
34
  import { CurveType } from './BasicComponents/Lines/models';
35
+ import Thresholds from './BasicComponents/Thresholds';
33
36
 
34
37
  interface Props extends LineChartProps {
35
38
  curve: CurveType;
@@ -39,8 +42,15 @@ interface Props extends LineChartProps {
39
42
  legend?: LegendModel;
40
43
  marginBottom: number;
41
44
  shapeLines?: GlobalAreaLines;
45
+ thresholdUnit?: string;
46
+ thresholds?: ThresholdsModel;
42
47
  }
43
48
 
49
+ const baseStyles = {
50
+ ...Tooltip.defaultStyles,
51
+ textAlign: 'center'
52
+ };
53
+
44
54
  const LineChart = ({
45
55
  graphData,
46
56
  height = 500,
@@ -58,15 +68,30 @@ const LineChart = ({
58
68
  graphRef,
59
69
  header,
60
70
  curve,
61
- marginBottom
71
+ marginBottom,
72
+ thresholds,
73
+ thresholdUnit
62
74
  }: Props): JSX.Element => {
75
+ const { classes } = useStyles();
76
+
77
+ const theme = useTheme();
78
+
79
+ const [linesGraph, setLinesGraph] = useState<Array<Line> | null>(null);
63
80
  const graphSvgRef = useRef<SVGSVGElement | null>(null);
64
81
 
65
- const { classes } = useStyles();
66
82
  const { isInViewport } = useIntersection({ element: graphRef?.current });
67
83
 
68
84
  const legendRef = useRef<HTMLDivElement | null>(null);
69
85
 
86
+ const {
87
+ tooltipOpen: thresholdTooltipOpen,
88
+ tooltipLeft: thresholdTooltipLeft,
89
+ tooltipTop: thresholdTooltipTop,
90
+ tooltipData: thresholdTooltipData,
91
+ hideTooltip: hideThresholdTooltip,
92
+ showTooltip: showThresholdTooltip
93
+ } = Tooltip.useTooltip();
94
+
70
95
  const graphWidth = width > 0 ? width - margin.left - margin.right : 0;
71
96
  const graphHeight =
72
97
  (height || 0) > 0
@@ -79,9 +104,16 @@ const LineChart = ({
79
104
 
80
105
  const { title, timeSeries, baseAxis, lines } = graphData;
81
106
 
107
+ const thresholdValues = flatten([
108
+ pluck('value', thresholds?.warning || []),
109
+ pluck('value', thresholds?.critical || [])
110
+ ]);
111
+
82
112
  const { displayedLines, newLines } = useFilterLines({
83
113
  displayThreshold: canDisplayThreshold(shapeLines?.areaThresholdLines),
84
- lines
114
+ lines,
115
+ linesGraph,
116
+ setLinesGraph
85
117
  });
86
118
 
87
119
  const xScale = useMemo(
@@ -98,9 +130,11 @@ const LineChart = ({
98
130
  getLeftScale({
99
131
  dataLines: displayedLines,
100
132
  dataTimeSeries: timeSeries,
133
+ thresholdUnit,
134
+ thresholds: (thresholds?.enabled && thresholdValues) || [],
101
135
  valueGraphHeight: graphHeight - 35
102
136
  }),
103
- [displayedLines, timeSeries, graphHeight]
137
+ [displayedLines, timeSeries, graphHeight, thresholdValues]
104
138
  );
105
139
 
106
140
  const rightScale = useMemo(
@@ -108,6 +142,8 @@ const LineChart = ({
108
142
  getRightScale({
109
143
  dataLines: displayedLines,
110
144
  dataTimeSeries: timeSeries,
145
+ thresholdUnit,
146
+ thresholds: (thresholds?.enabled && thresholdValues) || [],
111
147
  valueGraphHeight: graphHeight - 35
112
148
  }),
113
149
  [timeSeries, displayedLines, graphHeight]
@@ -201,6 +237,19 @@ const LineChart = ({
201
237
  }}
202
238
  zoomData={{ ...zoomPreview }}
203
239
  />
240
+
241
+ {thresholds?.enabled && (
242
+ <Thresholds
243
+ displayedLines={displayedLines}
244
+ hideTooltip={hideThresholdTooltip}
245
+ leftScale={leftScale}
246
+ rightScale={rightScale}
247
+ showTooltip={showThresholdTooltip}
248
+ thresholdUnit={thresholdUnit}
249
+ thresholds={thresholds as ThresholdsModel}
250
+ width={graphWidth}
251
+ />
252
+ )}
204
253
  </Group.Group>
205
254
  </svg>
206
255
  {displayTooltip && (
@@ -218,6 +267,20 @@ const LineChart = ({
218
267
  xScale={xScale}
219
268
  />
220
269
  )}
270
+ <Fade in={thresholdTooltipOpen}>
271
+ <Tooltip.Tooltip
272
+ left={thresholdTooltipLeft}
273
+ style={{
274
+ ...baseStyles,
275
+ backgroundColor: theme.palette.background.paper,
276
+ color: theme.palette.text.primary,
277
+ transform: `translate(${graphWidth / 2}px, -10px)`
278
+ }}
279
+ top={thresholdTooltipTop}
280
+ >
281
+ {thresholdTooltipData}
282
+ </Tooltip.Tooltip>
283
+ </Fade>
221
284
  </div>
222
285
  </ClickAwayListener>
223
286
  {displayLegend && (
@@ -227,7 +290,9 @@ const LineChart = ({
227
290
  displayAnchor={displayAnchor?.displayGuidingLines ?? true}
228
291
  lines={newLines}
229
292
  renderExtraComponent={legend?.renderExtraComponent}
293
+ setLinesGraph={setLinesGraph}
230
294
  timeSeries={timeSeries}
295
+ xScale={xScale}
231
296
  />
232
297
  </div>
233
298
  )}
@@ -1,6 +1,3 @@
1
1
  import { atom } from 'jotai';
2
2
 
3
- import { Line } from '../common/timeSeries/models';
4
-
5
- export const linesGraphAtom = atom<Array<Line> | null>(null);
6
3
  export const timeTickGraphAtom = atom<Date | null>(null);
@@ -29,10 +29,11 @@ import exclusionPeriodFirstPeriod from './mockedData/exclusionPeriodFirstPeriod.
29
29
  import exclusionPeriodSecondPeriod from './mockedData/exclusionPeriodSecondPeriod.json';
30
30
  import exclusionPeriodThirdPeriod from './mockedData/exclusionPeriodThirdPeriod.json';
31
31
  import dataLastDayForword from './mockedData/lastDayForward.json';
32
- import dataLastDay from './mockedData/lastDayThreshold.json';
32
+ import dataLastDayThreshold from './mockedData/lastDayThreshold.json';
33
33
  import dataLastMonth from './mockedData/lastMonth.json';
34
34
  import dataLastWeek from './mockedData/lastWeek.json';
35
35
  import dataZoomPreview from './mockedData/zoomPreview.json';
36
+ import dataLastDay from './mockedData/lastDay.json';
36
37
  import { Interval, ThresholdType, TooltipData } from './models';
37
38
 
38
39
  import WrapperLineChart from './index';
@@ -75,7 +76,7 @@ const Threshold = (args): JSX.Element => {
75
76
 
76
77
  <WrapperLineChart
77
78
  {...args}
78
- data={dataLastDay}
79
+ data={dataLastDayThreshold}
79
80
  shapeLines={{
80
81
  areaThresholdLines: [
81
82
  { type: ThresholdType.basic },
@@ -123,7 +124,7 @@ const LineChartAndCLS = (args): JSX.Element => {
123
124
  useEffect(() => {
124
125
  setTimeout(() => {
125
126
  setLoading(false);
126
- setData(dataLastDay as unknown as LineChartData);
127
+ setData(dataLastDayThreshold as unknown as LineChartData);
127
128
  }, 100000);
128
129
  }, []);
129
130
 
@@ -187,7 +188,7 @@ const LineChartAndTimePeriod = (args): JSX.Element => {
187
188
  }
188
189
 
189
190
  if (start.includes(`${defaultStart.split('T')[0]}`)) {
190
- setCurrentData(dataLastDay as unknown as LineChartData);
191
+ setCurrentData(dataLastDayThreshold as unknown as LineChartData);
191
192
 
192
193
  return;
193
194
  }
@@ -281,7 +282,7 @@ const LineChartAndExclusionPeriod = (args): JSX.Element => {
281
282
  </ButtonGroup>
282
283
  <WrapperLineChart
283
284
  {...args}
284
- data={dataLastDay as unknown as LineChartData}
285
+ data={dataLastDayThreshold as unknown as LineChartData}
285
286
  shapeLines={{
286
287
  areaThresholdLines: [
287
288
  {
@@ -303,7 +304,7 @@ const Template: Story = {
303
304
  render: (args) => (
304
305
  <WrapperLineChart
305
306
  {...args}
306
- data={dataLastDay as unknown as LineChartData}
307
+ data={dataLastDayThreshold as unknown as LineChartData}
307
308
  shapeLines={{
308
309
  areaThresholdLines: [
309
310
  {
@@ -381,3 +382,97 @@ export const withCLS: Story = {
381
382
  start: defaultStart
382
383
  }
383
384
  };
385
+
386
+ export const withThresholds: Story = {
387
+ argTypes,
388
+ args: {
389
+ ...argumentsData,
390
+ thresholds: {
391
+ critical: [
392
+ {
393
+ label: 'critical',
394
+ value: 350
395
+ }
396
+ ],
397
+ enabled: true,
398
+ warning: [
399
+ {
400
+ label: 'warning',
401
+ value: 300
402
+ }
403
+ ]
404
+ }
405
+ },
406
+ render: (args) => (
407
+ <WrapperLineChart
408
+ {...args}
409
+ data={dataLastDay as unknown as LineChartData}
410
+ />
411
+ )
412
+ };
413
+
414
+ export const withThresholdsAndUnit: Story = {
415
+ argTypes,
416
+ args: {
417
+ ...argumentsData,
418
+ thresholdUnit: '%',
419
+ thresholds: {
420
+ critical: [
421
+ {
422
+ label: 'critical',
423
+ value: 79
424
+ }
425
+ ],
426
+ enabled: true,
427
+ warning: [
428
+ {
429
+ label: 'warning',
430
+ value: 65
431
+ }
432
+ ]
433
+ }
434
+ },
435
+ render: (args) => (
436
+ <WrapperLineChart
437
+ {...args}
438
+ data={dataLastDay as unknown as LineChartData}
439
+ />
440
+ )
441
+ };
442
+
443
+ export const thresholdsRange: Story = {
444
+ argTypes,
445
+ args: {
446
+ ...argumentsData,
447
+ thresholdUnit: '%',
448
+ thresholds: {
449
+ critical: [
450
+ {
451
+ label: 'critical 1',
452
+ value: 60
453
+ },
454
+ {
455
+ label: 'critical 2',
456
+ value: 79
457
+ }
458
+ ],
459
+ enabled: true,
460
+ warning: [
461
+ {
462
+ label: 'warning 1',
463
+ value: 20
464
+ },
465
+ {
466
+ label: 'warning 2',
467
+ value: 30
468
+ }
469
+ ]
470
+ }
471
+ },
472
+ render: (args) => (
473
+ <WrapperLineChart
474
+ {...args}
475
+ data={dataLastDay as unknown as LineChartData}
476
+ />
477
+ )
478
+ };
@@ -10,7 +10,7 @@ import localizedFormat from 'dayjs/plugin/localizedFormat';
10
10
  import timezonePlugin from 'dayjs/plugin/timezone';
11
11
  import utcPlugin from 'dayjs/plugin/utc';
12
12
 
13
- import { LineChartData } from '../common/models';
13
+ import { LineChartData, Thresholds } from '../common/models';
14
14
 
15
15
  import LineChart from './LineChart';
16
16
  import LoadingSkeleton from './LoadingSkeleton';
@@ -31,6 +31,8 @@ interface Props extends Partial<LineChartProps> {
31
31
  marginBottom?: number;
32
32
  shapeLines?: GlobalAreaLines;
33
33
  start: string;
34
+ thresholdUnit?: string;
35
+ thresholds?: Thresholds;
34
36
  }
35
37
 
36
38
  const WrapperLineChart = ({
@@ -50,12 +52,14 @@ const WrapperLineChart = ({
50
52
  legend,
51
53
  header,
52
54
  curve = Curve.curveLinear,
53
- marginBottom = 0
55
+ marginBottom = 0,
56
+ thresholds,
57
+ thresholdUnit
54
58
  }: Props): JSX.Element | null => {
55
59
  const { adjustedData } = useLineChartData({ data, end, start });
56
60
  const lineChartRef = useRef<HTMLDivElement | null>(null);
57
61
 
58
- if (loading || !adjustedData) {
62
+ if (loading && !adjustedData) {
59
63
  return (
60
64
  <LoadingSkeleton
61
65
  displayTitleSkeleton={header?.displayTitle ?? true}
@@ -64,6 +68,10 @@ const WrapperLineChart = ({
64
68
  );
65
69
  }
66
70
 
71
+ if (!adjustedData) {
72
+ return null;
73
+ }
74
+
67
75
  return (
68
76
  <div
69
77
  ref={lineChartRef as MutableRefObject<HTMLDivElement>}
@@ -89,6 +97,8 @@ const WrapperLineChart = ({
89
97
  loading={loading}
90
98
  marginBottom={marginBottom}
91
99
  shapeLines={shapeLines}
100
+ thresholdUnit={thresholdUnit}
101
+ thresholds={thresholds}
92
102
  timeShiftZones={timeShiftZones}
93
103
  tooltip={tooltip}
94
104
  width={width ?? responsiveWidth}