@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centreon/ui",
3
- "version": "24.4.63",
3
+ "version": "24.4.65",
4
4
  "description": "Centreon UI Components",
5
5
  "scripts": {
6
6
  "update:deps": "pnpx npm-check-updates -i --format group",
@@ -82,7 +82,7 @@
82
82
  "@vitejs/plugin-react": "^4.2.1",
83
83
  "@vitejs/plugin-react-swc": "^3.6.0",
84
84
  "axios-mock-adapter": "^1.22.0",
85
- "cypress": "^13.7.0",
85
+ "cypress": "^13.7.1",
86
86
  "identity-obj-proxy": "^3.0.0",
87
87
  "jest-transform-stub": "^2.0.0",
88
88
  "mochawesome": "^7.1.3",
@@ -114,15 +114,20 @@
114
114
  "@lexical/selection": "^0.12.6",
115
115
  "@lexical/utils": "^0.12.6",
116
116
  "@react-spring/web": "^9.7.3",
117
+ "@visx/clip-path": "^3.3.0",
117
118
  "@visx/curve": "^2.1.0",
119
+ "@visx/event": "^3.3.0",
118
120
  "@visx/group": "^3.3.0",
121
+ "@visx/hierarchy": "^3.3.0",
119
122
  "@visx/legend": "^3.5.0",
120
123
  "@visx/pattern": "^3.3.0",
124
+ "@visx/point": "^3.3.0",
121
125
  "@visx/scale": "^3.5.0",
122
- "@visx/shape": "^2.12.2",
126
+ "@visx/shape": "^2.18.0",
123
127
  "@visx/text": "^3.3.0",
124
128
  "@visx/threshold": "^2.12.2",
125
129
  "@visx/visx": "2.16.0",
130
+ "@visx/zoom": "^3.3.0",
126
131
  "anylogger": "^1.0.11",
127
132
  "d3-array": "3.2.4",
128
133
  "humanize-duration": "^3.31.0",
@@ -1,41 +1,17 @@
1
- import { ScaleLinear } from 'd3-scale';
2
- import { isNil } from 'ramda';
3
-
4
1
  import Typography from '@mui/material/Typography';
5
2
 
6
- import { useLocaleDateTimeFormat, useMemoComponent } from '@centreon/ui';
3
+ import { useMemoComponent } from '@centreon/ui';
7
4
 
8
5
  import { useStyles } from '../LineChart.styles';
9
- import useTickGraph from '../InteractiveComponents/AnchorPoint/useTickGraph';
10
6
  import { LineChartHeader } from '../models';
11
- import { TimeValue } from '../../common/timeSeries/models';
12
7
 
13
8
  interface Props {
14
- displayTimeTick?: boolean;
15
9
  header?: LineChartHeader;
16
- timeSeries: Array<TimeValue>;
17
10
  title: string;
18
- xScale: ScaleLinear<number, number>;
19
11
  }
20
12
 
21
- const Header = ({
22
- title,
23
- displayTimeTick = true,
24
- header,
25
- timeSeries,
26
- xScale
27
- }: Props): JSX.Element => {
13
+ const Header = ({ title, header }: Props): JSX.Element => {
28
14
  const { classes } = useStyles();
29
- const { toDateTime } = useLocaleDateTimeFormat();
30
-
31
- const { tickAxisBottom } = useTickGraph({
32
- timeSeries,
33
- xScale
34
- });
35
- const time =
36
- displayTimeTick && !isNil(tickAxisBottom)
37
- ? toDateTime(tickAxisBottom)
38
- : null;
39
15
 
40
16
  const displayTitle = header?.displayTitle ?? true;
41
17
 
@@ -49,16 +25,12 @@ const Header = ({
49
25
  {title}
50
26
  </Typography>
51
27
  )}
52
-
53
- <Typography align="center" style={{ height: 20 }} variant="body1">
54
- {time}
55
- </Typography>
56
28
  </div>
57
29
  {header?.extraComponent}
58
30
  </div>
59
31
  ),
60
32
 
61
- memoProps: [time, timeSeries, xScale, displayTimeTick, title, header]
33
+ memoProps: [title, header]
62
34
  });
63
35
  };
64
36
 
@@ -2,13 +2,12 @@ import { useEffect, useState } from 'react';
2
2
 
3
3
  import { ScaleLinear } from 'd3-scale';
4
4
  import { useAtomValue } from 'jotai';
5
- import { isEmpty, isNil, not } from 'ramda';
6
5
 
7
6
  import useAxisY from '../../BasicComponents/Axes/useAxisY';
8
7
  import { margin } from '../../common';
