@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,183 @@
1
+ import { ScaleTime } from 'd3-scale';
2
+ import { atom } from 'jotai';
3
+ import {
4
+ always,
5
+ both,
6
+ cond,
7
+ dec,
8
+ equals,
9
+ find,
10
+ gte,
11
+ inc,
12
+ isNil,
13
+ last,
14
+ lte,
15
+ not,
16
+ or,
17
+ pipe,
18
+ Pred,
19
+ T,
20
+ __
21
+ } from 'ramda';
22
+
23
+ import { alpha } from '@mui/material';
24
+
25
+ import { TimelineEvent } from './models';
26
+
27
+ interface ChangeAnnotationHoveredProps {
28
+ annotationHoveredId: number;
29
+ graphWidth: number;
30
+ mouseX: number;
31
+ timeline: Array<TimelineEvent> | undefined;
32
+ xScale: ScaleTime<number, number>;
33
+ }
34
+
35
+ interface GetIsBetweenProps {
36
+ end: number;
37
+ start: number;
38
+ }
39
+
40
+ interface AnnotationColor {
41
+ annotation: AnnotationAtom;
42
+ color: string;
43
+ }
44
+
45
+ interface AnnotationAtom {
46
+ annotationHoveredId: number;
47
+ event?: TimelineEvent;
48
+ }
49
+
50
+ interface AnnotationWithHoveredState {
51
+ annotation: AnnotationAtom | undefined;
52
+ hoveredAnnotation: AnnotationAtom | undefined;
53
+ }
54
+
55
+ export const annotationHoveredAtom = atom<AnnotationAtom | undefined>(
56
+ undefined
57
+ );
58
+
59
+ export const getIsBetween = ({ start, end }: GetIsBetweenProps): Pred => {
60
+ const gteX = gte(__, start);
61
+ const lteX = lte(__, end);
62
+
63
+ return both(gteX, lteX);
64
+ };
65
+
66
+ export const changeAnnotationHoveredDerivedAtom = atom(
67
+ null,
68
+ (
69
+ _,
70
+ set,
71
+ {
72
+ xScale,
73
+ mouseX,
74
+ timeline,
75
+ graphWidth,
76
+ annotationHoveredId
77
+ }: ChangeAnnotationHoveredProps
78
+ ) => {
79
+ const isWithinErrorMargin = getIsBetween({
80
+ end: inc(mouseX),
81
+ start: dec(mouseX)
82
+ });
83
+
84
+ const annotationHovered = find(
85
+ ({ startDate, endDate, date }: TimelineEvent) => {
86
+ if (isNil(startDate)) {
87
+ return isWithinErrorMargin(xScale(new Date(date)));
88
+ }
89
+
90
+ const isBetweenStartAndEndDate = getIsBetween({
91
+ end: xScale(
92
+ endDate ? new Date(endDate) : last(xScale.domain()) || graphWidth
93
+ ),
94
+ start: xScale(new Date(startDate as string))
95
+ });
96
+
97
+ return isBetweenStartAndEndDate(mouseX);
98
+ },
99
+ timeline ?? []
100
+ );
101
+
102
+ set(annotationHoveredAtom, {
103
+ annotationHoveredId,
104
+ event: annotationHovered
105
+ });
106
+ }
107
+ );
108
+
109
+ const getIsNotHoveredOrNil = ({
110
+ hoveredAnnotation,
111
+ annotation
112
+ }: AnnotationWithHoveredState): boolean =>
113
+ or(
114
+ isNil(hoveredAnnotation?.event),
115
+ not(
116
+ equals(
117
+ hoveredAnnotation?.annotationHoveredId,
118
+ annotation?.annotationHoveredId
119
+ )
120
+ )
121
+ );
122
+
123
+ export const getStrokeWidthDerivedAtom = atom(
124
+ (get) =>
125
+ (annotation: AnnotationAtom | undefined): number =>
126
+ cond<AnnotationAtom | undefined, number>([
127
+ [
128
+ (hoveredAnnotation): boolean =>
129
+ getIsNotHoveredOrNil({ annotation, hoveredAnnotation }),
130
+ always(1)
131
+ ],
132
+ [equals(annotation), always(3)],
133
+ [T, always(1)]
134
+ ])(get(annotationHoveredAtom)) as number
135
+ );
136
+
137
+ export const getStrokeOpacityDerivedAtom = atom(
138
+ (get) =>
139
+ (annotation: AnnotationAtom | undefined): number =>
140
+ cond<AnnotationAtom | undefined, number>([
141
+ [
142
+ (hoveredAnnotation): boolean =>
143
+ getIsNotHoveredOrNil({ annotation, hoveredAnnotation }),
144
+ always(0.5)
145
+ ],
146
+ [equals(annotation), always(0.7)],
147
+ [T, always(0.2)]
148
+ ])(get(annotationHoveredAtom)) as number
149
+ );
150
+
151
+ export const getFillColorDerivedAtom = atom(
152
+ (get) =>
153
+ ({ color, annotation }: AnnotationColor): string =>
154
+ cond<AnnotationAtom | undefined, string>([
155
+ [
156
+ (hoveredAnnotation): boolean =>
157
+ getIsNotHoveredOrNil({ annotation, hoveredAnnotation }),
158
+ always(alpha(color, 0.3))
159
+ ],
160
+ [
161
+ equals<AnnotationAtom | undefined>(annotation),
162
+ always(alpha(color, 0.5))
163
+ ],
164
+ [T, always(alpha(color, 0.1))]
165
+ ])(get(annotationHoveredAtom)) as string
166
+ );
167
+
168
+ export const getIconColorDerivedAtom = atom(
169
+ (get) =>
170
+ ({ color, annotation }: AnnotationColor): string =>
171
+ cond<AnnotationAtom | undefined, string>([
172
+ [
173
+ (hoveredAnnotation): boolean =>
174
+ getIsNotHoveredOrNil({ annotation, hoveredAnnotation }),
175
+ always(color)
176
+ ],
177
+ [
178
+ pipe(equals<AnnotationAtom | undefined>(annotation), not),
179
+ always(alpha(color, 0.2))
180
+ ],
181
+ [T, always(color)]
182
+ ])(get(annotationHoveredAtom)) as string
183
+ );
@@ -0,0 +1,49 @@
1
+ import { MutableRefObject } from 'react';
2
+
3
+ import { ScaleTime } from 'd3-scale';
4
+
5
+ import DowntimeAnnotations from './Area/Downtime';
6
+ import AcknowledgementAnnotations from './Line/Acknowledgement';
7
+ import CommentAnnotations from './Line/Comments';
8
+ import { TimelineEvent } from './models';
9
+ import useAnnotation from './useAnnotation';
10
+
11
+ export interface Props {
12
+ data: Array<TimelineEvent>;
13
+ graphHeight: number;
14
+ graphSvgRef: MutableRefObject<SVGSVGElement | null>;
15
+ graphWidth: number;
16
+ xScale: ScaleTime<number, number>;
17
+ }
18
+
19
+ const Annotations = ({
20
+ xScale,
21
+ data,
22
+ graphHeight,
23
+ graphWidth,
24
+ graphSvgRef
25
+ }: Props): JSX.Element => {
26
+ const annotationHoveredId = useAnnotation({
27
+ data,
28
+ graphSvgRef,
29
+ graphWidth,
30
+ xScale
31
+ });
32
+
33
+ const props = {
34
+ annotationHoveredId,
35
+ data,
36
+ graphHeight,
37
+ xScale
38
+ };
39
+
40
+ return (
41
+ <g>
42
+ <CommentAnnotations {...props} />
43
+ <AcknowledgementAnnotations {...props} />
44
+ <DowntimeAnnotations {...props} />
45
+ </g>
46
+ );
47
+ };
48
+
49
+ export default Annotations;
@@ -0,0 +1,25 @@
1
+ import { Props } from '.';
2
+
3
+ export interface Status {
4
+ name: string;
5
+ severity_code: number;
6
+ }
7
+
8
+ export interface WithName {
9
+ name: string;
10
+ }
11
+ export interface TimelineEvent {
12
+ contact?: WithName;
13
+ content: string;
14
+ date: string;
15
+ endDate?: string;
16
+ id: number;
17
+ startDate?: string;
18
+ status?: Status;
19
+ tries?: number;
20
+ type: string;
21
+ }
22
+
23
+ export interface Args extends Omit<Props, 'graphWidth' | 'graphSvgRef'> {
24
+ annotationHoveredId: number;
25
+ }
@@ -0,0 +1,56 @@
1
+ import { useEffect } from 'react';
2
+
3
+ import { useAtomValue, useSetAtom } from 'jotai';
4
+
5
+ import { margin } from '../../common';
6
+ import {
7
+ eventMouseLeaveAtom,
8
+ mousePositionAtom
9
+ } from '../interactionWithGraphAtoms';
10
+
11
+ import {
12
+ annotationHoveredAtom,
13
+ changeAnnotationHoveredDerivedAtom
14
+ } from './annotationsAtoms';
15
+
16
+ import { Props } from '.';
17
+
18
+ const useAnnotation = ({
19
+ graphWidth,
20
+ data,
21
+ xScale
22
+ }: Omit<Props, 'graphHeight'>): number => {
23
+ const [annotationHoveredId] = crypto.getRandomValues(new Uint16Array(1));
24
+
25
+ const mousePosition = useAtomValue(mousePositionAtom);
26
+ const mouseLeaveEvent = useAtomValue(eventMouseLeaveAtom);
27
+
28
+ const setAnnotationHovered = useSetAtom(annotationHoveredAtom);
29
+ const changeAnnotationHovered = useSetAtom(
30
+ changeAnnotationHoveredDerivedAtom
31
+ );
32
+
33
+ useEffect(() => {
34
+ if (!mousePosition) {
35
+ return;
36
+ }
37
+
38
+ const mousePositionX = mousePosition[0] - margin.left;
39
+
40
+ changeAnnotationHovered({
41
+ annotationHoveredId,
42
+ graphWidth,
43
+ mouseX: mousePositionX,
44
+ timeline: data,
45
+ xScale
46
+ });
47
+ }, [mousePosition]);
48
+
49
+ useEffect(() => {
50
+ setAnnotationHovered(undefined);
51
+ }, [mouseLeaveEvent]);
52
+
53
+ return annotationHoveredId;
54
+ };
55
+
56
+ export default useAnnotation;
@@ -0,0 +1,21 @@
1
+ import { Shape } from '@visx/visx';
2
+ import { AddSVGProps } from '@visx/shape/lib/types';
3
+
4
+ interface BarProps {
5
+ className?: string;
6
+ innerRef?: React.Ref<SVGRectElement>;
7
+ open?: boolean;
8
+ }
9
+
10
+ const Bar = ({
11
+ open = true,
12
+ ...restProps
13
+ }: AddSVGProps<BarProps, SVGRectElement>): JSX.Element | null => {
14
+ if (!open) {
15
+ return null;
16
+ }
17
+
18
+ return <Shape.Bar {...restProps} />;
19
+ };
20
+
21
+ export default Bar;
@@ -0,0 +1,62 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ import { useTranslation } from 'react-i18next';
4
+ import { makeStyles } from 'tss-react/mui';
5
+
6
+ import { useMemoComponent } from '@centreon/ui';
7
+
8
+ import { TimeShiftDirection } from './models';
9
+
10
+ export const timeShiftIconSize = 20;
11
+
12
+ interface Props {
13
+ Icon: ReactNode;
14
+ ariaLabel: string;
15
+ directionHovered: TimeShiftDirection;
16
+ xIcon: number;
17
+ yIcon: number;
18
+ }
19
+
20
+ const useStyles = makeStyles()({
21
+ icon: {
22
+ cursor: 'pointer'
23
+ }
24
+ });
25
+
26
+ const TimeShiftIcon = ({
27
+ xIcon,
28
+ yIcon,
29
+ Icon,
30
+ ariaLabel,
31
+ directionHovered
32
+ }: Props): JSX.Element => {
33
+ const { classes } = useStyles();
34
+ const { t } = useTranslation();
35
+
36
+ const svgProps = {
37
+ 'aria-label': t(ariaLabel),
38
+ className: classes.icon,
39
+ height: timeShiftIconSize,
40
+ width: timeShiftIconSize,
41
+ x: xIcon,
42
+ y: yIcon
43
+ };
44
+
45
+ return useMemoComponent({
46
+ Component: (
47
+ <g>
48
+ <svg {...svgProps}>
49
+ <rect
50
+ fill="transparent"
51
+ height={timeShiftIconSize}
52
+ width={timeShiftIconSize}
53
+ />
54
+ {Icon}
55
+ </svg>
56
+ </g>
57
+ ),
58
+ memoProps: [xIcon, ariaLabel, directionHovered]
59
+ });
60
+ };
61
+
62
+ export default TimeShiftIcon;
@@ -0,0 +1,74 @@
1
+ import { Dispatch, SetStateAction } from 'react';
2
+
3
+ import { Shape } from '@visx/visx';
4
+ import { equals, negate } from 'ramda';
5
+ import { makeStyles } from 'tss-react/mui';
6
+
7
+ import { alpha, useTheme } from '@mui/material';
8
+
9
+ import { GraphInterval, Interval } from '../../models';
10
+
11
+ import { TimeShiftDirection } from './models';
12
+ import useTimeShiftZones from './useTimeShiftZones';
13
+
14
+ export const timeShiftZoneWidth = 50;
15
+
16
+ const useStyles = makeStyles()({
17
+ translationZone: {
18
+ cursor: 'pointer'
19
+ }
20
+ });
21
+
22
+ interface Props {
23
+ direction: TimeShiftDirection;
24
+ directionHovered: TimeShiftDirection | null;
25
+ getInterval?: (args: Interval) => void;
26
+ graphHeight: number;
27
+ graphInterval: GraphInterval;
28
+ graphWidth: number;
29
+ onDirectionHover: Dispatch<SetStateAction<TimeShiftDirection | null>>;
30
+ }
31
+
32
+ const TimeShiftZone = ({
33
+ direction,
34
+ onDirectionHover,
35
+ directionHovered,
36
+ graphHeight,
37
+ graphWidth,
38
+ graphInterval,
39
+ getInterval
40
+ }: Props): JSX.Element => {
41
+ const theme = useTheme();
42
+ const { classes } = useStyles();
43
+
44
+ const { end, start } = useTimeShiftZones({
45
+ direction,
46
+ graphInterval
47
+ });
48
+
49
+ const handleClick = (): void => getInterval?.({ end, start });
50
+
51
+ return (
52
+ <Shape.Bar
53
+ className={classes.translationZone}
54
+ fill={
55
+ equals(directionHovered, direction)
56
+ ? alpha(theme.palette.common.white, 0.5)
57
+ : 'transparent'
58
+ }
59
+ height={graphHeight}
60
+ width={timeShiftZoneWidth}
61
+ x={
62
+ equals(direction, TimeShiftDirection.backward)
63
+ ? negate(timeShiftZoneWidth)
64
+ : graphWidth
65
+ }
66
+ y={0}
67
+ onClick={handleClick}
68
+ onMouseLeave={(): void => onDirectionHover(null)}
69
+ onMouseOver={(): void => onDirectionHover(direction)}
70
+ />
71
+ );
72
+ };
73
+
74
+ export default TimeShiftZone;
@@ -0,0 +1,85 @@
1
+ import { useState } from 'react';
2
+
3
+ import { equals, isNil, negate } from 'ramda';
4
+
5
+ import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
6
+ import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
7
+
8
+ import { GraphInterval, Interval } from '../../models';
9
+ import { margin } from '../../common';
10
+
11
+ import TimeShiftIcon, { timeShiftIconSize } from './TimeShiftIcon';
12
+ import TimeShiftZone from './TimeShiftZone';
13
+ import { TimeShiftDirection } from './models';
14
+
15
+ interface Props {
16
+ getInterval?: (args: Interval) => void;
17
+ graphHeight: number;
18
+ graphInterval: GraphInterval;
19
+ graphWidth: number;
20
+ }
21
+
22
+ const TimeShiftZones = ({
23
+ graphHeight,
24
+ graphWidth,
25
+ getInterval,
26
+ graphInterval
27
+ }: Props): JSX.Element => {
28
+ const [directionHovered, setDirectionHovered] =
29
+ useState<TimeShiftDirection | null>(null);
30
+
31
+ const marginLeft = margin.left;
32
+
33
+ const isBackward = equals(directionHovered, TimeShiftDirection.backward);
34
+ const displayIcon = !isNil(directionHovered);
35
+ const propsIcon = { color: 'primary' as const };
36
+
37
+ const xIcon = isBackward
38
+ ? negate(marginLeft)
39
+ : graphWidth + timeShiftIconSize;
40
+
41
+ const yIcon = graphHeight / 2 - timeShiftIconSize / 2;
42
+
43
+ const Icon = isBackward ? (
44
+ <ArrowBackIosIcon {...propsIcon} />
45
+ ) : (
46
+ <ArrowForwardIosIcon {...propsIcon} />
47
+ );
48
+ const ariaLabelIcon = isBackward ? 'labelBackward' : 'labelForward';
49
+
50
+ const commonData = {
51
+ getInterval,
52
+ graphHeight,
53
+ graphInterval,
54
+ graphWidth
55
+ };
56
+
57
+ return (
58
+ <>
59
+ {displayIcon && (
60
+ <TimeShiftIcon
61
+ Icon={Icon}
62
+ ariaLabel={ariaLabelIcon}
63
+ directionHovered={directionHovered}
64
+ xIcon={xIcon}
65
+ yIcon={yIcon}
66
+ />
67
+ )}
68
+
69
+ <TimeShiftZone
70
+ direction={TimeShiftDirection.backward}
71
+ directionHovered={directionHovered}
72
+ onDirectionHover={setDirectionHovered}
73
+ {...commonData}
74
+ />
75
+ <TimeShiftZone
76
+ direction={TimeShiftDirection.forward}
77
+ directionHovered={directionHovered}
78
+ onDirectionHover={setDirectionHovered}
79
+ {...commonData}
80
+ />
81
+ </>
82
+ );
83
+ };
84
+
85
+ export default TimeShiftZones;
@@ -0,0 +1,12 @@
1
+ import { GraphInterval, GraphIntervalProperty } from '../../models';
2
+
3
+ export enum TimeShiftDirection {
4
+ backward,
5
+ forward
6
+ }
7
+
8
+ export interface GetShiftDate {
9
+ property: GraphIntervalProperty;
10
+ timePeriod: GraphInterval;
11
+ timeShiftDirection: TimeShiftDirection;
12
+ }
@@ -0,0 +1,72 @@
1
+ import { useEffect, useState } from 'react';
2
+
3
+ import { add, equals, negate, prop } from 'ramda';
4
+
5
+ import { GraphInterval, GraphIntervalProperty, Interval } from '../../models';
6
+
7
+ import { GetShiftDate, TimeShiftDirection } from './models';
8
+
9
+ interface Props {
10
+ direction: TimeShiftDirection;
11
+ graphInterval: GraphInterval;
12
+ }
13
+
14
+ const useTimeShiftZones = ({ graphInterval, direction }: Props): Interval => {
15
+ const shiftRatio = 2;
16
+
17
+ const [start, setStart] = useState<Date>();
18
+ const [end, setEnd] = useState<Date>();
19
+
20
+ const getShiftedDate = ({
21
+ property,
22
+ timeShiftDirection,
23
+ timePeriod
24
+ }: GetShiftDate): Date | null => {
25
+ if (!timePeriod?.end || !timePeriod?.start) {
26
+ return null;
27
+ }
28
+ const adjustTimePeriodProps =
29
+ (new Date(timePeriod.end).getTime() -
30
+ new Date(timePeriod.start).getTime()) /
31
+ shiftRatio;
32
+
33
+ const date = prop(property, timePeriod);
34
+
35
+ if (!date) {
36
+ return null;
37
+ }
38
+
39
+ return new Date(
40
+ add(
41
+ new Date(date).getTime(),
42
+ equals(timeShiftDirection, TimeShiftDirection.backward)
43
+ ? negate(adjustTimePeriodProps)
44
+ : adjustTimePeriodProps
45
+ )
46
+ );
47
+ };
48
+
49
+ useEffect(() => {
50
+ const endInterval = getShiftedDate({
51
+ property: GraphIntervalProperty.end,
52
+ timePeriod: graphInterval,
53
+ timeShiftDirection: direction
54
+ });
55
+
56
+ const startInterval = getShiftedDate({
57
+ property: GraphIntervalProperty.start,
58
+ timePeriod: graphInterval,
59
+ timeShiftDirection: direction
60
+ });
61
+
62
+ if (!endInterval || !startInterval) {
63
+ return;
64
+ }
65
+ setStart(startInterval);
66
+ setEnd(endInterval);
67
+ }, [graphInterval.end, graphInterval.start, direction]);
68
+
69
+ return { end, start } as Interval;
70
+ };
71
+
72
+ export default useTimeShiftZones;
@@ -0,0 +1,59 @@
1
+ import { useEffect } from 'react';
2
+
3
+ import { equals } from 'ramda';
4
+
5
+ import { Paper } from '@mui/material';
6
+
7
+ import { Tooltip } from '../../models';
8
+
9
+ import { GraphTooltip as GraphTooltipModel, width } from './models';
10
+
11
+ interface Props extends GraphTooltipModel, Tooltip {
12
+ [x: string]: unknown;
13
+ }
14
+
15
+ const GraphTooltip = ({
16
+ hideTooltip,
17
+ tooltipLeft,
18
+ tooltipTop,
19
+ tooltipData,
20
+ renderComponent,
21
+ tooltipOpen
22
+ }: Props): JSX.Element | null => {
23
+ const hideTooltipOnEscapePress = (event: globalThis.KeyboardEvent): void => {
24
+ if (equals(event.key, 'Escape')) {
25
+ hideTooltip();
26
+ }
27
+ };
28
+
29
+ useEffect(() => {
30
+ document.addEventListener('keydown', hideTooltipOnEscapePress, false);
31
+
32
+ return (): void => {
33
+ document.removeEventListener('keydown', hideTooltipOnEscapePress, false);
34
+ };
35
+ }, []);
36
+
37
+ if (!tooltipOpen) {
38
+ return null;
39
+ }
40
+
41
+ return (
42
+ <Paper
43
+ style={{
44
+ left: tooltipLeft,
45
+ position: 'absolute',
46
+ top: tooltipTop,
47
+ width
48
+ }}
49
+ >
50
+ {renderComponent?.({
51
+ data: tooltipData,
52
+ hideTooltip,
53
+ tooltipOpen
54
+ })}
55
+ </Paper>
56
+ );
57
+ };
58
+
59
+ export default GraphTooltip;