@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.
Files changed (70) hide show
  1. package/package.json +16 -12
  2. package/src/Button/Save/StartIcon.tsx +3 -3
  3. package/src/Dashboard/Item.tsx +1 -1
  4. package/src/Dashboard/Layout.tsx +2 -2
  5. package/src/FileDropZone/index.tsx +3 -1
  6. package/src/Form/Inputs/CheckboxGroup.tsx +1 -4
  7. package/src/Form/Inputs/index.tsx +1 -1
  8. package/src/Graph/LineChart/BasicComponents/Lines/Threshold/Circle.tsx +2 -2
  9. package/src/Graph/LineChart/BasicComponents/Lines/Threshold/index.tsx +5 -4
  10. package/src/Graph/LineChart/BasicComponents/Thresholds.tsx +2 -2
  11. package/src/Graph/LineChart/BasicComponents/useFilterLines.ts +1 -1
  12. package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/GuidingLines.tsx +2 -2
  13. package/src/Graph/LineChart/InteractiveComponents/Annotations/Annotation/index.tsx +2 -3
  14. package/src/Graph/LineChart/InteractiveComponents/Annotations/EventAnnotations.tsx +1 -1
  15. package/src/Graph/LineChart/Legend/useLegend.ts +5 -5
  16. package/src/Graph/LineChart/LineChart.tsx +5 -2
  17. package/src/Graph/LineChart/helpers/doc.ts +16 -13
  18. package/src/Graph/LineChart/helpers/index.ts +1 -1
  19. package/src/Graph/LineChart/index.stories.tsx +1 -2
  20. package/src/Graph/SingleBar/Thresholds.tsx +2 -2
  21. package/src/Graph/Text/Text.stories.tsx +60 -4
  22. package/src/Graph/common/timeSeries/index.ts +3 -3
  23. package/src/InputField/Select/Autocomplete/Connected/index.tsx +10 -7
  24. package/src/InputField/Select/Autocomplete/Draggable/SortableList.tsx +1 -1
  25. package/src/InputField/Select/Autocomplete/Draggable/SortableListContent.tsx +1 -1
  26. package/src/InputField/Select/Autocomplete/Draggable/index.tsx +1 -1
  27. package/src/InputField/Select/IconPopover/index.tsx +2 -2
  28. package/src/InputField/Select/index.tsx +1 -1
  29. package/src/Listing/Header/ListingHeader.tsx +1 -1
  30. package/src/Listing/index.stories.tsx +12 -1
  31. package/src/Listing/index.tsx +1 -1
  32. package/src/RichTextEditor/RichTextEditor.cypress.spec.tsx +100 -52
  33. package/src/RichTextEditor/RichTextEditor.tsx +21 -4
  34. package/src/RichTextEditor/plugins/ToolbarPlugin/AlignPicker.tsx +21 -20
  35. package/src/RichTextEditor/plugins/ToolbarPlugin/BlockButtons.tsx +35 -77
  36. package/src/RichTextEditor/plugins/ToolbarPlugin/FormatButtons.tsx +29 -83
  37. package/src/RichTextEditor/plugins/ToolbarPlugin/LinkButton.tsx +106 -0
  38. package/src/RichTextEditor/plugins/ToolbarPlugin/ListButton.tsx +155 -0
  39. package/src/RichTextEditor/plugins/ToolbarPlugin/MacrosButton.tsx +23 -39
  40. package/src/RichTextEditor/plugins/ToolbarPlugin/ToolbarPlugin.styles.ts +24 -14
  41. package/src/RichTextEditor/plugins/ToolbarPlugin/UndoRedoButtons.tsx +6 -0
  42. package/src/RichTextEditor/plugins/ToolbarPlugin/index.tsx +5 -10
  43. package/src/RichTextEditor/translatedLabels.ts +3 -0
  44. package/src/SortableItems/index.tsx +2 -7
  45. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +8 -3
  46. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/models.ts +0 -2
  47. package/src/TimePeriods/DateTimePickerInput.tsx +45 -17
  48. package/src/TimePeriods/TimePeriods.cypress.spec.tsx +9 -33
  49. package/src/TimePeriods/helpers/index.ts +1 -1
  50. package/src/TimePeriods/index.tsx +2 -2
  51. package/src/api/QueryProvider.tsx +1 -1
  52. package/src/api/TestQueryProvider.tsx +1 -1
  53. package/src/api/useFetchQuery/index.ts +28 -24
  54. package/src/api/useMutationQuery/index.ts +39 -17
  55. package/src/components/DataTable/Item/DataTableItem.tsx +2 -2
  56. package/src/components/Form/AccessRights/__fixtures__/contactAccessRight.mock.ts +2 -0
  57. package/src/components/Form/AccessRights/useAccessRightsForm.utils.ts +1 -1
  58. package/src/components/Form/Dashboard/DashboardForm.tsx +15 -12
  59. package/src/components/ItemComposition/ItemComposition.tsx +4 -2
  60. package/src/components/Menu/Button/MenuButton.tsx +4 -2
  61. package/src/components/Menu/MenuItem.tsx +5 -3
  62. package/src/components/Menu/MenuItems.tsx +4 -3
  63. package/src/index.ts +1 -0
  64. package/src/queryParameters/url/index.ts +5 -1
  65. package/src/utils/index.ts +0 -1
  66. package/src/utils/{useLicenseExpirationWarning.cypress.spec.tsx → useLicenseExpirationWarning.test.tsx} +48 -37
  67. package/src/utils/useLicenseExpirationWarning.ts +18 -18
  68. package/src/screens/dashboard/DashboardsDetail.stories.tsx +0 -108
  69. package/src/screens/dashboard/DashboardsOverview.stories.tsx +0 -281
  70. 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={Adapter}
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 dayjs from 'dayjs';
1
+ import { useCallback } from 'react';
2
2
 
