@campxdev/react-blueprint 1.6.4 → 1.6.6
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/.storybook/preview.tsx +1 -2
- package/package.json +1 -1
- package/src/App.tsx +71 -46
- package/src/components/Assets/Icons/IconComponents/PrinterIcon.tsx +42 -0
- package/src/components/Assets/Icons/Icons.tsx +2 -0
- package/src/components/DataDisplay/ActivityLogView/ActivityLogView.tsx +228 -0
- package/src/components/DataDisplay/ActivityLogView/Icons.tsx +65 -0
- package/src/components/DataDisplay/ActivityLogView/service.tsx +101 -0
- package/src/components/DataDisplay/ActivityLogView/styles.tsx +52 -0
- package/src/components/DataDisplay/Card/Card.tsx +1 -1
- package/src/components/DataDisplay/DataTable/TablePagination.tsx +4 -0
- package/src/components/DataDisplay/EditableDataTable/EditableDataTable.tsx +32 -21
- package/src/components/DataDisplay/export.ts +1 -0
- package/src/components/Feedback/Tooltip/ToolTipContent.tsx +15 -0
- package/src/components/Feedback/Tooltip/Tooltip.tsx +3 -17
- package/src/components/Feedback/export.ts +1 -0
- package/src/components/Input/SingleSelect/SingleSelect.tsx +22 -5
- package/src/components/Layout/PageHeader/PageHeader.tsx +52 -42
- package/src/components/Layout/PageHeader/components/DensitySelector/DensitySelector.tsx +2 -2
- package/src/components/Layout/PageHeader/components/SearchBar.tsx +66 -0
- package/src/components/Layout/PageHeader/components/TableColumnsSelector/TableColumnsSelector.tsx +14 -4
- package/src/components/Navigation/ConfirmDialog/ConfirmDialog.tsx +2 -2
- package/src/hooks/usePageHeader.ts +51 -12
- package/src/redux/slices/pageHeaderSlice.ts +71 -9
- package/src/stories/DataDisplay/ActivityLogView.stories.tsx +96 -0
- package/src/stories/Feedback/Tooltip.stories.tsx +2 -6
- package/src/stories/Input/TextField.stories.tsx +2 -2
|
@@ -16,10 +16,11 @@ import { v4 } from 'uuid';
|
|
|
16
16
|
import { DataTable, DataTableProps, Icons } from '../../export';
|
|
17
17
|
|
|
18
18
|
export type EditableDataTableProps = {
|
|
19
|
-
hideDelete?: boolean;
|
|
20
19
|
onChange: (rows: GridValidRowModel) => void;
|
|
21
20
|
onSave?: (params: any) => void;
|
|
22
21
|
onDelete?: (params: any) => void;
|
|
22
|
+
editVisibilityArray?: number[];
|
|
23
|
+
deleteVisibilityArray?: number[];
|
|
23
24
|
} & Omit<
|
|
24
25
|
DataTableProps,
|
|
25
26
|
| 'rowModesModel'
|
|
@@ -29,7 +30,7 @@ export type EditableDataTableProps = {
|
|
|
29
30
|
>;
|
|
30
31
|
|
|
31
32
|
export const EditableDataTable = (props: EditableDataTableProps) => {
|
|
32
|
-
const { rows } = props;
|
|
33
|
+
const { rows = [] } = props;
|
|
33
34
|
|
|
34
35
|
useEffect(() => {}, [props.columns]);
|
|
35
36
|
|
|
@@ -43,7 +44,7 @@ export const EditableDataTable = (props: EditableDataTableProps) => {
|
|
|
43
44
|
|
|
44
45
|
export const EditableTableCore = (props: EditableDataTableProps) => {
|
|
45
46
|
const theme = useTheme();
|
|
46
|
-
const { rows, columns } = props;
|
|
47
|
+
const { rows = [], columns } = props;
|
|
47
48
|
const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({});
|
|
48
49
|
const processRowUpdate = (newRow: GridRowModel) => {
|
|
49
50
|
const updatedRow = { ...newRow, isNew: false };
|
|
@@ -86,6 +87,12 @@ export const EditableTableCore = (props: EditableDataTableProps) => {
|
|
|
86
87
|
props.onChange(rows?.filter((row) => row.id !== params.id) ?? []);
|
|
87
88
|
};
|
|
88
89
|
|
|
90
|
+
const deleteVisibilityArray =
|
|
91
|
+
props.deleteVisibilityArray || rows.map((row) => row.id);
|
|
92
|
+
|
|
93
|
+
const editVisibilityArray =
|
|
94
|
+
props.editVisibilityArray || rows.map((row) => row.id);
|
|
95
|
+
|
|
89
96
|
return (
|
|
90
97
|
<>
|
|
91
98
|
<DataTable
|
|
@@ -159,25 +166,29 @@ export const EditableTableCore = (props: EditableDataTableProps) => {
|
|
|
159
166
|
cellClassName: 'actions',
|
|
160
167
|
getActions: (params) => {
|
|
161
168
|
const actions = [];
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
169
|
+
|
|
170
|
+
if (editVisibilityArray.includes(params.row.id)) {
|
|
171
|
+
if (rowModesModel[params.id]?.mode === GridRowModes.Edit) {
|
|
172
|
+
actions.push(
|
|
173
|
+
<GridActionsCellItem
|
|
174
|
+
icon={<Icons.SaveIcon />}
|
|
175
|
+
label="Save"
|
|
176
|
+
onClick={() => handleSaveClick(params)}
|
|
177
|
+
/>,
|
|
178
|
+
);
|
|
179
|
+
} else {
|
|
180
|
+
actions.push(
|
|
181
|
+
<GridActionsCellItem
|
|
182
|
+
icon={<Icons.EditIcon />}
|
|
183
|
+
label="Edit"
|
|
184
|
+
onClick={() => handleEditClick(params)}
|
|
185
|
+
color="inherit"
|
|
186
|
+
/>,
|
|
187
|
+
);
|
|
188
|
+
}
|
|
179
189
|
}
|
|
180
|
-
|
|
190
|
+
|
|
191
|
+
if (deleteVisibilityArray.includes(params.row.id)) {
|
|
181
192
|
actions.push(
|
|
182
193
|
<GridActionsCellItem
|
|
183
194
|
icon={<Icons.DeleteIcon />}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Stack } from '@mui/material';
|
|
2
|
+
import { Icons, Typography } from '../../export';
|
|
3
|
+
import { TooltipContentProps } from './Tooltip';
|
|
4
|
+
|
|
5
|
+
export const ToolTipContent = ({ message }: TooltipContentProps) => {
|
|
6
|
+
return (
|
|
7
|
+
<Stack gap={1} sx={{ margin: '5px' }}>
|
|
8
|
+
<Stack direction="row" gap={1}>
|
|
9
|
+
<Icons.BulbIcon />
|
|
10
|
+
<Typography variant="subtitle3">Note:</Typography>
|
|
11
|
+
</Stack>
|
|
12
|
+
<Typography variant="caption">{message}</Typography>
|
|
13
|
+
</Stack>
|
|
14
|
+
);
|
|
15
|
+
};
|
|
@@ -2,14 +2,11 @@ import {
|
|
|
2
2
|
IconButton,
|
|
3
3
|
Tooltip as MuiTooltip,
|
|
4
4
|
TooltipProps as MuiTooltipProps,
|
|
5
|
-
Stack,
|
|
6
5
|
} from '@mui/material';
|
|
7
|
-
import { Children,
|
|
8
|
-
import { BulbIcon } from '../../Assets/Icons/IconComponents/BulbIcon';
|
|
9
|
-
import { Typography } from '../../DataDisplay/Typography/Typography';
|
|
6
|
+
import { Children, ReactNode } from 'react';
|
|
10
7
|
|
|
11
8
|
export type TooltipProps = {
|
|
12
|
-
children:
|
|
9
|
+
children: ReactNode;
|
|
13
10
|
} & MuiTooltipProps;
|
|
14
11
|
export type TooltipContentProps = { message: string };
|
|
15
12
|
|
|
@@ -19,6 +16,7 @@ export const Tooltip = ({
|
|
|
19
16
|
...props
|
|
20
17
|
}: TooltipProps) => {
|
|
21
18
|
const isIconButton = Children.only(props.children).type === IconButton;
|
|
19
|
+
|
|
22
20
|
return (
|
|
23
21
|
<MuiTooltip {...props} placement={placement} arrow={arrow}>
|
|
24
22
|
{isIconButton ? (
|
|
@@ -29,15 +27,3 @@ export const Tooltip = ({
|
|
|
29
27
|
</MuiTooltip>
|
|
30
28
|
);
|
|
31
29
|
};
|
|
32
|
-
|
|
33
|
-
export const ToolTipContent = ({ message }: TooltipContentProps) => {
|
|
34
|
-
return (
|
|
35
|
-
<Stack gap={1} sx={{ margin: '5px' }}>
|
|
36
|
-
<Stack direction="row" gap={1}>
|
|
37
|
-
<BulbIcon />
|
|
38
|
-
<Typography variant="subtitle3">Note:</Typography>
|
|
39
|
-
</Stack>
|
|
40
|
-
<Typography variant="caption">{message}</Typography>
|
|
41
|
-
</Stack>
|
|
42
|
-
);
|
|
43
|
-
};
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
Paper,
|
|
7
7
|
} from '@mui/material';
|
|
8
8
|
import axios, { AxiosInstance } from 'axios';
|
|
9
|
-
import _, { debounce } from 'lodash';
|
|
9
|
+
import _, { debounce, startCase } from 'lodash';
|
|
10
10
|
import { SyntheticEvent, useEffect, useMemo, useReducer } from 'react';
|
|
11
11
|
import { Typography } from '../../DataDisplay/Typography/Typography';
|
|
12
12
|
import { Spinner } from '../../Feedback/Spinner/Spinner';
|
|
@@ -49,7 +49,12 @@ export type SingleSelectProps = {
|
|
|
49
49
|
isInt?: boolean;
|
|
50
50
|
isFloat?: boolean;
|
|
51
51
|
};
|
|
52
|
-
dbLabelProps?: {
|
|
52
|
+
dbLabelProps?: {
|
|
53
|
+
labelKey: string;
|
|
54
|
+
subLabelKey?: string;
|
|
55
|
+
useLabelStartCase?: boolean;
|
|
56
|
+
useSubLabelStartCase?: boolean;
|
|
57
|
+
};
|
|
53
58
|
onChange?: (value: any) => void;
|
|
54
59
|
error?: any;
|
|
55
60
|
helperText?: string;
|
|
@@ -102,7 +107,11 @@ export const SingleSelect = ({
|
|
|
102
107
|
isInt: false,
|
|
103
108
|
isFloat: false,
|
|
104
109
|
},
|
|
105
|
-
dbLabelProps
|
|
110
|
+
dbLabelProps = {
|
|
111
|
+
labelKey: '',
|
|
112
|
+
useLabelStartCase: false,
|
|
113
|
+
useSubLabelStartCase: false,
|
|
114
|
+
},
|
|
106
115
|
onOpen,
|
|
107
116
|
onClose,
|
|
108
117
|
...restProps
|
|
@@ -451,8 +460,16 @@ export const SingleSelect = ({
|
|
|
451
460
|
return (
|
|
452
461
|
<Box component="li" {...props} key={option.value}>
|
|
453
462
|
<OptionContainer>
|
|
454
|
-
<Typography variant="label1">
|
|
455
|
-
|
|
463
|
+
<Typography variant="label1">
|
|
464
|
+
{dbLabelProps.useLabelStartCase
|
|
465
|
+
? startCase(option.label)
|
|
466
|
+
: option.label}
|
|
467
|
+
</Typography>
|
|
468
|
+
<Typography variant="caption">
|
|
469
|
+
{dbLabelProps.useSubLabelStartCase
|
|
470
|
+
? startCase(option?.subLabel)
|
|
471
|
+
: option?.subLabel}
|
|
472
|
+
</Typography>
|
|
456
473
|
</OptionContainer>
|
|
457
474
|
</Box>
|
|
458
475
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Box, Divider, Stack, useTheme } from '@mui/material';
|
|
2
2
|
import { GridColDef } from '@mui/x-data-grid';
|
|
3
|
-
import { motion } from 'framer-motion';
|
|
3
|
+
import { AnimatePresence, motion } from 'framer-motion';
|
|
4
4
|
import { ReactNode, useState } from 'react';
|
|
5
5
|
import {
|
|
6
6
|
DensitySelector,
|
|
@@ -8,13 +8,19 @@ import {
|
|
|
8
8
|
TableColumnsSelector,
|
|
9
9
|
Typography,
|
|
10
10
|
} from '../../export';
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
ColumnsAnchor,
|
|
13
|
+
FiltersAnchor,
|
|
14
|
+
SearchAnchor,
|
|
15
|
+
} from './components/Anchors';
|
|
16
|
+
import { SearchBar } from './components/SearchBar';
|
|
12
17
|
|
|
13
18
|
interface PageHeaderProps {
|
|
14
|
-
uniqueId
|
|
19
|
+
uniqueId?: string;
|
|
15
20
|
viewsSlot?: ReactNode;
|
|
16
21
|
actions?: ReactNode[];
|
|
17
22
|
columns?: GridColDef[];
|
|
23
|
+
searchText?: string;
|
|
18
24
|
}
|
|
19
25
|
|
|
20
26
|
const ViewTab = ({ title }: { title: string }) => {
|
|
@@ -42,19 +48,16 @@ const motionDivVariants = {
|
|
|
42
48
|
expanded: { height: '102px' },
|
|
43
49
|
};
|
|
44
50
|
|
|
45
|
-
const motionTextFieldVariants = {
|
|
46
|
-
collapsed: { width: '40px' },
|
|
47
|
-
expanded: { width: '300px' },
|
|
48
|
-
};
|
|
49
|
-
|
|
50
51
|
export const PageHeader = ({
|
|
51
52
|
uniqueId,
|
|
52
53
|
actions,
|
|
53
54
|
columns,
|
|
54
55
|
viewsSlot = <Box></Box>,
|
|
56
|
+
searchText = 'Search',
|
|
55
57
|
}: PageHeaderProps) => {
|
|
56
58
|
const [expanded, setExpanded] = useState(false);
|
|
57
59
|
const [expandedSearch, setExpandedSearch] = useState(false);
|
|
60
|
+
|
|
58
61
|
const theme = useTheme();
|
|
59
62
|
|
|
60
63
|
const handleSearchClick = () => {
|
|
@@ -65,6 +68,8 @@ export const PageHeader = ({
|
|
|
65
68
|
setExpandedSearch(false);
|
|
66
69
|
};
|
|
67
70
|
|
|
71
|
+
const isTableMode = columns && uniqueId;
|
|
72
|
+
|
|
68
73
|
return (
|
|
69
74
|
<motion.div
|
|
70
75
|
style={{
|
|
@@ -85,17 +90,18 @@ export const PageHeader = ({
|
|
|
85
90
|
alignItems="center"
|
|
86
91
|
justifyContent="space-between"
|
|
87
92
|
>
|
|
88
|
-
{
|
|
93
|
+
{isTableMode ? <ViewTab title="Default View" /> : viewsSlot}
|
|
94
|
+
|
|
89
95
|
<Stack direction="row" alignItems="center">
|
|
90
|
-
{
|
|
96
|
+
{isTableMode && (
|
|
91
97
|
<FiltersAnchor
|
|
92
98
|
handleClick={() => {
|
|
93
99
|
setExpanded(!expanded);
|
|
94
100
|
}}
|
|
95
101
|
showDot={false}
|
|
96
102
|
/>
|
|
97
|
-
)}
|
|
98
|
-
{
|
|
103
|
+
)}
|
|
104
|
+
{isTableMode && (
|
|
99
105
|
<ColumnsAnchor
|
|
100
106
|
handleClick={() => {
|
|
101
107
|
setExpanded(!expanded);
|
|
@@ -103,35 +109,39 @@ export const PageHeader = ({
|
|
|
103
109
|
showDot={false}
|
|
104
110
|
/>
|
|
105
111
|
)}
|
|
106
|
-
{
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
112
|
+
{isTableMode && (
|
|
113
|
+
<AnimatePresence mode="wait">
|
|
114
|
+
{expandedSearch ? (
|
|
115
|
+
<motion.div
|
|
116
|
+
key="searchBar"
|
|
117
|
+
initial={{ opacity: 0, x: -20, scale: 0.95 }}
|
|
118
|
+
animate={{ opacity: 1, x: 0, scale: 1 }}
|
|
119
|
+
exit={{ opacity: 0, x: 20, scale: 0.95 }}
|
|
120
|
+
transition={{ duration: 0.3 }}
|
|
121
|
+
>
|
|
122
|
+
<SearchBar
|
|
123
|
+
searchText={searchText}
|
|
124
|
+
handleSearchBlur={handleSearchBlur}
|
|
125
|
+
uniqueId={uniqueId}
|
|
126
|
+
/>
|
|
127
|
+
</motion.div>
|
|
128
|
+
) : (
|
|
129
|
+
<motion.div
|
|
130
|
+
key="searchAnchor"
|
|
131
|
+
initial={{ opacity: 0, x: 20, scale: 0.95 }}
|
|
132
|
+
animate={{ opacity: 1, x: 0, scale: 1 }}
|
|
133
|
+
exit={{ opacity: 0, x: -20, scale: 0.95 }}
|
|
134
|
+
transition={{ duration: 0.3 }}
|
|
135
|
+
>
|
|
136
|
+
<SearchAnchor
|
|
137
|
+
handleClick={handleSearchClick}
|
|
138
|
+
showDot={false}
|
|
139
|
+
/>
|
|
140
|
+
</motion.div>
|
|
141
|
+
)}
|
|
142
|
+
</AnimatePresence>
|
|
143
|
+
)}
|
|
144
|
+
{isTableMode && <DensitySelector uniqueId={uniqueId} />}
|
|
135
145
|
{actions?.map((action, index) => action)}
|
|
136
146
|
</Stack>
|
|
137
147
|
</Stack>
|
|
@@ -144,7 +154,7 @@ export const PageHeader = ({
|
|
|
144
154
|
)}
|
|
145
155
|
{expanded && (
|
|
146
156
|
<Stack direction="row" width="100%" alignItems="center" gap={2}>
|
|
147
|
-
{columns && (
|
|
157
|
+
{columns && uniqueId && (
|
|
148
158
|
<TableColumnsSelector columns={columns} uniqueId={uniqueId} />
|
|
149
159
|
)}
|
|
150
160
|
<Divider
|
|
@@ -2,7 +2,7 @@ import { MenuListProps, MenuProps, Stack, useTheme } from '@mui/material';
|
|
|
2
2
|
import { GridDensity } from '@mui/x-data-grid';
|
|
3
3
|
import { capitalize } from 'lodash';
|
|
4
4
|
import { useDispatch, useSelector } from 'react-redux';
|
|
5
|
-
import {
|
|
5
|
+
import { setDensityForUniqueId } from '../../../../../redux/slices/pageHeaderSlice';
|
|
6
6
|
import { RootState } from '../../../../../redux/store';
|
|
7
7
|
import { Button, DropdownMenu, Icons, Typography } from '../../../../export';
|
|
8
8
|
import { DensityAnchor } from '../Anchors';
|
|
@@ -38,7 +38,7 @@ export const DensitySelector = ({
|
|
|
38
38
|
|
|
39
39
|
const handleMenuClick = (value: GridDensity, close: () => void) => {
|
|
40
40
|
dispatch(
|
|
41
|
-
|
|
41
|
+
setDensityForUniqueId({
|
|
42
42
|
uniqueId: uniqueId,
|
|
43
43
|
density: value,
|
|
44
44
|
}),
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { InputAdornment } from '@mui/material';
|
|
2
|
+
import { debounce } from 'lodash';
|
|
3
|
+
import React, { useMemo } from 'react';
|
|
4
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
5
|
+
import { setSearchForUniqueId } from '../../../../redux/slices/pageHeaderSlice';
|
|
6
|
+
import { RootState } from '../../../../redux/store';
|
|
7
|
+
import { Icons, TextField } from '../../../export';
|
|
8
|
+
|
|
9
|
+
export const SearchBar = ({
|
|
10
|
+
handleSearchBlur,
|
|
11
|
+
uniqueId,
|
|
12
|
+
searchText,
|
|
13
|
+
}: {
|
|
14
|
+
handleSearchBlur: () => void;
|
|
15
|
+
uniqueId: string;
|
|
16
|
+
searchText: string;
|
|
17
|
+
}) => {
|
|
18
|
+
const dispatch = useDispatch();
|
|
19
|
+
|
|
20
|
+
const search = useSelector(
|
|
21
|
+
(state: RootState) => state.pageHeader[uniqueId]?.filters?.search,
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
// Wrap onSearch in useCallback
|
|
25
|
+
const onSearch = (value: string) => {
|
|
26
|
+
dispatch(
|
|
27
|
+
setSearchForUniqueId({
|
|
28
|
+
uniqueId: uniqueId,
|
|
29
|
+
search: value,
|
|
30
|
+
}),
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Now we can memoize a debounced version of onSearch
|
|
35
|
+
const debouncedSendRequest = useMemo(
|
|
36
|
+
() => debounce(onSearch, 300),
|
|
37
|
+
[onSearch],
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// Pass the updated value to the debounced function in onChange
|
|
41
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
42
|
+
debouncedSendRequest(e.target.value);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<TextField
|
|
47
|
+
containerProps={{
|
|
48
|
+
margin: '0px',
|
|
49
|
+
width: '300px',
|
|
50
|
+
}}
|
|
51
|
+
size="small"
|
|
52
|
+
placeholder={searchText}
|
|
53
|
+
defaultValue={search || ''}
|
|
54
|
+
onChange={handleChange}
|
|
55
|
+
InputProps={{
|
|
56
|
+
startAdornment: (
|
|
57
|
+
<InputAdornment position="start">
|
|
58
|
+
<Icons.SearchIcon />
|
|
59
|
+
</InputAdornment>
|
|
60
|
+
),
|
|
61
|
+
}}
|
|
62
|
+
onBlur={handleSearchBlur}
|
|
63
|
+
autoFocus
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
};
|
package/src/components/Layout/PageHeader/components/TableColumnsSelector/TableColumnsSelector.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import { MenuListProps, MenuProps, Typography, useTheme } from '@mui/material';
|
|
|
3
3
|
import { GridColDef, GridColumnVisibilityModel } from '@mui/x-data-grid';
|
|
4
4
|
import { useState } from 'react';
|
|
5
5
|
import { useDispatch, useSelector } from 'react-redux';
|
|
6
|
-
import {
|
|
6
|
+
import { setColumnVisibilityModelForUniqueId } from '../../../../../redux/slices/pageHeaderSlice';
|
|
7
7
|
import { RootState } from '../../../../../redux/store';
|
|
8
8
|
import { Button, Icons, SearchBar, SingleCheckBox } from '../../../../export';
|
|
9
9
|
import { DropdownMenu } from '../../../../Navigation/export';
|
|
@@ -45,7 +45,7 @@ export const TableColumnsSelector = ({
|
|
|
45
45
|
[column.field]: !checked,
|
|
46
46
|
};
|
|
47
47
|
dispatch(
|
|
48
|
-
|
|
48
|
+
setColumnVisibilityModelForUniqueId({
|
|
49
49
|
uniqueId: uniqueId,
|
|
50
50
|
columnVisibilityModel: newColumnVisibilityModel,
|
|
51
51
|
}),
|
|
@@ -77,7 +77,17 @@ export const TableColumnsSelector = ({
|
|
|
77
77
|
Columns
|
|
78
78
|
</Button>
|
|
79
79
|
)}
|
|
80
|
-
menuProps={{
|
|
80
|
+
menuProps={{
|
|
81
|
+
...props.menuProps,
|
|
82
|
+
anchorOrigin: {
|
|
83
|
+
vertical: 'bottom',
|
|
84
|
+
horizontal: 'left',
|
|
85
|
+
},
|
|
86
|
+
transformOrigin: {
|
|
87
|
+
vertical: 'top',
|
|
88
|
+
horizontal: 'left',
|
|
89
|
+
},
|
|
90
|
+
}}
|
|
81
91
|
menuHeader={
|
|
82
92
|
<SearchBar
|
|
83
93
|
fullWidth
|
|
@@ -89,7 +99,7 @@ export const TableColumnsSelector = ({
|
|
|
89
99
|
/>
|
|
90
100
|
}
|
|
91
101
|
menuListContainerSx={{
|
|
92
|
-
margin: '10px
|
|
102
|
+
margin: '10px 5px 0px 5px',
|
|
93
103
|
gap: 1,
|
|
94
104
|
maxHeight: '350px',
|
|
95
105
|
}}
|
|
@@ -36,7 +36,7 @@ export const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
|
|
36
36
|
open={isOpen}
|
|
37
37
|
content={({ close }) => {
|
|
38
38
|
return (
|
|
39
|
-
|
|
39
|
+
<Box sx={{ padding: '16px' }}>
|
|
40
40
|
<Stack direction="row" alignItems="center">
|
|
41
41
|
<img
|
|
42
42
|
src={
|
|
@@ -71,7 +71,7 @@ export const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
|
|
|
71
71
|
{confirmButtonText}
|
|
72
72
|
</Button>
|
|
73
73
|
</Stack>
|
|
74
|
-
|
|
74
|
+
</Box>
|
|
75
75
|
);
|
|
76
76
|
}}
|
|
77
77
|
onClose={onCancel}
|
|
@@ -1,30 +1,69 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useRef } from 'react';
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
3
2
|
import { useDispatch, useSelector } from 'react-redux';
|
|
4
3
|
import { v4 } from 'uuid';
|
|
5
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
PageHeaderSingleState,
|
|
6
|
+
resetStateForUniqueId,
|
|
7
|
+
setDefaultFiltersForUniqueId,
|
|
8
|
+
setLimitForUniqueId,
|
|
9
|
+
setOffsetForUniqueId,
|
|
10
|
+
} from '../redux/slices/pageHeaderSlice';
|
|
6
11
|
import { RootState } from '../redux/store';
|
|
7
12
|
|
|
8
|
-
export const usePageHeader = () => {
|
|
13
|
+
export const usePageHeader = (defaultFilters?: { [x: string]: any }) => {
|
|
9
14
|
const uuidRef = useRef(v4());
|
|
10
15
|
const dispatch = useDispatch();
|
|
11
|
-
const filterState = useSelector(
|
|
12
|
-
(state: RootState) =>
|
|
13
|
-
state.pageHeader[uuidRef.current] ||
|
|
14
|
-
({} as {
|
|
15
|
-
density: GridDensity;
|
|
16
|
-
columnVisibilityModel: GridColumnVisibilityModel;
|
|
17
|
-
}),
|
|
18
|
-
);
|
|
19
16
|
|
|
20
17
|
const resetState = () => {
|
|
21
18
|
dispatch(resetStateForUniqueId({ uniqueId: uuidRef.current }));
|
|
22
19
|
};
|
|
23
20
|
|
|
21
|
+
const setDefaultFilters = (defaultFilters: { [x: string]: any }) => {
|
|
22
|
+
dispatch(
|
|
23
|
+
setDefaultFiltersForUniqueId({
|
|
24
|
+
uniqueId: uuidRef.current,
|
|
25
|
+
defaultFilters,
|
|
26
|
+
}),
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const onLimitChange = (limit: number) => {
|
|
31
|
+
dispatch(
|
|
32
|
+
setLimitForUniqueId({
|
|
33
|
+
uniqueId: uuidRef.current,
|
|
34
|
+
limit,
|
|
35
|
+
}),
|
|
36
|
+
);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const onPageChange = (offset: number) => {
|
|
40
|
+
dispatch(
|
|
41
|
+
setOffsetForUniqueId({
|
|
42
|
+
uniqueId: uuidRef.current,
|
|
43
|
+
offset,
|
|
44
|
+
}),
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (defaultFilters)
|
|
50
|
+
setDefaultFilters({ limit: 10, offset: 0, skip: 0, ...defaultFilters });
|
|
51
|
+
}, []);
|
|
52
|
+
|
|
53
|
+
const filterState = useSelector(
|
|
54
|
+
(state: RootState) =>
|
|
55
|
+
state.pageHeader[uuidRef.current] ||
|
|
56
|
+
({ filters: { limit: 10, offset: 0, skip: 0 } } as PageHeaderSingleState),
|
|
57
|
+
);
|
|
58
|
+
|
|
24
59
|
return {
|
|
25
60
|
columnVisibilityModel: filterState.columnVisibilityModel,
|
|
26
61
|
density: filterState.density,
|
|
62
|
+
filters: { ...defaultFilters, ...filterState.filters },
|
|
27
63
|
uniqueId: uuidRef.current,
|
|
28
64
|
resetState,
|
|
65
|
+
setDefaultFilters,
|
|
66
|
+
onPageChange,
|
|
67
|
+
onLimitChange,
|
|
29
68
|
};
|
|
30
69
|
};
|