@centreon/ui 24.4.59 → 24.4.61

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 (163) hide show
  1. package/package.json +50 -42
  2. package/public/mockServiceWorker.js +1 -1
  3. package/src/ActionsList/ActionsList.styles.ts +40 -71
  4. package/src/Button/Icon/index.tsx +1 -1
  5. package/src/Button/Save/StartIcon.tsx +3 -3
  6. package/src/Button/Save/index.tsx +9 -5
  7. package/src/Checkbox/Checkbox.tsx +2 -2
  8. package/src/Checkbox/CheckboxGroup/index.tsx +2 -2
  9. package/src/Dashboard/Item.tsx +1 -1
  10. package/src/Dashboard/Layout.tsx +2 -2
  11. package/src/Dialog/Confirm/index.tsx +10 -2
  12. package/src/Dialog/UnsavedChanges/index.tsx +21 -20
  13. package/src/Dialog/UnsavedChanges/translatedLabels.ts +4 -6
  14. package/src/Dialog/index.tsx +9 -2
  15. package/src/FallbackPage/FallbackPage.tsx +3 -3
  16. package/src/FileDropZone/index.tsx +3 -1
  17. package/src/Form/Form.cypress.spec.tsx +133 -0
  18. package/src/Form/Inputs/List/Content.tsx +62 -0
  19. package/src/Form/Inputs/List/List.styles.ts +29 -0
  20. package/src/Form/Inputs/List/List.tsx +58 -0
  21. package/src/Form/Inputs/List/useList.ts +81 -0
  22. package/src/Form/Inputs/Text.tsx +3 -1
  23. package/src/Form/Inputs/index.tsx +3 -1
  24. package/src/Form/Inputs/models.ts +10 -1
  25. package/src/Graph/BarStack/BarStack.cypress.spec.tsx +154 -0
  26. package/src/Graph/BarStack/BarStack.stories.tsx +123 -0
  27. package/src/Graph/BarStack/BarStack.styles.ts +37 -0
  28. package/src/Graph/BarStack/BarStack.tsx +14 -0
  29. package/src/Graph/BarStack/ResponsiveBarStack.tsx +222 -0
  30. package/src/Graph/BarStack/index.ts +1 -0
  31. package/src/Graph/BarStack/models.ts +20 -0
  32. package/src/Graph/BarStack/useResponsiveBarStack.ts +137 -0
  33. package/src/Graph/Gauge/Gauge.cypress.spec.tsx +102 -0
  34. package/src/Graph/Gauge/Gauge.tsx +1 -1
  35. package/src/Graph/HeatMap/HeatMap.cypress.spec.tsx +145 -0
  36. package/src/Graph/HeatMap/HeatMap.stories.tsx +0 -25
  37. package/src/Graph/HeatMap/ResponsiveHeatMap.tsx +8 -2
  38. package/src/Graph/Legend/Legend.tsx +21 -0
  39. package/src/Graph/Legend/index.ts +1 -0
  40. package/src/Graph/Legend/models.ts +11 -0
  41. package/src/Graph/LineChart/BasicComponents/Lines/Threshold/Circle.tsx +2 -2
  42. package/src/Graph/LineChart/BasicComponents/Thresholds.tsx +2 -2
  43. package/src/Graph/LineChart/BasicComponents/useFilterLines.ts +1 -1
  44. package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/GuidingLines.tsx +2 -2
  45. package/src/Graph/LineChart/InteractiveComponents/Annotations/EventAnnotations.tsx +1 -1
  46. package/src/Graph/LineChart/Legend/Legend.styles.ts +1 -1
  47. package/src/Graph/LineChart/Legend/LegendHeader.tsx +1 -1
  48. package/src/Graph/LineChart/Legend/useInteractiveValues.ts +2 -2
  49. package/src/Graph/LineChart/Legend/useLegend.ts +3 -3
  50. package/src/Graph/LineChart/helpers/doc.ts +16 -13
  51. package/src/Graph/LineChart/helpers/index.ts +1 -1
  52. package/src/Graph/LineChart/index.stories.tsx +4 -2
  53. package/src/Graph/LineChart/index.tsx +1 -1
  54. package/src/Graph/PieChart/PieChart.cypress.spec.tsx +169 -0
  55. package/src/Graph/PieChart/PieChart.stories.tsx +194 -0
  56. package/src/Graph/PieChart/PieChart.styles.ts +39 -0
  57. package/src/Graph/PieChart/PieChart.tsx +14 -0
  58. package/src/Graph/PieChart/ResponsivePie.tsx +254 -0
  59. package/src/Graph/PieChart/index.ts +1 -0
  60. package/src/Graph/PieChart/models.ts +20 -0
  61. package/src/Graph/PieChart/useResponsivePie.ts +85 -0
  62. package/src/Graph/SingleBar/SingleBar.cypress.spec.tsx +121 -0
  63. package/src/Graph/SingleBar/Thresholds.tsx +2 -2
  64. package/src/Graph/Text/Text.cypress.spec.tsx +101 -0
  65. package/src/Graph/Text/Text.stories.tsx +60 -4
  66. package/src/Graph/Text/Text.tsx +1 -1
  67. package/src/Graph/common/testUtils.ts +71 -0
  68. package/src/Graph/common/timeSeries/index.ts +22 -14
  69. package/src/Graph/common/utils.ts +19 -0
  70. package/src/Graph/index.ts +3 -0
  71. package/src/Graph/translatedLabels.ts +1 -0
  72. package/src/InputField/Select/Autocomplete/Connected/index.tsx +10 -7
  73. package/src/InputField/Select/Autocomplete/Draggable/SortableList.tsx +1 -1
  74. package/src/InputField/Select/Autocomplete/Draggable/SortableListContent.tsx +1 -1
  75. package/src/InputField/Select/Autocomplete/Draggable/index.tsx +1 -1
  76. package/src/InputField/Select/Autocomplete/Multi/index.tsx +4 -2
  77. package/src/InputField/Select/Autocomplete/index.tsx +129 -116
  78. package/src/InputField/Select/IconPopover/index.tsx +2 -2
  79. package/src/InputField/Select/index.tsx +15 -2
  80. package/src/InputField/Text/index.tsx +2 -2
  81. package/src/Listing/ActionBar/index.tsx +9 -8
  82. package/src/Listing/Cell/DataCell.styles.ts +3 -0
  83. package/src/Listing/Cell/DataCell.tsx +23 -5
  84. package/src/Listing/Header/ListingHeader.tsx +1 -1
  85. package/src/Listing/Listing.cypress.spec.tsx +218 -33
  86. package/src/Listing/Listing.styles.ts +4 -7
  87. package/src/Listing/Row/Row.tsx +7 -3
  88. package/src/Listing/index.stories.tsx +37 -3
  89. package/src/Listing/index.test.tsx +1 -1
  90. package/src/Listing/index.tsx +80 -36
  91. package/src/Listing/models.ts +1 -0
  92. package/src/Listing/useStyleTable.ts +1 -0
  93. package/src/Module/Module.cypress.spec.tsx +129 -0
  94. package/src/Module/index.tsx +2 -4
  95. package/src/PopoverMenu/index.tsx +6 -5
  96. package/src/RichTextEditor/RichTextEditor.tsx +12 -1
  97. package/src/SortableItems/index.tsx +2 -7
  98. package/src/ThemeProvider/index.tsx +24 -0
  99. package/src/TimePeriods/CustomTimePeriod/CompactCustomTimePeriod.styles.ts +6 -7
  100. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +8 -3
  101. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/models.ts +0 -2
  102. package/src/TimePeriods/DateTimePickerInput.tsx +56 -19
  103. package/src/TimePeriods/ResolutionTimePeriod.cypress.spec.tsx +12 -9
  104. package/src/TimePeriods/TimePeriods.cypress.spec.tsx +9 -33
  105. package/src/TimePeriods/helpers/index.ts +1 -1
  106. package/src/TimePeriods/index.stories.tsx +12 -4
  107. package/src/TimePeriods/index.tsx +2 -2
  108. package/src/Typography/FluidTypography/FluidTypography.cypress.spec.tsx +27 -0
  109. package/src/Typography/FluidTypography/index.stories.tsx +2 -2
  110. package/src/Typography/FluidTypography/index.tsx +21 -28
  111. package/src/api/QueryProvider.tsx +1 -1
  112. package/src/api/TestQueryProvider.tsx +1 -1
  113. package/src/api/index.ts +3 -3
  114. package/src/api/useFetchQuery/index.ts +27 -23
  115. package/src/api/useMutationQuery/index.test.ts +4 -4
  116. package/src/api/useMutationQuery/index.ts +60 -25
  117. package/src/components/Button/Icon/IconButton.tsx +6 -2
  118. package/src/components/DataTable/DataListing.tsx +6 -0
  119. package/src/components/DataTable/DataTable.cypress.spec.tsx +174 -0
  120. package/src/components/DataTable/DataTable.stories.tsx +40 -0
  121. package/src/components/DataTable/DataTable.styles.ts +3 -0
  122. package/src/components/DataTable/DataTable.tsx +3 -3
  123. package/src/components/DataTable/Item/DataTableItem.styles.ts +7 -2
  124. package/src/components/DataTable/Item/DataTableItem.tsx +4 -60
  125. package/src/components/DataTable/index.ts +3 -1
  126. package/src/components/Form/AccessRights/AccessRights.cypress.spec.tsx +13 -13
  127. package/src/components/Form/AccessRights/ShareInput/ContactSwitch.tsx +3 -3
  128. package/src/components/Form/AccessRights/ShareInput/ShareInput.tsx +1 -0
  129. package/src/components/Form/AccessRights/storiesData.ts +22 -22
  130. package/src/components/Form/Dashboard/DashboardDuplicationForm.tsx +85 -0
  131. package/src/components/Form/Dashboard/DashboardForm.tsx +15 -12
  132. package/src/components/Form/Dashboard/index.ts +1 -0
  133. package/src/components/Form/FormActions.tsx +7 -2
  134. package/src/components/ItemComposition/ItemComposition.styles.ts +2 -2
  135. package/src/components/Layout/PageLayout/PageLayout.tsx +1 -1
  136. package/src/components/Layout/PageLayout/PageLayoutActions.tsx +1 -0
  137. package/src/components/Layout/PageLayout/PageLayoutBody.tsx +1 -0
  138. package/src/components/Layout/PageLayout/PageLayoutHeader.tsx +5 -1
  139. package/src/components/Layout/PageLayout/PageQuickAccess.tsx +76 -0
  140. package/src/components/Layout/PageLayout/index.ts +3 -1
  141. package/src/components/Layout/PageLayout.cypress.spec.tsx +66 -0
  142. package/src/components/List/Item/ListItem.tsx +3 -3
  143. package/src/components/Modal/ConfirmationModal/ConfirmationModal.cypress.spec.tsx +168 -0
  144. package/src/components/Modal/ConfirmationModal/ConfirmationModal.stories.tsx +62 -0
  145. package/src/components/Modal/ConfirmationModal/ConfirmationModal.tsx +87 -0
  146. package/src/components/Modal/Modal.styles.ts +8 -3
  147. package/src/components/Modal/index.ts +2 -0
  148. package/src/components/Tooltip/ConfirmationTooltip/ConfirmationTooltip.stories.tsx +3 -3
  149. package/src/components/Tooltip/ConfirmationTooltip/ConfirmationTooltip.tsx +1 -1
  150. package/src/components/Tooltip/ConfirmationTooltip/models.ts +1 -1
  151. package/src/index.ts +2 -2
  152. package/src/queryParameters/url/index.ts +5 -1
  153. package/src/utils/index.ts +1 -1
  154. package/src/utils/useFullscreen/Fullscreen.cypress.spec.tsx +1 -3
  155. package/src/utils/useFullscreen/useFullscreenListener.ts +10 -7
  156. package/src/utils/useInfiniteScrollListing.ts +4 -1
  157. package/src/utils/{useLicenseExpirationWarning.cypress.spec.tsx → useLicenseExpirationWarning.test.tsx} +48 -37
  158. package/src/utils/useLicenseExpirationWarning.ts +18 -18
  159. package/src/utils/usePluralizedTranslation.ts +21 -0
  160. package/src/Typography/FluidTypography/useFluidResizeObserver.ts +0 -56
  161. package/src/screens/dashboard/DashboardsDetail.stories.tsx +0 -108
  162. package/src/screens/dashboard/DashboardsOverview.stories.tsx +0 -281
  163. package/src/utils/useDateTimePickerAdapter.ts +0 -309