3
- import { DateTimePicker } from '@mui/x-date-pickers';
3
+ import dayjs, { Dayjs } from 'dayjs';
4
+ import { useAtomValue } from 'jotai';
5
+ import { equals } from 'ramda';
4
6
 
5
- import { useDateTimePickerAdapter } from '@centreon/ui';
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 { desktopPickerMediaQuery } = useDateTimePickerAdapter();
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
- <DateTimePicker<dayjs.Dayjs>
36
- dayOfWeekFormatter={(day: string): string =>
37
- day.substring(0, 2).toUpperCase()
38
- }
39
- desktopModeMediaQuery={desktopMediaQuery ?? desktopPickerMediaQuery}
40
- disabled={disabled}
41
- maxDate={maxDate && dayjs(maxDate)}
42
- minDate={minDate && dayjs(minDate)}
43
- value={dayjs(date)}
44
- onChange={changeTime}
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, inc } from 'ramda';
6
+ import { equals } from 'ramda';
7
7
  import { renderHook } from '@testing-library/react';
8
8
 
9
- import { LocalizationProvider } from '@mui/x-date-pickers';
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
- <LocalizationProvider adapterLocale="en" dateAdapter={Adapter}>
315
- <DateTimePickerInput
316
- changeDate={cy.stub()}
317
- date={new Date(item.initialDate)}
318
- desktopMediaQuery="@media (min-width: 1024px)"
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', inc(numberWeeks));
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', inc(numberWeeks));
395
+ cy.get('@listWeeks').should('have.length', numberWeeks);
420
396
 
421
397
  cy.get('@listWeeks')
422
398
  .eq(numberWeeks - 1)
@@ -23,4 +23,4 @@ export const getTimePeriodById = ({
23
23
  id,
24
24
  timePeriods
25
25
  }: TimePeriodById): TimePeriod =>
26
- find<TimePeriod>(propEq('id', id))(timePeriods) as TimePeriod;
26
+ find<TimePeriod>(propEq(id, 'id'))(timePeriods) as TimePeriod;
@@ -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<TimePeriod, 'timelineEventsLimit'>>;
37
+ extraTimePeriods?: Array<Omit<TimePeriodModel, 'timelineEventsLimit'>>;
38
38
  getIsError?: (value: boolean) => void;
39
39
  getParameters?: ({ start, end, timelineEventsLimit }: Parameters) => void;
40
40
  renderExternalComponent?: ReactNode;
@@ -7,7 +7,7 @@ const defaultCacheTime = 5 * 1_000;
7
7
  const client = new QueryClient({
8
8
  defaultOptions: {
9
9
  queries: {
10
- cacheTime: defaultCacheTime,
10
+ gcTime: defaultCacheTime,
11
11
  refetchOnWindowFocus: false,
12
12
  staleTime: defaultCacheTime,
13
13
  suspense: true
@@ -5,7 +5,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
5
5
  const client = new QueryClient({
6
6
  defaultOptions: {
7
7
  queries: {
8
- cacheTime: 0,
8
+ gcTime: 0,
9
9
  retry: false
10
10
  }
11
11
  }
@@ -25,7 +25,9 @@ export interface UseFetchQueryProps<T> {
25
25
  getQueryKey: () => QueryKey;
26
26
  httpCodesBypassErrorSnackbar?: Array<number>;
27
27
  isPaginated?: boolean;
28
- queryOptions?: Omit<
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
- getQueryKey(),
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
- ...queryOptions
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
- queryKey,
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
- getQueryKey(),
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
- manageError();
166
- }, useDeepCompare([queryData.data]));
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
- } & Omit<UseMutationOptions<T & { _meta?: TMeta }>, 'mutationFn'>;
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
- } & UseMutationResult<T | ResponseError>;
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
- (_payload: T & { _meta: TMeta }): Promise<T | ResponseError> => {
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
- onError,
80
- onMutate,
81
- onSuccess
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
- manageError();
102
- }, useDeepCompare([queryData.data]));
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.isLoading
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}
@@ -7,6 +7,8 @@ import {
7
7
  RoleResource
8
8
  } from '../AccessRights.resource';
9
9
 
10
+ faker.seed(42);
11
+
10
12
  export const rolesMock = (): Array<RoleResource> => [
11
13
  { role: 'viewer' },
12
14
  { role: 'editor' }
@@ -36,6 +36,6 @@ export const createInitialState = (
36
36
  contactAccessRight,
37
37
  state: 'unchanged',
38
38
  stateHistory: []
39
- } as ContactAccessRightStateResource)
39
+ }) as ContactAccessRightStateResource
40
40
  )
41
41
  .sort(sortOnAddedStateFirstAndContactName);
@@ -1,7 +1,8 @@
1
1
  import { ReactElement, useCallback, useMemo } from 'react';
2
2
 
3
- import * as Yup from 'yup';
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: Yup.object().shape({
88
- description: Yup.string()
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: Yup.object().shape({
97
- interval: Yup.number().when('type', {
98
- is: 'global',
99
- otherwise: Yup.number().nullable(),
100
- then: Yup.number()
101
- .min(1, ({ min }) => t(labelMustBeAtLeast, { min }))
102
- .required(t(labelRequired) as string)
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: Yup.string()
107
+ type: string()
105
108
  }),
106
- name: Yup.string()
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}