@centreon/ui 24.6.5 → 24.7.1

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centreon/ui",
3
- "version": "24.6.5",
3
+ "version": "24.7.1",
4
4
  "description": "Centreon UI Components",
5
5
  "scripts": {
6
6
  "update:deps": "pnpx npm-check-updates -i --format group",
@@ -12,9 +12,9 @@
12
12
  "test:storybook:local": "test-storybook --url http://127.0.0.1:9001",
13
13
  "test:ci": "jest --silent --reporter=jest-junit",
14
14
  "cypress:ui": "cypress open --component --browser=chrome",
15
- "cypress:cli:updateSnapshot": "pnpm cypress:cli --env updateSnapshots=true",
15
+ "cypress:run:updateSnapshot": "pnpm cypress:cli --env updateSnapshots=true",
16
16
  "cypress:run:coverage": "cypress run --component --browser=chrome --env codeCoverageTasksRegistered=true",
17
- "cypress:cli": "cypress run --component --browser=chrome",
17
+ "cypress:run": "cypress run --component --browser=chrome",
18
18
  "tokens:transform": "TS_NODE_PROJECT=tsconfig.node.json ts-node style-dictionary.transform.ts"
19
19
  },
20
20
  "sideEffects": false,
@@ -8,6 +8,7 @@ import 'dayjs/locale/pt';
8
8
  import localizedFormat from 'dayjs/plugin/localizedFormat';
9
9
  import timezonePlugin from 'dayjs/plugin/timezone';
10
10
  import utcPlugin from 'dayjs/plugin/utc';
11
+ import { Provider } from 'jotai';
11
12
 
12
13
  import { Box } from '@mui/material';
13
14
 
@@ -33,7 +34,7 @@ export interface BarChartProps
33
34
  end: string;
34
35
  limitLegend?: false | number;
35
36
  loading: boolean;
36
- orientation: 'vertical' | 'horizontal';
37
+ orientation: 'vertical' | 'horizontal' | 'auto';
37
38
  start: string;
38
39
  thresholdUnit?: string;
39
40
  thresholds?: Thresholds;
@@ -71,30 +72,32 @@ const BarChart = ({
71
72
  }
72
73
 
73
74
  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>
75
+ <Provider>
76
+ <Box
77
+ ref={lineChartRef}
78
+ sx={{ height: '100%', overflow: 'hidden', width: '100%' }}
79
+ >
80
+ <ParentSize>
81
+ {({ height: responsiveHeight, width }) => (
82
+ <ResponsiveBarChart
83
+ axis={axis}
84
+ barStyle={barStyle}
85
+ graphData={adjustedData}
86
+ graphRef={lineChartRef}
87
+ header={header}
88
+ height={height || responsiveHeight}
89
+ legend={legend}
90
+ limitLegend={limitLegend}
91
+ orientation={orientation}
92
+ thresholdUnit={thresholdUnit}
93
+ thresholds={thresholds}
94
+ tooltip={tooltip}
95
+ width={width}
96
+ />
97
+ )}
98
+ </ParentSize>
99
+ </Box>
100
+ </Provider>
98
101
  );
99
102
  };
100
103
 
