@centreon/ui 24.10.21 → 24.10.23
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 +3 -3
- package/src/Graph/BarChart/ResponsiveBarChart.tsx +5 -5
- package/src/Graph/Chart/Chart.tsx +5 -2
- package/src/Graph/Chart/index.tsx +26 -6
- package/src/Graph/Chart/translatedLabels.ts +1 -0
- package/src/Graph/Chart/useChartData.ts +23 -2
- package/src/Graph/common/Axes/index.tsx +1 -1
- package/src/Graph/common/BaseChart/ChartSvgWrapper.tsx +23 -16
- package/src/Graph/common/Error/NoData.tsx +18 -0
- package/src/Graph/common/Grids/index.tsx +4 -4
- package/src/Graph/common/timeSeries/index.ts +44 -23
- package/src/Graph/common/timeSeries/models.ts +3 -1
- package/src/Graph/index.ts +20 -20
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@centreon/ui",
|
|
3
|
-
"version": "24.10.
|
|
3
|
+
"version": "24.10.23",
|
|
4
4
|
"description": "Centreon UI Components",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"update:deps": "pnpx npm-check-updates -i --format group",
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"url": "git+https://github.com/centreon/centreon.git"
|
|
25
25
|
},
|
|
26
26
|
"keywords": [
|
|
27
|
-
"
|
|
28
|
-
"
|
|
27
|
+
"react",
|
|
28
|
+
"centreon"
|
|
29
29
|
],
|
|
30
30
|
"author": {
|
|
31
31
|
"name": "centreon@centreon.com"
|
|
@@ -61,7 +61,7 @@ const ResponsiveBarChart = ({
|
|
|
61
61
|
|
|
62
62
|
const { classes, cx } = useTooltipStyles();
|
|
63
63
|
|
|
64
|
-
const [linesGraph, setLinesGraph] = useState<Array<Line>>(lines);
|
|
64
|
+
const [linesGraph, setLinesGraph] = useState<Array<Line>>(lines || []);
|
|
65
65
|
const graphSvgRef = useRef<SVGSVGElement | null>(null);
|
|
66
66
|
|
|
67
67
|
const [tooltipData, setTooltipData] = useAtom(tooltipDataAtom);
|
|
@@ -74,7 +74,7 @@ const ResponsiveBarChart = ({
|
|
|
74
74
|
);
|
|
75
75
|
|
|
76
76
|
const [firstUnit, secondUnit] = getUnits(displayedLines);
|
|
77
|
-
const allUnits = getUnits(lines);
|
|
77
|
+
const allUnits = getUnits(lines || []);
|
|
78
78
|
|
|
79
79
|
const { maxLeftAxisCharacters, maxRightAxisCharacters } =
|
|
80
80
|
useComputeYAxisMaxCharacters({
|
|
@@ -147,12 +147,12 @@ const ResponsiveBarChart = ({
|
|
|
147
147
|
]
|
|
148
148
|
);
|
|
149
149
|
|
|
150
|
-
const leftScale = yScalesPerUnit[firstUnit];
|
|
151
|
-
const rightScale = yScalesPerUnit[secondUnit];
|
|
150
|
+
const leftScale = yScalesPerUnit[firstUnit ?? allUnits[0]];
|
|
151
|
+
const rightScale = yScalesPerUnit[secondUnit ?? allUnits[1]];
|
|
152
152
|
|
|
153
153
|
useEffect(
|
|
154
154
|
() => {
|
|
155
|
-
setLinesGraph(lines);
|
|
155
|
+
setLinesGraph(lines || []);
|
|
156
156
|
},
|
|
157
157
|
useDeepCompare([lines])
|
|
158
158
|
);
|
|
@@ -194,8 +194,11 @@ const Chart = ({
|
|
|
194
194
|
]
|
|
195
195
|
);
|
|
196
196
|
|
|
197
|
-
const
|
|
198
|
-
const
|
|
197
|
+
const fallbackLeftUnit = axis?.axisYLeft?.unit ?? firstUnit ?? allUnits[0];
|
|
198
|
+
const fallbackRightUnit = axis?.axisYRight?.unit ?? secondUnit ?? allUnits[1];
|
|
199
|
+
|
|
200
|
+
const leftScale = yScalesPerUnit[fallbackLeftUnit];
|
|
201
|
+
const rightScale = yScalesPerUnit[fallbackRightUnit];
|
|
199
202
|
|
|
200
203
|
const linesDisplayedAsLine = useMemo(
|
|
201
204
|
() =>
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import dayjs from "dayjs";
|
|
2
|
-
import { memo, useRef } from "react";
|
|
3
2
|
import "dayjs/locale/en";
|
|
4
3
|
import "dayjs/locale/es";
|
|
5
4
|
import "dayjs/locale/fr";
|
|
6
5
|
import "dayjs/locale/pt";
|
|
6
|
+
import { memo, useRef } from "react";
|
|
7
|
+
|
|
8
|
+
import { NoData } from "@centreon/ui";
|
|
9
|
+
|
|
7
10
|
import localizedFormat from "dayjs/plugin/localizedFormat";
|
|
8
11
|
import timezonePlugin from "dayjs/plugin/timezone";
|
|
9
12
|
import utcPlugin from "dayjs/plugin/utc";
|
|
@@ -31,6 +34,10 @@ interface Props extends Partial<LineChartProps> {
|
|
|
31
34
|
thresholds?: Thresholds;
|
|
32
35
|
getRef?: (ref: React.RefObject<HTMLDivElement | null>) => void;
|
|
33
36
|
containerStyle?: string;
|
|
37
|
+
transformMatrix?: {
|
|
38
|
+
fx?: (pointX: number) => number;
|
|
39
|
+
fy?: (pointY: number) => number;
|
|
40
|
+
};
|
|
34
41
|
}
|
|
35
42
|
|
|
36
43
|
const WrapperChart = ({
|
|
@@ -52,8 +59,8 @@ const WrapperChart = ({
|
|
|
52
59
|
annotationEvent,
|
|
53
60
|
legend = {
|
|
54
61
|
display: true,
|
|
55
|
-
mode:
|
|
56
|
-
placement:
|
|
62
|
+
mode: "grid",
|
|
63
|
+
placement: "bottom",
|
|
57
64
|
},
|
|
58
65
|
header,
|
|
59
66
|
lineStyle,
|
|
@@ -62,11 +69,14 @@ const WrapperChart = ({
|
|
|
62
69
|
thresholdUnit,
|
|
63
70
|
limitLegend,
|
|
64
71
|
getRef,
|
|
72
|
+
transformMatrix,
|
|
73
|
+
additionalLines,
|
|
74
|
+
min,
|
|
75
|
+
max,
|
|
76
|
+
boundariesUnit,
|
|
65
77
|
...rest
|
|
66
78
|
}: Props): JSX.Element | null => {
|
|
67
79
|
const { classes, cx } = useChartStyles();
|
|
68
|
-
const ref = useRef<HTMLDivElement | null>(null);
|
|
69
|
-
|
|
70
80
|
const { adjustedData } = useChartData({ data, end, start });
|
|
71
81
|
|
|
72
82
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
@@ -97,13 +107,17 @@ const WrapperChart = ({
|
|
|
97
107
|
);
|
|
98
108
|
}
|
|
99
109
|
|
|
110
|
+
if (!adjustedData) {
|
|
111
|
+
return <NoData />;
|
|
112
|
+
}
|
|
113
|
+
|
|
100
114
|
return (
|
|
101
115
|
<div
|
|
102
116
|
ref={combinedRef}
|
|
103
117
|
className={cx(classes.wrapperContainer, rest?.containerStyle)}
|
|
104
118
|
>
|
|
105
119
|
{!responsiveHeight || !data ? (
|
|
106
|
-
<Loading height={height ||
|
|
120
|
+
<Loading height={height || "100%"} width={width} />
|
|
107
121
|
) : (
|
|
108
122
|
<Chart
|
|
109
123
|
annotationEvent={annotationEvent}
|
|
@@ -125,6 +139,12 @@ const WrapperChart = ({
|
|
|
125
139
|
tooltip={tooltip}
|
|
126
140
|
width={width || responsiveWidth || 0}
|
|
127
141
|
zoomPreview={zoomPreview}
|
|
142
|
+
skipIntersectionObserver={rest.skipIntersectionObserver}
|
|
143
|
+
additionalLines={additionalLines}
|
|
144
|
+
transformMatrix={transformMatrix}
|
|
145
|
+
min={min}
|
|
146
|
+
max={max}
|
|
147
|
+
boundariesUnit={boundariesUnit}
|
|
128
148
|
/>
|
|
129
149
|
)}
|
|
130
150
|
</div>
|
|
@@ -31,6 +31,15 @@ interface Props {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
const getBoolean = (value) => Boolean(Number(value));
|
|
34
|
+
const defaultDsData = {
|
|
35
|
+
ds_color_line: '#000000',
|
|
36
|
+
ds_filled: false,
|
|
37
|
+
ds_invert: false,
|
|
38
|
+
ds_legend: '',
|
|
39
|
+
ds_order: '0',
|
|
40
|
+
ds_stack: '0',
|
|
41
|
+
ds_transparency: 80
|
|
42
|
+
};
|
|
34
43
|
|
|
35
44
|
const useGraphData = ({ data, end, start }: Props): GraphDataResult => {
|
|
36
45
|
const adjustedDataRef = useRef<Data>();
|
|
@@ -44,9 +53,21 @@ const useGraphData = ({ data, end, start }: Props): GraphDataResult => {
|
|
|
44
53
|
return undefined;
|
|
45
54
|
}
|
|
46
55
|
|
|
56
|
+
const metricsWithValidDsData = (data?.metrics || []).map((metric) => ({
|
|
57
|
+
...metric,
|
|
58
|
+
ds_data: {
|
|
59
|
+
...defaultDsData,
|
|
60
|
+
...(metric?.ds_data || {}),
|
|
61
|
+
ds_color_area:
|
|
62
|
+
metric?.ds_data?.ds_color_area ??
|
|
63
|
+
metric?.ds_data?.ds_color_line ??
|
|
64
|
+
defaultDsData.ds_color_line
|
|
65
|
+
}
|
|
66
|
+
}));
|
|
67
|
+
|
|
47
68
|
const metricsGroupedByColor = groupBy(
|
|
48
|
-
(metric) => metric.ds_data
|
|
49
|
-
)(
|
|
69
|
+
(metric) => metric.ds_data?.ds_color_line || '#000000'
|
|
70
|
+
)(metricsWithValidDsData);
|
|
50
71
|
|
|
51
72
|
const newMetrics = Object.entries(metricsGroupedByColor).map(
|
|
52
73
|
([color, value]) => {
|
|
@@ -59,7 +59,7 @@ const Axes = ({
|
|
|
59
59
|
const formatAxisTick = (tick): string =>
|
|
60
60
|
format({ date: new Date(tick), formatString: tickFormat });
|
|
61
61
|
|
|
62
|
-
const displayAxisRight = !isNil(secondUnit);
|
|
62
|
+
const displayAxisRight = !isNil(secondUnit) && !isNil(rightScale);
|
|
63
63
|
|
|
64
64
|
const AxisBottom = isHorizontal ? Axis.AxisBottom : Axis.AxisLeft;
|
|
65
65
|
const AxisLeft = isHorizontal ? Axis.AxisLeft : Axis.AxisTop;
|
|
@@ -49,6 +49,11 @@ const ChartSvgWrapper = ({
|
|
|
49
49
|
hasSecondUnit
|
|
50
50
|
}: Props): JSX.Element => {
|
|
51
51
|
const isHorizontal = equals(orientation, 'horizontal');
|
|
52
|
+
const hasValidLeftScale = Boolean(leftScale);
|
|
53
|
+
const hasValidXScale = Boolean(xScale);
|
|
54
|
+
const canRenderAxes = hasValidLeftScale && hasValidXScale;
|
|
55
|
+
const canRenderGridRows = Boolean(isHorizontal ? leftScale : xScale);
|
|
56
|
+
const canRenderGridColumns = Boolean(isHorizontal ? xScale : leftScale);
|
|
52
57
|
|
|
53
58
|
return (
|
|
54
59
|
<svg
|
|
@@ -64,7 +69,7 @@ const ChartSvgWrapper = ({
|
|
|
64
69
|
}
|
|
65
70
|
top={margin.top}
|
|
66
71
|
>
|
|
67
|
-
{showGridLines && (
|
|
72
|
+
{showGridLines && (canRenderGridRows || canRenderGridColumns) && (
|
|
68
73
|
<Grids
|
|
69
74
|
gridLinesType={gridLinesType}
|
|
70
75
|
height={graphHeight - margin.top}
|
|
@@ -73,21 +78,23 @@ const ChartSvgWrapper = ({
|
|
|
73
78
|
xScale={isHorizontal ? xScale : leftScale}
|
|
74
79
|
/>
|
|
75
80
|
)}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
81
|
+
{canRenderAxes && (
|
|
82
|
+
<Axes
|
|
83
|
+
allUnits={allUnits}
|
|
84
|
+
data={{
|
|
85
|
+
baseAxis: base,
|
|
86
|
+
lines: displayedLines,
|
|
87
|
+
timeSeries,
|
|
88
|
+
...axis
|
|
89
|
+
}}
|
|
90
|
+
height={graphHeight}
|
|
91
|
+
leftScale={leftScale}
|
|
92
|
+
orientation={orientation}
|
|
93
|
+
rightScale={rightScale}
|
|
94
|
+
width={graphWidth}
|
|
95
|
+
xScale={xScale}
|
|
96
|
+
/>
|
|
97
|
+
)}
|
|
91
98
|
{children}
|
|
92
99
|
</Group.Group>
|
|
93
100
|
</svg>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Typography } from '@mui/material';
|
|
2
|
+
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
|
|
5
|
+
import { labelNoDataForThisPeriod } from '../../Chart/translatedLabels';
|
|
6
|
+
|
|
7
|
+
const NoData = () => {
|
|
8
|
+
const { t } = useTranslation();
|
|
9
|
+
return (
|
|
10
|
+
<div className={'flex items-center justify-center h-full'}>
|
|
11
|
+
<Typography align="center" variant="body1">
|
|
12
|
+
{t(labelNoDataForThisPeriod)}
|
|
13
|
+
</Typography>
|
|
14
|
+
</div>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default NoData;
|
|
@@ -8,9 +8,9 @@ import { ChartAxis } from '../../Chart/models';
|
|
|
8
8
|
|
|
9
9
|
interface Props extends Pick<ChartAxis, 'gridLinesType'> {
|
|
10
10
|
height: number;
|
|
11
|
-
leftScale
|
|
11
|
+
leftScale?: ScaleLinear<number, number>;
|
|
12
12
|
width: number;
|
|
13
|
-
xScale
|
|
13
|
+
xScale?: ScaleLinear<number, number>;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
const Grids = ({
|
|
@@ -31,10 +31,10 @@ const Grids = ({
|
|
|
31
31
|
|
|
32
32
|
return (
|
|
33
33
|
<g>
|
|
34
|
-
{displayRows && (
|
|
34
|
+
{displayRows && leftScale && (
|
|
35
35
|
<Grid.GridRows height={height} scale={leftScale} width={width} />
|
|
36
36
|
)}
|
|
37
|
-
{displayColumns && (
|
|
37
|
+
{displayColumns && xScale && (
|
|
38
38
|
<Grid.GridColumns height={height} scale={xScale} width={width} />
|
|
39
39
|
)}
|
|
40
40
|
</g>
|
|
@@ -53,6 +53,17 @@ interface TimeTickWithMetrics {
|
|
|
53
53
|
timeTick: string;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
const defaultDsData = {
|
|
57
|
+
ds_color_line: '#000000',
|
|
58
|
+
ds_filled: false,
|
|
59
|
+
ds_invert: false,
|
|
60
|
+
ds_legend: '',
|
|
61
|
+
ds_order: '0',
|
|
62
|
+
ds_stack: '0',
|
|
63
|
+
ds_stack_key: null,
|
|
64
|
+
ds_transparency: 80
|
|
65
|
+
};
|
|
66
|
+
|
|
56
67
|
const toTimeTickWithMetrics = ({
|
|
57
68
|
metrics,
|
|
58
69
|
times
|
|
@@ -119,29 +130,39 @@ const toLine = ({
|
|
|
119
130
|
maximum_value,
|
|
120
131
|
metric_id,
|
|
121
132
|
displayAs
|
|
122
|
-
}: Metric): Line =>
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
133
|
+
}: Metric): Line => {
|
|
134
|
+
const safeDsData = {
|
|
135
|
+
...defaultDsData,
|
|
136
|
+
...(ds_data || {}),
|
|
137
|
+
ds_color_area:
|
|
138
|
+
ds_data?.ds_color_area ?? ds_data?.ds_color_line ?? defaultDsData.ds_color_line
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
areaColor: safeDsData.ds_color_area,
|
|
143
|
+
average_value,
|
|
144
|
+
color: safeDsData.ds_color_line,
|
|
145
|
+
display: true,
|
|
146
|
+
displayAs,
|
|
147
|
+
filled: safeDsData.ds_filled,
|
|
148
|
+
highlight: undefined,
|
|
149
|
+
invert: safeDsData.ds_invert,
|
|
150
|
+
legend: safeDsData.ds_legend,
|
|
151
|
+
lineColor: safeDsData.ds_color_line,
|
|
152
|
+
maximum_value,
|
|
153
|
+
metric,
|
|
154
|
+
metric_id,
|
|
155
|
+
minimum_value,
|
|
156
|
+
name: legend,
|
|
157
|
+
stackKey: safeDsData.ds_stack_key || null,
|
|
158
|
+
stackOrder:
|
|
159
|
+
equals(safeDsData.ds_stack, '1') || equals(safeDsData.ds_stack, true)
|
|
160
|
+
? Number.parseInt(safeDsData.ds_order || '0', 10)
|
|
161
|
+
: null,
|
|
162
|
+
transparency: safeDsData.ds_transparency,
|
|
163
|
+
unit
|
|
164
|
+
};
|
|
165
|
+
};
|
|
145
166
|
|
|
146
167
|
const getLineData = (graphData: LineChartData): Array<Line> =>
|
|
147
168
|
map(toLine, graphData.metrics);
|
|
@@ -9,7 +9,8 @@ interface DsData {
|
|
|
9
9
|
ds_invert: string | null;
|
|
10
10
|
ds_legend: string | null;
|
|
11
11
|
ds_order: string | null;
|
|
12
|
-
ds_stack: string | null;
|
|
12
|
+
ds_stack: string | boolean | null;
|
|
13
|
+
ds_stack_key?: string | null;
|
|
13
14
|
ds_transparency: number;
|
|
14
15
|
}
|
|
15
16
|
|
|
@@ -56,6 +57,7 @@ export interface Line {
|
|
|
56
57
|
minimum_value: number | null;
|
|
57
58
|
name: string;
|
|
58
59
|
stackOrder: number | null;
|
|
60
|
+
stackKey: string | null;
|
|
59
61
|
transparency: number;
|
|
60
62
|
unit: string;
|
|
61
63
|
}
|
package/src/Graph/index.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
export type { ParentSizeProps } from
|
|
2
|
-
export { default as
|
|
3
|
-
export {
|
|
4
|
-
export { default as
|
|
5
|
-
export { default as
|
|
6
|
-
export
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
9
|
-
export { default as
|
|
10
|
-
|
|
11
|
-
export
|
|
12
|
-
export {
|
|
13
|
-
export {
|
|
14
|
-
export {
|
|
15
|
-
export
|
|
16
|
-
export
|
|
17
|
-
export
|
|
18
|
-
export
|
|
19
|
-
export
|
|
20
|
-
export * from
|
|
1
|
+
export type { ParentSizeProps } from "@visx/responsive/lib/components/ParentSize";
|
|
2
|
+
export { default as BarChart } from "./BarChart/BarChart";
|
|
3
|
+
export { BarStack } from "./BarStack";
|
|
4
|
+
export { default as LineChart } from "./Chart";
|
|
5
|
+
export { default as ThresholdLines } from "./Chart/BasicComponents/Lines/Threshold";
|
|
6
|
+
export * from "./Chart/models";
|
|
7
|
+
export { default as useLineChartData } from "./Chart/useChartData";
|
|
8
|
+
export { default as Header } from "./common/BaseChart/Header";
|
|
9
|
+
export { default as NoData } from "./common/Error/NoData";
|
|
10
|
+
export type { LineChartData, Threshold, Thresholds } from "./common/models";
|
|
11
|
+
export * from "./common/timeSeries";
|
|
12
|
+
export type { Metric } from "./common/timeSeries/models";
|
|
13
|
+
export { Gauge } from "./Gauge";
|
|
14
|
+
export { HeatMap } from "./HeatMap";
|
|
15
|
+
export { PieChart } from "./PieChart";
|
|
16
|
+
export * from "./PieChart/models";
|
|
17
|
+
export { SingleBar } from "./SingleBar";
|
|
18
|
+
export { Text as GraphText } from "./Text";
|
|
19
|
+
export { Timeline } from "./Timeline";
|
|
20
|
+
export * from "./Tree";
|