@centreon/ui 26.3.4 → 26.3.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/SingleBar/ResponsiveSingleBar.tsx +33 -11
- package/src/Graph/SingleBar/SingleBar.cypress.spec.tsx +25 -0
- package/src/Graph/SingleBar/SingleBar.stories.tsx +50 -1
- package/src/Graph/SingleBar/ThresholdLine.tsx +32 -25
- package/src/Graph/SingleBar/Thresholds.tsx +10 -2
- package/src/Graph/SingleBar/models.ts +2 -0
- package/src/api/buildListingEndpoint/index.ts +15 -2
- package/src/api/buildListingEndpoint/models.ts +1 -0
package/package.json
CHANGED
|
@@ -18,7 +18,7 @@ import { Metric } from '../common/timeSeries/models';
|
|
|
18
18
|
import { useTooltipStyles } from '../common/useTooltipStyles';
|
|
19
19
|
import { getColorFromDataAndTresholds } from '../common/utils';
|
|
20
20
|
|
|
21
|
-
import { barHeights } from './ThresholdLine';
|
|
21
|
+
import { barHeights, lineMargins } from './ThresholdLine';
|
|
22
22
|
import Thresholds, { groupMargin } from './Thresholds';
|
|
23
23
|
import { SingleBarProps } from './models';
|
|
24
24
|
|
|
@@ -36,7 +36,9 @@ const ResponsiveSingleBar = ({
|
|
|
36
36
|
baseColor,
|
|
37
37
|
size = 'medium',
|
|
38
38
|
showLabels = true,
|
|
39
|
-
max
|
|
39
|
+
max,
|
|
40
|
+
direction = 'column',
|
|
41
|
+
textWidth
|
|
40
42
|
}: Props): JSX.Element => {
|
|
41
43
|
const { classes } = useTooltipStyles();
|
|
42
44
|
const theme = useTheme();
|
|
@@ -79,16 +81,26 @@ const ResponsiveSingleBar = ({
|
|
|
79
81
|
|
|
80
82
|
const textHeight = isSmall ? 46 : 27;
|
|
81
83
|
|
|
84
|
+
const textY = useMemo(() => {
|
|
85
|
+
if (direction === 'row' && isSmall) {
|
|
86
|
+
return 2;
|
|
87
|
+
}
|
|
88
|
+
if (direction === 'row' && !isSmall) {
|
|
89
|
+
return 22;
|
|
90
|
+
}
|
|
91
|
+
return isSmall ? 10 : 25;
|
|
92
|
+
}, [direction, isSmall]);
|
|
93
|
+
|
|
82
94
|
const text = showLabels && (
|
|
83
95
|
<text
|
|
84
|
-
dominantBaseline=
|
|
96
|
+
dominantBaseline={direction === 'row' ? 'hanging' : 'middle'}
|
|
85
97
|
style={{
|
|
86
98
|
fill: barColor,
|
|
87
99
|
...textStyle
|
|
88
100
|
}}
|
|
89
|
-
textAnchor=
|
|
90
|
-
x=
|
|
91
|
-
y={
|
|
101
|
+
textAnchor={direction === 'row' ? 'start' : 'middle'}
|
|
102
|
+
x={direction === 'row' ? 0 : '50%'}
|
|
103
|
+
y={textY}
|
|
92
104
|
>
|
|
93
105
|
{formatMetricValueWithUnit({
|
|
94
106
|
base: 1000,
|
|
@@ -99,13 +111,18 @@ const ResponsiveSingleBar = ({
|
|
|
99
111
|
</text>
|
|
100
112
|
);
|
|
101
113
|
|
|
114
|
+
const widthMargin = useMemo(
|
|
115
|
+
() => (direction === 'row' && textWidth) || 0,
|
|
116
|
+
[direction, textWidth]
|
|
117
|
+
);
|
|
118
|
+
|
|
102
119
|
const xScale = useMemo(
|
|
103
120
|
() =>
|
|
104
121
|
scaleLinear<number>({
|
|
105
122
|
domain: [0, adaptedMaxValue],
|
|
106
|
-
range: [0, width - 10 || 0]
|
|
123
|
+
range: [0, width - widthMargin - 10 || 0]
|
|
107
124
|
}),
|
|
108
|
-
[width, adaptedMaxValue]
|
|
125
|
+
[width, adaptedMaxValue, widthMargin]
|
|
109
126
|
);
|
|
110
127
|
|
|
111
128
|
const metricBarWidth = useMemo(
|
|
@@ -119,7 +136,10 @@ const ResponsiveSingleBar = ({
|
|
|
119
136
|
|
|
120
137
|
const springStyle = useSpring({ width: metricBarWidth });
|
|
121
138
|
|
|
122
|
-
const barY =
|
|
139
|
+
const barY =
|
|
140
|
+
direction === 'row'
|
|
141
|
+
? lineMargins[size] / 2
|
|
142
|
+
: groupMargin + (isSmall ? 0 : 2 * margins.top);
|
|
123
143
|
|
|
124
144
|
const realBarHeight = !isSmall
|
|
125
145
|
? clamp(
|
|
@@ -161,7 +181,7 @@ const ResponsiveSingleBar = ({
|
|
|
161
181
|
height={realBarHeight}
|
|
162
182
|
rx={4}
|
|
163
183
|
style={springStyle}
|
|
164
|
-
x={5}
|
|
184
|
+
x={direction === 'row' ? textWidth : 5}
|
|
165
185
|
y={barY}
|
|
166
186
|
/>
|
|
167
187
|
<Bar
|
|
@@ -171,7 +191,7 @@ const ResponsiveSingleBar = ({
|
|
|
171
191
|
ry={4}
|
|
172
192
|
stroke={alpha(theme.palette.text.primary, 0.3)}
|
|
173
193
|
width={maxBarWidth}
|
|
174
|
-
x={5}
|
|
194
|
+
x={direction === 'row' ? textWidth : 5}
|
|
175
195
|
y={barY}
|
|
176
196
|
/>
|
|
177
197
|
{thresholds.enabled && (
|
|
@@ -183,6 +203,8 @@ const ResponsiveSingleBar = ({
|
|
|
183
203
|
size={size}
|
|
184
204
|
thresholds={thresholds}
|
|
185
205
|
xScale={xScale}
|
|
206
|
+
direction={direction}
|
|
207
|
+
textWidth={textWidth}
|
|
186
208
|
/>
|
|
187
209
|
)}
|
|
188
210
|
</Group.Group>
|
|
@@ -118,4 +118,29 @@ describe('Single bar', () => {
|
|
|
118
118
|
|
|
119
119
|
cy.makeSnapshot();
|
|
120
120
|
});
|
|
121
|
+
|
|
122
|
+
it('displays the value on the left of the bar when the corresponding prop is set', () => {
|
|
123
|
+
initialize({
|
|
124
|
+
thresholds: successThresholds,
|
|
125
|
+
direction: 'row',
|
|
126
|
+
textWidth: 100
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
cy.contains('0.41 s').should('be.visible');
|
|
130
|
+
|
|
131
|
+
cy.makeSnapshot();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('displays the value on the left of the bar when the corresponding prop is set and the size is mall', () => {
|
|
135
|
+
initialize({
|
|
136
|
+
thresholds: criticalThresholds,
|
|
137
|
+
direction: 'row',
|
|
138
|
+
textWidth: 70,
|
|
139
|
+
size: 'small'
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
cy.contains('0.41 s').should('be.visible');
|
|
143
|
+
|
|
144
|
+
cy.makeSnapshot();
|
|
145
|
+
});
|
|
121
146
|
});
|
|
@@ -12,7 +12,7 @@ export default meta;
|
|
|
12
12
|
type Story = StoryObj<typeof SingleBar>;
|
|
13
13
|
|
|
14
14
|
const Template = (props): JSX.Element => (
|
|
15
|
-
<div style={{ height: '500px', width: '
|
|
15
|
+
<div style={{ height: '500px', width: '200px' }}>
|
|
16
16
|
<SingleBar {...props} />
|
|
17
17
|
</div>
|
|
18
18
|
);
|
|
@@ -230,3 +230,52 @@ export const smallDisplay: Story = {
|
|
|
230
230
|
},
|
|
231
231
|
render: SmallTemplate
|
|
232
232
|
};
|
|
233
|
+
|
|
234
|
+
export const RowDirection: Story = {
|
|
235
|
+
args: {
|
|
236
|
+
data: dataLastWeek,
|
|
237
|
+
direction: 'row',
|
|
238
|
+
textWidth: 100,
|
|
239
|
+
thresholds: {
|
|
240
|
+
critical: [
|
|
241
|
+
{
|
|
242
|
+
label: 'Critical',
|
|
243
|
+
value: 0.6
|
|
244
|
+
}
|
|
245
|
+
],
|
|
246
|
+
enabled: true,
|
|
247
|
+
warning: [
|
|
248
|
+
{
|
|
249
|
+
label: 'Warning',
|
|
250
|
+
value: 0.5
|
|
251
|
+
}
|
|
252
|
+
]
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
render: Template
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
export const RowDirectionSmall: Story = {
|
|
259
|
+
args: {
|
|
260
|
+
data: dataLastWeek,
|
|
261
|
+
size: 'small',
|
|
262
|
+
direction: 'row',
|
|
263
|
+
textWidth: 70,
|
|
264
|
+
thresholds: {
|
|
265
|
+
critical: [
|
|
266
|
+
{
|
|
267
|
+
label: 'Critical',
|
|
268
|
+
value: 0.6
|
|
269
|
+
}
|
|
270
|
+
],
|
|
271
|
+
enabled: true,
|
|
272
|
+
warning: [
|
|
273
|
+
{
|
|
274
|
+
label: 'Warning',
|
|
275
|
+
value: 0.5
|
|
276
|
+
}
|
|
277
|
+
]
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
render: Template
|
|
281
|
+
};
|
|
@@ -4,7 +4,9 @@ import { useTheme } from '@mui/material';
|
|
|
4
4
|
|
|
5
5
|
import { margins } from '../common/margins';
|
|
6
6
|
|
|
7
|
+
import { useMemo } from 'react';
|
|
7
8
|
import { groupMargin } from './Thresholds';
|
|
9
|
+
import { SingleBarProps } from './models';
|
|
8
10
|
|
|
9
11
|
export const barHeights = {
|
|
10
12
|
medium: 72,
|
|
@@ -12,12 +14,12 @@ export const barHeights = {
|
|
|
12
14
|
};
|
|
13
15
|
export const margin = 40;
|
|
14
16
|
|
|
15
|
-
const lineMargins = {
|
|
17
|
+
export const lineMargins = {
|
|
16
18
|
medium: 10,
|
|
17
19
|
small: 5
|
|
18
20
|
};
|
|
19
21
|
|
|
20
|
-
interface Props {
|
|
22
|
+
interface Props extends Pick<SingleBarProps, 'direction'> {
|
|
21
23
|
barHeight: number;
|
|
22
24
|
hideTooltip: () => void;
|
|
23
25
|
isSmall: boolean;
|
|
@@ -27,6 +29,7 @@ interface Props {
|
|
|
27
29
|
thresholdType: string;
|
|
28
30
|
value: number;
|
|
29
31
|
xScale: (value: number) => number;
|
|
32
|
+
textWidth?: number;
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
export const ThresholdLine = ({
|
|
@@ -38,11 +41,13 @@ export const ThresholdLine = ({
|
|
|
38
41
|
hideTooltip,
|
|
39
42
|
size,
|
|
40
43
|
barHeight,
|
|
41
|
-
isSmall
|
|
44
|
+
isSmall,
|
|
45
|
+
direction,
|
|
46
|
+
textWidth
|
|
42
47
|
}: Props): JSX.Element => {
|
|
43
48
|
const theme = useTheme();
|
|
44
49
|
|
|
45
|
-
const scaledValue = xScale(value) || 0;
|
|
50
|
+
const scaledValue = xScale(value) + (textWidth || 0) || 0;
|
|
46
51
|
|
|
47
52
|
const lineMargin = lineMargins[size];
|
|
48
53
|
|
|
@@ -55,25 +60,35 @@ export const ThresholdLine = ({
|
|
|
55
60
|
? theme.palette.warning.main
|
|
56
61
|
: theme.palette.error.main;
|
|
57
62
|
|
|
63
|
+
const lineY1 = useMemo(() => {
|
|
64
|
+
if (direction === 'row') {
|
|
65
|
+
return 0;
|
|
66
|
+
}
|
|
67
|
+
return isSmall
|
|
68
|
+
? groupMargin - lineMargin
|
|
69
|
+
: groupMargin + lineMargin + margins.top;
|
|
70
|
+
}, [direction, isSmall, groupMargin, lineMargin, margins]);
|
|
71
|
+
|
|
72
|
+
const lineY2 = useMemo(() => {
|
|
73
|
+
if (direction === 'row') {
|
|
74
|
+
return barHeight + lineMargin;
|
|
75
|
+
}
|
|
76
|
+
return isSmall
|
|
77
|
+
? barHeight + groupMargin - lineMargin + margins.top - 6
|
|
78
|
+
: barHeight + groupMargin + lineMargin + 2 * margins.top;
|
|
79
|
+
}, [direction, isSmall, groupMargin, lineMargin, margins]);
|
|
80
|
+
|
|
58
81
|
return (
|
|
59
82
|
<>
|
|
60
83
|
<line
|
|
61
84
|
data-testid={`${thresholdType}-line-${value}`}
|
|
62
85
|
stroke={lineColor}
|
|
63
|
-
strokeDasharray="6,
|
|
86
|
+
strokeDasharray="6, 5"
|
|
64
87
|
strokeWidth={2}
|
|
65
88
|
x1={scaledValue}
|
|
66
89
|
x2={scaledValue + 1}
|
|
67
|
-
y1={
|
|
68
|
-
|
|
69
|
-
? groupMargin - lineMargin
|
|
70
|
-
: groupMargin + lineMargin + margins.top
|
|
71
|
-
}
|
|
72
|
-
y2={
|
|
73
|
-
isSmall
|
|
74
|
-
? barHeight + groupMargin - lineMargin + margins.top - 6
|
|
75
|
-
: barHeight + groupMargin + lineMargin + 2 * margins.top
|
|
76
|
-
}
|
|
90
|
+
y1={lineY1}
|
|
91
|
+
y2={lineY2}
|
|
77
92
|
/>
|
|
78
93
|
<line
|
|
79
94
|
data-testid={`${thresholdType}-line-${value}-tooltip`}
|
|
@@ -81,16 +96,8 @@ export const ThresholdLine = ({
|
|
|
81
96
|
strokeWidth={5}
|
|
82
97
|
x1={scaledValue}
|
|
83
98
|
x2={scaledValue + 1}
|
|
84
|
-
y1={
|
|
85
|
-
|
|
86
|
-
? groupMargin - lineMargin
|
|
87
|
-
: groupMargin + lineMargin + margins.top
|
|
88
|
-
}
|
|
89
|
-
y2={
|
|
90
|
-
isSmall
|
|
91
|
-
? barHeight + groupMargin - lineMargin + margins.top - 6
|
|
92
|
-
: barHeight + groupMargin + lineMargin + 2 * margins.top
|
|
93
|
-
}
|
|
99
|
+
y1={lineY1}
|
|
100
|
+
y2={lineY2}
|
|
94
101
|
onMouseEnter={onMouseEnter}
|
|
95
102
|
onMouseLeave={hideTooltip}
|
|
96
103
|
/>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Thresholds as ThresholdsModel } from '../common/models';
|
|
2
|
+
import { SingleBarProps } from './models';
|
|
2
3
|
|
|
3
4
|
import { ThresholdLine } from './ThresholdLine';
|
|
4
5
|
|
|
5
6
|
export const groupMargin = 25;
|
|
6
7
|
|
|
7
|
-
interface Props {
|
|
8
|
+
interface Props extends Pick<SingleBarProps, 'direction'> {
|
|
8
9
|
barHeight: number;
|
|
9
10
|
hideTooltip: () => void;
|
|
10
11
|
isSmall: boolean;
|
|
@@ -12,6 +13,7 @@ interface Props {
|
|
|
12
13
|
size: 'small' | 'medium';
|
|
13
14
|
thresholds: ThresholdsModel;
|
|
14
15
|
xScale: (value: number) => number;
|
|
16
|
+
textWidth?: number;
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
const Thresholds = ({
|
|
@@ -21,7 +23,9 @@ const Thresholds = ({
|
|
|
21
23
|
hideTooltip,
|
|
22
24
|
size,
|
|
23
25
|
barHeight,
|
|
24
|
-
isSmall
|
|
26
|
+
isSmall,
|
|
27
|
+
direction,
|
|
28
|
+
textWidth
|
|
25
29
|
}: Props): JSX.Element => (
|
|
26
30
|
<>
|
|
27
31
|
{thresholds.warning.map(({ value, label }) => (
|
|
@@ -36,6 +40,8 @@ const Thresholds = ({
|
|
|
36
40
|
thresholdType="warning"
|
|
37
41
|
value={value}
|
|
38
42
|
xScale={xScale}
|
|
43
|
+
direction={direction}
|
|
44
|
+
textWidth={textWidth}
|
|
39
45
|
/>
|
|
40
46
|
))}
|
|
41
47
|
{thresholds.critical.map(({ value, label }) => (
|
|
@@ -50,6 +56,8 @@ const Thresholds = ({
|
|
|
50
56
|
thresholdType="critical"
|
|
51
57
|
value={value}
|
|
52
58
|
xScale={xScale}
|
|
59
|
+
direction={direction}
|
|
60
|
+
textWidth={textWidth}
|
|
53
61
|
/>
|
|
54
62
|
))}
|
|
55
63
|
</>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import toRawQueryParameters from '../../queryParameters';
|
|
2
2
|
import { QueryParameter } from '../../queryParameters/models';
|
|
3
|
-
|
|
4
3
|
import { getSearchQueryParameterValue } from './getSearchQueryParameterValue';
|
|
5
4
|
import { BuildListingEndpointParameters, Parameters } from './models';
|
|
6
5
|
|
|
@@ -27,11 +26,25 @@ const buildEndpoint = ({ baseEndpoint, queryParameters }): string => {
|
|
|
27
26
|
return `${baseEndpoint}?${toRawQueryParameters(queryParameters)}`;
|
|
28
27
|
};
|
|
29
28
|
|
|
29
|
+
const buildCustomEndpoint = ({ baseEndpoint, queryParameters }): string => {
|
|
30
|
+
return `${baseEndpoint}&${toRawQueryParameters(queryParameters)}`;
|
|
31
|
+
};
|
|
32
|
+
|
|
30
33
|
const buildListingEndpoint = ({
|
|
31
34
|
baseEndpoint,
|
|
32
35
|
parameters,
|
|
33
|
-
customQueryParameters
|
|
36
|
+
customQueryParameters,
|
|
37
|
+
isCustomEndpoint = false
|
|
34
38
|
}: BuildListingEndpointParameters): string => {
|
|
39
|
+
if (isCustomEndpoint) {
|
|
40
|
+
return buildCustomEndpoint({
|
|
41
|
+
baseEndpoint,
|
|
42
|
+
queryParameters: [
|
|
43
|
+
...getQueryParameters({ ...parameters, customQueryParameters })
|
|
44
|
+
]
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
35
48
|
return buildEndpoint({
|
|
36
49
|
baseEndpoint,
|
|
37
50
|
queryParameters: [
|