@centreon/ui 24.6.3 → 24.6.4

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.
Files changed (54) hide show
  1. package/package.json +1 -1
  2. package/src/Graph/BarChart/BarChart.cypress.spec.tsx +233 -0
  3. package/src/Graph/BarChart/BarChart.stories.tsx +213 -0
  4. package/src/Graph/BarChart/BarChart.tsx +101 -0
  5. package/src/Graph/BarChart/BarGroup.tsx +246 -0
  6. package/src/Graph/BarChart/BarStack.tsx +126 -0
  7. package/src/Graph/BarChart/ResponsiveBarChart.tsx +263 -0
  8. package/src/Graph/BarChart/SingleBar.tsx +62 -0
  9. package/src/Graph/BarChart/Tooltip/BarChartTooltip.tsx +122 -0
  10. package/src/Graph/BarChart/Tooltip/useBarChartTooltipStyles.ts +28 -0
  11. package/src/Graph/BarChart/atoms.ts +5 -0
  12. package/src/Graph/BarChart/models.ts +21 -0
  13. package/src/Graph/BarChart/useBarChartStyles.tsx +5 -0
  14. package/src/Graph/BarChart/useBarStack.ts +114 -0
  15. package/src/Graph/BarChart/useSingleBar.ts +199 -0
  16. package/src/Graph/Gauge/Gauge.cypress.spec.tsx +1 -1
  17. package/src/Graph/Gauge/Gauge.stories.tsx +1 -1
  18. package/src/Graph/LineChart/LineChart.cypress.spec.tsx +4 -4
  19. package/src/Graph/LineChart/LineChart.styles.ts +0 -5
  20. package/src/Graph/LineChart/LineChart.tsx +118 -122
  21. package/src/Graph/LineChart/index.stories.tsx +12 -12
  22. package/src/Graph/SingleBar/SingleBar.cypress.spec.tsx +1 -1
  23. package/src/Graph/SingleBar/SingleBar.stories.tsx +1 -1
  24. package/src/Graph/Text/Text.cypress.spec.tsx +1 -1
  25. package/src/Graph/Text/Text.stories.tsx +1 -1
  26. package/src/Graph/common/Axes/index.tsx +40 -13
  27. package/src/Graph/common/BaseChart/BaseChart.tsx +25 -6
  28. package/src/Graph/common/BaseChart/ChartSvgWrapper.tsx +15 -4
  29. package/src/Graph/{LineChart → common/BaseChart}/Header/index.tsx +3 -3
  30. package/src/Graph/common/BaseChart/Header/models.ts +4 -0
  31. package/src/Graph/common/BaseChart/Header/useHeaderStyles.ts +9 -0
  32. package/src/Graph/common/BaseChart/useBaseChartStyles.ts +6 -0
  33. package/src/Graph/{LineChart/BasicComponents → common/Thresholds}/ThresholdLine.tsx +20 -10
  34. package/src/Graph/{LineChart/BasicComponents → common/Thresholds}/Thresholds.tsx +8 -4
  35. package/src/Graph/common/timeSeries/index.ts +33 -11
  36. package/src/Graph/common/timeSeries/models.ts +1 -0
  37. package/src/Graph/common/useTooltipStyles.ts +1 -0
  38. package/src/Graph/mockedData/pingService.json +203 -0
  39. package/src/Graph/mockedData/pingServiceMixedStacked.json +203 -0
  40. package/src/Graph/mockedData/pingServiceStacked.json +203 -0
  41. /package/src/Graph/{LineChart/mockedData → mockedData}/annotationData.json +0 -0
  42. /package/src/Graph/{LineChart/mockedData → mockedData}/curvesWithSameColor.json +0 -0
  43. /package/src/Graph/{LineChart/mockedData → mockedData}/exclusionPeriodFirstPeriod.json +0 -0
  44. /package/src/Graph/{LineChart/mockedData → mockedData}/exclusionPeriodSecondPeriod.json +0 -0
  45. /package/src/Graph/{LineChart/mockedData → mockedData}/exclusionPeriodThirdPeriod.json +0 -0
  46. /package/src/Graph/{LineChart/mockedData → mockedData}/lastDay.json +0 -0
  47. /package/src/Graph/{LineChart/mockedData → mockedData}/lastDayAreaStack.json +0 -0
  48. /package/src/Graph/{LineChart/mockedData → mockedData}/lastDayForward.json +0 -0
  49. /package/src/Graph/{LineChart/mockedData → mockedData}/lastDayThreshold.json +0 -0
  50. /package/src/Graph/{LineChart/mockedData → mockedData}/lastDayWithIncompleteValues.json +0 -0
  51. /package/src/Graph/{LineChart/mockedData → mockedData}/lastDayWithNullValues.json +0 -0
  52. /package/src/Graph/{LineChart/mockedData → mockedData}/lastMonth.json +0 -0
  53. /package/src/Graph/{LineChart/mockedData → mockedData}/lastWeek.json +0 -0
  54. /package/src/Graph/{LineChart/mockedData → mockedData}/zoomPreview.json +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centreon/ui",
