@centreon/ui 24.4.39 → 24.4.40

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 (95) hide show
  1. package/package.json +14 -19
  2. package/public/mockServiceWorker.js +1 -1
  3. package/src/Button/Icon/index.tsx +1 -1
  4. package/src/Button/Save/StartIcon.tsx +3 -3
  5. package/src/Button/Save/index.tsx +5 -9
  6. package/src/Checkbox/Checkbox.tsx +2 -2
  7. package/src/Checkbox/CheckboxGroup/index.tsx +2 -2
  8. package/src/Dashboard/Item.tsx +1 -1
  9. package/src/Dashboard/Layout.tsx +2 -2
  10. package/src/Dialog/index.tsx +1 -1
  11. package/src/FallbackPage/FallbackPage.tsx +3 -3
  12. package/src/FileDropZone/index.tsx +1 -3
  13. package/src/Form/Inputs/CheckboxGroup.tsx +4 -1
  14. package/src/Form/Inputs/index.tsx +1 -3
  15. package/src/Form/Inputs/models.ts +1 -9
  16. package/src/Graph/LineChart/BasicComponents/Lines/Threshold/Circle.tsx +2 -2
  17. package/src/Graph/LineChart/BasicComponents/Lines/Threshold/index.tsx +4 -5
  18. package/src/Graph/LineChart/BasicComponents/Thresholds.tsx +2 -2
  19. package/src/Graph/LineChart/BasicComponents/useFilterLines.ts +1 -1
  20. package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/GuidingLines.tsx +2 -2
  21. package/src/Graph/LineChart/InteractiveComponents/Annotations/Annotation/index.tsx +3 -2
  22. package/src/Graph/LineChart/InteractiveComponents/Annotations/EventAnnotations.tsx +1 -1
  23. package/src/Graph/LineChart/Legend/useLegend.ts +3 -3
  24. package/src/Graph/LineChart/helpers/doc.ts +13 -16
  25. package/src/Graph/LineChart/helpers/index.ts +1 -1
  26. package/src/Graph/LineChart/index.stories.tsx +2 -4
  27. package/src/Graph/SingleBar/Thresholds.tsx +2 -2
  28. package/src/Graph/Text/Text.stories.tsx +4 -60
  29. package/src/Graph/common/timeSeries/index.ts +3 -3
  30. package/src/InputField/Select/Autocomplete/Connected/index.tsx +7 -10
  31. package/src/InputField/Select/Autocomplete/Draggable/SortableList.tsx +1 -1
  32. package/src/InputField/Select/Autocomplete/Draggable/SortableListContent.tsx +1 -1
  33. package/src/InputField/Select/Autocomplete/Draggable/index.tsx +1 -1
  34. package/src/InputField/Select/Autocomplete/index.tsx +115 -121
  35. package/src/InputField/Select/IconPopover/index.tsx +2 -2
  36. package/src/InputField/Select/index.tsx +1 -1
  37. package/src/InputField/Text/index.tsx +2 -2
  38. package/src/Listing/Cell/DataCell.tsx +1 -15
  39. package/src/Listing/Header/ListingHeader.tsx +1 -1
  40. package/src/Listing/Listing.styles.ts +3 -2
  41. package/src/Listing/index.stories.tsx +1 -12
  42. package/src/Listing/index.tsx +2 -1
  43. package/src/Module/index.tsx +4 -2
  44. package/src/RichTextEditor/RichTextEditor.tsx +1 -12
  45. package/src/SortableItems/index.tsx +7 -2
  46. package/src/ThemeProvider/index.tsx +0 -24
  47. package/src/TimePeriods/CustomTimePeriod/CompactCustomTimePeriod.styles.ts +7 -6
  48. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +3 -8
  49. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/models.ts +2 -0
  50. package/src/TimePeriods/DateTimePickerInput.tsx +19 -56
  51. package/src/TimePeriods/ResolutionTimePeriod.cypress.spec.tsx +9 -12
  52. package/src/TimePeriods/TimePeriods.cypress.spec.tsx +33 -9
  53. package/src/TimePeriods/helpers/index.ts +1 -1
  54. package/src/TimePeriods/index.stories.tsx +4 -12
  55. package/src/TimePeriods/index.tsx +2 -2
  56. package/src/api/QueryProvider.tsx +1 -1
  57. package/src/api/TestQueryProvider.tsx +1 -1
  58. package/src/api/useFetchQuery/index.ts +23 -27
  59. package/src/api/useMutationQuery/index.ts +21 -45
  60. package/src/components/Button/Icon/IconButton.tsx +2 -6
  61. package/src/components/DataTable/DataTable.stories.tsx +0 -40
  62. package/src/components/DataTable/DataTable.styles.ts +0 -3
  63. package/src/components/DataTable/DataTable.tsx +3 -3
  64. package/src/components/DataTable/Item/DataTableItem.styles.ts +2 -7
  65. package/src/components/DataTable/Item/DataTableItem.tsx +4 -4
  66. package/src/components/DataTable/index.ts +1 -3
  67. package/src/components/Form/Dashboard/DashboardForm.tsx +12 -15
  68. package/src/components/Layout/PageLayout/PageLayout.tsx +1 -1
  69. package/src/components/Layout/PageLayout/PageLayoutActions.tsx +0 -1
  70. package/src/components/Layout/PageLayout/PageLayoutBody.tsx +0 -1
  71. package/src/components/Layout/PageLayout/PageLayoutHeader.tsx +1 -5
  72. package/src/components/Layout/PageLayout/index.ts +1 -3
  73. package/src/components/Modal/Modal.styles.ts +1 -1
  74. package/src/components/Tooltip/ConfirmationTooltip/ConfirmationTooltip.stories.tsx +3 -3
  75. package/src/components/Tooltip/ConfirmationTooltip/ConfirmationTooltip.tsx +1 -1
  76. package/src/components/Tooltip/ConfirmationTooltip/models.ts +1 -1
  77. package/src/index.ts +2 -2
  78. package/src/queryParameters/url/index.ts +1 -5
  79. package/src/screens/dashboard/DashboardsDetail.stories.tsx +108 -0
  80. package/src/screens/dashboard/DashboardsOverview.stories.tsx +281 -0
  81. package/src/utils/index.ts +1 -2
  82. package/src/utils/useDateTimePickerAdapter.ts +309 -0
  83. package/src/utils/{useLicenseExpirationWarning.test.tsx → useLicenseExpirationWarning.cypress.spec.tsx} +37 -48
  84. package/src/utils/useLicenseExpirationWarning.ts +18 -18
  85. package/src/Form/Form.cypress.spec.tsx +0 -133
  86. package/src/Form/Inputs/List/Content.tsx +0 -62
  87. package/src/Form/Inputs/List/List.styles.ts +0 -29
  88. package/src/Form/Inputs/List/List.tsx +0 -58
  89. package/src/Form/Inputs/List/useList.ts +0 -81
  90. package/src/Module/Module.cypress.spec.tsx +0 -129
  91. package/src/components/DataTable/DataListing.tsx +0 -6
  92. package/src/components/DataTable/DataTable.cypress.spec.tsx +0 -193
  93. package/src/components/Layout/PageLayout/PageQuickAccess.tsx +0 -76
  94. package/src/components/Layout/PageLayout.cypress.spec.tsx +0 -66
  95. package/src/utils/usePluralizedTranslation.ts +0 -21
