trithuc-mvc-react 1.6.14 → 1.7.1
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/components/DataManagement/DataTable.jsx +17 -8
- package/components/DataManagement/EditorDialog.jsx +6 -4
- package/components/DataManagement/TableHead.jsx +6 -4
- package/components/DataManagement/TableRowRender.jsx +47 -43
- package/components/DataManagement/TableToolbar.jsx +10 -7
- package/components/DataManagement/ViewDetailDialog.jsx +8 -10
- package/components/DataManagement/context.js +0 -1
- package/components/DataManagement/hooks.js +2 -18
- package/components/DataManagement/index.jsx +76 -75
- package/contexts/index.jsx +6 -0
- package/hooks/index.jsx +1 -0
- package/hooks/usePermission.js +34 -0
- package/index.js +3 -0
- package/jsconfig.json +12 -0
- package/package.json +1 -1
- package/providers/PermissionProvider.jsx +11 -0
- package/providers/index.jsx +1 -0
- package/utils/index.js +0 -2
|
@@ -11,16 +11,26 @@ import { useConfirm } from "material-ui-confirm";
|
|
|
11
11
|
|
|
12
12
|
import { TableRowRender } from "./TableRowRender";
|
|
13
13
|
import TableToolbar from "./TableToolbar";
|
|
14
|
-
import { useDataTable
|
|
15
|
-
|
|
14
|
+
import { useDataTable } from "./hooks";
|
|
15
|
+
import { usePermission } from "../../hooks";
|
|
16
16
|
const DataTable = () => {
|
|
17
|
-
const {
|
|
18
|
-
|
|
17
|
+
const {
|
|
18
|
+
tableName,
|
|
19
|
+
selectedField,
|
|
20
|
+
columns,
|
|
21
|
+
dataSearch,
|
|
22
|
+
setOpenEditorDialog,
|
|
23
|
+
setSelectedEditItem,
|
|
24
|
+
setOpenViewDialog,
|
|
25
|
+
onEditClick
|
|
26
|
+
} = useDataTable();
|
|
27
|
+
const { set: setPermission, permission } = usePermission(tableName);
|
|
19
28
|
const queryClient = useQueryClient();
|
|
20
29
|
const confirm = useConfirm();
|
|
21
30
|
const [selected, setSelected] = useState([]);
|
|
22
31
|
const [page, setPage] = useState(0);
|
|
23
32
|
const [rowsPerPage, setRowsPerPage] = useState(5);
|
|
33
|
+
|
|
24
34
|
const { data, isLoading } = useQuery({
|
|
25
35
|
queryKey: [tableName, page, rowsPerPage, dataSearch],
|
|
26
36
|
queryFn: () =>
|
|
@@ -80,7 +90,7 @@ const DataTable = () => {
|
|
|
80
90
|
tableName
|
|
81
91
|
});
|
|
82
92
|
})
|
|
83
|
-
.catch(() => {
|
|
93
|
+
.catch(() => {});
|
|
84
94
|
};
|
|
85
95
|
const handleChangeStatus = (Id) => {
|
|
86
96
|
changeStatusMutation.mutate({
|
|
@@ -92,7 +102,6 @@ const DataTable = () => {
|
|
|
92
102
|
setOpenEditorDialog(true);
|
|
93
103
|
setSelectedEditItem(item);
|
|
94
104
|
onEditClick(item);
|
|
95
|
-
|
|
96
105
|
};
|
|
97
106
|
const handlViewDetail = (item) => {
|
|
98
107
|
setOpenViewDialog(true);
|
|
@@ -111,7 +120,7 @@ const DataTable = () => {
|
|
|
111
120
|
useEffect(() => {
|
|
112
121
|
let PermissionModel = data?.PermissionModel;
|
|
113
122
|
PermissionModel && setPermission(PermissionModel);
|
|
114
|
-
}, [rows])
|
|
123
|
+
}, [rows]);
|
|
115
124
|
|
|
116
125
|
const handleChangePage = (event, newPage) => {
|
|
117
126
|
setPage(newPage);
|
|
@@ -153,7 +162,7 @@ const DataTable = () => {
|
|
|
153
162
|
ids: selected
|
|
154
163
|
});
|
|
155
164
|
})
|
|
156
|
-
.catch(() => {
|
|
165
|
+
.catch(() => {});
|
|
157
166
|
};
|
|
158
167
|
const theme = useTheme();
|
|
159
168
|
const downXL = useMediaQuery(theme.breakpoints.down("xl"));
|
|
@@ -11,7 +11,8 @@ import { useEffect, useRef, useState } from "react";
|
|
|
11
11
|
import PropTypes from "prop-types";
|
|
12
12
|
|
|
13
13
|
import EditorForm from "./EditorForm";
|
|
14
|
-
import { usePermission } from "
|
|
14
|
+
import { usePermission } from "../../hooks";
|
|
15
|
+
import { useDataTable } from "./hooks";
|
|
15
16
|
EditorDialog.propTypes = {
|
|
16
17
|
open: PropTypes.bool,
|
|
17
18
|
onClose: PropTypes.func,
|
|
@@ -19,7 +20,8 @@ EditorDialog.propTypes = {
|
|
|
19
20
|
};
|
|
20
21
|
function EditorDialog({ open, onClose = () => {}, defaultValues = {}, fields = [] }) {
|
|
21
22
|
const [isDisableBtnSave, setIsDisableBtnSave] = useState(false);
|
|
22
|
-
const {
|
|
23
|
+
const { tableName } = useDataTable();
|
|
24
|
+
const { canSave } = usePermission(tableName);
|
|
23
25
|
|
|
24
26
|
useEffect(() => {}, [defaultValues]);
|
|
25
27
|
|
|
@@ -31,7 +33,7 @@ function EditorDialog({ open, onClose = () => {}, defaultValues = {}, fields = [
|
|
|
31
33
|
};
|
|
32
34
|
const submitRef = useRef();
|
|
33
35
|
return (
|
|
34
|
-
<Dialog open={open} onClose={onClose} maxWidth="md" fullWidth={true} scroll={
|
|
36
|
+
<Dialog open={open} onClose={onClose} maxWidth="md" fullWidth={true} scroll={"body"}>
|
|
35
37
|
<DialogTitle>
|
|
36
38
|
{defaultValues?.Id ? "Cập nhật" : "Thêm mới"}
|
|
37
39
|
<IconButton
|
|
@@ -48,7 +50,7 @@ function EditorDialog({ open, onClose = () => {}, defaultValues = {}, fields = [
|
|
|
48
50
|
</IconButton>
|
|
49
51
|
</DialogTitle>
|
|
50
52
|
<DialogContent dividers={true}>
|
|
51
|
-
<EditorForm fields={fields} submitRef={submitRef}
|
|
53
|
+
<EditorForm fields={fields} submitRef={submitRef} />
|
|
52
54
|
</DialogContent>
|
|
53
55
|
<DialogActions>
|
|
54
56
|
<Button onClick={onClose}>Đóng</Button>
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Checkbox, TableRow, TableCell, TableHead as MuiTableHead, useTheme, useMediaQuery } from "@mui/material";
|
|
2
|
-
import { useDataTable
|
|
2
|
+
import { useDataTable } from "./hooks";
|
|
3
|
+
import { usePermission } from "../../hooks";
|
|
3
4
|
export function TableHead({ numSelected, rowCount, onSelectAllClick, headLabel }) {
|
|
4
|
-
const {
|
|
5
|
-
const {
|
|
5
|
+
const { disableStatus, disableCellThaoTac, tableName } = useDataTable();
|
|
6
|
+
const { canEdit } = usePermission(tableName);
|
|
7
|
+
|
|
6
8
|
const theme = useTheme();
|
|
7
9
|
const downXl = useMediaQuery(theme.breakpoints.down("xl"));
|
|
8
10
|
return (
|
|
@@ -11,7 +13,7 @@ export function TableHead({ numSelected, rowCount, onSelectAllClick, headLabel }
|
|
|
11
13
|
<TableCell padding="checkbox">
|
|
12
14
|
<Checkbox
|
|
13
15
|
indeterminate={numSelected > 0 && numSelected < rowCount}
|
|
14
|
-
size={downXl?"small":"medium"}
|
|
16
|
+
size={downXl ? "small" : "medium"}
|
|
15
17
|
checked={rowCount > 0 && numSelected === rowCount}
|
|
16
18
|
onChange={onSelectAllClick}
|
|
17
19
|
/>
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { Checkbox, IconButton, Switch, TableCell, TableRow, Tooltip, Toolbar, useMediaQuery } from "@mui/material";
|
|
2
2
|
import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline";
|
|
3
3
|
import { EditOutlined } from "@mui/icons-material";
|
|
4
|
-
import { useDataTable
|
|
4
|
+
import { useDataTable } from "./hooks";
|
|
5
5
|
import RemoveRedEyeOutlinedIcon from "@mui/icons-material/RemoveRedEyeOutlined";
|
|
6
|
-
|
|
6
|
+
import { usePermission } from "../../hooks";
|
|
7
7
|
// material
|
|
8
8
|
import { styled, useTheme } from "@mui/material/styles";
|
|
9
9
|
import MoreMenu from "../MoreMenu";
|
|
10
10
|
import { useMemo } from "react";
|
|
11
11
|
|
|
12
12
|
export const TableRowRender = ({ index, row, selected, onSelect, onChangeStatus, onDelete, onEdit, onView }) => {
|
|
13
|
-
const { selectedField, columns, statusKey, disableStatus, tableActions, disableCellThaoTac } = useDataTable();
|
|
14
|
-
const { canEdit, canDelete, canView, canAction } = usePermission();
|
|
13
|
+
const { selectedField, columns, statusKey, disableStatus, tableActions, disableCellThaoTac, tableName } = useDataTable();
|
|
14
|
+
const { canEdit, canDelete, canView, canAction } = usePermission(tableName);
|
|
15
15
|
|
|
16
16
|
const { tableActionsOnTable, tableActionsOnMoreMenu } = useMemo(() => {
|
|
17
17
|
const tableActionsAfterFilter = [...tableActions].filter(({ permissionType }) => {
|
|
@@ -69,46 +69,50 @@ export const TableRowRender = ({ index, row, selected, onSelect, onChangeStatus,
|
|
|
69
69
|
</TableCell>
|
|
70
70
|
)}
|
|
71
71
|
|
|
72
|
-
{!disableCellThaoTac &&
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
<
|
|
76
|
-
<
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
<
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
<
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
72
|
+
{!disableCellThaoTac && (
|
|
73
|
+
<TableCell align="center">
|
|
74
|
+
{canEdit && (
|
|
75
|
+
<Tooltip title="Chỉnh sửa">
|
|
76
|
+
<IconButton size={downXl ? "small" : "medium"} onClick={() => onEdit(row)}>
|
|
77
|
+
<EditOutlined fontSize="inherit" color="primary" />
|
|
78
|
+
</IconButton>
|
|
79
|
+
</Tooltip>
|
|
80
|
+
)}
|
|
81
|
+
{canView && !tableActions?.some(({ permissionType }) => permissionType == "view") && (
|
|
82
|
+
<Tooltip title="Xem chi tiết">
|
|
83
|
+
<IconButton onClick={() => onView(row)}>
|
|
84
|
+
<RemoveRedEyeOutlinedIcon color="info" />
|
|
85
|
+
</IconButton>
|
|
86
|
+
</Tooltip>
|
|
87
|
+
)}
|
|
88
|
+
{canDelete && (
|
|
89
|
+
<Tooltip title="Xóa">
|
|
90
|
+
<IconButton
|
|
91
|
+
size={downXl ? "small" : "medium"}
|
|
92
|
+
onClick={() => {
|
|
93
|
+
onDelete(row[selectedField]);
|
|
94
|
+
}}
|
|
95
|
+
>
|
|
96
|
+
<DeleteOutlineIcon fontSize="inherit" color="error" />
|
|
97
|
+
</IconButton>
|
|
98
|
+
</Tooltip>
|
|
99
|
+
)}
|
|
100
|
+
{tableActionsOnTable.map(({ title, onClick, element }) => (
|
|
101
|
+
<Tooltip key={title} title={title}>
|
|
102
|
+
<IconButton
|
|
103
|
+
size={downXl ? "small" : "medium"}
|
|
104
|
+
onClick={() => {
|
|
105
|
+
onClick(row);
|
|
106
|
+
}}
|
|
107
|
+
>
|
|
108
|
+
{element}
|
|
109
|
+
</IconButton>
|
|
110
|
+
</Tooltip>
|
|
111
|
+
))}
|
|
109
112
|
|
|
110
|
-
|
|
111
|
-
|
|
113
|
+
{<MoreMenu actions={tableActionsOnMoreMenu} data={row} />}
|
|
114
|
+
</TableCell>
|
|
115
|
+
)}
|
|
112
116
|
</TableRow>
|
|
113
117
|
);
|
|
114
118
|
};
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { Checkbox, IconButton, Tooltip, Typography, Box, useMediaQuery } from "@mui/material";
|
|
2
2
|
import { Delete } from "@mui/icons-material";
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
import PropTypes from "prop-types";
|
|
5
5
|
import { useTheme } from "@mui/material/styles";
|
|
6
6
|
import { RootStyle } from "./TableRowRender";
|
|
7
|
-
|
|
7
|
+
import { usePermission } from "../../hooks";
|
|
8
|
+
import { useDataTable } from "./hooks";
|
|
8
9
|
// ----------------------------------------------------------------------
|
|
9
10
|
const TableToolbar = ({ numSelected, onSelectAllClick, rowCount, onDeleteMultiple }) => {
|
|
10
11
|
const theme = useTheme();
|
|
11
12
|
const isLight = theme.palette.mode === "light";
|
|
12
|
-
const {
|
|
13
|
+
const { tableName } = useDataTable();
|
|
14
|
+
const { canDeleteMulti } = usePermission(tableName);
|
|
13
15
|
const downXl = useMediaQuery(theme.breakpoints.down("xl"));
|
|
14
16
|
|
|
15
17
|
return (
|
|
@@ -24,9 +26,10 @@ const TableToolbar = ({ numSelected, onSelectAllClick, rowCount, onDeleteMultipl
|
|
|
24
26
|
width: "100%",
|
|
25
27
|
...(numSelected > 0 && {
|
|
26
28
|
color: isLight ? "primary.main" : "text.primary",
|
|
27
|
-
bgcolor: isLight ? "primary.lighter" : "primary.dark"
|
|
28
|
-
})
|
|
29
|
-
}}
|
|
29
|
+
bgcolor: isLight ? "primary.lighter" : "primary.dark"
|
|
30
|
+
})
|
|
31
|
+
}}
|
|
32
|
+
>
|
|
30
33
|
<Box padding="checkbox" sx={{ display: "flex", alignItems: "center" }}>
|
|
31
34
|
<Checkbox
|
|
32
35
|
indeterminate={numSelected > 0 && numSelected < rowCount}
|
|
@@ -40,7 +43,7 @@ const TableToolbar = ({ numSelected, onSelectAllClick, rowCount, onDeleteMultipl
|
|
|
40
43
|
|
|
41
44
|
{canDeleteMulti && (
|
|
42
45
|
<Tooltip title="Xóa tất cả" onClick={onDeleteMultiple}>
|
|
43
|
-
<IconButton size={downXl ? "small" : "medium"}
|
|
46
|
+
<IconButton size={downXl ? "small" : "medium"}>
|
|
44
47
|
<Delete color="primary" />
|
|
45
48
|
</IconButton>
|
|
46
49
|
</Tooltip>
|
|
@@ -7,21 +7,20 @@ import DialogTitle from "@mui/material/DialogTitle";
|
|
|
7
7
|
import IconButton from "@mui/material/IconButton";
|
|
8
8
|
import CloseIcon from "@mui/icons-material/Close";
|
|
9
9
|
|
|
10
|
-
import { useEffect, useRef, useState } from "react";
|
|
11
10
|
import PropTypes from "prop-types";
|
|
12
11
|
|
|
13
|
-
import EditorForm from "
|
|
14
|
-
|
|
12
|
+
import EditorForm from "./EditorForm";
|
|
13
|
+
|
|
15
14
|
ViewDetailDialog.propTypes = {
|
|
16
15
|
open: PropTypes.bool,
|
|
17
|
-
onClose: PropTypes.func
|
|
16
|
+
onClose: PropTypes.func
|
|
18
17
|
};
|
|
19
18
|
import { Stack, Typography, List, ListItem, ListItemText, ListItemIcon, Link, Grid } from "@mui/material";
|
|
20
19
|
import TextSnippetOutlinedIcon from "@mui/icons-material/TextSnippetOutlined";
|
|
21
20
|
export const FieldView = ({ label, value }) => {
|
|
22
21
|
return (
|
|
23
22
|
<Stack direction="column">
|
|
24
|
-
<Typography variant="body2" sx={{ color: "text.secondary"
|
|
23
|
+
<Typography variant="body2" sx={{ color: "text.secondary" }}>
|
|
25
24
|
{label}
|
|
26
25
|
</Typography>
|
|
27
26
|
<Typography variant="subtitle2">{value}</Typography>
|
|
@@ -56,7 +55,7 @@ export const ListFileView = ({ files }) => {
|
|
|
56
55
|
<TextSnippetOutlinedIcon color="info" />
|
|
57
56
|
</ListItemIcon>
|
|
58
57
|
<ListItemText
|
|
59
|
-
primary={<Link href={urlFile}
|
|
58
|
+
primary={<Link href={urlFile}>{tenFile}</Link>}
|
|
60
59
|
secondary={Size}
|
|
61
60
|
primaryTypographyProps={{ variant: "subtitle2" }}
|
|
62
61
|
secondaryTypographyProps={{ variant: "caption" }}
|
|
@@ -68,11 +67,10 @@ export const ListFileView = ({ files }) => {
|
|
|
68
67
|
);
|
|
69
68
|
};
|
|
70
69
|
|
|
71
|
-
function ViewDetailDialog({ open, onClose = () => {
|
|
72
|
-
|
|
73
|
-
const fieldsView = fields.map(field=>({...field, disabled: true}));
|
|
70
|
+
function ViewDetailDialog({ open, onClose = () => {}, fields = [] }) {
|
|
71
|
+
const fieldsView = fields.map((field) => ({ ...field, disabled: true }));
|
|
74
72
|
return (
|
|
75
|
-
<Dialog open={open} onClose={onClose} maxWidth="md" fullWidth={true} scroll={
|
|
73
|
+
<Dialog open={open} onClose={onClose} maxWidth="md" fullWidth={true} scroll={"body"}>
|
|
76
74
|
<DialogTitle>
|
|
77
75
|
Xem chi tiết
|
|
78
76
|
<IconButton
|
|
@@ -1,22 +1,6 @@
|
|
|
1
|
-
import { useContext
|
|
2
|
-
import { DataTableContext
|
|
1
|
+
import { useContext } from "react";
|
|
2
|
+
import { DataTableContext } from "./context";
|
|
3
3
|
|
|
4
4
|
export function useDataTable() {
|
|
5
5
|
return useContext(DataTableContext);
|
|
6
6
|
}
|
|
7
|
-
export function usePermission() {
|
|
8
|
-
const { Permission, setPermission } = useContext(PermissionContext);
|
|
9
|
-
const { canEdit, canDelete, canDeleteMulti, canSave, canCreate, canAction, canView } = useMemo(() => {
|
|
10
|
-
const canEdit = !Permission || Permission.Edit;
|
|
11
|
-
const canDelete = !Permission || Permission.Delete;
|
|
12
|
-
const canDeleteMulti = !Permission || Permission.DeleteMulti;
|
|
13
|
-
const canSave = !Permission || Permission.Save;
|
|
14
|
-
const canCreate = !Permission || Permission.Create;
|
|
15
|
-
const canAction = !Permission || Permission.Action;
|
|
16
|
-
const canView = !Permission || Permission.View;
|
|
17
|
-
|
|
18
|
-
return { canEdit, canDelete, canDeleteMulti, canSave, canCreate, canAction, canView };
|
|
19
|
-
}, [Permission]);
|
|
20
|
-
|
|
21
|
-
return { Permission, setPermission, canEdit, canDelete, canDeleteMulti, canSave, canCreate, canAction, canView };
|
|
22
|
-
}
|
|
@@ -2,7 +2,7 @@ import { Button, Card, IconButton, Stack, Tooltip, Typography, useTheme, useMedi
|
|
|
2
2
|
|
|
3
3
|
import { useEffect, useMemo, useState } from "react";
|
|
4
4
|
|
|
5
|
-
import { DataTableContext
|
|
5
|
+
import { DataTableContext } from "./context";
|
|
6
6
|
import PropTypes from "prop-types";
|
|
7
7
|
import DataTable from "./DataTable";
|
|
8
8
|
import { Add, Refresh } from "@mui/icons-material";
|
|
@@ -13,7 +13,7 @@ import ViewDetailDialog from "./ViewDetailDialog";
|
|
|
13
13
|
|
|
14
14
|
import ExportExcelButton from "./ExportExcelButton";
|
|
15
15
|
import { FilterGod } from "./FilterGod";
|
|
16
|
-
|
|
16
|
+
import { usePermission } from "../../hooks";
|
|
17
17
|
|
|
18
18
|
DataManagement.propTypes = {
|
|
19
19
|
columns: PropTypes.array,
|
|
@@ -57,8 +57,8 @@ function DataManagement({
|
|
|
57
57
|
disableCellThaoTac = false,
|
|
58
58
|
tableActions = [],
|
|
59
59
|
disableEditor = false,
|
|
60
|
-
onAddClick = () => {
|
|
61
|
-
onEditClick = () => {
|
|
60
|
+
onAddClick = () => {},
|
|
61
|
+
onEditClick = () => {},
|
|
62
62
|
tabPanel,
|
|
63
63
|
backParentNavigator,
|
|
64
64
|
slotProps = {
|
|
@@ -71,8 +71,7 @@ function DataManagement({
|
|
|
71
71
|
const [selectedEditItem, setSelectedEditItem] = useState(null);
|
|
72
72
|
const [openViewDialog, setOpenViewDialog] = useState(false);
|
|
73
73
|
|
|
74
|
-
const
|
|
75
|
-
|
|
74
|
+
const { canCreate } = usePermission(tableName);
|
|
76
75
|
const { defaults, filters } = useMemo(() => {
|
|
77
76
|
const filters = tableFilters.filter(({ type }) => type !== "default");
|
|
78
77
|
const defaultFilters = tableFilters.filter(({ type }) => type === "default");
|
|
@@ -91,7 +90,6 @@ function DataManagement({
|
|
|
91
90
|
return elementSize;
|
|
92
91
|
}, [upXL]);
|
|
93
92
|
|
|
94
|
-
|
|
95
93
|
useEffect(() => {
|
|
96
94
|
setDataSearch({ ...dataSearch, ...defaults });
|
|
97
95
|
}, [filters]);
|
|
@@ -116,80 +114,83 @@ function DataManagement({
|
|
|
116
114
|
tableActions,
|
|
117
115
|
onEditClick
|
|
118
116
|
};
|
|
119
|
-
}, [
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
117
|
+
}, [
|
|
118
|
+
tableName,
|
|
119
|
+
selectedField,
|
|
120
|
+
columns,
|
|
121
|
+
selectedEditItem,
|
|
122
|
+
dataSearch,
|
|
123
|
+
setDataSearch,
|
|
124
|
+
validationSchema,
|
|
125
|
+
tableActions,
|
|
126
|
+
openViewDialog,
|
|
127
|
+
setOpenViewDialog,
|
|
128
|
+
onEditClick
|
|
129
|
+
]);
|
|
130
|
+
|
|
126
131
|
const methods = useForm({ defaultValues: {} });
|
|
127
132
|
const { reset, setValue } = methods;
|
|
128
133
|
return (
|
|
129
134
|
<>
|
|
130
135
|
<DataTableContext.Provider value={values}>
|
|
131
|
-
<
|
|
132
|
-
<
|
|
133
|
-
<
|
|
134
|
-
|
|
135
|
-
<
|
|
136
|
-
<
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
</Button>
|
|
171
|
-
)
|
|
172
|
-
)}
|
|
173
|
-
</Stack>
|
|
136
|
+
<FormProvider {...methods}>
|
|
137
|
+
<Stack direction="row" justifyContent={"space-between"} sx={{ mb: upXL ? 2 : 1, ...slotProps?.header?.sx }}>
|
|
138
|
+
<Typography variant="h4">{title}</Typography>
|
|
139
|
+
<Stack direction="row" spacing={1}>
|
|
140
|
+
<Tooltip title="Làm mới">
|
|
141
|
+
<IconButton
|
|
142
|
+
variant="outlined"
|
|
143
|
+
color="primary"
|
|
144
|
+
size={elementSize}
|
|
145
|
+
onClick={() => {
|
|
146
|
+
setDataSearch({ ...defaults });
|
|
147
|
+
[...filters].forEach((filter) => {
|
|
148
|
+
filter?.onChange?.();
|
|
149
|
+
});
|
|
150
|
+
reset();
|
|
151
|
+
setValue("Search");
|
|
152
|
+
}}
|
|
153
|
+
>
|
|
154
|
+
<Refresh fontSize="inherit" />
|
|
155
|
+
</IconButton>
|
|
156
|
+
</Tooltip>
|
|
157
|
+
|
|
158
|
+
<ExportExcelButton tableName={tableName} data={dataSearch} size={elementSize} />
|
|
159
|
+
{canCreate && !disableAdd && (
|
|
160
|
+
<Button
|
|
161
|
+
size={elementSize}
|
|
162
|
+
variant="contained"
|
|
163
|
+
startIcon={<Add fontSize="inherit" />}
|
|
164
|
+
onClick={(e) => {
|
|
165
|
+
if (!disableEditor) {
|
|
166
|
+
setOpenEditorDialog(true);
|
|
167
|
+
setSelectedEditItem(null);
|
|
168
|
+
}
|
|
169
|
+
onAddClick(e);
|
|
170
|
+
}}
|
|
171
|
+
>
|
|
172
|
+
Thêm
|
|
173
|
+
</Button>
|
|
174
|
+
)}
|
|
174
175
|
</Stack>
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
</
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
176
|
+
</Stack>
|
|
177
|
+
|
|
178
|
+
<Card>
|
|
179
|
+
{tabPanel}
|
|
180
|
+
<FilterGod filters={filters} elementSize={elementSize} />
|
|
181
|
+
{backParentNavigator}
|
|
182
|
+
<DataTable />
|
|
183
|
+
</Card>
|
|
184
|
+
</FormProvider>
|
|
185
|
+
{disableEditor || (
|
|
186
|
+
<EditorDialog
|
|
187
|
+
open={openEditorDialog}
|
|
188
|
+
onClose={() => setOpenEditorDialog(false)}
|
|
189
|
+
defaultValues={selectedEditItem}
|
|
190
|
+
fields={editorFields}
|
|
191
|
+
/>
|
|
192
|
+
)}
|
|
193
|
+
<ViewDetailDialog open={openViewDialog} onClose={() => setOpenViewDialog(false)} fields={editorFields} />
|
|
193
194
|
</DataTableContext.Provider>
|
|
194
195
|
</>
|
|
195
196
|
);
|
package/hooks/index.jsx
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./usePermission";
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useContext, useMemo } from "react";
|
|
2
|
+
import { PermissionContext } from "../contexts";
|
|
3
|
+
|
|
4
|
+
export const usePermission = (tableName) => {
|
|
5
|
+
if (!tableName) {
|
|
6
|
+
throw new Error("tableName is required");
|
|
7
|
+
}
|
|
8
|
+
const context = useContext(PermissionContext);
|
|
9
|
+
if (!context) {
|
|
10
|
+
throw new Error("usePermission must be used within a PermissionProvider");
|
|
11
|
+
}
|
|
12
|
+
const { permissionMap, setPermission } = context;
|
|
13
|
+
|
|
14
|
+
const permission = permissionMap[tableName];
|
|
15
|
+
|
|
16
|
+
const { canEdit, canDelete, canDeleteMulti, canSave, canCreate, canAction, canView, canImport } = useMemo(() => {
|
|
17
|
+
const canEdit = !permission || permission.Edit;
|
|
18
|
+
const canDelete = !permission || permission.Delete;
|
|
19
|
+
const canDeleteMulti = !permission || permission.DeleteMulti;
|
|
20
|
+
const canSave = !permission || permission.Save;
|
|
21
|
+
const canCreate = !permission || permission.Create;
|
|
22
|
+
const canAction = !permission || permission.Action;
|
|
23
|
+
const canView = !permission || permission.View;
|
|
24
|
+
const canImport = !permission || permission.ImportFile;
|
|
25
|
+
|
|
26
|
+
return { canEdit, canDelete, canDeleteMulti, canSave, canCreate, canAction, canView, canImport };
|
|
27
|
+
}, [permission]);
|
|
28
|
+
|
|
29
|
+
const set = (permission) => {
|
|
30
|
+
setPermission({ ...permissionMap, [tableName]: permission });
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return { permission, set, canEdit, canDelete, canDeleteMulti, canSave, canCreate, canAction, canView, canImport };
|
|
34
|
+
};
|
package/index.js
CHANGED
package/jsconfig.json
ADDED
package/package.json
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useMemo, useState } from "react";
|
|
2
|
+
import { PermissionContext } from "../contexts";
|
|
3
|
+
|
|
4
|
+
export const PermissionProvider = ({ children }) => {
|
|
5
|
+
const [permissionMap, setPermission] = useState({});
|
|
6
|
+
const value = useMemo(() => {
|
|
7
|
+
return { permissionMap, setPermission };
|
|
8
|
+
}, [permissionMap, setPermission]);
|
|
9
|
+
console.log("PermissionProvider: permissionMap", permissionMap);
|
|
10
|
+
return <PermissionContext.Provider value={value}>{children}</PermissionContext.Provider>;
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./PermissionProvider";
|