@centreon/ui 26.12.1 → 26.12.3

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 (59) hide show
  1. package/package.json +6 -3
  2. package/public/mockServiceWorker.js +31 -8
  3. package/src/Dashboard/Dashboard.browser.test.tsx +107 -0
  4. package/src/Form/CollapsibleGroup.tsx +6 -33
  5. package/src/Form/Form.browser.test.tsx +553 -0
  6. package/src/Form/Inputs/ExclusiveCheckboxGroup.browser.test.tsx +304 -0
  7. package/src/Form/Inputs/Grid.tsx +1 -2
  8. package/src/Form/Inputs/SegmentedButtons.browser.test.tsx +113 -0
  9. package/src/Form/Inputs/index.tsx +10 -52
  10. package/src/InputField/Number/Number.browser.test.tsx +109 -0
  11. package/src/InputField/Select/Autocomplete/Connected/Multi/MultiConnectedAutocompleteField.browser.test.tsx +250 -0
  12. package/src/Listing/Listing.browser.test.tsx +476 -0
  13. package/src/Module/Module.browser.test.tsx +145 -0
  14. package/src/Pagination/Pagination.browser.test.tsx +184 -0
  15. package/src/RichTextEditor/RichTextEditor.browser.test.tsx +567 -0
  16. package/src/RichTextEditor/plugins/FloatingLinkEditorPlugin.tsx +3 -1
  17. package/src/TimePeriods/ResolutionTimePeriod.browser.test.tsx +143 -0
  18. package/src/TimePeriods/TimePeriods.browser.test.tsx +468 -0
  19. package/src/Typography/FluidTypography/FluidTypography.browser.test.tsx +54 -0
  20. package/src/api/useMutationQuery/useMutationQuery.browser.test.tsx +154 -0
  21. package/src/components/CollapsibleItem/CollapsibleItem.browser.test.tsx +120 -0
  22. package/src/components/CopyCommand/CopyCommand.browser.test.tsx +287 -0
  23. package/src/components/CrudPage/CrudPage.browser.test.tsx +659 -0
  24. package/src/components/DataTable/DataTable.browser.test.tsx +257 -0
  25. package/src/components/Form/AccessRights/AccessRights.browser.test.tsx +527 -0
  26. package/src/components/ItemComposition/ItemComposition.browser.test.tsx +172 -0
  27. package/src/components/Layout/PageLayout.browser.test.tsx +114 -0
  28. package/src/components/Modal/ConfirmationModal/ConfirmationModal.browser.test.tsx +237 -0
  29. package/src/components/SortableEntriesList/SortableEntriesList.browser.test.tsx +981 -0
  30. package/src/components/Tabs/Tabs.browser.test.tsx +115 -0
  31. package/src/utils/useFullscreen/Fullscreen.browser.test.tsx +176 -0
  32. package/src/utils/useLocale/useLocale.browser.test.tsx +49 -0
  33. package/src/utils/useLocaleTimezoneDate/{LocaleTimezoneDate.cypress.spec.tsx → LocaleTimezoneDate.browser.test.tsx} +24 -11
  34. package/src/Dashboard/Dashboard.cypress.spec.tsx +0 -71
  35. package/src/Form/Form.cypress.spec.tsx +0 -306
  36. package/src/Form/Inputs/ExclusiveCheckboxGroup.cypress.spec.tsx +0 -236
  37. package/src/Form/Inputs/SegmentedButtons.cypress.spec.tsx +0 -101
  38. package/src/InputField/Number/Number.cypress.spec.tsx +0 -89
  39. package/src/InputField/Select/Autocomplete/Connected/Multi/MultiConnectedAutocompleteField.cypress.spec.tsx +0 -182
  40. package/src/Listing/Listing.cypress.spec.tsx +0 -349
  41. package/src/Module/Module.cypress.spec.tsx +0 -127
  42. package/src/Pagination/Pagination.cypress.spec.tsx +0 -140
  43. package/src/RichTextEditor/RichTextEditor.cypress.spec.tsx +0 -408
  44. package/src/TimePeriods/ResolutionTimePeriod.cypress.spec.tsx +0 -74
  45. package/src/TimePeriods/TimePeriods.cypress.spec.tsx +0 -488
  46. package/src/Typography/FluidTypography/FluidTypography.cypress.spec.tsx +0 -27
  47. package/src/api/useMutationQuery/useMutationQuery.cypress.spec.tsx +0 -93
  48. package/src/components/CollapsibleItem/CollapsibleItem.cypress.spec.tsx +0 -76
  49. package/src/components/CopyCommand/CopyCommand.cypress.spec.tsx +0 -167
  50. package/src/components/CrudPage/CrudPage.cypress.spec.tsx +0 -561
  51. package/src/components/DataTable/DataTable.cypress.spec.tsx +0 -174
  52. package/src/components/Form/AccessRights/AccessRights.cypress.spec.tsx +0 -376
  53. package/src/components/ItemComposition/ItemComposition.cypress.spec.tsx +0 -112
  54. package/src/components/Layout/PageLayout.cypress.spec.tsx +0 -64
  55. package/src/components/Modal/ConfirmationModal/ConfirmationModal.cypress.spec.tsx +0 -171
  56. package/src/components/SortableEntriesList/SortableEntriesList.cypress.spec.tsx +0 -792
  57. package/src/components/Tabs/Tabs.cypress.spec.tsx +0 -69
  58. package/src/utils/useFullscreen/Fullscreen.cypress.spec.tsx +0 -130
  59. package/src/utils/useLocale/useLocale.cypress.spec.tsx +0 -40
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@centreon/ui",
3
- "version": "26.12.1",
3
+ "version": "26.12.3",
4
4
  "description": "Centreon UI Components",
