@centreon/ui 23.10.1-MON-21149-implement-time-periods-thresholds-refresh-interval.13 → 23.10.1-MON-20798-fe-implement-buttons.0
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/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 +6 -70
- package/src/Graph/LineChart/graphAtoms.ts +3 -0
- package/src/Graph/LineChart/index.stories.tsx +6 -37
- package/src/Graph/LineChart/index.tsx +2 -18
- package/src/Graph/common/timeSeries/index.ts +8 -41
- package/src/Graph/common/timeSeries/models.ts +1 -3
- package/src/Listing/ActionBar/index.tsx +6 -2
- package/src/Listing/index.tsx +3 -0
- package/src/RichTextEditor/RichTextEditor.cypress.spec.tsx +27 -0
- 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/Thresholds.tsx +0 -119
- package/src/utils/useRefreshInterval.ts +0 -21
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-20798-fe-implement-buttons.0",
|
|
4
4
|
"description": "Centreon UI Components",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"eslint": "eslint ./src --ext .js,.jsx,.ts,.tsx --max-warnings 0",
|
|
@@ -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
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
2
|
|
|
3
3
|
import { slice } from 'ramda';
|
|
4
4
|
import { useAtomValue } from 'jotai';
|
|
@@ -28,10 +28,8 @@ interface Props {
|
|
|
28
28
|
limitLegendRows?: boolean;
|
|
29
29
|
lines: Array<Line>;
|
|
30
30
|
renderExtraComponent?: ReactNode;
|
|
31
|
-
setLinesGraph: Dispatch<SetStateAction<Array<Line> | null>>;
|
|
32
31
|
timeSeries: Array<TimeValue>;
|
|
33
32
|
toggable?: boolean;
|
|
34
|
-
xScale;
|
|
35
33
|
}
|
|
36
34
|
|
|
37
35
|
const MainLegend = ({
|
|
@@ -41,21 +39,18 @@ const MainLegend = ({
|
|
|
41
39
|
toggable = true,
|
|
42
40
|
limitLegendRows = true,
|
|
43
41
|
renderExtraComponent,
|
|
44
|
-
displayAnchor = true
|
|
45
|
-
setLinesGraph,
|
|
46
|
-
xScale
|
|
42
|
+
displayAnchor = true
|
|
47
43
|
}: Props): JSX.Element => {
|
|
48
44
|
const { classes, cx } = useStyles({ limitLegendRows });
|
|
49
45
|
const theme = useTheme();
|
|
50
46
|
|
|
51
47
|
const { selectMetricLine, clearHighlight, highlightLine, toggleMetricLine } =
|
|
52
|
-
useLegend({ lines
|
|
48
|
+
useLegend({ lines });
|
|
53
49
|
|
|
54
50
|
const { getFormattedValue } = useInteractiveValues({
|
|
55
51
|
base,
|
|
56
52
|
lines,
|
|
57
|
-
timeSeries
|
|
58
|
-
xScale
|
|
53
|
+
timeSeries
|
|
59
54
|
});
|
|
60
55
|
|
|
61
56
|
const displayedLines = limitLegendRows
|
|
@@ -3,12 +3,11 @@ import { useMemo } from 'react';
|
|
|
3
3
|
import { useAtomValue } from 'jotai';
|
|
4
4
|
import { equals, find, isNil } from 'ramda';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { timeValueAtom } from '../InteractiveComponents/interactionWithGraphAtoms';
|
|
7
7
|
import {
|
|
8
8
|
formatMetricValue,
|
|
9
9
|
getLineForMetric,
|
|
10
|
-
getMetrics
|
|
11
|
-
getTimeValue
|
|
10
|
+
getMetrics
|
|
12
11
|
} from '../../common/timeSeries';
|
|
13
12
|
import { Line, TimeValue } from '../../common/timeSeries/models';
|
|
14
13
|
|
|
@@ -22,22 +21,14 @@ interface Props {
|
|
|
22
21
|
base: number;
|
|
23
22
|
lines: Array<Line>;
|
|
24
23
|
timeSeries: Array<TimeValue>;
|
|
25
|
-
xScale;
|
|
26
24
|
}
|
|
27
25
|
|
|
28
26
|
const useInteractiveValues = ({
|
|
29
27
|
timeSeries,
|
|
30
28
|
lines,
|
|
31
|
-
base
|
|
32
|
-
xScale
|
|
29
|
+
base
|
|
33
30
|
}: Props): InteractiveValues => {
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
const timeValue = getTimeValue({
|
|
37
|
-
timeSeries,
|
|
38
|
-
x: mousePosition?.[0],
|
|
39
|
-
xScale
|
|
40
|
-
});
|
|
31
|
+
const timeValue = useAtomValue(timeValueAtom);
|
|
41
32
|
|
|
42
33
|
const graphTimeValue = timeSeries?.find((item) =>
|
|
43
34
|
equals(item.timeTick, timeValue?.timeTick)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
2
|
|
|
3
|
+
import { useSetAtom } from 'jotai';
|
|
3
4
|
import {
|
|
4
5
|
equals,
|
|
5
6
|
find,
|
|
@@ -16,6 +17,7 @@ import {
|
|
|
16
17
|
toLower
|
|
17
18
|
} from 'ramda';
|
|
18
19
|
|
|
20
|
+
import { linesGraphAtom } from '../graphAtoms';
|
|
19
21
|
import { Line } from '../../common/timeSeries/models';
|
|
20
22
|
|
|
21
23
|
interface LegendActions {
|
|
@@ -27,10 +29,11 @@ interface LegendActions {
|
|
|
27
29
|
|
|
28
30
|
interface Props {
|
|
29
31
|
lines: Array<Line>;
|
|
30
|
-
setLinesGraph: Dispatch<SetStateAction<Array<Line> | null>>;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
const useLegend = ({ lines
|
|
34
|
+
const useLegend = ({ lines }: Props): LegendActions => {
|
|
35
|
+
const setLines = useSetAtom(linesGraphAtom);
|
|
36
|
+
|
|
34
37
|
const displayedLines = reject(propEq('display', false), lines);
|
|
35
38
|
const getLineByMetric = (metric: string): Line =>
|
|
36
39
|
find(propEq('metric', metric), lines) as Line;
|
|
@@ -38,7 +41,7 @@ const useLegend = ({ lines, setLinesGraph }: Props): LegendActions => {
|
|
|
38
41
|
const toggleMetricLine = (metric): void => {
|
|
39
42
|
const line = getLineByMetric(metric);
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
setLines([
|
|
42
45
|
...reject(propEq('metric', metric), lines),
|
|
43
46
|
{ ...line, display: !line.display }
|
|
44
47
|
]);
|
|
@@ -53,11 +56,11 @@ const useLegend = ({ lines, setLinesGraph }: Props): LegendActions => {
|
|
|
53
56
|
|
|
54
57
|
const sortedData = sortBy(compose(toLower, prop('name')), data);
|
|
55
58
|
|
|
56
|
-
|
|
59
|
+
setLines(sortedData);
|
|
57
60
|
};
|
|
58
61
|
|
|
59
62
|
const clearHighlight = (): void => {
|
|
60
|
-
|
|
63
|
+
setLines(map((line) => ({ ...line, highlight: undefined }), lines));
|
|
61
64
|
};
|
|
62
65
|
|
|
63
66
|
const selectMetricLine = (metric: string): void => {
|
|
@@ -68,7 +71,7 @@ const useLegend = ({ lines, setLinesGraph }: Props): LegendActions => {
|
|
|
68
71
|
equals(displayedLines.length, 1) && isLineDisplayed;
|
|
69
72
|
|
|
70
73
|
if (isOnlyLineDisplayed || isEmpty(displayedLines)) {
|
|
71
|
-
|
|
74
|
+
setLines(
|
|
72
75
|
map(
|
|
73
76
|
(line) => ({
|
|
74
77
|
...line,
|
|
@@ -81,7 +84,7 @@ const useLegend = ({ lines, setLinesGraph }: Props): LegendActions => {
|
|
|
81
84
|
return;
|
|
82
85
|
}
|
|
83
86
|
|
|
84
|
-
|
|
87
|
+
setLines(
|
|
85
88
|
map(
|
|
86
89
|
(line) => ({
|
|
87
90
|
...line,
|
|
@@ -102,8 +105,8 @@ const useLegend = ({ lines, setLinesGraph }: Props): LegendActions => {
|
|
|
102
105
|
display: find(propEq('name', line.name), lines)?.display ?? true
|
|
103
106
|
}));
|
|
104
107
|
|
|
105
|
-
|
|
106
|
-
}, [
|
|
108
|
+
setLines(newLines);
|
|
109
|
+
}, []);
|
|
107
110
|
|
|
108
111
|
return { clearHighlight, highlightLine, selectMetricLine, toggleMetricLine };
|
|
109
112
|
};
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { MutableRefObject, useMemo, useRef
|
|
1
|
+
import { MutableRefObject, useMemo, useRef } from 'react';
|
|
2
2
|
|
|
3
|
-
import { Group
|
|
3
|
+
import { Group } from '@visx/visx';
|
|
4
4
|
import { isNil } from 'ramda';
|
|
5
5
|
|
|
6
|
-
import { ClickAwayListener,
|
|
6
|
+
import { ClickAwayListener, Skeleton } from '@mui/material';
|
|
7
7
|
|
|
8
8
|
import { getLeftScale, getRightScale, getXScale } from '../common/timeSeries';
|
|
9
|
-
import { Line } from '../common/timeSeries/models';
|
|
10
9
|
|
|
11
10
|
import Axes from './BasicComponents/Axes';
|
|
12
11
|
import Grids from './BasicComponents/Grids';
|
|
@@ -31,27 +30,17 @@ import {
|
|
|
31
30
|
} from './models';
|
|
32
31
|
import { useIntersection } from './useLineChartIntersection';
|
|
33
32
|
import { CurveType } from './BasicComponents/Lines/models';
|
|
34
|
-
import Thresholds from './BasicComponents/Thresholds';
|
|
35
33
|
|
|
36
34
|
interface Props extends LineChartProps {
|
|
37
35
|
curve: CurveType;
|
|
38
|
-
disabledThresholds?: boolean;
|
|
39
36
|
graphData: Data;
|
|
40
37
|
graphInterval: GraphInterval;
|
|
41
38
|
graphRef: MutableRefObject<HTMLDivElement | null>;
|
|
42
39
|
legend?: LegendModel;
|
|
43
40
|
marginBottom: number;
|
|
44
41
|
shapeLines?: GlobalAreaLines;
|
|
45
|
-
thresholdLabels?: Array<string>;
|
|
46
|
-
thresholdUnit?: string;
|
|
47
|
-
thresholds?: Array<number>;
|
|
48
42
|
}
|
|
49
43
|
|
|
50
|
-
const baseStyles = {
|
|
51
|
-
...Tooltip.defaultStyles,
|
|
52
|
-
textAlign: 'center'
|
|
53
|
-
};
|
|
54
|
-
|
|
55
44
|
const LineChart = ({
|
|
56
45
|
graphData,
|
|
57
46
|
height = 500,
|
|
@@ -69,32 +58,15 @@ const LineChart = ({
|
|
|
69
58
|
graphRef,
|
|
70
59
|
header,
|
|
71
60
|
curve,
|
|
72
|
-
marginBottom
|
|
73
|
-
thresholds,
|
|
74
|
-
thresholdUnit,
|
|
75
|
-
thresholdLabels,
|
|
76
|
-
disabledThresholds
|
|
61
|
+
marginBottom
|
|
77
62
|
}: Props): JSX.Element => {
|
|
78
|
-
const { classes } = useStyles();
|
|
79
|
-
|
|
80
|
-
const theme = useTheme();
|
|
81
|
-
|
|
82
|
-
const [linesGraph, setLinesGraph] = useState<Array<Line> | null>(null);
|
|
83
63
|
const graphSvgRef = useRef<SVGSVGElement | null>(null);
|
|
84
64
|
|
|
65
|
+
const { classes } = useStyles();
|
|
85
66
|
const { isInViewport } = useIntersection({ element: graphRef?.current });
|
|
86
67
|
|
|
87
68
|
const legendRef = useRef<HTMLDivElement | null>(null);
|
|
88
69
|
|
|
89
|
-
const {
|
|
90
|
-
tooltipOpen: thresholdTooltipOpen,
|
|
91
|
-
tooltipLeft: thresholdTooltipLeft,
|
|
92
|
-
tooltipTop: thresholdTooltipTop,
|
|
93
|
-
tooltipData: thresholdTooltipData,
|
|
94
|
-
hideTooltip: hideThresholdTooltip,
|
|
95
|
-
showTooltip: showThresholdTooltip
|
|
96
|
-
} = Tooltip.useTooltip();
|
|
97
|
-
|
|
98
70
|
const graphWidth = width > 0 ? width - margin.left - margin.right : 0;
|
|
99
71
|
const graphHeight =
|
|
100
72
|
(height || 0) > 0
|
|
@@ -109,9 +81,7 @@ const LineChart = ({
|
|
|
109
81
|
|
|
110
82
|
const { displayedLines, newLines } = useFilterLines({
|
|
111
83
|
displayThreshold: canDisplayThreshold(shapeLines?.areaThresholdLines),
|
|
112
|
-
lines
|
|
113
|
-
linesGraph,
|
|
114
|
-
setLinesGraph
|
|
84
|
+
lines
|
|
115
85
|
});
|
|
116
86
|
|
|
117
87
|
const xScale = useMemo(
|
|
@@ -128,8 +98,6 @@ const LineChart = ({
|
|
|
128
98
|
getLeftScale({
|
|
129
99
|
dataLines: displayedLines,
|
|
130
100
|
dataTimeSeries: timeSeries,
|
|
131
|
-
thresholdUnit,
|
|
132
|
-
thresholds: (!disabledThresholds && thresholds) || [],
|
|
133
101
|
valueGraphHeight: graphHeight - 35
|
|
134
102
|
}),
|
|
135
103
|
[displayedLines, timeSeries, graphHeight]
|
|
@@ -140,8 +108,6 @@ const LineChart = ({
|
|
|
140
108
|
getRightScale({
|
|
141
109
|
dataLines: displayedLines,
|
|
142
110
|
dataTimeSeries: timeSeries,
|
|
143
|
-
thresholdUnit,
|
|
144
|
-
thresholds: (!disabledThresholds && thresholds) || [],
|
|
145
111
|
valueGraphHeight: graphHeight - 35
|
|
146
112
|
}),
|
|
147
113
|
[timeSeries, displayedLines, graphHeight]
|
|
@@ -235,20 +201,6 @@ const LineChart = ({
|
|
|
235
201
|
}}
|
|
236
202
|
zoomData={{ ...zoomPreview }}
|
|
237
203
|
/>
|
|
238
|
-
|
|
239
|
-
{!disabledThresholds && (
|
|
240
|
-
<Thresholds
|
|
241
|
-
displayedLines={displayedLines}
|
|
242
|
-
hideTooltip={hideThresholdTooltip}
|
|
243
|
-
leftScale={leftScale}
|
|
244
|
-
rightScale={rightScale}
|
|
245
|
-
showTooltip={showThresholdTooltip}
|
|
246
|
-
thresholdLabels={thresholdLabels}
|
|
247
|
-
thresholdUnit={thresholdUnit}
|
|
248
|
-
thresholds={thresholds}
|
|
249
|
-
width={graphWidth}
|
|
250
|
-
/>
|
|
251
|
-
)}
|
|
252
204
|
</Group.Group>
|
|
253
205
|
</svg>
|
|
254
206
|
{displayTooltip && (
|
|
@@ -266,20 +218,6 @@ const LineChart = ({
|
|
|
266
218
|
xScale={xScale}
|
|
267
219
|
/>
|
|
268
220
|
)}
|
|
269
|
-
<Fade in={thresholdTooltipOpen}>
|
|
270
|
-
<Tooltip.Tooltip
|
|
271
|
-
left={thresholdTooltipLeft}
|
|
272
|
-
style={{
|
|
273
|
-
...baseStyles,
|
|
274
|
-
backgroundColor: theme.palette.background.paper,
|
|
275
|
-
color: theme.palette.text.primary,
|
|
276
|
-
transform: `translate(${graphWidth / 2}px, -10px)`
|
|
277
|
-
}}
|
|
278
|
-
top={thresholdTooltipTop}
|
|
279
|
-
>
|
|
280
|
-
{thresholdTooltipData}
|
|
281
|
-
</Tooltip.Tooltip>
|
|
282
|
-
</Fade>
|
|
283
221
|
</div>
|
|
284
222
|
</ClickAwayListener>
|
|
285
223
|
{displayLegend && (
|
|
@@ -289,9 +227,7 @@ const LineChart = ({
|
|
|
289
227
|
displayAnchor={displayAnchor?.displayGuidingLines ?? true}
|
|
290
228
|
lines={newLines}
|
|
291
229
|
renderExtraComponent={legend?.renderExtraComponent}
|
|
292
|
-
setLinesGraph={setLinesGraph}
|
|
293
230
|
timeSeries={timeSeries}
|
|
294
|
-
xScale={xScale}
|
|
295
231
|
/>
|
|
296
232
|
</div>
|
|
297
233
|
)}
|
|
@@ -29,11 +29,10 @@ 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
|
|
32
|
+
import dataLastDay 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';
|
|
37
36
|
import { Interval, ThresholdType, TooltipData } from './models';
|
|
38
37
|
|
|
39
38
|
import WrapperLineChart from './index';
|
|
@@ -76,7 +75,7 @@ const Threshold = (args): JSX.Element => {
|
|
|
76
75
|
|
|
77
76
|
<WrapperLineChart
|
|
78
77
|
{...args}
|
|
79
|
-
data={
|
|
78
|
+
data={dataLastDay}
|
|
80
79
|
shapeLines={{
|
|
81
80
|
areaThresholdLines: [
|
|
82
81
|
{ type: ThresholdType.basic },
|
|
@@ -124,7 +123,7 @@ const LineChartAndCLS = (args): JSX.Element => {
|
|
|
124
123
|
useEffect(() => {
|
|
125
124
|
setTimeout(() => {
|
|
126
125
|
setLoading(false);
|
|
127
|
-
setData(
|
|
126
|
+
setData(dataLastDay as unknown as LineChartData);
|
|
128
127
|
}, 100000);
|
|
129
128
|
}, []);
|
|
130
129
|
|
|
@@ -188,7 +187,7 @@ const LineChartAndTimePeriod = (args): JSX.Element => {
|
|
|
188
187
|
}
|
|
189
188
|
|
|
190
189
|
if (start.includes(`${defaultStart.split('T')[0]}`)) {
|
|
191
|
-
setCurrentData(
|
|
190
|
+
setCurrentData(dataLastDay as unknown as LineChartData);
|
|
192
191
|
|
|
193
192
|
return;
|
|
194
193
|
}
|
|
@@ -282,7 +281,7 @@ const LineChartAndExclusionPeriod = (args): JSX.Element => {
|
|
|
282
281
|
</ButtonGroup>
|
|
283
282
|
<WrapperLineChart
|
|
284
283
|
{...args}
|
|
285
|
-
data={
|
|
284
|
+
data={dataLastDay as unknown as LineChartData}
|
|
286
285
|
shapeLines={{
|
|
287
286
|
areaThresholdLines: [
|
|
288
287
|
{
|
|
@@ -304,7 +303,7 @@ const Template: Story = {
|
|
|
304
303
|
render: (args) => (
|
|
305
304
|
<WrapperLineChart
|
|
306
305
|
{...args}
|
|
307
|
-
data={
|
|
306
|
+
data={dataLastDay as unknown as LineChartData}
|
|
308
307
|
shapeLines={{
|
|
309
308
|
areaThresholdLines: [
|
|
310
309
|
{
|
|
@@ -382,33 +381,3 @@ export const withCLS: Story = {
|
|
|
382
381
|
start: defaultStart
|
|
383
382
|
}
|
|
384
383
|
};
|
|
385
|
-
|
|
386
|
-
export const withThresholds: Story = {
|
|
387
|
-
argTypes,
|
|
388
|
-
args: {
|
|
389
|
-
...argumentsData,
|
|
390
|
-
thresholdLabels: ['threshold 1', 'threshold 2'],
|
|
391
|
-
thresholds: [300, 350]
|
|
392
|
-
},
|
|
393
|
-
render: (args) => (
|
|
394
|
-
<WrapperLineChart
|
|
395
|
-
{...args}
|
|
396
|
-
data={dataLastDay as unknown as LineChartData}
|
|
397
|
-
/>
|
|
398
|
-
)
|
|
399
|
-
};
|
|
400
|
-
|
|
401
|
-
export const withThresholdsAndUnit: Story = {
|
|
402
|
-
argTypes,
|
|
403
|
-
args: {
|
|
404
|
-
...argumentsData,
|
|
405
|
-
thresholdUnit: '%',
|
|
406
|
-
thresholds: [65, 79]
|
|
407
|
-
},
|
|
408
|
-
render: (args) => (
|
|
409
|
-
<WrapperLineChart
|
|
410
|
-
{...args}
|
|
411
|
-
data={dataLastDay as unknown as LineChartData}
|
|
412
|
-
/>
|
|
413
|
-
)
|
|
414
|
-
};
|
|
@@ -25,16 +25,12 @@ dayjs.extend(timezonePlugin);
|
|
|
25
25
|
interface Props extends Partial<LineChartProps> {
|
|
26
26
|
curve?: CurveType;
|
|
27
27
|
data?: LineChartData;
|
|
28
|
-
disabledThresholds?: boolean;
|
|
29
28
|
end: string;
|
|
30
29
|
legend: LegendModel;
|
|
31
30
|
loading: boolean;
|
|
32
31
|
marginBottom?: number;
|
|
33
32
|
shapeLines?: GlobalAreaLines;
|
|
34
33
|
start: string;
|
|
35
|
-
thresholdLabels?: Array<string>;
|
|
36
|
-
thresholdUnit?: string;
|
|
37
|
-
thresholds?: Array<number>;
|
|
38
34
|
}
|
|
39
35
|
|
|
40
36
|
const WrapperLineChart = ({
|
|
@@ -54,16 +50,12 @@ const WrapperLineChart = ({
|
|
|
54
50
|
legend,
|
|
55
51
|
header,
|
|
56
52
|
curve = Curve.curveLinear,
|
|
57
|
-
marginBottom = 0
|
|
58
|
-
thresholds,
|
|
59
|
-
thresholdUnit,
|
|
60
|
-
thresholdLabels,
|
|
61
|
-
disabledThresholds
|
|
53
|
+
marginBottom = 0
|
|
62
54
|
}: Props): JSX.Element | null => {
|
|
63
55
|
const { adjustedData } = useLineChartData({ data, end, start });
|
|
64
56
|
const lineChartRef = useRef<HTMLDivElement | null>(null);
|
|
65
57
|
|
|
66
|
-
if (loading
|
|
58
|
+
if (loading || !adjustedData) {
|
|
67
59
|
return (
|
|
68
60
|
<LoadingSkeleton
|
|
69
61
|
displayTitleSkeleton={header?.displayTitle ?? true}
|
|
@@ -72,10 +64,6 @@ const WrapperLineChart = ({
|
|
|
72
64
|
);
|
|
73
65
|
}
|
|
74
66
|
|
|
75
|
-
if (!adjustedData) {
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
67
|
return (
|
|
80
68
|
<div
|
|
81
69
|
ref={lineChartRef as MutableRefObject<HTMLDivElement>}
|
|
@@ -91,7 +79,6 @@ const WrapperLineChart = ({
|
|
|
91
79
|
annotationEvent={annotationEvent}
|
|
92
80
|
axis={axis}
|
|
93
81
|
curve={curve}
|
|
94
|
-
disabledThresholds={disabledThresholds}
|
|
95
82
|
displayAnchor={displayAnchor}
|
|
96
83
|
graphData={adjustedData}
|
|
97
84
|
graphInterval={{ end, start }}
|
|
@@ -102,9 +89,6 @@ const WrapperLineChart = ({
|
|
|
102
89
|
loading={loading}
|
|
103
90
|
marginBottom={marginBottom}
|
|
104
91
|
shapeLines={shapeLines}
|
|
105
|
-
thresholdLabels={thresholdLabels}
|
|
106
|
-
thresholdUnit={thresholdUnit}
|
|
107
|
-
thresholds={thresholds}
|
|
108
92
|
timeShiftZones={timeShiftZones}
|
|
109
93
|
tooltip={tooltip}
|
|
110
94
|
width={width ?? responsiveWidth}
|
|
@@ -326,19 +326,10 @@ const getYScale = ({
|
|
|
326
326
|
const getScale = ({
|
|
327
327
|
graphValues,
|
|
328
328
|
height,
|
|
329
|
-
stackedValues
|
|
330
|
-
thresholds
|
|
329
|
+
stackedValues
|
|
331
330
|
}): ScaleLinear<number, number> => {
|
|
332
|
-
const minValue =
|
|
333
|
-
|
|
334
|
-
getMin(stackedValues),
|
|
335
|
-
Math.min(...thresholds)
|
|
336
|
-
);
|
|
337
|
-
const maxValue = Math.max(
|
|
338
|
-
getMax(graphValues),
|
|
339
|
-
getMax(stackedValues),
|
|
340
|
-
Math.max(...thresholds)
|
|
341
|
-
);
|
|
331
|
+
const minValue = min(getMin(graphValues), getMin(stackedValues));
|
|
332
|
+
const maxValue = max(getMax(graphValues), getMax(stackedValues));
|
|
342
333
|
|
|
343
334
|
const upperRangeValue = minValue === maxValue && maxValue === 0 ? height : 0;
|
|
344
335
|
|
|
@@ -352,17 +343,10 @@ const getScale = ({
|
|
|
352
343
|
const getLeftScale = ({
|
|
353
344
|
dataLines,
|
|
354
345
|
dataTimeSeries,
|
|
355
|
-
valueGraphHeight
|
|
356
|
-
thresholds,
|
|
357
|
-
thresholdUnit
|
|
346
|
+
valueGraphHeight
|
|
358
347
|
}: AxeScale): ScaleLinear<number, number> => {
|
|
359
348
|
const [firstUnit, , thirdUnit] = getUnits(dataLines);
|
|
360
349
|
|
|
361
|
-
const shouldApplyThresholds =
|
|
362
|
-
equals(thresholdUnit, firstUnit) ||
|
|
363
|
-
equals(thresholdUnit, thirdUnit) ||
|
|
364
|
-
!thresholdUnit;
|
|
365
|
-
|
|
366
350
|
const graphValues = isNil(thirdUnit)
|
|
367
351
|
? getMetricValuesForUnit({
|
|
368
352
|
lines: dataLines,
|
|
@@ -386,12 +370,7 @@ const getLeftScale = ({
|
|
|
386
370
|
})
|
|
387
371
|
: [0];
|
|
388
372
|
|
|
389
|
-
return getScale({
|
|
390
|
-
graphValues,
|
|
391
|
-
height: valueGraphHeight,
|
|
392
|
-
stackedValues,
|
|
393
|
-
thresholds: shouldApplyThresholds ? thresholds : []
|
|
394
|
-
});
|
|
373
|
+
return getScale({ graphValues, height: valueGraphHeight, stackedValues });
|
|
395
374
|
};
|
|
396
375
|
|
|
397
376
|
const getXScale = ({
|
|
@@ -407,9 +386,7 @@ const getXScale = ({
|
|
|
407
386
|
const getRightScale = ({
|
|
408
387
|
dataLines,
|
|
409
388
|
dataTimeSeries,
|
|
410
|
-
valueGraphHeight
|
|
411
|
-
thresholds,
|
|
412
|
-
thresholdUnit
|
|
389
|
+
valueGraphHeight
|
|
413
390
|
}: AxeScale): ScaleLinear<number, number> => {
|
|
414
391
|
const [, secondUnit] = getUnits(dataLines);
|
|
415
392
|
|
|
@@ -419,8 +396,6 @@ const getRightScale = ({
|
|
|
419
396
|
unit: secondUnit
|
|
420
397
|
});
|
|
421
398
|
|
|
422
|
-
const shouldApplyThresholds = equals(thresholdUnit, secondUnit);
|
|
423
|
-
|
|
424
399
|
const secondUnitHasStackedLines = isNil(secondUnit)
|
|
425
400
|
? false
|
|
426
401
|
: hasUnitStackedLines({ lines: dataLines, unit: secondUnit });
|
|
@@ -432,12 +407,7 @@ const getRightScale = ({
|
|
|
432
407
|
})
|
|
433
408
|
: [0];
|
|
434
409
|
|
|
435
|
-
return getScale({
|
|
436
|
-
graphValues,
|
|
437
|
-
height: valueGraphHeight,
|
|
438
|
-
stackedValues,
|
|
439
|
-
thresholds: shouldApplyThresholds ? thresholds : []
|
|
440
|
-
});
|
|
410
|
+
return getScale({ graphValues, height: valueGraphHeight, stackedValues });
|
|
441
411
|
};
|
|
442
412
|
|
|
443
413
|
const formatMetricValue = ({
|
|
@@ -506,10 +476,7 @@ const getTimeValue = ({
|
|
|
506
476
|
xScale,
|
|
507
477
|
timeSeries,
|
|
508
478
|
marginLeft = margin.left
|
|
509
|
-
}: TimeValueProps): TimeValue
|
|
510
|
-
if (isNil(x)) {
|
|
511
|
-
return null;
|
|
512
|
-
}
|
|
479
|
+
}: TimeValueProps): TimeValue => {
|
|
513
480
|
const date = xScale.invert(x - marginLeft);
|
|
514
481
|
const index = bisectDate(getDates(timeSeries), date);
|
|
515
482
|
|
|
@@ -65,8 +65,6 @@ 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>;
|
|
70
68
|
valueGraphHeight: number;
|
|
71
69
|
}
|
|
72
70
|
|
|
@@ -119,6 +117,6 @@ export interface YScales {
|
|
|
119
117
|
export interface TimeValueProps {
|
|
120
118
|
marginLeft?: number;
|
|
121
119
|
timeSeries: Array<TimeValue>;
|
|
122
|
-
x
|
|
120
|
+
x: number;
|
|
123
121
|
xScale: ScaleLinear<number, number>;
|
|
124
122
|
}
|
|
@@ -107,7 +107,8 @@ const MemoListingActionBar = ({
|
|
|
107
107
|
widthToMoveTablePagination = 550,
|
|
108
108
|
actionsBarMemoProps = [],
|
|
109
109
|
viewerModeConfiguration,
|
|
110
|
-
viewMode
|
|
110
|
+
viewMode,
|
|
111
|
+
visualizationActions
|
|
111
112
|
}: Props): JSX.Element => {
|
|
112
113
|
const marginWidthTableListing = 30;
|
|
113
114
|
const { classes, cx } = useStyles({
|
|
@@ -136,6 +137,7 @@ const MemoListingActionBar = ({
|
|
|
136
137
|
<div className={classes.actions}>
|
|
137
138
|
<div>{actions}</div>
|
|
138
139
|
</div>
|
|
140
|
+
{visualizationActions && <div>{visualizationActions}</div>}
|
|
139
141
|
<div className={classes.subContainer}>
|
|
140
142
|
{!isEmpty(viewerModeConfiguration) &&
|
|
141
143
|
!isNil(viewerModeConfiguration) && (
|
|
@@ -241,7 +243,8 @@ const ListingActionBar = ({
|
|
|
241
243
|
widthToMoveTablePagination,
|
|
242
244
|
customPaginationClassName,
|
|
243
245
|
viewMode,
|
|
244
|
-
viewerModeConfiguration
|
|
246
|
+
viewerModeConfiguration,
|
|
247
|
+
visualizationActions
|
|
245
248
|
}: Props): JSX.Element | null => {
|
|
246
249
|
if (
|
|
247
250
|
not(paginated) &&
|
|
@@ -265,6 +268,7 @@ const ListingActionBar = ({
|
|
|
265
268
|
totalRows={totalRows}
|
|
266
269
|
viewMode={viewMode}
|
|
267
270
|
viewerModeConfiguration={viewerModeConfiguration}
|
|
271
|
+
visualizationActions={visualizationActions}
|
|
268
272
|
widthToMoveTablePagination={widthToMoveTablePagination}
|
|
269
273
|
onLimitChange={onLimitChange}
|
|
270
274
|
onPaginate={onPaginate}
|
package/src/Listing/index.tsx
CHANGED
|
@@ -128,6 +128,7 @@ export interface Props<TRow> {
|
|
|
128
128
|
totalRows?: number;
|
|
129
129
|
viewMode?: ListingVariant;
|
|
130
130
|
viewerModeConfiguration?: ViewerModeConfiguration;
|
|
131
|
+
visualizationActions?: JSX.Element;
|
|
131
132
|
widthToMoveTablePagination?: number;
|
|
132
133
|
}
|
|
133
134
|
|
|
@@ -139,6 +140,7 @@ export const performanceRowsLimit = 60;
|
|
|
139
140
|
|
|
140
141
|
const Listing = <TRow extends { id: RowId }>({
|
|
141
142
|
limit = 10,
|
|
143
|
+
visualizationActions,
|
|
142
144
|
columns,
|
|
143
145
|
columnConfiguration = defaultColumnConfiguration,
|
|
144
146
|
customPaginationClassName,
|
|
@@ -506,6 +508,7 @@ const Listing = <TRow extends { id: RowId }>({
|
|
|
506
508
|
totalRows={totalRows}
|
|
507
509
|
viewMode={viewMode}
|
|
508
510
|
viewerModeConfiguration={viewerModeConfiguration}
|
|
511
|
+
visualizationActions={visualizationActions}
|
|
509
512
|
widthToMoveTablePagination={widthToMoveTablePagination}
|
|
510
513
|
onLimitChange={changeLimit}
|
|
511
514
|
onPaginate={onPaginate}
|
|
@@ -341,5 +341,32 @@ describe('Rich Text Editor', () => {
|
|
|
341
341
|
cy.get('[data-testid="RichTextEditor"]').find(tag).should('be.visible');
|
|
342
342
|
});
|
|
343
343
|
});
|
|
344
|
+
|
|
345
|
+
describe('Rich Text Editor is disabled', () => {
|
|
346
|
+
beforeEach(() => {
|
|
347
|
+
cy.mount({
|
|
348
|
+
Component: (
|
|
349
|
+
<RichTextEditor
|
|
350
|
+
disabled
|
|
351
|
+
editable
|
|
352
|
+
initialEditorState={mockInititalStateToEditor}
|
|
353
|
+
/>
|
|
354
|
+
)
|
|
355
|
+
});
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it('displays editor when editable props is false and an initialState exist', () => {
|
|
359
|
+
cy.get('[data-testid="RichTextEditor"]')
|
|
360
|
+
.invoke('attr', 'contenteditable')
|
|
361
|
+
.should('eq', 'false');
|
|
362
|
+
cy.findByLabelText('Undo').should('be.disabled');
|
|
363
|
+
cy.findByLabelText('Redo').should('be.disabled');
|
|
364
|
+
cy.findByLabelText('bold').should('be.disabled');
|
|
365
|
+
cy.findByLabelText('italic').should('be.disabled');
|
|
366
|
+
cy.findByLabelText('underline').should('be.disabled');
|
|
367
|
+
cy.findByLabelText('strikethrough').should('be.disabled');
|
|
368
|
+
cy.findByLabelText('link').should('be.disabled');
|
|
369
|
+
});
|
|
370
|
+
});
|
|
344
371
|
});
|
|
345
372
|
});
|
|
@@ -1,24 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { T, always, cond, flatten, isEmpty, join, pipe, pluck } from 'ramda';
|
|
2
2
|
import dayjs from 'dayjs';
|
|
3
3
|
|
|
4
4
|
import { LineChartData, useFetchQuery } from '../..';
|
|
5
5
|
|
|
6
6
|
import { ServiceMetric } from './models';
|
|
7
7
|
|
|
8
|
-
interface CustomTimePeriod {
|
|
9
|
-
end: string;
|
|
10
|
-
start: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
8
|
interface UseMetricsQueryProps {
|
|
14
9
|
baseEndpoint: string;
|
|
15
10
|
metrics: Array<ServiceMetric>;
|
|
16
11
|
refreshInterval?: number | false;
|
|
17
|
-
timePeriod?:
|
|
18
|
-
end?: string | null;
|
|
19
|
-
start?: string | null;
|
|
20
|
-
timePeriodType: number;
|
|
21
|
-
};
|
|
12
|
+
timePeriod?: TimePeriod;
|
|
22
13
|
}
|
|
23
14
|
|
|
24
15
|
interface UseMetricsQueryState {
|
|
@@ -29,24 +20,24 @@ interface UseMetricsQueryState {
|
|
|
29
20
|
start: string;
|
|
30
21
|
}
|
|
31
22
|
|
|
23
|
+
enum TimePeriod {
|
|
24
|
+
lastDay = 'last_day'
|
|
25
|
+
}
|
|
26
|
+
|
|
32
27
|
const getStartEndFromTimePeriod = (
|
|
33
|
-
timePeriod:
|
|
28
|
+
timePeriod: TimePeriod
|
|
34
29
|
): { end: string; start: string } => {
|
|
35
|
-
return
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
return cond([
|
|
31
|
+
[
|
|
32
|
+
T,
|
|
33
|
+
always({
|
|
34
|
+
end: dayjs().toISOString(),
|
|
35
|
+
start: dayjs().subtract(1, 'day').toISOString()
|
|
36
|
+
})
|
|
37
|
+
]
|
|
38
|
+
])(timePeriod);
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
const isCustomTimePeriod = (
|
|
42
|
-
timePeriod:
|
|
43
|
-
| number
|
|
44
|
-
| {
|
|
45
|
-
end?: string | null;
|
|
46
|
-
start?: string | null;
|
|
47
|
-
}
|
|
48
|
-
): boolean => has('end', timePeriod) && has('start', timePeriod);
|
|
49
|
-
|
|
50
41
|
interface PerformanceGraphData extends Omit<LineChartData, 'global'> {
|
|
51
42
|
base: number;
|
|
52
43
|
}
|
|
@@ -54,9 +45,7 @@ interface PerformanceGraphData extends Omit<LineChartData, 'global'> {
|
|
|
54
45
|
const useGraphQuery = ({
|
|
55
46
|
metrics,
|
|
56
47
|
baseEndpoint,
|
|
57
|
-
timePeriod =
|
|
58
|
-
timePeriodType: 1
|
|
59
|
-
},
|
|
48
|
+
timePeriod = TimePeriod.lastDay,
|
|
60
49
|
refreshInterval = false
|
|
61
50
|
}: UseMetricsQueryProps): UseMetricsQueryState => {
|
|
62
51
|
const metricIds = pipe(
|
|
@@ -66,32 +55,16 @@ const useGraphQuery = ({
|
|
|
66
55
|
join(',')
|
|
67
56
|
)(metrics);
|
|
68
57
|
|
|
69
|
-
const
|
|
70
|
-
? {
|
|
71
|
-
end: timePeriod.end,
|
|
72
|
-
start: timePeriod.start
|
|
73
|
-
}
|
|
74
|
-
: timePeriod?.timePeriodType;
|
|
58
|
+
const { end, start } = getStartEndFromTimePeriod(timePeriod);
|
|
75
59
|
|
|
76
60
|
const {
|
|
77
61
|
data: graphData,
|
|
78
62
|
isFetching,
|
|
79
63
|
isLoading
|
|
80
64
|
} = useFetchQuery<PerformanceGraphData>({
|
|
81
|
-
getEndpoint: () =>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
(timePeriodToUse as CustomTimePeriod).start
|
|
85
|
-
}&end=${(timePeriodToUse as CustomTimePeriod).end}`;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const { end, start } = getStartEndFromTimePeriod(
|
|
89
|
-
timePeriodToUse as number
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
return `${baseEndpoint}?metricIds=[${metricIds}]&start=${start}&end=${end}`;
|
|
93
|
-
},
|
|
94
|
-
getQueryKey: () => ['graph', metricIds, timePeriod],
|
|
65
|
+
getEndpoint: () =>
|
|
66
|
+
`${baseEndpoint}?metricIds=[${metricIds}]&start=${start}&end=${end}`,
|
|
67
|
+
getQueryKey: () => ['graph', metricIds],
|
|
95
68
|
queryOptions: {
|
|
96
69
|
enabled: !isEmpty(metricIds),
|
|
97
70
|
refetchInterval: refreshInterval,
|
|
@@ -110,10 +83,6 @@ const useGraphQuery = ({
|
|
|
110
83
|
}
|
|
111
84
|
: undefined;
|
|
112
85
|
|
|
113
|
-
const { end, start } = isCustomTimePeriod(timePeriodToUse)
|
|
114
|
-
? (timePeriodToUse as CustomTimePeriod)
|
|
115
|
-
: getStartEndFromTimePeriod(timePeriodToUse as number);
|
|
116
|
-
|
|
117
86
|
return {
|
|
118
87
|
end,
|
|
119
88
|
graphData: formattedGraphData,
|
package/src/utils/index.ts
CHANGED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { always, cond, equals, isNil } from 'ramda';
|
|
2
|
-
|
|
3
|
-
import { Theme, useTheme } from '@mui/material';
|
|
4
|
-
|
|
5
|
-
import { getUnits, getYScale } from '../../common/timeSeries';
|
|
6
|
-
import { Line } from '../../common/timeSeries/models';
|
|
7
|
-
|
|
8
|
-
interface Props {
|
|
9
|
-
displayedLines: Array<Line>;
|
|
10
|
-
hideTooltip: () => void;
|
|
11
|
-
leftScale: (value: number) => number;
|
|
12
|
-
rightScale: (value: number) => number;
|
|
13
|
-
showTooltip: (props) => void;
|
|
14
|
-
thresholdLabels?: Array<string>;
|
|
15
|
-
thresholdUnit?: string;
|
|
16
|
-
thresholds?: Array<number>;
|
|
17
|
-
width: number;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
interface GetColorProps {
|
|
21
|
-
index: number;
|
|
22
|
-
theme: Theme;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const getColor = ({ index, theme }: GetColorProps): string => {
|
|
26
|
-
return cond([
|
|
27
|
-
[equals(0), always(theme.palette.warning.main)],
|
|
28
|
-
[equals(1), always(theme.palette.error.main)]
|
|
29
|
-
])(index);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const Thresholds = ({
|
|
33
|
-
thresholds,
|
|
34
|
-
leftScale,
|
|
35
|
-
rightScale,
|
|
36
|
-
width,
|
|
37
|
-
displayedLines,
|
|
38
|
-
thresholdUnit,
|
|
39
|
-
showTooltip,
|
|
40
|
-
hideTooltip,
|
|
41
|
-
thresholdLabels
|
|
42
|
-
}: Props): JSX.Element | null => {
|
|
43
|
-
const theme = useTheme();
|
|
44
|
-
|
|
45
|
-
if (!thresholds) {
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const [firstUnit, secondUnit, thirdUnit] = getUnits(
|
|
50
|
-
displayedLines as Array<Line>
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
const shouldUseRightScale = equals(thresholdUnit, secondUnit);
|
|
54
|
-
|
|
55
|
-
const yScale = shouldUseRightScale
|
|
56
|
-
? rightScale
|
|
57
|
-
: getYScale({
|
|
58
|
-
hasMoreThanTwoUnits: !isNil(thirdUnit),
|
|
59
|
-
invert: null,
|
|
60
|
-
leftScale,
|
|
61
|
-
rightScale,
|
|
62
|
-
secondUnit,
|
|
63
|
-
unit: firstUnit
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
const thresholdScaledValues = thresholds
|
|
67
|
-
.sort()
|
|
68
|
-
.map((threshold) => yScale(threshold));
|
|
69
|
-
|
|
70
|
-
return (
|
|
71
|
-
<>
|
|
72
|
-
{thresholdScaledValues.map((threshold, index) => {
|
|
73
|
-
return (
|
|
74
|
-
<line
|
|
75
|
-
data-testid={`threshold-${threshold}`}
|
|
76
|
-
key={`threshold-${thresholdLabels?.[index]}-${threshold}`}
|
|
77
|
-
stroke={getColor({
|
|
78
|
-
index,
|
|
79
|
-
theme
|
|
80
|
-
})}
|
|
81
|
-
strokeDasharray="5,5"
|
|
82
|
-
strokeWidth={2}
|
|
83
|
-
x1={0}
|
|
84
|
-
x2={width}
|
|
85
|
-
y1={threshold}
|
|
86
|
-
y2={threshold}
|
|
87
|
-
/>
|
|
88
|
-
);
|
|
89
|
-
})}
|
|
90
|
-
{thresholdScaledValues.map((threshold, index) => {
|
|
91
|
-
return (
|
|
92
|
-
<line
|
|
93
|
-
data-testid={`threshold-${threshold}-tooltip`}
|
|
94
|
-
key={`threshold-${thresholdLabels?.[index]}-${threshold}-tooltip`}
|
|
95
|
-
stroke="transparent"
|
|
96
|
-
strokeWidth={4}
|
|
97
|
-
x1={0}
|
|
98
|
-
x2={width}
|
|
99
|
-
y1={threshold}
|
|
100
|
-
y2={threshold}
|
|
101
|
-
onMouseEnter={(): void => {
|
|
102
|
-
if (!thresholdLabels?.[index]) {
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
showTooltip({
|
|
106
|
-
tooltipData: thresholdLabels?.[index],
|
|
107
|
-
tooltipLeft: 0,
|
|
108
|
-
tooltipTop: threshold
|
|
109
|
-
});
|
|
110
|
-
}}
|
|
111
|
-
onMouseLeave={hideTooltip}
|
|
112
|
-
/>
|
|
113
|
-
);
|
|
114
|
-
})}
|
|
115
|
-
</>
|
|
116
|
-
);
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
export default Thresholds;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { always, cond, equals } from 'ramda';
|
|
2
|
-
|
|
3
|
-
interface Props {
|
|
4
|
-
globalRefreshInterval?: number;
|
|
5
|
-
refreshInterval: 'default' | 'custom' | 'manual';
|
|
6
|
-
refreshIntervalCustom?: number;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const useRefreshInterval = ({
|
|
10
|
-
refreshInterval,
|
|
11
|
-
refreshIntervalCustom,
|
|
12
|
-
globalRefreshInterval
|
|
13
|
-
}: Props): number | false => {
|
|
14
|
-
const refreshIntervalToUse = cond([
|
|
15
|
-
[equals('default'), always(globalRefreshInterval)],
|
|
16
|
-
[equals('custom'), always(refreshIntervalCustom)],
|
|
17
|
-
[equals('manual'), always(0)]
|
|
18
|
-
])(refreshInterval);
|
|
19
|
-
|
|
20
|
-
return refreshIntervalToUse ? refreshIntervalToUse * 1000 : false;
|
|
21
|
-
};
|