@centreon/ui 23.10.18-MON-17793-create-graph-component-centreon-ui.21 → 23.10.18-MON-17793-create-graph-component-centreon-ui.23

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 (33) hide show
  1. package/package.json +1 -1
  2. package/src/Graph/BasicComponents/Axes/index.tsx +2 -2
  3. package/src/Graph/BasicComponents/Axes/useAxisY.ts +5 -5
  4. package/src/Graph/BasicComponents/Lines/RegularLines/index.tsx +2 -2
  5. package/src/Graph/BasicComponents/Lines/StackedLines/index.tsx +2 -16
  6. package/src/Graph/BasicComponents/Lines/index.tsx +15 -6
  7. package/src/Graph/BasicComponents/useFilterLines.ts +4 -2
  8. package/src/Graph/Graph.tsx +18 -4
  9. package/src/Graph/Header/index.tsx +4 -2
  10. package/src/Graph/{icons → Icons}/Downtime.tsx +1 -1
  11. package/src/Graph/InteractiveComponents/AnchorPoint/AnchorPoint.styles.ts +52 -0
  12. package/src/Graph/InteractiveComponents/AnchorPoint/GuidingLines.tsx +45 -0
  13. package/src/Graph/InteractiveComponents/AnchorPoint/RegularAnchorPoint.tsx +4 -12
  14. package/src/Graph/InteractiveComponents/AnchorPoint/StackedAnchorPoint.tsx +16 -10
  15. package/src/Graph/InteractiveComponents/AnchorPoint/TooltipAnchorPoint.tsx +68 -0
  16. package/src/Graph/InteractiveComponents/AnchorPoint/index.tsx +9 -37
  17. package/src/Graph/InteractiveComponents/AnchorPoint/models.ts +38 -1
  18. package/src/Graph/InteractiveComponents/AnchorPoint/useTickGraph.ts +44 -7
  19. package/src/Graph/InteractiveComponents/AnchorPoint/useTooltipAnchorPoint.ts +107 -0
  20. package/src/Graph/InteractiveComponents/Annotations/Area/Downtime.tsx +1 -1
  21. package/src/Graph/InteractiveComponents/TimeShiftZones/TimeShiftIcon.tsx +6 -2
  22. package/src/Graph/InteractiveComponents/TimeShiftZones/index.tsx +1 -0
  23. package/src/Graph/InteractiveComponents/Tooltip/useGraphTooltip.ts +4 -14
  24. package/src/Graph/Legend/useLegend.ts +5 -2
  25. package/src/Graph/helpers/doc.ts +29 -4
  26. package/src/Graph/helpers/index.ts +12 -2
  27. package/src/Graph/index.stories.tsx +1 -1
  28. package/src/Graph/mockedData/lastDay.json +1282 -614
  29. package/src/Graph/models.ts +14 -1
  30. package/src/Graph/useGraphData.ts +2 -2
  31. package/src/api/useRequest/index.ts +9 -6
  32. package/src/utils/useIntersectionObserver.ts +4 -2
  33. /package/src/{Graph → @assets}/icons/downtime.icon.svg +0 -0
@@ -1,6 +1,6 @@
1
1
  import { ScaleLinear, ScaleTime } from 'd3-scale';
2
2
 
3
- import { TimeValue } from '../../timeSeries/models';
3
+ import { Line, TimeValue } from '../../timeSeries/models';
4
4
 
