@centreon/ui 23.10.1-MON-21256-handle-range-thresholds.9 → 23.10.1-MON-20799-fe-implement-new-visualization.13
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.
- package/package.json +1 -1
- package/src/Graph/Gauge/AnimatedPie.tsx +20 -31
- package/src/Graph/Gauge/Gauge.stories.tsx +6 -97
- package/src/Graph/Gauge/Gauge.tsx +15 -4
- package/src/Graph/Gauge/PieData.tsx +24 -8
- package/src/Graph/Gauge/ResponsiveGauge.tsx +14 -11
- package/src/Graph/Gauge/Thresholds.tsx +56 -109
- package/src/Graph/Gauge/models.ts +3 -2
- package/src/Graph/LineChart/BasicComponents/useFilterLines.ts +7 -9
- package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/index.tsx +4 -2
- package/src/Graph/LineChart/InteractiveComponents/interactionWithGraphAtoms.ts +0 -1
- package/src/Graph/LineChart/Legend/index.tsx +4 -9
- package/src/Graph/LineChart/Legend/useInteractiveValues.ts +4 -13
- package/src/Graph/LineChart/Legend/useLegend.ts +13 -10
- package/src/Graph/LineChart/LineChart.tsx +8 -73
- package/src/Graph/LineChart/graphAtoms.ts +3 -0
- package/src/Graph/LineChart/index.stories.tsx +6 -101
- package/src/Graph/LineChart/index.tsx +3 -13
- package/src/Graph/SingleBar/ResponsiveSingleBar.tsx +8 -10
- package/src/Graph/SingleBar/SingleBar.stories.tsx +6 -119
- package/src/Graph/SingleBar/Thresholds.tsx +82 -28
- package/src/Graph/SingleBar/models.ts +4 -2
- package/src/Graph/Text/Text.tsx +16 -20
- package/src/Graph/common/models.ts +0 -12
- package/src/Graph/common/timeSeries/index.ts +8 -41
- package/src/Graph/common/timeSeries/models.ts +1 -3
- package/src/Graph/common/utils.ts +6 -59
- package/src/Listing/ActionBar/index.tsx +14 -7
- package/src/Listing/Cell/DataCell.tsx +7 -7
- package/src/Listing/Cell/index.tsx +5 -5
- package/src/Listing/Header/Cell/ListingHeaderCell.styles.ts +3 -3
- package/src/Listing/Header/Cell/ListingHeaderCell.tsx +2 -2
- package/src/Listing/Header/ListingHeader.tsx +4 -4
- package/src/Listing/Listing.styles.ts +1 -1
- package/src/Listing/Row/Row.tsx +3 -3
- package/src/Listing/index.stories.tsx +5 -5
- package/src/Listing/index.tsx +15 -12
- package/src/Listing/tableAtoms.ts +14 -11
- package/src/Listing/useStyleTable.ts +8 -8
- package/src/SortableItems/SortableItem.tsx +2 -1
- package/src/api/useGraphQuery/index.ts +21 -52
- package/src/components/Modal/Modal.styles.ts +2 -1
- package/src/utils/index.ts +0 -1
- package/src/Graph/LineChart/BasicComponents/ThresholdLine.tsx +0 -64
- package/src/Graph/LineChart/BasicComponents/Thresholds.tsx +0 -77
- package/src/Graph/SingleBar/ThresholdLine.tsx +0 -74
- package/src/utils/useRefreshInterval.ts +0 -21
- package/src/utils/useThresholds.ts +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@centreon/ui",
|
|
3
|
-
"version": "23.10.1-MON-
|
|
3
|
+
"version": "23.10.1-MON-20799-fe-implement-new-visualization.13",
|
|
4
4
|
"description": "Centreon UI Components",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"eslint": "eslint ./src --ext .js,.jsx,.ts,.tsx --max-warnings 0",
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import { PieArcDatum, ProvidedProps } from '@visx/shape/lib/shapes/Pie';
|
|
2
|
-
import { useTransition,
|
|
3
|
-
import { equals
|
|
4
|
-
|
|
5
|
-
import { Typography } from '@mui/material';
|
|
2
|
+
import { useTransition, interpolate, animated } from '@react-spring/web';
|
|
3
|
+
import { equals } from 'ramda';
|
|
6
4
|
|
|
7
5
|
import { Metric } from '../common/timeSeries/models';
|
|
8
|
-
|
|
6
|
+
|
|
7
|
+
import { ThresholdType } from './models';
|
|
9
8
|
|
|
10
9
|
type AnimatedStyles = { endAngle: number; opacity: number; startAngle: number };
|
|
11
10
|
|
|
12
|
-
const fromLeaveTransition = (
|
|
13
|
-
endAngle,
|
|
11
|
+
const fromLeaveTransition = (): AnimatedStyles => ({
|
|
12
|
+
endAngle: 0,
|
|
14
13
|
opacity: 0,
|
|
15
|
-
startAngle:
|
|
14
|
+
startAngle: 0
|
|
16
15
|
});
|
|
17
16
|
const enterUpdateTransition = <T,>({
|
|
18
17
|
startAngle,
|
|
@@ -31,7 +30,7 @@ type AnimatedPieProps<Datum> = ProvidedProps<Datum> & {
|
|
|
31
30
|
hideTooltip?: () => void;
|
|
32
31
|
metric?: Metric;
|
|
33
32
|
showTooltip?: (args) => void;
|
|
34
|
-
|
|
33
|
+
thresholdTooltipLabels?: Array<string>;
|
|
35
34
|
};
|
|
36
35
|
|
|
37
36
|
const AnimatedPie = <Datum,>({
|
|
@@ -42,7 +41,7 @@ const AnimatedPie = <Datum,>({
|
|
|
42
41
|
getColor,
|
|
43
42
|
showTooltip,
|
|
44
43
|
hideTooltip,
|
|
45
|
-
|
|
44
|
+
thresholdTooltipLabels = []
|
|
46
45
|
}: AnimatedPieProps<Datum>): JSX.Element => {
|
|
47
46
|
const transitions = useTransition<PieArcDatum<Datum>, AnimatedStyles>(arcs, {
|
|
48
47
|
enter: enterUpdateTransition,
|
|
@@ -55,36 +54,26 @@ const AnimatedPie = <Datum,>({
|
|
|
55
54
|
return transitions((props, arc, { key }) => (
|
|
56
55
|
<g key={key}>
|
|
57
56
|
<animated.path
|
|
58
|
-
d={
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
57
|
+
d={interpolate(
|
|
58
|
+
[props.startAngle, props.endAngle],
|
|
59
|
+
(startAngle, endAngle) =>
|
|
60
|
+
path({
|
|
61
|
+
...arc,
|
|
62
|
+
endAngle,
|
|
63
|
+
startAngle
|
|
64
|
+
})
|
|
64
65
|
)}
|
|
65
66
|
data-testid={`${arc.data?.value || arc.data}-arc`}
|
|
66
|
-
display={
|
|
67
|
-
includes('transparent', arc.data?.name || '') ? 'none' : 'inline'
|
|
68
|
-
}
|
|
69
67
|
fill={getColor(arc)}
|
|
70
68
|
onMouseEnter={(event) => {
|
|
71
|
-
const thresholdType = arc.data
|
|
69
|
+
const thresholdType = arc.data.name;
|
|
72
70
|
|
|
73
|
-
if (equals(thresholdType,
|
|
71
|
+
if (equals(thresholdType, ThresholdType.Success)) {
|
|
74
72
|
return;
|
|
75
73
|
}
|
|
76
74
|
|
|
77
75
|
showTooltip?.({
|
|
78
|
-
tooltipData:
|
|
79
|
-
<div>
|
|
80
|
-
{pluck(
|
|
81
|
-
'label',
|
|
82
|
-
thresholds[thresholdType as 'warning' | 'critical']
|
|
83
|
-
).map((label) => (
|
|
84
|
-
<Typography key={label}>{label}</Typography>
|
|
85
|
-
))}
|
|
86
|
-
</div>
|
|
87
|
-
),
|
|
76
|
+
tooltipData: thresholdTooltipLabels[thresholdType],
|
|
88
77
|
tooltipLeft: event.clientX,
|
|
89
78
|
tooltipTop: event.clientY
|
|
90
79
|
});
|
|
@@ -20,21 +20,8 @@ const Template = (props): JSX.Element => (
|
|
|
20
20
|
export const success: Story = {
|
|
21
21
|
args: {
|
|
22
22
|
data: dataLastWeek,
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
}
|
|
23
|
+
thresholdTooltipLabels: ['Warning', 'Critical'],
|
|
24
|
+
thresholds: [0.5, 0.6]
|
|
38
25
|
},
|
|
39
26
|
render: Template
|
|
40
27
|
};
|
|
@@ -42,21 +29,8 @@ export const success: Story = {
|
|
|
42
29
|
export const warning: Story = {
|
|
43
30
|
args: {
|
|
44
31
|
data: dataLastWeek,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
{
|
|
48
|
-
label: 'Critical',
|
|
49
|
-
value: 0.6
|
|
50
|
-
}
|
|
51
|
-
],
|
|
52
|
-
enabled: true,
|
|
53
|
-
warning: [
|
|
54
|
-
{
|
|
55
|
-
label: 'Warning',
|
|
56
|
-
value: 0.2
|
|
57
|
-
}
|
|
58
|
-
]
|
|
59
|
-
}
|
|
32
|
+
thresholdTooltipLabels: ['Warning', 'Critical'],
|
|
33
|
+
thresholds: [0.2, 0.5]
|
|
60
34
|
},
|
|
61
35
|
render: Template
|
|
62
36
|
};
|
|
@@ -64,73 +38,8 @@ export const warning: Story = {
|
|
|
64
38
|
export const critical: Story = {
|
|
65
39
|
args: {
|
|
66
40
|
data: dataLastWeek,
|
|
67
|
-
|
|
68
|
-
|
|
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 withCriticalLowerThanWarning: Story = {
|
|
87
|
-
args: {
|
|
88
|
-
data: dataLastWeek,
|
|
89
|
-
thresholds: {
|
|
90
|
-
critical: [
|
|
91
|
-
{
|
|
92
|
-
label: 'Critical',
|
|
93
|
-
value: 0.13
|
|
94
|
-
}
|
|
95
|
-
],
|
|
96
|
-
enabled: true,
|
|
97
|
-
warning: [
|
|
98
|
-
{
|
|
99
|
-
label: 'Warning',
|
|
100
|
-
value: 0.5
|
|
101
|
-
}
|
|
102
|
-
]
|
|
103
|
-
}
|
|
104
|
-
},
|
|
105
|
-
render: Template
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
export const withRangeThresholds: Story = {
|
|
109
|
-
args: {
|
|
110
|
-
data: dataLastWeek,
|
|
111
|
-
thresholds: {
|
|
112
|
-
critical: [
|
|
113
|
-
{
|
|
114
|
-
label: 'Critical',
|
|
115
|
-
value: 0.55
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
label: 'Critical',
|
|
119
|
-
value: 0.65
|
|
120
|
-
}
|
|
121
|
-
],
|
|
122
|
-
enabled: true,
|
|
123
|
-
warning: [
|
|
124
|
-
{
|
|
125
|
-
label: 'Warning',
|
|
126
|
-
value: 0.13
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
label: 'Warning',
|
|
130
|
-
value: 0.5
|
|
131
|
-
}
|
|
132
|
-
]
|
|
133
|
-
}
|
|
41
|
+
thresholdTooltipLabels: ['Warning', 'Critical'],
|
|
42
|
+
thresholds: [0.13, 0.35]
|
|
134
43
|
},
|
|
135
44
|
render: Template
|
|
136
45
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Responsive } from '@visx/visx';
|
|
2
|
+
import { sort, subtract } from 'ramda';
|
|
2
3
|
|
|
3
|
-
import { LineChartData
|
|
4
|
+
import { LineChartData } from '../common/models';
|
|
4
5
|
import { getMetricWithLatestData } from '../common/timeSeries';
|
|
5
6
|
import { Metric } from '../common/timeSeries/models';
|
|
6
7
|
|
|
@@ -8,13 +9,21 @@ import ResponsiveGauge from './ResponsiveGauge';
|
|
|
8
9
|
|
|
9
10
|
interface Props {
|
|
10
11
|
data?: LineChartData;
|
|
11
|
-
|
|
12
|
+
disabledThresholds?: boolean;
|
|
13
|
+
thresholdTooltipLabels: Array<string>;
|
|
14
|
+
thresholds: Array<number>;
|
|
12
15
|
}
|
|
13
16
|
|
|
14
|
-
export const Gauge = ({
|
|
17
|
+
export const Gauge = ({
|
|
18
|
+
thresholds,
|
|
19
|
+
data,
|
|
20
|
+
thresholdTooltipLabels,
|
|
21
|
+
disabledThresholds
|
|
22
|
+
}: Props): JSX.Element | null => {
|
|
15
23
|
if (!data) {
|
|
16
24
|
return null;
|
|
17
25
|
}
|
|
26
|
+
const sortedThresholds = sort(subtract, thresholds);
|
|
18
27
|
|
|
19
28
|
const metric = getMetricWithLatestData(data) as Metric;
|
|
20
29
|
|
|
@@ -22,9 +31,11 @@ export const Gauge = ({ thresholds, data }: Props): JSX.Element | null => {
|
|
|
22
31
|
<Responsive.ParentSize>
|
|
23
32
|
{({ width, height }) => (
|
|
24
33
|
<ResponsiveGauge
|
|
34
|
+
disabledThresholds={disabledThresholds}
|
|
25
35
|
height={height}
|
|
26
36
|
metric={metric}
|
|
27
|
-
|
|
37
|
+
thresholdTooltipLabels={thresholdTooltipLabels}
|
|
38
|
+
thresholds={sortedThresholds}
|
|
28
39
|
width={width}
|
|
29
40
|
/>
|
|
30
41
|
)}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { scaleOrdinal } from '@visx/scale';
|
|
2
2
|
import { Pie } from '@visx/shape';
|
|
3
|
-
import { identity } from 'ramda';
|
|
3
|
+
import { T, always, cond, gt, head, identity } from 'ramda';
|
|
4
4
|
|
|
5
|
-
import { useTheme } from '@mui/material';
|
|
6
|
-
|
|
7
|
-
import { getColorFromDataAndTresholds } from '../common/utils';
|
|
5
|
+
import { Theme, useTheme } from '@mui/material';
|
|
8
6
|
|
|
9
7
|
import { thresholdThickness } from './Thresholds';
|
|
10
8
|
import AnimatedPie from './AnimatedPie';
|
|
@@ -12,11 +10,29 @@ import { GaugeProps } from './models';
|
|
|
12
10
|
|
|
13
11
|
const dataThickness = 45;
|
|
14
12
|
|
|
13
|
+
interface GetColorFromDataProps {
|
|
14
|
+
data: number;
|
|
15
|
+
theme: Theme;
|
|
16
|
+
thresholds: Array<number>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const getColorFromData = ({
|
|
20
|
+
data,
|
|
21
|
+
thresholds,
|
|
22
|
+
theme
|
|
23
|
+
}: GetColorFromDataProps): string =>
|
|
24
|
+
cond([
|
|
25
|
+
[gt(head(thresholds) as number), always(theme.palette.success.main)],
|
|
26
|
+
[gt(thresholds[1]), always(theme.palette.warning.main)],
|
|
27
|
+
[T, always(theme.palette.error.main)]
|
|
28
|
+
])(data);
|
|
29
|
+
|
|
15
30
|
const PieData = ({
|
|
16
31
|
metric,
|
|
17
32
|
adaptedMaxValue,
|
|
18
33
|
thresholds,
|
|
19
|
-
radius
|
|
34
|
+
radius,
|
|
35
|
+
disabledThresholds
|
|
20
36
|
}: Omit<
|
|
21
37
|
GaugeProps,
|
|
22
38
|
'width' | 'height' | 'showTooltip' | 'hideTooltip' | 'thresholdTooltipLabels'
|
|
@@ -24,9 +40,9 @@ const PieData = ({
|
|
|
24
40
|
const theme = useTheme();
|
|
25
41
|
|
|
26
42
|
const pieData = [metric.data[0], adaptedMaxValue - metric.data[0]];
|
|
27
|
-
const pieColor =
|
|
43
|
+
const pieColor = disabledThresholds
|
|
28
44
|
? theme.palette.success.main
|
|
29
|
-
:
|
|
45
|
+
: getColorFromData({
|
|
30
46
|
data: metric.data[0],
|
|
31
47
|
theme,
|
|
32
48
|
thresholds
|
|
@@ -53,7 +69,7 @@ const PieData = ({
|
|
|
53
69
|
animate
|
|
54
70
|
getColor={(arc) => getDataColor(arc.data)}
|
|
55
71
|
getKey={(arc) => `${arc.data}`}
|
|
56
|
-
|
|
72
|
+
thresholdTooltipLabels={[]}
|
|
57
73
|
/>
|
|
58
74
|
)}
|
|
59
75
|
</Pie>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useRef } from 'react';
|
|
2
2
|
|
|
3
3
|
import { Group } from '@visx/group';
|
|
4
|
-
import {
|
|
4
|
+
import { head } from 'ramda';
|
|
5
5
|
import { Tooltip } from '@visx/visx';
|
|
6
6
|
|
|
7
7
|
import { Box, Fade, useTheme } from '@mui/material';
|
|
@@ -13,11 +13,13 @@ import { margins } from '../common/margins';
|
|
|
13
13
|
|
|
14
14
|
import Thresholds from './Thresholds';
|
|
15
15
|
import PieData from './PieData';
|
|
16
|
-
import { GaugeProps } from './models';
|
|
17
16
|
|
|
18
|
-
interface Props
|
|
17
|
+
interface Props {
|
|
18
|
+
disabledThresholds?: boolean;
|
|
19
19
|
height: number;
|
|
20
20
|
metric: Metric;
|
|
21
|
+
thresholdTooltipLabels: Array<string>;
|
|
22
|
+
thresholds: Array<number>;
|
|
21
23
|
width: number;
|
|
22
24
|
}
|
|
23
25
|
|
|
@@ -30,7 +32,9 @@ const ResponsiveGauge = ({
|
|
|
30
32
|
width,
|
|
31
33
|
height,
|
|
32
34
|
thresholds,
|
|
33
|
-
metric
|
|
35
|
+
metric,
|
|
36
|
+
thresholdTooltipLabels,
|
|
37
|
+
disabledThresholds
|
|
34
38
|
}: Props): JSX.Element => {
|
|
35
39
|
const svgRef = useRef<SVGSVGElement>(null);
|
|
36
40
|
|
|
@@ -50,17 +54,13 @@ const ResponsiveGauge = ({
|
|
|
50
54
|
const centerY = innerHeight / 2;
|
|
51
55
|
const centerX = innerWidth / 2;
|
|
52
56
|
const radius = Math.min(innerWidth, innerHeight) / 2;
|
|
53
|
-
const thresholdValues = flatten([
|
|
54
|
-
pluck('value', thresholds.warning),
|
|
55
|
-
pluck('value', thresholds.critical)
|
|
56
|
-
]);
|
|
57
57
|
const adaptedMaxValue = Math.max(
|
|
58
58
|
metric.maximum_value || 0,
|
|
59
|
-
Math.max(...
|
|
59
|
+
Math.max(...thresholds) * 1.1,
|
|
60
60
|
head(metric.data) as number
|
|
61
61
|
);
|
|
62
62
|
|
|
63
|
-
const pieColor =
|
|
63
|
+
const pieColor = disabledThresholds
|
|
64
64
|
? theme.palette.success.main
|
|
65
65
|
: getColorFromDataAndTresholds({
|
|
66
66
|
data: metric.data[0],
|
|
@@ -79,14 +79,17 @@ const ResponsiveGauge = ({
|
|
|
79
79
|
<Group left={centerX + margins.left} top={centerY + height / 6}>
|
|
80
80
|
<Thresholds
|
|
81
81
|
adaptedMaxValue={adaptedMaxValue}
|
|
82
|
+
disabledThresholds={disabledThresholds}
|
|
82
83
|
hideTooltip={hideTooltip}
|
|
83
84
|
metric={metric}
|
|
84
85
|
radius={radius}
|
|
85
86
|
showTooltip={showTooltip}
|
|
87
|
+
thresholdTooltipLabels={thresholdTooltipLabels}
|
|
86
88
|
thresholds={thresholds}
|
|
87
89
|
/>
|
|
88
90
|
<PieData
|
|
89
91
|
adaptedMaxValue={adaptedMaxValue}
|
|
92
|
+
disabledThresholds={disabledThresholds}
|
|
90
93
|
metric={metric}
|
|
91
94
|
radius={radius}
|
|
92
95
|
thresholds={thresholds}
|
|
@@ -111,7 +114,7 @@ const ResponsiveGauge = ({
|
|
|
111
114
|
{metric.unit}
|
|
112
115
|
</text>
|
|
113
116
|
</svg>
|
|
114
|
-
<Fade in={tooltipOpen &&
|
|
117
|
+
<Fade in={tooltipOpen && !disabledThresholds}>
|
|
115
118
|
<Tooltip.Tooltip
|
|
116
119
|
left={(tooltipLeft || 0) - svgLeft}
|
|
117
120
|
style={{
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { scaleOrdinal } from '@visx/scale';
|
|
2
2
|
import { Pie } from '@visx/shape';
|
|
3
|
-
import {
|
|
3
|
+
import { pluck } from 'ramda';
|
|
4
4
|
|
|
5
5
|
import { useTheme } from '@mui/material';
|
|
6
6
|
|
|
7
7
|
import AnimatedPie from './AnimatedPie';
|
|
8
|
-
import { GaugeProps } from './models';
|
|
8
|
+
import { GaugeProps, ThresholdType } from './models';
|
|
9
9
|
|
|
10
10
|
export const thresholdThickness = 12;
|
|
11
11
|
|
|
@@ -15,125 +15,72 @@ const Thresholds = ({
|
|
|
15
15
|
adaptedMaxValue,
|
|
16
16
|
showTooltip,
|
|
17
17
|
hideTooltip,
|
|
18
|
-
metric
|
|
18
|
+
metric,
|
|
19
|
+
thresholdTooltipLabels,
|
|
20
|
+
disabledThresholds
|
|
19
21
|
}: Omit<GaugeProps, 'width' | 'height'>): JSX.Element => {
|
|
20
22
|
const theme = useTheme();
|
|
21
23
|
|
|
22
|
-
const
|
|
23
|
-
const warningThresholdValues = pluck('value', thresholds.warning);
|
|
24
|
-
|
|
25
|
-
const isCriticalLowerThanWarning =
|
|
26
|
-
criticalThresholdValues[0] < warningThresholdValues[0];
|
|
27
|
-
|
|
28
|
-
const criticalThreshold = isCriticalLowerThanWarning
|
|
29
|
-
? [0, ...criticalThresholdValues, adaptedMaxValue]
|
|
30
|
-
: [...criticalThresholdValues, adaptedMaxValue];
|
|
31
|
-
const criticalThresholdArc = criticalThreshold.map((value, index) => {
|
|
32
|
-
return {
|
|
33
|
-
name: equals(1, index) ? 'critical' : `transparent-${index}-critical`,
|
|
34
|
-
value: value - (criticalThreshold[index - 1] || 0)
|
|
35
|
-
};
|
|
36
|
-
});
|
|
37
|
-
const criticalThresholdScaleOrdinal = scaleOrdinal({
|
|
38
|
-
domain: pluck('name', criticalThresholdArc),
|
|
39
|
-
range: ['transparent', theme.palette.error.main, 'transparent']
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
const warningThreshold = isCriticalLowerThanWarning
|
|
43
|
-
? [0, ...warningThresholdValues, adaptedMaxValue]
|
|
44
|
-
: [...warningThresholdValues, adaptedMaxValue];
|
|
45
|
-
const warningThresholdArc = warningThreshold.map((value, index) => {
|
|
46
|
-
return {
|
|
47
|
-
name: equals(1, index) ? 'warning' : `transparent-${index}-warning`,
|
|
48
|
-
value: value - (warningThreshold[index - 1] || 0)
|
|
49
|
-
};
|
|
50
|
-
});
|
|
51
|
-
const warningThresholdScaleOrdinal = scaleOrdinal({
|
|
52
|
-
domain: pluck('name', warningThresholdArc),
|
|
53
|
-
range: ['transparent', theme.palette.warning.main, 'transparent']
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
const successThresholdArc = [adaptedMaxValue].map((value) => {
|
|
57
|
-
return {
|
|
58
|
-
name: 'success',
|
|
59
|
-
value
|
|
60
|
-
};
|
|
61
|
-
});
|
|
62
|
-
const successThresholdScaleOrdinal = scaleOrdinal({
|
|
63
|
-
domain: pluck('name', successThresholdArc),
|
|
64
|
-
range: [theme.palette.success.main]
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
if (!thresholds.enabled) {
|
|
68
|
-
return (
|
|
69
|
-
<Pie
|
|
70
|
-
data={successThresholdArc}
|
|
71
|
-
endAngle={-Math.PI / 2}
|
|
72
|
-
innerRadius={radius - thresholdThickness}
|
|
73
|
-
outerRadius={radius}
|
|
74
|
-
pieSortValues={() => -1}
|
|
75
|
-
pieValue={(d) => d.value}
|
|
76
|
-
startAngle={Math.PI / 2}
|
|
77
|
-
>
|
|
78
|
-
{(pie) => (
|
|
79
|
-
<AnimatedPie<{ name: string; value: number }>
|
|
80
|
-
{...pie}
|
|
81
|
-
animate
|
|
82
|
-
getColor={(arc) => successThresholdScaleOrdinal(arc.data.name)}
|
|
83
|
-
getKey={(arc) => `${arc.data.name}_${arc.data.value}`}
|
|
84
|
-
hideTooltip={hideTooltip}
|
|
85
|
-
metric={metric}
|
|
86
|
-
showTooltip={showTooltip}
|
|
87
|
-
thresholds={thresholds}
|
|
88
|
-
/>
|
|
89
|
-
)}
|
|
90
|
-
</Pie>
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const arcs = [
|
|
24
|
+
const namedThresholds = [
|
|
95
25
|
{
|
|
96
|
-
|
|
97
|
-
|
|
26
|
+
name: ThresholdType.Success,
|
|
27
|
+
value: thresholds[0]
|
|
98
28
|
},
|
|
99
29
|
{
|
|
100
|
-
|
|
101
|
-
|
|
30
|
+
name: ThresholdType.Warning,
|
|
31
|
+
value: thresholds[1]
|
|
102
32
|
},
|
|
103
33
|
{
|
|
104
|
-
|
|
105
|
-
|
|
34
|
+
name: ThresholdType.Error,
|
|
35
|
+
value: adaptedMaxValue
|
|
106
36
|
}
|
|
107
37
|
];
|
|
108
38
|
|
|
39
|
+
const adaptedThresholds = namedThresholds.map(({ name, value }, index) => {
|
|
40
|
+
return {
|
|
41
|
+
name,
|
|
42
|
+
value: value - (namedThresholds[index - 1]?.value || 0)
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const getThresholdColor = scaleOrdinal({
|
|
47
|
+
domain: pluck('name', adaptedThresholds),
|
|
48
|
+
range: disabledThresholds
|
|
49
|
+
? [
|
|
50
|
+
theme.palette.success.main,
|
|
51
|
+
theme.palette.success.main,
|
|
52
|
+
theme.palette.success.main
|
|
53
|
+
]
|
|
54
|
+
: [
|
|
55
|
+
theme.palette.success.main,
|
|
56
|
+
theme.palette.warning.main,
|
|
57
|
+
theme.palette.error.main
|
|
58
|
+
]
|
|
59
|
+
});
|
|
60
|
+
|
|
109
61
|
return (
|
|
110
|
-
|
|
111
|
-
{
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
/>
|
|
133
|
-
)}
|
|
134
|
-
</Pie>
|
|
135
|
-
))}
|
|
136
|
-
</>
|
|
62
|
+
<Pie
|
|
63
|
+
data={adaptedThresholds}
|
|
64
|
+
endAngle={-Math.PI / 2}
|
|
65
|
+
innerRadius={radius - thresholdThickness}
|
|
66
|
+
outerRadius={radius}
|
|
67
|
+
pieSortValues={() => -1}
|
|
68
|
+
pieValue={(d) => d.value}
|
|
69
|
+
startAngle={Math.PI / 2}
|
|
70
|
+
>
|
|
71
|
+
{(pie) => (
|
|
72
|
+
<AnimatedPie<{ name: ThresholdType; value: number }>
|
|
73
|
+
{...pie}
|
|
74
|
+
animate
|
|
75
|
+
getColor={(arc) => getThresholdColor(arc.data.name)}
|
|
76
|
+
getKey={(arc) => `${arc.data.name}_${arc.data.value}`}
|
|
77
|
+
hideTooltip={hideTooltip}
|
|
78
|
+
metric={metric}
|
|
79
|
+
showTooltip={showTooltip}
|
|
80
|
+
thresholdTooltipLabels={thresholdTooltipLabels}
|
|
81
|
+
/>
|
|
82
|
+
)}
|
|
83
|
+
</Pie>
|
|
137
84
|
);
|
|
138
85
|
};
|
|
139
86
|
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { Thresholds } from '../common/models';
|
|
2
1
|
import { Metric } from '../common/timeSeries/models';
|
|
3
2
|
|
|
4
3
|
export interface GaugeProps {
|
|
5
4
|
adaptedMaxValue: number;
|
|
5
|
+
disabledThresholds?: boolean;
|
|
6
6
|
height: number;
|
|
7
7
|
hideTooltip: () => void;
|
|
8
8
|
metric: Metric;
|
|
9
9
|
radius: number;
|
|
10
10
|
showTooltip: (args) => void;
|
|
11
|
-
|
|
11
|
+
thresholdTooltipLabels: Array<string>;
|
|
12
|
+
thresholds: Array<number>;
|
|
12
13
|
width: number;
|
|
13
14
|
}
|
|
14
15
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
2
|
|
|
3
|
+
import { useAtom } from 'jotai';
|
|
3
4
|
import { compose, equals, prop, propEq, reject, sortBy, toLower } from 'ramda';
|
|
4
5
|
|
|
6
|
+
import { linesGraphAtom } from '../graphAtoms';
|
|
5
7
|
import { Line } from '../../common/timeSeries/models';
|
|
6
8
|
|
|
7
9
|
import {
|
|
@@ -13,8 +15,6 @@ import {
|
|
|
13
15
|
interface UseFilterLines {
|
|
14
16
|
displayThreshold?: boolean;
|
|
15
17
|
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
|
|
28
|
-
linesGraph,
|
|
29
|
-
setLinesGraph
|
|
27
|
+
lines
|
|
30
28
|
}: 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,9 +45,7 @@ const useFilterLines = ({
|
|
|
45
45
|
|
|
46
46
|
useEffect(() => {
|
|
47
47
|
const filteredLines = filterLines();
|
|
48
|
-
if (!lines || !displayThreshold) {
|
|
49
|
-
setLinesGraph(lines);
|
|
50
|
-
|
|
48
|
+
if (!lines || !displayThreshold || filteredLines.length <= 0) {
|
|
51
49
|
return;
|
|
52
50
|
}
|
|
53
51
|
|
|
@@ -8,12 +8,14 @@ interface Props {
|
|
|
8
8
|
|
|
9
9
|
const Point = ({ lineColor, x, y }: Props): JSX.Element => (
|
|
10
10
|
<circle
|
|
11
|
-
cx={x}
|
|
12
|
-
cy={y}
|
|
13
11
|
fill={alpha(lineColor, 0.5)}
|
|
14
12
|
r={4}
|
|
15
13
|
stroke={lineColor}
|
|
16
14
|
strokeWidth={2}
|
|
15
|
+
style={{
|
|
16
|
+
transform: `translate(${x}px, ${y}px)`,
|
|
17
|
+
transition: 'transform 0.08s ease-out'
|
|
18
|
+
}}
|
|
17
19
|
/>
|
|
18
20
|
);
|
|
19
21
|
|