@@ -3,6 +3,7 @@ export * from './getNormalizedId';
3
3
  export * from './statuses';
4
4
  export * from './typedMemo';
5
5
  export * from './useCopyToClipboard';
6
+ export * from './useDateTimePickerAdapter';
6
7
  export * from './useDebounce';
7
8
  export * from './useDeepCallback';
8
9
  export * from './useDeepMemo';
@@ -19,5 +20,3 @@ export * from './useInfiniteScrollListing';
19
20
  export * from './useLicenseExpirationWarning';
20
21
  export * from './useRefreshInterval';
21
22
  export * from './centreonBaseURL';
22
- export * from './usePluralizedTranslation';
23
- export * from './useResizeObserver';
@@ -0,0 +1,309 @@
1
+ /* eslint-disable class-methods-use-this */
2
+ import { useCallback } from 'react';
3
+
4
+ import dayjs from 'dayjs';
5
+ import { useAtomValue } from 'jotai';
6
+ import { equals, isNil, not } from 'ramda';
7
+
8
+ import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
9
+
10
+ import { useLocaleDateTimeFormat } from '@centreon/ui';
11
+ import { userAtom } from '@centreon/ui-context';
12
+
13
+ interface GetDestinationAndConfiguredTimezoneOffsetProps {
14
+ endTimezone?: string;
15
+ startTimezone?: string;
16
+ }
17
+
18
+ interface UseDateTimePickerAdapterProps {
19
+ Adapter;
20
+ desktopPickerMediaQuery: string;
21
+ }
22
+
23
+ enum DSTState {
24
+ SUMMER,
25
+ WINTER,
26
+ NODST
27
+ }
28
+
29
+ interface ToTimezonedDateProps {
30
+ date: Date;
31
+ timeZone?: string;
32
+ }
33
+
34
+ interface GetDSTStateProps {
35
+ date: dayjs.Dayjs;
36
+ timezoneToUse?: string;
37
+ }
38
+
39
+ export const useDateTimePickerAdapter = (): UseDateTimePickerAdapterProps => {
40
+ const { timezone, locale } = useAtomValue(userAtom);
41
+ const { format } = useLocaleDateTimeFormat();
42
+
43
+ const desktopPickerMediaQuery =
44
+ '@media (pointer: fine) or (min-width: 1024px)';
45
+
46
+ const toTimezonedDate = ({
47
+ date,
48
+ timeZone = undefined
49
+ }: ToTimezonedDateProps): Date => {
50
+ if (isNil(timeZone)) {
51
+ return new Date(date.toLocaleString('en-US'));
52
+ }
53
+
54
+ return new Date(date.toLocaleString('en-US', { timeZone }));
55
+ };
56
+
57
+ const getDestinationAndConfiguredTimezoneOffset = ({
58
+ startTimezone = undefined,
59
+ endTimezone = timezone
60
+ }: GetDestinationAndConfiguredTimezoneOffsetProps): number => {
61
+ const now = new Date();
62
+ const currentTimezoneDate = toTimezonedDate({
63
+ date: now,
64
+ timeZone: startTimezone
65
+ });
66
+ const destinationTimezoneDate = toTimezonedDate({
67
+ date: now,
68
+ timeZone: endTimezone
69
+ });
70
+
71
+ return Math.floor(
72
+ (currentTimezoneDate.getTime() - destinationTimezoneDate.getTime()) /
73
+ 60 /
74
+ 60 /
75
+ 1000
76
+ );
77
+ };
78
+
79
+ const getDSTState = useCallback(
80
+ ({ date, timezoneToUse }: GetDSTStateProps): DSTState => {
81
+ const hasNoTimezone = isNil(timezoneToUse);
82
+ const currentYear = toTimezonedDate({
83
+ date: new Date(),
84
+ timeZone: timezoneToUse
85
+ }).getFullYear();
86
+
87
+ const january = hasNoTimezone
88
+ ? dayjs(new Date(currentYear, 0, 1)).utcOffset()
89
+ : dayjs(new Date(currentYear, 0, 1)).tz(timezoneToUse).utcOffset();
90
+ const july = hasNoTimezone
91
+ ? dayjs(new Date(currentYear, 6, 1)).utcOffset()
92
+ : dayjs(new Date(currentYear, 6, 1)).tz(timezoneToUse).utcOffset();
93
+
94
+ if (equals(january, july)) {
95
+ return DSTState.NODST;
96
+ }
97
+
98
+ return july === date.tz().utcOffset() ? DSTState.SUMMER : DSTState.WINTER;
99
+ },
100
+ [timezone]
101
+ );
102
+
103
+ const getDSTStateForCurrentTimezone = useCallback(
104
+ (date: dayjs.Dayjs): DSTState => {
105
+ return getDSTState({ date });
106
+ },
107
+ []
108
+ );
109
+
110
+ interface Chunk {
111
+ array: Array<unknown>;
112
+ size: number;
113
+ }
114
+ class Adapter extends AdapterDayjs {
115
+ public formatByString = (value, formatKey: string): string => {
116
+ return format({
117
+ date: value.tz(timezone).toDate(),
118
+ formatString: formatKey
119
+ });
120
+ };
121
+
122
+ public format = (date: dayjs.Dayjs, formatKey: string): string => {
123
+ return this.formatByString(
124
+ date.tz(timezone, true),
125
+ this.formats[formatKey]
126
+ );
127
+ };
128
+
129
+ public startOfWeek = (date: dayjs.Dayjs): dayjs.Dayjs => {
130
+ if (date.tz(timezone).isUTC()) {
131
+ return date.tz(timezone).startOf('week').utc();
132
+ }
133
+
134
+ return date.tz(timezone).startOf('week');
135
+ };
136
+
137
+ public setMinutes = (date: dayjs.Dayjs, count: number): dayjs.Dayjs => {
138
+ return date.minute(count);
139
+ };
140
+
141
+ public setHours = (date: dayjs.Dayjs, count: number): dayjs.Dayjs => {
142
+ return date.hour(count);
143
+ };
144
+
145
+ public isSameDay = (date: dayjs.Dayjs, comparing: dayjs.Dayjs): boolean => {
146
+ const isSameYearAndMonth = this.isSameYear(date, comparing)
147
+ ? this.isSameMonth(date, comparing)
148
+ : false;
149
+
150
+ return (
151
+ isSameYearAndMonth &&
152
+ date.tz(timezone).isSame(comparing.tz(timezone), 'day')
153
+ );
154
+ };
155
+
156
+ public startOfDay = (date: dayjs.Dayjs): dayjs.Dayjs => {
157
+ return date.tz(timezone).startOf('day') as dayjs.Dayjs;
158
+ };
159
+
160
+ public endOfDay = (date: dayjs.Dayjs): dayjs.Dayjs => {
161
+ return date.tz(timezone).endOf('day') as dayjs.Dayjs;
162
+ };
163
+
164
+ public startOfMonth = (date: dayjs.Dayjs): dayjs.Dayjs => {
165
+ if (date.tz(timezone).isUTC()) {
166
+ return date.tz(timezone).utc();
167
+ }
168
+
169
+ return date.tz(timezone);
170
+ };
171
+
172
+ public endOfMonth = (date: dayjs.Dayjs): dayjs.Dayjs => {
173
+ return date.tz(timezone).endOf('month') as dayjs.Dayjs;
174
+ };
175
+
176
+ public isSameMonth = (
177
+ date: dayjs.Dayjs,
178
+ comparing: dayjs.Dayjs
179
+ ): boolean => {
180
+ return date.tz(timezone).isSame(comparing.tz(timezone), 'month');
181
+ };
182
+
183
+ public getMonth = (date: dayjs.Dayjs): number => {
184
+ return date.tz(timezone).month();
185
+ };
186
+
187
+ public isAfter = (date: dayjs.Dayjs, value: dayjs.Dayjs): boolean => {
188
+ return date.isAfter(value.endOf('month'));
189
+ };
190
+
191
+ public isBefore = (date: dayjs.Dayjs, value: dayjs.Dayjs): boolean => {
192
+ return date.isBefore(value.startOf('month'));
193
+ };
194
+
195
+ public getDaysInMonth = (date: dayjs.Dayjs): number => {
196
+ return date.tz(timezone).daysInMonth();
197
+ };
198
+
199
+ public getWeekdays = (): Array<string> => {
200
+ const start = dayjs().locale(locale).tz(timezone).startOf('week');
201
+
202
+ return [0, 1, 2, 3, 4, 5, 6].map((diff) =>
203
+ this.formatByString(start.add(diff, 'day'), 'dd')
204
+ );
205
+ };
206
+
207
+ public getChunkFromArray = ({ array, size }: Chunk): Array<unknown> => {
208
+ if (!array.length) {
209
+ return [];
210
+ }
211
+ const head = array.slice(0, size);
212
+ const tail = array.slice(size);
213
+
214
+ return [head, ...this.getChunkFromArray({ array: tail, size })];
215
+ };
216
+
217
+ public getWeekArray = (date: dayjs.Dayjs): Array<Array<dayjs.Dayjs>> => {
218
+ const isMorning = equals(dayjs().tz(timezone).format('a'), 'am');
219
+ const startOfWeek = date.tz(timezone).startOf('month').startOf('week');
220
+ const endOfWeek = date.tz(timezone).endOf('month').endOf('week');
221
+ const start = startOfWeek.startOf('day');
222
+ const end = endOfWeek.endOf('day');
223
+ const customStart = isMorning
224
+ ? startOfWeek.startOf('day')
225
+ : startOfWeek.startOf('day');
226
+ const customEnd = isMorning
227
+ ? endOfWeek.startOf('day')
228
+ : endOfWeek.startOf('day');
229
+ const currentStart = start.isUTC()
230
+ ? start.tz(timezone, true)
231
+ : customStart;
232
+ const currentEnd = end.isUTC() ? end.tz(timezone, true) : customEnd;
233
+ const numberOfDaysInCurrentMonth = currentEnd.diff(
234
+ currentStart,
235
+ 'd',
236
+ true
237
+ );
238
+ const daysOfMonthWithTimezone = [
239
+ ...Array(Math.round(numberOfDaysInCurrentMonth)).keys()
240
+ ].reduce(
241
+ (acc, _, currentIndex) => {
242
+ if (acc[currentIndex].isUTC()) {
243
+ const newCurrent = acc[currentIndex]
244
+ .utc()
245
+ .add(1, 'day')
246
+ .tz(timezone, true);
247
+
248
+ return [...acc, newCurrent];
249
+ }
250
+ const newCurrent = acc[currentIndex].add(1, 'day');
251
+
252
+ return [...acc, newCurrent];
253
+ },
254
+ [currentStart]
255
+ );
256
+ const weeksArray = this.getChunkFromArray({
257
+ array: daysOfMonthWithTimezone,
258
+ size: 7
259
+ });
260
+
261
+ return weeksArray as Array<Array<dayjs.Dayjs>>;
262
+ };
263
+
264
+ public mergeDateAndTime = (
265
+ date: dayjs.Dayjs,
266
+ time: dayjs.Dayjs
267
+ ): dayjs.Dayjs => {
268
+ const dateWithTimezone = date.tz(timezone).startOf('day');
269
+ const timeWithTimezone = time.tz(timezone);
270
+ const dateDSTState = getDSTState({
271
+ date: dateWithTimezone,
272
+ timezoneToUse: timezone
273
+ });
274
+ const dateDSTStateWithCurrentTimezone =
275
+ getDSTStateForCurrentTimezone(date);
276
+
277
+ if (equals(dateDSTStateWithCurrentTimezone, DSTState.WINTER)) {
278
+ return dateWithTimezone
279
+ .add(
280
+ timeWithTimezone.hour() -
281
+ getDestinationAndConfiguredTimezoneOffset({
282
+ endTimezone: 'UTC',
283
+ startTimezone: dayjs.tz.guess()
284
+ }),
285
+ 'hour'
286
+ )
287
+ .add(timeWithTimezone.minute(), 'minute')
288
+ .add(timeWithTimezone.second(), 'second');
289
+ }
290
+
291
+ if (not(equals(dateDSTState, DSTState.SUMMER))) {
292
+ return dateWithTimezone
293
+ .add(timeWithTimezone.hour(), 'hour')
294
+ .add(timeWithTimezone.minute(), 'minute')
295
+ .add(timeWithTimezone.second(), 'second');
296
+ }
297
+
298
+ return dateWithTimezone
299
+ .hour(timeWithTimezone.hour())
300
+ .minute(timeWithTimezone.minute())
301
+ .second(timeWithTimezone.second());
302
+ };
303
+ }
304
+
305
+ return {
306
+ Adapter,
307
+ desktopPickerMediaQuery
308
+ };
309
+ };
@@ -1,13 +1,6 @@
1
1
  import dayjs from 'dayjs';
