@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
@@ -2,7 +2,7 @@ import { useMemo, useRef } from 'react';
2
2
 
3
3
  import { Group, Tooltip } from '@visx/visx';
4
4
  import { scaleLinear } from '@visx/scale';
5
- import { head } from 'ramda';
5
+ import { flatten, head, pluck } from 'ramda';
6
6
  import { Bar } from '@visx/shape';
7
7
  import { useSpring, animated } from '@react-spring/web';
8
8
 
@@ -17,7 +17,8 @@ import { getColorFromDataAndTresholds } from '../common/utils';
17
17
  import { margins } from '../common/margins';
18
18
 
19
19
  import { SingleBarProps } from './models';
20
- import Thresholds, { barHeight, groupMargin, margin } from './Thresholds';
20
+ import Thresholds, { groupMargin } from './Thresholds';
21
+ import { barHeight, margin } from './ThresholdLine';
21
22
 
22
23
  interface Props extends SingleBarProps {
23
24
  height: number;
@@ -31,19 +32,21 @@ const baseStyles = {
31
32
 
32
33
  const ResponsiveSingleBar = ({
33
34
  data,
34
- thresholdTooltipLabels,
35
35
  thresholds,
36
36
  width,
37
- height,
38
- disabledThresholds
37
+ height
39
38
  }: Props): JSX.Element => {
40
39
  const theme = useTheme();
41
40
 
42
41
  const metric = getMetricWithLatestData(data) as Metric;
43
42
  const latestMetricData = head(metric.data) as number;
43
+ const thresholdValues = flatten([
44
+ pluck('value', thresholds.warning),
45
+ pluck('value', thresholds.critical)
46
+ ]);
44
47
  const adaptedMaxValue = Math.max(
45
48
  metric.maximum_value || 0,
46
- Math.max(...thresholds) * 1.1,
49
+ Math.max(...thresholdValues) * 1.1,
47
50
  head(metric.data) as number
48
51
  );
49
52
 
@@ -131,11 +134,10 @@ const ResponsiveSingleBar = ({
131
134
  x={0}
132
135
  y={groupMargin + margin}
133
136
  />
134
- {!disabledThresholds && (
137
+ {thresholds.enabled && (
135
138
  <Thresholds
136
139
  hideTooltip={hideTooltip}
137
140
  showTooltip={showTooltip}
138
- thresholdTooltipLabels={thresholdTooltipLabels}
139
141
  thresholds={thresholds}
140
142
  xScale={xScale}
141
143
  />
@@ -20,8 +20,21 @@ const Template = (props): JSX.Element => (
20
20
  export const success: Story = {
21
21
  args: {
22
22
  data: dataLastWeek,
23
- thresholdTooltipLabels: ['Warning', 'Critical'],
24
- thresholds: [0.5, 1.5]
23
+ thresholds: {
24
+ critical: [
25
+ {
26
+ label: 'Critical',
27
+ value: 0.6
28
+ }
29
+ ],
30
+ enabled: true,
31
+ warning: [
32
+ {
33
+ label: 'Warning',
34
+ value: 0.5
35
+ }
36
+ ]
37
+ }
25
38
  },
26
39
  render: Template
27
40
  };
@@ -29,8 +42,21 @@ export const success: Story = {
29
42
  export const warning: Story = {
30
43
  args: {
31
44
  data: dataLastWeek,
32
- thresholdTooltipLabels: ['Warning', 'Critical'],
33
- thresholds: [0.2, 0.5]
45
+ thresholds: {
46
+ critical: [
47
+ {
48
+ label: 'Critical',
49
+ value: 0.5
50
+ }
51
+ ],
52
+ enabled: true,
53
+ warning: [
54
+ {
55
+ label: 'Warning',
56
+ value: 0.2
57
+ }
58
+ ]
59
+ }
34
60
  },
35
61
  render: Template
36
62
  };
@@ -38,8 +64,95 @@ export const warning: Story = {
38
64
  export const critical: Story = {
39
65
  args: {
40
66
  data: dataLastWeek,
41
- thresholdTooltipLabels: ['Warning', 'Critical'],
42
- thresholds: [0.13, 0.35]
67
+ thresholds: {
68
+ critical: [
69
+ {
70
+ label: 'Critical',
71
+ value: 0.35
72
+ }
73
+ ],
74
+ enabled: true,
75
+ warning: [
76
+ {
77
+ label: 'Warning',
78
+ value: 0.13
79
+ }
80
+ ]
81
+ }
82
+ },
83
+ render: Template
84
+ };
85
+
86
+ export const disabled: Story = {
87
+ args: {
88
+ data: dataLastWeek,
89
+ thresholds: {
90
+ critical: [
91
+ {
92
+ label: 'Critical',
93
+ value: 0.35
94
+ }
95
+ ],
96
+ enabled: false,
97
+ warning: [
98
+ {
99
+ label: 'Warning',
100
+ value: 0.13
101
+ }
102
+ ]
103
+ }
104
+ },
105
+ render: Template
106
+ };
107
+
108
+ export const criticalLowerThanWarning: Story = {
109
+ args: {
110
+ data: dataLastWeek,
111
+ thresholds: {
112
+ critical: [
113
+ {
114
+ label: 'Critical',
115
+ value: 0.13
116
+ }
117
+ ],
118
+ enabled: true,
119
+ warning: [
120
+ {
121
+ label: 'Warning',
122
+ value: 0.5
123
+ }
124
+ ]
125
+ }
126
+ },
127
+ render: Template
128
+ };
129
+
130
+ export const rangeThresholds: Story = {
131
+ args: {
132
+ data: dataLastWeek,
133
+ thresholds: {
134
+ critical: [
135
+ {
136
+ label: 'Critical 1',
137
+ value: 0.5
138
+ },
139
+ {
140
+ label: 'Critical 2',
141
+ value: 0.6
142
+ }
143
+ ],
144
+ enabled: true,
145
+ warning: [
146
+ {
147
+ label: 'Warning 1',
148
+ value: 0.13
149
+ },
150
+ {
151
+ label: 'Warning 2',
152
+ value: 0.3
153
+ }
154
+ ]
155
+ }
43
156
  },
44
157
  render: Template
45
158
  };
@@ -0,0 +1,74 @@
1
+ import { equals } from 'ramda';
2
+
3
+ import { useTheme } from '@mui/material';
4
+
5
+ import { groupMargin } from './Thresholds';
6
+
7
+ const lineMargin = 10;
8
+
9
+ const thresholdLineHeight = 60 + 2 * lineMargin;
10
+
11
+ export const margin = 40;
12
+
13
+ export const barHeight = 50;
14
+
15
+ interface Props {
16
+ hideTooltip: () => void;
17
+ label: string;
18
+ showTooltip: (args) => void;
19
+ thresholdType: string;
20
+ value: number;
21
+ xScale: (value: number) => number;
22
+ }
23
+
24
+ export const ThresholdLine = ({
25
+ value,
26
+ label,
27
+ xScale,
28
+ thresholdType,
29
+ showTooltip,
30
+ hideTooltip
31
+ }: Props): JSX.Element => {
32
+ const theme = useTheme();
33
+
34
+ const scaledValue = xScale(value) || 0;
35
+
36
+ const bottom = barHeight + margin * 2;
37
+
38
+ const onMouseEnter = (left) => (): void =>
39
+ showTooltip({
40
+ tooltipData: label,
41
+ tooltipLeft: left,
42
+ tooltipTop: bottom
43
+ });
44
+
45
+ const lineColor = equals(thresholdType, 'warning')
46
+ ? theme.palette.warning.main
47
+ : theme.palette.error.main;
48
+
49
+ return (
50
+ <>
51
+ <line
52
+ data-testid={`${thresholdType}-line-${value}`}
53
+ stroke={lineColor}
54
+ strokeDasharray={4}
55
+ strokeWidth={2}
56
+ x1={scaledValue}
57
+ x2={scaledValue}
58
+ y1={groupMargin + 3 * lineMargin}
59
+ y2={thresholdLineHeight + groupMargin + 3 * lineMargin}
60
+ />
61
+ <line
62
+ data-testid={`${thresholdType}-line-${value}-tooltip`}
63
+ stroke="transparent"
64
+ strokeWidth={5}
65
+ x1={scaledValue}
66
+ x2={scaledValue}
67
+ y1={groupMargin + 3 * lineMargin}
68
+ y2={thresholdLineHeight + groupMargin + 3 * lineMargin}
69
+ onMouseEnter={onMouseEnter(scaledValue)}
70
+ onMouseLeave={hideTooltip}
71
+ />
72
+ </>
73
+ );
74
+ };
@@ -1,20 +1,13 @@
1
- import { useTheme } from '@mui/material';
1
+ import { Thresholds } from '../common/models';
2
2
 
3
- export const margin = 40;
4
-
5
- export const barHeight = 50;
3
+ import { ThresholdLine } from './ThresholdLine';
6
4
 
7
5
  export const groupMargin = 25;
8
6
 
9
- const lineMargin = 10;
10
-
11
- const thresholdLineHeight = 60 + 2 * lineMargin;
12
-
13
7
  interface Props {
14
8
  hideTooltip: () => void;
15
9
  showTooltip: (args) => void;
16
- thresholdTooltipLabels: Array<string>;
17
- thresholds: Array<number>;
10
+ thresholds: Thresholds;
18
11
  xScale: (value: number) => number;
19
12
  }
20
13
 
@@ -22,79 +15,32 @@ const Thresholds = ({
22
15
  xScale,
23
16
  thresholds,
24
17
  showTooltip,
25
- hideTooltip,
26
- thresholdTooltipLabels
27
- }: Props): JSX.Element => {
28
- const theme = useTheme();
29
-
30
- const warningValue = thresholds[0];
31
- const criticalValue = thresholds[1];
32
- const warningTooltipLabel = thresholdTooltipLabels[0];
33
- const criticalTooltipLabel = thresholdTooltipLabels[1];
34
-
35
- const bottom = barHeight + margin * 2;
36
-
37
- const onMouseEnter =
38
- ({ label, left }) =>
39
- (): void =>
40
- showTooltip({
41
- tooltipData: label,
42
- tooltipLeft: left,
43
- tooltipTop: bottom
44
- });
45
-
46
- return (
47
- <>
48
- <line
49
- data-testid="warning-line"
50
- stroke={theme.palette.warning.main}
51
- strokeDasharray={4}
52
- strokeWidth={2}
53
- x1={xScale(warningValue)}
54
- x2={xScale(warningValue)}
55
- y1={groupMargin + 3 * lineMargin}
56
- y2={thresholdLineHeight + groupMargin + 3 * lineMargin}
57
- />
58
- <line
59
- data-testid="critical-line"
60
- stroke={theme.palette.error.main}
61
- strokeDasharray={4}
62
- strokeWidth={2}
63
- x1={xScale(criticalValue)}
64
- x2={xScale(criticalValue)}
65
- y1={groupMargin + 3 * lineMargin}
66
- y2={thresholdLineHeight + groupMargin + 3 * lineMargin}
67
- />
68
- <line
69
- data-testid="warning-line-tooltip"
70
- stroke="transparent"
71
- strokeWidth={5}
72
- x1={xScale(warningValue)}
73
- x2={xScale(warningValue)}
74
- y1={groupMargin + 3 * lineMargin}
75
- y2={thresholdLineHeight + groupMargin + 3 * lineMargin}
76
- onMouseEnter={onMouseEnter({
77
- label: warningTooltipLabel,
78
- left: xScale(warningValue)
79
- })}
80
- onMouseLeave={hideTooltip}
18
+ hideTooltip
19
+ }: Props): JSX.Element => (
20
+ <>
21
+ {thresholds.warning.map(({ value, label }) => (
22
+ <ThresholdLine
23
+ hideTooltip={hideTooltip}
24
+ key={`warning-${value.toString()}`}
25
+ label={label}
26
+ showTooltip={showTooltip}
27
+ thresholdType="warning"
28
+ value={value}
29
+ xScale={xScale}
81
30
  />
82
- <line
83
- data-testid="critical-line-tooltip"
84
- stroke="transparent"
85
- strokeWidth={5}
86
- x1={xScale(criticalValue)}
87
- x2={xScale(criticalValue)}
88
- y1={groupMargin + 3 * lineMargin}
89
- y2={thresholdLineHeight + groupMargin + 3 * lineMargin}
90
- onMouseEnter={onMouseEnter({
91
- label: criticalTooltipLabel,
92
- left: xScale(criticalValue)
93
- })}
94
- onMouseLeave={hideTooltip}
31
+ ))}
32
+ {thresholds.critical.map(({ value, label }) => (
33
+ <ThresholdLine
34
+ hideTooltip={hideTooltip}
35
+ key={`critical-${value.toString()}`}
36
+ label={label}
37
+ showTooltip={showTooltip}
38
+ thresholdType="critical"
39
+ value={value}
40
+ xScale={xScale}
95
41
  />
96
- </>
97
- );
98
- };
42
+ ))}
43
+ </>
44
+ );
99
45
 
100
46
  export default Thresholds;
@@ -1,8 +1,6 @@
1
- import { LineChartData } from '../common/models';
1
+ import { LineChartData, Thresholds } from '../common/models';
2
2
 
3
3
  export interface SingleBarProps {
4
4
  data?: LineChartData;
5
- disabledThresholds?: boolean;
6
- thresholdTooltipLabels: Array<string>;
7
- thresholds: Array<number>;
5
+ thresholds: Thresholds;
8
6
  }
@@ -2,7 +2,7 @@ import { isNil } from 'ramda';
2
2
 
3
3
  import { Typography, useTheme } from '@mui/material';
4
4
 
5
- import { LineChartData } from '../common/models';
5
+ import { LineChartData, Thresholds } from '../common/models';
6
6
  import {
7
7
  formatMetricValue,
8
8
  getMetricWithLatestData
@@ -13,19 +13,17 @@ import { useTextStyles } from './Text.styles';
13
13
 
14
14
  interface Props {
15
15
  data?: LineChartData;
16
- disabledThresholds?: boolean;
17
16
  labels: {
18
17
  critical: string;
19
18
  warning: string;
20
19
  };
21
- thresholds: Array<number>;
20
+ thresholds: Thresholds;
22
21
  }
23
22
 
24
23
  export const Text = ({
25
24
  thresholds,
26
25
  data,
27
- labels,
28
- disabledThresholds
26
+ labels
29
27
  }: Props): JSX.Element | null => {
30
28
  const theme = useTheme();
31
29
  const { classes } = useTextStyles();
@@ -44,6 +42,20 @@ export const Text = ({
44
42
  thresholds
45
43
  });
46
44
 
45
+ const warningThresholdLabels = thresholds.warning.map(({ value }) =>
46
+ formatMetricValue({
47
+ unit: metricUnit,
48
+ value
49
+ })
50
+ );
51
+
52
+ const criticalThresholdLabels = thresholds.critical.map(({ value }) =>
53
+ formatMetricValue({
54
+ unit: metricUnit,
55
+ value
56
+ })
57
+ );
58
+
47
59
  return (
48
60
  <div className={classes.graphText}>
49
61
  <Typography sx={{ color }} variant="h3">
@@ -53,25 +65,17 @@ export const Text = ({
53
65
  })}{' '}
54
66
  {metricUnit}
55
67
  </Typography>
56
- {!disabledThresholds && (
68
+ {thresholds.enabled && (
57
69
  <div className={classes.thresholds}>
58
70
  <Typography sx={{ color: 'warning.main' }} variant="h5">
59
71
  {labels.warning}
60
72
  {': '}
61
- {formatMetricValue({
62
- unit: metricUnit,
63
- value: thresholds[0]
64
- })}{' '}
65
- {metricUnit}
73
+ {warningThresholdLabels.join(' - ')} {metricUnit}
66
74
  </Typography>
67
75
  <Typography sx={{ color: 'error.main' }} variant="h5">
68
76
  {labels.critical}
69
77
  {': '}
70
- {formatMetricValue({
71
- unit: metricUnit,
72
- value: thresholds[1]
73
- })}{' '}
74
- {metricUnit}
78
+ {criticalThresholdLabels.join(' - ')} {metricUnit}
75
79
  </Typography>
76
80
  </div>
77
81
  )}
@@ -5,3 +5,15 @@ export interface LineChartData {
5
5
  metrics: Array<Metric>;
6
6
  times: Array<string>;
7
7
  }
8
+
9
+ export interface Thresholds {
10
+ critical: Array<{
11
+ label: string;
12
+ value: number;
13
+ }>;
14
+ enabled: boolean;
15
+ warning: Array<{
16
+ label: string;
17
+ value: number;
18
+ }>;
19
+ }
@@ -326,10 +326,19 @@ const getYScale = ({
326
326
  const getScale = ({
327
327
  graphValues,
328
328
  height,
329
- stackedValues
329
+ stackedValues,
330
+ thresholds
330
331
  }): ScaleLinear<number, number> => {
331
- const minValue = min(getMin(graphValues), getMin(stackedValues));
332
- const maxValue = max(getMax(graphValues), getMax(stackedValues));
332
+ const minValue = Math.min(
333
+ getMin(graphValues),
334
+ getMin(stackedValues),
335
+ Math.min(...thresholds)
336
+ );
337
+ const maxValue = Math.max(
338
+ getMax(graphValues),
339
+ getMax(stackedValues),
340
+ Math.max(...thresholds)
341
+ );
333
342
 
334
343
  const upperRangeValue = minValue === maxValue && maxValue === 0 ? height : 0;
335
344
 
@@ -343,10 +352,17 @@ const getScale = ({
343
352
  const getLeftScale = ({
344
353
  dataLines,
345
354
  dataTimeSeries,
346
- valueGraphHeight
355
+ valueGraphHeight,
356
+ thresholds,
357
+ thresholdUnit
347
358
  }: AxeScale): ScaleLinear<number, number> => {
348
359
  const [firstUnit, , thirdUnit] = getUnits(dataLines);
349
360
 
361
+ const shouldApplyThresholds =
362
+ equals(thresholdUnit, firstUnit) ||
363
+ equals(thresholdUnit, thirdUnit) ||
364
+ !thresholdUnit;
365
+
350
366
  const graphValues = isNil(thirdUnit)
351
367
  ? getMetricValuesForUnit({
352
368
  lines: dataLines,
@@ -370,7 +386,12 @@ const getLeftScale = ({
370
386
  })
371
387
  : [0];
372
388
 
373
- return getScale({ graphValues, height: valueGraphHeight, stackedValues });
389
+ return getScale({
390
+ graphValues,
391
+ height: valueGraphHeight,
392
+ stackedValues,
393
+ thresholds: shouldApplyThresholds ? thresholds : []
394
+ });
374
395
  };
375
396
 
376
397
  const getXScale = ({
@@ -386,7 +407,9 @@ const getXScale = ({
386
407
  const getRightScale = ({
387
408
  dataLines,
388
409
  dataTimeSeries,
389
- valueGraphHeight
410
+ valueGraphHeight,
411
+ thresholds,
412
+ thresholdUnit
390
413
  }: AxeScale): ScaleLinear<number, number> => {
391
414
  const [, secondUnit] = getUnits(dataLines);
392
415
 
@@ -396,6 +419,8 @@ const getRightScale = ({
396
419
  unit: secondUnit
397
420
  });
398
421
 
422
+ const shouldApplyThresholds = equals(thresholdUnit, secondUnit);
423
+
399
424
  const secondUnitHasStackedLines = isNil(secondUnit)
400
425
  ? false
401
426
  : hasUnitStackedLines({ lines: dataLines, unit: secondUnit });
@@ -407,7 +432,12 @@ const getRightScale = ({
407
432
  })
408
433
  : [0];
409
434
 
410
- return getScale({ graphValues, height: valueGraphHeight, stackedValues });
435
+ return getScale({
436
+ graphValues,
437
+ height: valueGraphHeight,
438
+ stackedValues,
439
+ thresholds: shouldApplyThresholds ? thresholds : []
440
+ });
411
441
  };
412
442
 
413
443
  const formatMetricValue = ({
@@ -476,7 +506,10 @@ const getTimeValue = ({
476
506
  xScale,
477
507
  timeSeries,
478
508
  marginLeft = margin.left
479
- }: TimeValueProps): TimeValue => {
509
+ }: TimeValueProps): TimeValue | null => {
510
+ if (isNil(x)) {
511
+ return null;
512
+ }
480
513
  const date = xScale.invert(x - marginLeft);
481
514
  const index = bisectDate(getDates(timeSeries), date);
482
515
 
@@ -65,6 +65,8 @@ export interface Xscale {
65
65
  export interface AxeScale {
66
66
  dataLines: Array<Line>;
67
67
  dataTimeSeries: Array<TimeValue>;
68
+ thresholdUnit?: string;
69
+ thresholds: Array<number>;
68
70
  valueGraphHeight: number;
69
71
  }
70
72
 
@@ -117,6 +119,6 @@ export interface YScales {
117
119
  export interface TimeValueProps {
118
120
  marginLeft?: number;
119
121
  timeSeries: Array<TimeValue>;
120
- x: number;
122
+ x?: number;
121
123
  xScale: ScaleLinear<number, number>;
122
124
  }