@centreon/ui 25.10.29 → 25.10.30

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 (69) hide show
  1. package/package.json +3 -3
  2. package/public/mockServiceWorker.js +8 -31
  3. package/src/Dashboard/Item.tsx +142 -149
  4. package/src/Form/Inputs/ConnectedAutocomplete.tsx +2 -0
  5. package/src/Form/Inputs/Grid.tsx +2 -3
  6. package/src/Form/Inputs/models.ts +2 -0
  7. package/src/Form/Section/navigateToSection.ts +6 -6
  8. package/src/Graph/BarChart/BarChart.cypress.spec.tsx +55 -102
  9. package/src/Graph/BarChart/BarChart.stories.tsx +1 -51
  10. package/src/Graph/BarChart/BarChart.tsx +1 -1
  11. package/src/Graph/BarChart/BarGroup.tsx +32 -22
  12. package/src/Graph/BarChart/BarStack.tsx +26 -15
  13. package/src/Graph/BarChart/MemoizedGroup.tsx +18 -14
  14. package/src/Graph/BarChart/ResponsiveBarChart.tsx +6 -7
  15. package/src/Graph/BarChart/Tooltip/BarChartTooltip.tsx +2 -2
  16. package/src/Graph/Chart/BasicComponents/Lines/StackedLines/index.tsx +5 -4
  17. package/src/Graph/Chart/BasicComponents/Lines/StackedLines/useStackedLines.ts +45 -18
  18. package/src/Graph/Chart/BasicComponents/Lines/index.tsx +118 -124
  19. package/src/Graph/Chart/Chart.cypress.spec.tsx +6 -25
  20. package/src/Graph/Chart/Chart.stories.tsx +1 -43
  21. package/src/Graph/Chart/Chart.tsx +13 -9
  22. package/src/Graph/Chart/InteractiveComponents/GraphValueTooltip/useGraphValueTooltip.ts +4 -2
  23. package/src/Graph/Chart/Legend/index.tsx +2 -26
  24. package/src/Graph/Chart/index.tsx +45 -31
  25. package/src/Graph/Chart/models.ts +1 -6
  26. package/src/Graph/Chart/translatedLabels.ts +1 -0
  27. package/src/Graph/Chart/useChartData.ts +24 -3
  28. package/src/Graph/common/Axes/index.tsx +1 -1
  29. package/src/Graph/common/BaseChart/BaseChart.tsx +1 -6
  30. package/src/Graph/common/BaseChart/ChartSvgWrapper.tsx +23 -16
  31. package/src/Graph/common/Error/NoData.tsx +18 -0
  32. package/src/Graph/common/Grids/index.tsx +4 -4
  33. package/src/Graph/common/timeSeries/index.test.ts +4 -24
  34. package/src/Graph/common/timeSeries/index.ts +120 -184
  35. package/src/Graph/common/timeSeries/models.ts +1 -1
  36. package/src/Graph/common/utils.ts +4 -10
  37. package/src/Graph/index.ts +20 -20
  38. package/src/InputField/Select/Autocomplete/Connected/index.tsx +3 -3
  39. package/src/InputField/Select/Autocomplete/Multi/Listbox.tsx +11 -3
  40. package/src/InputField/Select/Autocomplete/Multi/Multi.tsx +3 -2
  41. package/src/InputField/Select/index.tsx +2 -1
  42. package/src/Listing/ActionBar/Pagination.tsx +2 -1
  43. package/src/Listing/ActionBar/index.tsx +113 -8
  44. package/src/Listing/index.tsx +19 -2
  45. package/src/Listing/translatedLabels.ts +4 -0
  46. package/src/Module/index.tsx +2 -8
  47. package/src/ThemeProvider/index.tsx +21 -30
  48. package/src/ThemeProvider/tailwindcss.css +12 -10
  49. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +8 -5
  50. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/models.ts +0 -1
  51. package/src/api/useGraphQuery/index.ts +7 -4
  52. package/src/components/Layout/PageLayout/PageLayout.tsx +3 -9
  53. package/src/components/Layout/PageLayout/PageLayoutActions.tsx +3 -5
  54. package/src/components/Layout/PageLayout/PageLayoutBody.tsx +3 -5
  55. package/src/components/Layout/PageLayout/PageLayoutHeader.tsx +3 -5
  56. package/src/components/Layout/PageLayout/PageQuickAccess.tsx +44 -25
  57. package/src/components/Layout/PageLayout/translatedLabels.ts +1 -0
  58. package/src/components/Menu/Button/MenuButton.styles.ts +27 -0
  59. package/src/components/Menu/Button/MenuButton.tsx +5 -6
  60. package/src/components/Menu/Menu.styles.ts +68 -0
  61. package/src/components/Menu/MenuDivider.tsx +5 -1
  62. package/src/components/Menu/MenuItem.tsx +5 -1
  63. package/src/components/Menu/MenuItems.tsx +4 -5
  64. package/src/components/Modal/Modal.styles.ts +2 -1
  65. package/src/components/Modal/ModalHeader.tsx +1 -5
  66. package/src/utils/useInfiniteScrollListing.ts +11 -7
  67. package/src/utils/useViewportIntersection.ts +3 -4
  68. package/src/Graph/mockedData/dataWithMissingPoint.json +0 -74
  69. package/src/Graph/mockedData/pingServiceWithStackedKeys.json +0 -205
