@centreon/ui 23.10.30-MON-19324-dashboard-section-navigation.3 → 23.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 (205) hide show
  1. package/package.json +9 -12
  2. package/src/@assets/icons/downtime.icon.svg +1 -0
  3. package/src/Dashboard/DashboardLayout.stories.tsx +5 -3
  4. package/src/Dashboard/Layout.tsx +4 -4
  5. package/src/Dashboard/utils.ts +28 -28
  6. package/src/Graph/BasicComponents/Axes/UnitLabel.tsx +20 -0
  7. package/src/Graph/BasicComponents/Axes/index.tsx +88 -0
  8. package/src/Graph/BasicComponents/Axes/models.ts +26 -0
  9. package/src/Graph/BasicComponents/Axes/useAxisY.ts +100 -0
  10. package/src/Graph/BasicComponents/Grids/index.tsx +20 -0
  11. package/src/Graph/BasicComponents/Lines/RegularLines/index.tsx +91 -0
  12. package/src/Graph/BasicComponents/Lines/RegularLines/useRegularLines.ts +15 -0
  13. package/src/Graph/BasicComponents/Lines/StackedLines/index.tsx +76 -0
  14. package/src/Graph/BasicComponents/Lines/StackedLines/useStackedLines.ts +39 -0
  15. package/src/Graph/BasicComponents/Lines/Threshold/BasicThreshold.tsx +51 -0
  16. package/src/Graph/BasicComponents/Lines/Threshold/Circle.tsx +43 -0
  17. package/src/Graph/BasicComponents/Lines/Threshold/ThresholdWithPatternLines.tsx +73 -0
  18. package/src/Graph/BasicComponents/Lines/Threshold/ThresholdWithVariation.tsx +59 -0
  19. package/src/Graph/BasicComponents/Lines/Threshold/helpers/index.ts +69 -0
  20. package/src/Graph/BasicComponents/Lines/Threshold/index.tsx +138 -0
  21. package/src/Graph/BasicComponents/Lines/Threshold/models.ts +105 -0
  22. package/src/Graph/BasicComponents/Lines/Threshold/useCoordinateCircle.ts +46 -0
  23. package/src/Graph/BasicComponents/Lines/Threshold/useScaleThreshold.ts +171 -0
  24. package/src/Graph/BasicComponents/Lines/index.tsx +180 -0
  25. package/src/Graph/BasicComponents/Lines/models.ts +42 -0
  26. package/src/Graph/BasicComponents/LoadingProgress.tsx +46 -0
  27. package/src/Graph/BasicComponents/useFilterLines.ts +60 -0
  28. package/src/Graph/Graph.styles.ts +45 -0
  29. package/src/Graph/Graph.tsx +217 -0
  30. package/src/Graph/Header/index.tsx +65 -0
  31. package/src/Graph/Icons/Downtime.tsx +9 -0
  32. package/src/Graph/InteractiveComponents/AnchorPoint/AnchorPoint.styles.ts +58 -0
  33. package/src/Graph/InteractiveComponents/AnchorPoint/GuidingLines.tsx +45 -0
  34. package/src/Graph/InteractiveComponents/AnchorPoint/RegularAnchorPoint.tsx +66 -0
  35. package/src/Graph/InteractiveComponents/AnchorPoint/StackedAnchorPoint.tsx +76 -0
  36. package/src/Graph/InteractiveComponents/AnchorPoint/TooltipAnchorPoint.tsx +70 -0
  37. package/src/Graph/InteractiveComponents/AnchorPoint/index.tsx +20 -0
  38. package/src/Graph/InteractiveComponents/AnchorPoint/models.ts +62 -0
  39. package/src/Graph/InteractiveComponents/AnchorPoint/useTickGraph.ts +94 -0
  40. package/src/Graph/InteractiveComponents/AnchorPoint/useTooltipAnchorPoint.ts +107 -0
  41. package/src/Graph/InteractiveComponents/Annotations/Annotation/Area.tsx +114 -0
  42. package/src/Graph/InteractiveComponents/Annotations/Annotation/Line.tsx +103 -0
  43. package/src/Graph/InteractiveComponents/Annotations/Annotation/index.tsx +81 -0
  44. package/src/Graph/InteractiveComponents/Annotations/Area/Downtime.tsx +27 -0
  45. package/src/Graph/InteractiveComponents/Annotations/EventAnnotations.tsx +61 -0
  46. package/src/Graph/InteractiveComponents/Annotations/Line/Acknowledgement.tsx +27 -0
  47. package/src/Graph/InteractiveComponents/Annotations/Line/Comments.tsx +25 -0
  48. package/src/Graph/InteractiveComponents/Annotations/annotationsAtoms.ts +183 -0
  49. package/src/Graph/InteractiveComponents/Annotations/index.tsx +49 -0
  50. package/src/Graph/InteractiveComponents/Annotations/models.ts +25 -0
  51. package/src/Graph/InteractiveComponents/Annotations/useAnnotation.ts +56 -0
  52. package/src/Graph/InteractiveComponents/Bar.tsx +21 -0
  53. package/src/Graph/InteractiveComponents/TimeShiftZones/TimeShiftIcon.tsx +62 -0
  54. package/src/Graph/InteractiveComponents/TimeShiftZones/TimeShiftZone.tsx +74 -0
  55. package/src/Graph/InteractiveComponents/TimeShiftZones/index.tsx +85 -0
  56. package/src/Graph/InteractiveComponents/TimeShiftZones/models.ts +12 -0
  57. package/src/Graph/InteractiveComponents/TimeShiftZones/useTimeShiftZones.ts +72 -0
  58. package/src/Graph/InteractiveComponents/Tooltip/index.tsx +59 -0
  59. package/src/Graph/InteractiveComponents/Tooltip/models.ts +9 -0
  60. package/src/Graph/InteractiveComponents/Tooltip/useGraphTooltip.ts +67 -0
  61. package/src/Graph/InteractiveComponents/ZoomPreview/index.tsx +38 -0
  62. package/src/Graph/InteractiveComponents/ZoomPreview/models.ts +9 -0
  63. package/src/Graph/InteractiveComponents/ZoomPreview/useZoomPreview.ts +107 -0
  64. package/src/Graph/InteractiveComponents/ZoomPreview/zoomPreviewAtoms.ts +3 -0
  65. package/src/Graph/InteractiveComponents/index.tsx +168 -0
  66. package/src/Graph/InteractiveComponents/interactionWithGraphAtoms.ts +51 -0
  67. package/src/Graph/Legend/InteractiveValue.tsx +22 -0
  68. package/src/Graph/Legend/Legend.styles.ts +71 -0
  69. package/src/Graph/Legend/LegendContent.tsx +27 -0
  70. package/src/Graph/Legend/LegendHeader.tsx +45 -0
  71. package/src/Graph/Legend/Marker.tsx +43 -0
  72. package/src/Graph/Legend/index.tsx +166 -0
  73. package/src/Graph/Legend/models.ts +11 -0
  74. package/src/Graph/Legend/useInteractiveValues.ts +86 -0
  75. package/src/Graph/Legend/useLegend.ts +114 -0
  76. package/src/Graph/LoadingSkeleton.tsx +44 -0
  77. package/src/Graph/common/index.ts +35 -0
  78. package/src/Graph/graphAtoms.ts +6 -0
  79. package/src/Graph/helpers/doc.ts +560 -0
  80. package/src/Graph/helpers/index.ts +58 -0
  81. package/src/Graph/index.stories.tsx +372 -0
  82. package/src/Graph/index.tsx +90 -0
  83. package/src/Graph/mockedData/annotationData.json +326 -0
  84. package/src/Graph/mockedData/exclusionPeriodFirstPeriod.json +588 -0
  85. package/src/Graph/mockedData/exclusionPeriodSecondPeriod.json +588 -0
  86. package/src/Graph/mockedData/exclusionPeriodThirdPeriod.json +581 -0
  87. package/src/Graph/mockedData/lastDay.json +1326 -0
  88. package/src/Graph/mockedData/lastDayAreaStack.json +3106 -0
  89. package/src/Graph/mockedData/lastDayForward.json +1338 -0
  90. package/src/Graph/mockedData/lastDayThreshold.json +2352 -0
  91. package/src/Graph/mockedData/lastMonth.json +1674 -0
  92. package/src/Graph/mockedData/lastWeek.json +2202 -0
  93. package/src/Graph/mockedData/zoomPreview.json +742 -0
  94. package/src/Graph/models.ts +150 -0
  95. package/src/Graph/timeSeries/index.test.ts +506 -0
  96. package/src/Graph/timeSeries/index.ts +512 -0
  97. package/src/Graph/timeSeries/models.ts +120 -0
  98. package/src/Graph/translatedLabels.ts +9 -0
  99. package/src/Graph/useGraphData.ts +47 -0
  100. package/src/Graph/useGraphIntersection.ts +36 -0
  101. package/src/ThemeProvider/index.tsx +5 -6
  102. package/src/ThemeProvider/palettes.ts +215 -385
  103. package/src/TimePeriods/CustomTimePeriod/CompactCustomTimePeriod.styles.ts +51 -0
  104. package/src/TimePeriods/CustomTimePeriod/CompactCustomTimePeriod.tsx +95 -0
  105. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/ErrorText.tsx +14 -0
  106. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +163 -0
  107. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/index.tsx +76 -0
  108. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/models.ts +61 -0
  109. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/usePickersStartEndDate.ts +82 -0
  110. package/src/TimePeriods/CustomTimePeriod/index.tsx +66 -0
  111. package/src/TimePeriods/DateTimePickerInput.tsx +49 -0
  112. package/src/TimePeriods/ResolutionTimePeriod.cypress.spec.tsx +65 -0
  113. package/src/TimePeriods/SelectedTimePeriod.tsx +102 -0
  114. package/src/TimePeriods/TimePeriods.cypress.spec.tsx +510 -0
  115. package/src/TimePeriods/TimePeriods.styles.ts +22 -0
  116. package/src/TimePeriods/helpers/index.ts +26 -0
  117. package/src/TimePeriods/index.stories.tsx +98 -0
  118. package/src/TimePeriods/index.tsx +78 -0
  119. package/src/TimePeriods/mockedData.ts +12 -0
  120. package/src/TimePeriods/models.ts +97 -0
  121. package/src/TimePeriods/timePeriodsAtoms.ts +102 -0
  122. package/src/TimePeriods/translatedLabels.ts +9 -0
  123. package/src/TimePeriods/useSortTimePeriods.ts +31 -0
  124. package/src/TimePeriods/useTimePeriod.ts +49 -0
  125. package/src/api/TestQueryProvider.tsx +1 -2
  126. package/src/api/useFetchQuery/index.ts +7 -8
  127. package/src/api/useMutationQuery/index.ts +10 -11
  128. package/src/components/Button/Button.styles.ts +3 -17
  129. package/src/components/Button/Button.tsx +3 -6
  130. package/src/components/Button/Icon/IconButton.styles.ts +2 -9
  131. package/src/components/DataTable/DataTable.stories.tsx +0 -9
  132. package/src/components/DataTable/DataTable.styles.ts +0 -5
  133. package/src/components/DataTable/DataTable.tsx +6 -8
  134. package/src/components/DataTable/EmptyState/DataTableEmptyState.tsx +1 -4
  135. package/src/components/DataTable/Item/DataTableItem.styles.ts +2 -5
  136. package/src/components/DataTable/Item/DataTableItem.tsx +18 -36
  137. package/src/components/Header/Header.stories.tsx +27 -0
  138. package/src/components/Header/Header.styles.ts +27 -0
  139. package/src/components/Header/Header.tsx +23 -0
  140. package/src/components/Header/index.ts +1 -1
  141. package/src/components/Modal/index.ts +0 -2
  142. package/src/components/index.ts +0 -3
  143. package/src/index.ts +2 -0
  144. package/src/layout/TiledListingPage/TiledListingActions.tsx +15 -0
  145. package/src/layout/TiledListingPage/TiledListingContent.tsx +21 -0
  146. package/src/layout/TiledListingPage/TiledListingList.tsx +11 -0
  147. package/src/layout/TiledListingPage/TiledListingPage.styles.ts +16 -0
  148. package/src/layout/TiledListingPage/TiledListingPage.tsx +15 -0
  149. package/src/layout/TiledListingPage/index.ts +4 -0
  150. package/src/screens/dashboard/DashboardsOverview.stories.tsx +102 -110
  151. package/src/utils/index.ts +1 -1
  152. package/src/utils/sanitizedHTML.ts +1 -1
  153. package/test/setupTests.js +0 -3
  154. package/src/base/tokens/README.md +0 -3
  155. package/src/base/tokens/source/$metadata.json +0 -5
  156. package/src/base/tokens/source/base.json +0 -142
  157. package/src/base/tokens/themes/base.tokens.d.ts +0 -38
  158. package/src/base/tokens/themes/base.tokens.json +0 -695
  159. package/src/base/tokens/themes/base.tokens.ts +0 -38
  160. package/src/base/tokens/themes/ui-dark.tokens.d.ts +0 -38
  161. package/src/base/tokens/themes/ui-dark.tokens.json +0 -695
  162. package/src/base/tokens/themes/ui-dark.tokens.ts +0 -38
  163. package/src/base/tokens/themes/ui-light.tokens.d.ts +0 -38
  164. package/src/base/tokens/themes/ui-light.tokens.json +0 -695
  165. package/src/base/tokens/themes/ui-light.tokens.ts +0 -38
  166. package/src/components/Header/PageHeader/PageHeader.stories.tsx +0 -88
  167. package/src/components/Header/PageHeader/PageHeader.styles.ts +0 -99
  168. package/src/components/Header/PageHeader/PageHeader.tsx +0 -15
  169. package/src/components/Header/PageHeader/PageHeaderActions.tsx +0 -17
  170. package/src/components/Header/PageHeader/PageHeaderMain.tsx +0 -15
  171. package/src/components/Header/PageHeader/PageHeaderMenu.tsx +0 -15
  172. package/src/components/Header/PageHeader/PageHeaderTitle.tsx +0 -47
  173. package/src/components/Header/PageHeader/index.ts +0 -12
  174. package/src/components/Layout/AreaIndicator.styles.ts +0 -33
  175. package/src/components/Layout/AreaIndicator.tsx +0 -35
  176. package/src/components/Layout/PageLayout/PageLayout.stories.tsx +0 -81
  177. package/src/components/Layout/PageLayout/PageLayout.styles.ts +0 -40
  178. package/src/components/Layout/PageLayout/PageLayout.tsx +0 -21
  179. package/src/components/Layout/PageLayout/PageLayoutActions.tsx +0 -15
  180. package/src/components/Layout/PageLayout/PageLayoutBody.tsx +0 -24
  181. package/src/components/Layout/PageLayout/PageLayoutHeader.tsx +0 -15
  182. package/src/components/Layout/PageLayout/index.ts +0 -10
  183. package/src/components/Layout/index.ts +0 -1
  184. package/src/components/Menu/Button/MenuButton.stories.tsx +0 -16
  185. package/src/components/Menu/Button/MenuButton.styles.ts +0 -27
  186. package/src/components/Menu/Button/MenuButton.tsx +0 -59
  187. package/src/components/Menu/Button/index.ts +0 -1
  188. package/src/components/Menu/Menu.stories.tsx +0 -71
  189. package/src/components/Menu/Menu.styles.ts +0 -70
  190. package/src/components/Menu/Menu.tsx +0 -25
  191. package/src/components/Menu/MenuDivider.tsx +0 -13
  192. package/src/components/Menu/MenuItem.tsx +0 -36
  193. package/src/components/Menu/MenuItems.tsx +0 -35
  194. package/src/components/Menu/index.ts +0 -12
  195. package/src/components/Menu/useMenu.tsx +0 -79
  196. package/src/components/Tooltip/TextOverflowTooltip/TextOverflowTooltip.stories.tsx +0 -71
  197. package/src/components/Tooltip/TextOverflowTooltip/TextOverflowTooltip.styles.ts +0 -5
  198. package/src/components/Tooltip/TextOverflowTooltip/TextOverflowTooltip.tsx +0 -115
  199. package/src/components/Tooltip/TextOverflowTooltip/index.tsx +0 -1
  200. package/src/components/Tooltip/Tooltip.stories.tsx +0 -41
  201. package/src/components/Tooltip/Tooltip.styles.ts +0 -5
  202. package/src/components/Tooltip/Tooltip.tsx +0 -46
  203. package/src/components/Tooltip/index.ts +0 -1
  204. package/src/screens/dashboard/DashboardsDetail.stories.tsx +0 -108
  205. package/src/utils/useResizeObserver.ts +0 -6