9
- import { getMetrics, getTimeValue } from '../../../common/timeSeries';
8
+ import { getTimeValue } from '../../../common/timeSeries';
10
9
  import { Line, TimeValue } from '../../../common/timeSeries/models';
11
- import { mousePositionAtom, timeValueAtom } from '../interactionWithGraphAtoms';
10
+ import { mousePositionAtom } from '../interactionWithGraphAtoms';
12
11
 
13
12
  interface AnchorPointResult {
14
13
  positionX?: number;
@@ -42,14 +41,13 @@ const useTickGraph = ({
42
41
  const { axisRight, axisLeft } = useAxisY({ data: { baseAxis, lines } });
43
42
 
44
43
  const mousePosition = useAtomValue(mousePositionAtom);
45
- const timeValueData = useAtomValue(timeValueAtom);
46
44
 
47
- const metrics = getMetrics(timeValueData as TimeValue);
48
-
49
- const containsMetrics = not(isNil(metrics)) && not(isEmpty(metrics));
50
-
51
- const positionX = mousePosition ? mousePosition[0] - margin.left : undefined;
52
- const positionY = mousePosition ? mousePosition[1] - margin.top : undefined;
45
+ const positionX = mousePosition
46
+ ? mousePosition[0] - margin.left - 4
47
+ : undefined;
48
+ const positionY = mousePosition
49
+ ? mousePosition[1] - margin.top + 2
50
+ : undefined;
53
51
 
54
52
  useEffect(() => {
55
53
  if (!mousePosition) {
@@ -62,7 +60,7 @@ const useTickGraph = ({
62
60
  const mousePositionTimeTick = mousePosition
63
61
  ? getTimeValue({ timeSeries, x: mousePosition[0], xScale }).timeTick
64
62
  : 0;
65
- const timeTickValue = containsMetrics
63
+ const timeTickValue = mousePosition
66
64
  ? new Date(mousePositionTimeTick)
67
65
  : null;
68
66
 
@@ -0,0 +1,68 @@
1
+ import { useAtomValue } from 'jotai';
2
+ import { equals, isNil } from 'ramda';
3
+
4
+ import { Box, Typography } from '@mui/material';
5
+
6
+ import { mousePositionAtom } from '../interactionWithGraphAtoms';
7
+ import { formatMetricValueWithUnit } from '../../../common/timeSeries';
8
+
9
+ import { useGraphValueTooltip } from './useGraphValueTooltip';
10
+ import { useGraphValueTooltipStyles } from './useGraphValueTooltipStyles';
11
+
12
+ interface Props {
13
+ base: number;
14
+ }
15
+
16
+ const GraphValueTooltip = ({ base }: Props): JSX.Element | null => {
17
+ const { classes } = useGraphValueTooltipStyles();
18
+ const mousePosition = useAtomValue(mousePositionAtom);
19
+
20
+ const graphValue = useGraphValueTooltip();
21
+
22
+ if (isNil(graphValue) || isNil(mousePosition)) {
23
+ return null;
24
+ }
25
+
26
+ return (
27
+ <div className={classes.tooltipContainer}>
28
+ <Typography fontWeight="bold">{graphValue.dateTime}</Typography>
29
+ <div className={classes.metrics}>
30
+ {graphValue.metrics.map(({ unit, color, id, value, name }) => {
31
+ const isMetricHighlighted = equals(
32
+ id,
33
+ graphValue.highlightedMetricId
34
+ );
35
+
36
+ return (
37
+ <div
38
+ className={classes.metric}
39
+ data-highlight={isMetricHighlighted}
40
+ data-metric={name}
41
+ key={id}
42
+ >
43
+ <Box
44
+ className={classes.metricColorBox}
45
+ sx={{ backgroundColor: color }}
46
+ />
47
+ <Typography
48
+ className={classes.metricName}
49
+ fontWeight={isMetricHighlighted ? 'bold' : undefined}
50
+ >
51
+ {name}
52
+ </Typography>
53
+ <Typography fontWeight={isMetricHighlighted ? 'bold' : undefined}>
54
+ {formatMetricValueWithUnit({
55
+ base,
56
+ unit,
57
+ value
58
+ })}
59
+ </Typography>
60
+ </div>
61
+ );
62
+ })}
63
+ </div>
64
+ </div>
65
+ );
66
+ };
67
+
68
+ export default GraphValueTooltip;
@@ -0,0 +1,27 @@
1
+ import { useAtomValue } from 'jotai';
2
+ import { isNil } from 'ramda';
3
+
4
+ import { graphTooltipDataAtom } from '../interactionWithGraphAtoms';
5
+ import { useLocaleDateTimeFormat } from '../../../../utils';
6
+ import { GraphTooltipData } from '../../models';
7
+
8
+ interface UseGraphValueTooltipState extends Omit<GraphTooltipData, 'date'> {
9
+ dateTime: string;
10
+ }
11
+
12
+ export const useGraphValueTooltip = (): UseGraphValueTooltipState | null => {
13
+ const { toDate, toTime } = useLocaleDateTimeFormat();
14
+ const graphTooltipData = useAtomValue(graphTooltipDataAtom);
15
+
16
+ if (isNil(graphTooltipData)) {
17
+ return null;
18
+ }
19
+
20
+ const formattedDateTime = `${toDate(graphTooltipData.date)} / ${toTime(graphTooltipData.date)}`;
21
+
22
+ return {
23
+ dateTime: formattedDateTime,
24
+ highlightedMetricId: graphTooltipData.highlightedMetricId,
25
+ metrics: graphTooltipData.metrics
26
+ };
27
+ };
@@ -0,0 +1,31 @@
1
+ import { makeStyles } from 'tss-react/mui';
2
+
3
+ export const useGraphValueTooltipStyles = makeStyles()((theme) => ({
4
+ dateTimeLabel: {
5
+ fontSize: '1.1rem'
6
+ },
7
+ metric: {
8
+ alignItems: 'center',
9
+ display: 'flex',
10
+ gap: theme.spacing(1),
11
+ weidth: '100%'
12
+ },
13
+ metricColorBox: {
14
+ borderRadius: theme.shape.borderRadius,
15
+ flexShrink: 0,
16
+ height: theme.spacing(1.5),
17
+ width: theme.spacing(1.5)
18
+ },
19
+ metricName: {
20
+ flexGrow: 1
21
+ },
22
+ metrics: {
23
+ display: 'flex',
24
+ flexDirection: 'column',
25
+ marginTop: theme.spacing(0.5),
26
+ width: '100%'
27
+ },
28
+ tooltipContainer: {
29
+ padding: theme.spacing(1)
30
+ }
31
+ }));
@@ -3,7 +3,21 @@ import { MutableRefObject } from 'react';
3
3
  import { Event } from '@visx/visx';
4
4
  import { ScaleTime } from 'd3-scale';
5
5
  import { useSetAtom } from 'jotai';
6
- import { isEmpty, isNil } from 'ramda';
6
+ import {
7
+ all,
8
+ equals,
9
+ find,
10
+ isEmpty,
11
+ isNil,
12
+ keys,
13
+ map,
14
+ pick,
15
+ pipe,
16
+ pluck,
17
+ reduce,
18
+ toPairs,
19
+ values
20
+ } from 'ramda';
7
21
  import { makeStyles } from 'tss-react/mui';
8
22
 
9
23
  import {
@@ -12,8 +26,16 @@ import {
12
26
  InteractedZone,
13
27
  InteractedZone as ZoomPreviewModel
14
28
  } from '../models';
15
- import { getTimeValue } from '../../common/timeSeries';
16
- import { TimeValue } from '../../common/timeSeries/models';
29
+ import {
30
+ formatMetricName,
31
+ getLineForMetric,
32
+ getLinesForMetrics,
33
+ getTimeValue,
34
+ getUnits,
35
+ getYScale
36
+ } from '../../common/timeSeries';
37
+ import { Line, TimeValue } from '../../common/timeSeries/models';
38
+ import { margin } from '../common';
17
39
 
18
40
  import Annotations from './Annotations';
19
41
  import { TimelineEvent } from './Annotations/models';
@@ -22,10 +44,11 @@ import TimeShiftZones from './TimeShiftZones';
22
44
  import ZoomPreview from './ZoomPreview';
23
45
  import {
24
46
  MousePosition,
25
- changeMousePositionAndTimeValueDerivedAtom,
47
+ changeMousePositionDerivedAtom,
26
48
  eventMouseDownAtom,
27
49
  eventMouseLeaveAtom,
28
- eventMouseUpAtom
50
+ eventMouseUpAtom,
51
+ graphTooltipDataAtom
29
52
  } from './interactionWithGraphAtoms';
30
53
 
31
54
  const useStyles = makeStyles()(() => ({
@@ -38,6 +61,9 @@ interface CommonData {
38
61
  graphHeight: number;
39
62
  graphSvgRef: MutableRefObject<SVGSVGElement | null>;
40
63
  graphWidth: number;
64
+ leftScale;
65
+ lines;
66
+ rightScale;
41
67
  timeSeries: Array<TimeValue>;
42
68
  xScale: ScaleTime<number, number>;
43
69
  }
@@ -65,13 +91,19 @@ const InteractionWithGraph = ({
65
91
  const setEventMouseDown = useSetAtom(eventMouseDownAtom);
66
92
  const setEventMouseUp = useSetAtom(eventMouseUpAtom);
67
93
  const setEventMouseLeave = useSetAtom(eventMouseLeaveAtom);
94
+ const changeMousePosition = useSetAtom(changeMousePositionDerivedAtom);
95
+ const setGraphTooltipData = useSetAtom(graphTooltipDataAtom);
68
96
 
69
- const changeMousePositionAndTimeValue = useSetAtom(
70
- changeMousePositionAndTimeValueDerivedAtom
71
- );
72
-
73
- const { graphHeight, graphWidth, graphSvgRef, xScale, timeSeries } =
74
- commonData;
97
+ const {
98
+ graphHeight,
99
+ graphWidth,
100
+ graphSvgRef,
101
+ xScale,
102
+ timeSeries,
103
+ leftScale,
104
+ rightScale,
105
+ lines
106
+ } = commonData;
75
107
 
76
108
  const displayZoomPreview = zoomData?.enable ?? true;
77
109
 
@@ -83,6 +115,7 @@ const InteractionWithGraph = ({
83
115
  setEventMouseLeave(event);
84
116
  setEventMouseDown(null);
85
117
  updateMousePosition(null);
118
+ setGraphTooltipData(null);
86
119
  };
87
120
 
88
121
  const mouseUp = (event): void => {
@@ -107,10 +140,10 @@ const InteractionWithGraph = ({
107
140
 
108
141
  const updateMousePosition = (pointPosition: MousePosition): void => {
109
142
  if (isNil(pointPosition)) {
110
- changeMousePositionAndTimeValue({
111
- position: null,
112
- timeValue: null
143
+ changeMousePosition({
144
+ position: null
113
145
  });
146
+ setGraphTooltipData(null);
114
147
 
115
148
  return;
116
149
  }
@@ -120,7 +153,89 @@ const InteractionWithGraph = ({
120
153
  xScale
121
154
  });
122
155
 
123
- changeMousePositionAndTimeValue({ position: pointPosition, timeValue });
156
+ if (isNil(timeValue)) {
157
+ changeMousePosition({
158
+ position: null
159
+ });
160
+ setGraphTooltipData(null);
161
+
162
+ return;
163
+ }
164
+
165
+ const date = timeValue.timeTick;
166
+ const displayedMetricIds = pluck('metric_id', lines);
167
+ const filteredMetricsValue = pick(displayedMetricIds, timeValue);
168
+ const [, secondUnit, thirdUnit] = getUnits(lines as Array<Line>);
169
+ const areAllValuesEmpty = pipe(values, all(isNil))(filteredMetricsValue);
170
+
171
+ const linesData = getLinesForMetrics({
172
+ lines,
173
+ metricIds: keys(filteredMetricsValue).map(Number)
174
+ });
175
+
176
+ if (areAllValuesEmpty) {
177
+ changeMousePosition({ position: pointPosition });
178
+ setGraphTooltipData(null);
179
+
180
+ return;
181
+ }
182
+
183
+ const distanceWithPointPositionPerMetric = reduce(
184
+ (acc, [metricId, value]) => {
185
+ if (isNil(value)) {
186
+ return acc;
187
+ }
188
+
189
+ const lineData = getLineForMetric({
190
+ lines,
191
+ metric_id: Number(metricId)
192
+ });
193
+ const yScale = getYScale({
194
+ hasMoreThanTwoUnits: Boolean(thirdUnit),
195
+ invert: (lineData as Line).invert,
196
+ leftScale,
197
+ rightScale,
198
+ secondUnit,
199
+ unit: (lineData as Line).unit
200
+ });
201
+
202
+ const y0 = yScale(value);
203
+
204
+ const diffBetweenY0AndPointPosition = Math.abs(
205
+ y0 + margin.top - pointPosition[1]
206
+ );
207
+
208
+ return {
209
+ ...acc,
210
+ [metricId]: diffBetweenY0AndPointPosition
211
+ };
212
+ },
213
+ {},
214
+ Object.entries(filteredMetricsValue)
215
+ );
216
+
217
+ const nearestY0 = Math.min(...values(distanceWithPointPositionPerMetric));
218
+
219
+ const nearestLine = pipe(
220
+ toPairs,
221
+ find(([, y0]) => equals(y0, nearestY0)) as () => [string, number]
222
+ )(distanceWithPointPositionPerMetric);
223
+
224
+ changeMousePosition({ position: pointPosition });
225
+ setGraphTooltipData({
226
+ date,
227
+ highlightedMetricId: Number(nearestLine[0]),
228
+ metrics: map(
229
+ ({ metric_id, color, unit, legend, name }) => ({
230
+ color,
231
+ id: metric_id,
232
+ name: formatMetricName({ legend, name }),
233
+ unit,
234
+ value: timeValue?.[metric_id]
235
+ }),
236
+ linesData
237
+ ).filter(({ value }) => value)
238
+ });
124
239
  };
125
240
 
126
241
  return (
@@ -151,8 +266,9 @@ const InteractionWithGraph = ({
151
266
  )}
152
267
  <Bar
153
268
  className={classes.overlay}
269
+ data-testid="graph-interaction-zone"
154
270
  fill="transparent"
155
- height={graphHeight}
271
+ height={graphHeight - margin.bottom}
156
272
  width={graphWidth}
157
273
  x={0}
158
274
  y={0}
@@ -1,52 +1,32 @@
1
1
  import { atom } from 'jotai';
2
- import { not, isNil } from 'ramda';
2
+ import { isNil } from 'ramda';
3
3
 
4
4
  import { TimeValue } from '../../common/timeSeries/models';
5
+ import { GraphTooltipData } from '../models';
5
6
 
6
7
  export const eventMouseDownAtom = atom<null | MouseEvent>(null);
7
8
  export const eventMouseUpAtom = atom<null | MouseEvent>(null);
8
9
  export const eventMouseLeaveAtom = atom<null | MouseEvent>(null);
10
+ export const graphTooltipDataAtom = atom<GraphTooltipData | null>(null);
9
11
 
10
12
  export const timeValueAtom = atom<TimeValue | null>(null);
11
13
  export const mousePositionAtom = atom<MousePosition>(null);
12
14
  export const isListingGraphOpenAtom = atom(false);
13
15
  export type MousePosition = [number, number] | null;
14
16
 
15
- interface PositionTimeValue {
17
+ interface Position {
16
18
  position: MousePosition;
17
- timeValue: TimeValue | null;
18
19
  }
19
20
 
20
- interface NewTimeValueInViewportState {
21
- isInViewport?: boolean;
22
- newTimeValue: TimeValue | null;
23
- }
24
- export const changeTimeValueDerivedAtom = atom(
25
- null,
26
- (
27
- _,
28
- set,
29
- { newTimeValue, isInViewport }: NewTimeValueInViewportState
30
- ): void => {
31
- if (not(isInViewport)) {
32
- return;
33
- }
34
- set(timeValueAtom, newTimeValue);
35
- }
36
- );
37
-
38
- export const changeMousePositionAndTimeValueDerivedAtom = atom(
21
+ export const changeMousePositionDerivedAtom = atom(
39
22
  null,
40
- (_, set, { position, timeValue }: PositionTimeValue): void => {
41
- if (isNil(position) || isNil(timeValue)) {
23
+ (_, set, { position }: Position): void => {
24
+ if (isNil(position)) {
42
25
  set(mousePositionAtom, null);
43
- set(timeValueAtom, null);
44
26
 
45
27
  return;
46
28
  }
47
29
 
48
30
  set(mousePositionAtom, position);
49
-
50
- set(timeValueAtom, timeValue);
51
31
  }
52
32
  );
@@ -1,8 +1,12 @@
1
- import { includes, isEmpty, split } from 'ramda';
1
+ import { isEmpty } from 'ramda';
2
2
 
3
3
  import { Typography } from '@mui/material';
4
4
 
5
- import { EllipsisTypography, formatMetricValue } from '../../..';
5
+ import {
6
+ EllipsisTypography,
7
+ formatMetricName,
8
+ formatMetricValue
9
+ } from '../../..';
6
10
  import { Line } from '../../common/timeSeries/models';
7
11
  import { Tooltip } from '../../../components';
8
12
 
@@ -29,12 +33,11 @@ const LegendHeader = ({
29
33
 
30
34
  const { unit, name, legend } = line;
31
35
 
36
+ const metricName = formatMetricName({ legend, name });
37
+
32
38
  const legendName = legend || name;
33
39
  const hasUnit = !isEmpty(unit);
34
40
  const unitName = `(${unit})`;
35
- const metricName = includes('#', legendName)
36
- ? split('#')(legendName)[1]
37
- : legendName;
38
41
 
39
42
  const getEndText = (): string => {
40
43
  if (value) {