@@ -101,40 +101,34 @@ const Lines = ({
101
101
  {(areaStackedLines?.display ?? true) && (
102
102
  <>
103
103
  {Object.entries(stackedLinesData).map(
104
- ([stackedKey, { lines, timeSeries: stackedTimeSeries }]) => {
105
- const [, unit] = stackedKey.split('-');
106
- return (
107
- <StackedLines
108
- lineStyle={lineStyle}
109
- key={`stacked-${unit}`}
110
- lines={lines}
111
- timeSeries={stackedTimeSeries}
112
- yScale={yScalesPerUnit[unit || undefined]}
113
- {...commonStackedLinesProps}
114
- />
115
- );
116
- }
104
+ ([unit, { lines, timeSeries: stackedTimeSeries }]) => (
105
+ <StackedLines
106
+ lineStyle={lineStyle}
107
+ key={`stacked-${unit}`}
108
+ lines={lines}
109
+ timeSeries={stackedTimeSeries}
110
+ yScale={yScalesPerUnit[unit] ?? undefined}
111
+ {...commonStackedLinesProps}
112
+ />
113
+ )
117
114
  )}
118
115
  {Object.entries(invertedStackedLinesData).map(
119
- ([stackedKey, { lines, timeSeries: stackedTimeSeries }]) => {
120
- const [, unit] = stackedKey.split('-');
121
- return (
122
- <StackedLines
123
- lineStyle={lineStyle}
124
- key={`invert-stacked-${unit}`}
125
- lines={lines}
126
- timeSeries={stackedTimeSeries}
127
- yScale={getYScale({
128
- invert: '1',
129
- scale,
130
- scaleLogarithmicBase,
131
- unit: unit || undefined,
132
- yScalesPerUnit
133
- })}
134
- {...commonStackedLinesProps}
135
- />
136
- );
137
- }
116
+ ([unit, { lines, timeSeries: stackedTimeSeries }]) => (
117
+ <StackedLines
118
+ lineStyle={lineStyle}
119
+ key={`invert-stacked-${unit}`}
120
+ lines={lines}
121
+ timeSeries={stackedTimeSeries}
122
+ yScale={getYScale({
123
+ invert: '1',
124
+ scale,
125
+ scaleLogarithmicBase,
126
+ unit: unit ?? undefined,
127
+ yScalesPerUnit
128
+ })}
129
+ {...commonStackedLinesProps}
130
+ />
131
+ )
138
132
  )}
139
133
  </>
140
134
  )}
@@ -152,107 +146,107 @@ const Lines = ({
152
146
 
153
147
  {displayAreaRegularLines
154
148
  ? regularLines.map(
155
- ({
156
- areaColor,
157
- transparency,
158
- lineColor,
159
- filled,
149
+ ({
150
+ areaColor,
151
+ transparency,
152
+ lineColor,
153
+ filled,
154
+ unit,
155
+ highlight,
156
+ invert,
157
+ metric_id,
158
+ ...rest
159
+ }) => {
160
+ const yScale = getYScale({
161
+ invert,
162
+ scale,
163
+ scaleLogarithmicBase,
160
164
  unit,
161
- highlight,
165
+ yScalesPerUnit
166
+ });
167
+ const relatedTimeSeries = getTimeSeriesForLines({
162
168
  invert,
163
- metric_id,
164
- ...rest
165
- }) => {
166
- const yScale = getYScale({
167
- invert,
168
- scale,
169
- scaleLogarithmicBase,
170
- unit,
171
- yScalesPerUnit
172
- });
173
- const relatedTimeSeries = getTimeSeriesForLines({
174
- invert,
175
- lines: [
176
- {
177
- areaColor,
178
- filled,
179
- highlight,
180
- invert,
181
- lineColor,
182
- metric_id,
183
- transparency,
184
- unit,
185
- ...rest
186
- }
187
- ],
188
- timeSeries
189
- });
190
-
191
- const style = getStyle({
192
- style: lineStyle,
193
- metricId: metric_id
194
- }) as LineStyle;
195
-
196
- return (
197
- <g key={metric_id}>
198
- {displayGuidingLines && (
199
- <RegularAnchorPoint
200
- areaColor={areaColor || lineColor}
201
- lineColor={lineColor}
202
- metric_id={metric_id}
203
- timeSeries={relatedTimeSeries}
204
- transparency={transparency}
205
- xScale={xScale}
206
- yScale={yScale}
207
- maxLeftAxisCharacters={maxLeftAxisCharacters}
208
- hasSecondUnit={hasSecondUnit}
209
- />
210
- )}
211
- {style?.showPoints &&
212
- getDates(relatedTimeSeries).map((timeTick) => (
213
- <Point
214
- key={timeTick.toString()}
215
- lineColor={lineColor}
216
- metric_id={metric_id}
217
- radius={getPointRadius(style?.lineWidth)}
218
- timeSeries={relatedTimeSeries}
219
- timeTick={timeTick}
220
- xScale={xScale}
221
- yPoint={getYAnchorPoint({
222
- metric_id,
223
- timeSeries: relatedTimeSeries,
224
- timeTick,
225
- yScale
226
- })}
227
- yScale={yScale}
228
- />
229
- ))}
230
- <RegularLine
169
+ lines: [
170
+ {
171
+ areaColor,
172
+ filled,
173
+ highlight,
174
+ invert,
175
+ lineColor,
176
+ metric_id,
177
+ transparency,
178
+ unit,
179
+ ...rest
180
+ }
181
+ ],
182
+ timeSeries
183
+ });
184
+
185
+ const style = getStyle({
186
+ style: lineStyle,
187
+ metricId: metric_id
188
+ }) as LineStyle;
189
+
190
+ return (
191
+ <g key={metric_id}>
192
+ {displayGuidingLines && (
193
+ <RegularAnchorPoint
231
194
  areaColor={areaColor || lineColor}
232
- curve={style?.curve || 'linear'}
233
- dashLength={style?.dashLength}
234
- dashOffset={style?.dashOffset}
235
- dotOffset={style?.dotOffset}
236
- filled={isNil(style?.showArea) ? filled : style.showArea}
237
- graphHeight={height}
238
- highlight={highlight}
239
195
  lineColor={lineColor}
240
- lineWidth={style?.lineWidth || 2}
241
196
  metric_id={metric_id}
242
197
  timeSeries={relatedTimeSeries}
243
- transparency={
244
- isNil(style?.areaTransparency)
245
- ? transparency || 80
246
- : style.areaTransparency
247
- }
248
- unit={unit}
198
+ transparency={transparency}
249
199
  xScale={xScale}
250
200
  yScale={yScale}
201
+ maxLeftAxisCharacters={maxLeftAxisCharacters}
202
+ hasSecondUnit={hasSecondUnit}
251
203
  />
252
- </g>
253
- );
254
- }
255
- )
204
+ )}
205
+ {style?.showPoints &&
206
+ getDates(relatedTimeSeries).map((timeTick) => (
207
+ <Point
208
+ key={timeTick.toString()}
209
+ lineColor={lineColor}
210
+ metric_id={metric_id}
211
+ radius={getPointRadius(style?.lineWidth)}
212
+ timeSeries={relatedTimeSeries}
213
+ timeTick={timeTick}
214
+ xScale={xScale}
215
+ yPoint={getYAnchorPoint({
216
+ metric_id,
217
+ timeSeries: relatedTimeSeries,
218
+ timeTick,
219
+ yScale
220
+ })}
221
+ yScale={yScale}
222
+ />
223
+ ))}
224
+ <RegularLine
225
+ areaColor={areaColor || lineColor}
226
+ curve={style?.curve || 'linear'}
227
+ dashLength={style?.dashLength}
228
+ dashOffset={style?.dashOffset}
229
+ dotOffset={style?.dotOffset}
230
+ filled={isNil(style?.showArea) ? filled : style.showArea}
231
+ graphHeight={height}
232
+ highlight={highlight}
233
+ lineColor={lineColor}
234
+ lineWidth={style?.lineWidth || 2}
235
+ metric_id={metric_id}
236
+ timeSeries={relatedTimeSeries}
237
+ transparency={
238
+ isNil(style?.areaTransparency)
239
+ ? transparency || 80
240
+ : style.areaTransparency
241
+ }
242
+ unit={unit}
243
+ xScale={xScale}
244
+ yScale={yScale}
245
+ />
246
+ </g>
247
+ );
248
+ }
249
+ )
256
250
  : null}
257
251
  </g>
258
252
  );
@@ -180,7 +180,7 @@ describe('Line chart', () => {
180
180
  cy.contains('06/18/2023').should('be.visible');
181
181
 
182
182
  cy.contains('0.4 s').should('be.visible');
183
- cy.contains('75.64%').should('be.visible');
183
+ cy.contains('75.64%').should('be.visible');
184
184
 
185
185
  cy.makeSnapshot();
186
186
  });
@@ -532,7 +532,7 @@ describe('Line chart', () => {
532
532
 
533
533
  checkGraphWidth();
534
534
  cy.contains(':00 AM').should('be.visible');
535
- cy.get('circle[cx="248.33333333333334"]').should('be.visible');
535
+ cy.get('circle[cx="250.83333333333334"]').should('be.visible');
536
536
  cy.get('circle[cy="251.79089393069725"]').should('be.visible');
537
537
 
538
538
  cy.makeSnapshot();
@@ -591,7 +591,7 @@ describe('Line chart', () => {
591
591
  cy.get('path.visx-area-closed')
592
592
  .should('have.attr', 'stroke-dasharray')
593
593
  .and('equals', '5 4');
594
- cy.get('circle[cx="33.11111111111111"]').should('be.visible');
594
+ cy.get('circle[cx="33.44444444444444"]').should('be.visible');
595
595
 
596
596
  cy.makeSnapshot();
597
597
  });
@@ -713,7 +713,7 @@ describe('Lines and bars', () => {
713
713
  cy.findByLabelText('B').click();
714
714
 
715
715
  cy.findAllByTestId('unit-selector').eq(0).should('have.value', 'B');
716
- cy.contains('8.79 KB').should('be.visible');
716
+ cy.contains('8.79 KiB').should('be.visible');
717
717
 
718
718
  cy.findAllByTestId('unit-selector').eq(1).parent().click();
719
719
  cy.findByLabelText('%').click();
@@ -746,11 +746,9 @@ describe('Lines and bars', () => {
746
746
 
747
747
  checkGraphWidth();
748
748
 
749
- cy.get(
750
- 'path[d="M7.501377410468319,350.5553648585503 h56.51239669421488 h1v1 v23.44463514144968 a1,1 0 0 1 -1,1 h-56.51239669421488 a1,1 0 0 1 -1,-1 v-23.44463514144968 v-1h1z"]'
749
+ cy.get('path[d="M7.501377410468319,350.5553648585503 h56.51239669421488 h1v1 v23.44463514144968 a1,1 0 0 1 -1,1 h-56.51239669421488 a1,1 0 0 1 -1,-1 v-23.44463514144968 v-1h1z"]'
751
750
  ).should('be.visible');
752
- cy.get(
753
- 'path[d="M24.05509641873278,201.58170928199803 h23.404958677685954 a17.553719008264462,17.553719008264462 0 0 1 17.553719008264462,17.553719008264462 v113.86621756002336 v17.553719008264462h-17.553719008264462 h-23.404958677685954 h-17.553719008264462v-17.553719008264462 v-113.86621756002336 a17.553719008264462,17.553719008264462 0 0 1 17.553719008264462,-17.553719008264462z"]'
751
+ cy.get('path[d="M24.05509641873278,201.58170928199803 h23.404958677685954 a17.553719008264462,17.553719008264462 0 0 1 17.553719008264462,17.553719008264462 v113.86621756002336 v17.553719008264462h-17.553719008264462 h-23.404958677685954 h-17.553719008264462v-17.553719008264462 v-113.86621756002336 a17.553719008264462,17.553719008264462 0 0 1 17.553719008264462,-17.553719008264462z"]'
754
752
  ).should('be.visible');
755
753
 
756
754
  cy.makeSnapshot();
@@ -816,21 +814,4 @@ describe('Lines and bars', () => {
816
814
 
817
815
  cy.makeSnapshot();
818
816
  });
819
-
820
- it('calls the secondary function when a metric is clicked in the legend', () => {
821
- const secondaryClick = cy.stub().as('secondaryClick');
822
- initialize({
823
- data: dataPingServiceLines,
824
- legend: {
825
- mode: 'grid',
826
- placement: 'bottom',
827
- secondaryClick
828
- }
829
- });
830
-
831
- checkGraphWidth();
832
-
833
- cy.contains('Packet Loss').rightclick();
834
- cy.get('@secondaryClick').should('have.been.called');
835
- });
836
817
  });
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
2
2
 
3
3
  import { Meta, StoryObj } from '@storybook/react';
4
4
 
5
- import { Button, Menu } from '@mui/material';
5
+ import { Button } from '@mui/material';
6
6
  import ButtonGroup from '@mui/material/ButtonGroup';
7
7
  import Switch from '@mui/material/Switch';
8
8
  import Tooltip from '@mui/material/Tooltip';
@@ -26,7 +26,6 @@ import dataPingService from '../mockedData/pingService.json';
26
26
  import dataPingServiceLinesBars from '../mockedData/pingServiceLinesBars.json';
27
27
  import dataPingServiceLinesBarsMixed from '../mockedData/pingServiceLinesBarsMixed.json';
28
28
  import dataPingServiceLinesBarsStacked from '../mockedData/pingServiceLinesBarsStacked.json';
29
- import dataPingServiceLinesStackKeys from '../mockedData/pingServiceWithStackedKeys.json';
30
29
  import dataZoomPreview from '../mockedData/zoomPreview.json';
31
30
 
32
31
  import { dateTimeFormat } from './common';
@@ -759,44 +758,3 @@ export const linesAndBarsMinMaxForUnit: Story = {
759
758
  />
760
759
  )
761
760
  };
762
-
763
- const LegendSecondaryClick = (args) => {
764
- const [anchor, setAnchor] = useState<EventTarget | null>(null);
765
-
766
- return (
767
- <>
768
- <WrapperChart
769
- {...args}
770
- legend={{
771
- secondaryClick: ({ element }) => setAnchor(element)
772
- }}
773
- />
774
- <Menu
775
- anchorEl={anchor}
776
- open={Boolean(anchor)}
777
- onClose={() => setAnchor(null)}
778
- >
779
- menu
780
- </Menu>
781
- </>
782
- );
783
- };
784
-
785
- export const withLegendSecondaryClick: Story = {
786
- argTypes,
787
- args: argumentsData,
788
- render: (args) => (
789
- <LegendSecondaryClick
790
- {...args}
791
- data={dataPingService as unknown as LineChartData}
792
- />
793
- )
794
- };
795
-
796
- export const stackedKey: Story = {
797
- argTypes,
798
- args: {
799
- ...argumentsData,
800
- data: dataPingServiceLinesStackKeys
801
- }
802
- };
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  type MutableRefObject,
3
+ ReactElement,
3
4
  useEffect,
4
5
  useMemo,
5
6
  useRef,
@@ -116,7 +117,7 @@ const Chart = ({
116
117
  min,
117
118
  max,
118
119
  boundariesUnit
119
- }: Props): JSX.Element => {
120
+ }: Props): ReactElement => {
120
121
  const { classes } = useChartStyles();
121
122
 
122
123
  const { title, timeSeries, baseAxis, lines } = graphData;
@@ -137,7 +138,7 @@ const Chart = ({
137
138
  ]);
138
139
 
139
140
  const displayedLines = useMemo(
140
- () => linesGraph.filter(({ display }) => display),
141
+ () => (linesGraph || []).filter(({ display }) => display),
141
142
  [linesGraph]
142
143
  );
143
144
  const [firstUnit, secondUnit] = useMemo(
@@ -197,7 +198,8 @@ const Chart = ({
197
198
  valueGraphHeight: graphHeight - margin.bottom,
198
199
  min,
199
200
  max,
200
- boundariesUnit
201
+ boundariesUnit,
202
+ isFilled: lineStyle?.showArea
201
203
  }),
202
204
  [
203
205
  linesGraph,
@@ -211,8 +213,13 @@ const Chart = ({
211
213
  ]
212
214
  );
213
215
 
214
- const leftScale = yScalesPerUnit[axis?.axisYLeft?.unit ?? firstUnit];
215
- const rightScale = yScalesPerUnit[axis?.axisYRight?.unit ?? secondUnit];
216
+ const allUnits = getUnits(linesGraph || []);
217
+
218
+ const fallbackLeftUnit = axis?.axisYLeft?.unit ?? firstUnit ?? allUnits?.[0];
219
+ const fallbackRightUnit = axis?.axisYRight?.unit ?? secondUnit ?? allUnits?.[1];
220
+
221
+ const leftScale = yScalesPerUnit[fallbackLeftUnit];
222
+ const rightScale = yScalesPerUnit[fallbackRightUnit];
216
223
 
217
224
  const linesDisplayedAsLine = useMemo(
218
225
  () =>
@@ -227,8 +234,6 @@ const Chart = ({
227
234
  [displayedLines]
228
235
  );
229
236
 
230
- const allUnits = getUnits(linesGraph);
231
-
232
237
  useEffect(
233
238
  () => {
234
239
  setLinesGraph(
@@ -277,8 +282,7 @@ const Chart = ({
277
282
  legendHeight: legend?.height,
278
283
  mode: legend?.mode,
279
284
  placement: legend?.placement,
280
- renderExtraComponent: legend?.renderExtraComponent,
281
- secondaryClick: legend?.secondaryClick
285
+ renderExtraComponent: legend?.renderExtraComponent
282
286
  }}
283
287
  legendRef={legendRef}
284
288
  limitLegend={limitLegend}
@@ -27,13 +27,15 @@ export const useGraphValueTooltip = ({
27
27
  isSingleMode,
28
28
  sortOrder
29
29
  }: UseGraphValueTooltipProps): UseGraphValueTooltipState | null => {
30
- const { format } = useLocaleDateTimeFormat();
30
+ const { toDate, toTime } = useLocaleDateTimeFormat();
31
31
  const graphTooltipData = useAtomValue(graphTooltipDataAtom);
32
32
 
33
33
  if (isNil(graphTooltipData) || isNil(graphTooltipData.metrics)) {
34
34
  return null;
35
35
  }
36
36
 
37
+ const formattedDateTime = `${toDate(graphTooltipData.date)} / ${toTime(graphTooltipData.date)}`;
38
+
37
39
  const filteredMetrics = isSingleMode
38
40
  ? filter(
39
41
  ({ id }) => equals(id, graphTooltipData.highlightedMetricId),
@@ -52,7 +54,7 @@ export const useGraphValueTooltip = ({
52
54
  ])(sortOrder);
53
55
 
54
56
  return {
55
- dateTime: format({ date: graphTooltipData.date, formatString: 'L LTS' }),
57
+ dateTime: formattedDateTime,
56
58
  highlightedMetricId: graphTooltipData.highlightedMetricId,
57
59
  metrics: sortedMetrics
58
60
  };
@@ -26,11 +26,6 @@ interface Props extends Pick<LegendModel, 'placement' | 'mode'> {
26
26
  setLinesGraph: Dispatch<SetStateAction<Array<Line> | null>>;
27
27
  shouldDisplayLegendInCompactMode: boolean;
28
28
  toggable?: boolean;
29
- secondaryClick?: (props: {
30
- element: EventTarget | null;
31
- metricId: number | string;
32
- position: [number, number];
33
- }) => void;
34
29
  }
35
30
 
36
31
  const MainLegend = ({
@@ -43,8 +38,7 @@ const MainLegend = ({
43
38
  shouldDisplayLegendInCompactMode,
44
39
  placement,
45
40
  height,
46
- mode,
47
- secondaryClick
41
+ mode
48
42
  }: Props): JSX.Element => {
49
43
  const { classes, cx } = useStyles({
50
44
  limitLegendRows: Boolean(limitLegend),
@@ -71,24 +65,7 @@ const MainLegend = ({
71
65
  value
72
66
  }) || 'N/A';
73
67
 
74
- const contextMenuClick =
75
- (metricId: number) =>
76
- (event: MouseEvent): void => {
77
- if (!secondaryClick) {
78
- return;
79
- }
80
- event.preventDefault();
81
- secondaryClick({
82
- element: event.target,
83
- metricId,
84
- position: [event.pageX, event.pageY]
85
- });
86
- };
87
-
88
- const selectMetric = ({
89
- event,
90
- metric_id
91
- }: { event: MouseEvent; metric_id: number }): void => {
68
+ const selectMetric = ({ event, metric_id }): void => {
92
69
  if (!toggable) {
93
70
  return;
94
71
  }
@@ -150,7 +127,6 @@ const MainLegend = ({
150
127
  onClick={(event): void => selectMetric({ event, metric_id })}
151
128
  onMouseEnter={(): void => highlightLine(metric_id)}
152
129
  onMouseLeave={(): void => clearHighlight()}
153
- onContextMenu={contextMenuClick(metric_id)}
154
130
  >
155
131
  <LegendHeader
156
132
  color={markerColor}
@@ -1,22 +1,23 @@
1
- import { RefCallback, memo, useEffect } from 'react';
1
+ import dayjs from "dayjs";
2
+ import { memo, type RefCallback, useEffect, useRef } from "react";
3
+ import "dayjs/locale/en";
4
+ import "dayjs/locale/es";
5
+ import "dayjs/locale/fr";
6
+ import "dayjs/locale/pt";
2
7
 
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
- import Loading from '../../LoadingSkeleton';
12
- import type { LineChartData, Thresholds } from '../common/models';
8
+ import { NoData } from "@centreon/ui";
13
9
 
14
- import useResizeObserver from 'use-resize-observer';
15
- import Chart from './Chart';
16
- import { useChartStyles } from './Chart.styles';
17
- import LoadingSkeleton from './LoadingSkeleton';
18
- import type { GlobalAreaLines, LineChartProps } from './models';
19
- import useChartData from './useChartData';
10
+ import localizedFormat from "dayjs/plugin/localizedFormat";
11
+ import timezonePlugin from "dayjs/plugin/timezone";
12
+ import utcPlugin from "dayjs/plugin/utc";
13
+ import useResizeObserver from "use-resize-observer";
14
+ import Loading from "../../LoadingSkeleton";
15
+ import type { LineChartData, Thresholds } from "../common/models";
16
+ import Chart from "./Chart";
17
+ import { useChartStyles } from "./Chart.styles";
18
+ import LoadingSkeleton from "./LoadingSkeleton";
19
+ import type { GlobalAreaLines, LineChartProps } from "./models";
20
+ import useChartData from "./useChartData";
20
21
 
21
22
  dayjs.extend(localizedFormat);
22
23
  dayjs.extend(utcPlugin);
@@ -31,7 +32,7 @@ interface Props extends Partial<LineChartProps> {
31
32
  start: string;
32
33
  thresholdUnit?: string;
33
34
  thresholds?: Thresholds;
34
- getRef?: (ref: RefCallback<Element>) => void;
35
+ getRef?: (ref: React.RefObject<HTMLDivElement | null>) => void;
35
36
  containerStyle?: string;
36
37
  transformMatrix?: {
37
38
  fx?: (pointX: number) => number;
@@ -52,14 +53,14 @@ const WrapperChart = ({
52
53
  loading,
53
54
  timeShiftZones,
54
55
  tooltip = {
55
- mode: 'all',
56
- sortOrder: 'name'
56
+ mode: "all",
57
+ sortOrder: "name",
57
58
  },
58
59
  annotationEvent,
59
60
  legend = {
60
61
  display: true,
61
- mode: 'grid',
62
- placement: 'bottom'
62
+ mode: "grid",
63
+ placement: "bottom",
63
64
  },
64
65
  header,
65
66
  lineStyle,
@@ -76,17 +77,26 @@ const WrapperChart = ({
76
77
  ...rest
77
78
  }: Props): JSX.Element | null => {
78
79
  const { classes, cx } = useChartStyles();
79
-
80
80
  const { adjustedData } = useChartData({ data, end, start });
81
+
82
+ const containerRef = useRef<HTMLDivElement | null>(null);
83
+
81
84
  const {
82
- ref,
85
+ ref: resizeObserverRef,
83
86
  width: responsiveWidth,
84
- height: responsiveHeight
87
+ height: responsiveHeight,
85
88
  } = useResizeObserver();
86
89
 
87
- useEffect(() => {
88
- getRef?.(ref);
89
- }, [ref?.current]);
90
+ const combinedRef = (element: HTMLDivElement | null) => {
91
+ if (containerRef.current !== element) {
92
+ containerRef.current = element;
93
+ if (element) {
94
+ getRef?.(containerRef);
95
+ }
96
+ }
97
+ resizeObserverRef(element);
98
+ };
99
+
90
100
 
91
101
  if (loading && !adjustedData) {
92
102
  return (
@@ -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
- ref={ref}
116
+ ref={combinedRef}
103
117
  className={cx(classes.wrapperContainer, rest?.containerStyle)}
104
118
  >
105
119
  {!responsiveHeight ? (
106
- <Loading height={height || '100%'} width={width} />
120
+ <Loading height={height || "100%"} width={width} />
107
121
  ) : (
108
122
  <Chart
109
123
  annotationEvent={annotationEvent}
@@ -112,7 +126,7 @@ const WrapperChart = ({
112
126
  displayAnchor={displayAnchor}
113
127
  graphData={adjustedData}
114
128
  graphInterval={{ end, start }}
115
- graphRef={ref}
129
+ graphRef={containerRef}
116
130
  header={header}
117
131
  height={height || responsiveHeight || 0}
118
132
  legend={legend}