@@ -18,7 +18,6 @@ import {
18
18
  map,
19
19
  not,
20
20
  pick,
21
- pluck,
22
21
  prop,
23
22
  propEq,
24
23
  reduce,
@@ -58,6 +57,8 @@ import { SkeletonLoader } from './Row/SkeletonLoaderRows';
58
57
  import { ListingHeader } from './Header';
59
58
  import { subItemsPivotsAtom } from './tableAtoms';
60
59
 
60
+ const subItemPrefixKey = 'listing';
61
+
61
62
  const getVisibleColumns = ({
62
63
  columnConfiguration,
63
64
  columns
@@ -69,7 +70,7 @@ const getVisibleColumns = ({
69
70
  }
70
71
 
71
72
  return selectedColumnIds.map((id) =>
72
- columns.find(propEq('id', id))
73
+ columns.find(propEq(id, 'id'))
73
74
  ) as Array<Column>;
74
75
  };
75
76
 
@@ -102,6 +103,7 @@ export interface Props<TRow> {
102
103
  getId?: (row: TRow) => RowId;
103
104
  headerMemoProps?: Array<unknown>;
104
105
  innerScrollDisabled?: boolean;
106
+ isResponsive?: boolean;
105
107
  limit?: number;
106
108
  listingVariant?: ListingVariant;
107
109
  loading?: boolean;
@@ -139,7 +141,7 @@ const defaultColumnConfiguration = {
139
141
 
140
142
  export const performanceRowsLimit = 60;
141
143
 
142
- const Listing = <TRow extends { id: RowId }>({
144
+ const Listing = <TRow extends { id: RowId; internalListingParentId?: RowId }>({
143
145
  customListingComponent,
144
146
  displayCustomListing,
145
147
  limit = 10,
@@ -147,6 +149,7 @@ const Listing = <TRow extends { id: RowId }>({
147
149
  columns,
148
150
  columnConfiguration = defaultColumnConfiguration,
149
151
  customPaginationClassName,
152
+ isResponsive = false,
150
153
  onResetColumns,
151
154
  onSelectColumns,
152
155
  rows = [],
@@ -209,6 +212,21 @@ const Listing = <TRow extends { id: RowId }>({
209
212
 
210
213
  const subItemsPivots = useAtomValue(subItemsPivotsAtom);
211
214
 
215
+ const allSubItemIds = React.useMemo(
216
+ () =>
217
+ reduce<TRow | number, Array<string | number>>(
218
+ (acc, row) => [
219
+ ...acc,
220
+ ...(row[subItems?.getRowProperty() || ''] || []).map(
221
+ ({ id }) => `${subItemPrefixKey}_${getId(row)}_${id}`
222
+ )
223
+ ],
224
+ [],
225
+ rows
226
+ ),
227
+ [rows, subItems]
228
+ );
229
+
212
230
  const rowsToDisplay = React.useMemo(
213
231
  () =>
214
232
  subItems?.enable
@@ -218,7 +236,14 @@ const Listing = <TRow extends { id: RowId }>({
218
236
  row[subItems.getRowProperty()] &&
219
237
  subItemsPivots.includes(row.id)
220
238
  ) {
221
- return [...acc, row, ...row[subItems.getRowProperty()]];
239
+ return [
240
+ ...acc,
241
+ row,
242
+ ...row[subItems.getRowProperty()].map((subRow) => ({
243
+ ...subRow,
244
+ internalListingParentId: row.id
245
+ }))
246
+ ];
222
247
  }
223
248
 
224
249
  return [...acc, row];
@@ -230,11 +255,28 @@ const Listing = <TRow extends { id: RowId }>({
230
255
  [rows, subItemsPivots, subItems]
231
256
  );
232
257
 
258
+ const getSubItemRowId = React.useCallback((row: TRow) => {
259
+ return `${subItemPrefixKey}_${row.internalListingParentId}_${row.id}`;
260
+ }, []);
261
+
262
+ const getIsSubItem = React.useCallback(
263
+ (row: TRow) => {
264
+ return allSubItemIds.includes(getSubItemRowId(row));
265
+ },
266
+ [allSubItemIds]
267
+ );
268
+
269
+ const getRowId = React.useCallback(
270
+ (row: TRow) => {
271
+ return getIsSubItem(row) ? getSubItemRowId(row) : getId(row);
272
+ },
273
+ [allSubItemIds]
274
+ );
275
+
233
276
  const { classes } = useListingStyles({
234
277
  dataStyle,
235
278
  getGridTemplateColumn,
236
- limit,
237
- listingVariant,
279
+ isResponsive,
238
280
  rows: rowsToDisplay
239
281
  });
240
282
 
@@ -254,7 +296,7 @@ const Listing = <TRow extends { id: RowId }>({
254
296
  event.target.checked &&
255
297
  event.target.getAttribute('data-indeterminate') === 'false'
256
298
  ) {
257
- onSelectRows(reject(disableRowCheckCondition, rows));
299
+ onSelectRows(reject(disableRowCheckCondition, rowsToDisplay));
258
300
  setLastSelectionIndex(null);
259
301
 
260
302
  return;
@@ -326,7 +368,11 @@ const Listing = <TRow extends { id: RowId }>({
326
368
  const selectRowsWithShiftKey = (selectedRowIndex: number): void => {
327
369
  const lastSelectedIndex = lastSelectionIndex as number;
328
370
  if (isNil(shiftKeyDownRowPivot)) {
329
- const selectedRowsFromTheStart = slice(0, selectedRowIndex + 1, rows);
371
+ const selectedRowsFromTheStart = slice(
372
+ 0,
373
+ selectedRowIndex + 1,
374
+ rowsToDisplay
375
+ );
330
376
 
331
377
  onSelectRows(reject(disableRowCheckCondition, selectedRowsFromTheStart));
332
378
 
@@ -335,7 +381,10 @@ const Listing = <TRow extends { id: RowId }>({
335
381
 
336
382
  const selectedRowsIndex = map(
337
383
  (row) =>
338
- findIndex((listingRow) => equals(getId(row), getId(listingRow)), rows),
384
+ findIndex(
385
+ (listingRow) => equals(getId(row), getId(listingRow)),
386
+ rowsToDisplay
387
+ ),
339
388
  selectedRows
340
389
  ).sort(subtract);
341
390
 
@@ -343,7 +392,7 @@ const Listing = <TRow extends { id: RowId }>({
343
392
  const newSelection = slice(
344
393
  selectedRowIndex,
345
394
  (lastSelectionIndex as number) + 1,
346
- rows
395
+ rowsToDisplay
347
396
  );
348
397
  onSelectRows(
349
398
  reject(
@@ -362,7 +411,11 @@ const Listing = <TRow extends { id: RowId }>({
362
411
  return;
363
412
  }
364
413
 
365
- const newSelection = slice(lastSelectedIndex, selectedRowIndex + 1, rows);
414
+ const newSelection = slice(
415
+ lastSelectedIndex,
416
+ selectedRowIndex + 1,
417
+ rowsToDisplay
418
+ );
366
419
  onSelectRows(
367
420
  reject(
368
421
  disableRowCheckCondition,
@@ -386,7 +439,7 @@ const Listing = <TRow extends { id: RowId }>({
386
439
 
387
440
  const selectedRowIndex = findIndex(
388
441
  (listingRow) => equals(getId(row), getId(listingRow)),
389
- rows
442
+ rowsToDisplay
390
443
  );
391
444
 
392
445
  if (isShiftKeyDown) {
@@ -413,10 +466,10 @@ const Listing = <TRow extends { id: RowId }>({
413
466
  };
414
467
 
415
468
  const hoverRow = (row): void => {
416
- if (equals(hoveredRowId, getId(row))) {
469
+ if (equals(hoveredRowId, getRowId(row))) {
417
470
  return;
418
471
  }
419
- setHoveredRowId(getId(row));
472
+ setHoveredRowId(getRowId(row));
420
473
  };
421
474
 
422
475
  const clearHoveredRow = (): void => {
@@ -427,8 +480,6 @@ const Listing = <TRow extends { id: RowId }>({
427
480
  return selectedRowsInclude(row);
428
481
  };
429
482
 
430
- const emptyRows = limit - Math.min(limit, totalRows - currentPage * limit);
431
-
432
483
  const changeLimit = (updatedLimit: string): void => {
433
484
  onLimitChange?.(Number(updatedLimit));
434
485
  };
@@ -449,19 +500,6 @@ const Listing = <TRow extends { id: RowId }>({
449
500
 
450
501
  const areColumnsEditable = not(isNil(onSelectColumns));
451
502
 
452
- const allSubItemIds = React.useMemo(
453
- () =>
454
- reduce<TRow | number, Array<string | number>>(
455
- (acc, row) => [
456
- ...acc,
457
- ...pluck('id', row[subItems?.getRowProperty() || ''] || [])
458
- ],
459
- [],
460
- rows
461
- ),
462
- [rows, subItems]
463
- );
464
-
465
503
  return (
466
504
  <div className={classes.listingContainer}>
467
505
  {loading && rows.length > 0 && (
@@ -533,7 +571,7 @@ const Listing = <TRow extends { id: RowId }>({
533
571
  listingVariant={listingVariant}
534
572
  memoProps={headerMemoProps}
535
573
  predefinedRowsSelection={predefinedRowsSelection}
536
- rowCount={limit - emptyRows}
574
+ rowCount={rowsToDisplay.length}
537
575
  selectedRowCount={selectedRows.length}
538
576
  sortField={sortField}
539
577
  sortOrder={sortOrder}
@@ -550,8 +588,10 @@ const Listing = <TRow extends { id: RowId }>({
550
588
  >
551
589
  {rowsToDisplay.map((row, index) => {
552
590
  const isRowSelected = isSelected(row);
553
- const isRowHovered = equals(hoveredRowId, getId(row));
554
- const isSubItem = allSubItemIds.includes(row.id);
591
+ const isSubItem = allSubItemIds.includes(
592
+ getSubItemRowId(row)
593
+ );
594
+ const isRowHovered = equals(hoveredRowId, getRowId(row));
555
595
 
556
596
  return (
557
597
  <ListingRow
@@ -568,7 +608,7 @@ const Listing = <TRow extends { id: RowId }>({
568
608
  key={
569
609
  gte(limit, performanceRowsLimit)
570
610
  ? `row_${index}`
571
- : getId(row)
611
+ : getRowId(row)
572
612
  }
573
613
  lastSelectionIndex={lastSelectionIndex}
574
614
  limit={limit}
@@ -579,9 +619,13 @@ const Listing = <TRow extends { id: RowId }>({
579
619
  subItemsPivots={subItemsPivots}
580
620
  tabIndex={-1}
581
621
  visibleColumns={visibleColumns}
582
- onClick={(): void => {
583
- onRowClick(row);
584
- }}
622
+ onClick={
623
+ isSubItem
624
+ ? undefined
625
+ : (): void => {
626
+ onRowClick(row);
627
+ }
628
+ }
585
629
  onFocus={(): void => hoverRow(row)}
586
630
  onMouseOver={(): void => hoverRow(row)}
587
631
  >
@@ -15,6 +15,7 @@ export interface ComponentColumnProps {
15
15
 
16
16
  export interface Column {
17
17
  Component?: (props: ComponentColumnProps) => JSX.Element | null;
18
+ align?: 'start' | 'end' | 'center';
18
19
  clickable?: boolean;
19
20
  compact?: boolean;
20
21
  disablePadding?: boolean;
@@ -53,6 +53,7 @@ const useStyleTable = ({
53
53
  const checkbox = checkable ? 'fit-content(1rem) ' : ''; // SelectAction (checkbox) cell adjusts to content
54
54
 
55
55
  const columnTemplate = currentVisibleColumns
56
+ ?.filter((column) => column)
56
57
  ?.map(({ width, shortLabel }) => {
57
58
  if (!isNil(shortLabel)) {
58
59
  return 'min-content';
@@ -0,0 +1,129 @@
1
+ import { createStore } from 'jotai';
2
+
3
+ import { Method } from '..';
4
+
5
+ import LicensedModule from './LicensedModule';
6
+
7
+ import Module from '.';
8
+
9
+ const initializeModule = (): void => {
10
+ cy.mount({
11
+ Component: (
12
+ <Module seedName="seed" store={createStore()}>
13
+ <p>Module</p>
14
+ </Module>
15
+ )
16
+ });
17
+ };
18
+
19
+ const initializeModuleWithValidLicense = (
20
+ isFederatedComponent = false
21
+ ): void => {
22
+ cy.interceptAPIRequest({
23
+ alias: 'getValidLicense',
24
+ method: Method.GET,
25
+ path: './api/internal.php?object=centreon_license_manager&action=licenseValid&productName=valid',
26
+ response: {
27
+ success: true
28
+ }
29
+ });
30
+
31
+ cy.mount({
32
+ Component: (
33
+ <div style={{ height: '100vh' }}>
34
+ <LicensedModule
35
+ isFederatedComponent={isFederatedComponent}
36
+ moduleName="valid"
37
+ seedName="seed"
38
+ store={createStore()}
39
+ >
40
+ <p>Module</p>
41
+ </LicensedModule>
42
+ </div>
43
+ )
44
+ });
45
+ };
46
+
47
+ const initializeModuleWithInvalidLicense = (
48
+ isFederatedComponent = false
49
+ ): void => {
50
+ cy.interceptAPIRequest({
51
+ alias: 'getInvalidLicense',
52
+ method: Method.GET,
53
+ path: './api/internal.php?object=centreon_license_manager&action=licenseValid&productName=invalid',
54
+ response: {
55
+ success: false
56
+ }
57
+ });
58
+
59
+ cy.mount({
60
+ Component: (
61
+ <div style={{ height: '100vh' }}>
62
+ <LicensedModule
63
+ isFederatedComponent={isFederatedComponent}
64
+ moduleName="invalid"
65
+ seedName="seed"
66
+ store={createStore()}
67
+ >
68
+ <p>Module</p>
69
+ </LicensedModule>
70
+ </div>
71
+ )
72
+ });
73
+ };
74
+
75
+ describe('Module', () => {
76
+ beforeEach(() => {
77
+ initializeModule();
78
+ });
79
+
80
+ it('displays the content of the module', () => {
81
+ cy.contains('Module').should('be.visible');
82
+
83
+ cy.makeSnapshot();
84
+ });
85
+ });
86
+
87
+ describe('Valid license module', () => {
88
+ it('displays the content of the page when the license is valid license', () => {
89
+ initializeModuleWithValidLicense();
90
+ cy.waitForRequest('@getValidLicense');
91
+
92
+ cy.contains('Module').should('be.visible');
93
+
94
+ cy.makeSnapshot();
95
+ });
96
+
97
+ it('displays the content of the component when the license is valid license', () => {
98
+ initializeModuleWithValidLicense(true);
99
+
100
+ cy.contains('Module').should('be.visible');
101
+
102
+ cy.makeSnapshot();
103
+ });
104
+ });
105
+
106
+ describe('Invalid license module', () => {
107
+ it('displays the content of the page when the license is invalid license', () => {
108
+ initializeModuleWithInvalidLicense();
109
+ cy.waitForRequest('@getInvalidLicense');
110
+
111
+ cy.contains('Module').should('not.exist');
112
+
113
+ cy.contains('Oops').should('be.visible');
114
+ cy.contains('License invalid or expired').should('be.visible');
115
+ cy.contains('Please contact your administrator.').should('be.visible');
116
+ cy.get('img[alt="License invalid or expired !"]').should('be.visible');
117
+ cy.get('img[alt="Centreon Logo"]').should('be.visible');
118
+
119
+ cy.makeSnapshot();
120
+ });
121
+
122
+ it('displays the content of the module when the license is invalid license', () => {
123
+ initializeModuleWithInvalidLicense(true);
124
+
125
+ cy.contains('Module').should('not.exist');
126
+
127
+ cy.makeSnapshot();
128
+ });
129
+ });
@@ -1,5 +1,3 @@
1
- import * as React from 'react';
2
-
3
1
  import { Provider as JotaiProvider, createStore } from 'jotai';
4
2
 
5
3
  import { createGenerateClassName, StylesProvider } from '@mui/styles';
@@ -9,7 +7,7 @@ import SnackbarProvider from '../Snackbar/SnackbarProvider';
9
7
 
10
8
  export interface ModuleProps {
11
9
  children: React.ReactElement;
12
- maxSnackbars: number;
10
+ maxSnackbars?: number;
13
11
  seedName: string;
14
12
  store: ReturnType<typeof createStore>;
15
13
  }
@@ -17,7 +15,7 @@ export interface ModuleProps {
17
15
  const Module = ({
18
16
  children,
19
17
  seedName,
20
- maxSnackbars,
18
+ maxSnackbars = 3,
21
19
  store
22
20
  }: ModuleProps): JSX.Element => {
23
21
  const generateClassName = createGenerateClassName({
@@ -6,14 +6,16 @@ import {
6
6
  ClickAwayListener,
7
7
  Paper,
8
8
  Popper,
9
- PopperPlacementType,
10
- useTheme
9
+ PopperPlacementType
11
10
  } from '@mui/material';
12
11
  import { PopperProps } from '@mui/material/Popper';
13
12
 
14
13
  import { IconButton } from '..';
15
14
 
16
- const useStyles = makeStyles()(() => ({
15
+ const useStyles = makeStyles()((theme) => ({
16
+ popover: {
17
+ zIndex: theme.zIndex.tooltip
18
+ },
17
19
  popoverIconButton: {
18
20
  padding: 0,
19
21
  width: '100%'
@@ -52,7 +54,6 @@ const PopoverMenu = ({
52
54
  getPopoverData,
53
55
  popperProps
54
56
  }: Props): JSX.Element => {
55
- const theme = useTheme();
56
57
  const { classes, cx } = useStyles();
57
58
  const [anchorEl, setAnchorEl] = useState<HTMLElement | undefined>();
58
59
  const isOpen = Boolean(anchorEl);
@@ -105,9 +106,9 @@ const PopoverMenu = ({
105
106
  <Popper
106
107
  open
107
108
  anchorEl={anchorEl}
109
+ className={classes.popover}
108
110
  nonce={undefined}
109
111
  placement={popperPlacement}
110
- style={{ zIndex: theme.zIndex.tooltip }}
111
112
  onResize={(): undefined => undefined}
112
113
  onResizeCapture={(): undefined => undefined}
113
114
  {...popperProps}
@@ -12,6 +12,7 @@ import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
12
12
  import { equals } from 'ramda';
13
13
  import { ListPlugin } from '@lexical/react/LexicalListPlugin';
14
14
  import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';
15
+ import { $generateHtmlFromNodes } from '@lexical/html';
15
16
 
16
17
  import { Typography } from '@mui/material';
17
18
 
@@ -38,6 +39,7 @@ export interface RichTextEditorProps {
38
39
  openLinkInNewTab?: boolean;
39
40
  placeholder?: string;
40
41
  resetEditorToInitialStateCondition?: () => boolean;
42
+ setHtmlString?: (htmlString: string) => void;
41
43
  toolbarClassName?: string;
42
44
  toolbarPositions?: 'start' | 'end';
43
45
  }
@@ -143,6 +145,7 @@ const RichTextEditor = ({
143
145
  openLinkInNewTab = true,
144
146
  initialize,
145
147
  displayBlockButtons = true,
148
+ setHtmlString,
146
149
  toolbarClassName
147
150
  }: RichTextEditorProps): JSX.Element => {
148
151
  const { classes } = useStyles({ toolbarPositions });
@@ -178,6 +181,13 @@ const RichTextEditor = ({
178
181
  }
179
182
  };
180
183
 
184
+ const change = (state: EditorState, editor: LexicalEditor): void => {
185
+ editor.update(() => {
186
+ setHtmlString?.($generateHtmlFromNodes(editor, null));
187
+ });
188
+ getEditorState?.(state, editor);
189
+ };
190
+
181
191
  return (
182
192
  <LexicalComposer initialConfig={initialConfig}>
183
193
  <div className={classes.container}>
@@ -210,6 +220,7 @@ const RichTextEditor = ({
210
220
  resetEditorToInitialStateCondition={
211
221
  resetEditorToInitialStateCondition
212
222
  }
223
+ setHtmlString={setHtmlString}
213
224
  onBlur={onBlur}
214
225
  />
215
226
  }
@@ -218,7 +229,7 @@ const RichTextEditor = ({
218
229
  <HistoryPlugin />
219
230
  <LinkPlugin />
220
231
  <ListPlugin />
221
- <OnChangePlugin onChange={getEditorState} />
232
+ <OnChangePlugin onChange={change} />
222
233
  <AutoCompleteLinkPlugin openLinkInNewTab={openLinkInNewTab} />
223
234
  <FloatingLinkEditorPlugin
224
235
  editable={editable}
@@ -15,11 +15,7 @@ import {
15
15
  DragEndEvent,
16
16
  Over
17
17
  } from '@dnd-kit/core';
18
- import {
19
- SortableContext,
20
- sortableKeyboardCoordinates,
21
- SortingStrategy
22
- } from '@dnd-kit/sortable';
18
+ import { SortableContext, SortingStrategy } from '@dnd-kit/sortable';
23
19
  import {
24
20
  equals,
25
21
  find,
@@ -117,7 +113,6 @@ const SortableItems = <T extends { [propertyToFilterItemsOn]: string }>({
117
113
  useSensor(MouseSensor),
118
114
  useSensor(PointerSensor),
119
115
  useSensor(KeyboardSensor, {
120
- coordinateGetter: sortableKeyboardCoordinates,
121
116
  keyboardCodes: {
122
117
  cancel: ['Escape'],
123
118
  end: ['Space', 'Enter'],
@@ -169,7 +164,7 @@ const SortableItems = <T extends { [propertyToFilterItemsOn]: string }>({
169
164
  };
170
165
 
171
166
  const getItemById = (id): T | undefined =>
172
- find(propEq(propertyToFilterItemsOn, id), items);
167
+ find(propEq(id, propertyToFilterItemsOn), items);
173
168
 
174
169
  const activeItem = getItemById(activeId) as Record<string, unknown>;
175
170
 
@@ -147,6 +147,30 @@ export const getTheme = (mode: ThemeMode): ThemeOptions => ({
147
147
  },
148
148
  MuiCssBaseline: {
149
149
  styleOverrides: (theme) => `
150
+ ::-webkit-scrollbar {
151
+ height: ${theme.spacing(1)};
152
+ width: ${theme.spacing(1)};
153
+ background-color: transparent;
154
+ }
155
+ ::-webkit-scrollbar-thumb {
156
+ background-color: ${
157
+ equals(mode, 'dark')
158
+ ? theme.palette.divider
159
+ : theme.palette.text.disabled
160
+ };
161
+ border-radius: ${theme.spacing(0.5)};
162
+ }
163
+ ::-webkit-scrollbar-thumb:hover {
164
+ background-color: ${theme.palette.primary.main};
165
+ }
166
+ * {
167
+ scrollbar-color: ${
168
+ equals(mode, 'dark')
169
+ ? theme.palette.divider
170
+ : theme.palette.text.disabled
171
+ } ${theme.palette.background.default};
172
+ scrollbar-width: thin;
173
+ }
150
174
  html {
151
175
  margin: 0;
152
176
  padding: 0;
@@ -12,22 +12,21 @@ const useStyles = makeStyles()((theme) => ({
12
12
  },
13
13
  containerDates: {
14
14
  display: 'flex',
15
- gap: theme.spacing(0.5),
16
15
  [theme.breakpoints.down('sm')]: {
17
- columnGap: theme.spacing(0.5),
18
- flexDirection: 'column'
16
+ flexDirection: 'column',
17
+ gap: theme.spacing(0.5)
19
18
  }
20
19
  },
21
20
  date: {
22
- minWidth: theme.spacing(12.5),
21
+ minWidth: theme.spacing(12),
23
22
  textAlign: 'start'
24
23
  },
25
24
  error: {
26
25
  textAlign: 'center'
27
26
  },
28
27
  label: {
29
- minWidth: theme.spacing(3),
30
- textAlign: 'start'
28
+ minWidth: theme.spacing(3.5),
29
+ textAlign: 'end'
31
30
  },
32
31
 
33
32
  picker: {
@@ -39,7 +38,7 @@ const useStyles = makeStyles()((theme) => ({
39
38
  },
40
39
  timeContainer: {
41
40
  alignItems: 'center',
42
- columnGap: theme.spacing(1),
41
+ columnGap: theme.spacing(0.5),
43
42
  display: 'flex',
44
43
  flexDirection: 'row',
45
44
  [theme.breakpoints.down('sm')]: {
@@ -2,12 +2,15 @@ import { useAtomValue } from 'jotai';
2
2
  import { makeStyles } from 'tss-react/mui';
3
3
  import { equals } from 'ramda';
4
4
  import { useTranslation } from 'react-i18next';
5
+ import dayjs from 'dayjs';
6
+ import utc from 'dayjs/plugin/utc';
7
+ import timezone from 'dayjs/plugin/timezone';
5
8
 
9
+ import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
6
10
  import { Typography } from '@mui/material';
7
11
  import { LocalizationProvider } from '@mui/x-date-pickers';
8
12
 
9
13
  import { userAtom } from '@centreon/ui-context';
10
- import { useDateTimePickerAdapter } from '@centreon/ui';
11
14
 
12
15
  import DateTimePickerInput from '../../DateTimePickerInput';
13
16
  import {
@@ -20,6 +23,9 @@ import ErrorText from './ErrorText';
20
23
  import { PickersData, PickersStartEndDateDirection } from './models';
21
24
  import { PickersStartEndDateModel } from './usePickersStartEndDate';
22
25
 
26
+ dayjs.extend(utc);
27
+ dayjs.extend(timezone);
28
+
23
29
  const useStyles = makeStyles()((theme) => ({
24
30
  error: {
25
31
  textAlign: 'center'
@@ -104,7 +110,6 @@ const PickersStartEndDate = ({
104
110
  direction = PickersStartEndDateDirection.column
105
111
  }: Props): JSX.Element => {
106
112
  const { classes, cx } = useStyles();
107
- const { Adapter } = useDateTimePickerAdapter();
108
113
 
109
114
  const { locale } = useAtomValue(userAtom);
110
115
  const error = useAtomValue(errorTimePeriodAtom);
@@ -126,7 +131,7 @@ const PickersStartEndDate = ({
126
131
  return (
127
132
  <LocalizationProvider
128
133
  adapterLocale={locale.substring(0, 2)}
129
- dateAdapter={Adapter}
134
+ dateAdapter={AdapterDayjs}
130
135
  >
131
136
  <div className={styleContainer}>
132
137
  <PickerDateWithLabel
@@ -18,8 +18,6 @@ export interface PickersData {
18
18
  getError?: (value: boolean) => void;
19
19
  isDisabledEndPicker?: boolean;
20
20
  isDisabledStartPicker?: boolean;
21
- onCloseEndPicker?: (isClosed: boolean) => void;
22
- onCloseStartPicker?: (isClosed: boolean) => void;
23
21
  rangeEndDate?: RangeDate;
24
22
  rangeStartDate?: RangeDate;
25
23
  }