2
- import { renderHook } from '@testing-library/react';
3
2
 
4
- import {
5
- getFetchCall,
6
- mockResponse,
7
- resetMocks,
8
- waitFor
9
- } from '../../test/testRenderer';
10
- import TestQueryProvider from '../api/TestQueryProvider';
3
+ import { TestQueryProvider, Method, SnackbarProvider } from '@centreon/ui';
11
4
 
12
5
  import { labelLicenseWarning } from './translatedLabel';
13
6
 
@@ -86,63 +79,59 @@ const getMockedResponse = (expirationDate): object => ({
86
79
  });
87
80
 
88
81
  const mockRequest = ({ expirationDate }: { expirationDate }): void => {
89
- resetMocks();
90
- mockResponse({
91
- data: getMockedResponse(expirationDate)
82
+ cy.interceptAPIRequest({
83
+ alias: 'getLicenseInformations',
84
+ method: Method.GET,
85
+ path: '**internal.php?object=centreon_module&action=list',
86
+ response: getMockedResponse(expirationDate)
92
87
  });
93
88
  };
94
89
 
95
- const showMessage = jest.fn();
90
+ const TestComponent = (): JSX.Element => {
91
+ useLicenseExpirationWarning({
92
+ module: 'centreon-autodiscovery-server'
93
+ });
96
94
 
97
- jest.mock('../Snackbar/useSnackbar', () => ({
98
- __esModule: true,
99
- default: jest
100
- .fn()
101
- .mockImplementation(() => ({ showWarningMessage: showMessage }))
102
- }));
95
+ return <div />;
96
+ };
103
97
 
104
- const initialize = (): void => {
105
- renderHook(
106
- () =>
107
- useLicenseExpirationWarning({
108
- module: 'centreon-autodiscovery-server'
109
- }),
110
- {
111
- wrapper: TestQueryProvider
112
- }
98
+ const TestWithQueryProvider = (): JSX.Element => {
99
+ return (
100
+ <TestQueryProvider>
101
+ <SnackbarProvider>
102
+ <TestComponent />
103
+ </SnackbarProvider>
104
+ </TestQueryProvider>
113
105
  );
114
106
  };
115
107
 
108
+ const initialize = (): void => {
109
+ cy.viewport('macbook-13');
110
+
111
+ cy.mount({
112
+ Component: <TestWithQueryProvider />
113
+ });
114
+ };
115
+
116
116
  const currentDate = dayjs();
117
117
 
118
118
  describe('License', () => {
119
+ beforeEach(initialize);
120
+
119
121
  it('does not display any warning message when the license expires in more than 15 days from the current date', () => {
120
122
  mockRequest({ expirationDate: currentDate.add(20, 'day') });
121
- initialize();
122
123
 
123
- waitFor(() => {
124
- expect(getFetchCall(0)).toEqual(
125
- 'internal.php?object=centreon_module&action=list'
126
- );
127
- });
124
+ cy.waitForRequest('@getLicenseInformations');
128
125
 
129
- expect(showMessage).not.toHaveBeenCalled();
126
+ cy.findByText(
127
+ labelLicenseWarning('centreon-autodiscovery-server', 20)
128
+ ).should('not.exist');
130
129
  });
131
-
132
130
  it('displays a warning message when the license expires within 15 days', () => {
133
131
  mockRequest({ expirationDate: currentDate.add(10.5, 'day') });
134
- initialize();
135
-
136
- waitFor(() => {
137
- expect(getFetchCall(0)).toEqual(
138
- 'internal.php?object=centreon_module&action=list'
139
- );
140
- });
141
-
142
- waitFor(() => {
143
- expect(showMessage).toHaveBeenCalledWith(
144
- labelLicenseWarning('centreon-autodiscovery-server', 10)
145
- );
146
- });
132
+
133
+ cy.findByText(labelLicenseWarning('centreon-autodiscovery-server', 10));
134
+
135
+ cy.makeSnapshot();
147
136
  });
148
137
  });
@@ -19,7 +19,7 @@ export const useLicenseExpirationWarning = ({ module }: Props): void => {
19
19
  const { t } = useTranslation();
20
20
  const { showWarningMessage } = useSnackbar();
21
21
 
22
- const { data } = useFetchQuery({
22
+ const { fetchQuery } = useFetchQuery({
23
23
  getEndpoint: () => extensionsEndpoint,
24
24
  getQueryKey: () => [module]
25
25
  });
@@ -28,25 +28,25 @@ export const useLicenseExpirationWarning = ({ module }: Props): void => {
28
28
 
29
29
  const getExpirationDate = pipe(
30
30
  path(['result', 'module', 'entities']),
31
- find(propEq(module, 'id')),
31
+ find(propEq('id', module)),
32
32
  path(['license', 'expiration_date'])
33
33
  ) as (data) => string;
34
34
 
35
35
  useEffect(() => {
36
- if (isNil(data)) {
37
- return;
38
- }
39
-
40
- const expirationDate = getExpirationDate(data);
41
-
42
- if (isNil(expirationDate)) {
43
- return;
44
- }
45
-
46
- const daysUntilExpiration = dayjs(expirationDate).diff(currentDate, 'day');
47
-
48
- if (lt(daysUntilExpiration, 15)) {
49
- showWarningMessage(t(labelLicenseWarning(module, daysUntilExpiration)));
50
- }
51
- }, [data]);
36
+ fetchQuery().then((response) => {
37
+ const expirationDate = getExpirationDate(response);
38
+ if (isNil(expirationDate)) {
39
+ return;
40
+ }
41
+
42
+ const daysUntilExpiration = dayjs(expirationDate).diff(
43
+ currentDate,
44
+ 'day'
45
+ );
46
+
47
+ if (lt(daysUntilExpiration, 15)) {
48
+ showWarningMessage(t(labelLicenseWarning(module, daysUntilExpiration)));
49
+ }
50
+ });
51
+ }, []);
52
52
  };
@@ -1,133 +0,0 @@
1
- import { object } from 'yup';
2
- import { faker } from '@faker-js/faker';
3
- import { useFormikContext } from 'formik';
4
-
5
- import { Typography } from '@mui/material';
6
-
7
- import { Button } from '../components';
8
-
9
- import { Form } from './Form';
10
- import { InputType } from './Inputs/models';
11
-
12
- faker.seed(42);
13
-
14
- const AddItem = ({ addItem }: { addItem: (item) => void }): JSX.Element => {
15
- const { values } = useFormikContext();
16
- const add = (): void => {
17
- addItem({
18
- alias: faker.company.name(),
19
- id: values.list.length,
20
- name: faker.person.firstName()
21
- });
22
- };
23
-
24
- return (
25
- <Button variant="ghost" onClick={add}>
26
- Add item
27
- </Button>
28
- );
29
- };
30
-
31
- const SortContent = ({
32
- name,
33
- alias
34
- }: {
35
- alias: string;
36
- name: string;
37
- }): JSX.Element => (
38
- <Typography>
39
- {name} ({alias})
40
- </Typography>
41
- );
42
-
43
- const initializeFormList = (): void => {
44
- cy.mount({
45
- Component: (
46
- <Form
47
- initialValues={{
48
- list: []
49
- }}
50
- inputs={[
51
- {
52
- fieldName: 'list',
53
- group: '',
54
- label: '',
55
- list: {
56
- AddItem,
57
- SortContent,
58
- addItemLabel: 'Add an item to the list',
59
- itemProps: ['id', 'name', 'alias'],
60
- sortLabel: 'Sort items'
61
- },
62
- type: InputType.List
63
- }
64
- ]}
65
- submit={cy.stub()}
66
- validationSchema={object()}
67
- />
68
- )
69
- });
70
- };
71
-
72
- describe('Form list', () => {
73
- beforeEach(initializeFormList);
74
-
75
- it('adds an element to the list', () => {
76
- cy.contains('Add an item to the list').should('be.visible');
77
- cy.contains('Sort items').should('be.visible');
78
-
79
- cy.contains('Add item').click();
80
-
81
- cy.findByLabelText('sort-0').should('be.visible');
82
- cy.findByLabelText('delete-0').should('be.visible');
83
- cy.contains('Christelle (Schinner - Wiegand)').should('be.visible');
84
-
85
- cy.makeSnapshot();
86
- });
87
-
88
- it('sorts elements in the list', () => {
89
- cy.contains('Add an item to the list').should('be.visible');
90
- cy.contains('Sort items').should('be.visible');
91
-
92
- cy.contains('Add item').click();
93
- cy.contains('Add item').click();
94
-
95
- cy.findByLabelText('sort-0').should('be.visible');
96
- cy.findByLabelText('delete-0').should('be.visible');
97
- cy.contains('Carley (Satterfield, Miller and Metz)').should('be.visible');
98
- cy.findByLabelText('sort-1').should('be.visible');
99
- cy.findByLabelText('delete-1').should('be.visible');
100
- cy.contains('Anderson (Crist - Bradtke)').should('be.visible');
101
-
102
- cy.moveSortableElementUsingAriaLabel({
103
- ariaLabel: 'sort-0',
104
- direction: 'down'
105
- });
106
-
107
- cy.contains('Carley (Satterfield, Miller and Metz)').should('be.visible');
108
- cy.contains('Anderson (Crist - Bradtke)').should('be.visible');
109
-
110
- cy.makeSnapshot();
111
- });
112
-
113
- it('removes an element from the list', () => {
114
- cy.contains('Add an item to the list').should('be.visible');
115
- cy.contains('Sort items').should('be.visible');
116
-
117
- cy.contains('Add item').click();
118
- cy.contains('Add item').click();
119
-
120
- cy.findByLabelText('sort-0').should('be.visible');
121
- cy.findByLabelText('delete-0').should('be.visible');
122
- cy.contains('Lea (Streich - Hartmann)').should('be.visible');
123
- cy.findByLabelText('sort-1').should('be.visible');
124
- cy.findByLabelText('delete-1').should('be.visible');
125
- cy.contains('Akeem (Quigley LLC)').should('be.visible');
126
-
127
- cy.findByLabelText('delete-0').click();
128
-
129
- cy.contains('Lea (Streich - Hartmann)').should('not.exist');
130
-
131
- cy.makeSnapshot();
132
- });
133
- });
@@ -1,62 +0,0 @@
1
- import { ReactNode } from 'react';
2
-
3
- import { DraggableSyntheticListeners } from '@dnd-kit/core';
4
-
5
- import KrilinIndicatorIcon from '@mui/icons-material/DragIndicator';
6
- import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
7
-
8
- import { IconButton } from '../../../components';
9
-
10
- import { useListStyles } from './List.styles';
11
-
12
- export interface ContentProps {
13
- attributes;
14
- children: ReactNode;
15
- deleteItem: (id: string) => () => void;
16
- id: string;
17
- isDragging: boolean;
18
- isInDragOverlay?: boolean;
19
- itemRef: React.RefObject<HTMLDivElement>;
20
- listeners: DraggableSyntheticListeners;
21
- name: string;
22
- style;
23
- }
24
-
25
- const Content = ({
26
- listeners,
27
- itemRef,
28
- attributes,
29
- style,
30
- isDragging,
31
- id,
32
- children,
33
- deleteItem
34
- }: ContentProps): JSX.Element => {
35
- const { classes } = useListStyles();
36
-
37
- return (
38
- <div
39
- className={classes.content}
40
- ref={itemRef}
41
- {...attributes}
42
- style={style}
43
- >
44
- <IconButton
45
- data-dragging={isDragging}
46
- size="small"
47
- {...listeners}
48
- aria-label={`sort-${id}`}
49
- icon={<KrilinIndicatorIcon fontSize="small" />}
50
- />
51
- <div className={classes.innerContent}>{children}</div>
52
- <IconButton
53
- aria-label={`delete-${id}`}
54
- icon={<DeleteOutlineIcon color="error" fontSize="small" />}
55
- size="small"
56
- onClick={deleteItem(id)}
57
- />
58
- </div>
59
- );
60
- };
61
-
62
- export default Content;