@centreon/ui 25.3.2 → 25.3.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.
- package/package.json +49 -46
- package/public/mockServiceWorker.js +1 -1
- package/src/Button/Save/index.tsx +17 -35
- package/src/Button/Save/useSave.tsx +89 -0
- package/src/Form/Inputs/LoadingSkeleton.tsx +1 -1
- package/src/Form/Inputs/Radio.tsx +7 -5
- package/src/Form/Inputs/Switch.tsx +4 -2
- package/src/Graph/Chart/Chart.cypress.spec.tsx +2 -2
- package/src/Graph/SingleBar/ThresholdLine.tsx +2 -2
- package/src/Graph/common/Thresholds/ThresholdLine.tsx +2 -2
- package/src/InputField/Select/index.tsx +11 -9
- package/src/Listing/Listing.cypress.spec.tsx +9 -11
- package/src/RichTextEditor/RichTextEditor.tsx +1 -1
- package/src/api/useMutationQuery/useMutationQuery.cypress.spec.tsx +0 -18
- package/src/components/Button/Button.tsx +19 -15
- package/src/components/CollapsibleItem/CollapsibleItem.cypress.spec.tsx +8 -8
- package/src/components/CopyCommand/CopyCommand.cypress.spec.tsx +11 -10
- package/src/Button/Save/Content.tsx +0 -34
- package/src/Button/Save/StartIcon.tsx +0 -24
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@centreon/ui",
|
|
3
|
-
"version": "25.3.
|
|
3
|
+
"version": "25.3.3",
|
|
4
4
|
"description": "Centreon UI Components",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"update:deps": "pnpx npm-check-updates -i --format group",
|
|
@@ -16,7 +16,10 @@
|
|
|
16
16
|
"cypress:run:updateSnapshots": "cypress run --component --browser=chrome --env updateSnapshots=true",
|
|
17
17
|
"cypress:run:coverage": "cypress run --component --browser=chrome --env codeCoverageTasksRegistered=true",
|
|
18
18
|
"cypress:run": "cypress run --component --browser=chrome",
|
|
19
|
-
"
|
|
19
|
+
"cypress:install": "cypress install",
|
|
20
|
+
"cypress:cli": "./cypress/scripts/cypress-cli.sh",
|
|
21
|
+
"tokens:transform": "TS_NODE_PROJECT=tsconfig.node.json ts-node style-dictionary.transform.ts",
|
|
22
|
+
"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"
|
|
20
23
|
},
|
|
21
24
|
"type": "module",
|
|
22
25
|
"sideEffects": false,
|
|
@@ -50,71 +53,71 @@
|
|
|
50
53
|
"test/*"
|
|
51
54
|
],
|
|
52
55
|
"devDependencies": {
|
|
53
|
-
"@cypress/react": "^
|
|
54
|
-
"@cypress/webpack-dev-server": "^
|
|
55
|
-
"@faker-js/faker": "^9.
|
|
56
|
+
"@cypress/react": "^9.0.0",
|
|
57
|
+
"@cypress/webpack-dev-server": "^4.0.1",
|
|
58
|
+
"@faker-js/faker": "^9.5.1",
|
|
56
59
|
"@mdx-js/react": "^3.1.0",
|
|
57
60
|
"@simonsmith/cypress-image-snapshot": "^9.1.0",
|
|
58
|
-
"@storybook/addon-a11y": "^8.
|
|
59
|
-
"@storybook/addon-docs": "^8.
|
|
60
|
-
"@storybook/addon-essentials": "^8.
|
|
61
|
-
"@storybook/addon-interactions": "^8.
|
|
62
|
-
"@storybook/addon-themes": "^8.
|
|
63
|
-
"@storybook/blocks": "^8.
|
|
64
|
-
"@storybook/manager-api": "^8.
|
|
61
|
+
"@storybook/addon-a11y": "^8.6.3",
|
|
62
|
+
"@storybook/addon-docs": "^8.6.3",
|
|
63
|
+
"@storybook/addon-essentials": "^8.6.3",
|
|
64
|
+
"@storybook/addon-interactions": "^8.6.3",
|
|
65
|
+
"@storybook/addon-themes": "^8.6.3",
|
|
66
|
+
"@storybook/blocks": "^8.6.3",
|
|
67
|
+
"@storybook/manager-api": "^8.6.3",
|
|
65
68
|
"@storybook/mdx2-csf": "^1.1.0",
|
|
66
|
-
"@storybook/preview-api": "^8.
|
|
67
|
-
"@storybook/react": "^8.
|
|
68
|
-
"@storybook/react-vite": "^8.
|
|
69
|
-
"@storybook/test": "^8.
|
|
70
|
-
"@storybook/test-runner": "^0.
|
|
71
|
-
"@storybook/theming": "^8.
|
|
72
|
-
"@testing-library/cypress": "^10.0.
|
|
69
|
+
"@storybook/preview-api": "^8.6.3",
|
|
70
|
+
"@storybook/react": "^8.6.3",
|
|
71
|
+
"@storybook/react-vite": "^8.6.3",
|
|
72
|
+
"@storybook/test": "^8.6.3",
|
|
73
|
+
"@storybook/test-runner": "^0.22.0",
|
|
74
|
+
"@storybook/theming": "^8.6.3",
|
|
75
|
+
"@testing-library/cypress": "^10.0.3",
|
|
73
76
|
"@testing-library/jest-dom": "^6.6.3",
|
|
74
|
-
"@testing-library/react": "^16.
|
|
77
|
+
"@testing-library/react": "^16.2.0",
|
|
75
78
|
"@testing-library/react-hooks": "^8.0.1",
|
|
76
79
|
"@types/jest": "^29.5.14",
|
|
77
80
|
"@types/mocha": "^10.0.10",
|
|
78
81
|
"@types/ramda": "^0.30.2",
|
|
79
|
-
"@types/react": "^
|
|
82
|
+
"@types/react": "^19.0.10",
|
|
80
83
|
"@types/testing-library__jest-dom": "^6.0.0",
|
|
81
84
|
"@vitejs/plugin-react": "^4.3.4",
|
|
82
|
-
"@vitejs/plugin-react-swc": "^3.
|
|
83
|
-
"chai": "^5.
|
|
84
|
-
"cypress": "^
|
|
85
|
+
"@vitejs/plugin-react-swc": "^3.8.0",
|
|
86
|
+
"chai": "^5.2.0",
|
|
87
|
+
"cypress": "^14.1.0",
|
|
85
88
|
"identity-obj-proxy": "^3.0.0",
|
|
86
89
|
"jest-transform-stub": "^2.0.0",
|
|
87
90
|
"mochawesome": "^7.1.3",
|
|
88
|
-
"msw": "2.
|
|
91
|
+
"msw": "2.7.3",
|
|
89
92
|
"msw-storybook-addon": "^2.0.4",
|
|
90
|
-
"react": "^
|
|
91
|
-
"react-dom": "^
|
|
93
|
+
"react": "^19.0.0",
|
|
94
|
+
"react-dom": "^19.0.0",
|
|
92
95
|
"react-test-renderer": "^19.0.0",
|
|
93
|
-
"remark-gfm": "^4.0.
|
|
96
|
+
"remark-gfm": "^4.0.1",
|
|
94
97
|
"speed-measure-vite-plugin": "^1.1.0",
|
|
95
|
-
"storybook": "^8.
|
|
98
|
+
"storybook": "^8.6.3",
|
|
96
99
|
"storybook-addon-mock": "^5.0.0",
|
|
97
100
|
"storybook-dark-mode": "^4.0.2",
|
|
98
|
-
"style-dictionary": "^4.3.
|
|
101
|
+
"style-dictionary": "^4.3.3",
|
|
99
102
|
"ts-node": "^10.9.2",
|
|
100
103
|
"use-resize-observer": "^9.1.0",
|
|
101
|
-
"vite": "^6.0
|
|
102
|
-
"vite-plugin-istanbul": "^
|
|
104
|
+
"vite": "^6.2.0",
|
|
105
|
+
"vite-plugin-istanbul": "^7.0.0",
|
|
103
106
|
"vite-plugin-svgr": "^4.3.0",
|
|
104
107
|
"vite-plugin-turbosnap": "^1.0.3"
|
|
105
108
|
},
|
|
106
109
|
"peerDependencies": {
|
|
107
|
-
"@centreon/ui-context": "
|
|
110
|
+
"@centreon/ui-context": "link:../ui-context"
|
|
108
111
|
},
|
|
109
112
|
"dependencies": {
|
|
110
|
-
"@lexical/html": "^0.
|
|
111
|
-
"@lexical/link": "^0.
|
|
112
|
-
"@lexical/list": "^0.
|
|
113
|
-
"@lexical/react": "^0.
|
|
114
|
-
"@lexical/rich-text": "^0.
|
|
115
|
-
"@lexical/selection": "^0.
|
|
116
|
-
"@lexical/utils": "^0.
|
|
117
|
-
"@mui/material": "^6.
|
|
113
|
+
"@lexical/html": "^0.27.0",
|
|
114
|
+
"@lexical/link": "^0.27.0",
|
|
115
|
+
"@lexical/list": "^0.27.0",
|
|
116
|
+
"@lexical/react": "^0.27.0",
|
|
117
|
+
"@lexical/rich-text": "^0.27.0",
|
|
118
|
+
"@lexical/selection": "^0.27.0",
|
|
119
|
+
"@lexical/utils": "^0.27.0",
|
|
120
|
+
"@mui/material": "^6.4.6",
|
|
118
121
|
"@react-spring/web": "^9.7.5",
|
|
119
122
|
"@visx/clip-path": "^3.12.0",
|
|
120
123
|
"@visx/curve": "^3.12.0",
|
|
@@ -133,18 +136,18 @@
|
|
|
133
136
|
"anylogger": "^1.0.11",
|
|
134
137
|
"d3-array": "3.2.4",
|
|
135
138
|
"dayjs": "^1.11.13",
|
|
136
|
-
"highlight.js": "^11.
|
|
137
|
-
"html-react-parser": "^5.2.
|
|
139
|
+
"highlight.js": "^11.11.1",
|
|
140
|
+
"html-react-parser": "^5.2.2",
|
|
138
141
|
"humanize-duration": "^3.32.1",
|
|
139
|
-
"lexical": "^0.
|
|
140
|
-
"notistack": "^3.0.
|
|
142
|
+
"lexical": "^0.27.0",
|
|
143
|
+
"notistack": "^3.0.2",
|
|
141
144
|
"numeral": "^2.0.6",
|
|
142
145
|
"ramda": "0.30.1",
|
|
143
146
|
"react-grid-layout": "^1.5.0",
|
|
144
147
|
"react-resizable": "^3.0.5",
|
|
145
148
|
"react-router": "7",
|
|
146
149
|
"react-transition-group": "^4.4.5",
|
|
147
|
-
"sanitize-html": "^2.
|
|
150
|
+
"sanitize-html": "^2.14.0",
|
|
148
151
|
"ulog": "^2.0.0-beta.19"
|
|
149
152
|
},
|
|
150
153
|
"jest-junit": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* - Please do NOT serve this file on production.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
const PACKAGE_VERSION = '2.
|
|
11
|
+
const PACKAGE_VERSION = '2.7.3'
|
|
12
12
|
const INTEGRITY_CHECKSUM = '00729d72e3b82faf54ca8b9621dbb96f'
|
|
13
13
|
const IS_MOCKED_RESPONSE = Symbol('isMockedResponse')
|
|
14
14
|
const activeClientIds = new Set()
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import { any, isEmpty, isNil, not, or, pipe } from 'ramda';
|
|
2
1
|
import { makeStyles } from 'tss-react/mui';
|
|
3
2
|
|
|
4
|
-
import { LoadingButton, LoadingButtonProps } from '@mui/lab';
|
|
5
3
|
import { Theme, Tooltip } from '@mui/material';
|
|
6
4
|
|
|
7
5
|
import { getNormalizedId } from '../../utils';
|
|
8
6
|
|
|
9
|
-
import
|
|
10
|
-
import
|
|
7
|
+
import { Button, ButtonProps } from '../../components';
|
|
8
|
+
import { useSave } from './useSave';
|
|
11
9
|
|
|
12
10
|
const useStyles = makeStyles()((theme: Theme) => ({
|
|
13
11
|
loadingButton: {
|
|
@@ -15,7 +13,7 @@ const useStyles = makeStyles()((theme: Theme) => ({
|
|
|
15
13
|
}
|
|
16
14
|
}));
|
|
17
15
|
|
|
18
|
-
interface Props {
|
|
16
|
+
export interface Props {
|
|
19
17
|
className?: string;
|
|
20
18
|
labelLoading?: string;
|
|
21
19
|
labelSave?: string;
|
|
@@ -28,15 +26,6 @@ interface Props {
|
|
|
28
26
|
tooltipLabel?: string;
|
|
29
27
|
}
|
|
30
28
|
|
|
31
|
-
interface StartIconConfigProps {
|
|
32
|
-
hasLabel: boolean;
|
|
33
|
-
loading: boolean;
|
|
34
|
-
succeeded: boolean;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const isNilOrEmpty = (value): boolean => or(isNil(value), isEmpty(value));
|
|
38
|
-
const hasValue = any(pipe(isNilOrEmpty, not));
|
|
39
|
-
|
|
40
29
|
const SaveButton = ({
|
|
41
30
|
succeeded = false,
|
|
42
31
|
loading = false,
|
|
@@ -48,20 +37,22 @@ const SaveButton = ({
|
|
|
48
37
|
className,
|
|
49
38
|
startIcon = true,
|
|
50
39
|
...rest
|
|
51
|
-
}: Props &
|
|
40
|
+
}: Props & Omit<ButtonProps, 'children'>): JSX.Element => {
|
|
52
41
|
const { classes, cx } = useStyles();
|
|
53
|
-
const hasLabel = hasValue([labelLoading, labelSave, labelSucceeded]);
|
|
54
42
|
|
|
55
|
-
const
|
|
56
|
-
|
|
43
|
+
const { content, startIconToDisplay, hasLabel } = useSave({
|
|
44
|
+
labelLoading,
|
|
45
|
+
labelSave,
|
|
46
|
+
labelSucceeded,
|
|
57
47
|
loading,
|
|
58
|
-
succeeded
|
|
59
|
-
|
|
48
|
+
succeeded,
|
|
49
|
+
startIcon
|
|
50
|
+
});
|
|
60
51
|
|
|
61
52
|
return (
|
|
62
53
|
<Tooltip placement="bottom" title={tooltipLabel}>
|
|
63
54
|
<div>
|
|
64
|
-
<
|
|
55
|
+
<Button
|
|
65
56
|
aria-label="save button"
|
|
66
57
|
className={cx(
|
|
67
58
|
{
|
|
@@ -69,26 +60,17 @@ const SaveButton = ({
|
|
|
69
60
|
},
|
|
70
61
|
className
|
|
71
62
|
)}
|
|
72
|
-
color="primary"
|
|
73
63
|
data-testid={labelSave}
|
|
74
64
|
id={getNormalizedId(labelSave)}
|
|
75
65
|
loading={loading}
|
|
76
|
-
loadingPosition={labelLoading ? 'start' :
|
|
66
|
+
loadingPosition={labelLoading ? 'start' : undefined}
|
|
77
67
|
size={size}
|
|
78
|
-
startIcon={
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
variant="contained"
|
|
68
|
+
startIcon={startIconToDisplay}
|
|
69
|
+
variant="primary"
|
|
82
70
|
{...rest}
|
|
83
71
|
>
|
|
84
|
-
{
|
|
85
|
-
|
|
86
|
-
labelSave,
|
|
87
|
-
labelSucceeded,
|
|
88
|
-
loading,
|
|
89
|
-
succeeded
|
|
90
|
-
})}
|
|
91
|
-
</LoadingButton>
|
|
72
|
+
{content}
|
|
73
|
+
</Button>
|
|
92
74
|
</div>
|
|
93
75
|
</Tooltip>
|
|
94
76
|
);
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import CheckIcon from '@mui/icons-material/Check';
|
|
2
|
+
import SaveIcon from '@mui/icons-material/Save';
|
|
3
|
+
import {
|
|
4
|
+
T,
|
|
5
|
+
always,
|
|
6
|
+
any,
|
|
7
|
+
cond,
|
|
8
|
+
isEmpty,
|
|
9
|
+
isNil,
|
|
10
|
+
not,
|
|
11
|
+
or,
|
|
12
|
+
pipe,
|
|
13
|
+
propEq
|
|
14
|
+
} from 'ramda';
|
|
15
|
+
import { useMemo } from 'react';
|
|
16
|
+
import { useTranslation } from 'react-i18next';
|
|
17
|
+
import { Props } from '.';
|
|
18
|
+
|
|
19
|
+
interface StartIconConfigProps {
|
|
20
|
+
hasLabel: boolean;
|
|
21
|
+
loading: boolean;
|
|
22
|
+
succeeded: boolean;
|
|
23
|
+
enabled: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const isNilOrEmpty = (value): boolean => or(isNil(value), isEmpty(value));
|
|
27
|
+
const hasValue = any(pipe(isNilOrEmpty, not));
|
|
28
|
+
|
|
29
|
+
interface UseSaveState {
|
|
30
|
+
content: string | JSX.Element;
|
|
31
|
+
startIconToDisplay: null | JSX.Element;
|
|
32
|
+
hasLabel: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const useSave = ({
|
|
36
|
+
labelLoading,
|
|
37
|
+
labelSave,
|
|
38
|
+
labelSucceeded,
|
|
39
|
+
loading,
|
|
40
|
+
succeeded,
|
|
41
|
+
startIcon
|
|
42
|
+
}: Pick<
|
|
43
|
+
Props,
|
|
44
|
+
| 'startIcon'
|
|
45
|
+
| 'succeeded'
|
|
46
|
+
| 'loading'
|
|
47
|
+
| 'labelSave'
|
|
48
|
+
| 'labelSucceeded'
|
|
49
|
+
| 'labelLoading'
|
|
50
|
+
>): UseSaveState => {
|
|
51
|
+
const { t } = useTranslation();
|
|
52
|
+
|
|
53
|
+
const hasLabel = hasValue([labelLoading, labelSave, labelSucceeded]);
|
|
54
|
+
|
|
55
|
+
const startIconConfig = {
|
|
56
|
+
hasLabel,
|
|
57
|
+
loading,
|
|
58
|
+
succeeded,
|
|
59
|
+
enabled: startIcon
|
|
60
|
+
} as StartIconConfigProps;
|
|
61
|
+
|
|
62
|
+
const content = useMemo(() => {
|
|
63
|
+
if (loading) {
|
|
64
|
+
return t(labelLoading || 'loading');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (succeeded) {
|
|
68
|
+
return labelSucceeded ? t(labelSucceeded) : <CheckIcon />;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return labelSave ? t(labelSave) : <SaveIcon />;
|
|
72
|
+
}, [labelLoading, labelSucceeded, labelSave, loading, succeeded]);
|
|
73
|
+
|
|
74
|
+
const startIconToDisplay = useMemo(() => {
|
|
75
|
+
return cond<Array<StartIconConfigProps>, JSX.Element | null>([
|
|
76
|
+
[propEq(true, 'enabled'), always(null)],
|
|
77
|
+
[pipe(propEq(true, 'hasLabel'), not), always(null)],
|
|
78
|
+
[propEq(true, 'succeeded'), always(<CheckIcon />)],
|
|
79
|
+
[propEq(true, 'loading'), always(<SaveIcon />)],
|
|
80
|
+
[T, always(<SaveIcon />)]
|
|
81
|
+
])(startIconConfig);
|
|
82
|
+
}, [startIconConfig]);
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
content,
|
|
86
|
+
startIconToDisplay,
|
|
87
|
+
hasLabel
|
|
88
|
+
};
|
|
89
|
+
};
|
|
@@ -80,11 +80,13 @@ const Radio = ({
|
|
|
80
80
|
data-testid={`${dataTestId} ${optionLabel}`}
|
|
81
81
|
disabled={disabled}
|
|
82
82
|
id={getNormalizedId(`${dataTestId}${optionLabel}`)}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
slotProps={{
|
|
84
|
+
input: {
|
|
85
|
+
'aria-label':
|
|
86
|
+
(equals(type(optionLabel), 'String') &&
|
|
87
|
+
t(optionLabel as string)) ||
|
|
88
|
+
''
|
|
89
|
+
}
|
|
88
90
|
}}
|
|
89
91
|
/>
|
|
90
92
|
}
|
|
@@ -58,8 +58,10 @@ const Switch = ({
|
|
|
58
58
|
data-testid={dataTestId}
|
|
59
59
|
disabled={disabled}
|
|
60
60
|
id={getNormalizedId(dataTestId || '')}
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
slotProps={{
|
|
62
|
+
input: {
|
|
63
|
+
'aria-label': t(label) || ''
|
|
64
|
+
}
|
|
63
65
|
}}
|
|
64
66
|
onChange={changeSwitchValue}
|
|
65
67
|
/>
|
|
@@ -758,8 +758,8 @@ describe('Lines and bars', () => {
|
|
|
758
758
|
cy.get('path[data-metric="3"]').should('be.visible');
|
|
759
759
|
|
|
760
760
|
cy.contains('some text').should('be.visible');
|
|
761
|
-
cy.findByTestId('pink-3').should('
|
|
762
|
-
cy.findByTestId('red-0.15').should('
|
|
761
|
+
cy.findByTestId('pink-3').should('exist');
|
|
762
|
+
cy.findByTestId('red-0.15').should('exist');
|
|
763
763
|
|
|
764
764
|
cy.makeSnapshot();
|
|
765
765
|
});
|
|
@@ -63,7 +63,7 @@ export const ThresholdLine = ({
|
|
|
63
63
|
strokeDasharray="6, 6"
|
|
64
64
|
strokeWidth={2}
|
|
65
65
|
x1={scaledValue}
|
|
66
|
-
x2={scaledValue}
|
|
66
|
+
x2={scaledValue + 1}
|
|
67
67
|
y1={
|
|
68
68
|
isSmall
|
|
69
69
|
? groupMargin - lineMargin + 6
|
|
@@ -80,7 +80,7 @@ export const ThresholdLine = ({
|
|
|
80
80
|
stroke="transparent"
|
|
81
81
|
strokeWidth={5}
|
|
82
82
|
x1={scaledValue}
|
|
83
|
-
x2={scaledValue}
|
|
83
|
+
x2={scaledValue + 1}
|
|
84
84
|
y1={
|
|
85
85
|
isSmall
|
|
86
86
|
? groupMargin - lineMargin + 5
|
|
@@ -97,15 +97,17 @@ const SelectField = ({
|
|
|
97
97
|
<Select
|
|
98
98
|
displayEmpty
|
|
99
99
|
fullWidth={fullWidth}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
100
|
+
slotProps={{
|
|
101
|
+
input: {
|
|
102
|
+
'aria-label': ariaLabel,
|
|
103
|
+
className: cx(classes.input, {
|
|
104
|
+
[classes.noLabelInput]: !label && !compact,
|
|
105
|
+
[classes.compact]: compact
|
|
106
|
+
}),
|
|
107
|
+
'data-testid': dataTestId,
|
|
108
|
+
id: getNormalizedId(dataTestId || ''),
|
|
109
|
+
...inputProps
|
|
110
|
+
}
|
|
109
111
|
}}
|
|
110
112
|
label={label}
|
|
111
113
|
renderValue={(id): string => {
|
|
@@ -237,35 +237,33 @@ describe('Listing', () => {
|
|
|
237
237
|
it('selects displayed rows when a row is selected and another row is selected with the shift key', () => {
|
|
238
238
|
mountListingForSubItems({ canCheckSubItems: true, isSmallListing: true });
|
|
239
239
|
|
|
240
|
-
cy.findByLabelText('Expand
|
|
240
|
+
cy.findByLabelText('Expand 2').click();
|
|
241
241
|
|
|
242
|
-
cy.findByLabelText('Collapse
|
|
242
|
+
cy.findByLabelText('Collapse 2').should('be.visible');
|
|
243
243
|
|
|
244
|
-
cy.findAllByLabelText('Select row
|
|
244
|
+
cy.findAllByLabelText('Select row 2').eq(0).click();
|
|
245
245
|
cy.get('body').type('{shift}', { release: false });
|
|
246
246
|
cy.findByLabelText('Select row 50').eq(0).click();
|
|
247
247
|
|
|
248
|
-
cy.findAllByLabelText('Select row
|
|
249
|
-
cy.findAllByLabelText('Select row 0').eq(1).should('be.checked');
|
|
248
|
+
cy.findAllByLabelText('Select row 2').eq(0).should('be.checked');
|
|
250
249
|
cy.findByLabelText('Select row 10').should('be.checked');
|
|
251
250
|
cy.findByLabelText('Select row 20').should('be.checked');
|
|
252
251
|
cy.findByLabelText('Select row 30').should('be.checked');
|
|
253
252
|
cy.findByLabelText('Select row 40').should('be.checked');
|
|
254
|
-
cy.findByLabelText('Select row 50').should('be.checked');
|
|
255
253
|
|
|
256
|
-
cy.findByLabelText('Collapse
|
|
254
|
+
cy.findByLabelText('Collapse 2').click();
|
|
257
255
|
});
|
|
258
256
|
|
|
259
257
|
it('selects displayed rows when the corresponding checkbox is clicked', () => {
|
|
260
258
|
mountListingForSubItems({ canCheckSubItems: true, isSmallListing: true });
|
|
261
259
|
|
|
262
|
-
cy.findByLabelText('Expand
|
|
260
|
+
cy.findByLabelText('Expand 2').click();
|
|
263
261
|
|
|
264
|
-
cy.findByLabelText('Collapse
|
|
262
|
+
cy.findByLabelText('Collapse 2').should('be.visible');
|
|
265
263
|
|
|
266
264
|
cy.findAllByLabelText('Select all').eq(0).click();
|
|
267
265
|
|
|
268
|
-
cy.findAllByLabelText('Select row
|
|
266
|
+
cy.findAllByLabelText('Select row 2').eq(0).should('be.checked');
|
|
269
267
|
tenElements.forEach((_, index) => {
|
|
270
268
|
if (index === 0) {
|
|
271
269
|
cy.findAllByLabelText('Select row 0').eq(1).should('be.checked');
|
|
@@ -277,7 +275,7 @@ describe('Listing', () => {
|
|
|
277
275
|
cy.findByLabelText('Select row 1').should('be.checked');
|
|
278
276
|
cy.findByLabelText('Select row 2').should('be.checked');
|
|
279
277
|
|
|
280
|
-
cy.findByLabelText('Collapse
|
|
278
|
+
cy.findByLabelText('Collapse 2').click();
|
|
281
279
|
});
|
|
282
280
|
});
|
|
283
281
|
|
|
@@ -2,7 +2,7 @@ import { $generateHtmlFromNodes } from '@lexical/html';
|
|
|
2
2
|
import { AutoLinkNode, LinkNode } from '@lexical/link';
|
|
3
3
|
import { ListItemNode, ListNode } from '@lexical/list';
|
|
4
4
|
import { LexicalComposer } from '@lexical/react/LexicalComposer';
|
|
5
|
-
import LexicalErrorBoundary from '@lexical/react/LexicalErrorBoundary';
|
|
5
|
+
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';
|
|
6
6
|
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
|
|
7
7
|
import { LinkPlugin } from '@lexical/react/LexicalLinkPlugin';
|
|
8
8
|
import { ListPlugin } from '@lexical/react/LexicalListPlugin';
|
|
@@ -2,17 +2,12 @@ import useMutationQuery, { Method } from '.';
|
|
|
2
2
|
import SnackbarProvider from '../../Snackbar/SnackbarProvider';
|
|
3
3
|
import TestQueryProvider from '../TestQueryProvider';
|
|
4
4
|
|
|
5
|
-
// biome-ignore lint/suspicious/noImplicitAnyLet: <explanation>
|
|
6
|
-
let spyMutation;
|
|
7
|
-
|
|
8
5
|
const TestComponent = (props) => {
|
|
9
6
|
const mutation = useMutationQuery({
|
|
10
7
|
...props,
|
|
11
8
|
getEndpoint: () => '/endpoint'
|
|
12
9
|
});
|
|
13
10
|
|
|
14
|
-
spyMutation = mutation;
|
|
15
|
-
|
|
16
11
|
return (
|
|
17
12
|
<button
|
|
18
13
|
type="button"
|
|
@@ -46,8 +41,6 @@ const initialize = ({ mutationProps, isError = false }) => {
|
|
|
46
41
|
</TestQueryProvider>
|
|
47
42
|
</SnackbarProvider>
|
|
48
43
|
)
|
|
49
|
-
}).then(() => {
|
|
50
|
-
cy.spy(spyMutation, 'mutateAsync').as('mutateAsync');
|
|
51
44
|
});
|
|
52
45
|
};
|
|
53
46
|
|
|
@@ -67,13 +60,6 @@ describe('useMutationQuery', () => {
|
|
|
67
60
|
expect(request.body).to.deep.equal({ a: 'a', b: 2, c: ['arr', 'ay'] });
|
|
68
61
|
expect(request.headers.get('content-type')).to.equal('application/json');
|
|
69
62
|
});
|
|
70
|
-
cy.get('@mutateAsync').should('be.calledWith', {
|
|
71
|
-
payload: {
|
|
72
|
-
a: 'a',
|
|
73
|
-
b: 2,
|
|
74
|
-
c: ['arr', 'ay']
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
63
|
});
|
|
78
64
|
|
|
79
65
|
it("shows an error from the API via the Snackbar and inside the browser's console when posting data to an endpoint", () => {
|
|
@@ -87,8 +73,6 @@ describe('useMutationQuery', () => {
|
|
|
87
73
|
|
|
88
74
|
cy.get('button').click();
|
|
89
75
|
|
|
90
|
-
cy.get('@mutateAsync').should('be.called');
|
|
91
|
-
|
|
92
76
|
cy.contains('custom error message').should('be.visible');
|
|
93
77
|
});
|
|
94
78
|
|
|
@@ -104,8 +88,6 @@ describe('useMutationQuery', () => {
|
|
|
104
88
|
|
|
105
89
|
cy.get('button').click();
|
|
106
90
|
|
|
107
|
-
cy.get('@mutateAsync').should('be.called');
|
|
108
|
-
|
|
109
91
|
cy.contains('custom error message').should('not.exist');
|
|
110
92
|
});
|
|
111
93
|
});
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { ReactElement, ReactNode, useMemo } from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
Button as MuiButton,
|
|
5
|
+
ButtonProps as MuiButtonProps
|
|
6
|
+
} from '@mui/material';
|
|
4
7
|
|
|
5
8
|
import { AriaLabelingAttributes } from '../../@types/aria-attributes';
|
|
6
9
|
import { DataTestAttributes } from '../../@types/data-attributes';
|
|
@@ -16,20 +19,21 @@ const muiVariantMap: Record<
|
|
|
16
19
|
secondary: 'outlined'
|
|
17
20
|
};
|
|
18
21
|
|
|
19
|
-
export type ButtonProps =
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
22
|
+
export type ButtonProps = AriaLabelingAttributes &
|
|
23
|
+
DataTestAttributes &
|
|
24
|
+
Omit<MuiButtonProps, 'variant'> & {
|
|
25
|
+
children: ReactNode;
|
|
26
|
+
className?: string;
|
|
27
|
+
disabled?: boolean;
|
|
28
|
+
icon?: string | ReactNode;
|
|
29
|
+
iconVariant?: 'none' | 'start' | 'end';
|
|
30
|
+
isDanger?: boolean;
|
|
31
|
+
onClick?: (e) => void;
|
|
32
|
+
ref?: React.Ref<HTMLButtonElement>;
|
|
33
|
+
size?: 'small' | 'medium' | 'large';
|
|
34
|
+
type?: 'button' | 'submit' | 'reset';
|
|
35
|
+
variant?: 'primary' | 'secondary' | 'ghost';
|
|
36
|
+
};
|
|
33
37
|
|
|
34
38
|
const Button = ({
|
|
35
39
|
children,
|
|
@@ -16,7 +16,7 @@ describe('CollapsibleItem', () => {
|
|
|
16
16
|
|
|
17
17
|
cy.contains(title).should('be.visible');
|
|
18
18
|
cy.contains('Content').should('not.be.visible');
|
|
19
|
-
cy.get('
|
|
19
|
+
cy.get('button[aria-expanded="false"]').should('exist');
|
|
20
20
|
|
|
21
21
|
cy.makeSnapshot();
|
|
22
22
|
});
|
|
@@ -26,7 +26,7 @@ describe('CollapsibleItem', () => {
|
|
|
26
26
|
|
|
27
27
|
cy.contains(title).should('be.visible');
|
|
28
28
|
cy.contains('Content').should('be.visible');
|
|
29
|
-
cy.get('
|
|
29
|
+
cy.get('button[aria-expanded="true"]').should('exist');
|
|
30
30
|
|
|
31
31
|
cy.makeSnapshot();
|
|
32
32
|
});
|
|
@@ -35,7 +35,7 @@ describe('CollapsibleItem', () => {
|
|
|
35
35
|
initialize({ title: customizedTitle });
|
|
36
36
|
|
|
37
37
|
cy.contains('Customized title').should('be.visible');
|
|
38
|
-
cy.get('
|
|
38
|
+
cy.get('button[aria-expanded="false"]').should('exist');
|
|
39
39
|
|
|
40
40
|
cy.makeSnapshot();
|
|
41
41
|
});
|
|
@@ -44,7 +44,7 @@ describe('CollapsibleItem', () => {
|
|
|
44
44
|
initialize({ compact: true, title });
|
|
45
45
|
|
|
46
46
|
cy.contains(title).should('be.visible');
|
|
47
|
-
cy.get('
|
|
47
|
+
cy.get('button[aria-expanded="false"]').should('exist');
|
|
48
48
|
cy.get('div[data-compact="true"]').should('exist');
|
|
49
49
|
|
|
50
50
|
cy.makeSnapshot();
|
|
@@ -54,11 +54,11 @@ describe('CollapsibleItem', () => {
|
|
|
54
54
|
initialize({ compact: true, title });
|
|
55
55
|
|
|
56
56
|
cy.contains(title).should('be.visible');
|
|
57
|
-
cy.get('
|
|
57
|
+
cy.get('button[aria-expanded="false"]').should('exist');
|
|
58
58
|
|
|
59
|
-
cy.get('
|
|
59
|
+
cy.get('button[aria-expanded="false"]').click();
|
|
60
60
|
|
|
61
|
-
cy.get('
|
|
61
|
+
cy.get('button[aria-expanded="true"]').should('exist');
|
|
62
62
|
cy.contains('Content').should('be.visible');
|
|
63
63
|
|
|
64
64
|
cy.makeSnapshot();
|
|
@@ -68,7 +68,7 @@ describe('CollapsibleItem', () => {
|
|
|
68
68
|
initialize({ compact: true, title: customizedTitle });
|
|
69
69
|
|
|
70
70
|
cy.contains('Customized title').should('be.visible');
|
|
71
|
-
cy.get('
|
|
71
|
+
cy.get('button[aria-expanded="false"]').should('exist');
|
|
72
72
|
cy.get('div[data-compact="true"]').should('exist');
|
|
73
73
|
|
|
74
74
|
cy.makeSnapshot();
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { ThemeMode, userAtom } from '@centreon/ui-context';
|
|
2
|
-
import { mount } from 'cypress/react18';
|
|
3
2
|
import { Provider, createStore } from 'jotai';
|
|
4
3
|
import SnackbarProvider from '../../Snackbar/SnackbarProvider';
|
|
5
4
|
import ThemeProvider from '../../ThemeProvider';
|
|
@@ -8,15 +7,17 @@ import CopyCommand, { CopyCommandProps } from './CopyCommand';
|
|
|
8
7
|
const initialize = (props: CopyCommandProps & { theme?: ThemeMode }): void => {
|
|
9
8
|
const store = createStore();
|
|
10
9
|
store.set(userAtom, { themeMode: props.theme || ThemeMode.light });
|
|
11
|
-
mount(
|
|
12
|
-
|
|
13
|
-
<
|
|
14
|
-
<
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
10
|
+
cy.mount({
|
|
11
|
+
Component: (
|
|
12
|
+
<Provider store={store}>
|
|
13
|
+
<ThemeProvider>
|
|
14
|
+
<SnackbarProvider>
|
|
15
|
+
<CopyCommand {...props} />
|
|
16
|
+
</SnackbarProvider>
|
|
17
|
+
</ThemeProvider>
|
|
18
|
+
</Provider>
|
|
19
|
+
)
|
|
20
|
+
});
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
describe('CopyCommand', () => {
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { useTranslation } from 'react-i18next';
|
|
2
|
-
|
|
3
|
-
import CheckIcon from '@mui/icons-material/Check';
|
|
4
|
-
import SaveIcon from '@mui/icons-material/Save';
|
|
5
|
-
|
|
6
|
-
interface Props {
|
|
7
|
-
labelLoading: string;
|
|
8
|
-
labelSave: string;
|
|
9
|
-
labelSucceeded: string;
|
|
10
|
-
loading: boolean;
|
|
11
|
-
succeeded: boolean;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const Content = ({
|
|
15
|
-
succeeded,
|
|
16
|
-
labelSucceeded,
|
|
17
|
-
labelSave,
|
|
18
|
-
loading,
|
|
19
|
-
labelLoading
|
|
20
|
-
}: Props): JSX.Element | string | null => {
|
|
21
|
-
const { t } = useTranslation();
|
|
22
|
-
|
|
23
|
-
if (loading) {
|
|
24
|
-
return t(labelLoading);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (succeeded) {
|
|
28
|
-
return labelSucceeded ? t(labelSucceeded) : <CheckIcon />;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return labelSave ? t(labelSave) : <SaveIcon />;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export default Content;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { T, always, cond, not, pipe, propEq } from 'ramda';
|
|
2
|
-
|
|
3
|
-
import CheckIcon from '@mui/icons-material/Check';
|
|
4
|
-
import SaveIcon from '@mui/icons-material/Save';
|
|
5
|
-
|
|
6
|
-
interface StartIconConfigProps {
|
|
7
|
-
hasLabel: boolean;
|
|
8
|
-
loading: boolean;
|
|
9
|
-
succeeded: boolean;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
interface Props {
|
|
13
|
-
startIconConfig: StartIconConfigProps;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const StartIcon = ({ startIconConfig }: Props): JSX.Element | null =>
|
|
17
|
-
cond<Array<StartIconConfigProps>, JSX.Element | null>([
|
|
18
|
-
[pipe(propEq(true, 'hasLabel'), not), always(null)],
|
|
19
|
-
[propEq(true, 'succeeded'), always(<CheckIcon />)],
|
|
20
|
-
[propEq(true, 'loading'), always(<SaveIcon />)],
|
|
21
|
-
[T, always(<SaveIcon />)]
|
|
22
|
-
])(startIconConfig);
|
|
23
|
-
|
|
24
|
-
export default StartIcon;
|