@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,95 @@
1
+ import { useAtomValue } from 'jotai';
2
+ import { useTranslation } from 'react-i18next';
3
+
4
+ import AccessTimeIcon from '@mui/icons-material/AccessTime';
5
+ import { Button, Typography } from '@mui/material';
6
+
7
+ import { dateTimeFormat, useLocaleDateTimeFormat } from '@centreon/ui';
8
+
9
+ import { customTimePeriodAtom } from '../timePeriodsAtoms';
10
+ import {
11
+ labelCompactTimePeriod,
12
+ labelFrom,
13
+ labelTo
14
+ } from '../translatedLabels';
15
+
16
+ import useStyles from './CompactCustomTimePeriod.styles';
17
+
18
+ interface Props {
19
+ disabled?: boolean;
20
+ onClick: (event) => void;
21
+ }
22
+
23
+ const CompactCustomTimePeriod = ({
24
+ onClick,
25
+ disabled = false
26
+ }: Props): JSX.Element => {
27
+ const { classes } = useStyles();
28
+ const { t } = useTranslation();
29
+
30
+ const { format } = useLocaleDateTimeFormat();
31
+
32
+ const customTimePeriod = useAtomValue(customTimePeriodAtom);
33
+
34
+ return (
35
+ <div>
36
+ <Button
37
+ aria-label={t(labelCompactTimePeriod) as string}
38
+ className={classes.button}
39
+ color="primary"
40
+ data-testid={labelCompactTimePeriod}
41
+ disabled={disabled}
42
+ variant="outlined"
43
+ onClick={onClick}
44
+ >
45
+ <div className={classes.buttonContent}>
46
+ <AccessTimeIcon />
47
+ <div className={classes.containerDates}>
48
+ <div className={classes.timeContainer}>
49
+ <Typography
50
+ className={classes.label}
51
+ component="div"
52
+ variant="caption"
53
+ >
54
+ {t(labelFrom)}:
55
+ </Typography>
56
+
57
+ <Typography
58
+ className={classes.date}
59
+ component="div"
60
+ variant="caption"
61
+ >
62
+ {format({
63
+ date: customTimePeriod.start,
64
+ formatString: dateTimeFormat
65
+ })}
66
+ </Typography>
67
+ </div>
68
+ <div className={classes.timeContainer}>
69
+ <Typography
70
+ className={classes.label}
71
+ component="div"
72
+ variant="caption"
73
+ >
74
+ {t(labelTo)}:
75
+ </Typography>
76
+
77
+ <Typography
78
+ className={classes.date}
79
+ component="div"
80
+ variant="caption"
81
+ >
82
+ {format({
83
+ date: customTimePeriod.end,
84
+ formatString: dateTimeFormat
85
+ })}
86
+ </Typography>
87
+ </div>
88
+ </div>
89
+ </div>
90
+ </Button>
91
+ </div>
92
+ );
93
+ };
94
+
95
+ export default CompactCustomTimePeriod;
@@ -0,0 +1,14 @@
1
+ import { FormHelperText } from '@mui/material';
2
+
3
+ interface Props {
4
+ message: string;
5
+ style: string;
6
+ }
7
+
8
+ const ErrorText = ({ message, style }: Props): JSX.Element => (
9
+ <FormHelperText error className={style}>
10
+ {message}
11
+ </FormHelperText>
12
+ );
13
+
14
+ export default ErrorText;
@@ -0,0 +1,163 @@
1
+ import { useAtomValue } from 'jotai';
2
+ import { makeStyles } from 'tss-react/mui';
3
+ import { equals } from 'ramda';
4
+
5
+ import { Typography } from '@mui/material';
6
+ import { LocalizationProvider } from '@mui/x-date-pickers';
7
+
8
+ import { userAtom } from '@centreon/ui-context';
9
+ import { useDateTimePickerAdapter } from '@centreon/ui';
10
+
11
+ import DateTimePickerInput from '../../DateTimePickerInput';
12
+ import {
13
+ CustomTimePeriodProperty,
14
+ DateTimePickerInputModel
15
+ } from '../../models';
16
+ import { errorTimePeriodAtom } from '../../timePeriodsAtoms';
17
+
18
+ import ErrorText from './ErrorText';
19
+ import { PickersData, PickersStartEndDateDirection } from './models';
20
+ import { PickersStartEndDateModel } from './usePickersStartEndDate';
21
+
22
+ const useStyles = makeStyles()((theme) => ({
23
+ error: {
24
+ textAlign: 'center'
25
+ },
26
+ horizontalDirection: {
27
+ display: 'flex',
28
+ flexDirection: 'row',
29
+ gap: theme.spacing(1),
30
+ justifyItems: 'center',
31
+ padding: 0
32
+ },
33
+ horizontalError: {
34
+ textAlign: 'left'
35
+ },
36
+ row: {
37
+ display: 'flex',
38
+ flexDirection: 'row',
39
+ gap: theme.spacing(1)
40
+ },
41
+ verticalDirection: {
42
+ display: 'flex',
43
+ flexDirection: 'column',
44
+ gap: theme.spacing(1),
45
+ justifyItems: 'center',
46
+ padding: theme.spacing(1, 2)
47
+ }
48
+ }));
49
+
50
+ interface PropsPickersDateWithLabel extends DateTimePickerInputModel {
51
+ direction?: PickersStartEndDateDirection;
52
+ label: string;
53
+ }
54
+
55
+ const PickerDateWithLabel = ({
56
+ label,
57
+ changeDate,
58
+ maxDate,
59
+ minDate,
60
+ property,
61
+ disabled,
62
+ date,
63
+ direction = PickersStartEndDateDirection.column
64
+ }: PropsPickersDateWithLabel): JSX.Element => {
65
+ const { classes, cx } = useStyles();
66
+ const isRow = equals(direction, PickersStartEndDateDirection.row);
67
+
68
+ return (
69
+ <div aria-label={label} className={cx({ [classes.row]: isRow })}>
70
+ <Typography component={isRow ? 'div' : 'p'}>{label}</Typography>
71
+ <DateTimePickerInput
72
+ changeDate={changeDate}
73
+ date={date}
74
+ disabled={disabled}
75
+ maxDate={maxDate}
76
+ minDate={minDate}
77
+ property={property}
78
+ />
79
+ </div>
80
+ );
81
+ };
82
+
83
+ interface DisabledPicker {
84
+ isDisabledEndPicker?: boolean;
85
+ isDisabledStartPicker?: boolean;
86
+ }
87
+ type PickersDate = Pick<PickersData, 'rangeEndDate' | 'rangeStartDate'>;
88
+
89
+ interface Props extends PickersDate, PickersStartEndDateModel {
90
+ direction?: PickersStartEndDateDirection;
91
+ disabled?: DisabledPicker;
92
+ }
93
+
94
+ const PickersStartEndDate = ({
95
+ startDate,
96
+ endDate,
97
+ disabled,
98
+ changeDate,
99
+ rangeStartDate,
100
+ rangeEndDate,
101
+ direction = PickersStartEndDateDirection.column
102
+ }: Props): JSX.Element => {
103
+ const { classes, cx } = useStyles();
104
+ const { Adapter } = useDateTimePickerAdapter();
105
+
106
+ const { locale } = useAtomValue(userAtom);
107
+ const error = useAtomValue(errorTimePeriodAtom);
108
+
109
+ const maxStart = rangeStartDate?.max;
110
+ const minStart = rangeStartDate?.min;
111
+ const maxEnd = rangeEndDate?.max;
112
+ const minEnd = rangeEndDate?.min;
113
+
114
+ const styleContainer = equals(direction, PickersStartEndDateDirection.column)
115
+ ? classes.verticalDirection
116
+ : classes.horizontalDirection;
117
+
118
+ const isHorizontalDirection = equals(
119
+ direction,
120
+ PickersStartEndDateDirection.row
121
+ );
122
+
123
+ return (
124
+ <LocalizationProvider
125
+ adapterLocale={locale.substring(0, 2)}
126
+ dateAdapter={Adapter}
127
+ >
128
+ <div className={styleContainer}>
129
+ <PickerDateWithLabel
130
+ changeDate={changeDate}
131
+ date={startDate}
132
+ direction={direction}
133
+ disabled={disabled?.isDisabledStartPicker}
134
+ label="From"
135
+ maxDate={maxStart}
136
+ minDate={minStart}
137
+ property={CustomTimePeriodProperty.start}
138
+ />
139
+ <PickerDateWithLabel
140
+ changeDate={changeDate}
141
+ date={endDate}
142
+ direction={direction}
143
+ disabled={disabled?.isDisabledEndPicker}
144
+ label="To"
145
+ maxDate={maxEnd}
146
+ minDate={minEnd}
147
+ property={CustomTimePeriodProperty.end}
148
+ />
149
+ </div>
150
+
151
+ {error && (
152
+ <ErrorText
153
+ message="The end date must be greater than the start date"
154
+ style={cx(classes.error, {
155
+ [classes.horizontalError]: isHorizontalDirection
156
+ })}
157
+ />
158
+ )}
159
+ </LocalizationProvider>
160
+ );
161
+ };
162
+
163
+ export default PickersStartEndDate;
@@ -0,0 +1,76 @@
1
+ import { makeStyles } from 'tss-react/mui';
2
+
3
+ import { Popover } from '@mui/material';
4
+
5
+ import {
6
+ PickersData,
7
+ PopoverData,
8
+ defaultAnchorOrigin,
9
+ defaultTransformOrigin
10
+ } from './models';
11
+ import usePickersStartEndDate from './usePickersStartEndDate';
12
+ import PickersStartEndDate from './PickersStartEndDate';
13
+
14
+ const useStyles = makeStyles()((theme) => ({
15
+ paper: {
16
+ '& .MuiPopover-paper': {
17
+ minWidth: 250,
18
+ padding: theme.spacing(1)
19
+ }
20
+ }
21
+ }));
22
+
23
+ interface Props {
24
+ pickersData: PickersData;
25
+ popoverData: PopoverData;
26
+ }
27
+
28
+ const PopoverCustomTimePeriod = ({
29
+ popoverData,
30
+ pickersData
31
+ }: Props): JSX.Element => {
32
+ const { classes } = useStyles();
33
+
34
+ const { open, onClose } = popoverData;
35
+ const { acceptDate, customTimePeriod } = pickersData;
36
+
37
+ const { startDate, endDate, changeDate } = usePickersStartEndDate({
38
+ acceptDate,
39
+ customTimePeriod
40
+ });
41
+
42
+ const anchorEl = popoverData?.anchorEl;
43
+ const anchorPosition = popoverData?.anchorPosition;
44
+ const anchorOrigin = popoverData?.anchorOrigin;
45
+ const transformOrigin = popoverData?.transformOrigin;
46
+ const anchorReference = anchorPosition ? 'anchorPosition' : 'anchorEl';
47
+
48
+ const disabled = {
49
+ isDisabledEndPicker: pickersData?.isDisabledEndPicker,
50
+ isDisabledStartPicker: pickersData?.isDisabledStartPicker
51
+ };
52
+
53
+ return (
54
+ <Popover
55
+ anchorEl={anchorEl}
56
+ anchorOrigin={anchorOrigin ?? defaultAnchorOrigin}
57
+ anchorPosition={anchorPosition}
58
+ anchorReference={anchorReference}
59
+ className={classes.paper}
60
+ open={open}
61
+ transformOrigin={transformOrigin ?? defaultTransformOrigin}
62
+ onClose={onClose}
63
+ >
64
+ <PickersStartEndDate
65
+ changeDate={changeDate}
66
+ disabled={disabled}
67
+ endDate={endDate}
68
+ rangeEndDate={pickersData?.rangeEndDate}
69
+ rangeStartDate={pickersData?.rangeStartDate}
70
+ startDate={startDate}
71
+ />
72
+ </Popover>
73
+ );
74
+ };
75
+
76
+ export default PopoverCustomTimePeriod;
@@ -0,0 +1,61 @@
1
+ import { PopoverOrigin, PopoverPosition } from '@mui/material';
2
+
3
+ import { CustomTimePeriod, CustomTimePeriodProperty } from '../../models';
4
+
5
+ interface RangeDate {
6
+ max?: Date;
7
+ min?: Date;
8
+ }
9
+
10
+ export interface AcceptDateProps {
11
+ date: Date;
12
+ property: CustomTimePeriodProperty;
13
+ }
14
+
15
+ export interface PickersData {
16
+ acceptDate: (props: AcceptDateProps) => void;
17
+ customTimePeriod: CustomTimePeriod;
18
+ getError?: (value: boolean) => void;
19
+ isDisabledEndPicker?: boolean;
20
+ isDisabledStartPicker?: boolean;
21
+ onCloseEndPicker?: (isClosed: boolean) => void;
22
+ onCloseStartPicker?: (isClosed: boolean) => void;
23
+ rangeEndDate?: RangeDate;
24
+ rangeStartDate?: RangeDate;
25
+ }
26
+
27
+ export interface PopoverData {
28
+ anchorEl?: HTMLButtonElement;
29
+ anchorOrigin?: PopoverOrigin;
30
+ anchorPosition?: PopoverPosition;
31
+ onClose?: () => void;
32
+ open: boolean;
33
+ transformOrigin?: PopoverOrigin;
34
+ }
35
+
36
+ export enum OriginHorizontalEnum {
37
+ center = 'center',
38
+ left = 'left',
39
+ right = 'right'
40
+ }
41
+
42
+ export enum OriginVerticalEnum {
43
+ bottom = 'bottom',
44
+ center = 'center',
45
+ top = 'top'
46
+ }
47
+
48
+ export const defaultAnchorOrigin = {
49
+ horizontal: OriginHorizontalEnum.center,
50
+ vertical: OriginVerticalEnum.top
51
+ };
52
+
53
+ export const defaultTransformOrigin = {
54
+ horizontal: OriginHorizontalEnum.center,
55
+ vertical: OriginVerticalEnum.top
56
+ };
57
+
58
+ export enum PickersStartEndDateDirection {
59
+ column = 'column',
60
+ row = 'row'
61
+ }
@@ -0,0 +1,82 @@
1
+ import { useEffect, useState } from 'react';
2
+
3
+ import dayjs from 'dayjs';
4
+ import { useSetAtom } from 'jotai';
5
+ import { and, cond, equals, isNil } from 'ramda';
6
+
7
+ import { CustomTimePeriod, CustomTimePeriodProperty } from '../../models';
8
+ import { errorTimePeriodAtom } from '../../timePeriodsAtoms';
9
+
10
+ import { AcceptDateProps } from './models';
11
+
12
+ export interface PickersStartEndDateModel {
13
+ changeDate: (props: AcceptDateProps) => void;
14
+ endDate: Date | null;
15
+ startDate: Date | null;
16
+ }
17
+ interface Props {
18
+ acceptDate: (props: AcceptDateProps) => void;
19
+ customTimePeriod: CustomTimePeriod;
20
+ }
21
+
22
+ const usePickersStartEndDate = ({
23
+ customTimePeriod,
24
+ acceptDate
25
+ }: Props): PickersStartEndDateModel => {
26
+ const [start, setStart] = useState<Date | null>(
27
+ !isNil(customTimePeriod) ? customTimePeriod.start : null
28
+ );
29
+ const [end, setEnd] = useState<Date | null>(
30
+ !isNil(customTimePeriod) ? customTimePeriod.end : null
31
+ );
32
+
33
+ const setError = useSetAtom(errorTimePeriodAtom);
34
+
35
+ const isInvalidDate = ({ startDate, endDate }): boolean =>
36
+ dayjs(startDate).isSameOrAfter(dayjs(endDate), 'minute');
37
+
38
+ const changeDate = ({ property, date }): void => {
39
+ const currentDate = customTimePeriod[property];
40
+ cond([
41
+ [equals(CustomTimePeriodProperty?.start), (): void => setStart(date)],
42
+ [equals(CustomTimePeriodProperty?.end), (): void => setEnd(date)]
43
+ ])(property);
44
+
45
+ if (dayjs(date).isSame(dayjs(currentDate)) || !dayjs(date).isValid()) {
46
+ return;
47
+ }
48
+
49
+ acceptDate({
50
+ date,
51
+ property
52
+ });
53
+ };
54
+
55
+ useEffect(() => {
56
+ if (
57
+ and(
58
+ dayjs(customTimePeriod.start).isSame(dayjs(start), 'minute'),
59
+ dayjs(customTimePeriod.end).isSame(dayjs(end), 'minute')
60
+ )
61
+ ) {
62
+ return;
63
+ }
64
+ setStart(customTimePeriod.start);
65
+ setEnd(customTimePeriod.end);
66
+ }, [customTimePeriod.start, customTimePeriod.end]);
67
+
68
+ useEffect(() => {
69
+ if (!end || !start) {
70
+ return;
71
+ }
72
+ setError(isInvalidDate({ endDate: end, startDate: start }));
73
+ }, [end, start]);
74
+
75
+ return {
76
+ changeDate,
77
+ endDate: end,
78
+ startDate: start
79
+ };
80
+ };
81
+
82
+ export default usePickersStartEndDate;
@@ -0,0 +1,66 @@
1
+ import { MouseEvent, useState } from 'react';
2
+
3
+ import { useAtomValue, useSetAtom } from 'jotai';
4
+
5
+ import { useDebounce } from '@centreon/ui';
6
+
7
+ import {
8
+ changeCustomTimePeriodDerivedAtom,
9
+ customTimePeriodAtom
10
+ } from '../timePeriodsAtoms';
11
+
12
+ import CompactCustomTimePeriod from './CompactCustomTimePeriod';
13
+ import PopoverCustomTimePeriod from './PopoverCustomTimePeriod';
14
+
15
+ interface Props {
16
+ disabled?: boolean;
17
+ }
18
+
19
+ const CustomTimePeriod = ({ disabled = false }: Props): JSX.Element => {
20
+ const [anchorEl, setAnchorEl] = useState<HTMLButtonElement>();
21
+
22
+ const customTimePeriod = useAtomValue(customTimePeriodAtom);
23
+ const changeCustomTimePeriod = useSetAtom(changeCustomTimePeriodDerivedAtom);
24
+
25
+ const debouncedChangeDate = useDebounce({
26
+ functionToDebounce: ({ property, date }): void =>
27
+ changeCustomTimePeriod({ date, property }),
28
+ wait: 500
29
+ });
30
+
31
+ const onClickCompactCustomTimePeriod = (
32
+ event: MouseEvent<HTMLButtonElement>
33
+ ): void => {
34
+ setAnchorEl(event.currentTarget);
35
+ };
36
+
37
+ const closePopover = (): void => {
38
+ setAnchorEl(undefined);
39
+ };
40
+
41
+ return (
42
+ <>
43
+ <CompactCustomTimePeriod
44
+ disabled={disabled}
45
+ onClick={onClickCompactCustomTimePeriod}
46
+ />
47
+ <PopoverCustomTimePeriod
48
+ pickersData={{
49
+ acceptDate: debouncedChangeDate,
50
+ customTimePeriod,
51
+ isDisabledEndPicker: disabled,
52
+ isDisabledStartPicker: disabled,
53
+ rangeEndDate: { min: customTimePeriod.start },
54
+ rangeStartDate: { max: customTimePeriod.end }
55
+ }}
56
+ popoverData={{
57
+ anchorEl,
58
+ onClose: closePopover,
59
+ open: Boolean(anchorEl)
60
+ }}
61
+ />
62
+ </>
63
+ );
64
+ };
65
+
66
+ export default CustomTimePeriod;
@@ -0,0 +1,49 @@
1
+ import dayjs from 'dayjs';
2
+
3
+ import { DateTimePicker } from '@mui/x-date-pickers';
4
+
5
+ import { useDateTimePickerAdapter } from '@centreon/ui';
6
+
7
+ import { CustomTimePeriodProperty } from './models';
8
+
9
+ interface Props {
10
+ changeDate: (props) => void;
11
+ date: Date | null;
12
+ desktopMediaQuery?: string;
13
+ disabled?: boolean;
14
+ maxDate?: Date;
15
+ minDate?: Date;
16
+ property: CustomTimePeriodProperty;
17
+ }
18
+
19
+ const DateTimePickerInput = ({
20
+ date,
21
+ maxDate,
22
+ minDate,
23
+ property,
24
+ changeDate,
25
+ disabled = false,
26
+ desktopMediaQuery
27
+ }: Props): JSX.Element => {
28
+ const { desktopPickerMediaQuery } = useDateTimePickerAdapter();
29
+
30
+ const changeTime = (newValue: dayjs.Dayjs | null): void => {
31
+ changeDate({ date: dayjs(newValue).toDate(), property });
32
+ };
33
+
34
+ return (
35
+ <DateTimePicker<dayjs.Dayjs>
36
+ dayOfWeekFormatter={(day: string): string =>
37
+ day.substring(0, 2).toUpperCase()
38
+ }
39
+ desktopModeMediaQuery={desktopMediaQuery ?? desktopPickerMediaQuery}
40
+ disabled={disabled}
41
+ maxDate={maxDate && dayjs(maxDate)}
42
+ minDate={minDate && dayjs(minDate)}
43
+ value={dayjs(date)}
44
+ onChange={changeTime}
45
+ />
46
+ );
47
+ };
48
+
49
+ export default DateTimePickerInput;
@@ -0,0 +1,65 @@
1
+ import dayjs from 'dayjs';
2
+ import 'dayjs/locale/fr';
3
+ import localizedFormatPlugin from 'dayjs/plugin/localizedFormat';
4
+ import timezonePlugin from 'dayjs/plugin/timezone';
5
+ import utcPlugin from 'dayjs/plugin/utc';
6
+ import { Provider, createStore } from 'jotai';
7
+
8
+ import { Switch } from '@mui/material';
9
+
10
+ import { userAtom } from '@centreon/ui-context';
11
+
12
+ import { retrievedUser } from './mockedData';
13
+
14
+ import TimePeriod from '.';
15
+
16
+ dayjs.extend(timezonePlugin);
17
+ dayjs.extend(utcPlugin);
18
+ dayjs.extend(localizedFormatPlugin);
19
+
20
+ const data = [
21
+ {
22
+ locale: 'fr_FR',
23
+ resolution: { height: 720, width: 500 },
24
+ timezone: 'Europe/Paris'
25
+ },
26
+ {
27
+ locale: 'fr_FR',
28
+ resolution: { height: 720, width: 200 },
29
+ timezone: 'Europe/Paris'
30
+ },
31
+ {
32
+ locale: 'fr_FR',
33
+ resolution: { height: 720, width: 1024 },
34
+ timezone: 'Europe/Paris'
35
+ }
36
+ ];
37
+
38
+ data.forEach((item) =>
39
+ describe('Time period', () => {
40
+ const { height, width } = item.resolution;
41
+ beforeEach(() => {
42
+ cy.viewport(width, height);
43
+
44
+ const store = createStore();
45
+
46
+ store.set(userAtom, {
47
+ ...retrievedUser,
48
+ locale: 'fr_FR',
49
+ timezone: 'Europe/Paris'
50
+ });
51
+
52
+ cy.mount({
53
+ Component: (
54
+ <Provider store={store}>
55
+ <TimePeriod renderExternalComponent={<Switch />} />
56
+ </Provider>
57
+ )
58
+ });
59
+ });
60
+
61
+ it(`displays correctly the dates design when screen resolution is ${width}px`, () => {
62
+ cy.matchImageSnapshot(`${width}px`);
63
+ });
64
+ })
65
+ );