5
5
  "scripts": {
6
6
  "update:deps": "pnpx npm-check-updates -i --format group",
7
- "type-check": "tsc --project tsconfig.typecheck.json",
7
+ "type-check": "tsc --project tsconfig.typecheck.json && tsc --project tsconfig.rstest.json",
8
8
  "type-check:staged": "node typecheck-staged.mjs",
9
9
  "lint": "biome check ./src/ --error-on-warnings",
10
10
  "lint:fix": "pnpm lint --fix",
@@ -21,7 +21,10 @@
21
21
  "cypress:install": "cypress install",
22
22
  "cypress:cli": "./cypress/scripts/cypress-cli.sh",
23
23
  "tokens:transform": "TS_NODE_PROJECT=tsconfig.node.json ts-node style-dictionary.transform.ts",
24
- "install:arm:binaries": "pnpm i -D @swc/core-linux-arm64-gnu@1.6.6 @rspack/binding-linux-arm64-gnu@1.1.6 -w && pnpm remove @swc/core-linux-arm64-gnu @rspack/binding-linux-arm64-gnu"
24
+ "install:arm:binaries": "pnpm i -D @swc/core-linux-arm64-gnu@1.6.6 @rspack/binding-linux-arm64-gnu@1.1.6 -w && pnpm remove @swc/core-linux-arm64-gnu @rspack/binding-linux-arm64-gnu",
25
+ "rstest:run": "TZ=Etc/UTC rstest run",
26
+ "rstest:ui": "TZ=Etc/UTC rstest run --browser.headless=false --pool.maxWorkers=1",
27
+ "rstest:install": "playwright install --with-deps --only-shell chromium"
25
28
  },
26
29
  "type": "module",
27
30
  "sideEffects": false,
@@ -8,8 +8,8 @@
8
8
  * - Please do NOT serve this file on production.
9
9
  */
10
10
 
11
- const PACKAGE_VERSION = '2.2.14'
12
- const INTEGRITY_CHECKSUM = '26357c79639bfa20d64c0efca2a87423'
11
+ const PACKAGE_VERSION = '2.7.3'
12
+ const INTEGRITY_CHECKSUM = '00729d72e3b82faf54ca8b9621dbb96f'
13
13
  const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
14
14
  const activeClientIds = new Set()
15
15
 
