@centreon/ui 24.4.63 → 24.4.65

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 (47) hide show
  1. package/package.json +8 -3
  2. package/src/Graph/LineChart/Header/index.tsx +3 -31
  3. package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/useTickGraph.ts +9 -11
  4. package/src/Graph/LineChart/InteractiveComponents/GraphValueTooltip/GraphValueTooltip.tsx +68 -0
  5. package/src/Graph/LineChart/InteractiveComponents/GraphValueTooltip/useGraphValueTooltip.ts +27 -0
  6. package/src/Graph/LineChart/InteractiveComponents/GraphValueTooltip/useGraphValueTooltipStyles.ts +31 -0
  7. package/src/Graph/LineChart/InteractiveComponents/index.tsx +132 -16
  8. package/src/Graph/LineChart/InteractiveComponents/interactionWithGraphAtoms.ts +7 -27
  9. package/src/Graph/LineChart/Legend/LegendHeader.tsx +8 -5
  10. package/src/Graph/LineChart/Legend/index.tsx +10 -47
  11. package/src/Graph/LineChart/LineChart.cypress.spec.tsx +91 -0
  12. package/src/Graph/LineChart/LineChart.styles.ts +8 -0
  13. package/src/Graph/LineChart/LineChart.tsx +107 -109
  14. package/src/Graph/LineChart/mockedData/lastDayWithIncompleteValues.json +1320 -0
  15. package/src/Graph/LineChart/mockedData/lastDayWithNullValues.json +1314 -0
  16. package/src/Graph/LineChart/models.ts +12 -0
  17. package/src/Graph/Tree/DescendantNodes.tsx +88 -0
  18. package/src/Graph/Tree/Links.tsx +64 -0
  19. package/src/Graph/Tree/StandaloneTree.tsx +32 -0
  20. package/src/Graph/Tree/Tree.cypress.spec.tsx +171 -0
  21. package/src/Graph/Tree/Tree.stories.tsx +144 -0
  22. package/src/Graph/Tree/Tree.tsx +116 -0
  23. package/src/Graph/Tree/constants.ts +2 -0
  24. package/src/Graph/Tree/index.ts +4 -0
  25. package/src/Graph/Tree/models.ts +52 -0
  26. package/src/Graph/Tree/stories/contents.tsx +164 -0
  27. package/src/Graph/Tree/stories/datas.ts +305 -0
  28. package/src/Graph/Tree/utils.ts +49 -0
  29. package/src/Graph/common/timeSeries/index.ts +31 -1
  30. package/src/Graph/index.ts +1 -0
  31. package/src/components/Zoom/Minimap.tsx +127 -0
  32. package/src/components/Zoom/Zoom.cypress.spec.tsx +246 -0
  33. package/src/components/Zoom/Zoom.stories.tsx +115 -0
  34. package/src/components/Zoom/Zoom.styles.tsx +68 -0
  35. package/src/components/Zoom/Zoom.tsx +61 -0
  36. package/src/components/Zoom/ZoomContent.tsx +167 -0
  37. package/src/components/Zoom/constants.ts +2 -0
  38. package/src/components/Zoom/localPoint.ts +51 -0
  39. package/src/components/Zoom/models.ts +25 -0
  40. package/src/components/Zoom/useMinimap.ts +156 -0
  41. package/src/components/Zoom/useZoom.ts +70 -0
  42. package/src/components/Zoom/utils.ts +55 -0
  43. package/src/components/index.ts +1 -0
  44. package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/TooltipAnchorPoint.tsx +0 -96
  45. package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/useTooltipAnchorPoint.ts +0 -107
  46. package/src/Graph/LineChart/Legend/InteractiveValue.tsx +0 -22
  47. package/src/Graph/LineChart/Legend/useInteractiveValues.ts +0 -99
@@ -1,48 +1,38 @@
1
1
  import { Dispatch, ReactNode, SetStateAction } from 'react';
2
2
 
3
3
  import { prop, slice, sortBy } from 'ramda';
4
- import { useAtomValue } from 'jotai';
5
4
 
6
5
  import { Box, alpha, useTheme } from '@mui/material';
7
6
 
8
7
  import { useMemoComponent } from '@centreon/ui';
9
8
 
10
9
  import { formatMetricValue } from '../../common/timeSeries';
11
- import { Line, TimeValue } from '../../common/timeSeries/models';
10
+ import { Line } from '../../common/timeSeries/models';
12
11
  import { labelAvg, labelMax, labelMin } from '../translatedLabels';
13
- import { timeValueAtom } from '../InteractiveComponents/interactionWithGraphAtoms';
14
12
 