3
- "version": "24.6.3",
3
+ "version": "24.6.4",
4
4
  "description": "Centreon UI Components",
5
5
  "scripts": {
6
6
  "update:deps": "pnpx npm-check-updates -i --format group",
@@ -0,0 +1,233 @@
1
+ import dayjs from 'dayjs';
2
+
3
+ import dataPingService from '../mockedData/pingService.json';
4
+ import dataPingServiceStacked from '../mockedData/pingServiceStacked.json';
5
+ import dataPingServiceMixedStacked from '../mockedData/pingServiceMixedStacked.json';
6
+
7
+ import BarChart, { BarChartProps } from './BarChart';
8
+
9
+ const defaultStart = new Date(
10
+ dayjs(Date.now()).subtract(24, 'hour').toDate().getTime()
11
+ ).toISOString();
12
+
13
+ const defaultEnd = new Date(Date.now()).toISOString();
14
+
15
+ const defaultArgs = {
16
+ end: defaultEnd,
17
+ height: 500,
18
+ loading: false,
19
+ start: defaultStart
20
+ };
21
+
22
+ const initialize = ({
23
+ data = dataPingService,
24
+ legend,
25
+ tooltip,
26
+ axis,
27
+ orientation,
28
+ barStyle
29
+ }: Pick<
30
+ BarChartProps,
31
+ 'data' | 'legend' | 'axis' | 'barStyle' | 'orientation' | 'tooltip'
32
+ >): void => {
33
+ cy.mount({
34
+ Component: (
35
+ <div style={{ height: '100%', width: '100%' }}>
36
+ <BarChart
37
+ axis={axis}
38
+ barStyle={barStyle}
39
+ data={data}
40
+ legend={legend}
41
+ orientation={orientation ?? 'horizontal'}
42
+ tooltip={tooltip}
43
+ {...defaultArgs}
44
+ />
45
+ </div>
46
+ )
47
+ });
48
+ };
49
+
50
+ describe('Bar chart', () => {
51
+ ['horizontal', 'vertical'].forEach((orientation) => {
52
+ it(`displays the bar chart ${orientation}ly`, () => {
53
+ initialize({ orientation });
54
+
55
+ cy.contains('0 ms').should('be.visible');
56
+ cy.contains('20').should('be.visible');
57
+ cy.contains(':40 AM').should('be.visible');
58
+
59
+ cy.makeSnapshot();
60
+ });
61
+
62
+ it(`displays the bar chart ${orientation}ly centered in zero`, () => {
63
+ initialize({ axis: { isCenteredZero: true }, orientation });
64
+
65
+ cy.contains('0 ms').should('be.visible');
66
+ cy.contains('20').should('be.visible');
67
+ cy.contains(':40 AM').should('be.visible');
68
+
69
+ cy.makeSnapshot();
70
+ });
71
+
72
+ it(`displays the stacked bar chart ${orientation}ly`, () => {
73
+ initialize({ data: dataPingServiceStacked, orientation });
74
+
75
+ cy.contains('0 ms').should('be.visible');
76
+ cy.contains('20').should('be.visible');
77
+ cy.contains(':40 AM').should('be.visible');
78
+
79
+ cy.makeSnapshot();
80
+ });
81
+
82
+ it(`displays bar chart ${orientation}ly with a mix of stacked and non-stacked data`, () => {
83
+ initialize({ data: dataPingServiceMixedStacked, orientation });
84
+
85
+ cy.contains('0 ms').should('be.visible');
86
+ cy.contains('20').should('be.visible');
87
+ cy.contains(':40 AM').should('be.visible');
88
+
89
+ cy.makeSnapshot();
90
+ });
91
+
92
+ it(`displays the stacked bar chart ${orientation}ly centered in zero`, () => {
93
+ initialize({
94
+ axis: { isCenteredZero: true },
95
+ data: dataPingServiceStacked,
96
+ orientation
97
+ });
98
+
99
+ cy.contains('0 ms').should('be.visible');
100
+ cy.contains('20').should('be.visible');
101
+ cy.contains(':40 AM').should('be.visible');
102
+
103
+ cy.makeSnapshot();
104
+ });
105
+
106
+ it(`displays bar chart ${orientation}ly with a mix of stacked and non-stacked data centered in zero`, () => {
107
+ initialize({
108
+ axis: { isCenteredZero: true },
109
+ data: dataPingServiceMixedStacked,
110
+ orientation
111
+ });
112
+
113
+ cy.contains('0 ms').should('be.visible');
114
+ cy.contains('20').should('be.visible');
115
+ cy.contains(':40 AM').should('be.visible');
116
+
117
+ cy.makeSnapshot();
118
+ });
119
+
120
+ it(`displays bar chart ${orientation}ly with a custom style`, () => {
121
+ initialize({
122
+ barStyle: { opacity: 0.5, radius: 0.5 },
123
+ data: dataPingServiceMixedStacked,
124
+ orientation
125
+ });
126
+
127
+ cy.contains('0 ms').should('be.visible');
128
+ cy.contains('20').should('be.visible');
129
+ cy.contains(':40 AM').should('be.visible');
130
+
131
+ cy.makeSnapshot();
132
+ });
133
+ });
134
+
135
+ it('displays a tooltip when a single bar is hovered', () => {
136
+ initialize({
137
+ orientation: 'horizontal'
138
+ });
139
+
140
+ cy.contains('0 ms').should('be.visible');
141
+ cy.contains('20').should('be.visible');
142
+ cy.contains(':40 AM').should('be.visible');
143
+
144
+ cy.findByTestId('single-bar-3-2-0.11372').realHover();
145
+
146
+ cy.contains('06/19/2024').should('be.visible');
147
+ cy.contains('Centreon-Server: Round-Trip Maximum Time').should(
148
+ 'be.visible'
149
+ );
150
+ cy.contains('0.11 ms').should('be.visible');
151
+
152
+ cy.makeSnapshot();
153
+ });
154
+
155
+ it('does not display a tooltip when a bar is hovered and a props is set', () => {
156
+ initialize({
157
+ data: dataPingServiceStacked,
158
+ orientation: 'horizontal',
159
+ tooltip: {
160
+ mode: 'hidden',
161
+ sortOrder: 'descending'
162
+ }
163
+ });
164
+
165
+ cy.contains('0 ms').should('be.visible');
166
+ cy.contains('20').should('be.visible');
167
+ cy.contains(':40 AM').should('be.visible');
168
+
169
+ cy.findByTestId('stacked-bar-1-0-0.05296').realHover();
170
+
171
+ cy.contains('06/19/2024').should('not.exist');
172
+
173
+ cy.makeSnapshot();
174
+ });
175
+
176
+ it('displays a tooltip when a stacked bar is hovered', () => {
177
+ initialize({
178
+ data: dataPingServiceStacked,
179
+ orientation: 'horizontal',
180
+ tooltip: {
181
+ mode: 'all',
182
+ sortOrder: 'ascending'
183
+ }
184
+ });
185
+
186
+ cy.contains('0 ms').should('be.visible');
187
+ cy.contains('20').should('be.visible');
188
+ cy.contains(':40 AM').should('be.visible');
189
+
190
+ cy.findByTestId('stacked-bar-1-0-0.05296').realHover();
191
+
192
+ cy.contains('06/19/2024').should('be.visible');
193
+ cy.contains('Centreon-Server: Round-Trip Maximum Time').should(
194
+ 'be.visible'
195
+ );
196
+ cy.contains('Centreon-Server: Round-Trip Average Time').should(
197
+ 'be.visible'
198
+ );
199
+ cy.contains('Centreon-Server: Round-Trip Minimum Time').should(
200
+ 'be.visible'
201
+ );
202
+ cy.contains('0.05 ms').should('be.visible');
203
+ cy.contains('0.02 ms').should('be.visible');
204
+ cy.contains('0.11 ms').should('be.visible');
205
+
206
+ cy.makeSnapshot();
207
+ });
208
+
209
+ it('displays a tooltip with a single metric when a stacked bar is hovered and a prop is set', () => {
210
+ initialize({
211
+ data: dataPingServiceStacked,
212
+ orientation: 'horizontal',
213
+ tooltip: {
214
+ mode: 'single',
215
+ sortOrder: 'descending'
216
+ }
217
+ });
218
+
219
+ cy.contains('0 ms').should('be.visible');
220
+ cy.contains('20').should('be.visible');
221
+ cy.contains(':40 AM').should('be.visible');
222
+
223
+ cy.findByTestId('stacked-bar-1-0-0.05296').realHover();
224
+
225
+ cy.contains('06/19/2024').should('be.visible');
226
+ cy.contains('Centreon-Server: Round-Trip Average Time').should(
227
+ 'be.visible'
228
+ );
229
+ cy.contains('0.05 ms').should('be.visible');
230
+
231
+ cy.makeSnapshot();
232
+ });
233
+ });
@@ -0,0 +1,213 @@
1
+ import { Meta, StoryObj } from '@storybook/react';
2
+ import dayjs from 'dayjs';
3
+
4
+ import { LineChartData } from '../common/models';
5
+ import dataPingService from '../mockedData/pingService.json';
6
+ import dataPingServiceStacked from '../mockedData/pingServiceStacked.json';
7
+ import dataPingServiceMixedStacked from '../mockedData/pingServiceMixedStacked.json';
8
+
9
+ import BarChart from './BarChart';
10
+
11
+ const meta: Meta<typeof BarChart> = {
12
+ component: BarChart
13
+ };
14
+ export default meta;
15
+
16
+ type Story = StoryObj<typeof BarChart>;
17
+
18
+ const defaultStart = new Date(
19
+ dayjs(Date.now()).subtract(24, 'hour').toDate().getTime()
20
+ ).toISOString();
21
+
22
+ const defaultEnd = new Date(Date.now()).toISOString();
23
+
24
+ const defaultArgs = {
25
+ end: defaultEnd,
26
+ height: 500,
27
+ loading: false,
28
+ start: defaultStart
29
+ };
30
+
31
+ const Template = (args): JSX.Element => (
32
+ <BarChart data={dataPingService as unknown as LineChartData} {...args} />
33
+ );
34
+
35
+ export const Default: Story = {
36
+ args: defaultArgs,
37
+ render: Template
38
+ };
39
+
40
+ export const withCenteredZero: Story = {
41
+ args: {
42
+ ...defaultArgs,
43
+ axis: {
44
+ isCenteredZero: true
45
+ }
46
+ },
47
+ render: Template
48
+ };
49
+
50
+ export const vertical: Story = {
51
+ args: {
52
+ ...defaultArgs,
53
+ height: 800,
54
+ orientation: 'vertical'
55
+ },
56
+ render: Template
57
+ };
58
+
59
+ export const verticalCenteredZero: Story = {
60
+ args: {
61
+ ...defaultArgs,
62
+ axis: {
63
+ isCenteredZero: true
64
+ },
65
+ height: 800,
66
+ orientation: 'vertical'
67
+ },
68
+ render: Template
69
+ };
70
+
71
+ export const stacked: Story = {
72
+ args: {
73
+ ...defaultArgs,
74
+ data: dataPingServiceStacked
75
+ },
76
+ render: Template
77
+ };
78
+
79
+ export const stackedVertical: Story = {
80
+ args: {
81
+ ...defaultArgs,
82
+ data: dataPingServiceStacked,
83
+ height: 800,
84
+ orientation: 'vertical'
85
+ },
86
+ render: Template
87
+ };
88
+
89
+ export const stackedCenteredZero: Story = {
90
+ args: {
91
+ ...defaultArgs,
92
+ axis: {
93
+ isCenteredZero: true
94
+ },
95
+ data: dataPingServiceStacked
96
+ },
97
+ render: Template
98
+ };
99
+
100
+ export const stackedVerticalCenteredZero: Story = {
101
+ args: {
102
+ ...defaultArgs,
103
+ axis: {
104
+ isCenteredZero: true
105
+ },
106
+ data: dataPingServiceStacked,
107
+ height: 800,
108
+ orientation: 'vertical'
109
+ },
110
+ render: Template
111
+ };
112
+
113
+ export const thresholds: Story = {
114
+ args: {
115
+ ...defaultArgs,
116
+ thresholdUnit: 'ms',
117
+ thresholds: {
118
+ critical: [
119
+ {
120
+ label: 'critical 1',
121
+ value: 0.1
122
+ }
123
+ ],
124
+ enabled: true,
125
+ warning: [
126
+ {
127
+ label: 'warning 1',
128
+ value: 0.05
129
+ }
130
+ ]
131
+ }
132
+ },
133
+ render: Template
134
+ };
135
+
136
+ export const thresholdsVertical: Story = {
137
+ args: {
138
+ ...defaultArgs,
139
+ axis: {
140
+ isCenteredZero: true
141
+ },
142
+ orientation: 'vertical',
143
+ thresholdUnit: 'ms',
144
+ thresholds: {
145
+ critical: [
146
+ {
147
+ label: 'critical 1',
148
+ value: 0.1
149
+ }
150
+ ],
151
+ enabled: true,
152
+ warning: [
153
+ {
154
+ label: 'warning 1',
155
+ value: 0.05
156
+ }
157
+ ]
158
+ }
159
+ },
160
+ render: Template
161
+ };
162
+
163
+ export const thresholdStacked: Story = {
164
+ args: {
165
+ ...defaultArgs,
166
+ data: dataPingServiceStacked,
167
+ thresholdUnit: 'ms',
168
+ thresholds: {
169
+ critical: [
170
+ {
171
+ label: 'critical 1',
172
+ value: 0.1
173
+ }
174
+ ],
175
+ enabled: true,
176
+ warning: [
177
+ {
178
+ label: 'warning 1',
179
+ value: 0.05
180
+ }
181
+ ]
182
+ }
183
+ },
184
+ render: Template
185
+ };
186
+
187
+ export const customBarStyle: Story = {
188
+ args: {
189
+ ...defaultArgs,
190
+ barStyle: {
191
+ opacity: 0.5,
192
+ radius: 0.5
193
+ }
194
+ },
195
+ render: Template
196
+ };
197
+
198
+ export const mixedStacked: Story = {
199
+ args: {
200
+ ...defaultArgs,
201
+ data: dataPingServiceMixedStacked
202
+ },
203
+ render: Template
204
+ };
205
+
206
+ export const mixedStackedVertical: Story = {
207
+ args: {
208
+ ...defaultArgs,
209
+ data: dataPingServiceMixedStacked,
210
+ orientation: 'vertical'
211
+ },
212
+ render: Template
213
+ };
@@ -0,0 +1,101 @@
1
+ import { useRef } from 'react';
2
+
3
+ import dayjs from 'dayjs';
4
+ import 'dayjs/locale/en';
5
+ import 'dayjs/locale/es';
6
+ import 'dayjs/locale/fr';
7
+ import 'dayjs/locale/pt';
8
+ import localizedFormat from 'dayjs/plugin/localizedFormat';
9
+ import timezonePlugin from 'dayjs/plugin/timezone';
10
+ import utcPlugin from 'dayjs/plugin/utc';
11
+
12
+ import { Box } from '@mui/material';
13
+
14
+ import { LineChartProps } from '../LineChart/models';
15
+ import { LineChartData, Thresholds } from '../common/models';
16
+ import { ParentSize } from '../../ParentSize';
17
+ import useLineChartData from '../LineChart/useLineChartData';
18
+ import LoadingSkeleton from '../LineChart/LoadingSkeleton';
19
+
20
+ import ResponsiveBarChart from './ResponsiveBarChart';
21
+ import { BarStyle } from './models';
22
+
23
+ dayjs.extend(localizedFormat);
24
+ dayjs.extend(utcPlugin);
25
+ dayjs.extend(timezonePlugin);
26
+
27
+ export interface BarChartProps
28
+ extends Partial<
29
+ Pick<LineChartProps, 'tooltip' | 'legend' | 'height' | 'axis' | 'header'>
30
+ > {
31
+ barStyle?: BarStyle;
32
+ data?: LineChartData;
33
+ end: string;
34
+ limitLegend?: false | number;
35
+ loading: boolean;
36
+ orientation: 'vertical' | 'horizontal';
37
+ start: string;
38
+ thresholdUnit?: string;
39
+ thresholds?: Thresholds;
40
+ }
41
+
42
+ const BarChart = ({
43
+ data,
44
+ end,
45
+ start,
46
+ height = 500,
47
+ tooltip,
48
+ axis,
49
+ legend,
50
+ loading,
51
+ limitLegend,
52
+ thresholdUnit,
53
+ thresholds,
54
+ orientation = 'horizontal',
55
+ header,
56
+ barStyle = {
57
+ opacity: 1,
58
+ radius: 0.2
59
+ }
60
+ }: BarChartProps): JSX.Element => {
61
+ const { adjustedData } = useLineChartData({ data, end, start });
62
+ const lineChartRef = useRef<HTMLDivElement | null>(null);
63
+
64
+ if (loading && !adjustedData) {
65
+ return (
66
+ <LoadingSkeleton
67
+ displayTitleSkeleton={header?.displayTitle ?? false}
68
+ graphHeight={height || 200}
69
+ />
70
+ );
71
+ }
72
+
73
+ return (
74
+ <Box
75
+ ref={lineChartRef}
76
+ sx={{ height: '100%', overflow: 'hidden', width: '100%' }}
77
+ >
78
+ <ParentSize>
79
+ {({ height: responsiveHeight, width }) => (
80
+ <ResponsiveBarChart
81
+ axis={axis}
82
+ barStyle={barStyle}
83
+ graphData={adjustedData}
84
+ graphRef={lineChartRef}
85
+ header={header}
86
+ height={height || responsiveHeight}
87
+ legend={legend}
88
+ limitLegend={limitLegend}
89
+ orientation={orientation}
90
+ thresholdUnit={thresholdUnit}
91
+ thresholds={thresholds}
92
+ tooltip={tooltip}
93
+ width={width}
94
+ />
95
+ )}
96
+ </ParentSize>
97
+ </Box>
98
+ );
99
+ };
100
+
101
+ export default BarChart;