@@ -62,7 +62,12 @@ self.addEventListener('message', async function (event) {
62
62
 
63
63
  sendToClient(client, {
64
64
  type: 'MOCKING_ENABLED',
65
- payload: true,
65
+ payload: {
66
+ client: {
67
+ id: client.id,
68
+ frameType: client.frameType,
69
+ },
70
+ },
66
71
  })
67
72
  break
68
73
  }
@@ -155,6 +160,10 @@ async function handleRequest(event, requestId) {
155
160
  async function resolveMainClient(event) {
156
161
  const client = await self.clients.get(event.clientId)
157
162
 
163
+ if (activeClientIds.has(event.clientId)) {
164
+ return client
165
+ }
166
+
158
167
  if (client?.frameType === 'top-level') {
159
168
  return client
160
169
  }
@@ -183,12 +192,26 @@ async function getResponse(event, client, requestId) {
183
192
  const requestClone = request.clone()
184
193
 
185
194
  function passthrough() {
186
- const headers = Object.fromEntries(requestClone.headers.entries())
195
+ // Cast the request headers to a new Headers instance
196
+ // so the headers can be manipulated with.
197
+ const headers = new Headers(requestClone.headers)
198
+
199
+ // Remove the "accept" header value that marked this request as passthrough.
200
+ // This prevents request alteration and also keeps it compliant with the
201
+ // user-defined CORS policies.
202
+ const acceptHeader = headers.get('accept')
203
+ if (acceptHeader) {
204
+ const values = acceptHeader.split(',').map((value) => value.trim())
205
+ const filteredValues = values.filter(
206
+ (value) => value !== 'msw/passthrough',
207
+ )
187
208
 
188
- // Remove internal MSW request header so the passthrough request
189
- // complies with any potential CORS preflight checks on the server.
190
- // Some servers forbid unknown request headers.
191
- delete headers['x-msw-intention']
209
+ if (filteredValues.length > 0) {
210
+ headers.set('accept', filteredValues.join(', '))
211
+ } else {
212
+ headers.delete('accept')
213
+ }
214
+ }
192
215
 
193
216
  return fetch(requestClone, { headers })
194
217
  }
@@ -0,0 +1,107 @@
1
+ import { Typography } from '@mui/material';
2
+
3
+ import { render } from '@test-setup/render';
4
+ import { screen, waitFor } from '@testing-library/react';
5
+ import type { LayoutItem } from 'react-grid-layout';
6
+
7
+ import { DashboardLayout } from '.';
8
+
9
+ interface CustomLayout extends LayoutItem {
10
+ content: string;
11
+ shouldUseFluidTypography?: boolean;
12
+ }
13
+
14
+ const dashboardLayout: Array<CustomLayout> = [
15
+ {
16
+ content: 'Panel 1',
17
+ h: 4,
18
+ i: 'a',
19
+ shouldUseFluidTypography: false,
20
+ w: 6,
21
+ x: 0,
22
+ y: 0
23
+ },
24
+ {
25
+ content: 'Panel 2',
26
+ h: 3,
27
+ i: 'b',
28
+ minW: 2,
29
+ w: 7,
30
+ x: 1,
31
+ y: 7
32
+ },
33
+ {
34
+ content: 'Panel 3',
35
+ h: 7,
36
+ i: 'c',
37
+ w: 6,
38
+ x: 6,
39
+ y: 6
40
+ },
41
+ {
42
+ content: 'Panel 4',
43
+ h: 3,
44
+ i: 'd',
45
+ minW: 2,
46
+ w: 5,
47
+ x: 4,
48
+ y: 10
49
+ }
50
+ ];
51
+
52
+ const initialize = (): void => {
53
+ render(
54
+ <DashboardLayout.Layout layout={dashboardLayout}>
55
+ {dashboardLayout.map(({ i, content }) => (
56
+ <DashboardLayout.Item header={<div>header</div>} id={i} key={i}>
57
+ {[<Typography key="content">{content}</Typography>]}
58
+ </DashboardLayout.Item>
59
+ ))}
60
+ </DashboardLayout.Layout>
61
+ );
62
+ };
63
+
64
+ const panelBox = (content: string): DOMRect =>
65
+ (
66
+ screen.getByText(content).closest('.react-grid-item') as HTMLElement
67
+ ).getBoundingClientRect();
68
+
69
+ describe('Dashboard', () => {
70
+ beforeEach(() => {
71
+ expect.hasAssertions();
72
+ });
73
+
74
+ it('displays placeholder when panels is out of viewport', async () => {
75
+ initialize();
76
+
77
+ // The four panels render with their header. Panels 1 and 3 share the
78
+ // first row (Panel 3 taller), Panel 2 sits below Panel 3 starting within
79
+ // Panel 1's width, and Panel 4 is below Panel 2.
80
+ expect(await screen.findByText('Panel 1')).toBeVisible();
81
+ expect(screen.getByText('Panel 2')).toBeVisible();
82
+ expect(screen.getByText('Panel 3')).toBeVisible();
83
+ expect(screen.getByText('Panel 4')).toBeInTheDocument();
84
+ expect(screen.getAllByText('header')).toHaveLength(4);
85
+
86
+ await waitFor(() => {
87
+ const panel1 = panelBox('Panel 1');
88
+ const panel3 = panelBox('Panel 3');
89
+
90
+ expect(panel1.width).toBeGreaterThan(0);
91
+ expect(panel3.top).toBe(panel1.top);
92
+ expect(panel3.left).toBeGreaterThan(panel1.right);
93
+ expect(panel3.width).toBe(panel1.width);
94
+ expect(panel3.height).toBeGreaterThan(panel1.height);
95
+ });
96
+
97
+ const panel1 = panelBox('Panel 1');
98
+ const panel2 = panelBox('Panel 2');
99
+ const panel3 = panelBox('Panel 3');
100
+ const panel4 = panelBox('Panel 4');
101
+
102
+ expect(panel2.top).toBeGreaterThan(panel3.bottom);
103
+ expect(panel2.left).toBeGreaterThan(panel1.left);
104
+ expect(panel2.left).toBeLessThan(panel1.right);
105
+ expect(panel4.top).toBeGreaterThan(panel2.bottom);
106
+ });
107
+ });
@@ -10,7 +10,6 @@ import {
10
10
 
11
11
  import { useCallback, useState } from 'react';
12
12
  import { useTranslation } from 'react-i18next';
13
- import { makeStyles } from 'tss-react/mui';
14
13
 
15
14
  import type { Group } from './Inputs/models';
16
15
 
@@ -23,22 +22,6 @@ interface Props {
23
22
  isCollapsible: boolean;
24
23
  }
25
24
 
26
- const useStyles = makeStyles()((theme) => ({
27
- expandCollapseIcon: {
28
- justifySelf: 'flex-end'
29
- },
30
- groupTitleContainer: {
31
- alignItems: 'center',
32
- columnGap: theme.spacing(1),
33
- display: 'flex',
34
- flexDirection: 'row'
35
- },
36
- title: {},
37
- tooltip: {
38
- maxWidth: theme.spacing(60)
39
- }
40
- }));
41
-
42
25
  const CollapsibleGroup = ({
43
26
  children,
44
27
  isCollapsible,
@@ -47,7 +30,6 @@ const CollapsibleGroup = ({
47
30
  defaultIsOpen = false,
48
31
  className
49
32
  }: Props): JSX.Element => {
50
- const { classes, cx } = useStyles();
51
33
  const { t } = useTranslation();
52
34
 
53
35
  const [isOpen, setIsOpen] = useState(isCollapsible && defaultIsOpen);
@@ -56,7 +38,7 @@ const CollapsibleGroup = ({
56
38
  setIsOpen((currentIsOpen) => !currentIsOpen);
57
39
  };
58
40
 
59
- const containerClassName = className || '';
41
+ const containerClassName = `flex items-center gap-x-2 ${className || ''}`;
60
42
 
61
43
  const CollapseIcon = isOpen ? ExpandLess : ExpandMore;
62
44
  const ContainerComponent = useCallback(
@@ -66,7 +48,7 @@ const CollapsibleGroup = ({
66
48
  isCollapsible ? (
67
49
  <ListItemButton
68
50
  aria-label={group?.name}
69
- className={`${cx(classes.groupTitleContainer, containerClassName)} bg-background-listing-header`}
51
+ className={`${containerClassName} bg-background-listing-header rounded-lg`}
70
52
  dense
71
53
  disableGutters
72
54
  disableRipple
@@ -75,18 +57,9 @@ const CollapsibleGroup = ({
75
57
  {containerComponentChildren}
76
58
  </ListItemButton>
77
59
  ) : (
78
- <Box className={cx(classes.groupTitleContainer, containerClassName)}>
79
- {containerComponentChildren}
80
- </Box>
60
+ <Box className={containerClassName}>{containerComponentChildren}</Box>
81
61
  ),
82
- [
83
- isCollapsible,
84
- classes.groupTitleContainer,
85
- containerClassName,
86
- cx,
87
- group?.name,
88
- toggle
89
- ]
62
+ [isCollapsible, containerClassName, group?.name, toggle]
90
63
  );
91
64
 
92
65
  return (
@@ -100,7 +73,7 @@ const CollapsibleGroup = ({
100
73
  data-testid={`${group?.name}-header`}
101
74
  >
102
75
  <Typography
103
- className="groupText scroll-m-12 snap-start"
76
+ className="groupText scroll-m-12 snap-start text-base font-medium"
104
77
  variant="h6"
105
78
  {...group?.titleAttributes}
106
79
  data-section-group-form-id={group?.name}
@@ -110,7 +83,7 @@ const CollapsibleGroup = ({
110
83
  {group?.EndIcon && (
111
84
  <Tooltip
112
85
  classes={{
113
- tooltip: classes.tooltip
86
+ tooltip: 'max-w-120'
114
87
  }}
115
88
  placement="top"
116
89
  title={group?.TooltipContent ? <group.TooltipContent /> : ''}