@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.
- package/package.json +1 -1
- package/src/Graph/Gauge/AnimatedPie.tsx +31 -20
- package/src/Graph/Gauge/Gauge.stories.tsx +97 -6
- package/src/Graph/Gauge/Gauge.tsx +4 -15
- package/src/Graph/Gauge/PieData.tsx +8 -24
- package/src/Graph/Gauge/ResponsiveGauge.tsx +11 -14
- package/src/Graph/Gauge/Thresholds.tsx +109 -56
- package/src/Graph/Gauge/models.ts +2 -3
- package/src/Graph/LineChart/BasicComponents/ThresholdLine.tsx +64 -0
- package/src/Graph/LineChart/BasicComponents/Thresholds.tsx +77 -0
- package/src/Graph/LineChart/BasicComponents/useFilterLines.ts +9 -7
- package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/index.tsx +2 -4
- package/src/Graph/LineChart/InteractiveComponents/interactionWithGraphAtoms.ts +1 -0
- package/src/Graph/LineChart/Legend/index.tsx +9 -4
- package/src/Graph/LineChart/Legend/useInteractiveValues.ts +13 -4
- package/src/Graph/LineChart/Legend/useLegend.ts +10 -13
- package/src/Graph/LineChart/LineChart.tsx +73 -8
- package/src/Graph/LineChart/graphAtoms.ts +0 -3
- package/src/Graph/LineChart/index.stories.tsx +101 -6
- package/src/Graph/LineChart/index.tsx +13 -3
- package/src/Graph/SingleBar/ResponsiveSingleBar.tsx +10 -8
- package/src/Graph/SingleBar/SingleBar.stories.tsx +119 -6
- package/src/Graph/SingleBar/ThresholdLine.tsx +74 -0
- package/src/Graph/SingleBar/Thresholds.tsx +28 -82
- package/src/Graph/SingleBar/models.ts +2 -4
- package/src/Graph/Text/Text.tsx +20 -16
- package/src/Graph/common/models.ts +12 -0
- package/src/Graph/common/timeSeries/index.ts +41 -8
- package/src/Graph/common/timeSeries/models.ts +3 -1
- package/src/Graph/common/utils.ts +59 -6
- package/src/api/useGraphQuery/index.ts +52 -21
- package/src/components/Modal/Modal.styles.ts +1 -2
- package/src/utils/index.ts +1 -0
- package/src/utils/useRefreshInterval.ts +21 -0
- package/src/utils/useThresholds.ts +0 -0
package/package.json
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { PieArcDatum, ProvidedProps } from '@visx/shape/lib/shapes/Pie';
|
|
2
|
-
import { useTransition,
|
|
3
|
-
import { equals } from 'ramda';
|
|
2
|
+
import { useTransition, to, animated } from '@react-spring/web';
|
|
3
|
+
import { equals, includes, pluck } from 'ramda';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Typography } from '@mui/material';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { Metric } from '../common/timeSeries/models';
|
|
8
|
+
import { Thresholds } from '../common/models';
|
|
8
9
|
|
|
9
10
|
type AnimatedStyles = { endAngle: number; opacity: number; startAngle: number };
|
|
10
11
|
|
|
11
|
-
const fromLeaveTransition = (): AnimatedStyles => ({
|
|
12
|
-
endAngle
|
|
12
|
+
const fromLeaveTransition = ({ endAngle }): AnimatedStyles => ({
|
|
13
|
+
endAngle,
|
|
13
14
|
opacity: 0,
|
|
14
|
-
startAngle:
|
|
15
|
+
startAngle: -(Math.PI / 2)
|
|
15
16
|
});
|
|
16
17
|
const enterUpdateTransition = <T,>({
|
|
17
18
|
startAngle,
|
|
@@ -30,7 +31,7 @@ type AnimatedPieProps<Datum> = ProvidedProps<Datum> & {
|
|
|
30
31
|
hideTooltip?: () => void;
|
|
31
32
|
metric?: Metric;
|
|
32
33
|
showTooltip?: (args) => void;
|
|
33
|
-
|
|
34
|
+
thresholds: Thresholds;
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
const AnimatedPie = <Datum,>({
|
|
@@ -41,7 +42,7 @@ const AnimatedPie = <Datum,>({
|
|
|
41
42
|
getColor,
|
|
42
43
|
showTooltip,
|
|
43
44
|
hideTooltip,
|
|
44
|
-
|
|
45
|
+
thresholds
|
|
45
46
|
}: AnimatedPieProps<Datum>): JSX.Element => {
|
|
46
47
|
const transitions = useTransition<PieArcDatum<Datum>, AnimatedStyles>(arcs, {
|
|
47
48
|
enter: enterUpdateTransition,
|
|
@@ -54,26 +55,36 @@ const AnimatedPie = <Datum,>({
|
|
|
54
55
|
return transitions((props, arc, { key }) => (
|
|
55
56
|
<g key={key}>
|
|
56
57
|
<animated.path
|
|
57
|
-
d={
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
startAngle
|
|
64
|
-
})
|
|
58
|
+
d={to([props.startAngle, props.endAngle], (startAngle, endAngle) =>
|
|
59
|
+
path({
|
|
60
|
+
...arc,
|
|
61
|
+
endAngle,
|
|
62
|
+
startAngle
|
|
63
|
+
})
|
|
65
64
|
)}
|
|
66
65
|
data-testid={`${arc.data?.value || arc.data}-arc`}
|
|
66
|
+
display={
|
|
67
|
+
includes('transparent', arc.data?.name || '') ? 'none' : 'inline'
|
|
68
|
+
}
|
|
67
69
|
fill={getColor(arc)}
|
|
68
70
|
onMouseEnter={(event) => {
|
|
69
|
-
const thresholdType = arc.data
|
|
71
|
+
const thresholdType = arc.data?.name as string;
|
|
70
72
|
|
|
71
|
-
if (equals(thresholdType,
|
|
73
|
+
if (equals(thresholdType, 'success')) {
|
|
72
74
|
return;
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
showTooltip?.({
|
|
76
|
-
tooltipData:
|
|
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
|
+
),
|
|
77
88
|
tooltipLeft: event.clientX,
|
|
78
89
|
tooltipTop: event.clientY
|
|
79
90
|
});
|
|
@@ -20,8 +20,21 @@ const Template = (props): JSX.Element => (
|
|
|
20
20
|
export const success: Story = {
|
|
21
21
|
args: {
|
|
22
22
|
data: dataLastWeek,
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
33
|
-
|
|
45
|
+
thresholds: {
|
|
46
|
+
critical: [
|
|
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
|
+
}
|
|
34
60
|
},
|
|
35
61
|
render: Template
|
|
36
62
|
};
|
|
@@ -38,8 +64,73 @@ export const warning: Story = {
|
|
|
38
64
|
export const critical: Story = {
|
|
39
65
|
args: {
|
|
40
66
|
data: dataLastWeek,
|
|
41
|
-
|
|
42
|
-
|
|
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 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
|
+
}
|
|
43
134
|
},
|
|
44
135
|
render: Template
|
|
45
136
|
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Responsive } from '@visx/visx';
|
|
2
|
-
import { sort, subtract } from 'ramda';
|
|
3
2
|
|
|
4
|
-
import { LineChartData } from '../common/models';
|
|
3
|
+
import { LineChartData, Thresholds } from '../common/models';
|
|
5
4
|
import { getMetricWithLatestData } from '../common/timeSeries';
|
|
6
5
|
import { Metric } from '../common/timeSeries/models';
|
|
7
6
|
|
|
@@ -9,21 +8,13 @@ import ResponsiveGauge from './ResponsiveGauge';
|
|
|
9
8
|
|
|
10
9
|
interface Props {
|
|
11
10
|
data?: LineChartData;
|
|
12
|
-
|
|
13
|
-
thresholdTooltipLabels: Array<string>;
|
|
14
|
-
thresholds: Array<number>;
|
|
11
|
+
thresholds: Thresholds;
|
|
15
12
|
}
|
|
16
13
|
|
|
17
|
-
export const Gauge = ({
|
|
18
|
-
thresholds,
|
|
19
|
-
data,
|
|
20
|
-
thresholdTooltipLabels,
|
|
21
|
-
disabledThresholds
|
|
22
|
-
}: Props): JSX.Element | null => {
|
|
14
|
+
export const Gauge = ({ thresholds, data }: Props): JSX.Element | null => {
|
|
23
15
|
if (!data) {
|
|
24
16
|
return null;
|
|
25
17
|
}
|
|
26
|
-
const sortedThresholds = sort(subtract, thresholds);
|
|
27
18
|
|
|
28
19
|
const metric = getMetricWithLatestData(data) as Metric;
|
|
29
20
|
|
|
@@ -31,11 +22,9 @@ export const Gauge = ({
|
|
|
31
22
|
<Responsive.ParentSize>
|
|
32
23
|
{({ width, height }) => (
|
|
33
24
|
<ResponsiveGauge
|
|
34
|
-
disabledThresholds={disabledThresholds}
|
|
35
25
|
height={height}
|
|
36
26
|
metric={metric}
|
|
37
|
-
|
|
38
|
-
thresholds={sortedThresholds}
|
|
27
|
+
thresholds={thresholds}
|
|
39
28
|
width={width}
|
|
40
29
|
/>
|
|
41
30
|
)}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { scaleOrdinal } from '@visx/scale';
|
|
2
2
|
import { Pie } from '@visx/shape';
|
|
3
|
-
import {
|
|
3
|
+
import { identity } from 'ramda';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { useTheme } from '@mui/material';
|
|
6
|
+
|
|
7
|
+
import { getColorFromDataAndTresholds } from '../common/utils';
|
|
6
8
|
|
|
7
9
|
import { thresholdThickness } from './Thresholds';
|
|
8
10
|
import AnimatedPie from './AnimatedPie';
|
|
@@ -10,29 +12,11 @@ import { GaugeProps } from './models';
|
|
|
10
12
|
|
|
11
13
|
const dataThickness = 45;
|
|
12
14
|
|
|
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
|
-
|
|
30
15
|
const PieData = ({
|
|
31
16
|
metric,
|
|
32
17
|
adaptedMaxValue,
|
|
33
18
|
thresholds,
|
|
34
|
-
radius
|
|
35
|
-
disabledThresholds
|
|
19
|
+
radius
|
|
36
20
|
}: Omit<
|
|
37
21
|
GaugeProps,
|
|
38
22
|
'width' | 'height' | 'showTooltip' | 'hideTooltip' | 'thresholdTooltipLabels'
|
|
@@ -40,9 +24,9 @@ const PieData = ({
|
|
|
40
24
|
const theme = useTheme();
|
|
41
25
|
|
|
42
26
|
const pieData = [metric.data[0], adaptedMaxValue - metric.data[0]];
|
|
43
|
-
const pieColor =
|
|
27
|
+
const pieColor = !thresholds.enabled
|
|
44
28
|
? theme.palette.success.main
|
|
45
|
-
:
|
|
29
|
+
: getColorFromDataAndTresholds({
|
|
46
30
|
data: metric.data[0],
|
|
47
31
|
theme,
|
|
48
32
|
thresholds
|
|
@@ -69,7 +53,7 @@ const PieData = ({
|
|
|
69
53
|
animate
|
|
70
54
|
getColor={(arc) => getDataColor(arc.data)}
|
|
71
55
|
getKey={(arc) => `${arc.data}`}
|
|
72
|
-
|
|
56
|
+
thresholds={thresholds}
|
|
73
57
|
/>
|
|
74
58
|
)}
|
|
75
59
|
</Pie>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useRef } from 'react';
|
|
2
2
|
|
|
3
3
|
import { Group } from '@visx/group';
|
|
4
|
-
import { head } from 'ramda';
|
|
4
|
+
import { flatten, head, pluck } from 'ramda';
|
|
5
5
|
import { Tooltip } from '@visx/visx';
|
|
6
6
|
|
|
7
7
|
import { Box, Fade, useTheme } from '@mui/material';
|
|
@@ -13,13 +13,11 @@ import { margins } from '../common/margins';
|
|
|
13
13
|
|
|
14
14
|
import Thresholds from './Thresholds';
|
|
15
15
|
import PieData from './PieData';
|
|
16
|
+
import { GaugeProps } from './models';
|
|
16
17
|
|
|
17
|
-
interface Props {
|
|
18
|
-
disabledThresholds?: boolean;
|
|
18
|
+
interface Props extends Pick<GaugeProps, 'thresholds'> {
|
|
19
19
|
height: number;
|
|
20
20
|
metric: Metric;
|
|
21
|
-
thresholdTooltipLabels: Array<string>;
|
|
22
|
-
thresholds: Array<number>;
|
|
23
21
|
width: number;
|
|
24
22
|
}
|
|
25
23
|
|
|
@@ -32,9 +30,7 @@ const ResponsiveGauge = ({
|
|
|
32
30
|
width,
|
|
33
31
|
height,
|
|
34
32
|
thresholds,
|
|
35
|
-
metric
|
|
36
|
-
thresholdTooltipLabels,
|
|
37
|
-
disabledThresholds
|
|
33
|
+
metric
|
|
38
34
|
}: Props): JSX.Element => {
|
|
39
35
|
const svgRef = useRef<SVGSVGElement>(null);
|
|
40
36
|
|
|
@@ -54,13 +50,17 @@ const ResponsiveGauge = ({
|
|
|
54
50
|
const centerY = innerHeight / 2;
|
|
55
51
|
const centerX = innerWidth / 2;
|
|
56
52
|
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(...thresholdValues) * 1.1,
|
|
60
60
|
head(metric.data) as number
|
|
61
61
|
);
|
|
62
62
|
|
|
63
|
-
const pieColor =
|
|
63
|
+
const pieColor = !thresholds.enabled
|
|
64
64
|
? theme.palette.success.main
|
|
65
65
|
: getColorFromDataAndTresholds({
|
|
66
66
|
data: metric.data[0],
|
|
@@ -79,17 +79,14 @@ const ResponsiveGauge = ({
|
|
|
79
79
|
<Group left={centerX + margins.left} top={centerY + height / 6}>
|
|
80
80
|
<Thresholds
|
|
81
81
|
adaptedMaxValue={adaptedMaxValue}
|
|
82
|
-
disabledThresholds={disabledThresholds}
|
|
83
82
|
hideTooltip={hideTooltip}
|
|
84
83
|
metric={metric}
|
|
85
84
|
radius={radius}
|
|
86
85
|
showTooltip={showTooltip}
|
|
87
|
-
thresholdTooltipLabels={thresholdTooltipLabels}
|
|
88
86
|
thresholds={thresholds}
|
|
89
87
|
/>
|
|
90
88
|
<PieData
|
|
91
89
|
adaptedMaxValue={adaptedMaxValue}
|
|
92
|
-
disabledThresholds={disabledThresholds}
|
|
93
90
|
metric={metric}
|
|
94
91
|
radius={radius}
|
|
95
92
|
thresholds={thresholds}
|
|
@@ -114,7 +111,7 @@ const ResponsiveGauge = ({
|
|
|
114
111
|
{metric.unit}
|
|
115
112
|
</text>
|
|
116
113
|
</svg>
|
|
117
|
-
<Fade in={tooltipOpen &&
|
|
114
|
+
<Fade in={tooltipOpen && thresholds.enabled}>
|
|
118
115
|
<Tooltip.Tooltip
|
|
119
116
|
left={(tooltipLeft || 0) - svgLeft}
|
|
120
117
|
style={{
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { scaleOrdinal } from '@visx/scale';
|
|
2
2
|
import { Pie } from '@visx/shape';
|
|
3
|
-
import { pluck } from 'ramda';
|
|
3
|
+
import { equals, pluck } from 'ramda';
|
|
4
4
|
|
|
5
5
|
import { useTheme } from '@mui/material';
|
|
6
6
|
|
|
7
7
|
import AnimatedPie from './AnimatedPie';
|
|
8
|
-
import { GaugeProps
|
|
8
|
+
import { GaugeProps } from './models';
|
|
9
9
|
|
|
10
10
|
export const thresholdThickness = 12;
|
|
11
11
|
|
|
@@ -15,72 +15,125 @@ const Thresholds = ({
|
|
|
15
15
|
adaptedMaxValue,
|
|
16
16
|
showTooltip,
|
|
17
17
|
hideTooltip,
|
|
18
|
-
metric
|
|
19
|
-
thresholdTooltipLabels,
|
|
20
|
-
disabledThresholds
|
|
18
|
+
metric
|
|
21
19
|
}: Omit<GaugeProps, 'width' | 'height'>): JSX.Element => {
|
|
22
20
|
const theme = useTheme();
|
|
23
21
|
|
|
24
|
-
const
|
|
22
|
+
const criticalThresholdValues = pluck('value', thresholds.critical);
|
|
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 = [
|
|
25
95
|
{
|
|
26
|
-
|
|
27
|
-
|
|
96
|
+
thresholdArc: successThresholdArc,
|
|
97
|
+
thresholdScaleOrdinal: successThresholdScaleOrdinal
|
|
28
98
|
},
|
|
29
99
|
{
|
|
30
|
-
|
|
31
|
-
|
|
100
|
+
thresholdArc: warningThresholdArc,
|
|
101
|
+
thresholdScaleOrdinal: warningThresholdScaleOrdinal
|
|
32
102
|
},
|
|
33
103
|
{
|
|
34
|
-
|
|
35
|
-
|
|
104
|
+
thresholdArc: criticalThresholdArc,
|
|
105
|
+
thresholdScaleOrdinal: criticalThresholdScaleOrdinal
|
|
36
106
|
}
|
|
37
107
|
];
|
|
38
108
|
|
|
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
|
-
|
|
61
109
|
return (
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
110
|
+
<>
|
|
111
|
+
{arcs.map(({ thresholdArc, thresholdScaleOrdinal }) => (
|
|
112
|
+
<Pie
|
|
113
|
+
data={thresholdArc}
|
|
114
|
+
endAngle={-Math.PI / 2}
|
|
115
|
+
innerRadius={radius - thresholdThickness}
|
|
116
|
+
key={`arc-${thresholdArc[0].name}`}
|
|
117
|
+
outerRadius={radius}
|
|
118
|
+
pieSortValues={() => -1}
|
|
119
|
+
pieValue={(d) => d.value}
|
|
120
|
+
startAngle={Math.PI / 2}
|
|
121
|
+
>
|
|
122
|
+
{(pie) => (
|
|
123
|
+
<AnimatedPie<{ name: string; value: number }>
|
|
124
|
+
{...pie}
|
|
125
|
+
animate
|
|
126
|
+
getColor={(arc) => thresholdScaleOrdinal(arc.data.name)}
|
|
127
|
+
getKey={(arc) => `${arc.data.name}_${arc.data.value}`}
|
|
128
|
+
hideTooltip={hideTooltip}
|
|
129
|
+
metric={metric}
|
|
130
|
+
showTooltip={showTooltip}
|
|
131
|
+
thresholds={thresholds}
|
|
132
|
+
/>
|
|
133
|
+
)}
|
|
134
|
+
</Pie>
|
|
135
|
+
))}
|
|
136
|
+
</>
|
|
84
137
|
);
|
|
85
138
|
};
|
|
86
139
|
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
+
import { Thresholds } from '../common/models';
|
|
1
2
|
import { Metric } from '../common/timeSeries/models';
|
|
2
3
|
|
|
3
4
|
export interface GaugeProps {
|
|
4
5
|
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
|
-
|
|
12
|
-
thresholds: Array<number>;
|
|
11
|
+
thresholds: Thresholds;
|
|
13
12
|
width: number;
|
|
14
13
|
}
|
|
15
14
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { equals } from 'ramda';
|
|
2
|
+
|
|
3
|
+
import { useTheme } from '@mui/material';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
hideTooltip: () => void;
|
|
7
|
+
label: string;
|
|
8
|
+
showTooltip: (args) => void;
|
|
9
|
+
thresholdType: string;
|
|
10
|
+
value: number;
|
|
11
|
+
width: number;
|
|
12
|
+
yScale: (value: number) => number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const ThresholdLine = ({
|
|
16
|
+
value,
|
|
17
|
+
label,
|
|
18
|
+
yScale,
|
|
19
|
+
thresholdType,
|
|
20
|
+
showTooltip,
|
|
21
|
+
hideTooltip,
|
|
22
|
+
width
|
|
23
|
+
}: Props): JSX.Element => {
|
|
24
|
+
const theme = useTheme();
|
|
25
|
+
|
|
26
|
+
const scaledValue = yScale(value);
|
|
27
|
+
|
|
28
|
+
const onMouseEnter = (): void =>
|
|
29
|
+
showTooltip({
|
|
30
|
+
tooltipData: label,
|
|
31
|
+
tooltipLeft: 0,
|
|
32
|
+
tooltipTop: scaledValue
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const lineColor = equals(thresholdType, 'warning')
|
|
36
|
+
? theme.palette.warning.main
|
|
37
|
+
: theme.palette.error.main;
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<>
|
|
41
|
+
<line
|
|
42
|
+
data-testid={`${thresholdType}-line-${value}`}
|
|
43
|
+
stroke={lineColor}
|
|
44
|
+
strokeDasharray="5,5"
|
|
45
|
+
strokeWidth={2}
|
|
46
|
+
x1={0}
|
|
47
|
+
x2={width}
|
|
48
|
+
y1={scaledValue}
|
|
49
|
+
y2={scaledValue}
|
|
50
|
+
/>
|
|
51
|
+
<line
|
|
52
|
+
data-testid={`${thresholdType}-line-${value}-tooltip`}
|
|
53
|
+
stroke="transparent"
|
|
54
|
+
strokeWidth={5}
|
|
55
|
+
x1={0}
|
|
56
|
+
x2={width}
|
|
57
|
+
y1={scaledValue}
|
|
58
|
+
y2={scaledValue}
|
|
59
|
+
onMouseEnter={onMouseEnter}
|
|
60
|
+
onMouseLeave={hideTooltip}
|
|
61
|
+
/>
|
|
62
|
+
</>
|
|
63
|
+
);
|
|
64
|
+
};
|