@@ -0,0 +1,94 @@
1
+ import { useEffect, useState } from 'react';
2
+
3
+ import { ScaleLinear } from 'd3-scale';
4
+ import { useAtomValue } from 'jotai';
5
+ import { isEmpty, isNil, not } from 'ramda';
6
+
7
+ import useAxisY from '../../BasicComponents/Axes/useAxisY';
8
+ import { margin } from '../../common';
9
+ import { getMetrics, getTimeValue } from '../../timeSeries';
10
+ import { Line, TimeValue } from '../../timeSeries/models';
11
+ import { mousePositionAtom, timeValueAtom } from '../interactionWithGraphAtoms';
12
+
13
+ interface AnchorPointResult {
14
+ positionX?: number;
15
+ positionY?: number;
16
+ tickAxisBottom: Date | null;
17
+ tickAxisLeft: string | null;
18
+ tickAxisRight: string | null;
19
+ }
20
+
21
+ interface Props {
22
+ baseAxis?: number;
23
+ leftScale?: ScaleLinear<number, number>;
24
+ lines?: Array<Line>;
25
+ rightScale?: ScaleLinear<number, number>;
26
+ timeSeries: Array<TimeValue>;
27
+ xScale: ScaleLinear<number, number>;
28
+ }
29
+
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
+
44
+ const mousePosition = useAtomValue(mousePositionAtom);
45
+ const timeValueData = useAtomValue(timeValueAtom);
46
+
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;
53
+
54
+ useEffect(() => {
55
+ if (!mousePosition) {
56
+ setTickAxisBottom(null);
57
+ setTickAxisLeft(null);
58
+ setTickAxisRight(null);
59
+
60
+ return;
61
+ }
62
+ const mousePositionTimeTick = mousePosition
63
+ ? getTimeValue({ timeSeries, x: mousePosition[0], xScale }).timeTick
64
+ : 0;
65
+ const timeTickValue = containsMetrics
66
+ ? new Date(mousePositionTimeTick)
67
+ : null;
68
+
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);
84
+ }, [mousePosition]);
85
+
86
+ return {
87
+ positionX,
88
+ positionY,
89
+ tickAxisBottom,
90
+ tickAxisLeft,
91
+ tickAxisRight
92
+ };
93
+ };
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,
68
+ tooltipTop: graphHeight + margin.top
69
+ });
70
+ }, [positionX, positionY, tickAxisBottom]);
71
+
72
+ useEffect(() => {
73
+ if (!positionX || !positionY || !tickAxisLeft) {
74
+ return;
75
+ }
76
+ showTooltipAxisYLeft({
77
+ tooltipData: tickAxisLeft,
78
+ tooltipLeft: margin.left,
79
+ tooltipTop: positionY + margin.top
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 + margin.left : 0,
90
+ tooltipTop: positionY + margin.top
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;
@@ -0,0 +1,114 @@
1
+ import { Shape } from '@visx/visx';
2
+ import { ScaleTime } from 'd3-scale';
3
+ import { max, pick, prop } from 'ramda';
4
+ import { useAtom, useAtomValue } from 'jotai';
5
+ import { makeStyles } from 'tss-react/mui';
6
+
7
+ import { useLocaleDateTimeFormat, useMemoComponent } from '@centreon/ui';
8
+
9
+ import { labelFrom, labelTo } from '../../../translatedLabels';
10
+ import {
11
+ annotationHoveredAtom,
12
+ getFillColorDerivedAtom,
13
+ getIconColorDerivedAtom
14
+ } from '../annotationsAtoms';
15
+
16
+ import Annotation, { Props as AnnotationProps, yMargin, iconSize } from '.';
17
+
18
+ type Props = {
19
+ Icon: (props) => JSX.Element | null;
20
+ ariaLabel: string;
21
+ color: string;
22
+ endDate: string;
23
+ graphHeight: number;
24
+ startDate: string;
25
+ xScale: ScaleTime<number, number>;
26
+ } & Omit<AnnotationProps, 'marker' | 'xIcon' | 'header' | 'icon'>;
27
+
28
+ const useStyles = makeStyles()((theme) => ({
29
+ icon: {
30
+ transition: theme.transitions.create('color', {
31
+ duration: theme.transitions.duration.shortest
32
+ })
33
+ }
34
+ }));
35
+
36
+ const AreaAnnotation = ({
37
+ Icon,
38
+ ariaLabel,
39
+ color,
40
+ graphHeight,
41
+ xScale,
42
+ startDate,
43
+ endDate,
44
+ ...props
45
+ }: Props): JSX.Element => {
46
+ const { toDateTime } = useLocaleDateTimeFormat();
47
+
48
+ const { classes } = useStyles();
49
+
50
+ const [annotationHovered, setAnnotationHovered] = useAtom(
51
+ annotationHoveredAtom
52
+ );
53
+ const getFillColor = useAtomValue(getFillColorDerivedAtom);
54
+ const getIconColor = useAtomValue(getIconColorDerivedAtom);
55
+
56
+ const xIconMargin = -iconSize / 2;
57
+
58
+ const xStart = max(xScale(new Date(startDate)), 0);
59
+ const xEnd = endDate ? xScale(new Date(endDate)) : xScale.range()[1];
60
+
61
+ const annotation = pick(['event', 'annotationHoveredId'], props);
62
+
63
+ const area = (
64
+ <Shape.Bar
65
+ fill={getFillColor({ annotation, color })}
66
+ height={graphHeight + iconSize / 2}
67
+ width={xEnd - xStart}
68
+ x={xStart}
69
+ y={yMargin + iconSize + 2}
70
+ onMouseEnter={(): void =>
71
+ setAnnotationHovered(() => ({
72
+ annotation,
73
+ annotationHoveredId: prop('annotationHoveredId', props)
74
+ }))
75
+ }
76
+ onMouseLeave={(): void => setAnnotationHovered(() => undefined)}
77
+ />
78
+ );
79
+
80
+ const from = `${labelFrom} ${toDateTime(startDate)}`;
81
+ const to = endDate ? ` ${labelTo} ${toDateTime(endDate)}` : '';
82
+
83
+ const header = `${from}${to}`;
84
+
85
+ const icon = (
86
+ <Icon
87
+ aria-label={ariaLabel}
88
+ className={classes.icon}
89
+ height={iconSize}
90
+ style={{
91
+ color: getIconColor({
92
+ annotation,
93
+ color
94
+ })
95
+ }}
96
+ width={iconSize}
97
+ />
98
+ );
99
+
100
+ return useMemoComponent({
101
+ Component: (
102
+ <Annotation
103
+ header={header}
104
+ icon={icon}
105
+ marker={area}
106
+ xIcon={xStart + (xEnd - xStart) / 2 + xIconMargin}
107
+ {...props}
108
+ />
109
+ ),
110
+ memoProps: [annotationHovered, xStart, xEnd]
111
+ });
112
+ };
113
+
114
+ export default AreaAnnotation;
@@ -0,0 +1,103 @@
1
+ import { Shape } from '@visx/visx';
2
+ import { ScaleTime } from 'd3-scale';
3
+ import { pick } from 'ramda';
4
+ import { useAtomValue } from 'jotai';
5
+ import { makeStyles } from 'tss-react/mui';
6
+
7
+ import { useLocaleDateTimeFormat, useMemoComponent } from '@centreon/ui';
8
+
9
+ import {
10
+ annotationHoveredAtom,
11
+ getIconColorDerivedAtom,
12
+ getStrokeOpacityDerivedAtom,
13
+ getStrokeWidthDerivedAtom
14
+ } from '../annotationsAtoms';
15
+
16
+ import Annotation, { Props as AnnotationProps, yMargin, iconSize } from '.';
17
+
18
+ type Props = {
19
+ Icon: (props) => JSX.Element | null;
20
+ ariaLabel: string;
21
+ color: string;
22
+ date: string;
23
+ graphHeight: number;
24
+ xScale: ScaleTime<number, number>;
25
+ } & Omit<
26
+ AnnotationProps,
27
+ 'marker' | 'xIcon' | 'header' | 'icon' | 'setAnnotationHovered' | 'resourceId'
28
+ >;
29
+
30
+ const useStyles = makeStyles()((theme) => ({
31
+ icon: {
32
+ transition: theme.transitions.create('color', {
33
+ duration: theme.transitions.duration.shortest
34
+ })
35
+ }
36
+ }));
37
+
38
+ const LineAnnotation = ({
39
+ color,
40
+ graphHeight,
41
+ xScale,
42
+ date,
43
+ Icon,
44
+ ariaLabel,
45
+ ...props
46
+ }: Props): JSX.Element => {
47
+ const { toDateTime } = useLocaleDateTimeFormat();
48
+
49
+ const { classes } = useStyles();
50
+
51
+ const annotationHovered = useAtomValue(annotationHoveredAtom);
52
+ const getStrokeWidth = useAtomValue(getStrokeWidthDerivedAtom);
53
+ const getStrokeOpacity = useAtomValue(getStrokeOpacityDerivedAtom);
54
+ const getIconColor = useAtomValue(getIconColorDerivedAtom);
55
+
56
+ const xIconMargin = -iconSize / 2;
57
+
58
+ const xIcon = xScale(new Date(date));
59
+
60
+ const header = toDateTime(date);
61
+
62
+ const annotation = pick(['event', 'annotationHoveredId'], props);
63
+
64
+ const line = (
65
+ <Shape.Line
66
+ from={{ x: xIcon, y: yMargin + iconSize + 2 }}
67
+ stroke={color}
68
+ strokeOpacity={getStrokeOpacity(annotation)}
69
+ strokeWidth={getStrokeWidth(annotation)}
70
+ to={{ x: xIcon, y: graphHeight }}
71
+ />
72
+ );
73
+
74
+ const icon = (
75
+ <Icon
76
+ aria-label={ariaLabel}
77
+ className={classes.icon}
78
+ height={iconSize}
79
+ style={{
80
+ color: getIconColor({
81
+ annotation,
82
+ color
83
+ })
84
+ }}
85
+ width={iconSize}
86
+ />
87
+ );
88
+
89
+ return useMemoComponent({
90
+ Component: (
91
+ <Annotation
92
+ header={header}
93
+ icon={icon}
94
+ marker={line}
95
+ xIcon={xIcon + xIconMargin}
96
+ {...props}
97
+ />
98
+ ),
99
+ memoProps: [annotationHovered, xIcon]
100
+ });
101
+ };
102
+
103
+ export default LineAnnotation;
@@ -0,0 +1,81 @@
1
+ import { useTranslation } from 'react-i18next';
2
+ import { useSetAtom } from 'jotai';
3
+ import { makeStyles } from 'tss-react/mui';
4
+
5
+ import { Tooltip, Paper, Typography } from '@mui/material';
6
+
7
+ import { truncate } from '../../../helpers';
8
+ import { labelBy } from '../../../translatedLabels';
9
+ import { TimelineEvent } from '../models';
10
+ import { annotationHoveredAtom } from '../annotationsAtoms';
11
+
12
+ const yMargin = -32;
13
+ const iconSize = 20;
14
+
15
+ const useStyles = makeStyles()((theme) => ({
16
+ tooltip: {
17
+ backgroundColor: 'transparent'
18
+ },
19
+ tooltipContent: {
20
+ padding: theme.spacing(1)
21
+ }
22
+ }));
23
+
24
+ export interface Props {
25
+ annotationHoveredId: number;
26
+ event: TimelineEvent;
27
+ header: string;
28
+ icon: JSX.Element;
29
+ marker: JSX.Element;
30
+ xIcon: number;
31
+ }
32
+
33
+ const Annotation = ({
34
+ icon,
35
+ header,
36
+ event,
37
+ xIcon,
38
+ marker,
39
+ annotationHoveredId
40
+ }: Props): JSX.Element => {
41
+ const { classes } = useStyles();
42
+ const { t } = useTranslation();
43
+
44
+ const setAnnotationHovered = useSetAtom(annotationHoveredAtom);
45
+
46
+ const content = `${truncate(event.content)} (${t(labelBy)} ${
47
+ event.contact?.name
48
+ })`;
49
+
50
+ return (
51
+ <g>
52
+ <Tooltip
53
+ classes={{ tooltip: classes.tooltip }}
54
+ title={
55
+ <Paper className={classes.tooltipContent}>
56
+ <Typography variant="body2">{header}</Typography>
57
+ <Typography variant="caption">{content}</Typography>
58
+ </Paper>
59
+ }
60
+ >
61
+ <svg
62
+ height={iconSize}
63
+ width={iconSize}
64
+ x={xIcon}
65
+ y={yMargin}
66
+ onMouseEnter={(): void =>
67
+ setAnnotationHovered(() => ({ annotationHoveredId, event }))
68
+ }
69
+ onMouseLeave={(): void => setAnnotationHovered(() => undefined)}
70
+ >
71
+ <rect fill="transparent" height={iconSize} width={iconSize} />
72
+ {icon}
73
+ </svg>
74
+ </Tooltip>
75
+ {marker}
76
+ </g>
77
+ );
78
+ };
79
+
80
+ export default Annotation;
81
+ export { yMargin, iconSize };
@@ -0,0 +1,27 @@
1
+ import { useTranslation } from 'react-i18next';
2
+
3
+ import { useTheme } from '@mui/material';
4
+
5
+ import IconDowntime from '../../../Icons/Downtime';
6
+ import { labelDowntime } from '../../../translatedLabels';
7
+ import EventAnnotations from '../EventAnnotations';
8
+ import { Args } from '../models';
9
+
10
+ const DowntimeAnnotations = (props: Args): JSX.Element => {
11
+ const { t } = useTranslation();
12
+ const theme = useTheme();
13
+
14
+ const color = theme.palette.action.inDowntime;
15
+
16
+ return (
17
+ <EventAnnotations
18
+ Icon={IconDowntime}
19
+ ariaLabel={t(labelDowntime)}
20
+ color={color}
21
+ type="downtime"
22
+ {...props}
23
+ />
24
+ );
25
+ };
26
+
27
+ export default DowntimeAnnotations;
@@ -0,0 +1,61 @@
1
+ import { filter, propEq, isNil } from 'ramda';
2
+ import { ScaleTime } from 'd3-scale';
3
+
4
+ import { TimelineEvent } from './models';
5
+ import LineAnnotation from './Annotation/Line';
6
+ import AreaAnnotation from './Annotation/Area';
7
+
8
+ interface Props {
9
+ Icon: (props) => JSX.Element | null;
10
+ annotationHoveredId: number;
11
+ ariaLabel: string;
12
+ color: string;
13
+ data: Array<TimelineEvent>;
14
+ graphHeight: number;
15
+ type: string;
16
+ xScale: ScaleTime<number, number>;
17
+ }
18
+
19
+ const EventAnnotations = ({
20
+ type,
21
+ xScale,
22
+ data,
23
+ graphHeight,
24
+ Icon,
25
+ ariaLabel,
26
+ color,
27
+ annotationHoveredId
28
+ }: Props): JSX.Element => {
29
+ const events = filter(propEq('type', type), data);
30
+
31
+ return (
32
+ <>
33
+ {events.map((event) => {
34
+ const props = {
35
+ Icon,
36
+ annotationHoveredId,
37
+ ariaLabel,
38
+ color,
39
+ event,
40
+ graphHeight,
41
+ xScale
42
+ };
43
+
44
+ if (isNil(event.startDate) && isNil(event.endDate)) {
45
+ return <LineAnnotation date={event.date} key={event.id} {...props} />;
46
+ }
47
+
48
+ return (
49
+ <AreaAnnotation
50
+ endDate={event.endDate as string}
51
+ key={event.id}
52
+ startDate={event.startDate as string}
53
+ {...props}
54
+ />
55
+ );
56
+ })}
57
+ </>
58
+ );
59
+ };
60
+
61
+ export default EventAnnotations;
@@ -0,0 +1,27 @@
1
+ import { useTranslation } from 'react-i18next';
2
+
3
+ import IconAcknowledge from '@mui/icons-material/Person';
4
+ import { useTheme } from '@mui/material';
5
+
6
+ import { labelAcknowledgement } from '../../../translatedLabels';
7
+ import EventAnnotations from '../EventAnnotations';
8
+ import { Args } from '../models';
9
+
10
+ const AcknowledgementAnnotations = (props: Args): JSX.Element => {
11
+ const { t } = useTranslation();
12
+ const theme = useTheme();
13
+
14
+ const color = theme.palette.action.acknowledged;
15
+
16
+ return (
17
+ <EventAnnotations
18
+ Icon={IconAcknowledge}
19
+ ariaLabel={t(labelAcknowledgement)}
20
+ color={color}
21
+ type="acknowledgement"
22
+ {...props}
23
+ />
24
+ );
25
+ };
26
+
27
+ export default AcknowledgementAnnotations;
@@ -0,0 +1,25 @@
1
+ import { useTranslation } from 'react-i18next';
2
+
3
+ import { useTheme } from '@mui/material';
4
+ import IconComment from '@mui/icons-material/Comment';
5
+
6
+ import { labelComment } from '../../../translatedLabels';
7
+ import EventAnnotations from '../EventAnnotations';
8
+ import { Args } from '../models';
9
+
10
+ const CommentAnnotations = (props: Args): JSX.Element => {
11
+ const { t } = useTranslation();
12
+ const theme = useTheme();
13
+
14
+ return (
15
+ <EventAnnotations
16
+ Icon={IconComment}
17
+ ariaLabel={t(labelComment)}
18
+ color={theme.palette.primary.main}
19
+ type="comment"
20
+ {...props}
21
+ />
22
+ );
23
+ };
24
+
25
+ export default CommentAnnotations;