@centreon/ui 24.4.72 → 24.4.74

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 (131) hide show
  1. package/package.json +24 -23
  2. package/src/Checkbox/fonts/roboto-bold-webfont.ttf +0 -0
  3. package/src/Checkbox/fonts/roboto-bold-webfont.woff +0 -0
  4. package/src/Checkbox/fonts/roboto-bold-webfont.woff2 +0 -0
  5. package/src/Checkbox/fonts/roboto-light-webfont.ttf +0 -0
  6. package/src/Checkbox/fonts/roboto-light-webfont.woff +0 -0
  7. package/src/Checkbox/fonts/roboto-light-webfont.woff2 +0 -0
  8. package/src/Checkbox/fonts/roboto-medium-webfont.ttf +0 -0
  9. package/src/Checkbox/fonts/roboto-medium-webfont.woff +0 -0
  10. package/src/Checkbox/fonts/roboto-medium-webfont.woff2 +0 -0
  11. package/src/Checkbox/fonts/roboto-regular-webfont.ttf +0 -0
  12. package/src/Checkbox/fonts/roboto-regular-webfont.woff +0 -0
  13. package/src/Checkbox/fonts/roboto-regular-webfont.woff2 +0 -0
  14. package/src/Dashboard/Item.tsx +2 -11
  15. package/src/Dashboard/Layout.tsx +2 -4
  16. package/src/Dashboard/utils.ts +1 -1
  17. package/src/Form/Inputs/Grid.tsx +8 -4
  18. package/src/Form/Inputs/models.ts +15 -14
  19. package/src/Graph/BarStack/BarStack.cypress.spec.tsx +87 -9
  20. package/src/Graph/BarStack/BarStack.stories.tsx +4 -2
  21. package/src/Graph/BarStack/BarStack.styles.ts +59 -30
  22. package/src/Graph/BarStack/Graph.tsx +176 -0
  23. package/src/Graph/BarStack/GraphAndLegend.tsx +119 -0
  24. package/src/Graph/BarStack/ResponsiveBarStack.tsx +62 -157
  25. package/src/Graph/BarStack/constants.ts +5 -0
  26. package/src/Graph/BarStack/models.ts +1 -1
  27. package/src/Graph/BarStack/useGraphAndLegend.ts +86 -0
  28. package/src/Graph/BarStack/useResponsiveBarStack.ts +74 -99
  29. package/src/Graph/HeatMap/ResponsiveHeatMap.tsx +19 -2
  30. package/src/Graph/HeatMap/model.ts +5 -1
  31. package/src/Graph/Legend/Legend.styles.ts +10 -0
  32. package/src/Graph/Legend/Legend.tsx +6 -1
  33. package/src/Graph/LineChart/BasicComponents/Lines/RegularLines/index.tsx +2 -1
  34. package/src/Graph/LineChart/BasicComponents/Lines/StackedLines/index.tsx +3 -4
  35. package/src/Graph/LineChart/Icons/Downtime.tsx +3 -3
  36. package/src/Graph/LineChart/InteractiveComponents/ZoomPreview/index.tsx +2 -1
  37. package/src/Graph/LineChart/Legend/Legend.styles.ts +16 -5
  38. package/src/Graph/LineChart/Legend/LegendHeader.tsx +4 -1
  39. package/src/Graph/LineChart/Legend/index.tsx +12 -5
  40. package/src/Graph/LineChart/LineChart.cypress.spec.tsx +53 -0
  41. package/src/Graph/LineChart/LineChart.tsx +10 -9
  42. package/src/Graph/LineChart/index.stories.tsx +13 -0
  43. package/src/Graph/LineChart/mockedData/curvesWithSameColor.json +252 -0
  44. package/src/Graph/LineChart/useLineChartData.ts +68 -18
  45. package/src/Graph/PieChart/ResponsivePie.tsx +3 -1
  46. package/src/Graph/PieChart/models.ts +1 -0
  47. package/src/Graph/Tree/DescendantNodes.tsx +0 -1
  48. package/src/Graph/Tree/Links.tsx +2 -15
  49. package/src/Graph/Tree/Tree.cypress.spec.tsx +0 -24
  50. package/src/Graph/Tree/Tree.stories.tsx +1 -17
  51. package/src/Graph/Tree/models.ts +0 -3
  52. package/src/Graph/common/utils.ts +51 -2
  53. package/src/Icon/BaseIcon.tsx +32 -0
  54. package/src/Icon/DowntimeIcon.tsx +14 -0
  55. package/src/InputField/Select/Autocomplete/Connected/Multi/index.test.tsx +21 -1
  56. package/src/InputField/Select/Autocomplete/Connected/index.test.tsx +2 -2
  57. package/src/InputField/Select/Autocomplete/Connected/index.tsx +10 -7
  58. package/src/InputField/Select/Autocomplete/Multi/index.stories.tsx +19 -0
  59. package/src/InputField/Select/Autocomplete/Multi/index.tsx +8 -5
  60. package/src/InputField/Text/index.tsx +7 -5
  61. package/src/Listing/ActionBar/index.tsx +1 -0
  62. package/src/PopoverMenu/index.tsx +4 -4
  63. package/src/RichTextEditor/ContentEditable.tsx +195 -195
  64. package/src/StoryBookThemeProvider/index.tsx +35 -36
  65. package/src/ThemeProvider/index.tsx +12 -12
  66. package/src/ThemeProvider/palettes.ts +11 -8
  67. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +2 -3
  68. package/src/TimePeriods/DateTimePickerInput.tsx +4 -1
  69. package/src/TopCounterElements/TopCounterLayout.tsx +4 -3
  70. package/src/TopCounterElements/useCloseOnLegacyPage.tsx +9 -6
  71. package/src/api/buildListingEndpoint/getSearchQueryParameterValue.ts +7 -1
  72. package/src/api/buildListingEndpoint/models.ts +1 -0
  73. package/src/api/useGraphQuery/index.ts +1 -7
  74. package/src/components/Form/AccessRights/AccessRights.cypress.spec.tsx +13 -27
  75. package/src/components/Form/AccessRights/AccessRights.stories.tsx +19 -0
  76. package/src/components/Form/AccessRights/AccessRights.styles.ts +1 -1
  77. package/src/components/Form/AccessRights/AccessRights.tsx +5 -6
  78. package/src/components/Form/AccessRights/Actions/Actions.styles.ts +7 -3
  79. package/src/components/Form/AccessRights/Actions/Actions.tsx +32 -15
  80. package/src/components/Form/AccessRights/Actions/useActions.ts +37 -4
  81. package/src/components/Form/AccessRights/models.ts +3 -0
  82. package/src/components/Form/AccessRights/storiesData.ts +3 -0
  83. package/src/components/List/Item/ListItem.styles.ts +2 -2
  84. package/src/components/Zoom/Minimap.tsx +2 -4
  85. package/src/components/Zoom/Zoom.cypress.spec.tsx +13 -13
  86. package/src/components/Zoom/Zoom.tsx +1 -4
  87. package/src/components/Zoom/ZoomContent.tsx +2 -5
  88. package/src/components/index.ts +0 -1
  89. package/src/fonts/roboto-bold-webfont.ttf +0 -0
  90. package/src/fonts/roboto-bold-webfont.woff +0 -0
  91. package/src/fonts/roboto-bold-webfont.woff2 +0 -0
  92. package/src/fonts/roboto-light-webfont.ttf +0 -0
  93. package/src/fonts/roboto-light-webfont.woff +0 -0
  94. package/src/fonts/roboto-light-webfont.woff2 +0 -0
  95. package/src/fonts/roboto-medium-webfont.ttf +0 -0
  96. package/src/fonts/roboto-medium-webfont.woff +0 -0
  97. package/src/fonts/roboto-medium-webfont.woff2 +0 -0
  98. package/src/fonts/roboto-regular-webfont.ttf +0 -0
  99. package/src/fonts/roboto-regular-webfont.woff +0 -0
  100. package/src/fonts/roboto-regular-webfont.woff2 +0 -0
  101. package/src/index.ts +1 -0
  102. package/src/utils/index.ts +25 -25
  103. package/src/utils/useFullscreen/Fullscreen.cypress.spec.tsx +3 -0
  104. package/src/utils/useInfiniteScrollListing.ts +6 -1
  105. package/src/utils/useLocale/index.ts +10 -0
  106. package/src/utils/useLocale/useLocale.cypress.spec.tsx +40 -0
  107. package/src/utils/useLocaleDateTimeFormat/index.ts +5 -2
  108. package/src/utils/usePluralizedTranslation.ts +4 -21
  109. package/src/@assets/icons/downtime.icon.svg +0 -1
  110. package/src/components/Form/AccessRights/useAccessRightsChange.ts +0 -30
  111. package/src/components/Form/AccessRights/utils.ts +0 -18
  112. package/src/components/Tabs/Tab.styles.ts +0 -25
  113. package/src/components/Tabs/TabPanel.tsx +0 -22
  114. package/src/components/Tabs/Tabs.cypress.spec.tsx +0 -70
  115. package/src/components/Tabs/Tabs.stories.tsx +0 -55
  116. package/src/components/Tabs/Tabs.tsx +0 -55
  117. package/src/components/Tabs/index.ts +0 -6
  118. package/src/utils/resourcesStatusURL.ts +0 -166
  119. package/src/utils/usePluralizedTranslation.test.ts +0 -159
  120. /package/{public → src/Button}/fonts/roboto-bold-webfont.ttf +0 -0
  121. /package/{public → src/Button}/fonts/roboto-bold-webfont.woff +0 -0
  122. /package/{public → src/Button}/fonts/roboto-bold-webfont.woff2 +0 -0
  123. /package/{public → src/Button}/fonts/roboto-light-webfont.ttf +0 -0
  124. /package/{public → src/Button}/fonts/roboto-light-webfont.woff +0 -0
  125. /package/{public → src/Button}/fonts/roboto-light-webfont.woff2 +0 -0
  126. /package/{public → src/Button}/fonts/roboto-medium-webfont.ttf +0 -0
  127. /package/{public → src/Button}/fonts/roboto-medium-webfont.woff +0 -0
  128. /package/{public → src/Button}/fonts/roboto-medium-webfont.woff2 +0 -0
  129. /package/{public → src/Button}/fonts/roboto-regular-webfont.ttf +0 -0
  130. /package/{public → src/Button}/fonts/roboto-regular-webfont.woff +0 -0
  131. /package/{public → src/Button}/fonts/roboto-regular-webfont.woff2 +0 -0