@@ -171,6 +171,7 @@ const BarGroup = ({
171
171
  <BarStack
172
172
  barIndex={barGroup.index}
173
173
  barPadding={isHorizontal ? bar.x : bar.y}
174
+ barStyle={barStyle}
174
175
  barWidth={isHorizontal ? bar.width : bar.height}
175
176
  isHorizontal={isHorizontal}
176
177
  isTooltipHidden={isTooltipHidden}
@@ -183,6 +184,7 @@ const BarGroup = ({
183
184
  <BarStack
184
185
  barIndex={barGroup.index}
185
186
  barPadding={isHorizontal ? bar.x : bar.y}
187
+ barStyle={barStyle}
186
188
  barWidth={isHorizontal ? bar.width : bar.height}
187
189
  isHorizontal={isHorizontal}
188
190
  isTooltipHidden={isTooltipHidden}
@@ -4,6 +4,7 @@ import { scaleBand } from '@visx/scale';
4
4
  import { equals, gt, pick } from 'ramda';
5
5
 
6
6
  import { useBarStack, UseBarStackProps } from './useBarStack';
7
+ import { BarStyle } from './models';
7
8
 
8
9
  const xScale = scaleBand<number>({
9
10
  domain: [0, 0],
@@ -14,6 +15,7 @@ const xScale = scaleBand<number>({
14
15
  interface Props extends Omit<UseBarStackProps, 'xScale'> {
15
16
  barIndex: number;
16
17
  barPadding: number;
18
+ barStyle: BarStyle;
17
19
  barWidth: number;
18
20
  isTooltipHidden: boolean;
19
21
  }
@@ -34,7 +36,8 @@ const BarStack = ({
34
36
  barWidth,
35
37
  barPadding,
36
38
  barIndex,
37
- isTooltipHidden
39
+ isTooltipHidden,
40
+ barStyle
38
41
  }: Props): JSX.Element => {
39
42
  const {
40
43
  BarStackComponent,
@@ -63,6 +66,7 @@ const BarStack = ({
63
66
  fill={bar.color}
64
67
  height={isHorizontal ? Math.abs(bar.height) : barWidth}
65
68
  key={`bar-stack-${barStack.index}-${bar.index}`}
69
+ opacity={barStyle.opacity}
66
70
  width={isHorizontal ? barWidth : Math.abs(bar.width)}
67
71
  x={
68
72
  isHorizontal
@@ -107,7 +111,8 @@ const propsToMemoize = [
107
111
  'lines',
108
112
  'barPadding',
109
113
  'barIndex',
110
- 'isTooltipHidden'
114
+ 'isTooltipHidden',
115
+ 'barStyle'
111
116
  ];
112
117
 
113
118
  export default memo(BarStack, (prevProps, nextProps) => {
@@ -1,6 +1,6 @@
1
- import { MutableRefObject, useMemo, useRef, useState } from 'react';
1
+ import { MutableRefObject, useEffect, useMemo, useRef, useState } from 'react';
2
2
 
3
- import { equals, flatten, has, isNil, pluck } from 'ramda';
3
+ import { equals, flatten, gte, has, isNil, pluck } from 'ramda';
4
4
  import { useAtom } from 'jotai';
5
5
 
6
6
  import { Skeleton } from '@mui/material';
@@ -22,6 +22,7 @@ import { useTooltipStyles } from '../common/useTooltipStyles';
22
22
  import { margin } from '../LineChart/common';
23
23
  import { Tooltip } from '../../components';
24
24
  import Thresholds from '../common/Thresholds/Thresholds';
25
+ import { useDeepCompare } from '../../utils';
25
26
 
26
27
  import BarGroup from './BarGroup';
27
28
  import { tooltipDataAtom } from './atoms';
@@ -35,7 +36,7 @@ interface Props
35
36
  graphRef: MutableRefObject<HTMLDivElement | null>;
36
37
  height: number;
37
38
  limitLegend?: false | number;
38
- orientation: 'vertical' | 'horizontal';
39
+ orientation: 'vertical' | 'horizontal' | 'auto';
39
40
  thresholdUnit?: string;
40
41
  thresholds?: ThresholdsModel;
41
42
  width: number;
@@ -82,7 +83,13 @@ const ResponsiveBarChart = ({
82
83
  pluck('value', thresholds?.critical || [])
83
84
  ]);
84
85
 
85
- const isHorizontal = equals(orientation, 'horizontal');
86
+ const isHorizontal = useMemo(() => {
87
+ if (!equals(orientation, 'auto')) {
88
+ return equals(orientation, 'horizontal');
89
+ }
90
+
91
+ return gte(graphWidth, graphHeight + 60);
92
+ }, [orientation, graphWidth, graphHeight]);
86
93
 
87
94
  const xScale = useMemo(
88
95
  () =>
@@ -144,6 +151,13 @@ const ResponsiveBarChart = ({
144
151
  ]
145
152
  );
146
153
 
154
+ useEffect(
155
+ () => {
156
+ setLinesGraph(lines);
157
+ },
158
+ useDeepCompare([lines])
159
+ );
160
+
147
161
  const displayLegend = legend?.display ?? true;
148
162
 
149
163
  const displayedLines = useMemo(
@@ -214,7 +228,7 @@ const ResponsiveBarChart = ({
214
228
  graphWidth={graphWidth - (isHorizontal ? 0 : margin.left - 15)}
215
229
  gridLinesType={axis?.gridLinesType}
216
230
  leftScale={leftScale}
217
- orientation={orientation}
231
+ orientation={isHorizontal ? 'horizontal' : 'vertical'}
218
232
  rightScale={rightScale}
219
233
  showGridLines={showGridLines}
220
234
  svgRef={graphSvgRef}
@@ -228,7 +242,7 @@ const ResponsiveBarChart = ({
228
242
  isTooltipHidden={isTooltipHidden}
229
243
  leftScale={leftScale}
230
244
  lines={displayedLines}
231
- orientation={orientation}
245
+ orientation={isHorizontal ? 'horizontal' : 'vertical'}
232
246
  rightScale={rightScale}
233
247
  secondUnit={secondUnit}
234
248
  size={isHorizontal ? graphHeight - margin.top - 5 : graphWidth}
@@ -55,14 +55,14 @@ const WrapperThresholdLines = ({
55
55
  };
56
56
 
57
57
  const thresholdLines = areaThresholdLines?.map((item, index) => {
58
- const { type } = item;
58
+ const { type, id } = item;
59
59
 
60
60
  if (equals(type, ThresholdType.basic)) {
61
61
  return [
62
62
  {
63
63
  Component: BasicThreshold,
64
64
  key: index,
65
- props: { ...commonProps, getY0, getY1 }
65
+ props: { ...commonProps, getY0, getY1, id }
66
66
  }
67
67
  ];
68
68
  }
@@ -131,7 +131,7 @@ const WrapperThresholdLines = ({
131
131
  <g>
132
132
  {filteredThresholdLines.map((element) =>
133
133
  element?.map(({ Component, props, key }) => (
134
- <Component {...props} id={key} key={key} />
134
+ <Component {...props} id={props?.id ?? key} key={key} />
135
135
  ))
136
136
  )}
137
137
  </g>
@@ -123,6 +123,7 @@ const LineChart = ({
123
123
  hasSecondUnit: Boolean(secondUnit),
124
124
  height,
125
125
  legendDisplay: legend?.display,
126
+ legendHeight: legend?.height,
126
127
  legendPlacement: legend?.placement,
127
128
  width
128
129
  });
@@ -229,6 +230,7 @@ const LineChart = ({
229
230
  height={height}
230
231
  legend={{
231
232
  displayLegend,
233
+ legendHeight: legend?.height,
232
234
  mode: legend?.mode,
233
235
  placement: legend?.placement,
234
236
  renderExtraComponent: legend?.renderExtraComponent
@@ -11,6 +11,7 @@ import utcPlugin from 'dayjs/plugin/utc';
11
11
 
12
12
  import { ParentSize } from '../..';
13
13
  import { LineChartData, Thresholds } from '../common/models';
14
+ import Loading from '../../LoadingSkeleton';
14
15
 
15
16
  import LineChart from './LineChart';
16
17
  import LoadingSkeleton from './LoadingSkeleton';
@@ -73,7 +74,7 @@ const WrapperLineChart = ({
73
74
  }
74
75
 
75
76
  if (!adjustedData) {
76
- return null;
77
+ return <Loading height={height} width={width} />;
77
78
  }
78
79
 
79
80
  return (
@@ -154,6 +154,7 @@ export interface GlobalAreaLines {
154
154
  }
155
155
  export interface LegendModel {
156
156
  display?: boolean;
157
+ height?: number;
157
158
  mode: 'grid' | 'list';
158
159
  placement: 'bottom' | 'left' | 'right';
159
160
  renderExtraComponent?: ReactNode;
@@ -32,19 +32,23 @@ const Axes = ({
32
32
  }: Props): JSX.Element => {
33
33
  const { format } = useLocaleDateTimeFormat();
34
34
  const { lines, showBorder, yAxisTickLabelRotation } = data;
35
+ const isHorizontal = equals(orientation, 'horizontal');
35
36
 
36
- const { axisLeft, axisRight } = useAxisY({ data, graphHeight: height });
37
+ const { axisLeft, axisRight } = useAxisY({
38
+ data,
39
+ graphHeight: height,
40
+ graphWidth: width,
41
+ isHorizontal
42
+ });
37
43
 
38
44
  const [firstUnit, secondUnit, thirdUnit] = getUnits(lines);
39
45
 
40
46
  const xTickCount = Math.min(Math.ceil(width / 82), 12);
41
47
 
48
+ const [start, end] = xScale.domain();
49
+
42
50
  const tickFormat =
43
- data?.axisX?.xAxisTickFormat ??
44
- getXAxisTickFormat({
45
- start: xScale.domain()[0],
46
- start: xScale.domain()[-1]
47
- });
51
+ data?.axisX?.xAxisTickFormat ?? getXAxisTickFormat({ end, start });
48
52
 
49
53
  const formatAxisTick = (tick): string =>
50
54
  format({ date: new Date(tick), formatString: tickFormat });
@@ -52,8 +56,6 @@ const Axes = ({
52
56
  const hasMoreThanTwoUnits = !isNil(thirdUnit);
53
57
  const displayAxisRight = !isNil(secondUnit) && !hasMoreThanTwoUnits;
54
58
 
55
- const isHorizontal = equals(orientation, 'horizontal');
56
-
57
59
  const AxisBottom = isHorizontal ? Axis.AxisBottom : Axis.AxisLeft;
58
60
  const AxisLeft = isHorizontal ? Axis.AxisLeft : Axis.AxisTop;
59
61
  const AxisRight = isHorizontal ? Axis.AxisRight : Axis.AxisBottom;
@@ -76,7 +78,7 @@ const Axes = ({
76
78
  <UnitLabel
77
79
  unit={firstUnit}
78
80
  x={isHorizontal ? -8 : width + 8}
79
- y={isHorizontal ? 16 : 0}
81
+ y={isHorizontal ? 16 : -2}
80
82
  />
81
83
  )}
82
84
 
@@ -88,8 +90,8 @@ const Axes = ({
88
90
  tickLabelProps={() => ({
89
91
  ...axisLeft.tickLabelProps(),
90
92
  angle: yAxisTickLabelRotation,
91
- dx: isHorizontal ? -8 : 2,
92
- dy: isHorizontal ? 4 : -4
93
+ dx: isHorizontal ? -8 : 16,
94
+ dy: isHorizontal ? 4 : -6
93
95
  })}
94
96
  tickLength={2}
95
97
  />
@@ -27,15 +27,24 @@ interface AxisY {
27
27
  interface Props {
28
28
  data: Omit<Data, 'timeSeries'>;
29
29
  graphHeight?: number;
30
+ graphWidth?: number;
31
+ isHorizontal: boolean;
30
32
  }
31
33
 
32
- const useAxisY = ({ data, graphHeight }: Props): AxisY => {
34
+ const useAxisY = ({
35
+ data,
36
+ graphHeight,
37
+ graphWidth,
38
+ isHorizontal
39
+ }: Props): AxisY => {
33
40
  const theme = useTheme();
34
41
 
35
42
  const { lines } = data;
36
43
  const [firstUnit, secondUnit, thirdUnit] = getUnits(lines);
37
44
 
38
- const numTicks = graphHeight && Math.ceil(graphHeight / 30);
45
+ const numTicks = isHorizontal
46
+ ? graphHeight && Math.ceil(graphHeight / 30)
47
+ : graphWidth && Math.ceil(graphWidth / 60);
39
48
 
40
49
  const hasMoreThanTwoUnits = !isNil(thirdUnit);
41
50
  const hasTwoUnits = !isNil(secondUnit) && !hasMoreThanTwoUnits;
@@ -27,6 +27,7 @@ interface Props {
27
27
  isHorizontal?: boolean;
28
28
  legend: {
29
29
  displayLegend: boolean;
30
+ legendHeight?: number;
30
31
  mode?: 'grid' | 'list';
31
32
  placement?: 'left' | 'right' | 'bottom';
32
33
  renderExtraComponent?: ReactNode;
@@ -112,7 +113,10 @@ const BaseChart = ({
112
113
  </Stack>
113
114
  </div>
114
115
  {legend.displayLegend && displayLegendInBottom && (
115
- <div ref={legendRef}>
116
+ <div
117
+ ref={legendRef}
118
+ style={{ height: legend?.legendHeight ?? 'undefined' }}
119
+ >
116
120
  <Legend
117
121
  base={base}
118
122
  height={height}
@@ -4,10 +4,10 @@ import { Group } from '@visx/visx';
4
4
  import { equals } from 'ramda';
5
5
 
6
6
  import { margin } from '../../LineChart/common';
7
- import Grids from '../Grids';
7
+ import { LineChartAxis } from '../../LineChart/models';
8
8
  import Axes from '../Axes';
9
+ import Grids from '../Grids';
9
10
  import { Line, TimeValue } from '../timeSeries/models';
10
- import { LineChartAxis } from '../../LineChart/models';
11
11
 
12
12
  import { extraMargin } from './useComputeBaseChartDimensions';
13
13
 
@@ -10,6 +10,7 @@ interface UseComputeBaseChartDimensionsProps {
10
10
  hasSecondUnit?: boolean;
11
11
  height: number | null;
12
12
  legendDisplay?: boolean;
13
+ legendHeight?: number;
13
14
  legendPlacement?: string;
14
15
  width: number;
15
16
  }
@@ -25,14 +26,18 @@ export const useComputeBaseChartDimensions = ({
25
26
  height,
26
27
  legendDisplay,
27
28
  legendPlacement,
28
- hasSecondUnit
29
+ hasSecondUnit,
30
+ legendHeight
29
31
  }: UseComputeBaseChartDimensionsProps): UseComputeBaseChartDimensionsState => {
30
32
  const legendRef = useRef<HTMLDivElement | null>(null);
31
33
 
34
+ const currentLegendHeight =
35
+ legendHeight ?? (legendRef.current?.getBoundingClientRect().height || 0);
36
+
32
37
  const legendBoundingHeight =
33
38
  !equals(legendDisplay, false) &&
34
39
  (isNil(legendPlacement) || equals(legendPlacement, 'bottom'))
35
- ? legendRef.current?.getBoundingClientRect().height || 0
40
+ ? currentLegendHeight
36
41
  : 0;
37
42
  const legendBoundingWidth =
38
43
  !equals(legendDisplay, false) &&
@@ -1,4 +1,7 @@
1
1
  export { default as LineChart } from './LineChart';
2
+ export { default as ThresholdLines } from './LineChart/BasicComponents/Lines/Threshold';
3
+ export { default as useLineChartData } from './LineChart/useLineChartData';
4
+ export { default as BarChart } from './BarChart/BarChart';
2
5
  export { Gauge } from './Gauge';
3
6
  export { SingleBar } from './SingleBar';
4
7
  export { Text as GraphText } from './Text';
@@ -7,3 +10,6 @@ export { HeatMap } from './HeatMap';
7
10
  export { BarStack } from './BarStack';
8
11
  export { PieChart } from './PieChart';
9
12
  export * from './Tree';
13
+ export type { LineChartData } from './common/models';
14
+ export * from './common/timeSeries';
15
+ export * from './LineChart/models';
@@ -9,6 +9,7 @@ import timezonePlugin from 'dayjs/plugin/timezone';
9
9
  import utcPlugin from 'dayjs/plugin/utc';
10
10
 
11
11
  import { ParentSize } from '..';
12
+ import LoadingSkeleton from '../LoadingSkeleton';
12
13
 
13
14
  import { WrapperTimePeriodProps } from './models';
14
15
  import TimePeriods from './TimePeriods';
@@ -18,10 +19,17 @@ dayjs.extend(utcPlugin);
18
19
  dayjs.extend(timezonePlugin);
19
20
  dayjs.extend(duration);
20
21
 
21
- const WrapperTimePeriods = (props: WrapperTimePeriodProps): JSX.Element => (
22
+ const WrapperTimePeriods = ({
23
+ skeletonHeight = 38,
24
+ ...rest
25
+ }: WrapperTimePeriodProps): JSX.Element => (
22
26
  <ParentSize>
23
27
  {({ width }): JSX.Element => {
24
- return <TimePeriods width={width} {...props} />;
28
+ return !width ? (
29
+ <LoadingSkeleton height={skeletonHeight} variant="rectangular" />
30
+ ) : (
31
+ <TimePeriods width={width} {...rest} />
32
+ );
25
33
  }}
26
34
  </ParentSize>
27
35
  );
@@ -109,4 +109,5 @@ export interface WrapperTimePeriodProps {
109
109
  getIsError?: (value: boolean) => void;
110
110
  getParameters?: ({ start, end, timelineEventsLimit }: Parameters) => void;
111
111
  renderExternalComponent?: ReactNode;
112
+ skeletonHeight?: number;
112
113
  }
package/src/index.ts CHANGED
@@ -158,8 +158,6 @@ export { default as FluidTypography } from './Typography/FluidTypography';
158
158
  export { default as EllipsisTypography } from './Typography/EllipsisTypography';
159
159
  export * from './Dashboard';
160
160
  export * from './Graph';
161
- export type { LineChartData } from './Graph/common/models';
162
- export * from './Graph/common/timeSeries';
163
161
 
164
162
  export { default as TimePeriods } from './TimePeriods';
165
163
  export { default as SimpleCustomTimePeriod } from './TimePeriods/CustomTimePeriod/SimpleCustomTimePeriod';
@@ -1,60 +0,0 @@
1
- import { Dispatch, SetStateAction, useEffect } from 'react';
2
-
3
- import { equals, propEq, reject } from 'ramda';
4
-
5
- import { Line } from '../../common/timeSeries/models';
6
-
7
- import {
8
- findLineOfOriginMetricThreshold,
9
- lowerLineName,
10
- upperLineName
11
- } from './Lines/Threshold/models';
12
-
13
- interface UseFilterLines {
14
- displayThreshold?: boolean;
15
- lines: Array<Line>;
16
- linesGraph: Array<Line> | null;
17
- setLinesGraph: Dispatch<SetStateAction<Array<Line> | null>>;
18
- }
19
-
20
- interface Result {
21
- displayedLines: Array<Line>;
22
- newLines: Array<Line>;
23
- }
24
-
25
- const useFilterLines = ({
26
- displayThreshold = false,
27
- lines,
28
- linesGraph,
29
- setLinesGraph
30
- }: UseFilterLines): Result => {
31
- const displayedLines = reject(propEq(false, 'display'), linesGraph ?? lines);
32
- const filterLines = (): Array<Line> => {
33
- const lineOriginMetric = findLineOfOriginMetricThreshold(lines);
34
-
35
- const findLinesUpperLower = lines.map((line) =>
36
- equals(line.name, lowerLineName) || equals(line.name, upperLineName)
37
- ? line
38
- : null
39
- );
40
-
41
- const linesUpperLower = reject((element) => !element, findLinesUpperLower);
42
-
43
- return [...lineOriginMetric, ...linesUpperLower] as Array<Line>;
44
- };
45
-
46
- useEffect(() => {
47
- const filteredLines = filterLines();
48
- if (!lines || !displayThreshold) {
49
- setLinesGraph(lines);
50
-
51
- return;
52
- }
53
-
54
- setLinesGraph(filteredLines);
55
- }, [lines, displayThreshold]);
56
-
57
- return { displayedLines, newLines: linesGraph ?? lines };
58
- };
59
-
60
- export default useFilterLines;