@centreon/ui 25.2.3 → 25.2.5
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/BarChart/BarChart.cypress.spec.tsx +2 -2
- package/src/Graph/BarChart/ResponsiveBarChart.tsx +17 -4
- package/src/Graph/Chart/Chart.cypress.spec.tsx +13 -17
- package/src/Graph/Chart/Chart.tsx +50 -33
- package/src/Graph/Chart/InteractiveComponents/AnchorPoint/GuidingLines.tsx +3 -3
- package/src/Graph/Chart/InteractiveComponents/AnchorPoint/useTickGraph.ts +19 -6
- package/src/Graph/common/Axes/index.tsx +1 -1
- package/src/Graph/common/Axes/useAxisY.ts +8 -4
- package/src/Graph/common/BaseChart/ChartSvgWrapper.tsx +12 -4
- package/src/Graph/common/BaseChart/useComputeBaseChartDimensions.ts +6 -4
- package/src/Graph/common/BaseChart/useComputeYAxisMaxCharacters.ts +92 -0
- package/src/Graph/common/models.ts +7 -8
- package/src/Graph/common/timeSeries/index.test.ts +1 -1
- package/src/Graph/common/timeSeries/index.ts +1 -7
- package/src/Graph/common/utils.ts +49 -1
- package/src/Graph/mockedData/lastDayWithNullValues.json +46 -12
- package/src/InputField/Select/Autocomplete/Connected/Multi/index.test.tsx +20 -1
- package/src/InputField/Select/Autocomplete/Multi/index.stories.tsx +19 -0
- package/src/InputField/Select/Autocomplete/Multi/index.tsx +8 -5
- package/src/Listing/index.tsx +3 -1
- package/src/Graph/common/timeSeries/index.test.ts-E +0 -622
package/package.json
CHANGED
|
@@ -61,14 +61,14 @@ const checkWidth = (orientation): void => {
|
|
|
61
61
|
cy.get('g[class*="visx-rows"] > line')
|
|
62
62
|
.eq(0)
|
|
63
63
|
.should('have.attr', 'x2')
|
|
64
|
-
.and('equal', '
|
|
64
|
+
.and('equal', '1145');
|
|
65
65
|
|
|
66
66
|
return;
|
|
67
67
|
}
|
|
68
68
|
cy.get('g[class*="visx-rows"] > line')
|
|
69
69
|
.eq(0)
|
|
70
70
|
.should('have.attr', 'x2')
|
|
71
|
-
.and('equal', '
|
|
71
|
+
.and('equal', '1180');
|
|
72
72
|
};
|
|
73
73
|
|
|
74
74
|
describe('Bar chart', () => {
|
|
@@ -13,6 +13,7 @@ import { useIntersection } from '../Chart/useChartIntersection';
|
|
|
13
13
|
import BaseChart from '../common/BaseChart/BaseChart';
|
|
14
14
|
import ChartSvgWrapper from '../common/BaseChart/ChartSvgWrapper';
|
|
15
15
|
import { useComputeBaseChartDimensions } from '../common/BaseChart/useComputeBaseChartDimensions';
|
|
16
|
+
import { useComputeYAxisMaxCharacters } from '../common/BaseChart/useComputeYAxisMaxCharacters';
|
|
16
17
|
import Thresholds from '../common/Thresholds/Thresholds';
|
|
17
18
|
import { Thresholds as ThresholdsModel } from '../common/models';
|
|
18
19
|
import {
|
|
@@ -22,7 +23,6 @@ import {
|
|
|
22
23
|
} from '../common/timeSeries';
|
|
23
24
|
import { Line } from '../common/timeSeries/models';
|
|
24
25
|
import { useTooltipStyles } from '../common/useTooltipStyles';
|
|
25
|
-
|
|
26
26
|
import BarGroup from './BarGroup';
|
|
27
27
|
import BarChartTooltip from './Tooltip/BarChartTooltip';
|
|
28
28
|
import { tooltipDataAtom } from './atoms';
|
|
@@ -58,7 +58,7 @@ const ResponsiveBarChart = ({
|
|
|
58
58
|
barStyle,
|
|
59
59
|
skipIntersectionObserver
|
|
60
60
|
}: Props): JSX.Element => {
|
|
61
|
-
const { title, timeSeries, baseAxis, lines } = graphData;
|
|
61
|
+
const { title, timeSeries, baseAxis, lines } = graphData || {};
|
|
62
62
|
|
|
63
63
|
const { classes, cx } = useTooltipStyles();
|
|
64
64
|
|
|
@@ -70,19 +70,30 @@ const ResponsiveBarChart = ({
|
|
|
70
70
|
const { isInViewport } = useIntersection({ element: graphRef?.current });
|
|
71
71
|
|
|
72
72
|
const displayedLines = useMemo(
|
|
73
|
-
() => linesGraph.filter(({ display }) => display),
|
|
73
|
+
() => (linesGraph || []).filter(({ display }) => display),
|
|
74
74
|
[linesGraph]
|
|
75
75
|
);
|
|
76
76
|
|
|
77
77
|
const [firstUnit, secondUnit] = getUnits(displayedLines);
|
|
78
78
|
const allUnits = getUnits(lines);
|
|
79
79
|
|
|
80
|
+
const { maxLeftAxisCharacters, maxRightAxisCharacters } =
|
|
81
|
+
useComputeYAxisMaxCharacters({
|
|
82
|
+
graphData,
|
|
83
|
+
thresholds,
|
|
84
|
+
thresholdUnit,
|
|
85
|
+
axis,
|
|
86
|
+
firstUnit,
|
|
87
|
+
secondUnit
|
|
88
|
+
});
|
|
89
|
+
|
|
80
90
|
const { legendRef, graphWidth, graphHeight } = useComputeBaseChartDimensions({
|
|
81
91
|
hasSecondUnit: Boolean(secondUnit),
|
|
82
92
|
height,
|
|
83
93
|
legendDisplay: legend?.display,
|
|
84
94
|
legendPlacement: legend?.placement,
|
|
85
|
-
width
|
|
95
|
+
width,
|
|
96
|
+
maxAxisCharacters: maxRightAxisCharacters || maxLeftAxisCharacters
|
|
86
97
|
});
|
|
87
98
|
|
|
88
99
|
const thresholdValues = flatten([
|
|
@@ -216,6 +227,8 @@ const ResponsiveBarChart = ({
|
|
|
216
227
|
svgRef={graphSvgRef}
|
|
217
228
|
timeSeries={timeSeries}
|
|
218
229
|
xScale={xScale}
|
|
230
|
+
maxAxisCharacters={maxLeftAxisCharacters}
|
|
231
|
+
hasSecondUnit={Boolean(secondUnit)}
|
|
219
232
|
>
|
|
220
233
|
<>
|
|
221
234
|
<BarGroup
|
|
@@ -129,13 +129,13 @@ const initializeCustomUnits = ({
|
|
|
129
129
|
};
|
|
130
130
|
|
|
131
131
|
const checkGraphWidth = (): void => {
|
|
132
|
-
cy.findByTestId('graph-interaction-zone')
|
|
133
|
-
.should('have.attr', 'width')
|
|
134
|
-
.and('equal', '1170');
|
|
135
|
-
|
|
136
132
|
cy.findByTestId('graph-interaction-zone')
|
|
137
133
|
.should('have.attr', 'height')
|
|
138
134
|
.and('equal', '393');
|
|
135
|
+
|
|
136
|
+
cy.findByTestId('graph-interaction-zone').then((graph) => {
|
|
137
|
+
expect(Number(graph[0].attributes.width.value)).to.be.greaterThan(1170);
|
|
138
|
+
});
|
|
139
139
|
};
|
|
140
140
|
|
|
141
141
|
describe('Line chart', () => {
|
|
@@ -158,8 +158,7 @@ describe('Line chart', () => {
|
|
|
158
158
|
cy.contains('06/18/2023').should('be.visible');
|
|
159
159
|
|
|
160
160
|
cy.contains('0.45 s').should('be.visible');
|
|
161
|
-
cy.contains('
|
|
162
|
-
cy.contains('0.43 s').should('be.visible');
|
|
161
|
+
cy.contains('73.65%').should('be.visible');
|
|
163
162
|
|
|
164
163
|
cy.makeSnapshot();
|
|
165
164
|
});
|
|
@@ -181,7 +180,7 @@ describe('Line chart', () => {
|
|
|
181
180
|
cy.get('[data-metric="connTime"]').should(
|
|
182
181
|
'have.attr',
|
|
183
182
|
'data-highlight',
|
|
184
|
-
'
|
|
183
|
+
'false'
|
|
185
184
|
);
|
|
186
185
|
|
|
187
186
|
cy.makeSnapshot();
|
|
@@ -194,7 +193,7 @@ describe('Line chart', () => {
|
|
|
194
193
|
|
|
195
194
|
cy.contains('Min: 70.31').should('be.visible');
|
|
196
195
|
|
|
197
|
-
cy.findByTestId('graph-interaction-zone').realMouseMove(
|
|
196
|
+
cy.findByTestId('graph-interaction-zone').realMouseMove(1198, 100);
|
|
198
197
|
|
|
199
198
|
cy.get('[data-metric="querytime"]').should('not.exist');
|
|
200
199
|
|
|
@@ -208,10 +207,10 @@ describe('Line chart', () => {
|
|
|
208
207
|
|
|
209
208
|
cy.contains('Min: 70.31').should('be.visible');
|
|
210
209
|
|
|
211
|
-
cy.findByTestId('graph-interaction-zone').realMouseMove(
|
|
210
|
+
cy.findByTestId('graph-interaction-zone').realMouseMove(1170, 100);
|
|
212
211
|
|
|
213
212
|
cy.get('[data-metric="querytime"]').should('be.visible');
|
|
214
|
-
cy.get('[data-metric="hitratio"]').should('
|
|
213
|
+
cy.get('[data-metric="hitratio"]').should('be.visible');
|
|
215
214
|
|
|
216
215
|
cy.makeSnapshot();
|
|
217
216
|
});
|
|
@@ -225,12 +224,12 @@ describe('Line chart', () => {
|
|
|
225
224
|
|
|
226
225
|
cy.findByTestId('graph-interaction-zone').realMouseMove(452, 26);
|
|
227
226
|
|
|
228
|
-
cy.get('[data-metric="
|
|
227
|
+
cy.get('[data-metric="hitratio"]').should(
|
|
229
228
|
'have.attr',
|
|
230
229
|
'data-highlight',
|
|
231
230
|
'true'
|
|
232
231
|
);
|
|
233
|
-
cy.get('[data-metric="
|
|
232
|
+
cy.get('[data-metric="querytime"]').should('not.exist');
|
|
234
233
|
|
|
235
234
|
cy.makeSnapshot();
|
|
236
235
|
});
|
|
@@ -286,7 +285,7 @@ describe('Line chart', () => {
|
|
|
286
285
|
|
|
287
286
|
cy.findByTestId('graph-interaction-zone')
|
|
288
287
|
.should('have.attr', 'width')
|
|
289
|
-
.and('equal', '
|
|
288
|
+
.and('equal', '1200');
|
|
290
289
|
|
|
291
290
|
cy.findByLabelText('Centreon-Server: Round-Trip Average Time')
|
|
292
291
|
.find('[data-icon="true"]')
|
|
@@ -371,8 +370,6 @@ describe('Line chart', () => {
|
|
|
371
370
|
cy.get('[data-as-list="true"]').should('exist');
|
|
372
371
|
|
|
373
372
|
cy.contains(':00 AM').should('be.visible');
|
|
374
|
-
|
|
375
|
-
cy.makeSnapshot();
|
|
376
373
|
});
|
|
377
374
|
});
|
|
378
375
|
|
|
@@ -528,8 +525,7 @@ describe('Line chart', () => {
|
|
|
528
525
|
|
|
529
526
|
checkGraphWidth();
|
|
530
527
|
cy.contains(':00 AM').should('be.visible');
|
|
531
|
-
cy.get('circle[cx="
|
|
532
|
-
cy.get('circle[cy="105.21757370835121"]').should('be.visible');
|
|
528
|
+
cy.get('circle[cx="37.625"]').should('be.visible');
|
|
533
529
|
|
|
534
530
|
cy.makeSnapshot();
|
|
535
531
|
});
|
|
@@ -16,6 +16,7 @@ import BarGroup from '../BarChart/BarGroup';
|
|
|
16
16
|
import BaseChart from '../common/BaseChart/BaseChart';
|
|
17
17
|
import ChartSvgWrapper from '../common/BaseChart/ChartSvgWrapper';
|
|
18
18
|
import { useComputeBaseChartDimensions } from '../common/BaseChart/useComputeBaseChartDimensions';
|
|
19
|
+
import { useComputeYAxisMaxCharacters } from '../common/BaseChart/useComputeYAxisMaxCharacters';
|
|
19
20
|
import Thresholds from '../common/Thresholds/Thresholds';
|
|
20
21
|
import type { Thresholds as ThresholdsModel } from '../common/models';
|
|
21
22
|
import {
|
|
@@ -25,7 +26,6 @@ import {
|
|
|
25
26
|
getYScalePerUnit
|
|
26
27
|
} from '../common/timeSeries';
|
|
27
28
|
import type { Line } from '../common/timeSeries/models';
|
|
28
|
-
|
|
29
29
|
import Lines from './BasicComponents/Lines';
|
|
30
30
|
import {
|
|
31
31
|
canDisplayThreshold,
|
|
@@ -140,13 +140,24 @@ const Chart = ({
|
|
|
140
140
|
[displayedLines]
|
|
141
141
|
);
|
|
142
142
|
|
|
143
|
+
const { maxLeftAxisCharacters, maxRightAxisCharacters } =
|
|
144
|
+
useComputeYAxisMaxCharacters({
|
|
145
|
+
graphData,
|
|
146
|
+
thresholds,
|
|
147
|
+
thresholdUnit,
|
|
148
|
+
axis,
|
|
149
|
+
firstUnit,
|
|
150
|
+
secondUnit
|
|
151
|
+
});
|
|
152
|
+
|
|
143
153
|
const { legendRef, graphWidth, graphHeight } = useComputeBaseChartDimensions({
|
|
144
154
|
hasSecondUnit: Boolean(secondUnit),
|
|
145
155
|
height,
|
|
146
156
|
legendDisplay: legend?.display,
|
|
147
157
|
legendHeight: legend?.height,
|
|
148
158
|
legendPlacement: legend?.placement,
|
|
149
|
-
width
|
|
159
|
+
width,
|
|
160
|
+
maxAxisCharacters: maxRightAxisCharacters || maxLeftAxisCharacters
|
|
150
161
|
});
|
|
151
162
|
|
|
152
163
|
const xScale = useMemo(
|
|
@@ -283,39 +294,45 @@ const Chart = ({
|
|
|
283
294
|
svgRef={graphSvgRef}
|
|
284
295
|
timeSeries={timeSeries}
|
|
285
296
|
xScale={xScale}
|
|
297
|
+
maxAxisCharacters={maxLeftAxisCharacters}
|
|
298
|
+
hasSecondUnit={Boolean(secondUnit)}
|
|
286
299
|
>
|
|
287
300
|
<>
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
301
|
+
{!isEmpty(linesDisplayedAsBar) && (
|
|
302
|
+
<BarGroup
|
|
303
|
+
barStyle={barStyle}
|
|
304
|
+
isTooltipHidden={false}
|
|
305
|
+
lines={linesDisplayedAsBar}
|
|
306
|
+
orientation="horizontal"
|
|
307
|
+
size={graphHeight - margin.top - 5}
|
|
308
|
+
timeSeries={timeSeries}
|
|
309
|
+
xScale={xScaleBand}
|
|
310
|
+
yScalesPerUnit={yScalesPerUnit}
|
|
311
|
+
/>
|
|
312
|
+
)}
|
|
313
|
+
{!isEmpty(linesDisplayedAsLine) && (
|
|
314
|
+
<Lines
|
|
315
|
+
areaTransparency={lineStyle?.areaTransparency}
|
|
316
|
+
curve={lineStyle?.curve || 'linear'}
|
|
317
|
+
dashLength={lineStyle?.dashLength}
|
|
318
|
+
dashOffset={lineStyle?.dashOffset}
|
|
319
|
+
displayAnchor={displayAnchor}
|
|
320
|
+
displayedLines={linesDisplayedAsLine}
|
|
321
|
+
dotOffset={lineStyle?.dotOffset}
|
|
322
|
+
graphSvgRef={graphSvgRef}
|
|
323
|
+
height={graphHeight - margin.top}
|
|
324
|
+
lineWidth={lineStyle?.lineWidth}
|
|
325
|
+
scale={axis?.scale}
|
|
326
|
+
scaleLogarithmicBase={axis?.scaleLogarithmicBase}
|
|
327
|
+
showArea={lineStyle?.showArea}
|
|
328
|
+
showPoints={lineStyle?.showPoints}
|
|
329
|
+
timeSeries={timeSeries}
|
|
330
|
+
width={graphWidth}
|
|
331
|
+
xScale={xScale}
|
|
332
|
+
yScalesPerUnit={yScalesPerUnit}
|
|
333
|
+
{...shapeLines}
|
|
334
|
+
/>
|
|
335
|
+
)}
|
|
319
336
|
<InteractionWithGraph
|
|
320
337
|
annotationData={{ ...annotationEvent }}
|
|
321
338
|
commonData={{
|
|
@@ -11,7 +11,7 @@ const GuidingLines = ({
|
|
|
11
11
|
graphHeight,
|
|
12
12
|
graphWidth
|
|
13
13
|
}: GuidingLinesModel): JSX.Element | null => {
|
|
14
|
-
const { positionX, positionY } = useTickGraph({
|
|
14
|
+
const { positionX, positionY, guidingLinesRef } = useTickGraph({
|
|
15
15
|
timeSeries,
|
|
16
16
|
xScale
|
|
17
17
|
});
|
|
@@ -20,7 +20,7 @@ const GuidingLines = ({
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
return (
|
|
23
|
-
|
|
23
|
+
<g ref={guidingLinesRef}>
|
|
24
24
|
<Shape.Line
|
|
25
25
|
fill="dotted"
|
|
26
26
|
from={{ x: positionX, y: 0 }}
|
|
@@ -38,7 +38,7 @@ const GuidingLines = ({
|
|
|
38
38
|
strokeWidth={1}
|
|
39
39
|
to={{ x: graphWidth, y: positionY }}
|
|
40
40
|
/>
|
|
41
|
-
|
|
41
|
+
</g>
|
|
42
42
|
);
|
|
43
43
|
};
|
|
44
44
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
1
|
+
import { MutableRefObject, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
import { ScaleLinear } from 'd3-scale';
|
|
4
4
|
import { useAtomValue } from 'jotai';
|
|
@@ -15,6 +15,7 @@ interface AnchorPointResult {
|
|
|
15
15
|
tickAxisBottom: Date | null;
|
|
16
16
|
tickAxisLeft: string | null;
|
|
17
17
|
tickAxisRight: string | null;
|
|
18
|
+
guidingLinesRef: MutableRefObject<SVGGElement | null>;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
interface Props {
|
|
@@ -34,6 +35,7 @@ const useTickGraph = ({
|
|
|
34
35
|
lines = [],
|
|
35
36
|
baseAxis = 1000
|
|
36
37
|
}: Props): AnchorPointResult => {
|
|
38
|
+
const guidingLinesRef = useRef<SVGGElement | null>(null);
|
|
37
39
|
const [tickAxisBottom, setTickAxisBottom] = useState<Date | null>(null);
|
|
38
40
|
const [tickAxisLeft, setTickAxisLeft] = useState<string | null>(null);
|
|
39
41
|
const [tickAxisRight, setTickAxisRight] = useState<string | null>(null);
|
|
@@ -42,12 +44,22 @@ const useTickGraph = ({
|
|
|
42
44
|
|
|
43
45
|
const mousePosition = useAtomValue(mousePositionAtom);
|
|
44
46
|
|
|
47
|
+
const paddingLeftString = useMemo(
|
|
48
|
+
() =>
|
|
49
|
+
(
|
|
50
|
+
guidingLinesRef.current?.parentElement?.parentElement?.attributes
|
|
51
|
+
?.transform.value || ''
|
|
52
|
+
).match(/translate\(([0-9\.]+), ([0-9\.]+)\)/)?.[1] || '0',
|
|
53
|
+
[
|
|
54
|
+
guidingLinesRef.current?.parentElement?.parentElement?.attributes
|
|
55
|
+
?.transform.value
|
|
56
|
+
]
|
|
57
|
+
);
|
|
58
|
+
|
|
45
59
|
const positionX = mousePosition
|
|
46
|
-
? mousePosition[0] -
|
|
47
|
-
: undefined;
|
|
48
|
-
const positionY = mousePosition
|
|
49
|
-
? mousePosition[1] - margin.top + 2
|
|
60
|
+
? mousePosition[0] - Number(paddingLeftString) - 1
|
|
50
61
|
: undefined;
|
|
62
|
+
const positionY = mousePosition ? mousePosition[1] - margin.top : undefined;
|
|
51
63
|
|
|
52
64
|
useEffect(() => {
|
|
53
65
|
if (!mousePosition) {
|
|
@@ -86,7 +98,8 @@ const useTickGraph = ({
|
|
|
86
98
|
positionY,
|
|
87
99
|
tickAxisBottom,
|
|
88
100
|
tickAxisLeft,
|
|
89
|
-
tickAxisRight
|
|
101
|
+
tickAxisRight,
|
|
102
|
+
guidingLinesRef
|
|
90
103
|
};
|
|
91
104
|
};
|
|
92
105
|
export default useTickGraph;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
2
|
|
|
3
|
-
import { Axis } from '@visx/visx';
|
|
3
|
+
import type { Axis } from '@visx/visx';
|
|
4
4
|
import { isNil } from 'ramda';
|
|
5
5
|
|
|
6
6
|
import { useTheme } from '@mui/material';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { formatMetricValueWithUnit, getUnits } from '../timeSeries';
|
|
9
9
|
import { commonTickLabelProps } from '../utils';
|
|
10
10
|
|
|
11
|
-
import { Data, LabelProps } from './models';
|
|
11
|
+
import type { Data, LabelProps } from './models';
|
|
12
12
|
|
|
13
13
|
interface AxisYData {
|
|
14
14
|
displayUnit: boolean;
|
|
@@ -69,7 +69,11 @@ const useAxisY = ({
|
|
|
69
69
|
return '';
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
return
|
|
72
|
+
return formatMetricValueWithUnit({
|
|
73
|
+
base: data.baseAxis,
|
|
74
|
+
unit,
|
|
75
|
+
value
|
|
76
|
+
}) as string;
|
|
73
77
|
};
|
|
74
78
|
|
|
75
79
|
const labelProps = ({
|
|
@@ -9,8 +9,6 @@ import Axes from '../Axes';
|
|
|
9
9
|
import Grids from '../Grids';
|
|
10
10
|
import { Line, TimeValue } from '../timeSeries/models';
|
|
11
11
|
|
|
12
|
-
import { extraMargin } from './useComputeBaseChartDimensions';
|
|
13
|
-
|
|
14
12
|
interface Props {
|
|
15
13
|
allUnits: Array<string>;
|
|
16
14
|
axis?: ChartAxis;
|
|
@@ -27,6 +25,8 @@ interface Props {
|
|
|
27
25
|
svgRef: MutableRefObject<SVGSVGElement | null>;
|
|
28
26
|
timeSeries: Array<TimeValue>;
|
|
29
27
|
xScale;
|
|
28
|
+
maxAxisCharacters?: number;
|
|
29
|
+
hasSecondUnit?: boolean;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
const ChartSvgWrapper = ({
|
|
@@ -44,7 +44,9 @@ const ChartSvgWrapper = ({
|
|
|
44
44
|
axis,
|
|
45
45
|
children,
|
|
46
46
|
orientation = 'horizontal',
|
|
47
|
-
allUnits
|
|
47
|
+
allUnits,
|
|
48
|
+
maxAxisCharacters = 0,
|
|
49
|
+
hasSecondUnit
|
|
48
50
|
}: Props): JSX.Element => {
|
|
49
51
|
const isHorizontal = equals(orientation, 'horizontal');
|
|
50
52
|
|
|
@@ -55,7 +57,13 @@ const ChartSvgWrapper = ({
|
|
|
55
57
|
ref={svgRef}
|
|
56
58
|
width="100%"
|
|
57
59
|
>
|
|
58
|
-
<Group.Group
|
|
60
|
+
<Group.Group
|
|
61
|
+
left={
|
|
62
|
+
maxAxisCharacters * 5 +
|
|
63
|
+
(hasSecondUnit ? margin.top * 0.8 : margin.top * 0.6)
|
|
64
|
+
}
|
|
65
|
+
top={margin.top}
|
|
66
|
+
>
|
|
59
67
|
{showGridLines && (
|
|
60
68
|
<Grids
|
|
61
69
|
gridLinesType={gridLinesType}
|
|
@@ -3,6 +3,7 @@ import { MutableRefObject, useRef } from 'react';
|
|
|
3
3
|
import { equals, isNil } from 'ramda';
|
|
4
4
|
|
|
5
5
|
import { margin } from '../../Chart/common';
|
|
6
|
+
import { margins } from '../margins';
|
|
6
7
|
|
|
7
8
|
export const extraMargin = 10;
|
|
8
9
|
|
|
@@ -13,6 +14,7 @@ interface UseComputeBaseChartDimensionsProps {
|
|
|
13
14
|
legendHeight?: number;
|
|
14
15
|
legendPlacement?: string;
|
|
15
16
|
width: number;
|
|
17
|
+
maxAxisCharacters: number;
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
interface UseComputeBaseChartDimensionsState {
|
|
@@ -27,7 +29,8 @@ export const useComputeBaseChartDimensions = ({
|
|
|
27
29
|
legendDisplay,
|
|
28
30
|
legendPlacement,
|
|
29
31
|
hasSecondUnit,
|
|
30
|
-
legendHeight
|
|
32
|
+
legendHeight,
|
|
33
|
+
maxAxisCharacters
|
|
31
34
|
}: UseComputeBaseChartDimensionsProps): UseComputeBaseChartDimensionsState => {
|
|
32
35
|
const legendRef = useRef<HTMLDivElement | null>(null);
|
|
33
36
|
|
|
@@ -48,9 +51,8 @@ export const useComputeBaseChartDimensions = ({
|
|
|
48
51
|
const graphWidth =
|
|
49
52
|
width > 0
|
|
50
53
|
? width -
|
|
51
|
-
|
|
52
|
-
(hasSecondUnit ?
|
|
53
|
-
extraMargin -
|
|
54
|
+
(hasSecondUnit ? maxAxisCharacters * 2 : maxAxisCharacters) * 6 -
|
|
55
|
+
(hasSecondUnit ? margins.left * 0.8 : margin.left) -
|
|
54
56
|
legendBoundingWidth
|
|
55
57
|
: 0;
|
|
56
58
|
const graphHeight =
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { isEmpty } from 'ramda';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { ChartAxis } from '../../Chart/models';
|
|
4
|
+
import { Data } from '../Axes/models';
|
|
5
|
+
import { Thresholds } from '../models';
|
|
6
|
+
import { getFormattedAxisValues } from '../utils';
|
|
7
|
+
|
|
8
|
+
interface UseComputeYAxisMaxCharactersProps {
|
|
9
|
+
firstUnit: string;
|
|
10
|
+
secondUnit: string;
|
|
11
|
+
thresholdUnit?: string;
|
|
12
|
+
thresholds?: Thresholds;
|
|
13
|
+
graphData: Data;
|
|
14
|
+
axis?: ChartAxis;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface UseComputteYAxisMaxCharactersState {
|
|
18
|
+
maxLeftAxisCharacters: number;
|
|
19
|
+
maxRightAxisCharacters: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const useComputeYAxisMaxCharacters = ({
|
|
23
|
+
thresholds,
|
|
24
|
+
firstUnit,
|
|
25
|
+
secondUnit,
|
|
26
|
+
graphData,
|
|
27
|
+
axis,
|
|
28
|
+
thresholdUnit
|
|
29
|
+
}: UseComputeYAxisMaxCharactersProps): UseComputteYAxisMaxCharactersState => {
|
|
30
|
+
const maxLeftValue = useMemo(
|
|
31
|
+
() =>
|
|
32
|
+
getFormattedAxisValues({
|
|
33
|
+
threshold: thresholds?.critical ?? [],
|
|
34
|
+
axisUnit: axis?.axisYLeft?.unit ?? firstUnit,
|
|
35
|
+
timeSeries: graphData?.timeSeries ?? [],
|
|
36
|
+
thresholdUnit,
|
|
37
|
+
lines: graphData?.lines ?? [],
|
|
38
|
+
base: graphData?.baseAxis
|
|
39
|
+
}),
|
|
40
|
+
[
|
|
41
|
+
thresholds?.critical,
|
|
42
|
+
axis?.axisYLeft?.unit,
|
|
43
|
+
firstUnit,
|
|
44
|
+
graphData?.timeSeries,
|
|
45
|
+
thresholdUnit,
|
|
46
|
+
graphData?.lines,
|
|
47
|
+
graphData?.baseAxis
|
|
48
|
+
]
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const maxRightValue = useMemo(
|
|
52
|
+
() =>
|
|
53
|
+
getFormattedAxisValues({
|
|
54
|
+
threshold: thresholds?.critical ?? [],
|
|
55
|
+
axisUnit: axis?.axisYRight?.unit ?? secondUnit,
|
|
56
|
+
timeSeries: graphData.timeSeries ?? [],
|
|
57
|
+
thresholdUnit,
|
|
58
|
+
lines: graphData.lines ?? [],
|
|
59
|
+
base: graphData.baseAxis
|
|
60
|
+
}),
|
|
61
|
+
[
|
|
62
|
+
thresholds?.critical,
|
|
63
|
+
axis?.axisYRight?.unit,
|
|
64
|
+
secondUnit,
|
|
65
|
+
graphData.timeSeries,
|
|
66
|
+
thresholdUnit,
|
|
67
|
+
graphData.lines,
|
|
68
|
+
graphData.baseAxis
|
|
69
|
+
]
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
const maxLeftAxisCharacters = useMemo(
|
|
73
|
+
() =>
|
|
74
|
+
isEmpty(maxLeftValue)
|
|
75
|
+
? 2
|
|
76
|
+
: Math.max(...maxLeftValue.map((value) => value.length), 2),
|
|
77
|
+
[maxLeftValue]
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const maxRightAxisCharacters = useMemo(
|
|
81
|
+
() =>
|
|
82
|
+
isEmpty(maxRightValue)
|
|
83
|
+
? 5
|
|
84
|
+
: Math.max(...maxRightValue.map((value) => value.length), 5),
|
|
85
|
+
[maxRightValue]
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
maxLeftAxisCharacters,
|
|
90
|
+
maxRightAxisCharacters
|
|
91
|
+
};
|
|
92
|
+
};
|
|
@@ -6,14 +6,13 @@ export interface LineChartData {
|
|
|
6
6
|
times: Array<string>;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
+
export interface Threshold {
|
|
10
|
+
label: string;
|
|
11
|
+
value: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
9
14
|
export interface Thresholds {
|
|
10
|
-
critical: Array<
|
|
11
|
-
label: string;
|
|
12
|
-
value: number;
|
|
13
|
-
}>;
|
|
15
|
+
critical: Array<Threshold>;
|
|
14
16
|
enabled: boolean;
|
|
15
|
-
warning: Array<
|
|
16
|
-
label: string;
|
|
17
|
-
value: number;
|
|
18
|
-
}>;
|
|
17
|
+
warning: Array<Threshold>;
|
|
19
18
|
}
|
|
@@ -523,13 +523,7 @@ const getYScalePerUnit = ({
|
|
|
523
523
|
};
|
|
524
524
|
|
|
525
525
|
const formatTime = (value: number): string => {
|
|
526
|
-
|
|
527
|
-
return `${numeral(value).format('0.[00]a')} ms`;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
const t = numeral(value / 1000).format('0.[00]a');
|
|
531
|
-
|
|
532
|
-
return `${t} seconds`;
|
|
526
|
+
return `${numeral(value).format('0.[00]a')} ms`;
|
|
533
527
|
};
|
|
534
528
|
|
|
535
529
|
const registerMsUnitToNumeral = (): null => {
|