@centreon/ui 24.6.1 → 24.6.3

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 (50) hide show
  1. package/package.json +1 -1
  2. package/src/Dashboard/Item.tsx +18 -3
  3. package/src/Dashboard/Layout.tsx +15 -1
  4. package/src/Dashboard/atoms.ts +3 -0
  5. package/src/Graph/BarStack/BarStack.cypress.spec.tsx +1 -1
  6. package/src/Graph/BarStack/BarStack.stories.tsx +15 -0
  7. package/src/Graph/BarStack/BarStack.styles.ts +5 -1
  8. package/src/Graph/BarStack/ResponsiveBarStack.tsx +18 -15
  9. package/src/Graph/BarStack/useResponsiveBarStack.ts +4 -8
  10. package/src/Graph/Gauge/AnimatedPie.tsx +3 -1
  11. package/src/Graph/Gauge/Gauge.stories.tsx +10 -2
  12. package/src/Graph/Gauge/PieData.tsx +9 -4
  13. package/src/Graph/Gauge/ResponsiveGauge.tsx +55 -69
  14. package/src/Graph/Gauge/Thresholds.tsx +5 -3
  15. package/src/Graph/Gauge/utils.ts +4 -0
  16. package/src/Graph/HeatMap/HeatMap.tsx +3 -1
  17. package/src/Graph/HeatMap/ResponsiveHeatMap.tsx +12 -4
  18. package/src/Graph/LineChart/Header/index.tsx +2 -2
  19. package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/useTickGraph.ts +1 -1
  20. package/src/Graph/LineChart/InteractiveComponents/GraphValueTooltip/useGraphValueTooltip.ts +5 -3
  21. package/src/Graph/LineChart/Legend/Legend.styles.ts +10 -3
  22. package/src/Graph/LineChart/Legend/LegendHeader.tsx +3 -1
  23. package/src/Graph/LineChart/Legend/index.tsx +19 -3
  24. package/src/Graph/LineChart/LineChart.styles.ts +4 -47
  25. package/src/Graph/LineChart/LineChart.tsx +132 -211
  26. package/src/Graph/LineChart/index.stories.tsx +3 -1
  27. package/src/Graph/LineChart/models.ts +1 -5
  28. package/src/Graph/PieChart/PieChart.cypress.spec.tsx +1 -1
  29. package/src/Graph/PieChart/PieChart.stories.tsx +14 -0
  30. package/src/Graph/PieChart/ResponsivePie.tsx +15 -9
  31. package/src/Graph/PieChart/useResponsivePie.ts +0 -3
  32. package/src/Graph/SingleBar/ResponsiveSingleBar.tsx +65 -68
  33. package/src/Graph/SingleBar/SingleBar.stories.tsx +28 -0
  34. package/src/Graph/SingleBar/ThresholdLine.tsx +14 -18
  35. package/src/Graph/SingleBar/Thresholds.tsx +9 -1
  36. package/src/Graph/Text/Text.stories.tsx +32 -0
  37. package/src/Graph/Text/Text.styles.ts +0 -1
  38. package/src/Graph/Text/Text.tsx +11 -7
  39. package/src/Graph/{LineChart/BasicComponents → common}/Axes/UnitLabel.tsx +1 -1
  40. package/src/Graph/{LineChart/BasicComponents → common}/Axes/index.tsx +8 -7
  41. package/src/Graph/{LineChart/BasicComponents → common}/Axes/models.ts +2 -2
  42. package/src/Graph/{LineChart/BasicComponents → common}/Axes/useAxisY.ts +2 -2
  43. package/src/Graph/common/BaseChart/BaseChart.tsx +114 -0
  44. package/src/Graph/common/BaseChart/ChartSvgWrapper.tsx +75 -0
  45. package/src/Graph/common/BaseChart/useBaseChartStyles.ts +38 -0
  46. package/src/Graph/common/BaseChart/useComputeBaseChartDimensions.ts +61 -0
  47. package/src/Graph/{LineChart/BasicComponents → common}/Grids/index.tsx +1 -1
  48. package/src/Graph/common/useTooltipStyles.ts +17 -0
  49. package/src/Graph/common/utils.ts +6 -0
  50. package/src/Typography/FluidTypography/index.tsx +5 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centreon/ui",