15
- import InteractiveValue from './InteractiveValue';
16
13
  import { useStyles } from './Legend.styles';
17
14
  import LegendHeader from './LegendHeader';
18
15
  import { GetMetricValueProps, LegendDisplayMode } from './models';
19
- import useInteractiveValues from './useInteractiveValues';
20
16
  import useLegend from './useLegend';
21
17
  import LegendContent from './LegendContent';
22
18
 
23
19
  interface Props {
24
20
  base: number;
25
- displayAnchor?: boolean;
26
21
  limitLegend?: false | number;
27
22
  lines: Array<Line>;
28
23
  renderExtraComponent?: ReactNode;
29
24
  setLinesGraph: Dispatch<SetStateAction<Array<Line> | null>>;
30
25
  shouldDisplayLegendInCompactMode: boolean;
31
- timeSeries: Array<TimeValue>;
32
26
  toggable?: boolean;
33
- xScale;
34
27
  }
35
28
 
36
29
  const MainLegend = ({
37
30
  lines,
38
- timeSeries,
39
31
  base,
40
32
  toggable = true,
41
33
  limitLegend = false,
42
34
  renderExtraComponent,
43
- displayAnchor = true,
44
35
  setLinesGraph,
45
- xScale,
46
36
  shouldDisplayLegendInCompactMode
47
37
  }: Props): JSX.Element => {
48
38
  const { classes, cx } = useStyles({ limitLegendRows: Boolean(limitLegend) });
@@ -51,13 +41,6 @@ const MainLegend = ({
51
41
  const { selectMetricLine, clearHighlight, highlightLine, toggleMetricLine } =
52
42
  useLegend({ lines, setLinesGraph });
53
43
 
54
- const { getFormattedValue } = useInteractiveValues({
55
- base,
56
- lines,
57
- timeSeries,
58
- xScale
59
- });
60
-
61
44
  const sortedData = sortBy(prop('metric_id'), lines);
62
45
 
63
46
  const displayedLines = limitLegend
@@ -99,10 +82,6 @@ const MainLegend = ({
99
82
  ? color
100
83
  : alpha(theme.palette.text.disabled, 0.2);
101
84
 
102
- const interactiveValue = displayAnchor
103
- ? getFormattedValue(line)
104
- : null;
105
-
106
85
  const minMaxAvg = [
107
86
  {
108
87
  label: labelMin,
@@ -137,28 +116,18 @@ const MainLegend = ({
137
116
  minMaxAvg={
138
117
  shouldDisplayLegendInCompactMode ? minMaxAvg : undefined
139
118
  }
140
- value={
141
- shouldDisplayLegendInCompactMode
142
- ? interactiveValue
143
- : undefined
144
- }
145
119
  />
146
120
  {!shouldDisplayLegendInCompactMode && (
147
121
  <div>
148
- {displayAnchor && (
149
- <InteractiveValue value={interactiveValue} />
150
- )}
151
- {!interactiveValue && (
152
- <div className={classes.minMaxAvgContainer}>
153
- {minMaxAvg.map(({ label, value }) => (
154
- <LegendContent
155
- data={getMetricValue({ unit: line.unit, value })}
156
- key={label}
157
- label={label}
158
- />
159
- ))}
160
- </div>
161
- )}
122
+ <div className={classes.minMaxAvgContainer}>
123
+ {minMaxAvg.map(({ label, value }) => (
124
+ <LegendContent
125
+ data={getMetricValue({ unit: line.unit, value })}
126
+ key={label}
127
+ label={label}
128
+ />
129
+ ))}
130
+ </div>
162
131
  </div>
163
132
  )}
164
133
  </Box>
@@ -174,24 +143,18 @@ const Legend = (props: Props): JSX.Element => {
174
143
  const {
175
144
  toggable,
176
145
  limitLegend,
177
- timeSeries,
178
146
  lines,
179
147
  base,
180
- displayAnchor,
181
148
  shouldDisplayLegendInCompactMode
182
149
  } = props;
183
- const timeValue = useAtomValue(timeValueAtom);
184
150
 
185
151
  return useMemoComponent({
186
152
  Component: <MainLegend {...props} />,
187
153
  memoProps: [
188
- timeValue,
189
- timeSeries,
190
154
  lines,
191
155
  base,
192
156
  toggable,
193
157
  limitLegend,
194
- displayAnchor,
195
158
  shouldDisplayLegendInCompactMode
196
159
  ]
197
160
  });
@@ -0,0 +1,91 @@
1
+ import { LineChartData } from '../common/models';
2
+
3
+ import dataLastDay from './mockedData/lastDay.json';
4
+ import dataLastDayWithNullValues from './mockedData/lastDayWithNullValues.json';
5
+ import dataLastDayWithIncompleteValues from './mockedData/lastDayWithIncompleteValues.json';
6
+ import { args as argumentsData } from './helpers/doc';
7
+
8
+ import WrapperLineChart from '.';
9
+
10
+ const initialize = (data = dataLastDay): void => {
11
+ cy.mount({
12
+ Component: (
13
+ <WrapperLineChart
14
+ {...argumentsData}
15
+ data={data as unknown as LineChartData}
16
+ />
17
+ )
18
+ });
19
+ };
20
+
21
+ describe('Line chart', () => {
22
+ describe('Tooltip', () => {
23
+ it('displays a tooltip when the graph is hovered', () => {
24
+ initialize();
25
+
26
+ cy.contains('oracle-buffer-hit-ratio graph on srv-oracle-users').should(
27
+ 'be.visible'
28
+ );
29
+ cy.contains('hitratio').should('be.visible');
30
+ cy.contains('querytime').should('be.visible');
31
+ cy.contains('connTime').should('be.visible');
32
+ cy.contains('Min: 70.31').should('be.visible');
33
+
34
+ cy.findByTestId('graph-interaction-zone').realMouseMove(250, 70);
35
+
36
+ cy.contains('06/18/2023').should('be.visible');
37
+
38
+ cy.contains('0.45 s').should('be.visible');
39
+ cy.contains('75.93%').should('be.visible');
40
+ cy.contains('0.43 s').should('be.visible');
41
+
42
+ cy.makeSnapshot();
43
+ });
44
+
45
+ it('displays a metric highlighted when the graph is hovered and the metric is the nearest point', () => {
46
+ initialize();
47
+
48
+ cy.contains('Min: 70.31').should('be.visible');
49
+
50
+ cy.findByTestId('graph-interaction-zone').realMouseMove(452, 26);
51
+
52
+ cy.get('[data-metric="querytime"]').should(
53
+ 'have.attr',
54
+ 'data-highlight',
55
+ 'true'
56
+ );
57
+ cy.get('[data-metric="connTime"]').should(
58
+ 'have.attr',
59
+ 'data-highlight',
60
+ 'false'
61
+ );
62
+
63
+ cy.makeSnapshot();
64
+ });
65
+
66
+ it('does not display the tooltip when null values are hovered', () => {
67
+ initialize(dataLastDayWithNullValues);
68
+
69
+ cy.contains('Min: 70.31').should('be.visible');
70
+
71
+ cy.findByTestId('graph-interaction-zone').realMouseMove(1160, 100);
72
+
73
+ cy.get('[data-metric="querytime"]').should('not.exist');
74
+
75
+ cy.makeSnapshot();
76
+ });
77
+
78
+ it('displays the tooltip with defined values whent the graph is hovered', () => {
79
+ initialize(dataLastDayWithIncompleteValues);
80
+
81
+ cy.contains('Min: 70.31').should('be.visible');
82
+
83
+ cy.findByTestId('graph-interaction-zone').realMouseMove(1150, 100);
84
+
85
+ cy.get('[data-metric="querytime"]').should('be.visible');
86
+ cy.get('[data-metric="hitratio"]').should('not.exist');
87
+
88
+ cy.makeSnapshot();
89
+ });
90
+ });
91
+ });
@@ -35,6 +35,14 @@ const useStyles = makeStyles()((theme) => ({
35
35
  fill: theme.palette.text.primary,
36
36
  position: 'relative'
37
37
  },
38
+ graphValueTooltip: {
39
+ backgroundColor: theme.palette.background.paper,
40
+ borderRadius: theme.shape.borderRadius,
41
+ boxShadow: theme.shadows[3],
42
+ color: theme.palette.text.primary,
43
+ maxWidth: 'none',
44
+ padding: 0
45
+ },
38
46
  header: {
39
47
  display: 'grid',
40
48
  gridTemplateColumns: '0.4fr 1fr 0.4fr',
@@ -8,6 +8,7 @@ import { ClickAwayListener, Fade, Skeleton, useTheme } from '@mui/material';
8
8
  import { getLeftScale, getRightScale, getXScale } from '../common/timeSeries';
9
9
  import { Line } from '../common/timeSeries/models';
10
10
  import { Thresholds as ThresholdsModel } from '../common/models';
11
+ import { Tooltip as MuiTooltip } from '../../components/Tooltip';
11
12
 
12
13
  import Axes from './BasicComponents/Axes';
13
14
  import Grids from './BasicComponents/Grids';
@@ -18,7 +19,6 @@ import useFilterLines from './BasicComponents/useFilterLines';
18
19
  import { useStyles } from './LineChart.styles';
19
20
  import Header from './Header';
20
21
  import InteractionWithGraph from './InteractiveComponents';
21
- import TooltipAnchorPoint from './InteractiveComponents/AnchorPoint/TooltipAnchorPoint';
22
22
  import GraphTooltip from './InteractiveComponents/Tooltip';
23
23
  import useGraphTooltip from './InteractiveComponents/Tooltip/useGraphTooltip';
24
24
  import Legend from './Legend';
@@ -34,6 +34,7 @@ import { useIntersection } from './useLineChartIntersection';
34
34
  import { CurveType } from './BasicComponents/Lines/models';
35
35
  import Thresholds from './BasicComponents/Thresholds';
36
36
  import { legendWidth } from './Legend/Legend.styles';
37
+ import GraphValueTooltip from './InteractiveComponents/GraphValueTooltip/GraphValueTooltip';
37
38
 
38
39
  const extraMargin = 10;
39
40
 
@@ -185,131 +186,128 @@ const LineChart = ({
185
186
 
186
187
  return (
187
188
  <>
188
- <Header
189
- displayTimeTick={displayAnchor?.displayGuidingLines ?? true}
190
- header={header}
191
- timeSeries={timeSeries}
192
- title={title}
193
- xScale={xScale}
194
- />
189
+ <Header header={header} title={title} />
195
190
  <ClickAwayListener onClickAway={graphTooltipData?.hideTooltip}>
196
- <div className={classes.container}>
197
- <LoadingProgress
198
- display={loading}
199
- height={graphHeight}
200
- width={width}
201
- />
202
- <svg height={graphHeight + margin.top} ref={graphSvgRef} width="100%">
203
- <Group.Group left={margin.left + extraMargin / 2} top={margin.top}>
204
- <Grids
205
- height={graphHeight - margin.top}
206
- leftScale={leftScale}
207
- width={graphWidth}
208
- xScale={xScale}
209
- />
210
- <Axes
211
- data={{
212
- baseAxis,
213
- lines: displayedLines,
214
- timeSeries,
215
- ...axis
216
- }}
217
- graphInterval={graphInterval}
218
- height={graphHeight - margin.top}
219
- leftScale={leftScale}
220
- rightScale={rightScale}
221
- width={graphWidth}
222
- xScale={xScale}
223
- />
224
-
225
- <Lines
226
- curve={curve}
227
- displayAnchor={displayAnchor}
228
- displayedLines={displayedLines}
229
- graphSvgRef={graphSvgRef}
230
- height={graphHeight - margin.top}
231
- leftScale={leftScale}
232
- rightScale={rightScale}
233
- timeSeries={timeSeries}
234
- width={graphWidth}
235
- xScale={xScale}
236
- {...shapeLines}
237
- />
238
-
239
- <InteractionWithGraph
240
- annotationData={{ ...annotationEvent }}
241
- commonData={{
242
- graphHeight,
243
- graphSvgRef,
244
- graphWidth,
245
- timeSeries,
246
- xScale
247
- }}
248
- timeShiftZonesData={{
249
- ...timeShiftZones,
250
- graphInterval,
251
- loading
252
- }}
253
- zoomData={{ ...zoomPreview }}
254
- />
191
+ <MuiTooltip
192
+ classes={{
193
+ tooltip: classes.graphValueTooltip
194
+ }}
195
+ placement="top-start"
196
+ title={<GraphValueTooltip base={baseAxis} />}
197
+ >
198
+ <div className={classes.container}>
199
+ <LoadingProgress
200
+ display={loading}
201
+ height={graphHeight}
202
+ width={width}
203
+ />
204
+ <svg
205
+ height={graphHeight + margin.top}
206
+ ref={graphSvgRef}
207
+ width="100%"
208
+ >
209
+ <Group.Group
210
+ left={margin.left + extraMargin / 2}
211
+ top={margin.top}
212
+ >
213
+ <Grids
214
+ height={graphHeight - margin.top}
215
+ leftScale={leftScale}
216
+ width={graphWidth}
217
+ xScale={xScale}
218
+ />
219
+ <Axes
220
+ data={{
221
+ baseAxis,
222
+ lines: displayedLines,
223
+ timeSeries,
224
+ ...axis
225
+ }}
226
+ graphInterval={graphInterval}
227
+ height={graphHeight - margin.top}
228
+ leftScale={leftScale}
229
+ rightScale={rightScale}
230
+ width={graphWidth}
231
+ xScale={xScale}
232
+ />
255
233
 
256
- {thresholds?.enabled && (
257
- <Thresholds
234
+ <Lines
235
+ curve={curve}
236
+ displayAnchor={displayAnchor}
258
237
  displayedLines={displayedLines}
259
- hideTooltip={hideThresholdTooltip}
238
+ graphSvgRef={graphSvgRef}
239
+ height={graphHeight - margin.top}
260
240
  leftScale={leftScale}
261
241
  rightScale={rightScale}
262
- showTooltip={showThresholdTooltip}
263
- thresholdUnit={thresholdUnit}
264
- thresholds={thresholds as ThresholdsModel}
242
+ timeSeries={timeSeries}
265
243
  width={graphWidth}
244
+ xScale={xScale}
245
+ {...shapeLines}
266
246
  />
267
- )}
268
- </Group.Group>
269
- </svg>
270
- {displayTooltip && (
271
- <GraphTooltip {...tooltip} {...graphTooltipData} />
272
- )}
273
- {(displayAnchor?.displayTooltipsGuidingLines ?? true) && (
274
- <TooltipAnchorPoint
275
- baseAxis={baseAxis}
276
- graphHeight={graphHeight - 35}
277
- graphWidth={graphWidth}
278
- leftScale={leftScale}
279
- lines={displayedLines}
280
- rightScale={rightScale}
281
- timeSeries={timeSeries}
282
- xScale={xScale}
283
- />
284
- )}
285
- <Fade in={thresholdTooltipOpen}>
286
- <Tooltip.Tooltip
287
- left={thresholdTooltipLeft}
288
- style={{
289
- ...baseStyles,
290
- backgroundColor: theme.palette.background.paper,
291
- color: theme.palette.text.primary,
292
- transform: `translate(${graphWidth / 2}px, -10px)`
293
- }}
294
- top={thresholdTooltipTop}
295
- >
296
- {thresholdTooltipData}
297
- </Tooltip.Tooltip>
298
- </Fade>
299
- </div>
247
+
248
+ <InteractionWithGraph
249
+ annotationData={{ ...annotationEvent }}
250
+ commonData={{
251
+ graphHeight,
252
+ graphSvgRef,
253
+ graphWidth,
254
+ leftScale,
255
+ lines: displayedLines,
256
+ rightScale,
257
+ timeSeries,
258
+ xScale
259
+ }}
260
+ timeShiftZonesData={{
261
+ ...timeShiftZones,
262
+ graphInterval,
263
+ loading
264
+ }}
265
+ zoomData={{ ...zoomPreview }}
266
+ />
267
+
268
+ {thresholds?.enabled && (
269
+ <Thresholds
270
+ displayedLines={displayedLines}
271
+ hideTooltip={hideThresholdTooltip}
272
+ leftScale={leftScale}
273
+ rightScale={rightScale}
274
+ showTooltip={showThresholdTooltip}
275
+ thresholdUnit={thresholdUnit}
276
+ thresholds={thresholds as ThresholdsModel}
277
+ width={graphWidth}
278
+ />
279
+ )}
280
+ </Group.Group>
281
+ </svg>
282
+ {displayTooltip && (
283
+ <GraphTooltip {...tooltip} {...graphTooltipData} />
284
+ )}
285
+ <Fade in={thresholdTooltipOpen}>
286
+ <Tooltip.Tooltip
287
+ left={thresholdTooltipLeft}
288
+ style={{
289
+ ...baseStyles,
290
+ backgroundColor: theme.palette.background.paper,
291
+ color: theme.palette.text.primary,
292
+ transform: `translate(${graphWidth / 2}px, -10px)`
293
+ }}
294
+ top={thresholdTooltipTop}
295
+ >
296
+ {thresholdTooltipData}
297
+ </Tooltip.Tooltip>
298
+ </Fade>
299
+ </div>
300
+ </MuiTooltip>
300
301
  </ClickAwayListener>
301
302
  {displayLegend && (
302
303
  <div ref={legendRef}>
303
304
  <Legend
304
305
  base={baseAxis}
305
- displayAnchor={displayAnchor?.displayGuidingLines ?? true}
306
306
  limitLegend={limitLegend}
307
307
  lines={newLines}
308
308
  renderExtraComponent={legend?.renderExtraComponent}
309
309
  setLinesGraph={setLinesGraph}
310
310
  shouldDisplayLegendInCompactMode={shouldDisplayLegendInCompactMode}
311
- timeSeries={timeSeries}
312
- xScale={xScale}
313
311
  />
314
312
  </div>
315
313
  )}