5
5
  interface AnchorPoint {
6
6
  areaColor: string;
@@ -23,3 +23,40 @@ export interface StackData {
23
23
  data: TimeValue;
24
24
  }
25
25
  export type StackValue = [number, number, StackData];
26
+
27
+ export interface GuidingLines {
28
+ graphHeight: number;
29
+ graphWidth: number;
30
+ timeSeries: Array<TimeValue>;
31
+ xScale: ScaleLinear<number, number>;
32
+ }
33
+
34
+ export interface GetYAnchorPoint {
35
+ metric: string;
36
+ timeSeries: Array<TimeValue>;
37
+ timeTick: Date;
38
+ yScale: ScaleLinear<number, number>;
39
+ }
40
+
41
+ export interface UseTooltipAnchorPointResult {
42
+ tooltipDataAxisX?: string | null;
43
+ tooltipDataAxisYLeft?: number | null;
44
+ tooltipDataAxisYRight?: number | null;
45
+ tooltipLeftAxisX?: number;
46
+ tooltipLeftAxisYLeft?: number;
47
+ tooltipLeftAxisYRight?: number;
48
+ tooltipTopAxisX?: number;
49
+ tooltipTopAxisYLeft?: number;
50
+ tooltipTopAxisYRight?: number;
51
+ }
52
+
53
+ export interface TooltipAnchorModel {
54
+ baseAxis: number;
55
+ graphHeight: number;
56
+ graphWidth?: number;
57
+ leftScale?: ScaleLinear<number, number>;
58
+ lines: Array<Line>;
59
+ rightScale?: ScaleLinear<number, number>;
60
+ timeSeries: Array<TimeValue>;
61
+ xScale: ScaleLinear<number, number>;
62
+ }
@@ -4,24 +4,43 @@ import { ScaleLinear } from 'd3-scale';
4
4
  import { useAtomValue } from 'jotai';
5
5
  import { isEmpty, isNil, not } from 'ramda';
6
6
 
7
+ import useAxisY from '../../BasicComponents/Axes/useAxisY';
7
8
  import { margin } from '../../common';
8
9
  import { getMetrics, getTimeValue } from '../../timeSeries';
9
- import { TimeValue } from '../../timeSeries/models';
10
+ import { Line, TimeValue } from '../../timeSeries/models';
10
11
  import { mousePositionAtom, timeValueAtom } from '../interactionWithGraphAtoms';
11
12
 
12
13
  interface AnchorPointResult {
13
14
  positionX?: number;
14
15
  positionY?: number;
15
- timeTick: Date | null;
16
+ tickAxisBottom: Date | null;
17
+ tickAxisLeft: string | null;
18
+ tickAxisRight: string | null;
16
19
  }
17
20
 
18
21
  interface Props {
22
+ baseAxis?: number;
23
+ leftScale?: ScaleLinear<number, number>;
24
+ lines?: Array<Line>;
25
+ rightScale?: ScaleLinear<number, number>;
19
26
  timeSeries: Array<TimeValue>;
20
27
  xScale: ScaleLinear<number, number>;
21
28
  }
22
29
 
23
- const useTickGraph = ({ timeSeries, xScale }: Props): AnchorPointResult => {
24
- const [timeTick, setTimeTick] = useState<Date | null>(null);
30
+ const useTickGraph = ({
31
+ timeSeries,
32
+ xScale,
33
+ leftScale,
34
+ rightScale,
35
+ lines = [],
36
+ baseAxis = 1000
37
+ }: Props): AnchorPointResult => {
38
+ const [tickAxisBottom, setTickAxisBottom] = useState<Date | null>(null);
39
+ const [tickAxisLeft, setTickAxisLeft] = useState<string | null>(null);
40
+ const [tickAxisRight, setTickAxisRight] = useState<string | null>(null);
41
+
42
+ const { axisRight, axisLeft } = useAxisY({ data: { baseAxis, lines } });
43
+
25
44
  const mousePosition = useAtomValue(mousePositionAtom);
26
45
  const timeValueData = useAtomValue(timeValueAtom);
27
46
 
@@ -34,7 +53,9 @@ const useTickGraph = ({ timeSeries, xScale }: Props): AnchorPointResult => {
34
53
 
35
54
  useEffect(() => {
36
55
  if (!mousePosition) {
37
- setTimeTick(null);
56
+ setTickAxisBottom(null);
57
+ setTickAxisLeft(null);
58
+ setTickAxisRight(null);
38
59
 
39
60
  return;
40
61
  }
@@ -45,13 +66,29 @@ const useTickGraph = ({ timeSeries, xScale }: Props): AnchorPointResult => {
45
66
  ? new Date(mousePositionTimeTick)
46
67
  : null;
47
68
 
48
- setTimeTick(timeTickValue);
69
+ setTickAxisBottom(timeTickValue);
70
+
71
+ const valueTickAxisLeft = leftScale?.invert(positionY);
72
+ const formattedTickAxisLeft = axisLeft?.tickFormat?.(valueTickAxisLeft);
73
+
74
+ setTickAxisLeft(formattedTickAxisLeft);
75
+
76
+ if (!axisRight.display) {
77
+ setTickAxisRight(null);
78
+
79
+ return;
80
+ }
81
+ const valueTickAxisRight = rightScale?.invert(positionY);
82
+ const formattedTickAxisRight = axisRight?.tickFormat?.(valueTickAxisRight);
83
+ setTickAxisRight(formattedTickAxisRight);
49
84
  }, [mousePosition]);
50
85
 
51
86
  return {
52
87
  positionX,
53
88
  positionY,
54
- timeTick
89
+ tickAxisBottom,
90
+ tickAxisLeft,
91
+ tickAxisRight
55
92
  };
56
93
  };
57
94
  export default useTickGraph;
@@ -0,0 +1,107 @@
1
+ import { useEffect } from 'react';
2
+
3
+ import { Tooltip } from '@visx/visx';
4
+ import { isNil } from 'ramda';
5
+
6
+ import { useLocaleDateTimeFormat } from '@centreon/ui';
7
+
8
+ import { margin, timeFormat } from '../../common/index';
9
+
10
+ import { TooltipAnchorModel, UseTooltipAnchorPointResult } from './models';
11
+ import useTickGraph from './useTickGraph';
12
+
13
+ const useTooltipAnchorPoint = ({
14
+ timeSeries,
15
+ xScale,
16
+ graphHeight,
17
+ leftScale,
18
+ rightScale,
19
+ graphWidth,
20
+ lines,
21
+ baseAxis
22
+ }: TooltipAnchorModel): UseTooltipAnchorPointResult => {
23
+ const { format } = useLocaleDateTimeFormat();
24
+
25
+ const { positionX, positionY, tickAxisBottom, tickAxisLeft, tickAxisRight } =
26
+ useTickGraph({
27
+ baseAxis,
28
+ leftScale,
29
+ lines,
30
+ rightScale,
31
+ timeSeries,
32
+ xScale
33
+ });
34
+
35
+ const {
36
+ showTooltip: showTooltipAxisYLeft,
37
+ tooltipData: tooltipDataAxisYLeft,
38
+ tooltipLeft: tooltipLeftAxisYLeft,
39
+ tooltipTop: tooltipTopAxisYLeft
40
+ } = Tooltip.useTooltip();
41
+ const {
42
+ showTooltip: showTooltipAxisX,
43
+ tooltipData: tooltipDataAxisX,
44
+ tooltipLeft: tooltipLeftAxisX,
45
+ tooltipTop: tooltipTopAxisX
46
+ } = Tooltip.useTooltip();
47
+
48
+ const {
49
+ showTooltip: showTooltipAxisYRight,
50
+ tooltipData: tooltipDataAxisYRight,
51
+ tooltipLeft: tooltipLeftAxisYRight,
52
+ tooltipTop: tooltipTopAxisYRight
53
+ } = Tooltip.useTooltip();
54
+
55
+ useEffect(() => {
56
+ if (!positionX || !positionY || !tickAxisBottom) {
57
+ return;
58
+ }
59
+
60
+ const dataAxisX = format({
61
+ date: tickAxisBottom,
62
+ formatString: timeFormat
63
+ });
64
+
65
+ showTooltipAxisX({
66
+ tooltipData: dataAxisX,
67
+ tooltipLeft: positionX + margin.left / 2,
68
+ tooltipTop: graphHeight + margin.top / 2
69
+ });
70
+ }, [positionX, positionY, tickAxisBottom]);
71
+
72
+ useEffect(() => {
73
+ if (!positionX || !positionY || !tickAxisLeft) {
74
+ return;
75
+ }
76
+ showTooltipAxisYLeft({
77
+ tooltipData: tickAxisLeft,
78
+ tooltipLeft: 40,
79
+ tooltipTop: positionY + margin.top / 2
80
+ });
81
+ }, [tickAxisLeft, positionX, positionY]);
82
+
83
+ useEffect(() => {
84
+ if (!positionX || !positionY || !tickAxisRight) {
85
+ return;
86
+ }
87
+ showTooltipAxisYRight({
88
+ tooltipData: tickAxisRight,
89
+ tooltipLeft: graphWidth ? graphWidth + 40 : 0,
90
+ tooltipTop: positionY + margin.top / 2
91
+ });
92
+ }, [positionX, positionY, tickAxisRight]);
93
+
94
+ return {
95
+ tooltipDataAxisX: !isNil(tickAxisBottom) ? tooltipDataAxisX : null,
96
+ tooltipDataAxisYLeft: !isNil(tickAxisLeft) ? tooltipDataAxisYLeft : null,
97
+ tooltipDataAxisYRight: !isNil(tickAxisRight) ? tooltipDataAxisYRight : null,
98
+ tooltipLeftAxisX,
99
+ tooltipLeftAxisYLeft,
100
+ tooltipLeftAxisYRight,
101
+ tooltipTopAxisX,
102
+ tooltipTopAxisYLeft,
103
+ tooltipTopAxisYRight
104
+ } as UseTooltipAnchorPointResult;
105
+ };
106
+
107
+ export default useTooltipAnchorPoint;
@@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next';
2
2
 
3
3
  import { useTheme } from '@mui/material';
4
4
 
5
- import IconDowntime from '../../../icons/Downtime';
5
+ import IconDowntime from '../../../Icons/Downtime';
6
6
  import { labelDowntime } from '../../../translatedLabels';
7
7
  import EventAnnotations from '../EventAnnotations';
8
8
  import { Args } from '../models';
@@ -5,11 +5,14 @@ import { makeStyles } from 'tss-react/mui';
5
5
 
6
6
  import { useMemoComponent } from '@centreon/ui';
7
7
 
8
+ import { TimeShiftDirection } from './models';
9
+
8
10
  export const timeShiftIconSize = 20;
9
11
 
10
12
  interface Props {
11
13
  Icon: ReactNode;
12
14
  ariaLabel: string;
15
+ directionHovered: TimeShiftDirection;
13
16
  xIcon: number;
14
17
  yIcon: number;
15
18
  }
@@ -24,7 +27,8 @@ const TimeShiftIcon = ({
24
27
  xIcon,
25
28
  yIcon,
26
29
  Icon,
27
- ariaLabel
30
+ ariaLabel,
31
+ directionHovered
28
32
  }: Props): JSX.Element => {
29
33
  const { classes } = useStyles();
30
34
  const { t } = useTranslation();
@@ -51,7 +55,7 @@ const TimeShiftIcon = ({
51
55
  </svg>
52
56
  </g>
53
57
  ),
54
- memoProps: [xIcon, ariaLabel]
58
+ memoProps: [xIcon, ariaLabel, directionHovered]
55
59
  });
56
60
  };
57
61
 
@@ -60,6 +60,7 @@ const TimeShiftZones = ({
60
60
  <TimeShiftIcon
61
61
  Icon={Icon}
62
62
  ariaLabel={ariaLabelIcon}
63
+ directionHovered={directionHovered}
63
64
  xIcon={xIcon}
64
65
  yIcon={yIcon}
65
66
  />
@@ -1,13 +1,13 @@
1
1
  import { useEffect } from 'react';
2
2
 
3
- import { ScaleLinear } from 'd3-scale';
4
3
  import { Event, Tooltip } from '@visx/visx';
4
+ import { ScaleLinear } from 'd3-scale';
5
5
  import { useAtomValue } from 'jotai';
6
6
 
7
- import { getTimeValue } from '../../timeSeries';
8
- import { eventMouseUpAtom } from '../interactionWithGraphAtoms';
7
+ import { getDate } from '../../helpers/index';
9
8
  import { TimeValue } from '../../timeSeries/models';
10
9
  import { applyingZoomAtomAtom } from '../ZoomPreview/zoomPreviewAtoms';
10
+ import { eventMouseUpAtom } from '../interactionWithGraphAtoms';
11
11
 
12
12
  import { GraphTooltip, width } from './models';
13
13
 
@@ -36,16 +36,6 @@ const useGraphTooltip = ({
36
36
  const mouseUpEvent = useAtomValue(eventMouseUpAtom);
37
37
  const isZoomApplied = useAtomValue(applyingZoomAtomAtom);
38
38
 
39
- const getDate = (positionX): Date => {
40
- const { timeTick } = getTimeValue({
41
- timeSeries,
42
- x: positionX,
43
- xScale
44
- });
45
-
46
- return new Date(timeTick);
47
- };
48
-
49
39
  useEffect(() => {
50
40
  if (!mouseUpEvent || isZoomApplied) {
51
41
  return;
@@ -59,7 +49,7 @@ const useGraphTooltip = ({
59
49
  const displayLeft = graphWidth - x < tooltipWidth;
60
50
 
61
51
  showTooltip({
62
- tooltipData: getDate(x),
52
+ tooltipData: getDate({ positionX: x, timeSeries, xScale }),
63
53
  tooltipLeft: displayLeft ? x - tooltipWidth : x,
64
54
  tooltipTop: y
65
55
  });
@@ -12,7 +12,9 @@ import {
12
12
  prop,
13
13
  propEq,
14
14
  reject,
15
- sortBy
15
+ sortBy,
16
+ compose,
17
+ toLower
16
18
  } from 'ramda';
17
19
 
18
20
  import { linesGraphAtom } from '../graphAtoms';
@@ -52,7 +54,8 @@ const useLegend = ({ lines }: Props): LegendActions => {
52
54
  { ...getLineByMetric(metric), highlight: true }
53
55
  ];
54
56
 
55
- const sortedData = sortBy(prop('name'), data);
57
+ const sortedData = sortBy(compose(toLower, prop('name')), data);
58
+
56
59
  setLines(sortedData);
57
60
  };
58
61
 
@@ -201,13 +201,38 @@ export const argTypes = {
201
201
  category: 'Graph data'
202
202
  }
203
203
  },
204
+
204
205
  displayAnchor: {
205
- control: 'boolean',
206
- description:
207
- 'displays or not the timing, circle, vertical and horizontal line for each point of the corresponding graph (line) according to the interaction of the mouse with the graph',
206
+ control: 'object',
207
+ description: getDescription({
208
+ sections: [
209
+ {
210
+ name: '',
211
+ props: [
212
+ {
213
+ displayGuidingLines: {
214
+ description: 'displays the guiding lines',
215
+ type: 'boolean'
216
+ }
217
+ },
218
+ {
219
+ displayTooltipsGuidingLines: {
220
+ description:
221
+ 'displays the tooltips (labels) on the axis bottom/left/right',
222
+ type: 'boolean'
223
+ }
224
+ }
225
+ ],
226
+ type: 'object'
227
+ }
228
+ ]
229
+ }),
208
230
  table: {
209
231
  category: 'Graph interaction',
210
- type: { summary: 'boolean' }
232
+ type: {
233
+ summary:
234
+ 'displays or not the guiding lines and the dots for each point of the corresponding graph (line) according to the interaction of the mouse with the graph'
235
+ }
211
236
  }
212
237
  },
213
238
  end: {
@@ -3,8 +3,8 @@ import { gt, gte, isEmpty, isNil, prop, propEq, reject, sortBy } from 'ramda';
3
3
 
4
4
  import { LinesData } from '../BasicComponents/Lines/models';
5
5
  import { dateFormat, timeFormat } from '../common';
6
- import { GraphData, GraphInterval } from '../models';
7
- import { getLineData, getTimeSeries } from '../timeSeries';
6
+ import { GetDate, GraphData, GraphInterval } from '../models';
7
+ import { getLineData, getTimeSeries, getTimeValue } from '../timeSeries';
8
8
 
9
9
  export const adjustGraphData = (graphData: GraphData): LinesData => {
10
10
  const lines = getLineData(graphData);
@@ -46,3 +46,13 @@ export const truncate = (content?: string): string => {
46
46
 
47
47
  export const displayArea = (data: unknown): boolean =>
48
48
  !isEmpty(data) && !isNil(data);
49
+
50
+ export const getDate = ({ positionX, xScale, timeSeries }: GetDate): Date => {
51
+ const { timeTick } = getTimeValue({
52
+ timeSeries,
53
+ x: positionX,
54
+ xScale
55
+ });
56
+
57
+ return new Date(timeTick);
58
+ };
@@ -102,7 +102,7 @@ const ExternalComponent = (tooltipData): JSX.Element => {
102
102
  <br />
103
103
  <br />
104
104
  {format({
105
- date: new Date(data),
105
+ date: data,
106
106
  formatString: dateTimeFormat
107
107
  })}
108
108
  <br />