@centreon/ui 23.10.119 → 23.10.120
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 +16 -12
- package/src/Button/Save/StartIcon.tsx +3 -3
- package/src/Dashboard/Item.tsx +1 -1
- package/src/Dashboard/Layout.tsx +2 -2
- package/src/FileDropZone/index.tsx +3 -1
- package/src/Form/Inputs/CheckboxGroup.tsx +1 -4
- package/src/Form/Inputs/index.tsx +1 -1
- package/src/Graph/LineChart/BasicComponents/Lines/Threshold/Circle.tsx +2 -2
- package/src/Graph/LineChart/BasicComponents/Lines/Threshold/index.tsx +5 -4
- package/src/Graph/LineChart/BasicComponents/Thresholds.tsx +2 -2
- package/src/Graph/LineChart/BasicComponents/useFilterLines.ts +1 -1
- package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/GuidingLines.tsx +2 -2
- package/src/Graph/LineChart/InteractiveComponents/Annotations/Annotation/index.tsx +2 -3
- package/src/Graph/LineChart/InteractiveComponents/Annotations/EventAnnotations.tsx +1 -1
- package/src/Graph/LineChart/Legend/useLegend.ts +5 -5
- package/src/Graph/LineChart/LineChart.tsx +5 -2
- package/src/Graph/LineChart/helpers/doc.ts +16 -13
- package/src/Graph/LineChart/helpers/index.ts +1 -1
- package/src/Graph/LineChart/index.stories.tsx +1 -2
- package/src/Graph/SingleBar/Thresholds.tsx +2 -2
- package/src/Graph/Text/Text.stories.tsx +60 -4
- package/src/Graph/common/timeSeries/index.ts +3 -3
- package/src/InputField/Select/Autocomplete/Connected/index.tsx +10 -7
- package/src/InputField/Select/Autocomplete/Draggable/SortableList.tsx +1 -1
- package/src/InputField/Select/Autocomplete/Draggable/SortableListContent.tsx +1 -1
- package/src/InputField/Select/Autocomplete/Draggable/index.tsx +1 -1
- package/src/InputField/Select/IconPopover/index.tsx +2 -2
- package/src/InputField/Select/index.tsx +1 -1
- package/src/Listing/Header/ListingHeader.tsx +1 -1
- package/src/Listing/index.stories.tsx +12 -1
- package/src/Listing/index.tsx +1 -1
- package/src/RichTextEditor/RichTextEditor.cypress.spec.tsx +100 -52
- package/src/RichTextEditor/RichTextEditor.tsx +21 -4
- 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/SortableItems/index.tsx +2 -7
- package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +8 -3
- package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/models.ts +0 -2
- package/src/TimePeriods/DateTimePickerInput.tsx +45 -17
- package/src/TimePeriods/TimePeriods.cypress.spec.tsx +9 -33
- package/src/TimePeriods/helpers/index.ts +1 -1
- package/src/TimePeriods/index.tsx +2 -2
- package/src/api/QueryProvider.tsx +1 -1
- package/src/api/TestQueryProvider.tsx +1 -1
- package/src/api/useFetchQuery/index.ts +28 -24
- package/src/api/useMutationQuery/index.ts +39 -17
- package/src/components/DataTable/Item/DataTableItem.tsx +2 -2
- package/src/components/Form/AccessRights/__fixtures__/contactAccessRight.mock.ts +2 -0
- package/src/components/Form/AccessRights/useAccessRightsForm.utils.ts +1 -1
- package/src/components/Form/Dashboard/DashboardForm.tsx +15 -12
- package/src/components/ItemComposition/ItemComposition.tsx +4 -2
- 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/index.ts +1 -0
- package/src/queryParameters/url/index.ts +5 -1
- package/src/utils/index.ts +0 -1
- package/src/utils/{useLicenseExpirationWarning.cypress.spec.tsx → useLicenseExpirationWarning.test.tsx} +48 -37
- package/src/utils/useLicenseExpirationWarning.ts +18 -18
- package/src/screens/dashboard/DashboardsDetail.stories.tsx +0 -108
- package/src/screens/dashboard/DashboardsOverview.stories.tsx +0 -281
- package/src/utils/useDateTimePickerAdapter.ts +0 -309
|
@@ -2,12 +2,15 @@ import { useAtomValue } from 'jotai';
|
|
|
2
2
|
import { makeStyles } from 'tss-react/mui';
|
|
3
3
|
import { equals } from 'ramda';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
|
+
import dayjs from 'dayjs';
|
|
6
|
+
import utc from 'dayjs/plugin/utc';
|
|
7
|
+
import timezone from 'dayjs/plugin/timezone';
|
|
5
8
|
|
|
9
|
+
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
|
6
10
|
import { Typography } from '@mui/material';
|
|
7
11
|
import { LocalizationProvider } from '@mui/x-date-pickers';
|
|
8
12
|
|
|
9
13
|
import { userAtom } from '@centreon/ui-context';
|
|
10
|
-
import { useDateTimePickerAdapter } from '@centreon/ui';
|
|
11
14
|
|
|
12
15
|
import DateTimePickerInput from '../../DateTimePickerInput';
|
|
13
16
|
import {
|
|
@@ -20,6 +23,9 @@ import ErrorText from './ErrorText';
|
|
|
20
23
|
import { PickersData, PickersStartEndDateDirection } from './models';
|
|
21
24
|
import { PickersStartEndDateModel } from './usePickersStartEndDate';
|
|
22
25
|
|
|
26
|
+
dayjs.extend(utc);
|
|
27
|
+
dayjs.extend(timezone);
|
|
28
|
+
|
|
23
29
|
const useStyles = makeStyles()((theme) => ({
|
|
24
30
|
error: {
|
|
25
31
|
textAlign: 'center'
|
|
@@ -104,7 +110,6 @@ const PickersStartEndDate = ({
|
|
|
104
110
|
direction = PickersStartEndDateDirection.column
|
|
105
111
|
}: Props): JSX.Element => {
|
|
106
112
|
const { classes, cx } = useStyles();
|
|
107
|
-
const { Adapter } = useDateTimePickerAdapter();
|
|
108
113
|
|
|
109
114
|
const { locale } = useAtomValue(userAtom);
|
|
110
115
|
const error = useAtomValue(errorTimePeriodAtom);
|
|
@@ -126,7 +131,7 @@ const PickersStartEndDate = ({
|
|
|
126
131
|
return (
|
|
127
132
|
<LocalizationProvider
|
|
128
133
|
adapterLocale={locale.substring(0, 2)}
|
|
129
|
-
dateAdapter={
|
|
134
|
+
dateAdapter={AdapterDayjs}
|
|
130
135
|
>
|
|
131
136
|
<div className={styleContainer}>
|
|
132
137
|
<PickerDateWithLabel
|
|
@@ -18,8 +18,6 @@ export interface PickersData {
|
|
|
18
18
|
getError?: (value: boolean) => void;
|
|
19
19
|
isDisabledEndPicker?: boolean;
|
|
20
20
|
isDisabledStartPicker?: boolean;
|
|
21
|
-
onCloseEndPicker?: (isClosed: boolean) => void;
|
|
22
|
-
onCloseStartPicker?: (isClosed: boolean) => void;
|
|
23
21
|
rangeEndDate?: RangeDate;
|
|
24
22
|
rangeStartDate?: RangeDate;
|
|
25
23
|
}
|
|
@@ -1,19 +1,29 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import dayjs, { Dayjs } from 'dayjs';
|
|
4
|
+
import { useAtomValue } from 'jotai';
|
|
5
|
+
import { equals } from 'ramda';
|
|
4
6
|
|
|
5
|
-
import {
|
|
7
|
+
import { DateTimePicker, LocalizationProvider } from '@mui/x-date-pickers';
|
|
8
|
+
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
|
9
|
+
|
|
10
|
+
import { userAtom } from '@centreon/ui-context';
|
|
6
11
|
|
|
7
12
|
import { CustomTimePeriodProperty } from './models';
|
|
8
13
|
|
|
14
|
+
interface ChangeDateProps {
|
|
15
|
+
date: Date;
|
|
16
|
+
property: CustomTimePeriodProperty | string;
|
|
17
|
+
}
|
|
18
|
+
|
|
9
19
|
interface Props {
|
|
10
|
-
changeDate: (props) => void;
|
|
20
|
+
changeDate: (props: ChangeDateProps) => void;
|
|
11
21
|
date: Date | null;
|
|
12
22
|
desktopMediaQuery?: string;
|
|
13
23
|
disabled?: boolean;
|
|
14
24
|
maxDate?: Date;
|
|
15
25
|
minDate?: Date;
|
|
16
|
-
property: CustomTimePeriodProperty;
|
|
26
|
+
property: CustomTimePeriodProperty | string;
|
|
17
27
|
}
|
|
18
28
|
|
|
19
29
|
const DateTimePickerInput = ({
|
|
@@ -25,24 +35,42 @@ const DateTimePickerInput = ({
|
|
|
25
35
|
disabled = false,
|
|
26
36
|
desktopMediaQuery
|
|
27
37
|
}: Props): JSX.Element => {
|
|
28
|
-
const
|
|
38
|
+
const desktopPickerMediaQuery =
|
|
39
|
+
'@media (min-width: 1024px) or (pointer: fine)';
|
|
40
|
+
|
|
41
|
+
const { timezone, locale } = useAtomValue(userAtom);
|
|
42
|
+
|
|
43
|
+
const isUTC = equals(timezone, 'UTC');
|
|
29
44
|
|
|
30
45
|
const changeTime = (newValue: dayjs.Dayjs | null): void => {
|
|
31
46
|
changeDate({ date: dayjs(newValue).toDate(), property });
|
|
32
47
|
};
|
|
33
48
|
|
|
49
|
+
const formatDate = useCallback(
|
|
50
|
+
(currentDate: Date | null): Dayjs => {
|
|
51
|
+
return isUTC ? dayjs.utc(currentDate) : dayjs.tz(currentDate, timezone);
|
|
52
|
+
},
|
|
53
|
+
[isUTC, timezone]
|
|
54
|
+
);
|
|
55
|
+
|
|
34
56
|
return (
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
57
|
+
<LocalizationProvider
|
|
58
|
+
adapterLocale={locale.substring(0, 2)}
|
|
59
|
+
dateAdapter={AdapterDayjs}
|
|
60
|
+
dateLibInstance={dayjs}
|
|
61
|
+
>
|
|
62
|
+
<DateTimePicker<dayjs.Dayjs>
|
|
63
|
+
dayOfWeekFormatter={(dayOfWeek) =>
|
|
64
|
+
dayOfWeek.substring(0, 2).toLocaleUpperCase()
|
|
65
|
+
}
|
|
66
|
+
desktopModeMediaQuery={desktopMediaQuery ?? desktopPickerMediaQuery}
|
|
67
|
+
disabled={disabled}
|
|
68
|
+
maxDate={maxDate && formatDate(maxDate)}
|
|
69
|
+
minDate={minDate && formatDate(minDate)}
|
|
70
|
+
value={formatDate(date)}
|
|
71
|
+
onChange={changeTime}
|
|
72
|
+
/>
|
|
73
|
+
</LocalizationProvider>
|
|
46
74
|
);
|
|
47
75
|
};
|
|
48
76
|
|
|
@@ -3,15 +3,10 @@ import localizedFormatPlugin from 'dayjs/plugin/localizedFormat';
|
|
|
3
3
|
import timezonePlugin from 'dayjs/plugin/timezone';
|
|
4
4
|
import utcPlugin from 'dayjs/plugin/utc';
|
|
5
5
|
import { Provider, createStore } from 'jotai';
|
|
6
|
-
import { equals
|
|
6
|
+
import { equals } from 'ramda';
|
|
7
7
|
import { renderHook } from '@testing-library/react';
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
useLocaleDateTimeFormat,
|
|
13
|
-
useDateTimePickerAdapter
|
|
14
|
-
} from '@centreon/ui';
|
|
9
|
+
import { useLocaleDateTimeFormat } from '@centreon/ui';
|
|
15
10
|
import { ListingVariant, userAtom } from '@centreon/ui-context';
|
|
16
11
|
|
|
17
12
|
import { CustomTimePeriodProperty } from './models';
|
|
@@ -297,10 +292,6 @@ testData.forEach((item) =>
|
|
|
297
292
|
beforeEach(() => {
|
|
298
293
|
cy.viewport('macbook-13');
|
|
299
294
|
|
|
300
|
-
const { result } = renderHook(() => useDateTimePickerAdapter());
|
|
301
|
-
|
|
302
|
-
const { Adapter } = result.current;
|
|
303
|
-
|
|
304
295
|
const store = createStore();
|
|
305
296
|
store.set(userAtom, {
|
|
306
297
|
...retrievedUser,
|
|
@@ -311,31 +302,16 @@ testData.forEach((item) =>
|
|
|
311
302
|
cy.mount({
|
|
312
303
|
Component: (
|
|
313
304
|
<Provider store={store}>
|
|
314
|
-
<
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
property={CustomTimePeriodProperty.start}
|
|
320
|
-
/>
|
|
321
|
-
</LocalizationProvider>
|
|
305
|
+
<DateTimePickerInput
|
|
306
|
+
changeDate={cy.stub()}
|
|
307
|
+
date={new Date(item.initialDate)}
|
|
308
|
+
property={CustomTimePeriodProperty.start}
|
|
309
|
+
/>
|
|
322
310
|
</Provider>
|
|
323
311
|
)
|
|
324
312
|
});
|
|
325
313
|
});
|
|
326
314
|
|
|
327
|
-
it('checks input calendar value contains correct date', () => {
|
|
328
|
-
const { result } = renderHook(() => useLocaleDateTimeFormat());
|
|
329
|
-
const { format } = result.current;
|
|
330
|
-
|
|
331
|
-
const dateInput = format({
|
|
332
|
-
date: dayjs(item.initialDate).tz(item.timezone),
|
|
333
|
-
formatString: 'L hh:mm A'
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
cy.get('input').should('have.value', dateInput);
|
|
337
|
-
});
|
|
338
|
-
|
|
339
315
|
it(`displays the correct number of days for the current month when the ${item.button} button is clicked`, () => {
|
|
340
316
|
cy.get('button').click();
|
|
341
317
|
item.data.forEach((element) => {
|
|
@@ -389,7 +365,7 @@ testData.forEach((item) =>
|
|
|
389
365
|
|
|
390
366
|
cy.get('[role="rowgroup"]').children().as('listWeeks');
|
|
391
367
|
|
|
392
|
-
cy.get('@listWeeks').should('have.length',
|
|
368
|
+
cy.get('@listWeeks').should('have.length', numberWeeks);
|
|
393
369
|
cy.get('@listWeeks').eq(0).as('firstWeek');
|
|
394
370
|
cy.get('@firstWeek').children().as('listDaysInFirstWeek');
|
|
395
371
|
|
|
@@ -416,7 +392,7 @@ testData.forEach((item) =>
|
|
|
416
392
|
|
|
417
393
|
cy.get('[role="rowgroup"]').children().as('listWeeks');
|
|
418
394
|
|
|
419
|
-
cy.get('@listWeeks').should('have.length',
|
|
395
|
+
cy.get('@listWeeks').should('have.length', numberWeeks);
|
|
420
396
|
|
|
421
397
|
cy.get('@listWeeks')
|
|
422
398
|
.eq(numberWeeks - 1)
|
|
@@ -20,7 +20,7 @@ import { useStyles } from './TimePeriods.styles';
|
|
|
20
20
|
import {
|
|
21
21
|
CustomTimePeriod as CustomTimePeriodModel,
|
|
22
22
|
EndStartInterval,
|
|
23
|
-
TimePeriod
|
|
23
|
+
TimePeriod as TimePeriodModel
|
|
24
24
|
} from './models';
|
|
25
25
|
import useTimePeriod from './useTimePeriod';
|
|
26
26
|
|
|
@@ -34,7 +34,7 @@ interface Parameters extends EndStartInterval {
|
|
|
34
34
|
export interface Props {
|
|
35
35
|
adjustTimePeriodData?: Omit<CustomTimePeriodModel, 'timelineEventsLimit'>;
|
|
36
36
|
disabled?: boolean;
|
|
37
|
-
extraTimePeriods?: Array<Omit<
|
|
37
|
+
extraTimePeriods?: Array<Omit<TimePeriodModel, 'timelineEventsLimit'>>;
|
|
38
38
|
getIsError?: (value: boolean) => void;
|
|
39
39
|
getParameters?: ({ start, end, timelineEventsLimit }: Parameters) => void;
|
|
40
40
|
renderExternalComponent?: ReactNode;
|
|
@@ -25,7 +25,9 @@ export interface UseFetchQueryProps<T> {
|
|
|
25
25
|
getQueryKey: () => QueryKey;
|
|
26
26
|
httpCodesBypassErrorSnackbar?: Array<number>;
|
|
27
27
|
isPaginated?: boolean;
|
|
28
|
-
queryOptions?:
|
|
28
|
+
queryOptions?: {
|
|
29
|
+
suspense?: boolean;
|
|
30
|
+
} & Omit<
|
|
29
31
|
UseQueryOptions<T | ResponseError, Error, T | ResponseError, QueryKey>,
|
|
30
32
|
'queryKey' | 'queryFn'
|
|
31
33
|
>;
|
|
@@ -33,11 +35,12 @@ export interface UseFetchQueryProps<T> {
|
|
|
33
35
|
|
|
34
36
|
export type UseFetchQueryState<T> = {
|
|
35
37
|
data?: T;
|
|
38
|
+
error: Omit<ResponseError, 'isError'> | null;
|
|
36
39
|
fetchQuery: () => Promise<T | ResponseError>;
|
|
37
40
|
prefetchNextPage: ({ page, getPrefetchQueryKey }) => void;
|
|
38
41
|
prefetchPreviousPage: ({ page, getPrefetchQueryKey }) => void;
|
|
39
42
|
prefetchQuery: ({ endpointParams, queryKey }) => void;
|
|
40
|
-
} & Omit<QueryObserverBaseResult, 'data'>;
|
|
43
|
+
} & Omit<QueryObserverBaseResult, 'data' | 'error'>;
|
|
41
44
|
|
|
42
45
|
export interface PrefetchEndpointParams {
|
|
43
46
|
page: number;
|
|
@@ -58,9 +61,8 @@ const useFetchQuery = <T extends object>({
|
|
|
58
61
|
}: UseFetchQueryProps<T>): UseFetchQueryState<T> => {
|
|
59
62
|
const { showErrorMessage } = useSnackbar();
|
|
60
63
|
|
|
61
|
-
const queryData = useQuery<T | ResponseError, Error>(
|
|
62
|
-
|
|
63
|
-
({ signal }): Promise<T | ResponseError> =>
|
|
64
|
+
const queryData = useQuery<T | ResponseError, Error>({
|
|
65
|
+
queryFn: ({ signal }): Promise<T | ResponseError> =>
|
|
64
66
|
customFetch<T>({
|
|
65
67
|
catchError,
|
|
66
68
|
decoder,
|
|
@@ -69,10 +71,9 @@ const useFetchQuery = <T extends object>({
|
|
|
69
71
|
headers: new Headers(fetchHeaders),
|
|
70
72
|
signal
|
|
71
73
|
}),
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
);
|
|
74
|
+
queryKey: getQueryKey(),
|
|
75
|
+
...queryOptions
|
|
76
|
+
});
|
|
76
77
|
|
|
77
78
|
const queryClient = useQueryClient();
|
|
78
79
|
|
|
@@ -92,9 +93,8 @@ const useFetchQuery = <T extends object>({
|
|
|
92
93
|
};
|
|
93
94
|
|
|
94
95
|
const prefetchQuery = ({ endpointParams, queryKey }): void => {
|
|
95
|
-
queryClient.prefetchQuery(
|
|
96
|
-
|
|
97
|
-
({ signal }): Promise<T | ResponseError> =>
|
|
96
|
+
queryClient.prefetchQuery({
|
|
97
|
+
queryFn: ({ signal }): Promise<T | ResponseError> =>
|
|
98
98
|
customFetch<T>({
|
|
99
99
|
catchError,
|
|
100
100
|
decoder,
|
|
@@ -102,8 +102,9 @@ const useFetchQuery = <T extends object>({
|
|
|
102
102
|
endpoint: getEndpoint(endpointParams),
|
|
103
103
|
headers: new Headers(fetchHeaders),
|
|
104
104
|
signal
|
|
105
|
-
})
|
|
106
|
-
|
|
105
|
+
}),
|
|
106
|
+
queryKey
|
|
107
|
+
});
|
|
107
108
|
};
|
|
108
109
|
|
|
109
110
|
const prefetchNextPage = ({ page, getPrefetchQueryKey }): void => {
|
|
@@ -133,9 +134,8 @@ const useFetchQuery = <T extends object>({
|
|
|
133
134
|
};
|
|
134
135
|
|
|
135
136
|
const fetchQuery = (): Promise<T | ResponseError> => {
|
|
136
|
-
return queryClient.fetchQuery(
|
|
137
|
-
|
|
138
|
-
({ signal }): Promise<T | ResponseError> =>
|
|
137
|
+
return queryClient.fetchQuery({
|
|
138
|
+
queryFn: ({ signal }): Promise<T | ResponseError> =>
|
|
139
139
|
customFetch<T>({
|
|
140
140
|
catchError,
|
|
141
141
|
decoder,
|
|
@@ -143,8 +143,9 @@ const useFetchQuery = <T extends object>({
|
|
|
143
143
|
endpoint: getEndpoint(),
|
|
144
144
|
headers: new Headers(fetchHeaders),
|
|
145
145
|
signal
|
|
146
|
-
})
|
|
147
|
-
|
|
146
|
+
}),
|
|
147
|
+
queryKey: getQueryKey()
|
|
148
|
+
});
|
|
148
149
|
};
|
|
149
150
|
|
|
150
151
|
const data = useMemo(
|
|
@@ -157,16 +158,19 @@ const useFetchQuery = <T extends object>({
|
|
|
157
158
|
|
|
158
159
|
useEffect(() => {
|
|
159
160
|
return (): void => {
|
|
160
|
-
queryClient.cancelQueries(getQueryKey());
|
|
161
|
+
queryClient.cancelQueries({ queryKey: getQueryKey() });
|
|
161
162
|
};
|
|
162
163
|
}, []);
|
|
163
164
|
|
|
164
|
-
useEffect(
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
useEffect(
|
|
166
|
+
() => {
|
|
167
|
+
manageError();
|
|
168
|
+
},
|
|
169
|
+
useDeepCompare([queryData.data])
|
|
170
|
+
);
|
|
167
171
|
|
|
168
172
|
return {
|
|
169
|
-
...omit(['data'], queryData),
|
|
173
|
+
...omit(['data', 'error'], queryData),
|
|
170
174
|
data,
|
|
171
175
|
error: errorData?.isError ? omit(['isError'], errorData) : null,
|
|
172
176
|
fetchQuery,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from '@tanstack/react-query';
|
|
9
9
|
import { JsonDecoder } from 'ts.data.json';
|
|
10
10
|
import anylogger from 'anylogger';
|
|
11
|
-
import { includes } from 'ramda';
|
|
11
|
+
import { includes, omit } from 'ramda';
|
|
12
12
|
|
|
13
13
|
import { CatchErrorProps, customFetch, ResponseError } from '../customFetch';
|
|
14
14
|
import useSnackbar from '../../Snackbar/useSnackbar';
|
|
@@ -30,14 +30,33 @@ export type UseMutationQueryProps<T, TMeta> = {
|
|
|
30
30
|
getEndpoint: (_meta: TMeta) => string;
|
|
31
31
|
httpCodesBypassErrorSnackbar?: Array<number>;
|
|
32
32
|
method: Method;
|
|
33
|
-
|
|
33
|
+
onError?: (
|
|
34
|
+
error: ResponseError,
|
|
35
|
+
variables: T & { _meta: TMeta },
|
|
36
|
+
context: unknown
|
|
37
|
+
) => unknown;
|
|
38
|
+
onMutate?: (variables: T & { _meta: TMeta }) => Promise<unknown> | unknown;
|
|
39
|
+
onSuccess?: (
|
|
40
|
+
data: ResponseError | T,
|
|
41
|
+
variables: T & {
|
|
42
|
+
_meta: TMeta;
|
|
43
|
+
},
|
|
44
|
+
context: unknown
|
|
45
|
+
) => unknown;
|
|
46
|
+
} & Omit<
|
|
47
|
+
UseMutationOptions<T & { _meta?: TMeta }>,
|
|
48
|
+
'mutationFn' | 'onError' | 'onMutate' | 'onSuccess'
|
|
49
|
+
>;
|
|
34
50
|
|
|
35
51
|
const log = anylogger('API Request');
|
|
36
52
|
|
|
37
|
-
export type UseMutationQueryState<T> =
|
|
53
|
+
export type UseMutationQueryState<T> = Omit<
|
|
54
|
+
UseMutationResult<T | ResponseError>,
|
|
55
|
+
'isError'
|
|
56
|
+
> & {
|
|
38
57
|
isError: boolean;
|
|
39
58
|
isMutating: boolean;
|
|
40
|
-
}
|
|
59
|
+
};
|
|
41
60
|
|
|
42
61
|
const useMutationQuery = <T extends object, TMeta>({
|
|
43
62
|
getEndpoint,
|
|
@@ -57,8 +76,10 @@ const useMutationQuery = <T extends object, TMeta>({
|
|
|
57
76
|
T | ResponseError,
|
|
58
77
|
ResponseError,
|
|
59
78
|
T & { _meta: TMeta }
|
|
60
|
-
>(
|
|
61
|
-
|
|
79
|
+
>({
|
|
80
|
+
mutationFn: (
|
|
81
|
+
_payload: T & { _meta: TMeta }
|
|
82
|
+
): Promise<T | ResponseError> => {
|
|
62
83
|
const { _meta, ...payload } = _payload || {};
|
|
63
84
|
|
|
64
85
|
return customFetch<T>({
|
|
@@ -75,12 +96,10 @@ const useMutationQuery = <T extends object, TMeta>({
|
|
|
75
96
|
payload
|
|
76
97
|
});
|
|
77
98
|
},
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
);
|
|
99
|
+
onError,
|
|
100
|
+
onMutate,
|
|
101
|
+
onSuccess
|
|
102
|
+
});
|
|
84
103
|
|
|
85
104
|
const manageError = (): void => {
|
|
86
105
|
const data = queryData.data as ResponseError | undefined;
|
|
@@ -97,14 +116,17 @@ const useMutationQuery = <T extends object, TMeta>({
|
|
|
97
116
|
}
|
|
98
117
|
};
|
|
99
118
|
|
|
100
|
-
useEffect(
|
|
101
|
-
|
|
102
|
-
|
|
119
|
+
useEffect(
|
|
120
|
+
() => {
|
|
121
|
+
manageError();
|
|
122
|
+
},
|
|
123
|
+
useDeepCompare([queryData.data])
|
|
124
|
+
);
|
|
103
125
|
|
|
104
126
|
return {
|
|
105
|
-
...queryData,
|
|
127
|
+
...omit(['isError'], queryData),
|
|
106
128
|
isError: (queryData.data as ResponseError | undefined)?.isError || false,
|
|
107
|
-
isMutating: queryData.
|
|
129
|
+
isMutating: queryData.isPending
|
|
108
130
|
};
|
|
109
131
|
};
|
|
110
132
|
|
|
@@ -22,7 +22,7 @@ export interface DataTableItemProps {
|
|
|
22
22
|
description?: string;
|
|
23
23
|
hasActions?: boolean;
|
|
24
24
|
hasCardAction?: boolean;
|
|
25
|
-
labelsDelete
|
|
25
|
+
labelsDelete?: {
|
|
26
26
|
cancel: string;
|
|
27
27
|
confirm: {
|
|
28
28
|
label: string;
|
|
@@ -76,7 +76,7 @@ const DataTableItem = forwardRef(
|
|
|
76
76
|
{hasActions && (
|
|
77
77
|
<MuiCardActions>
|
|
78
78
|
<span>
|
|
79
|
-
{onDelete && (
|
|
79
|
+
{onDelete && labelsDelete && (
|
|
80
80
|
<ConfirmationTooltip
|
|
81
81
|
confirmVariant="error"
|
|
82
82
|
labels={labelsDelete}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ReactElement, useCallback, useMemo } from 'react';
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { string, number, object } from 'yup';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
|
+
import { equals } from 'ramda';
|
|
5
6
|
|
|
6
7
|
import { InputType } from '../../../Form/Inputs/models';
|
|
7
8
|
import { Form, FormProps } from '../../../Form';
|
|
@@ -84,8 +85,8 @@ const DashboardForm = ({
|
|
|
84
85
|
}
|
|
85
86
|
],
|
|
86
87
|
submit: (values, bag) => onSubmit?.(values, bag),
|
|
87
|
-
validationSchema:
|
|
88
|
-
description:
|
|
88
|
+
validationSchema: object({
|
|
89
|
+
description: string()
|
|
89
90
|
.label(labels?.entity?.description || '')
|
|
90
91
|
.max(
|
|
91
92
|
180,
|
|
@@ -93,17 +94,19 @@ const DashboardForm = ({
|
|
|
93
94
|
`${p.label} ${t(labelMustBeMost)} ${p.max} ${t(labelCharacters)}`
|
|
94
95
|
)
|
|
95
96
|
.nullable(),
|
|
96
|
-
globalRefreshInterval:
|
|
97
|
-
interval:
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
globalRefreshInterval: object({
|
|
98
|
+
interval: number().when('type', ([type], schema) => {
|
|
99
|
+
if (equals(type, 'manual')) {
|
|
100
|
+
schema
|
|
101
|
+
.min(1, ({ min }) => t(labelMustBeAtLeast, { min }))
|
|
102
|
+
.required(t(labelRequired) as string);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return schema.nullable();
|
|
103
106
|
}),
|
|
104
|
-
type:
|
|
107
|
+
type: string()
|
|
105
108
|
}),
|
|
106
|
-
name:
|
|
109
|
+
name: string()
|
|
107
110
|
.label(labels?.entity?.name)
|
|
108
111
|
.min(3, ({ min, label }) => t(labelMustBeAtLeast, { label, min }))
|
|
109
112
|
.max(50, ({ max, label }) => t(labelMustBeMost, { label, max }))
|
|
@@ -7,6 +7,7 @@ import { Button } from '..';
|
|
|
7
7
|
import { useItemCompositionStyles } from './ItemComposition.styles';
|
|
8
8
|
|
|
9
9
|
type Props = {
|
|
10
|
+
IconAdd?;
|
|
10
11
|
addButtonHidden?: boolean;
|
|
11
12
|
addbuttonDisabled?: boolean;
|
|
12
13
|
children: Array<ReactElement>;
|
|
@@ -19,7 +20,8 @@ export const ItemComposition = ({
|
|
|
19
20
|
children,
|
|
20
21
|
labelAdd,
|
|
21
22
|
addbuttonDisabled,
|
|
22
|
-
addButtonHidden
|
|
23
|
+
addButtonHidden,
|
|
24
|
+
IconAdd
|
|
23
25
|
}: Props): JSX.Element => {
|
|
24
26
|
const { classes } = useItemCompositionStyles();
|
|
25
27
|
|
|
@@ -31,7 +33,7 @@ export const ItemComposition = ({
|
|
|
31
33
|
aria-label={labelAdd}
|
|
32
34
|
data-testid={labelAdd}
|
|
33
35
|
disabled={addbuttonDisabled}
|
|
34
|
-
icon={<AddIcon />}
|
|
36
|
+
icon={IconAdd || <AddIcon />}
|
|
35
37
|
iconVariant="start"
|
|
36
38
|
size="small"
|
|
37
39
|
variant="ghost"
|
|
@@ -15,6 +15,7 @@ import { useStyles } from './MenuButton.styles';
|
|
|
15
15
|
type MenuButtonProps = {
|
|
16
16
|
ariaLabel?: string;
|
|
17
17
|
children?: ReactNode;
|
|
18
|
+
className?: string;
|
|
18
19
|
hasArrow?: boolean;
|
|
19
20
|
isOpen?: boolean;
|
|
20
21
|
onClick?: (args: { isOpen: boolean }) => void;
|
|
@@ -29,9 +30,10 @@ const MenuButton = ({
|
|
|
29
30
|
size = 'small',
|
|
30
31
|
variant = 'ghost',
|
|
31
32
|
ariaLabel,
|
|
33
|
+
className,
|
|
32
34
|
...attr
|
|
33
35
|
}: MenuButtonProps): ReactElement => {
|
|
34
|
-
const { classes } = useStyles();
|
|
36
|
+
const { cx, classes } = useStyles();
|
|
35
37
|
|
|
36
38
|
const { isMenuOpen, setIsMenuOpen, setAnchorEl, onOpen } = useMenu();
|
|
37
39
|
|
|
@@ -50,7 +52,7 @@ const MenuButton = ({
|
|
|
50
52
|
<Button
|
|
51
53
|
{...attr}
|
|
52
54
|
aria-label={ariaLabel}
|
|
53
|
-
className={classes.menuButton}
|
|
55
|
+
className={cx(classes.menuButton, className)}
|
|
54
56
|
data-is-active={isMenuOpen}
|
|
55
57
|
size={size}
|
|
56
58
|
variant={variant}
|
|
@@ -6,6 +6,7 @@ import { useStyles } from './Menu.styles';
|
|
|
6
6
|
|
|
7
7
|
type MenuItemProps = {
|
|
8
8
|
children?: ReactNode;
|
|
9
|
+
className?: string;
|
|
9
10
|
isActive?: boolean;
|
|
10
11
|
isDisabled?: boolean;
|
|
11
12
|
onClick?: () => void;
|
|
@@ -15,13 +16,14 @@ const MenuItem = ({
|
|
|
15
16
|
children,
|
|
16
17
|
onClick,
|
|
17
18
|
isActive = false,
|
|
18
|
-
isDisabled = false
|
|
19
|
+
isDisabled = false,
|
|
20
|
+
className
|
|
19
21
|
}: MenuItemProps): ReactElement => {
|
|
20
|
-
const { classes } = useStyles();
|
|
22
|
+
const { cx, classes } = useStyles();
|
|
21
23
|
|
|
22
24
|
return (
|
|
23
25
|
<MuiMenuItem
|
|
24
|
-
className={classes.menuItem}
|
|
26
|
+
className={cx(classes.menuItem, className)}
|
|
25
27
|
data-is-active={isActive}
|
|
26
28
|
data-is-disabled={isDisabled}
|
|
27
29
|
disabled={isDisabled}
|