@centreon/ui 23.10.1-sync-dev-23-10-x-develop-oss.0 → 23.10.1-sync-release-34346.0
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 +6 -1
- package/public/mockServiceWorker.js +2 -2
- package/src/Form/Inputs/ConnectedAutocomplete.tsx +3 -1
- package/src/Form/Inputs/models.ts +1 -0
- package/src/Graph/Gauge/Gauge.stories.tsx +15 -2
- package/src/Graph/HeatMap/HeatMap.stories.tsx +105 -0
- package/src/Graph/HeatMap/HeatMap.styles.tsx +29 -0
- package/src/Graph/HeatMap/HeatMap.tsx +12 -0
- package/src/Graph/HeatMap/HeatMapData.json +137 -0
- package/src/Graph/HeatMap/ResponsiveHeatMap.tsx +98 -0
- package/src/Graph/HeatMap/index.ts +1 -0
- package/src/Graph/HeatMap/model.ts +33 -0
- package/src/Graph/LineChart/BasicComponents/Lines/RegularLines/index.tsx +1 -1
- package/src/Graph/LineChart/BasicComponents/useFilterLines.ts +2 -4
- package/src/Graph/LineChart/Legend/InteractiveValue.tsx +3 -3
- package/src/Graph/LineChart/Legend/Legend.styles.ts +78 -32
- package/src/Graph/LineChart/Legend/LegendContent.tsx +12 -6
- package/src/Graph/LineChart/Legend/LegendHeader.tsx +69 -21
- package/src/Graph/LineChart/Legend/index.tsx +51 -23
- package/src/Graph/LineChart/Legend/models.ts +5 -0
- package/src/Graph/LineChart/Legend/useLegend.ts +9 -10
- package/src/Graph/LineChart/LineChart.tsx +17 -3
- package/src/Graph/index.ts +1 -0
- package/src/InputField/Select/Autocomplete/Connected/Multi/index.test.tsx +1 -0
- package/src/InputField/Select/Autocomplete/Connected/index.test.tsx +1 -0
- package/src/InputField/Select/Autocomplete/Connected/index.tsx +15 -3
- package/src/InputField/Text/index.tsx +6 -1
- package/src/Module/LicensedModule/LicenseCheck/index.tsx +24 -9
- package/src/Module/LicensedModule/index.tsx +7 -1
- package/src/RichTextEditor/RichTextEditor.cypress.spec.tsx +100 -52
- package/src/RichTextEditor/RichTextEditor.tsx +9 -3
- package/src/RichTextEditor/plugins/ToolbarPlugin/AlignPicker.tsx +21 -20
- package/src/RichTextEditor/plugins/ToolbarPlugin/BlockButtons.tsx +35 -77
- package/src/RichTextEditor/plugins/ToolbarPlugin/FormatButtons.tsx +29 -83
- package/src/RichTextEditor/plugins/ToolbarPlugin/LinkButton.tsx +106 -0
- package/src/RichTextEditor/plugins/ToolbarPlugin/ListButton.tsx +155 -0
- package/src/RichTextEditor/plugins/ToolbarPlugin/MacrosButton.tsx +23 -39
- package/src/RichTextEditor/plugins/ToolbarPlugin/ToolbarPlugin.styles.ts +24 -14
- package/src/RichTextEditor/plugins/ToolbarPlugin/UndoRedoButtons.tsx +6 -0
- package/src/RichTextEditor/plugins/ToolbarPlugin/index.tsx +5 -10
- package/src/RichTextEditor/translatedLabels.ts +3 -0
- package/src/ThemeProvider/palettes.ts +4 -4
- package/src/Typography/EllipsisTypography.tsx +18 -0
- package/src/Typography/Subtitle.tsx +55 -0
- package/src/api/buildListingEndpoint/models.ts +2 -1
- package/src/api/customFetch.ts +12 -3
- package/src/api/useFetchQuery/index.ts +22 -5
- package/src/api/useGraphQuery/index.ts +4 -1
- package/src/api/useMutationQuery/index.ts +12 -2
- package/src/components/Form/AccessRightsV2/AccessRights.cypress.spec.tsx +350 -0
- package/src/components/Form/AccessRightsV2/AccessRights.stories.tsx +119 -0
- package/src/components/Form/AccessRightsV2/AccessRights.styles.ts +10 -0
- package/src/components/Form/AccessRightsV2/AccessRights.tsx +60 -0
- package/src/components/Form/AccessRightsV2/Actions/Actions.styles.ts +14 -0
- package/src/components/Form/AccessRightsV2/Actions/Actions.tsx +81 -0
- package/src/components/Form/AccessRightsV2/Actions/useActions.ts +79 -0
- package/src/components/Form/AccessRightsV2/List/Item.tsx +90 -0
- package/src/components/Form/AccessRightsV2/List/List.styles.tsx +45 -0
- package/src/components/Form/AccessRightsV2/List/List.tsx +52 -0
- package/src/components/Form/AccessRightsV2/List/ListItemSkeleton.tsx +18 -0
- package/src/components/Form/AccessRightsV2/List/ListSkeleton.tsx +22 -0
- package/src/components/Form/AccessRightsV2/List/RemoveAccessRight.tsx +38 -0
- package/src/components/Form/AccessRightsV2/List/StateChip.tsx +28 -0
- package/src/components/Form/AccessRightsV2/List/useItem.ts +64 -0
- package/src/components/Form/AccessRightsV2/Provider.tsx +15 -0
- package/src/components/Form/AccessRightsV2/ShareInput/ContactSwitch.tsx +42 -0
- package/src/components/Form/AccessRightsV2/ShareInput/ShareInput.styles.ts +9 -0
- package/src/components/Form/AccessRightsV2/ShareInput/ShareInput.tsx +77 -0
- package/src/components/Form/AccessRightsV2/ShareInput/useShareInput.tsx +109 -0
- package/src/components/Form/AccessRightsV2/Stats/Stats.tsx +36 -0
- package/src/components/Form/AccessRightsV2/atoms.ts +97 -0
- package/src/components/Form/AccessRightsV2/common/RoleSelectField.styles.tsx +7 -0
- package/src/components/Form/AccessRightsV2/common/RoleSelectField.tsx +45 -0
- package/src/components/Form/AccessRightsV2/models.ts +54 -0
- package/src/components/Form/AccessRightsV2/storiesData.ts +221 -0
- package/src/components/Form/AccessRightsV2/useAccessRightsInitValues.ts +51 -0
- package/src/components/Form/index.ts +1 -0
- package/src/components/Header/PageHeader/PageHeader.styles.ts +28 -1
- package/src/components/Header/PageHeader/PageHeaderMessage.tsx +32 -0
- package/src/components/Header/PageHeader/index.ts +2 -0
- package/src/components/ItemComposition/Item.tsx +2 -2
- package/src/components/ItemComposition/ItemComposition.styles.ts +3 -0
- package/src/components/ItemComposition/ItemComposition.tsx +4 -2
- package/src/components/List/Item/ListItem.styles.ts +6 -0
- package/src/components/List/Item/ListItem.tsx +3 -1
- package/src/components/List/Item/Text.tsx +5 -3
- package/src/components/Menu/Button/MenuButton.tsx +4 -2
- package/src/components/Menu/MenuItem.tsx +5 -3
- package/src/components/Menu/MenuItems.tsx +4 -3
- package/src/components/Modal/Modal.styles.ts +4 -2
- package/src/index.ts +5 -0
- package/src/utils/useInfiniteScrollListing.ts +22 -7
- package/src/utils/useLocaleDateTimeFormat/index.ts +3 -0
- package/src/Graph/LineChart/Legend/Marker.tsx +0 -43
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Box, Typography, TypographyProps } from '@mui/material';
|
|
2
|
+
|
|
3
|
+
const EllipsisTypography = (props: TypographyProps): JSX.Element => {
|
|
4
|
+
return (
|
|
5
|
+
<Box sx={{ width: '100%' }}>
|
|
6
|
+
<Typography
|
|
7
|
+
sx={{
|
|
8
|
+
overflow: 'hidden',
|
|
9
|
+
textOverflow: 'ellipsis',
|
|
10
|
+
whiteSpace: 'nowrap'
|
|
11
|
+
}}
|
|
12
|
+
{...props}
|
|
13
|
+
/>
|
|
14
|
+
</Box>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default EllipsisTypography;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import { type, equals } from 'ramda';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
|
|
6
|
+
import { Typography } from '@mui/material';
|
|
7
|
+
import HelpOutlineIcon from '@mui/icons-material/HelpOutline';
|
|
8
|
+
|
|
9
|
+
import { Tooltip } from '../components';
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
secondaryLabel?: string | Array<string>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const Subtitle = ({ children, secondaryLabel }: Props): JSX.Element => {
|
|
17
|
+
const { t } = useTranslation();
|
|
18
|
+
|
|
19
|
+
const containsSeveralSecondaryLabels = equals(type(secondaryLabel), 'Array');
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<Typography variant="subtitle1">
|
|
23
|
+
<strong>{children}</strong>
|
|
24
|
+
{secondaryLabel && (
|
|
25
|
+
<Tooltip
|
|
26
|
+
aria-label={
|
|
27
|
+
containsSeveralSecondaryLabels
|
|
28
|
+
? secondaryLabel[0]
|
|
29
|
+
: (secondaryLabel as string)
|
|
30
|
+
}
|
|
31
|
+
followCursor={false}
|
|
32
|
+
label={
|
|
33
|
+
containsSeveralSecondaryLabels ? (
|
|
34
|
+
<>
|
|
35
|
+
{secondaryLabel.map((label) => (
|
|
36
|
+
<p key={label}>{t(label)}</p>
|
|
37
|
+
))}
|
|
38
|
+
</>
|
|
39
|
+
) : (
|
|
40
|
+
t(secondaryLabel)
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
placement="right"
|
|
44
|
+
>
|
|
45
|
+
<HelpOutlineIcon
|
|
46
|
+
color="primary"
|
|
47
|
+
sx={{ ml: 1, verticalAlign: 'middle' }}
|
|
48
|
+
/>
|
|
49
|
+
</Tooltip>
|
|
50
|
+
)}
|
|
51
|
+
</Typography>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default Subtitle;
|
package/src/api/customFetch.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { equals } from 'ramda';
|
|
1
|
+
import { equals, isNil, startsWith } from 'ramda';
|
|
2
2
|
import { JsonDecoder } from 'ts.data.json';
|
|
3
3
|
|
|
4
4
|
import { Method } from './useMutationQuery';
|
|
@@ -22,6 +22,7 @@ export interface CatchErrorProps {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
interface CustomFetchProps<T> {
|
|
25
|
+
baseEndpoint?: string;
|
|
25
26
|
catchError?: (props: CatchErrorProps) => void;
|
|
26
27
|
decoder?: JsonDecoder.Decoder<T>;
|
|
27
28
|
defaultFailureMessage?: string;
|
|
@@ -42,10 +43,18 @@ export const customFetch = <T>({
|
|
|
42
43
|
defaultFailureMessage = 'Something went wrong',
|
|
43
44
|
isMutation = false,
|
|
44
45
|
payload,
|
|
45
|
-
method = 'GET'
|
|
46
|
+
method = 'GET',
|
|
47
|
+
baseEndpoint = './api/latest'
|
|
46
48
|
}: CustomFetchProps<T>): Promise<T | ResponseError> => {
|
|
47
49
|
const defaultOptions = { headers, method, signal };
|
|
48
50
|
|
|
51
|
+
const formattedEndpoint =
|
|
52
|
+
!isNil(baseEndpoint) &&
|
|
53
|
+
!startsWith(baseEndpoint, endpoint) &&
|
|
54
|
+
!startsWith('./api/internal.php', endpoint)
|
|
55
|
+
? `${baseEndpoint}${endpoint}`
|
|
56
|
+
: endpoint;
|
|
57
|
+
|
|
49
58
|
const options = isMutation
|
|
50
59
|
? {
|
|
51
60
|
...defaultOptions,
|
|
@@ -53,7 +62,7 @@ export const customFetch = <T>({
|
|
|
53
62
|
}
|
|
54
63
|
: defaultOptions;
|
|
55
64
|
|
|
56
|
-
return fetch(
|
|
65
|
+
return fetch(formattedEndpoint, options)
|
|
57
66
|
.then((response) => {
|
|
58
67
|
if (equals(response.status, 204)) {
|
|
59
68
|
return {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useMemo } from 'react';
|
|
1
|
+
import { useEffect, useMemo, useRef } from 'react';
|
|
2
2
|
|
|
3
3
|
import 'ulog';
|
|
4
4
|
import {
|
|
@@ -10,16 +10,18 @@ import {
|
|
|
10
10
|
} from '@tanstack/react-query';
|
|
11
11
|
import { JsonDecoder } from 'ts.data.json';
|
|
12
12
|
import anylogger from 'anylogger';
|
|
13
|
-
import { has, includes, not, omit } from 'ramda';
|
|
13
|
+
import { has, includes, isNil, not, omit } from 'ramda';
|
|
14
14
|
|
|
15
15
|
import { CatchErrorProps, customFetch, ResponseError } from '../customFetch';
|
|
16
16
|
import useSnackbar from '../../Snackbar/useSnackbar';
|
|
17
17
|
import { useDeepCompare } from '../../utils';
|
|
18
18
|
|
|
19
19
|
export interface UseFetchQueryProps<T> {
|
|
20
|
+
baseEndpoint?: string;
|
|
20
21
|
catchError?: (props: CatchErrorProps) => void;
|
|
21
22
|
decoder?: JsonDecoder.Decoder<T>;
|
|
22
23
|
defaultFailureMessage?: string;
|
|
24
|
+
doNotCancelCallsOnUnmount?: boolean;
|
|
23
25
|
fetchHeaders?: HeadersInit;
|
|
24
26
|
getEndpoint: (params?: PrefetchEndpointParams) => string;
|
|
25
27
|
getQueryKey: () => QueryKey;
|
|
@@ -54,14 +56,19 @@ const useFetchQuery = <T extends object>({
|
|
|
54
56
|
fetchHeaders,
|
|
55
57
|
isPaginated,
|
|
56
58
|
queryOptions,
|
|
57
|
-
httpCodesBypassErrorSnackbar = []
|
|
59
|
+
httpCodesBypassErrorSnackbar = [],
|
|
60
|
+
baseEndpoint,
|
|
61
|
+
doNotCancelCallsOnUnmount = false
|
|
58
62
|
}: UseFetchQueryProps<T>): UseFetchQueryState<T> => {
|
|
63
|
+
const dataRef = useRef<T | undefined>(undefined);
|
|
64
|
+
|
|
59
65
|
const { showErrorMessage } = useSnackbar();
|
|
60
66
|
|
|
61
67
|
const queryData = useQuery<T | ResponseError, Error>(
|
|
62
68
|
getQueryKey(),
|
|
63
69
|
({ signal }): Promise<T | ResponseError> =>
|
|
64
70
|
customFetch<T>({
|
|
71
|
+
baseEndpoint,
|
|
65
72
|
catchError,
|
|
66
73
|
decoder,
|
|
67
74
|
defaultFailureMessage,
|
|
@@ -96,6 +103,7 @@ const useFetchQuery = <T extends object>({
|
|
|
96
103
|
queryKey,
|
|
97
104
|
({ signal }): Promise<T | ResponseError> =>
|
|
98
105
|
customFetch<T>({
|
|
106
|
+
baseEndpoint,
|
|
99
107
|
catchError,
|
|
100
108
|
decoder,
|
|
101
109
|
defaultFailureMessage,
|
|
@@ -137,6 +145,7 @@ const useFetchQuery = <T extends object>({
|
|
|
137
145
|
getQueryKey(),
|
|
138
146
|
({ signal }): Promise<T | ResponseError> =>
|
|
139
147
|
customFetch<T>({
|
|
148
|
+
baseEndpoint,
|
|
140
149
|
catchError,
|
|
141
150
|
decoder,
|
|
142
151
|
defaultFailureMessage,
|
|
@@ -153,10 +162,18 @@ const useFetchQuery = <T extends object>({
|
|
|
153
162
|
[queryData.data]
|
|
154
163
|
);
|
|
155
164
|
|
|
165
|
+
if (!isNil(data)) {
|
|
166
|
+
dataRef.current = data;
|
|
167
|
+
}
|
|
168
|
+
|
|
156
169
|
const errorData = queryData.data as ResponseError | undefined;
|
|
157
170
|
|
|
158
171
|
useEffect(() => {
|
|
159
172
|
return (): void => {
|
|
173
|
+
if (doNotCancelCallsOnUnmount) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
160
177
|
queryClient.cancelQueries(getQueryKey());
|
|
161
178
|
};
|
|
162
179
|
}, []);
|
|
@@ -166,8 +183,8 @@ const useFetchQuery = <T extends object>({
|
|
|
166
183
|
}, useDeepCompare([queryData.data]));
|
|
167
184
|
|
|
168
185
|
return {
|
|
169
|
-
...omit(['data'], queryData),
|
|
170
|
-
data,
|
|
186
|
+
...omit(['data', 'error'], queryData),
|
|
187
|
+
data: dataRef.current,
|
|
171
188
|
error: errorData?.isError ? omit(['isError'], errorData) : null,
|
|
172
189
|
fetchQuery,
|
|
173
190
|
prefetchNextPage,
|
|
@@ -92,6 +92,9 @@ const useGraphQuery = ({
|
|
|
92
92
|
: getStartEndFromTimePeriod(timePeriodToUse as number);
|
|
93
93
|
|
|
94
94
|
const definedMetrics = metrics.filter((metric) => metric);
|
|
95
|
+
const formattedDefinedMetrics = definedMetrics.map((metric) =>
|
|
96
|
+
encodeURIComponent(metric)
|
|
97
|
+
);
|
|
95
98
|
|
|
96
99
|
const {
|
|
97
100
|
data: graphData,
|
|
@@ -115,7 +118,7 @@ const useGraphQuery = ({
|
|
|
115
118
|
|
|
116
119
|
return `${endpoint}&start=${startAndEnd.start}&end=${
|
|
117
120
|
startAndEnd.end
|
|
118
|
-
}&metric_names=[${
|
|
121
|
+
}&metric_names=[${formattedDefinedMetrics.join(',')}]`;
|
|
119
122
|
},
|
|
120
123
|
getQueryKey: () => [
|
|
121
124
|
'graph',
|
|
@@ -23,6 +23,7 @@ export enum Method {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export type UseMutationQueryProps<T, TMeta> = {
|
|
26
|
+
baseEndpoint?: string;
|
|
26
27
|
catchError?: (props: CatchErrorProps) => void;
|
|
27
28
|
decoder?: JsonDecoder.Decoder<T>;
|
|
28
29
|
defaultFailureMessage?: string;
|
|
@@ -49,7 +50,8 @@ const useMutationQuery = <T extends object, TMeta>({
|
|
|
49
50
|
method,
|
|
50
51
|
onMutate,
|
|
51
52
|
onError,
|
|
52
|
-
onSuccess
|
|
53
|
+
onSuccess,
|
|
54
|
+
baseEndpoint
|
|
53
55
|
}: UseMutationQueryProps<T, TMeta>): UseMutationQueryState<T> => {
|
|
54
56
|
const { showErrorMessage } = useSnackbar();
|
|
55
57
|
|
|
@@ -62,6 +64,7 @@ const useMutationQuery = <T extends object, TMeta>({
|
|
|
62
64
|
const { _meta, ...payload } = _payload || {};
|
|
63
65
|
|
|
64
66
|
return customFetch<T>({
|
|
67
|
+
baseEndpoint,
|
|
65
68
|
catchError,
|
|
66
69
|
decoder,
|
|
67
70
|
defaultFailureMessage,
|
|
@@ -78,7 +81,14 @@ const useMutationQuery = <T extends object, TMeta>({
|
|
|
78
81
|
{
|
|
79
82
|
onError,
|
|
80
83
|
onMutate,
|
|
81
|
-
onSuccess
|
|
84
|
+
onSuccess: (data, variables, context) => {
|
|
85
|
+
if (data?.isError) {
|
|
86
|
+
onError?.(data, variables, context);
|
|
87
|
+
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
onSuccess?.(data, variables, context);
|
|
91
|
+
}
|
|
82
92
|
}
|
|
83
93
|
);
|
|
84
94
|
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import { Provider, createStore } from 'jotai';
|
|
2
|
+
|
|
3
|
+
import { Method, SnackbarProvider, TestQueryProvider } from '../../..';
|
|
4
|
+
|
|
5
|
+
import { AccessRights } from './AccessRights';
|
|
6
|
+
import {
|
|
7
|
+
buildResult,
|
|
8
|
+
emptyAccessRights,
|
|
9
|
+
labels,
|
|
10
|
+
removedAccessRights,
|
|
11
|
+
roles,
|
|
12
|
+
simpleAccessRights,
|
|
13
|
+
updatedAccessRights
|
|
14
|
+
} from './storiesData';
|
|
15
|
+
|
|
16
|
+
const initialize = ({
|
|
17
|
+
initialValues = simpleAccessRights,
|
|
18
|
+
loading = false,
|
|
19
|
+
link = 'link'
|
|
20
|
+
}): unknown => {
|
|
21
|
+
const cancel = cy.stub();
|
|
22
|
+
const save = cy.stub();
|
|
23
|
+
|
|
24
|
+
cy.interceptAPIRequest({
|
|
25
|
+
alias: 'getContacts',
|
|
26
|
+
method: Method.GET,
|
|
27
|
+
path: '**/contacts?**',
|
|
28
|
+
response: buildResult(false)
|
|
29
|
+
});
|
|
30
|
+
cy.interceptAPIRequest({
|
|
31
|
+
alias: 'getContactGroups',
|
|
32
|
+
method: Method.GET,
|
|
33
|
+
path: '**/contact-groups?**',
|
|
34
|
+
response: buildResult(true)
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
cy.mount({
|
|
38
|
+
Component: (
|
|
39
|
+
<SnackbarProvider>
|
|
40
|
+
<TestQueryProvider>
|
|
41
|
+
<Provider store={createStore()}>
|
|
42
|
+
<AccessRights
|
|
43
|
+
cancel={cancel}
|
|
44
|
+
endpoints={{
|
|
45
|
+
contact: '/contacts',
|
|
46
|
+
contactGroup: '/contact-groups'
|
|
47
|
+
}}
|
|
48
|
+
initialValues={initialValues}
|
|
49
|
+
labels={labels}
|
|
50
|
+
link={link}
|
|
51
|
+
loading={loading}
|
|
52
|
+
roles={roles}
|
|
53
|
+
submit={save}
|
|
54
|
+
/>
|
|
55
|
+
</Provider>
|
|
56
|
+
</TestQueryProvider>
|
|
57
|
+
</SnackbarProvider>
|
|
58
|
+
)
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
cancel,
|
|
63
|
+
save
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
describe('Access rights', () => {
|
|
68
|
+
it('displays the access rights in loading state', () => {
|
|
69
|
+
initialize({ loading: true });
|
|
70
|
+
|
|
71
|
+
cy.contains('Share dashboard with').should('be.visible');
|
|
72
|
+
cy.contains('Contact').should('be.visible');
|
|
73
|
+
cy.contains('Contact group').should('be.visible');
|
|
74
|
+
cy.findByLabelText('Add a contact').should('be.visible');
|
|
75
|
+
cy.findByTestId('add_role').should('be.disabled');
|
|
76
|
+
cy.findByTestId('add').should('be.disabled');
|
|
77
|
+
cy.findByLabelText('Copy link').should('be.visible');
|
|
78
|
+
cy.findByLabelText('Cancel').should('be.visible');
|
|
79
|
+
cy.findByLabelText('Save').should('be.visible');
|
|
80
|
+
|
|
81
|
+
cy.makeSnapshot();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('displays the access rights without link', () => {
|
|
85
|
+
initialize({ link: null });
|
|
86
|
+
|
|
87
|
+
cy.findByLabelText('Copy link').should('not.exist');
|
|
88
|
+
|
|
89
|
+
cy.makeSnapshot();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('displays the access rights with an empty list', () => {
|
|
93
|
+
initialize({ initialValues: emptyAccessRights });
|
|
94
|
+
|
|
95
|
+
cy.contains('The contact list is empty').should('be.visible');
|
|
96
|
+
|
|
97
|
+
cy.makeSnapshot();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('displays the access rights with an empty list', () => {
|
|
101
|
+
initialize({});
|
|
102
|
+
|
|
103
|
+
simpleAccessRights.forEach(({ name, email, isContactGroup, role }) => {
|
|
104
|
+
cy.contains(name).should('be.visible');
|
|
105
|
+
cy.contains(email).should('be.visible');
|
|
106
|
+
cy.get(`[data-groupChip="${name}"]`).should(
|
|
107
|
+
isContactGroup ? 'be.visible' : 'not.exist'
|
|
108
|
+
);
|
|
109
|
+
cy.findByTestId(`role-${name}`).should('have.value', role);
|
|
110
|
+
cy.findByTestId(`remove-${name}`).should('be.visible');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
cy.makeSnapshot();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('displays a removed chip when the corresponding icon is clicked', () => {
|
|
117
|
+
initialize({});
|
|
118
|
+
|
|
119
|
+
cy.findByTestId(`remove-Leah McGlynn`).should(
|
|
120
|
+
'have.attr',
|
|
121
|
+
'data-removed',
|
|
122
|
+
'false'
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
cy.findByTestId(`remove-Leah McGlynn`).click();
|
|
126
|
+
|
|
127
|
+
cy.findByTestId(`remove-Leah McGlynn`).should(
|
|
128
|
+
'have.attr',
|
|
129
|
+
'data-removed',
|
|
130
|
+
'true'
|
|
131
|
+
);
|
|
132
|
+
cy.contains(labels.list.removed).should('be.visible');
|
|
133
|
+
|
|
134
|
+
cy.makeSnapshot();
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('restores the contact when the contact is removed and the corresponding icon is clicked', () => {
|
|
138
|
+
initialize({});
|
|
139
|
+
|
|
140
|
+
cy.findByTestId(`remove-Leah McGlynn`).click();
|
|
141
|
+
|
|
142
|
+
cy.findByTestId(`remove-Leah McGlynn`).should(
|
|
143
|
+
'have.attr',
|
|
144
|
+
'data-removed',
|
|
145
|
+
'true'
|
|
146
|
+
);
|
|
147
|
+
cy.contains(labels.list.removed).should('be.visible');
|
|
148
|
+
|
|
149
|
+
cy.findByTestId(`remove-Leah McGlynn`).click();
|
|
150
|
+
|
|
151
|
+
cy.findByTestId(`remove-Leah McGlynn`).should(
|
|
152
|
+
'have.attr',
|
|
153
|
+
'data-removed',
|
|
154
|
+
'false'
|
|
155
|
+
);
|
|
156
|
+
cy.contains(labels.list.removed).should('not.exist');
|
|
157
|
+
|
|
158
|
+
cy.makeSnapshot();
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('submits the new acces rights list without the removed contact', () => {
|
|
162
|
+
const { save } = initialize({});
|
|
163
|
+
|
|
164
|
+
cy.findByTestId(`remove-Leah McGlynn`).click();
|
|
165
|
+
|
|
166
|
+
cy.findByTestId(`remove-Leah McGlynn`).should(
|
|
167
|
+
'have.attr',
|
|
168
|
+
'data-removed',
|
|
169
|
+
'true'
|
|
170
|
+
);
|
|
171
|
+
cy.contains(labels.list.removed).should('be.visible');
|
|
172
|
+
cy.contains('1 removed').should('be.visible');
|
|
173
|
+
|
|
174
|
+
cy.contains(labels.actions.save)
|
|
175
|
+
.click()
|
|
176
|
+
.then(() => {
|
|
177
|
+
expect(save).to.have.been.calledWith(removedAccessRights);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
cy.makeSnapshot();
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('submits the new acces rights list with the updated contact', () => {
|
|
184
|
+
const { save } = initialize({});
|
|
185
|
+
|
|
186
|
+
cy.findByTestId(`role-Leah McGlynn`).parent().click();
|
|
187
|
+
|
|
188
|
+
cy.get('li[data-value="editor"]').click();
|
|
189
|
+
cy.contains(labels.list.updated).should('be.visible');
|
|
190
|
+
cy.contains('1 updated').should('be.visible');
|
|
191
|
+
|
|
192
|
+
cy.contains(labels.actions.save)
|
|
193
|
+
.click()
|
|
194
|
+
.then(() => {
|
|
195
|
+
expect(save).to.have.been.calledWith(updatedAccessRights);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
cy.makeSnapshot();
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('removes the updated chip when the contact role is updated and its initial role is assigned back', () => {
|
|
202
|
+
initialize({});
|
|
203
|
+
|
|
204
|
+
cy.findByTestId(`role-Leah McGlynn`).parent().click();
|
|
205
|
+
|
|
206
|
+
cy.get('li[data-value="editor"]').click();
|
|
207
|
+
cy.contains(labels.list.updated).should('be.visible');
|
|
208
|
+
|
|
209
|
+
cy.get('li[data-value="viewer"]').click();
|
|
210
|
+
cy.contains(labels.list.updated).should('not.exist');
|
|
211
|
+
|
|
212
|
+
cy.makeSnapshot();
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('retrieves contacts when the contact radio is selected', () => {
|
|
216
|
+
initialize({});
|
|
217
|
+
|
|
218
|
+
cy.contains(labels.add.contact).click();
|
|
219
|
+
cy.findByLabelText(labels.add.autocompleteContact).click();
|
|
220
|
+
|
|
221
|
+
cy.waitForRequest('@getContacts');
|
|
222
|
+
|
|
223
|
+
cy.makeSnapshot();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('retrieves contact groups when the contact group radio is selected', () => {
|
|
227
|
+
initialize({});
|
|
228
|
+
|
|
229
|
+
cy.contains(labels.add.contactGroup).click();
|
|
230
|
+
cy.findByLabelText(labels.add.autocompleteContactGroup).click();
|
|
231
|
+
|
|
232
|
+
cy.waitForRequest('@getContactGroups');
|
|
233
|
+
|
|
234
|
+
cy.makeSnapshot();
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('adds the contact as viewer when a contact is selected and the corresponding button is clicked', () => {
|
|
238
|
+
initialize({});
|
|
239
|
+
|
|
240
|
+
cy.contains(labels.add.contact).click();
|
|
241
|
+
cy.findByLabelText(labels.add.autocompleteContact).click();
|
|
242
|
+
|
|
243
|
+
cy.waitForRequest('@getContacts');
|
|
244
|
+
|
|
245
|
+
cy.contains('Entity 10').click();
|
|
246
|
+
|
|
247
|
+
cy.findByTestId('add').click();
|
|
248
|
+
|
|
249
|
+
cy.contains('Entity 10').should('be.visible');
|
|
250
|
+
|
|
251
|
+
cy.findByTestId('role-Entity 10').should('have.value', 'viewer');
|
|
252
|
+
cy.contains(labels.list.added).should('be.visible');
|
|
253
|
+
|
|
254
|
+
cy.makeSnapshot();
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('adds the contact group as editor when a contact group is selected and the corresponding button is clicked', () => {
|
|
258
|
+
initialize({});
|
|
259
|
+
|
|
260
|
+
cy.contains(labels.add.contactGroup).click();
|
|
261
|
+
cy.findByLabelText(labels.add.autocompleteContactGroup).click();
|
|
262
|
+
|
|
263
|
+
cy.waitForRequest('@getContactGroups');
|
|
264
|
+
|
|
265
|
+
cy.contains('Entity Group 10').click();
|
|
266
|
+
cy.findByTestId('add_role').parent().click();
|
|
267
|
+
cy.get('li[data-value="editor"]').click();
|
|
268
|
+
cy.findByTestId('add').click();
|
|
269
|
+
|
|
270
|
+
cy.contains('Entity Group 10').should('be.visible');
|
|
271
|
+
|
|
272
|
+
cy.findByTestId('role-Entity Group 10').should('have.value', 'editor');
|
|
273
|
+
cy.contains(labels.list.added).should('be.visible');
|
|
274
|
+
cy.contains('1 added').should('be.visible');
|
|
275
|
+
|
|
276
|
+
cy.makeSnapshot();
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('displays statistics when a contact is added, a contact is updated and a contact is removed', () => {
|
|
280
|
+
initialize({});
|
|
281
|
+
|
|
282
|
+
cy.contains(labels.add.contactGroup).click();
|
|
283
|
+
cy.findByLabelText(labels.add.autocompleteContactGroup).click();
|
|
284
|
+
|
|
285
|
+
cy.waitForRequest('@getContactGroups');
|
|
286
|
+
|
|
287
|
+
cy.contains('Entity Group 10').click();
|
|
288
|
+
cy.findByTestId('add_role').parent().click();
|
|
289
|
+
cy.get('li[data-value="editor"]').click();
|
|
290
|
+
cy.findByTestId('add').click();
|
|
291
|
+
|
|
292
|
+
cy.contains('Entity Group 10').should('be.visible');
|
|
293
|
+
|
|
294
|
+
cy.findByTestId(`role-Leah McGlynn`).parent().click();
|
|
295
|
+
cy.get('li[data-value="editor"]').click();
|
|
296
|
+
|
|
297
|
+
cy.findByTestId('remove-Jody Blanda').click();
|
|
298
|
+
|
|
299
|
+
cy.contains('1 added | 1 updated | 1 removed').should('be.visible');
|
|
300
|
+
|
|
301
|
+
cy.makeSnapshot();
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it('clears the autocomplete when a contact is selected and the contact type is changed', () => {
|
|
305
|
+
initialize({});
|
|
306
|
+
|
|
307
|
+
cy.contains(labels.add.contact).click();
|
|
308
|
+
cy.findByLabelText(labels.add.autocompleteContact).click();
|
|
309
|
+
|
|
310
|
+
cy.waitForRequest('@getContacts');
|
|
311
|
+
|
|
312
|
+
cy.contains('Entity 10').click();
|
|
313
|
+
cy.findByLabelText(labels.add.autocompleteContact).should(
|
|
314
|
+
'have.value',
|
|
315
|
+
'Entity 10'
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
cy.contains(labels.add.contactGroup).click();
|
|
319
|
+
cy.findByLabelText(labels.add.autocompleteContactGroup).should(
|
|
320
|
+
'have.value',
|
|
321
|
+
''
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
cy.makeSnapshot();
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('removes the contact from the list when the contact has been to the list and the corresponding button is clicked', () => {
|
|
328
|
+
initialize({});
|
|
329
|
+
|
|
330
|
+
cy.contains(labels.add.contact).click();
|
|
331
|
+
cy.findByLabelText(labels.add.autocompleteContact).click();
|
|
332
|
+
|
|
333
|
+
cy.waitForRequest('@getContacts');
|
|
334
|
+
|
|
335
|
+
cy.contains('Entity 10').click();
|
|
336
|
+
|
|
337
|
+
cy.findByTestId('add').click();
|
|
338
|
+
|
|
339
|
+
cy.contains('Entity 10').should('be.visible');
|
|
340
|
+
|
|
341
|
+
cy.contains(labels.list.added).should('be.visible');
|
|
342
|
+
|
|
343
|
+
cy.findByTestId('remove-Entity 10').click();
|
|
344
|
+
|
|
345
|
+
cy.contains('Entity 10').should('not.exist');
|
|
346
|
+
cy.contains(labels.list.added).should('not.exist');
|
|
347
|
+
|
|
348
|
+
cy.makeSnapshot();
|
|
349
|
+
});
|
|
350
|
+
});
|