3
- "version": "24.6.1",
3
+ "version": "24.6.3",
4
4
  "description": "Centreon UI Components",
5
5
  "scripts": {
6
6
  "update:deps": "pnpx npm-check-updates -i --format group",
@@ -4,10 +4,12 @@ import {
4
4
  forwardRef,
5
5
  MouseEvent,
6
6
  ReactElement,
7
- useEffect
7
+ useEffect,
8
+ useMemo
8
9
  } from 'react';
9
10
 
10
- import { isNil, prop } from 'ramda';
11
+ import { equals, isNil, prop } from 'ramda';
12
+ import { useAtomValue } from 'jotai';
11
13
 
12
14
  import { Card, useTheme } from '@mui/material';
13
15
 
@@ -15,6 +17,7 @@ import { useMemoComponent, useViewportIntersection } from '../utils';
15
17
  import LoadingSkeleton from '../LoadingSkeleton';
16
18
 
17
19
  import { useDashboardItemStyles } from './Dashboard.styles';
20
+ import { isResizingItemAtom } from './atoms';
18
21
 
19
22
  interface DashboardItemProps {
20
23
  additionalMemoProps?: Array<unknown>;
@@ -55,6 +58,18 @@ const Item = forwardRef<HTMLDivElement, DashboardItemProps>(
55
58
  const { classes, cx } = useDashboardItemStyles({ hasHeader });
56
59
  const theme = useTheme();
57
60
 
61
+ const isResizingItem = useAtomValue(isResizingItemAtom);
62
+
63
+ const isResizing = useMemo(
64
+ () => equals(id, isResizingItem),
65
+ [isResizingItem, id]
66
+ );
67
+
68
+ const sanitizedReactGridLayoutClassName = useMemo(
69
+ () => (isResizing ? className : className?.replace(' resizing ', '')),
70
+ [className, isResizing]
71
+ );
72
+
58
73
  const listeners = {
59
74
  onMouseDown,
60
75
  onMouseUp,
@@ -75,7 +90,7 @@ const Item = forwardRef<HTMLDivElement, DashboardItemProps>(
75
90
  Component: (
76
91
  <div
77
92
  {...cardContainerListeners}
78
- className={className}
93
+ className={sanitizedReactGridLayoutClassName}
79
94
  ref={ref}
80
95
  style={{
81
96
  ...style,
@@ -1,5 +1,6 @@
1
- import { useEffect, useState } from 'react';
1
+ import { useCallback, useEffect, useState } from 'react';
2
2
 
3
+ import { useSetAtom } from 'jotai';
3
4
  import GridLayout, { Layout, WidthProvider } from 'react-grid-layout';
4
5
  import 'react-grid-layout/css/styles.css';
5
6
 
@@ -12,6 +13,7 @@ import {
12
13
  import { useDashboardLayoutStyles } from './Dashboard.styles';
13
14
  import { getColumnsFromScreenSize, getLayout, rowHeight } from './utils';
14
15
  import Grid from './Grid';
16
+ import { isResizingItemAtom } from './atoms';
15
17
 
16
18
  const ReactGridLayout = WidthProvider(GridLayout);
17
19
 
@@ -36,10 +38,20 @@ const DashboardLayout = <T extends Layout>({
36
38
 
37
39
  const [columns, setColumns] = useState(getColumnsFromScreenSize());
38
40
 
41
+ const setIsResizingItem = useSetAtom(isResizingItemAtom);
42
+
39
43
  const resize = (): void => {
40
44
  setColumns(getColumnsFromScreenSize());
41
45
  };
42
46
 
47
+ const startResize = useCallback((_, __, newItem: T) => {
48
+ setIsResizingItem(newItem.i);
49
+ }, []);
50
+
51
+ const stopResize = useCallback(() => {
52
+ setIsResizingItem(null);
53
+ }, []);
54
+
43
55
  useEffect(() => {
44
56
  window.addEventListener('resize', resize);
45
57
 
@@ -66,6 +78,8 @@ const DashboardLayout = <T extends Layout>({
66
78
  rowHeight={rowHeight}
67
79
  width={width}
68
80
  onLayoutChange={changeLayout}
81
+ onResizeStart={startResize}
82
+ onResizeStop={stopResize}
69
83
  >
70
84
  {children}
71
85
  </ReactGridLayout>
@@ -0,0 +1,3 @@
1
+ import { atom } from 'jotai';
2
+
3
+ export const isResizingItemAtom = atom<string | null>(null);
@@ -55,7 +55,7 @@ describe('Bar stack', () => {
55
55
  it('adjusts size based on the provided width and height', () => {
56
56
  initialize({ displayLegend: false, height: '300px', width: '300px' });
57
57
 
58
- cy.findByTestId('barStack').should('have.css', 'height', '300px');
58
+ cy.findByTestId('barStack').should('have.css', 'height', '270px');
59
59
 
60
60
  cy.makeSnapshot();
61
61
  });
@@ -50,6 +50,10 @@ const Template = (args): JSX.Element => {
50
50
  return <ResponsiveBarStack height={300} width={500} {...args} />;
51
51
  };
52
52
 
53
+ const SmallTemplate = (args): JSX.Element => {
54
+ return <ResponsiveBarStack height={120} width={120} {...args} />;
55
+ };
56
+
53
57
  export const Vertical: Story = {
54
58
  args: { data, title: 'hosts' },
55
59
  render: Template
@@ -123,3 +127,14 @@ export const HorizontalWithoutLegend: Story = {
123
127
  },
124
128
  render: Template
125
129
  };
130
+
131
+ export const SmallDisplay: Story = {
132
+ args: {
133
+ TooltipContent,
134
+ data,
135
+ displayValues: true,
136
+ title: 'hosts',
137
+ variant: 'horizontal'
138
+ },
139
+ render: SmallTemplate
140
+ };
@@ -13,12 +13,16 @@ export const useBarStackStyles = makeStyles()((theme) => ({
13
13
  gap: theme.spacing(1.5),
14
14
  justifyContent: 'center'
15
15
  },
16
+ smallTitle: {
17
+ fontSize: theme.typography.body1.fontSize
18
+ },
16
19
  svgContainer: {
17
20
  alignItems: 'center',
18
21
  backgroundColor: theme.palette.background.panelGroups,
19
22
  borderRadius: theme.spacing(1.25),
20
23
  display: 'flex',
21
- justifyContent: 'center'
24
+ justifyContent: 'center',
25
+ padding: theme.spacing(1)
22
26
  },
23
27
  svgWrapper: {
24
28
  alignItems: 'center',
@@ -5,7 +5,7 @@ import { Group } from '@visx/group';
5
5
  import numeral from 'numeral';
6
6
  import { Text } from '@visx/text';
7
7
  import { useTranslation } from 'react-i18next';
8
- import { equals } from 'ramda';
8
+ import { equals, lt } from 'ramda';
9
9
 
10
10
  import { Tooltip } from '../../components';
11
11
  import { LegendProps } from '../Legend/models';
@@ -36,7 +36,7 @@ const ResponsiveBarStack = ({
36
36
  legendDirection = 'column'
37
37
  }: BarStackProps & { height: number; width: number }): JSX.Element => {
38
38
  const { t } = useTranslation();
39
- const { classes } = useBarStackStyles();
39
+ const { classes, cx } = useBarStackStyles();
40
40
 
41
41
  const titleRef = useRef(null);
42
42
  const legendRef = useRef(null);
@@ -50,7 +50,6 @@ const ResponsiveBarStack = ({
50
50
  total,
51
51
  xScale,
52
52
  yScale,
53
- svgWrapperWidth,
54
53
  svgContainerSize,
55
54
  isVerticalBar
56
55
  } = useResponsiveBarStack({
@@ -68,24 +67,28 @@ const ResponsiveBarStack = ({
68
67
  ? BarStackVertical
69
68
  : BarStackHorizontal;
70
69
 
70
+ const isSmallHeight = isVerticalBar ? lt(height, 190) : lt(height, 100);
71
+ const isSmallWidth = isVerticalBar ? lt(width, 80) : lt(width, 350);
72
+ const mustDisplayLegend = isSmallWidth ? false : displayLegend;
73
+
71
74
  return (
72
- <div className={classes.container} style={{ height, width }}>
73
- <div
74
- className={classes.svgWrapper}
75
- style={{
76
- minHeight: height,
77
- width: svgWrapperWidth
78
- }}
79
- >
75
+ <div className={classes.container} style={{ width }}>
76
+ <div className={classes.svgWrapper}>
80
77
  {title && (
81
- <div className={classes.title} data-testid="Title" ref={titleRef}>
78
+ <div
79
+ className={cx(classes.title, isSmallHeight && classes.smallTitle)}
80
+ data-testid="Title"
81
+ ref={titleRef}
82
+ >
82
83
  {`${numeral(total).format('0a').toUpperCase()} `} {t(title)}
83
84
  </div>
84
85
  )}
85
86
  <div
86
87
  className={classes.svgContainer}
87
88
  data-testid="barStack"
88
- style={svgContainerSize}
89
+ style={{
90
+ width: svgContainerSize.width
91
+ }}
89
92
  >
90
93
  <svg
91
94
  data-variant={variant}
@@ -155,7 +158,7 @@ const ResponsiveBarStack = ({
155
158
  isVerticalBar ? bar.height - 1 : bar.height
156
159
  }
157
160
  key={`bar-stack-${barStack.index}-${bar.index}`}
158
- ry={10}
161
+ ry={4}
159
162
  width={isVerticalBar ? bar.width : bar.width - 1}
160
163
  x={bar.x}
161
164
  y={bar.y}
@@ -190,7 +193,7 @@ const ResponsiveBarStack = ({
190
193
  </svg>
191
194
  </div>
192
195
  </div>
193
- {displayLegend && (
196
+ {mustDisplayLegend && (
194
197
  <div data-testid="Legend" ref={legendRef}>
195
198
  <Legend
196
199
  data={data}
@@ -1,5 +1,5 @@
1
1
  import { scaleBand, scaleLinear, scaleOrdinal } from '@visx/scale';
2
- import { equals, pluck } from 'ramda';
2
+ import { equals, gt, pluck } from 'ramda';
3
3
 
4
4
  import { getValueByUnit } from '../common/utils';
5
5
  import { LegendScale } from '../Legend/models';
@@ -29,7 +29,6 @@ interface useBarStackState {
29
29
  keys: Array<string>;
30
30
  legendScale: LegendScale;
31
31
  svgContainerSize: Size;
32
- svgWrapperWidth: number;
33
32
  total: number;
34
33
  xScale;
35
34
  yScale;
@@ -53,17 +52,15 @@ const useResponsiveBarStack = ({
53
52
  const horizontalGap = widthOfLegend > 0 ? 12 : 0;
54
53
  const verticalGap = heightOfTitle > 0 ? 8 : 0;
55
54
 
56
- const svgWrapperWidth = isVerticalBar
57
- ? size + 36
58
- : width - widthOfLegend - horizontalGap;
59
-
60
55
  const svgContainerSize = {
61
56
  height: isVerticalBar ? height - heightOfTitle - verticalGap : size,
62
57
  width: isVerticalBar ? size : width - widthOfLegend - horizontalGap
63
58
  };
64
59
 
65
60
  const barSize = {
66
- height: svgContainerSize.height - 16,
61
+ height: gt(height / 2, svgContainerSize.height - 16)
62
+ ? svgContainerSize.height - 16
63
+ : svgContainerSize.height - 46,
67
64
  width: svgContainerSize.width - 16
68
65
  };
69
66
 
@@ -121,7 +118,6 @@ const useResponsiveBarStack = ({
121
118
  keys,
122
119
  legendScale,
123
120
  svgContainerSize,
124
- svgWrapperWidth,
125
121
  total,
126
122
  xScale,
127
123
  yScale
@@ -85,7 +85,9 @@ const AnimatedPie = <Datum,>({
85
85
  'label',
86
86
  thresholds[thresholdType as 'warning' | 'critical']
87
87
  ).map((label) => (
88
- <Typography key={label}>{label}</Typography>
88
+ <Typography key={label} variant="body2">
89
+ {label}
90
+ </Typography>
89
91
  ))}
90
92
  </div>
91
93
  ),
@@ -12,8 +12,16 @@ export default meta;
12
12
  type Story = StoryObj<typeof Gauge>;
13
13
 
14
14
  const Template = (props): JSX.Element => (
15
- <div style={{ height: '500px', width: '500px' }}>
16
- <Gauge {...props} />
15
+ <div style={{ display: 'flex', flexDirection: 'row' }}>
16
+ <div style={{ height: '500px', width: '500px' }}>
17
+ <Gauge {...props} />
18
+ </div>
19
+ <div style={{ height: '100px', width: '120px' }}>
20
+ <Gauge {...props} />
21
+ </div>
22
+ <div style={{ height: '300px', width: '200px' }}>
23
+ <Gauge {...props} />
24
+ </div>
17
25
  </div>
18
26
  );
19
27
 
@@ -9,6 +9,7 @@ import { getColorFromDataAndTresholds } from '../common/utils';
9
9
  import { thresholdThickness } from './Thresholds';
10
10
  import AnimatedPie from './AnimatedPie';
11
11
  import { GaugeProps } from './models';
12
+ import { angles } from './utils';
12
13
 
13
14
  const dataThickness = 45;
14
15
 
@@ -37,15 +38,19 @@ const PieData = ({
37
38
  range: [pieColor, 'transparent']
38
39
  });
39
40
 
41
+ const dataThicknessFactor = radius / dataThickness / 3;
42
+ const thresholdThicknessFactor = radius / thresholdThickness / 15;
43
+
40
44
  return (
41
45
  <Pie
46
+ {...angles}
42
47
  data={pieData}
43
- endAngle={-Math.PI / 2}
44
- innerRadius={radius - dataThickness}
45
- outerRadius={radius - thresholdThickness * 1.3}
48
+ innerRadius={radius - dataThickness * dataThicknessFactor}
49
+ outerRadius={
50
+ radius - thresholdThickness * thresholdThicknessFactor * 1.25
51
+ }
46
52
  pieSortValues={() => -1}
47
53
  pieValue={identity}
48
- startAngle={Math.PI / 2}
49
54
  >
50
55
  {(pie) => (
51
56
  <AnimatedPie<number>
@@ -1,15 +1,17 @@
1
1
  import { useRef } from 'react';
2
2
 
3
3
  import { Group } from '@visx/group';
4
- import { flatten, head, pluck } from 'ramda';
5
4
  import { Tooltip } from '@visx/visx';
5
+ import { flatten, head, pluck } from 'ramda';
6
6
 
7
- import { Box, Fade, useTheme } from '@mui/material';
7
+ import { Box, useTheme } from '@mui/material';
8
8
 
9
9
  import { Metric } from '../common/timeSeries/models';
10
10
  import { formatMetricValueWithUnit } from '../common/timeSeries';
11
11
  import { getColorFromDataAndTresholds } from '../common/utils';
12
12
  import { margins } from '../common/margins';
13
+ import { Tooltip as MuiTooltip } from '../../components/Tooltip';
14
+ import { useTooltipStyles } from '../common/useTooltipStyles';
13
15
 
14
16
  import Thresholds from './Thresholds';
15
17
  import PieData from './PieData';
@@ -22,11 +24,6 @@ interface Props extends Pick<GaugeProps, 'thresholds' | 'baseColor'> {
22
24
  width: number;
23
25
  }
24
26
 
25
- const baseStyles = {
26
- ...Tooltip.defaultStyles,
27
- textAlign: 'center'
28
- };
29
-
30
27
  const ResponsiveGauge = ({
31
28
  width,
32
29
  height,
@@ -35,24 +32,21 @@ const ResponsiveGauge = ({
35
32
  displayAsRaw,
36
33
  baseColor
37
34
  }: Props): JSX.Element => {
35
+ const { classes } = useTooltipStyles();
38
36
  const svgRef = useRef<SVGSVGElement>(null);
39
37
 
40
38
  const theme = useTheme();
41
39
 
42
- const {
43
- showTooltip,
44
- hideTooltip,
45
- tooltipOpen,
46
- tooltipLeft,
47
- tooltipTop,
48
- tooltipData
49
- } = Tooltip.useTooltip();
40
+ const { showTooltip, hideTooltip, tooltipOpen, tooltipData } =
41
+ Tooltip.useTooltip();
50
42
 
51
43
  const innerWidth = width - margins.left - margins.right;
52
44
  const innerHeight = height - margins.top - margins.bottom;
53
45
  const centerY = innerHeight / 2;
54
46
  const centerX = innerWidth / 2;
55
- const radius = Math.min(innerWidth, innerHeight) / 2;
47
+ const baseSize = Math.min(width, height);
48
+ const heightOverWidthRatio = height / width;
49
+ const radius = baseSize / (heightOverWidthRatio > 0.9 ? 2 : 1.8);
56
50
  const thresholdValues = thresholds.enabled
57
51
  ? flatten([
58
52
  pluck('value', thresholds.warning),
@@ -72,11 +66,6 @@ const ResponsiveGauge = ({
72
66
  thresholds
73
67
  });
74
68
 
75
- const svgTop = svgRef.current?.getBoundingClientRect().top || 0;
76
- const svgLeft = svgRef.current?.getBoundingClientRect().left || 0;
77
-
78
- const isSmallWidget = height < 240;
79
-
80
69
  const gaugeValue = formatMetricValueWithUnit({
81
70
  base: 1000,
82
71
  isRaw: displayAsRaw,
@@ -93,54 +82,51 @@ const ResponsiveGauge = ({
93
82
  width: '100%'
94
83
  }}
95
84
  >
96
- <svg height={height} ref={svgRef} width={width}>
97
- <Group left={centerX + margins.left} top={centerY + height / 6}>
98
- <Thresholds
99
- adaptedMaxValue={adaptedMaxValue}
100
- hideTooltip={hideTooltip}
101
- metric={metric}
102
- radius={radius}
103
- showTooltip={showTooltip}
104
- thresholds={thresholds}
105
- />
106
- <PieData
107
- adaptedMaxValue={adaptedMaxValue}
108
- baseColor={baseColor}
109
- metric={metric}
110
- radius={radius}
111
- thresholds={thresholds}
112
- />
113
- </Group>
114
- <text
115
- dominantBaseline="middle"
116
- style={{
117
- fill: pieColor,
118
- ...theme.typography.h3,
119
- fontSize:
120
- Math.min(width, height) / 7 -
121
- (isSmallWidget ? 0 : (gaugeValue?.length || 0) * 2)
122
- }}
123
- textAnchor="middle"
124
- x="50%"
125
- y={isSmallWidget ? 130 : height - height / 2.3}
126
- >
127
- {gaugeValue}
128
- </text>
129
- </svg>
130
- <Fade in={tooltipOpen && thresholds.enabled}>
131
- <Tooltip.Tooltip
132
- left={(tooltipLeft || 0) - svgLeft}
133
- style={{
134
- ...baseStyles,
135
- backgroundColor: theme.palette.background.paper,
136
- color: theme.palette.text.primary,
137
- transform: 'translate(-50%, -24px)'
138
- }}
139
- top={(tooltipTop || 0) - svgTop + 20}
140
- >
141
- {tooltipData}
142
- </Tooltip.Tooltip>
143
- </Fade>
85
+ <MuiTooltip
86
+ classes={{
87
+ tooltip: classes.tooltip
88
+ }}
89
+ label={tooltipData}
90
+ open={thresholds.enabled && tooltipOpen}
91
+ placement="top"
92
+ >
93
+ <svg height={height} ref={svgRef} width={width}>
94
+ <Group
95
+ left={centerX + margins.left}
96
+ top={centerY + margins.top + baseSize / 8}
97
+ >
98
+ <Thresholds
99
+ adaptedMaxValue={adaptedMaxValue}
100
+ hideTooltip={hideTooltip}
101
+ metric={metric}
102
+ radius={radius}
103
+ showTooltip={showTooltip}
104
+ thresholds={thresholds}
105
+ />
106
+ <PieData
107
+ adaptedMaxValue={adaptedMaxValue}
108
+ baseColor={baseColor}
109
+ metric={metric}
110
+ radius={radius}
111
+ thresholds={thresholds}
112
+ />
113
+ <text
114
+ dominantBaseline="middle"
115
+ style={{
116
+ fill: pieColor,
117
+ ...theme.typography.h3,
118
+ fontSize:
119
+ Math.min(width, height) / (gaugeValue?.length || 1) + 3
120
+ }}
121
+ textAnchor="middle"
122
+ x="0%"
123
+ y="0%"
124
+ >
125
+ {gaugeValue}
126
+ </text>
127
+ </Group>
128
+ </svg>
129
+ </MuiTooltip>
144
130
  </Box>
145
131
  );
146
132
  };
@@ -6,6 +6,7 @@ import { useTheme } from '@mui/material';
6
6
 
7
7
  import AnimatedPie from './AnimatedPie';
8
8
  import { GaugeProps } from './models';
9
+ import { angles } from './utils';
9
10
 
10
11
  export const thresholdThickness = 12;
11
12
 
@@ -83,18 +84,19 @@ const Thresholds = ({
83
84
  }
84
85
  ];
85
86
 
87
+ const thresholdThicknessFactor = radius / thresholdThickness / 15;
88
+
86
89
  return (
87
90
  <>
88
91
  {arcs.map(({ thresholdArc, thresholdScaleOrdinal }) => (
89
92
  <Pie
93
+ {...angles}
90
94
  data={thresholdArc}
91
- endAngle={-Math.PI / 2}
92
- innerRadius={radius - thresholdThickness}
95
+ innerRadius={radius - thresholdThickness * thresholdThicknessFactor}
93
96
  key={`arc-${thresholdArc[0].name}`}
94
97
  outerRadius={radius}
95
98
  pieSortValues={() => -1}
96
99
  pieValue={(d) => d.value}
97
- startAngle={Math.PI / 2}
98
100
  >
99
101
  {(pie) => (
100
102
  <AnimatedPie<{ name: string; value: number }>
@@ -0,0 +1,4 @@
1
+ export const angles = {
2
+ endAngle: -(2 * Math.PI) / 3,
3
+ startAngle: (2 * Math.PI) / 3
4
+ };
@@ -5,7 +5,9 @@ import { HeatMapProps } from './model';
5
5
 
6
6
  const HeatMap = <TData,>(props: HeatMapProps<TData>): JSX.Element => (
7
7
  <ParentSize>
8
- {({ width }) => <ResponsiveHeatMap<TData> {...props} width={width} />}
8
+ {({ width, height }) => (
9
+ <ResponsiveHeatMap<TData> {...props} height={height} width={width} />
10
+ )}
9
11
  </ParentSize>
10
12
  );
11
13
 
@@ -21,8 +21,12 @@ const ResponsiveHeatMap = <TData,>({
21
21
  arrowClassName,
22
22
  tooltipContent,
23
23
  tileSizeFixed,
24
- displayTooltipCondition = T
25
- }: HeatMapProps<TData> & { width: number }): JSX.Element | null => {
24
+ displayTooltipCondition = T,
25
+ height
26
+ }: HeatMapProps<TData> & {
27
+ height: number;
28
+ width: number;
29
+ }): JSX.Element | null => {
26
30
  const { classes, cx } = useHeatMapStyles();
27
31
 
28
32
  const tileSize = useMemo(() => {
@@ -40,7 +44,11 @@ const ResponsiveHeatMap = <TData,>({
40
44
  const theoricalTotalTilesWidth =
41
45
  tilesLength * tileWidth + (tilesLength - 1) * gap;
42
46
 
43
- if (lt(width, 680) && gt(maxTotalTilesWidth, width) && !tileSizeFixed) {
47
+ if (
48
+ (lt(height, maxTileSize) ||
49
+ (lt(width, 680) && gt(maxTotalTilesWidth, width))) &&
50
+ !tileSizeFixed
51
+ ) {
44
52
  return smallestTileSize;
45
53
  }
46
54
 
@@ -49,7 +57,7 @@ const ResponsiveHeatMap = <TData,>({
49
57
  }
50
58
 
51
59
  return tileSizeFixed ? maxTileSize : tileWidth;
52
- }, [width, tiles]);
60
+ }, [width, tiles, height]);
53
61
 
54
62
  const isSmallestSize = equals(tileSize, smallestTileSize);
55
63
 
@@ -2,7 +2,7 @@ import Typography from '@mui/material/Typography';
2
2
 
3
3
  import { useMemoComponent } from '@centreon/ui';
4
4
 
5
- import { useStyles } from '../LineChart.styles';
5
+ import { useLineChartStyles } from '../LineChart.styles';
6
6
  import { LineChartHeader } from '../models';
7
7
 
8
8
  interface Props {
@@ -11,7 +11,7 @@ interface Props {
11
11
  }
12
12
 
13
13
  const Header = ({ title, header }: Props): JSX.Element => {
14
- const { classes } = useStyles();
14
+ const { classes } = useLineChartStyles();
15
15
 
16
16
  const displayTitle = header?.displayTitle ?? true;
17
17
 
@@ -3,7 +3,7 @@ import { useEffect, useState } from 'react';
3
3
  import { ScaleLinear } from 'd3-scale';
4
4
  import { useAtomValue } from 'jotai';
5
5
 
6
- import useAxisY from '../../BasicComponents/Axes/useAxisY';
6
+ import useAxisY from '../../../common/Axes/useAxisY';
7
7
  import { margin } from '../../common';
8
8
  import { getTimeValue } from '../../../common/timeSeries';
9
9
  import { Line, TimeValue } from '../../../common/timeSeries/models';
@@ -7,7 +7,8 @@ import {
7
7
  isNil,
8
8
  prop,
9
9
  reverse,
10
- sortBy
10
+ sortBy,
11
+ T
11
12
  } from 'ramda';
12
13
 
13
14
  import { graphTooltipDataAtom } from '../interactionWithGraphAtoms';
@@ -29,7 +30,7 @@ export const useGraphValueTooltip = ({
29
30
  const { toDate, toTime } = useLocaleDateTimeFormat();
30
31
  const graphTooltipData = useAtomValue(graphTooltipDataAtom);
31
32
 
32
- if (isNil(graphTooltipData)) {
33
+ if (isNil(graphTooltipData) || isNil(graphTooltipData.metrics)) {
33
34
  return null;
34
35
  }
35
36
 
@@ -48,7 +49,8 @@ export const useGraphValueTooltip = ({
48
49
  [
49
50
  equals('descending'),
50
51
  always(reverse(sortBy(prop('value'), filteredMetrics)))
51
- ]
52
+ ],
53
+ [T, always(filteredMetrics)]
52
54
  ])(sortOrder);
53
55
 
54
56
  return {