@centreon/ui 26.5.9 → 26.5.11
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 +3 -1
- package/src/@types/globals.d.ts +21 -0
- package/src/Colors/index.tsx +1 -1
- package/src/Dashboard/Item.tsx +11 -14
- package/src/Dialog/Duplicate/index.tsx +1 -1
- package/src/FileDropZone/useDropzone.test.ts +18 -15
- package/src/Form/Inputs/Checkbox.tsx +6 -3
- package/src/Form/Inputs/CheckboxGroup.tsx +8 -8
- package/src/Form/Inputs/ConnectedAutocomplete.tsx +9 -3
- package/src/Form/Inputs/FieldsTable/FieldsTable.tsx +1 -1
- package/src/Form/Inputs/File.tsx +3 -1
- package/src/Form/Inputs/Grid.tsx +1 -1
- package/src/Form/Inputs/List/List.tsx +8 -7
- package/src/Form/Inputs/List/useList.ts +12 -6
- package/src/Form/Inputs/Radio.tsx +7 -1
- package/src/Form/Inputs/Text.tsx +1 -1
- package/src/Form/Inputs/index.tsx +7 -2
- package/src/Form/storiesData.tsx +5 -2
- package/src/Graph/BarChart/Bar.tsx +2 -2
- package/src/Graph/BarChart/BarChart.tsx +2 -0
- package/src/Graph/BarChart/BarGroup.tsx +3 -0
- package/src/Graph/BarChart/BarStack.tsx +1 -0
- package/src/Graph/BarChart/MemoizedGroup.tsx +3 -1
- package/src/Graph/BarChart/ResponsiveBarChart.tsx +5 -0
- package/src/Graph/BarChart/Tooltip/BarChartTooltip.tsx +4 -0
- package/src/Graph/BarStack/Graph.tsx +3 -0
- package/src/Graph/Chart/BasicComponents/Lines/RegularLines/index.tsx +4 -1
- package/src/Graph/Chart/BasicComponents/Lines/StackedLines/index.tsx +7 -1
- package/src/Graph/Chart/BasicComponents/Lines/Threshold/BasicThreshold.tsx +1 -0
- package/src/Graph/Chart/BasicComponents/Lines/index.tsx +11 -1
- package/src/Graph/Chart/Chart.tsx +9 -0
- package/src/Graph/Chart/InteractiveComponents/AnchorPoint/StackedAnchorPoint.tsx +2 -0
- package/src/Graph/Chart/InteractiveComponents/AnchorPoint/useTickGraph.ts +2 -0
- package/src/Graph/Chart/InteractiveComponents/Annotations/annotationsAtoms.ts +5 -0
- package/src/Graph/Chart/InteractiveComponents/GraphValueTooltip/GraphValueTooltip.tsx +3 -0
- package/src/Graph/Chart/Legend/LegendHeader.tsx +1 -0
- package/src/Graph/Chart/Legend/index.tsx +6 -1
- package/src/Graph/Chart/useChartData.ts +6 -0
- package/src/Graph/Gauge/AnimatedPie.tsx +3 -0
- package/src/Graph/Gauge/PieData.tsx +5 -0
- package/src/Graph/Gauge/ResponsiveGauge.tsx +2 -0
- package/src/Graph/Gauge/Thresholds.tsx +1 -0
- package/src/Graph/HeatMap/ResponsiveHeatMap.tsx +1 -0
- package/src/Graph/SingleBar/ResponsiveSingleBar.tsx +2 -0
- package/src/Graph/Timeline/ResponsiveTimeline.tsx +1 -0
- package/src/Graph/Tree/Links.tsx +1 -0
- package/src/Graph/Tree/Tree.tsx +1 -0
- package/src/Graph/Tree/stories/datas.ts +2 -0
- package/src/Graph/common/Axes/index.tsx +3 -3
- package/src/Graph/common/BaseChart/BaseChart.tsx +3 -0
- package/src/Graph/common/BaseChart/ChartSvgWrapper.tsx +1 -0
- package/src/Graph/common/BaseChart/Header/models.ts +1 -0
- package/src/Graph/common/timeSeries/index.test.ts +17 -1
- package/src/Graph/common/timeSeries/index.ts +12 -0
- package/src/Graph/common/utils.ts +6 -2
- package/src/InputField/Number/Number.tsx +10 -4
- package/src/InputField/Search/PersistentTooltip.tsx +6 -5
- package/src/InputField/Select/Autocomplete/Connected/Single.tsx +3 -1
- package/src/InputField/Select/Autocomplete/Connected/index.test.tsx +1 -1
- package/src/InputField/Select/Autocomplete/Connected/index.tsx +5 -1
- package/src/InputField/Select/Autocomplete/Draggable/SortableList.tsx +4 -5
- package/src/InputField/Select/Autocomplete/Draggable/index.tsx +4 -5
- package/src/InputField/Select/Autocomplete/Multi/Listbox.tsx +16 -1
- package/src/InputField/Select/Autocomplete/Multi/Multi.tsx +44 -30
- package/src/InputField/Select/Autocomplete/Multi/index.tsx +1 -0
- package/src/InputField/Select/Autocomplete/index.tsx +7 -1
- package/src/InputField/Select/IconPopover/index.tsx +0 -3
- package/src/InputField/Select/Option.tsx +6 -1
- package/src/InputField/Select/index.tsx +3 -3
- package/src/InputField/Text/index.tsx +11 -3
- package/src/InputField/Text/useAutoSize.ts +2 -2
- package/src/Listing/ActionBar/index.tsx +2 -3
- package/src/Listing/Cell/index.tsx +24 -22
- package/src/Listing/Header/Cell/ListingHeaderCell.styles.ts +7 -0
- package/src/Listing/Header/ListingHeader.tsx +2 -2
- package/src/Listing/Header/_internals/PredefinedSelectionList.tsx +3 -3
- package/src/Listing/index.tsx +29 -34
- package/src/Listing/useStyleTable.ts +1 -1
- package/src/Module/index.tsx +3 -3
- package/src/MultiSelectEntries/index.tsx +1 -1
- package/src/Pagination/Pagination.tsx +1 -1
- package/src/ParentSize/ParentSize.tsx +2 -1
- package/src/PopoverMenu/index.tsx +1 -7
- package/src/RichTextEditor/ContentEditable.tsx +2 -0
- package/src/RichTextEditor/RichTextEditor.tsx +1 -0
- package/src/RichTextEditor/plugins/FloatingLinkEditorPlugin.tsx +1 -0
- package/src/RichTextEditor/plugins/ToolbarPlugin/BlockButtons.tsx +1 -0
- package/src/RichTextEditor/plugins/ToolbarPlugin/ListButton.tsx +2 -0
- package/src/Snackbar/index.tsx +3 -1
- package/src/SortableItems/Item.tsx +8 -7
- package/src/SortableItems/index.tsx +1 -1
- package/src/ThemeProvider/index.tsx +5 -3
- package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +3 -2
- package/src/TimePeriods/SelectedTimePeriod.tsx +1 -1
- package/src/TimePeriods/timePeriodsAtoms.ts +1 -1
- package/src/TimePeriods/useSortTimePeriods.ts +1 -1
- package/src/Typography/Subtitle.tsx +3 -1
- package/src/Typography/story.utils.tsx +3 -2
- package/src/Wizard/ActionsBar.tsx +2 -2
- package/src/api/QueryProvider.tsx +1 -2
- package/src/api/buildListingEndpoint/getSearchQueryParameterValue.ts +4 -2
- package/src/api/useGraphQuery/index.ts +11 -6
- package/src/api/useMutationQuery/index.ts +11 -7
- package/src/api/useMutationQuery/useOptimisticMutation.ts +34 -16
- package/src/api/useRequest/index.test.ts +1 -1
- package/src/api/useRequest/index.ts +1 -1
- package/src/components/Button/Button.tsx +2 -2
- package/src/components/CrudPage/Actions/Filters.tsx +1 -1
- package/src/components/CrudPage/Actions/useSearch.tsx +1 -1
- package/src/components/CrudPage/Columns/Actions.tsx +2 -2
- package/src/components/CrudPage/CrudPageRoot.tsx +1 -1
- package/src/components/CrudPage/DeleteModal.tsx +14 -6
- package/src/components/CrudPage/Form/AddModal.tsx +16 -4
- package/src/components/CrudPage/Form/UpdateModal.tsx +2 -2
- package/src/components/CrudPage/Listing.tsx +2 -1
- package/src/components/CrudPage/hooks/useDeleteItem.ts +5 -1
- package/src/components/CrudPage/hooks/useGetItem.ts +3 -3
- package/src/components/DataTable/DataListing.tsx +1 -1
- package/src/components/ExpandableContainer/ExpandableContainer.tsx +1 -0
- package/src/components/Form/AccessRights/Actions/Actions.tsx +1 -1
- package/src/components/Form/AccessRights/Actions/useActions.ts +1 -4
- package/src/components/Form/AccessRights/List/StateChip.tsx +1 -1
- package/src/components/Form/AccessRights/Stats/Stats.tsx +1 -1
- package/src/components/Form/AccessRights/common/RoleSelectField.tsx +4 -6
- package/src/components/Form/Dashboard/DashboardForm.tsx +2 -2
- package/src/components/Header/PageHeader/PageHeader.styles.ts +26 -20
- package/src/components/Menu/useMenu.tsx +3 -3
- package/src/components/Modal/ConfirmationModal/ConfirmationModal.tsx +14 -9
- package/src/components/Modal/Modal.tsx +5 -3
- package/src/components/Modal/ModalActions.tsx +1 -1
- package/src/components/Modal/ModalBody.tsx +2 -2
- package/src/components/Modal/ModalHeader.tsx +2 -2
- package/src/components/Tooltip/TextOverflowTooltip/TextOverflowTooltip.tsx +8 -2
- package/src/index.ts +1 -1
- package/src/utils/sanitizedHTML.ts +1 -1
- package/src/utils/useDebounce.ts +3 -1
- package/src/utils/useLicenseExpirationWarning.ts +11 -6
- package/src/utils/useLocaleDateTimeFormat/index.test.tsx +3 -1
- package/src/utils/useLocaleDateTimeFormat/localeFallback.test.tsx +3 -1
- package/src/utils/useMemoComponent.ts +1 -1
- package/src/utils/usePluralizedTranslation.test.ts +2 -0
- package/src/utils/useViewportIntersection.ts +3 -4
|
@@ -5,8 +5,8 @@ import { Method } from '.';
|
|
|
5
5
|
|
|
6
6
|
interface GetOptimisticMutationListingProps<T, TMeta> {
|
|
7
7
|
method: Method;
|
|
8
|
-
payload: T;
|
|
9
|
-
_meta: TMeta;
|
|
8
|
+
payload: T | undefined;
|
|
9
|
+
_meta: TMeta | undefined;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export interface OptimisticListing {
|
|
@@ -39,7 +39,7 @@ export const useOptimisticMutation = <T, TMeta>({
|
|
|
39
39
|
? optimisticListing?.queryKey
|
|
40
40
|
: [optimisticListing?.queryKey];
|
|
41
41
|
|
|
42
|
-
return listingQueryKey
|
|
42
|
+
return listingQueryKey as Array<string>;
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
const getPreviousListing = (): unknown => {
|
|
@@ -62,9 +62,12 @@ export const useOptimisticMutation = <T, TMeta>({
|
|
|
62
62
|
const listingQueryKey = getListingQueryKey();
|
|
63
63
|
|
|
64
64
|
const updatedPayload =
|
|
65
|
-
payload && 'id' in payload
|
|
65
|
+
payload && 'id' in (payload as Record<string, unknown>)
|
|
66
66
|
? payload
|
|
67
|
-
: {
|
|
67
|
+
: {
|
|
68
|
+
...(payload as Record<string, unknown>),
|
|
69
|
+
id: (optimisticListing?.total ?? 0) + 1
|
|
70
|
+
};
|
|
68
71
|
|
|
69
72
|
const hasOnlyOnePage =
|
|
70
73
|
(optimisticListing?.total || 0) <= (optimisticListing?.limit || 0);
|
|
@@ -74,19 +77,22 @@ export const useOptimisticMutation = <T, TMeta>({
|
|
|
74
77
|
queryClient.getQueriesData({
|
|
75
78
|
queryKey: listingQueryKey
|
|
76
79
|
})
|
|
77
|
-
)?.[1];
|
|
80
|
+
)?.[1] as { result: Array<Record<string, unknown>> } | undefined;
|
|
78
81
|
|
|
79
82
|
if (equals(Method.POST, method) && !isFormDataPayload && hasOnlyOnePage) {
|
|
80
|
-
const newItems = append(
|
|
83
|
+
const newItems = append(
|
|
84
|
+
updatedPayload as Record<string, unknown>,
|
|
85
|
+
items?.result ?? []
|
|
86
|
+
);
|
|
81
87
|
|
|
82
88
|
return { ...items, result: newItems };
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
if (equals(Method.DELETE, method) && hasOnlyOnePage) {
|
|
86
|
-
const itemIndex = items
|
|
87
|
-
equals(id, _meta
|
|
92
|
+
const itemIndex = items?.result.findIndex(({ id }) =>
|
|
93
|
+
equals(id, (_meta as Record<string, unknown>)?.id)
|
|
88
94
|
);
|
|
89
|
-
const newItems = remove(itemIndex, 1, items
|
|
95
|
+
const newItems = remove(itemIndex ?? 0, 1, items?.result ?? []);
|
|
90
96
|
|
|
91
97
|
return { ...items, result: newItems };
|
|
92
98
|
}
|
|
@@ -97,24 +103,36 @@ export const useOptimisticMutation = <T, TMeta>({
|
|
|
97
103
|
(equals(Method.POST, method) && isFormDataPayload)) &&
|
|
98
104
|
hasOnlyOnePage
|
|
99
105
|
) {
|
|
100
|
-
const itemIndex = items
|
|
101
|
-
equals(id, _meta
|
|
106
|
+
const itemIndex = items?.result.findIndex(({ id }) =>
|
|
107
|
+
equals(id, (_meta as Record<string, unknown>)?.id)
|
|
108
|
+
);
|
|
109
|
+
const item = items?.result.find(({ id }) =>
|
|
110
|
+
equals(id, (_meta as Record<string, unknown>)?.id)
|
|
102
111
|
);
|
|
103
|
-
const item = items.result.find(({ id }) => equals(id, _meta.id));
|
|
104
112
|
const updatedItem = equals(Method.PUT, method)
|
|
105
113
|
? updatedPayload
|
|
106
114
|
: {
|
|
107
115
|
...item,
|
|
108
116
|
...(isFormDataPayload
|
|
109
|
-
?
|
|
117
|
+
? (
|
|
118
|
+
Object as unknown as {
|
|
119
|
+
fromEntries: (
|
|
120
|
+
entries: IterableIterator<[string, FormDataEntryValue]>
|
|
121
|
+
) => Record<string, unknown>;
|
|
122
|
+
}
|
|
123
|
+
).fromEntries((updatedPayload as unknown as FormData).entries())
|
|
110
124
|
: updatedPayload)
|
|
111
125
|
};
|
|
112
|
-
const newItems = update(
|
|
126
|
+
const newItems = update(
|
|
127
|
+
itemIndex ?? 0,
|
|
128
|
+
updatedItem as Record<string, unknown>,
|
|
129
|
+
items?.result ?? []
|
|
130
|
+
);
|
|
113
131
|
|
|
114
132
|
return { ...items, result: newItems };
|
|
115
133
|
}
|
|
116
134
|
|
|
117
|
-
return items;
|
|
135
|
+
return items as object;
|
|
118
136
|
};
|
|
119
137
|
return { getListingQueryKey, getOptimisticMutationItems, getPreviousListing };
|
|
120
138
|
};
|
|
@@ -22,7 +22,7 @@ const request = jest.fn();
|
|
|
22
22
|
|
|
23
23
|
const renderUseRequest = (
|
|
24
24
|
requestParams: RequestParams<Result>
|
|
25
|
-
): RenderHookResult<
|
|
25
|
+
): RenderHookResult<RequestResult<Result>, unknown> =>
|
|
26
26
|
renderHook(() => useRequest(requestParams));
|
|
27
27
|
|
|
28
28
|
describe(useRequest, () => {
|
|
@@ -7,7 +7,7 @@ import { type ReactElement, type ReactNode, useMemo } from 'react';
|
|
|
7
7
|
|
|
8
8
|
import type { AriaLabelingAttributes } from '../../@types/aria-attributes';
|
|
9
9
|
import type { DataTestAttributes } from '../../@types/data-attributes';
|
|
10
|
-
import
|
|
10
|
+
import styles from './Button.module.css';
|
|
11
11
|
|
|
12
12
|
const muiVariantMap: Record<
|
|
13
13
|
Required<ButtonProps>['variant'],
|
|
@@ -58,7 +58,7 @@ const Button = ({
|
|
|
58
58
|
|
|
59
59
|
return (
|
|
60
60
|
<MuiButton
|
|
61
|
-
className={`${button} ${className}`}
|
|
61
|
+
className={`${styles.button} ${className}`}
|
|
62
62
|
data-icon-variant={iconVariant}
|
|
63
63
|
data-is-danger={isDanger}
|
|
64
64
|
data-size={size}
|
|
@@ -19,7 +19,7 @@ const Filters: React.FC<Props> = ({ label, filters }: Props): JSX.Element => {
|
|
|
19
19
|
title={label}
|
|
20
20
|
tooltipClassName={classes.tooltipFilters}
|
|
21
21
|
>
|
|
22
|
-
{isValidElement(filters) ? filters : <div />}
|
|
22
|
+
{isValidElement(filters) ? () => filters : () => <div />}
|
|
23
23
|
</PopoverMenu>
|
|
24
24
|
);
|
|
25
25
|
};
|
|
@@ -9,7 +9,7 @@ interface UseSearchState {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export const useSearch = (): UseSearchState => {
|
|
12
|
-
const timeoutRef = useRef<
|
|
12
|
+
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
13
13
|
|
|
14
14
|
const [search, setSearch] = useAtom(searchAtom);
|
|
15
15
|
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
interface Props<TData> {
|
|
18
18
|
row: TData & {
|
|
19
19
|
internalListingParentId?: number;
|
|
20
|
-
internalListingParentRow: TData;
|
|
20
|
+
internalListingParentRow: TData & { id: number };
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
|
|
@@ -64,7 +64,7 @@ const Actions = <TData extends { id: number; name: string }>({
|
|
|
64
64
|
<IconButton
|
|
65
65
|
data-testid={
|
|
66
66
|
row.internalListingParentRow
|
|
67
|
-
? `edit-${row.internalListingParentRow.id}-${row.id}`
|
|
67
|
+
? `edit-${(row.internalListingParentRow as TData & { id: number }).id}-${row.id}`
|
|
68
68
|
: `edit-${row.id}`
|
|
69
69
|
}
|
|
70
70
|
icon={<EditOutlined color="primary" fontSize="small" />}
|
|
@@ -36,7 +36,7 @@ export const CrudPageRoot = <
|
|
|
36
36
|
deleteItem,
|
|
37
37
|
form
|
|
38
38
|
}: CrudPageRootProps<TData, TFilters, TItem, TItemForm>): JSX.Element => {
|
|
39
|
-
const previousCanDeleteSubItemRef = useRef<boolean | undefined>();
|
|
39
|
+
const previousCanDeleteSubItemRef = useRef<boolean | undefined>(undefined);
|
|
40
40
|
const previousFormLabelButtonsRef = useRef<unknown | null>(null);
|
|
41
41
|
const { isDataEmpty, hasItems, isLoading, items, total } = useGetItems<
|
|
42
42
|
TData,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Box, CircularProgress, Typography } from '@mui/material';
|
|
2
2
|
|
|
3
3
|
import { useAtom } from 'jotai';
|
|
4
|
-
import { useCallback, useRef } from 'react';
|
|
4
|
+
import { type ReactElement, useCallback, useRef } from 'react';
|
|
5
5
|
|
|
6
6
|
import { Button } from '../Button';
|
|
7
7
|
import { Modal } from '../Modal';
|
|
@@ -35,7 +35,9 @@ const DeleteModal = <TData extends { id: number; name: string }>({
|
|
|
35
35
|
}, [setItemToDelete]);
|
|
36
36
|
|
|
37
37
|
const confirm = useCallback(() => {
|
|
38
|
-
|
|
38
|
+
if (itemToDeleteRef.current) {
|
|
39
|
+
deleteItem(itemToDeleteRef.current).then(close);
|
|
40
|
+
}
|
|
39
41
|
}, [close, deleteItem]);
|
|
40
42
|
|
|
41
43
|
if (isOpen) {
|
|
@@ -46,14 +48,20 @@ const DeleteModal = <TData extends { id: number; name: string }>({
|
|
|
46
48
|
<Modal onClose={close} open={isOpen} size={modalSize}>
|
|
47
49
|
<Modal.Header>
|
|
48
50
|
{isAFunction(labels.title)
|
|
49
|
-
? labels.title
|
|
50
|
-
|
|
51
|
+
? (labels.title as (item: ItemToDelete) => string | ReactElement)(
|
|
52
|
+
itemToDeleteRef.current as TData
|
|
53
|
+
)
|
|
54
|
+
: (labels.title as string | ReactElement)}
|
|
51
55
|
</Modal.Header>
|
|
52
56
|
<Modal.Body>
|
|
53
57
|
<Typography>
|
|
54
58
|
{isAFunction(labels.description)
|
|
55
|
-
?
|
|
56
|
-
|
|
59
|
+
? (
|
|
60
|
+
labels.description as (
|
|
61
|
+
item: ItemToDelete
|
|
62
|
+
) => string | ReactElement
|
|
63
|
+
)(itemToDeleteRef.current as TData)
|
|
64
|
+
: (labels.description as string | ReactElement)}
|
|
57
65
|
</Typography>
|
|
58
66
|
</Modal.Body>
|
|
59
67
|
<Box
|
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
import { useAtomValue, useSetAtom } from 'jotai';
|
|
2
|
-
import {
|
|
2
|
+
import { isNotNil } from 'ramda';
|
|
3
3
|
import { useCallback, useMemo } from 'react';
|
|
4
4
|
|
|
5
5
|
import { Modal } from '../../Modal';
|
|
6
6
|
import { askBeforeCloseFormModalAtom, openFormModalAtom } from '../atoms';
|
|
7
7
|
import Buttons from './Buttons';
|
|
8
8
|
|
|
9
|
-
const AddModal = ({
|
|
9
|
+
const AddModal = ({
|
|
10
|
+
title,
|
|
11
|
+
Form,
|
|
12
|
+
modalSize = 'medium'
|
|
13
|
+
}: {
|
|
14
|
+
title: string;
|
|
15
|
+
Form: (props: { Buttons: () => JSX.Element }) => JSX.Element;
|
|
16
|
+
modalSize?: 'small' | 'medium' | 'large' | 'xlarge' | 'fullscreen';
|
|
17
|
+
}): JSX.Element => {
|
|
10
18
|
const setAskBeforeCloseFormModal = useSetAtom(askBeforeCloseFormModalAtom);
|
|
11
19
|
|
|
12
20
|
const openFormModal = useAtomValue(openFormModalAtom);
|
|
13
21
|
|
|
14
22
|
const isModalOpen = useMemo(
|
|
15
|
-
() => isNotNil(openFormModal) &&
|
|
23
|
+
() => isNotNil(openFormModal) && openFormModal === 'add',
|
|
16
24
|
[openFormModal]
|
|
17
25
|
);
|
|
18
26
|
|
|
@@ -22,7 +30,11 @@ const AddModal = ({ title, Form, modalSize = 'medium' }): JSX.Element => {
|
|
|
22
30
|
);
|
|
23
31
|
|
|
24
32
|
return (
|
|
25
|
-
<Modal
|
|
33
|
+
<Modal
|
|
34
|
+
onClose={openAskBeforeClose}
|
|
35
|
+
open={isModalOpen}
|
|
36
|
+
size={modalSize as 'small' | 'medium' | 'large' | 'xlarge' | 'fullscreen'}
|
|
37
|
+
>
|
|
26
38
|
<Modal.Header>{title}</Modal.Header>
|
|
27
39
|
<Modal.Body>
|
|
28
40
|
<Form Buttons={Buttons} />
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useAtomValue, useSetAtom } from 'jotai';
|
|
2
|
-
import {
|
|
2
|
+
import { isNotNil } from 'ramda';
|
|
3
3
|
import { useCallback, useMemo } from 'react';
|
|
4
4
|
|
|
5
5
|
import { Modal } from '../..';
|
|
@@ -33,7 +33,7 @@ const UpdateModal = <TItem extends { id: number; name: string }, TItemForm>({
|
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
const isModalOpen = useMemo(
|
|
36
|
-
() => isNotNil(openFormModal) &&
|
|
36
|
+
() => isNotNil(openFormModal) && openFormModal !== 'add',
|
|
37
37
|
[openFormModal]
|
|
38
38
|
);
|
|
39
39
|
|
|
@@ -47,6 +47,7 @@ const Listing = <TData extends { id: number; name: string }>({
|
|
|
47
47
|
actions={<Actions filters={filters} labels={labels} />}
|
|
48
48
|
columns={listingColumns}
|
|
49
49
|
currentPage={page}
|
|
50
|
+
isActionBarVisible
|
|
50
51
|
limit={limit}
|
|
51
52
|
loading={isLoading}
|
|
52
53
|
onLimitChange={setLimit}
|
|
@@ -54,7 +55,7 @@ const Listing = <TData extends { id: number; name: string }>({
|
|
|
54
55
|
onSort={changeSort}
|
|
55
56
|
rows={rows}
|
|
56
57
|
sortField={sortField}
|
|
57
|
-
sortOrder={sortOrder}
|
|
58
|
+
sortOrder={sortOrder as 'asc' | 'desc' | undefined}
|
|
58
59
|
subItems={subItems}
|
|
59
60
|
totalRows={total}
|
|
60
61
|
/>
|
|
@@ -40,7 +40,11 @@ export const useDeleteItem = ({
|
|
|
40
40
|
onSuccess: (_data, { _meta }) => {
|
|
41
41
|
queryClient.invalidateQueries({ queryKey: [listingQueryKey] });
|
|
42
42
|
showSuccessMessage(
|
|
43
|
-
isAFunction(successMessage)
|
|
43
|
+
(isAFunction(successMessage)
|
|
44
|
+
? (successMessage as (item: ItemToDelete) => string | ReactElement)(
|
|
45
|
+
_meta as ItemToDelete
|
|
46
|
+
)
|
|
47
|
+
: successMessage) as string
|
|
44
48
|
);
|
|
45
49
|
}
|
|
46
50
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isNotNil } from 'ramda';
|
|
2
2
|
|
|
3
3
|
import { useFetchQuery } from '../../..';
|
|
4
4
|
import type { GetItem } from '../models';
|
|
@@ -22,10 +22,10 @@ export const useGetItem = <
|
|
|
22
22
|
}): UseGetItem<TItemForm> => {
|
|
23
23
|
const { data, isLoading } = useFetchQuery<TItem>({
|
|
24
24
|
decoder,
|
|
25
|
-
getEndpoint: () => baseEndpoint(id),
|
|
25
|
+
getEndpoint: () => baseEndpoint(id as number),
|
|
26
26
|
getQueryKey: () => [itemQueryKey, id],
|
|
27
27
|
queryOptions: {
|
|
28
|
-
enabled: isNotNil(id) &&
|
|
28
|
+
enabled: isNotNil(id) && id !== 'add',
|
|
29
29
|
suspense: false
|
|
30
30
|
}
|
|
31
31
|
});
|
|
@@ -30,10 +30,7 @@ export const useActions = ({ submit, clear }: Props): UseActionsState => {
|
|
|
30
30
|
const save = (): void => {
|
|
31
31
|
submit(
|
|
32
32
|
values.filter(({ isRemoved }) => !isRemoved).map(formatValueForSubmition)
|
|
33
|
-
)?.then((
|
|
34
|
-
if (isError) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
33
|
+
)?.then(() => {
|
|
37
34
|
clear();
|
|
38
35
|
});
|
|
39
36
|
};
|
|
@@ -12,7 +12,7 @@ const StateChip = ({ label, state }: Props): JSX.Element => {
|
|
|
12
12
|
const { classes, cx } = useListStyles();
|
|
13
13
|
|
|
14
14
|
return (
|
|
15
|
-
<div className={cx(classes.state)}>
|
|
15
|
+
<div className={cx((classes as Record<string, string>).state)}>
|
|
16
16
|
<Chip
|
|
17
17
|
className={classes.stateChip}
|
|
18
18
|
data-state={state}
|
|
@@ -11,7 +11,7 @@ interface Props {
|
|
|
11
11
|
labels: Labels['list'];
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const Stats = ({ labels }: Props): JSX.Element => {
|
|
14
|
+
const Stats = ({ labels }: Props): JSX.Element | null => {
|
|
15
15
|
const { t } = useTranslation();
|
|
16
16
|
const { hasStats, addedItems, updatedItems, removedItems } =
|
|
17
17
|
useAtomValue(statsDerivedAtom);
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { SelectChangeEvent } from '@mui/material';
|
|
2
|
-
|
|
3
1
|
import SelectField, { type SelectEntry } from '../../../../InputField/Select';
|
|
4
2
|
import { useRoleSelectField } from './RoleSelectField.styles';
|
|
5
3
|
|
|
@@ -21,18 +19,18 @@ const RoleSelectField = ({
|
|
|
21
19
|
disabled
|
|
22
20
|
}: Props): JSX.Element => {
|
|
23
21
|
const { classes } = useRoleSelectField();
|
|
24
|
-
const change = (event: SelectChangeEvent): void => {
|
|
25
|
-
onChange(event.target.value as string);
|
|
26
|
-
};
|
|
27
22
|
|
|
28
23
|
return (
|
|
29
24
|
<div className={classes.roleContainer}>
|
|
30
25
|
<SelectField
|
|
31
26
|
dataTestId={testId}
|
|
32
27
|
disabled={disabled}
|
|
28
|
+
formControlProps={{}}
|
|
33
29
|
fullWidth
|
|
34
30
|
label={label}
|
|
35
|
-
onChange={
|
|
31
|
+
onChange={(event) => {
|
|
32
|
+
onChange(event.target.value);
|
|
33
|
+
}}
|
|
36
34
|
options={roles}
|
|
37
35
|
selectedOptionId={value}
|
|
38
36
|
size="small"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { equals } from 'ramda';
|
|
2
2
|
import { type ReactElement, useCallback, useMemo } from 'react';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
|
-
import { number, object, string } from 'yup';
|
|
4
|
+
import { number, object, type Schema, string } from 'yup';
|
|
5
5
|
|
|
6
6
|
import { Form, type FormProps } from '../../../Form';
|
|
7
7
|
import { InputType } from '../../../Form/Inputs/models';
|
|
@@ -109,7 +109,7 @@ const DashboardForm = ({
|
|
|
109
109
|
.min(3, ({ min, label }) => t(labelMustBeAtLeast, { label, min }))
|
|
110
110
|
.max(50, ({ max, label }) => t(labelMustBeMost, { label, max }))
|
|
111
111
|
.required(t(labelRequired) as string)
|
|
112
|
-
})
|
|
112
|
+
}) as unknown as Schema<DashboardResource>
|
|
113
113
|
}),
|
|
114
114
|
[resource, labels, onSubmit, showRefreshIntervalFields, t]
|
|
115
115
|
);
|
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
import { alpha } from '@mui/system';
|
|
2
2
|
|
|
3
|
+
import type { CSSObject } from 'tss-react';
|
|
3
4
|
import { makeStyles } from 'tss-react/mui';
|
|
4
5
|
|
|
5
6
|
const useStyles = makeStyles()((theme) => ({
|
|
6
7
|
header: {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
flexDirection: 'row',
|
|
11
|
-
h1: {
|
|
12
|
-
...theme.typography.h5,
|
|
8
|
+
'& h1': {
|
|
9
|
+
fontFamily: theme.typography.h5.fontFamily,
|
|
10
|
+
fontSize: theme.typography.h5.fontSize,
|
|
13
11
|
fontWeight: theme.typography.fontWeightMedium,
|
|
12
|
+
letterSpacing: theme.typography.h5.letterSpacing,
|
|
13
|
+
lineHeight: theme.typography.h5.lineHeight,
|
|
14
14
|
margin: theme.spacing(0, 0, 1.5, 0)
|
|
15
|
-
},
|
|
16
|
-
justifyContent: 'space-between',
|
|
15
|
+
} as CSSObject,
|
|
17
16
|
|
|
18
|
-
nav: {
|
|
17
|
+
'& nav': {
|
|
19
18
|
display: 'flex',
|
|
20
19
|
gap: theme.spacing(1),
|
|
21
20
|
justifyContent: 'flex-end'
|
|
22
|
-
},
|
|
21
|
+
} as CSSObject,
|
|
22
|
+
alignItems: 'flex-start',
|
|
23
|
+
borderBottom: `1px solid ${theme.palette.primary.main}`,
|
|
24
|
+
display: 'flex',
|
|
25
|
+
flexDirection: 'row',
|
|
26
|
+
justifyContent: 'space-between',
|
|
23
27
|
|
|
24
28
|
padding: theme.spacing(0, 0, 1.5, 0)
|
|
25
29
|
},
|
|
@@ -39,7 +43,7 @@ const useStyles = makeStyles()((theme) => ({
|
|
|
39
43
|
backgroundColor: theme.palette.header.page.action.background.default,
|
|
40
44
|
|
|
41
45
|
color: theme.palette.header.page.action.color.default
|
|
42
|
-
},
|
|
46
|
+
} as CSSObject,
|
|
43
47
|
display: 'flex',
|
|
44
48
|
|
|
45
49
|
gap: theme.spacing(2)
|
|
@@ -84,28 +88,30 @@ const useStyles = makeStyles()((theme) => ({
|
|
|
84
88
|
pageHeaderTitle: {
|
|
85
89
|
'& > *': {
|
|
86
90
|
display: 'grid'
|
|
87
|
-
},
|
|
91
|
+
} as CSSObject,
|
|
88
92
|
'& > span': {
|
|
89
93
|
alignItems: 'center',
|
|
90
94
|
display: 'flex',
|
|
91
95
|
flexDirection: 'row',
|
|
92
96
|
gap: theme.spacing(2)
|
|
93
|
-
},
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
h1: {
|
|
98
|
-
...theme.typography.h5,
|
|
97
|
+
} as CSSObject,
|
|
98
|
+
'& h1': {
|
|
99
|
+
fontFamily: theme.typography.h5.fontFamily,
|
|
100
|
+
fontSize: theme.typography.h5.fontSize,
|
|
99
101
|
fontWeight: theme.typography.fontWeightBold,
|
|
102
|
+
letterSpacing: theme.typography.h5.letterSpacing,
|
|
100
103
|
lineHeight: '1',
|
|
101
104
|
margin: theme.spacing(0)
|
|
102
|
-
}
|
|
105
|
+
} as CSSObject,
|
|
106
|
+
alignSelf: 'flex-start',
|
|
107
|
+
display: 'flex',
|
|
108
|
+
flexDirection: 'column'
|
|
103
109
|
},
|
|
104
110
|
pageHeaderTitleActions: {
|
|
105
111
|
'& > button': {
|
|
106
112
|
opacity: 0.2,
|
|
107
113
|
padding: 0
|
|
108
|
-
},
|
|
114
|
+
} as CSSObject,
|
|
109
115
|
alignItems: 'bottom',
|
|
110
116
|
display: 'flex',
|
|
111
117
|
gap: theme.spacing(1),
|
|
@@ -37,9 +37,9 @@ const MenuProvider = ({
|
|
|
37
37
|
[
|
|
38
38
|
[isMenuOpenAtom, initialIsOpen ?? false],
|
|
39
39
|
[anchorElAtom, null],
|
|
40
|
-
[onOpenAtom, onOpen],
|
|
41
|
-
[onCloseAtom, onClose]
|
|
42
|
-
],
|
|
40
|
+
[onOpenAtom, onOpen ?? null],
|
|
41
|
+
[onCloseAtom, onClose ?? null]
|
|
42
|
+
] as unknown as Parameters<typeof useHydrateAtoms>[0],
|
|
43
43
|
{ store: menuStore }
|
|
44
44
|
);
|
|
45
45
|
|
|
@@ -42,29 +42,34 @@ export const ConfirmationModal = <TAtom,>({
|
|
|
42
42
|
disabled,
|
|
43
43
|
size
|
|
44
44
|
}: ConfirmationModalProps<TAtom>): JSX.Element => {
|
|
45
|
-
const [atomData, setAtomData] = useAtom
|
|
45
|
+
const [atomData, setAtomData] = useAtom(atom);
|
|
46
|
+
|
|
47
|
+
const typedAtomData = atomData as Awaited<TAtom> | null;
|
|
46
48
|
|
|
47
49
|
const closeModal = (): void => {
|
|
48
|
-
onClose?.(
|
|
50
|
+
onClose?.(typedAtomData);
|
|
49
51
|
setAtomData(null);
|
|
50
52
|
};
|
|
51
53
|
|
|
52
54
|
const formattedLabels = useMemo(() => {
|
|
53
55
|
return {
|
|
54
|
-
cancel: getLabel({ atomData, label: labels.cancel }),
|
|
55
|
-
confirm: getLabel({ atomData, label: labels.confirm }),
|
|
56
|
-
description: getLabel({
|
|
57
|
-
|
|
56
|
+
cancel: getLabel({ atomData: typedAtomData, label: labels.cancel }),
|
|
57
|
+
confirm: getLabel({ atomData: typedAtomData, label: labels.confirm }),
|
|
58
|
+
description: getLabel({
|
|
59
|
+
atomData: typedAtomData,
|
|
60
|
+
label: labels.description
|
|
61
|
+
}),
|
|
62
|
+
title: getLabel({ atomData: typedAtomData, label: labels.title })
|
|
58
63
|
};
|
|
59
|
-
}, [labels,
|
|
64
|
+
}, [labels, typedAtomData]);
|
|
60
65
|
|
|
61
66
|
const confirm = (): void => {
|
|
62
|
-
onConfirm?.(
|
|
67
|
+
onConfirm?.(typedAtomData);
|
|
63
68
|
setAtomData(null);
|
|
64
69
|
};
|
|
65
70
|
|
|
66
71
|
const cancel = (): void => {
|
|
67
|
-
onCancel?.(
|
|
72
|
+
onCancel?.(typedAtomData);
|
|
68
73
|
setAtomData(null);
|
|
69
74
|
};
|
|
70
75
|
|
|
@@ -54,9 +54,11 @@ const Modal = ({
|
|
|
54
54
|
onClose={onClose}
|
|
55
55
|
open={open}
|
|
56
56
|
TransitionComponent={isFullscreen ? Slide : undefined}
|
|
57
|
-
TransitionProps={
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
TransitionProps={
|
|
58
|
+
{
|
|
59
|
+
direction: 'up'
|
|
60
|
+
} as Record<string, unknown>
|
|
61
|
+
}
|
|
60
62
|
{...attr}
|
|
61
63
|
>
|
|
62
64
|
{hasCloseButton && (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ReactElement, ReactNode } from 'react';
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import styles from './modal.module.css';
|
|
4
4
|
|
|
5
5
|
export type ModalHeaderProps = {
|
|
6
6
|
children?: ReactNode;
|
|
@@ -8,7 +8,7 @@ export type ModalHeaderProps = {
|
|
|
8
8
|
|
|
9
9
|
const ModalBody = ({ children }: ModalHeaderProps): ReactElement => {
|
|
10
10
|
return (
|
|
11
|
-
<div className={modalBody} data-testid="modal-body">
|
|
11
|
+
<div className={styles.modalBody} data-testid="modal-body">
|
|
12
12
|
{children}
|
|
13
13
|
</div>
|
|
14
14
|
);
|