@@ -1,38 +1,30 @@
1
- import { scaleBand, scaleLinear, scaleOrdinal } from '@visx/scale';
2
- import { equals, pluck } from 'ramda';
1
+ import { useMemo } from 'react';
2
+
3
+ import { scaleOrdinal } from '@visx/scale';
4
+ import { equals, isNil, pluck } from 'ramda';
3
5
 
4
- import { getValueByUnit } from '../common/utils';
5
6
  import { LegendScale } from '../Legend/models';
7
+ import { getValueByUnit } from '../common/utils';
6
8
 
7
9
  import { BarType } from './models';
8
10
 
9
- interface Size {
10
- height: number;
11
- width: number;
12
- }
13
-
14
- interface useBarStackProps {
11
+ interface UseBarStackProps {
15
12
  data: Array<BarType>;
16
13
  height: number;
17
- legendRef;
18
- size: number;
19
- titleRef;
14
+ legendDirection?: 'column' | 'row';
20
15
  unit?: 'percentage' | 'number';
21
16
  variant?: 'vertical' | 'horizontal';
22
17
  width: number;
23
18
  }
24
- interface useBarStackState {
25
- barSize: Size;
19
+
20
+ interface UseBarStackState {
26
21
  colorScale;
27
- input;
22
+ formattedLegendDirection: 'column' | 'row';
23
+ isSmall: boolean;
28
24
  isVerticalBar: boolean;
29
- keys: Array<string>;
30
25
  legendScale: LegendScale;
31
- svgContainerSize: Size;
32
- svgWrapperWidth: number;
26
+ titleVariant: 'xs' | 'sm' | 'md';
33
27
  total: number;
34
- xScale;
35
- yScale;
36
28
  }
37
29
 
38
30
  const useResponsiveBarStack = ({
@@ -41,90 +33,73 @@ const useResponsiveBarStack = ({
41
33
  height,
42
34
  width,
43
35
  unit = 'number',
44
- titleRef,
45
- legendRef,
46
- size
47
- }: useBarStackProps): useBarStackState => {
48
- const isVerticalBar = equals(variant, 'vertical');
49
-
50
- const heightOfTitle = titleRef.current?.offsetHeight || 0;
51
- const widthOfLegend = legendRef.current?.offsetWidth || 0;
52
-
53
- const horizontalGap = widthOfLegend > 0 ? 12 : 0;
54
- const verticalGap = heightOfTitle > 0 ? 8 : 0;
55
-
56
- const svgWrapperWidth = isVerticalBar
57
- ? size + 36
58
- : width - widthOfLegend - horizontalGap;
59
-
60
- const svgContainerSize = {
61
- height: isVerticalBar ? height - heightOfTitle - verticalGap : size,
62
- width: isVerticalBar ? size : width - widthOfLegend - horizontalGap
63
- };
64
-
65
- const barSize = {
66
- height: svgContainerSize.height - 16,
67
- width: svgContainerSize.width - 16
68
- };
69
-
70
- const total = Math.floor(data.reduce((acc, { value }) => acc + value, 0));
71
-
72
- const yScale = isVerticalBar
73
- ? scaleLinear({
74
- domain: [0, total]
75
- })
76
- : scaleBand({
77
- domain: [0, 0],
78
- padding: 0
79
- });
80
-
81
- const xScale = isVerticalBar
82
- ? scaleBand({
83
- domain: [0, 0],
84
- padding: 0
85
- })
86
- : scaleLinear({
87
- domain: [0, total]
88
- });
89
-
90
- const keys = pluck('label', data);
91
-
92
- const colorsRange = pluck('color', data);
93
-
94
- const colorScale = scaleOrdinal({
95
- domain: keys,
96
- range: colorsRange
97
- });
98
-
99
- const legendScale = {
100
- domain: data.map(({ value }) => getValueByUnit({ total, unit, value })),
101
- range: colorsRange
102
- };
103
-
104
- const xMax = barSize.width;
105
- const yMax = barSize.height;
106
-
107
- xScale.rangeRound([0, xMax]);
108
- yScale.range([yMax, 0]);
109
-
110
- const input = data.reduce((acc, { label, value }) => {
111
- acc[label] = value;
112
-
113
- return acc;
114
- }, {});
36
+ legendDirection
37
+ }: UseBarStackProps): UseBarStackState => {
38
+ const total = useMemo(
39
+ () => Math.floor(data.reduce((acc, { value }) => acc + value, 0)),
40
+ [data]
41
+ );
42
+
43
+ const isVerticalBar = useMemo(() => equals(variant, 'vertical'), [variant]);
44
+
45
+ const isSmall = useMemo(
46
+ () => Math.floor(height) < 90,
47
+ [isVerticalBar, height]
48
+ );
49
+
50
+ const titleVariant = useMemo(() => {
51
+ if (width <= 105) {
52
+ return 'xs';
53
+ }
54
+
55
+ if (width <= 150 || isSmall) {
56
+ return 'sm';
57
+ }
58
+
59
+ return 'md';
60
+ }, [isSmall, width]);
61
+
62
+ const keys = useMemo(() => pluck('label', data), [data]);
63
+
64
+ const colorsRange = useMemo(() => pluck('color', data), [data]);
65
+
66
+ const colorScale = useMemo(
67
+ () =>
68
+ scaleOrdinal({
69
+ domain: keys,
70
+ range: colorsRange
71
+ }),
72
+ [keys, colorsRange]
73
+ );
74
+
75
+ const legendScale = useMemo(
76
+ () => ({
77
+ domain: data.map(({ value }) => getValueByUnit({ total, unit, value })),
78
+ range: colorsRange
79
+ }),
80
+ [data, colorsRange]
81
+ );
82
+
83
+ const formattedLegendDirection = useMemo(() => {
84
+ if (!isNil(legendDirection)) {
85
+ return legendDirection;
86
+ }
87
+
88
+ if (equals(variant, 'horizontal')) {
89
+ return 'row';
90
+ }
91
+
92
+ return 'column';
93
+ }, [legendDirection, variant]);
115
94
 
116
95
  return {
117
- barSize,
118
96
  colorScale,
119
- input,
97
+ formattedLegendDirection,
98
+ isSmall,
120
99
  isVerticalBar,
121
- keys,
122
100
  legendScale,
123
- svgContainerSize,
124
- svgWrapperWidth,
125
- total,
126
- xScale,
127
- yScale
101
+ titleVariant,
102
+ total
128
103
  };
129
104
  };
130
105
 
@@ -1,4 +1,4 @@
1
- import { useMemo } from 'react';
1
+ import { useMemo, useRef } from 'react';
2
2
 
3
3
  import { scaleLinear } from '@visx/scale';
4
4
  import { T, equals, gt, lt } from 'ramda';
@@ -13,6 +13,7 @@ import { useHeatMapStyles } from './HeatMap.styles';
13
13
  const gap = 8;
14
14
  const maxTileSize = 120;
15
15
  const smallestTileSize = 44;
16
+ const toleratedRangeWidth = 10;
16
17
 
17
18
  const ResponsiveHeatMap = <TData,>({
18
19
  width,
@@ -24,6 +25,7 @@ const ResponsiveHeatMap = <TData,>({
24
25
  displayTooltipCondition = T
25
26
  }: HeatMapProps<TData> & { width: number }): JSX.Element | null => {
26
27
  const { classes, cx } = useHeatMapStyles();
28
+ const previousTileSize = useRef(0);
27
29
 
28
30
  const tileSize = useMemo(() => {
29
31
  const scaleWidth = scaleLinear({
@@ -39,6 +41,12 @@ const ResponsiveHeatMap = <TData,>({
39
41
  tilesLength * maxTileSize + (tilesLength - 1) * gap;
40
42
  const theoricalTotalTilesWidth =
41
43
  tilesLength * tileWidth + (tilesLength - 1) * gap;
44
+ const canUpdateTileSize =
45
+ Math.abs(tileWidth - previousTileSize.current) > toleratedRangeWidth;
46
+
47
+ if (!canUpdateTileSize) {
48
+ return previousTileSize.current;
49
+ }
42
50
 
43
51
  if (lt(width, 680) && gt(maxTotalTilesWidth, width) && !tileSizeFixed) {
44
52
  return smallestTileSize;
@@ -52,6 +60,8 @@ const ResponsiveHeatMap = <TData,>({
52
60
  }, [width, tiles]);
53
61
 
54
62
  const isSmallestSize = equals(tileSize, smallestTileSize);
63
+ const isMediumSize = !isSmallestSize && lt(tileSize, 90);
64
+ previousTileSize.current = tileSize;
55
65
 
56
66
  if (equals(width, 0)) {
57
67
  return null;
@@ -92,7 +102,14 @@ const ResponsiveHeatMap = <TData,>({
92
102
  position="right-start"
93
103
  >
94
104
  <div className={classes.heatMapTileContent}>
95
- {children({ backgroundColor, data, id, isSmallestSize })}
105
+ {children({
106
+ backgroundColor,
107
+ data,
108
+ id,
109
+ isMediumSize,
110
+ isSmallestSize,
111
+ tileSize
112
+ })}
96
113
  </div>
97
114
  </Tooltip>
98
115
  </Box>
@@ -10,7 +10,9 @@ interface ChildrenProps<TData> {
10
10
  backgroundColor: string;
11
11
  data: TData;
12
12
  id: string;
13
+ isMediumSize?: boolean;
13
14
  isSmallestSize: boolean;
15
+ tileSize?: number;
14
16
  }
15
17
 
16
18
  export interface HeatMapProps<TData> {
@@ -19,7 +21,9 @@ export interface HeatMapProps<TData> {
19
21
  backgroundColor,
20
22
  id,
21
23
  data,
22
- isSmallestSize
24
+ isSmallestSize,
25
+ tileSize,
26
+ isMediumSize
23
27
  }: ChildrenProps<TData>) => ReactElement | boolean | null;
24
28
  displayTooltipCondition?: (data: TData) => boolean;
25
29
  tileSizeFixed?: boolean;
@@ -0,0 +1,10 @@
1
+ import { makeStyles } from 'tss-react/mui';
2
+
3
+ export const useStyles = makeStyles()((theme) => ({
4
+ container: {
5
+ border: `1px solid ${theme.palette.divider}`,
6
+ borderRadius: theme.shape.borderRadius,
7
+ padding: theme.spacing(1),
8
+ width: 'fit-content'
9
+ }
10
+ }));
@@ -1,9 +1,13 @@
1
1
  import { LegendOrdinal } from '@visx/legend';
2
2
  import { scaleOrdinal } from '@visx/scale';
3
+ import { equals } from 'ramda';
3
4
 
5
+ import { useStyles } from './Legend.styles';
4
6
  import { LegendProps } from './models';
5
7
 
6
8
  const Legend = ({ scale, direction = 'column' }: LegendProps): JSX.Element => {
9
+ const { classes } = useStyles();
10
+
7
11
  const legendScale = scaleOrdinal({
8
12
  domain: scale.domain,
9
13
  range: scale.range
@@ -11,8 +15,9 @@ const Legend = ({ scale, direction = 'column' }: LegendProps): JSX.Element => {
11
15
 
12
16
  return (
13
17
  <LegendOrdinal
18
+ className={classes.container}
14
19
  direction={direction}
15
- labelMargin="0 16px 0 0"
20
+ labelMargin={equals(direction, 'row') ? '0 12px 0 0' : '0 0 0 0'}
16
21
  scale={legendScale}
17
22
  />
18
23
  );
@@ -55,6 +55,7 @@ const RegularLine = ({
55
55
  if (filled) {
56
56
  return (
57
57
  <Shape.AreaClosed<TimeValue>
58
+ data-metric={metric_id}
58
59
  fill={getFillColor({ areaColor, transparency })}
59
60
  fillRule="nonzero"
60
61
  key={metric_id}
@@ -65,7 +66,7 @@ const RegularLine = ({
65
66
  );
66
67
  }
67
68
 
68
- return <Shape.LinePath<TimeValue> {...props} />;
69
+ return <Shape.LinePath<TimeValue> data-metric={metric_id} {...props} />;
69
70
  };
70
71
 
71
72
  export default memo(RegularLine, (prevProps, nextProps) => {
@@ -45,10 +45,8 @@ const StackLines = ({
45
45
  >
46
46
  {({ stacks, path: linePath }): Array<JSX.Element> => {
47
47
  return stacks.map((stack, index) => {
48
- const { areaColor, transparency, lineColor, highlight } = nth(
49
- index,
50
- lines
51
- ) as Line;
48
+ const { areaColor, transparency, lineColor, highlight, metric_id } =
49
+ nth(index, lines) as Line;
52
50
 
53
51
  return (
54
52
  <g key={`stack-${prop('key', stack)}`}>
@@ -65,6 +63,7 @@ const StackLines = ({
65
63
  )}
66
64
  <path
67
65
  d={linePath(stack) || ''}
66
+ data-metric={metric_id}
68
67
  fill={getFillColor({ areaColor, transparency })}
69
68
  opacity={highlight === false ? 0.3 : 1}
70
69
  stroke={lineColor}
@@ -1,9 +1,9 @@
1
- import { SvgIcon, SvgIconProps } from '@mui/material';
1
+ import { SvgIconProps } from '@mui/material';
2
2
 
3
- import { ReactComponent as IconDowntime } from '../../../@assets/icons/downtime.icon.svg';
3
+ import { DowntimeIcon } from '../../../Icon/DowntimeIcon';
4
4
 
5
5
  const Downtime = (props: SvgIconProps): JSX.Element => (
6
- <SvgIcon component={IconDowntime} {...props} />
6
+ <DowntimeIcon {...props} />
7
7
  );
8
8
 
9
9
  export default Downtime;
@@ -1,6 +1,7 @@
1
1
  import { omit } from 'ramda';
2
2
 
3
- import { alpha, useTheme } from '@mui/system';
3
+ import { useTheme } from '@mui/material';
4
+ import { alpha } from '@mui/system';
4
5
 
5
6
  import Bar from '../Bar';
6
7
 
@@ -1,8 +1,10 @@
1
+ import { lt } from 'ramda';
1
2
  import { makeStyles } from 'tss-react/mui';
2
3
 
3
4
  import { margin } from '../common';
4
5
 
5
6
  interface MakeStylesProps {
7
+ height?: number | null;
6
8
  limitLegendRows?: boolean;
7
9
  }
8
10
 
@@ -10,8 +12,16 @@ export const legendWidth = 21;
10
12
  const legendItemHeight = 5.25;
11
13
  const legendItemHeightCompact = 2;
12
14
 
15
+ const getLegendMaxHeight = ({ height }): number => {
16
+ if (lt(height || 0, 220)) {
17
+ return 40;
18
+ }
19
+
20
+ return 90;
21
+ };
22
+
13
23
  export const useStyles = makeStyles<MakeStylesProps>()(
14
- (theme, { limitLegendRows }) => ({
24
+ (theme, { limitLegendRows, height = 0 }) => ({
15
25
  highlight: {
16
26
  color: theme.typography.body1.color
17
27
  },
@@ -29,9 +39,6 @@ export const useStyles = makeStyles<MakeStylesProps>()(
29
39
  display: 'grid',
30
40
  gridAutoRows: theme.spacing(legendItemHeight),
31
41
  gridTemplateColumns: `repeat(auto-fit, minmax(${theme.spacing(legendWidth)}, 1fr))`,
32
- maxHeight: limitLegendRows
33
- ? theme.spacing(legendItemHeight * 2 + 1)
34
- : 'unset',
35
42
  overflowX: 'hidden',
36
43
  overflowY: 'auto',
37
44
  rowGap: theme.spacing(1),
@@ -40,7 +47,11 @@ export const useStyles = makeStyles<MakeStylesProps>()(
40
47
  legend: {
41
48
  marginLeft: margin.left,
42
49
  marginRight: margin.right,
43
- overflow: 'hidden'
50
+ maxHeight: limitLegendRows
51
+ ? theme.spacing(legendItemHeight * 2 + 1)
52
+ : getLegendMaxHeight({ height }),
53
+ overflowX: 'hidden',
54
+ overflowY: 'auto'
44
55
  },
45
56
  minMaxAvgContainer: {
46
57
  columnGap: theme.spacing(0.5),
@@ -63,7 +63,10 @@ const LegendHeader = ({
63
63
  placement="top"
64
64
  >
65
65
  <div className={classes.markerAndLegendName}>
66
- <div className={cx(classes.icon, { [classes.disabled]: disabled })} />
66
+ <div
67
+ data-icon
68
+ className={cx(classes.icon, { [classes.disabled]: disabled })}
69
+ />
67
70
  <EllipsisTypography
68
71
  className={cx(classes.text, classes.legendName)}
69
72
  data-mode={
@@ -11,13 +11,14 @@ import { Line } from '../../common/timeSeries/models';
11
11
  import { labelAvg, labelMax, labelMin } from '../translatedLabels';
12
12
 
13
13
  import { useStyles } from './Legend.styles';
14
+ import LegendContent from './LegendContent';
14
15
  import LegendHeader from './LegendHeader';
15
16
  import { GetMetricValueProps, LegendDisplayMode } from './models';
16
17
  import useLegend from './useLegend';
17
- import LegendContent from './LegendContent';
18
18
 
19
19
  interface Props {
20
20
  base: number;
21
+ height?: number | null;
21
22
  limitLegend?: false | number;
22
23
  lines: Array<Line>;
23
24
  renderExtraComponent?: ReactNode;
@@ -33,9 +34,13 @@ const MainLegend = ({
33
34
  limitLegend = false,
34
35
  renderExtraComponent,
35
36
  setLinesGraph,
36
- shouldDisplayLegendInCompactMode
37
+ shouldDisplayLegendInCompactMode,
38
+ height
37
39
  }: Props): JSX.Element => {
38
- const { classes, cx } = useStyles({ limitLegendRows: Boolean(limitLegend) });
40
+ const { classes, cx } = useStyles({
41
+ height,
42
+ limitLegendRows: Boolean(limitLegend)
43
+ });
39
44
  const theme = useTheme();
40
45
 
41
46
  const { selectMetricLine, clearHighlight, highlightLine, toggleMetricLine } =
@@ -145,7 +150,8 @@ const Legend = (props: Props): JSX.Element => {
145
150
  limitLegend,
146
151
  lines,
147
152
  base,
148
- shouldDisplayLegendInCompactMode
153
+ shouldDisplayLegendInCompactMode,
154
+ height
149
155
  } = props;
150
156
 
151
157
  return useMemoComponent({
@@ -155,7 +161,8 @@ const Legend = (props: Props): JSX.Element => {
155
161
  base,
156
162
  toggable,
157
163
  limitLegend,
158
- shouldDisplayLegendInCompactMode
164
+ shouldDisplayLegendInCompactMode,
165
+ height
159
166
  ]
160
167
  });
161
168
  };
@@ -3,6 +3,7 @@ import { LineChartData } from '../common/models';
3
3
  import dataLastDay from './mockedData/lastDay.json';
4
4
  import dataLastDayWithNullValues from './mockedData/lastDayWithNullValues.json';
5
5
  import dataLastDayWithIncompleteValues from './mockedData/lastDayWithIncompleteValues.json';
6
+ import dataCurvesWithSameColor from './mockedData/curvesWithSameColor.json';
6
7
  import { args as argumentsData } from './helpers/doc';
7
8
 
8
9
  import WrapperLineChart from '.';
@@ -88,4 +89,56 @@ describe('Line chart', () => {
88
89
  cy.makeSnapshot();
89
90
  });
90
91
  });
92
+
93
+ it('displays the curves with different shades when curves have same color', () => {
94
+ initialize(dataCurvesWithSameColor);
95
+
96
+ cy.findByLabelText('Centreon-Server: Round-Trip Average Time')
97
+ .find('[data-icon="true"]')
98
+ .should('have.css', 'background-color', 'rgb(41, 175, 238)');
99
+ cy.findByLabelText('Centreon-Server_5: Round-Trip Average Time')
100
+ .find('[data-icon="true"]')
101
+ .should('have.css', 'background-color', 'rgb(83, 191, 241)');
102
+ cy.findByLabelText('Centreon-Server_4: Round-Trip Average Time')
103
+ .find('[data-icon="true"]')
104
+ .should('have.css', 'background-color', 'rgb(8, 34, 47)');
105
+ cy.findByLabelText('Centreon-Server_3: Round-Trip Average Time')
106
+ .find('[data-icon="true"]')
107
+ .should('have.css', 'background-color', 'rgb(16, 70, 95)');
108
+ cy.findByLabelText('Centreon-Server_2: Round-Trip Average Time')
109
+ .find('[data-icon="true"]')
110
+ .should('have.css', 'background-color', 'rgb(24, 105, 142)');
111
+ cy.findByLabelText('Centreon-Server_1: Round-Trip Average Time')
112
+ .find('[data-icon="true"]')
113
+ .should('have.css', 'background-color', 'rgb(32, 140, 190)');
114
+
115
+ cy.get('[data-metric="1"]').should(
116
+ 'have.attr',
117
+ 'stroke',
118
+ 'rgb(41, 175, 238)'
119
+ );
120
+ cy.get('[data-metric="21"]').should(
121
+ 'have.attr',
122
+ 'stroke',
123
+ 'rgb(32, 140, 190)'
124
+ );
125
+ cy.get('[data-metric="17"]').should(
126
+ 'have.attr',
127
+ 'stroke',
128
+ 'rgb(24, 105, 142)'
129
+ );
130
+ cy.get('[data-metric="13"]').should(
131
+ 'have.attr',
132
+ 'stroke',
133
+ 'rgb(16, 70, 95)'
134
+ );
135
+ cy.get('[data-metric="9"]').should('have.attr', 'stroke', 'rgb(8, 34, 47)');
136
+ cy.get('[data-metric="5"]').should(
137
+ 'have.attr',
138
+ 'stroke',
139
+ 'rgb(83, 191, 241)'
140
+ );
141
+
142
+ cy.makeSnapshot();
143
+ });
91
144
  });
@@ -5,35 +5,35 @@ import { flatten, gt, isNil, lte, pluck, reduce } from 'ramda';
5
5
 
6
6
  import { ClickAwayListener, Fade, Skeleton, useTheme } from '@mui/material';
7
7
 
8
+ import { Tooltip as MuiTooltip } from '../../components/Tooltip';
9
+ import { Thresholds as ThresholdsModel } from '../common/models';
8
10
  import { getLeftScale, getRightScale, getXScale } from '../common/timeSeries';
9
11
  import { Line } from '../common/timeSeries/models';
10
- import { Thresholds as ThresholdsModel } from '../common/models';
11
- import { Tooltip as MuiTooltip } from '../../components/Tooltip';
12
12
 
13
13
  import Axes from './BasicComponents/Axes';
14
14
  import Grids from './BasicComponents/Grids';
15
15
  import Lines from './BasicComponents/Lines';
16
16
  import { canDisplayThreshold } from './BasicComponents/Lines/Threshold/models';
17
+ import { CurveType } from './BasicComponents/Lines/models';
18
+ import Thresholds from './BasicComponents/Thresholds';
17
19
  import useFilterLines from './BasicComponents/useFilterLines';
18
- import { useStyles } from './LineChart.styles';
19
20
  import Header from './Header';
20
21
  import InteractionWithGraph from './InteractiveComponents';
22
+ import GraphValueTooltip from './InteractiveComponents/GraphValueTooltip/GraphValueTooltip';
21
23
  import GraphTooltip from './InteractiveComponents/Tooltip';
22
24
  import useGraphTooltip from './InteractiveComponents/Tooltip/useGraphTooltip';
23
25
  import Legend from './Legend';
26
+ import { legendWidth } from './Legend/Legend.styles';
27
+ import { useStyles } from './LineChart.styles';
24
28
  import { margin } from './common';
25
29
  import {
26
30
  Data,
27
31
  GlobalAreaLines,
28
32
  GraphInterval,
29
- LineChartProps,
30
- LegendModel
33
+ LegendModel,
34
+ LineChartProps
31
35
  } from './models';
32
36
  import { useIntersection } from './useLineChartIntersection';
33
- import { CurveType } from './BasicComponents/Lines/models';
34
- import Thresholds from './BasicComponents/Thresholds';
35
- import { legendWidth } from './Legend/Legend.styles';
36
- import GraphValueTooltip from './InteractiveComponents/GraphValueTooltip/GraphValueTooltip';
37
37
 
38
38
  const extraMargin = 10;
39
39
 
@@ -292,6 +292,7 @@ const LineChart = ({
292
292
  <div ref={legendRef}>
293
293
  <Legend
294
294
  base={baseAxis}
295
+ height={height}
295
296
  limitLegend={limitLegend}
296
297
  lines={newLines}
297
298
  renderExtraComponent={legend?.renderExtraComponent}
@@ -34,6 +34,7 @@ import dataLastMonth from './mockedData/lastMonth.json';
34
34
  import dataLastWeek from './mockedData/lastWeek.json';
35
35
  import dataZoomPreview from './mockedData/zoomPreview.json';
36
36
  import dataLastDay from './mockedData/lastDay.json';
37
+ import dataCurvesSameColor from './mockedData/curvesWithSameColor.json';
37
38
  import { Interval, ThresholdType, TooltipData } from './models';
38
39
 
39
40
  import WrapperLineChart from './index';
@@ -478,3 +479,15 @@ export const thresholdsRange: Story = {
478
479
  />
479
480
  )
480
481
  };
482
+
483
+ export const LineChartWithSameColorCurves: Story = {
484
+ ...Template,
485
+ argTypes,
486
+ args: argumentsData,
487
+ render: (args) => (
488
+ <WrapperLineChart
489
+ {...args}
490
+ data={dataCurvesSameColor as unknown as LineChartData}
491
+ />
492
+ )
493
+ };