@centreon/ui 25.3.2 → 25.3.4
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/ActionsList/index.tsx +1 -0
- package/src/Button/Icon/index.tsx +3 -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/Chart/InteractiveComponents/Annotations/Annotation/index.tsx +1 -1
- package/src/Graph/Chart/helpers/index.ts +4 -3
- 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/Cell/index.tsx +26 -19
- package/src/Listing/Listing.cypress.spec.tsx +9 -11
- package/src/RichTextEditor/RichTextEditor.tsx +1 -1
- package/src/ThemeProvider/palettes.ts +2 -2
- package/src/api/customFetch.ts +0 -9
- package/src/api/useBulkResponse.ts +58 -0
- 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/components/CrudPage/Actions/Actions.styles.ts +15 -1
- package/src/components/CrudPage/Actions/Actions.tsx +7 -4
- package/src/components/CrudPage/Actions/Search.tsx +15 -14
- package/src/components/Header/PageHeader/PageHeader.styles.ts +5 -5
- package/src/components/Layout/PageLayout/PageLayout.styles.ts +1 -1
- package/src/index.ts +1 -0
- 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.4",
|
|
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()
|
|
@@ -19,6 +19,7 @@ const useStyles = makeStyles()((theme) => ({
|
|
|
19
19
|
|
|
20
20
|
type Props = {
|
|
21
21
|
ariaLabel?: string;
|
|
22
|
+
dataTestid?: string;
|
|
22
23
|
className?: string;
|
|
23
24
|
onClick: (event) => void;
|
|
24
25
|
title?: string | JSX.Element;
|
|
@@ -42,6 +43,7 @@ export const IconButton = ({
|
|
|
42
43
|
title = '',
|
|
43
44
|
ariaLabel,
|
|
44
45
|
className,
|
|
46
|
+
dataTestid,
|
|
45
47
|
tooltipPlacement,
|
|
46
48
|
tooltipClassName,
|
|
47
49
|
...props
|
|
@@ -59,7 +61,7 @@ export const IconButton = ({
|
|
|
59
61
|
aria-label={ariaLabel}
|
|
60
62
|
className={cx(classes.button, className)}
|
|
61
63
|
color="primary"
|
|
62
|
-
data-testid={ariaLabel}
|
|
64
|
+
data-testid={dataTestid || ariaLabel}
|
|
63
65
|
id={getNormalizedId(ariaLabel || '')}
|
|
64
66
|
{...props}
|
|
65
67
|
/>
|
|
@@ -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
|
});
|
|
@@ -43,7 +43,7 @@ const Annotation = ({
|
|
|
43
43
|
|
|
44
44
|
const setAnnotationHovered = useSetAtom(annotationHoveredAtom);
|
|
45
45
|
|
|
46
|
-
const content = `${truncate(event.content)} (${t(labelBy)} ${
|
|
46
|
+
const content = `${truncate({ content: event.content })} (${t(labelBy)} ${
|
|
47
47
|
event.contact?.name
|
|
48
48
|
})`;
|
|
49
49
|
|
|
@@ -38,9 +38,10 @@ export const getXAxisTickFormat = (graphInterval: GraphInterval): string => {
|
|
|
38
38
|
return gte(numberDays, 2) ? dateFormat : timeFormat;
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
export const truncate = (
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
export const truncate = ({
|
|
42
|
+
content,
|
|
43
|
+
maxLength = 180
|
|
44
|
+
}: { content?: string; maxLength?: number }): string => {
|
|
44
45
|
if (isNil(content)) {
|
|
45
46
|
return '';
|
|
46
47
|
}
|
|
@@ -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 => {
|
|
@@ -25,6 +25,18 @@ interface GetBackgroundColorProps extends Omit<Props, 'isRowHighlighted'> {
|
|
|
25
25
|
theme: Theme;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
interface StylesProps extends Props {
|
|
29
|
+
isRowHighlighted?: boolean;
|
|
30
|
+
listingVariant?: ListingVariant;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface GetRowHighlightStyleProps {
|
|
34
|
+
isRowHighlighted?: boolean;
|
|
35
|
+
theme: Theme;
|
|
36
|
+
disableRowCondition;
|
|
37
|
+
row;
|
|
38
|
+
}
|
|
39
|
+
|
|
28
40
|
const getBackgroundColor = ({
|
|
29
41
|
isRowHovered,
|
|
30
42
|
row,
|
|
@@ -51,25 +63,20 @@ const getBackgroundColor = ({
|
|
|
51
63
|
return 'unset';
|
|
52
64
|
};
|
|
53
65
|
|
|
54
|
-
|
|
55
|
-
isRowHighlighted?: boolean;
|
|
56
|
-
listingVariant?: ListingVariant;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
interface GetRowHighlightStyleProps {
|
|
60
|
-
isRowHighlighted?: boolean;
|
|
61
|
-
theme: Theme;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const getRowHighlightStyle = ({
|
|
66
|
+
const getRowTextColor = ({
|
|
65
67
|
isRowHighlighted,
|
|
66
|
-
theme
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
theme,
|
|
69
|
+
disableRowCondition,
|
|
70
|
+
row
|
|
71
|
+
}: GetRowHighlightStyleProps): CSSObject | undefined => {
|
|
72
|
+
if (isRowHighlighted) {
|
|
73
|
+
return { color: theme.palette.text.primary };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (disableRowCondition(row)) {
|
|
77
|
+
return { color: alpha(theme.palette.text.secondary, 0.5) };
|
|
78
|
+
}
|
|
79
|
+
};
|
|
73
80
|
|
|
74
81
|
const useStyles = makeStyles<StylesProps>()(
|
|
75
82
|
(
|
|
@@ -112,7 +119,7 @@ const useStyles = makeStyles<StylesProps>()(
|
|
|
112
119
|
height: '100%',
|
|
113
120
|
overflow: 'hidden',
|
|
114
121
|
...getTextStyleByViewMode({ listingVariant, theme }),
|
|
115
|
-
p:
|
|
122
|
+
p: getRowTextColor({ isRowHighlighted, disableRowCondition, row, theme }),
|
|
116
123
|
padding: theme.spacing(0, 1),
|
|
117
124
|
whiteSpace: 'nowrap'
|
|
118
125
|
}
|
|
@@ -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';
|
|
@@ -211,7 +211,7 @@ export const lightPalette: PaletteOptions = {
|
|
|
211
211
|
default: '#696969'
|
|
212
212
|
}
|
|
213
213
|
},
|
|
214
|
-
border: '#
|
|
214
|
+
border: '#EDEDED',
|
|
215
215
|
description: '#4A4A4A',
|
|
216
216
|
title: '#000000'
|
|
217
217
|
}
|
|
@@ -353,7 +353,7 @@ export const darkPalette: PaletteOptions = {
|
|
|
353
353
|
default: '#696969'
|
|
354
354
|
}
|
|
355
355
|
},
|
|
356
|
-
border: '#
|
|
356
|
+
border: '#666666',
|
|
357
357
|
description: '#bdbdbd',
|
|
358
358
|
title: '#fff'
|
|
359
359
|
}
|
package/src/api/customFetch.ts
CHANGED
|
@@ -95,15 +95,6 @@ export const customFetch = <T>({
|
|
|
95
95
|
};
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
if (equals(response.status, 207)) {
|
|
99
|
-
return {
|
|
100
|
-
data: data.results,
|
|
101
|
-
isError: false,
|
|
102
|
-
message: '',
|
|
103
|
-
statusCode: response.status
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
|
|
107
98
|
if (decoder) {
|
|
108
99
|
return decoder.decodeToPromise(data).catch((error: string) => {
|
|
109
100
|
catchError({
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {
|
|
2
|
+
complement,
|
|
3
|
+
includes,
|
|
4
|
+
isEmpty,
|
|
5
|
+
isNil,
|
|
6
|
+
last,
|
|
7
|
+
length,
|
|
8
|
+
prop,
|
|
9
|
+
propEq,
|
|
10
|
+
split
|
|
11
|
+
} from 'ramda';
|
|
12
|
+
import useSnackbar from '../Snackbar/useSnackbar';
|
|
13
|
+
|
|
14
|
+
const useBulkResponse = () => {
|
|
15
|
+
const { showSuccessMessage, showErrorMessage, showWarningMessage } =
|
|
16
|
+
useSnackbar();
|
|
17
|
+
|
|
18
|
+
const handleBulkResponse = ({
|
|
19
|
+
data,
|
|
20
|
+
labelSuccess,
|
|
21
|
+
labelWarning,
|
|
22
|
+
labelFailed,
|
|
23
|
+
items
|
|
24
|
+
}) => {
|
|
25
|
+
const successfullResponses =
|
|
26
|
+
data?.filter(propEq(204, 'status')) || isNil(data);
|
|
27
|
+
|
|
28
|
+
const failedResponses = data?.filter(complement(propEq(204, 'status')));
|
|
29
|
+
|
|
30
|
+
const failedResponsesIds = failedResponses
|
|
31
|
+
?.map(prop('href'))
|
|
32
|
+
?.map((item: string) =>
|
|
33
|
+
Number.parseInt(last(split('/', item || '')) as string, 10)
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
if (isEmpty(successfullResponses)) {
|
|
37
|
+
showErrorMessage(labelFailed);
|
|
38
|
+
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (length(successfullResponses) < length(data)) {
|
|
43
|
+
const failedResponsesNames = items
|
|
44
|
+
?.filter((item) => includes(item.id, failedResponsesIds))
|
|
45
|
+
.map((item) => item.name);
|
|
46
|
+
|
|
47
|
+
showWarningMessage(`${labelWarning}: ${failedResponsesNames.join(', ')}`);
|
|
48
|
+
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
showSuccessMessage(labelSuccess);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
return handleBulkResponse;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export default useBulkResponse;
|
|
@@ -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', () => {
|
|
@@ -2,7 +2,21 @@ import { makeStyles } from 'tss-react/mui';
|
|
|
2
2
|
|
|
3
3
|
export const useActionsStyles = makeStyles()((theme) => ({
|
|
4
4
|
search: {
|
|
5
|
-
maxWidth: theme.spacing(
|
|
5
|
+
maxWidth: theme.spacing(60),
|
|
6
|
+
minWidth: theme.spacing(20),
|
|
7
|
+
width: '100%'
|
|
8
|
+
},
|
|
9
|
+
filters: {
|
|
10
|
+
width: '100%',
|
|
11
|
+
paddingInline: theme.spacing(1),
|
|
12
|
+
display: 'flex',
|
|
13
|
+
alignItems: 'center',
|
|
14
|
+
justifyContent: 'center'
|
|
15
|
+
},
|
|
16
|
+
actions: {
|
|
17
|
+
display: 'grid',
|
|
18
|
+
gridTemplateColumns: 'min-content auto',
|
|
19
|
+
gap: theme.spacing(1)
|
|
6
20
|
},
|
|
7
21
|
clearButton: {
|
|
8
22
|
alignSelf: 'flex-start'
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Box } from '@mui/material';
|
|
2
|
+
import { useActionsStyles } from './Actions.styles';
|
|
2
3
|
import AddButton from './AddButton';
|
|
3
4
|
import Search from './Search';
|
|
4
5
|
|
|
@@ -11,12 +12,14 @@ interface Props {
|
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
const Actions = ({ labels, filters }: Props): JSX.Element => {
|
|
15
|
+
const { classes } = useActionsStyles();
|
|
16
|
+
|
|
14
17
|
return (
|
|
15
|
-
<Box
|
|
16
|
-
sx={{ display: 'grid', gridTemplateColumns: 'min-content auto', gap: 2 }}
|
|
17
|
-
>
|
|
18
|
+
<Box className={classes.actions}>
|
|
18
19
|
<AddButton label={labels.add} />
|
|
19
|
-
<
|
|
20
|
+
<div className={classes.filters}>
|
|
21
|
+
<Search label={labels.search} filters={filters} />
|
|
22
|
+
</div>
|
|
20
23
|
</Box>
|
|
21
24
|
);
|
|
22
25
|
};
|
|
@@ -14,21 +14,22 @@ const Search = ({ label, filters }: Props): JSX.Element => {
|
|
|
14
14
|
const { change } = useSearch();
|
|
15
15
|
|
|
16
16
|
return (
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
17
|
+
<div className={classes.search}>
|
|
18
|
+
<SearchField
|
|
19
|
+
debounced
|
|
20
|
+
fullWidth
|
|
21
|
+
dataTestId={label}
|
|
22
|
+
placeholder={label}
|
|
23
|
+
onChange={change}
|
|
24
|
+
textFieldSlotsAndSlotProps={{
|
|
25
|
+
slotProps: {
|
|
26
|
+
input: {
|
|
27
|
+
endAdornment: <Filters label="filters" filters={filters} />
|
|
28
|
+
}
|
|
28
29
|
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
}}
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
32
33
|
);
|
|
33
34
|
};
|
|
34
35
|
|
|
@@ -25,9 +25,10 @@ const useStyles = makeStyles()((theme) => ({
|
|
|
25
25
|
},
|
|
26
26
|
pageHeader: {
|
|
27
27
|
alignItems: 'center',
|
|
28
|
-
borderBottom: `
|
|
28
|
+
borderBottom: `2px solid ${theme.palette.header.page.border}`,
|
|
29
29
|
display: 'flex',
|
|
30
|
-
gap: theme.spacing(4)
|
|
30
|
+
gap: theme.spacing(4),
|
|
31
|
+
paddingBottom: theme.spacing(0.5)
|
|
31
32
|
},
|
|
32
33
|
pageHeaderActions: {
|
|
33
34
|
'& > button': {
|
|
@@ -46,8 +47,7 @@ const useStyles = makeStyles()((theme) => ({
|
|
|
46
47
|
pageHeaderMain: {
|
|
47
48
|
display: 'flex',
|
|
48
49
|
flexGrow: 1,
|
|
49
|
-
gap: theme.spacing(1)
|
|
50
|
-
minHeight: theme.spacing(4.5)
|
|
50
|
+
gap: theme.spacing(1)
|
|
51
51
|
},
|
|
52
52
|
pageHeaderMenu: {
|
|
53
53
|
alignItems: 'flex-start',
|
|
@@ -96,7 +96,7 @@ const useStyles = makeStyles()((theme) => ({
|
|
|
96
96
|
alignSelf: 'flex-start',
|
|
97
97
|
h1: {
|
|
98
98
|
...theme.typography.h5,
|
|
99
|
-
fontWeight: theme.typography.
|
|
99
|
+
fontWeight: theme.typography.fontWeightBold,
|
|
100
100
|
margin: theme.spacing(0),
|
|
101
101
|
lineHeight: '1'
|
|
102
102
|
}
|
|
@@ -29,7 +29,7 @@ export const useStyles = makeStyles()((theme) => ({
|
|
|
29
29
|
display: 'grid',
|
|
30
30
|
gridTemplateRows: 'auto',
|
|
31
31
|
overflow: 'hidden',
|
|
32
|
-
padding: theme.spacing(
|
|
32
|
+
padding: theme.spacing(0, 3, 1.5)
|
|
33
33
|
},
|
|
34
34
|
pageLayoutHeader: {
|
|
35
35
|
'[data-variant="fixed-header"] &': {
|
package/src/index.ts
CHANGED
|
@@ -133,6 +133,7 @@ export {
|
|
|
133
133
|
} from './api/useGraphQuery';
|
|
134
134
|
export { WidgetResourceType as ResourceType } from './api/useGraphQuery/models';
|
|
135
135
|
export { default as QueryProvider, client } from './api/QueryProvider';
|
|
136
|
+
export { default as useBulkResponse } from './api/useBulkResponse';
|
|
136
137
|
export {
|
|
137
138
|
default as FileDropZone,
|
|
138
139
|
transformFileListToArray
|
|
@@ -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;
|