trithuc-mvc-react 1.6.13 → 1.7.0

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.
@@ -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, usePermission } from "./hooks";
15
-
14
+ import { useDataTable } from "./hooks";
15
+ import { usePermission } from "../../hooks";
16
16
  const DataTable = () => {
17
- const { tableName, selectedField, columns, dataSearch, setOpenEditorDialog, setSelectedEditItem, setOpenViewDialog, onEditClick } = useDataTable();
18
- const { setPermission, Permission } = usePermission();
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: () =>
@@ -34,7 +44,7 @@ const DataTable = () => {
34
44
  onSuccess: ({ PermissionModel, status }) => {
35
45
  if (status) {
36
46
  // setPermission(PermissionModel);
37
- console.log("LOAD LAI PermissionModel");
47
+ // console.log("LOAD LAI PermissionModel");
38
48
  }
39
49
  }
40
50
  });
@@ -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 "./hooks";
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 { canSave } = usePermission();
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={'body'}>
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>
@@ -28,7 +28,7 @@ function EditorForm({ fields, submitRef }) {
28
28
  if (selectedEditItem) {
29
29
  setValue("Id", selectedEditItem.Id);
30
30
 
31
- fields.forEach(({ field, onChange, type, keyValue, keyValueLabel, defaultValue, }) => {
31
+ fields.forEach(({ field, onChange, type, keyValue, keyValueLabel, defaultValue }) => {
32
32
  if (type == "autocomplete") {
33
33
  onChange?.({
34
34
  [keyValue]: selectedEditItem[field]
@@ -44,8 +44,7 @@ function EditorForm({ fields, submitRef }) {
44
44
  if (typeof fileValue == "string") {
45
45
  fileValue = JSON.parse(fileValue);
46
46
  }
47
- }
48
- catch (e) {
47
+ } catch (e) {
49
48
  fileValue = [];
50
49
  }
51
50
  setValue(field, fileValue);
@@ -64,12 +63,10 @@ function EditorForm({ fields, submitRef }) {
64
63
  if (type === "switch" && defaultValue === undefined) {
65
64
  methods.setValue(field, true);
66
65
  } else {
67
-
68
66
  methods.setValue(field, defaultValue);
69
67
  }
70
68
  });
71
69
  }
72
-
73
70
  }, [selectedEditItem]);
74
71
 
75
72
  const saveMutation = useMutation(saveDataToTable, {
@@ -116,9 +113,12 @@ function EditorForm({ fields, submitRef }) {
116
113
  }
117
114
  });
118
115
  };
116
+ const onValid = (data) => {
117
+ console.log(data);
118
+ };
119
119
  return (
120
120
  <FormProvider {...methods}>
121
- <Box component={"form"} onSubmit={methods.handleSubmit(onSubmit)}>
121
+ <Box component={"form"} onSubmit={methods.handleSubmit(onSubmit, onValid)}>
122
122
  <Grid container spacing={2}>
123
123
  {fields.map(
124
124
  ({
@@ -129,7 +129,7 @@ function EditorForm({ fields, submitRef }) {
129
129
  childrenFields,
130
130
  datas,
131
131
  loading = false,
132
- onChange = () => { },
132
+ onChange = () => {},
133
133
  keyLabel,
134
134
  keyValue,
135
135
  keyValueLabel,
@@ -1,12 +1,14 @@
1
- import { Accordion, AccordionSummary, Box, FormControl, InputLabel, MenuItem, Select, Slider, Toolbar, Typography } from "@mui/material";
1
+ import { Accordion, AccordionSummary, Box, Slider, Typography } from "@mui/material";
2
2
  import { useFormContext } from "react-hook-form";
3
3
  import Grid from "@mui/material/Unstable_Grid2";
4
- import DateRangePicker from "../date/DateRangePicker";
4
+
5
5
  import { FilterElement } from "./FilterElement";
6
6
  import { useDataTable } from "./hooks";
7
7
 
8
- import AccordionDetails from '@mui/material/AccordionDetails';
9
- import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
8
+ import AccordionDetails from "@mui/material/AccordionDetails";
9
+ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
10
+ import { DateRangePicker } from "../date";
11
+ import { ArraySchema } from "yup";
10
12
 
11
13
  export const FilterGod = ({ filters, elementSize = "small" }) => {
12
14
  const { handleSubmit } = useFormContext();
@@ -14,15 +16,12 @@ export const FilterGod = ({ filters, elementSize = "small" }) => {
14
16
  const { setDataSearch, dataSearch } = useDataTable();
15
17
 
16
18
  return (
17
- <Box
18
- component={"form"}
19
- onSubmit={handleSubmit(onSubmit)}
20
- >
19
+ <Box component={"form"} onSubmit={handleSubmit(onSubmit)}>
21
20
  <Accordion>
22
21
  <AccordionSummary
23
22
  sx={{
24
23
  minHeight: 40,
25
- '& .MuiAccordionSummary-content': {
24
+ "& .MuiAccordionSummary-content": {
26
25
  my: 1
27
26
  }
28
27
  }}
@@ -36,15 +35,21 @@ export const FilterGod = ({ filters, elementSize = "small" }) => {
36
35
  <Grid container spacing={1}>
37
36
  {filters.map(({ field, size, ...rest }) => {
38
37
  if (rest.type === "date-range") {
38
+ let label = ["từ ngày", "tới ngày"];
39
+
40
+ if (Array.isArray(field.label)) {
41
+ label = field.label;
42
+ }
39
43
  return (
40
44
  <Grid key={field.toString()} md={size?.md} xs={size?.xs} sm={size?.sm}>
41
45
  <DateRangePicker
46
+ label={label}
42
47
  onChange={(value) => {
43
- setDataSearch(({ previousState }) => ({
44
- ...previousState,
48
+ setDataSearch({
49
+ ...dataSearch,
45
50
  [field[0]]: value[0],
46
51
  [field[1]]: value[1]
47
- }));
52
+ });
48
53
  }}
49
54
  size={elementSize}
50
55
  value={[dataSearch?.[field[0]], dataSearch?.[field[1]]]}
@@ -55,10 +60,7 @@ export const FilterGod = ({ filters, elementSize = "small" }) => {
55
60
 
56
61
  if (rest.type === "slider-range") {
57
62
  return (
58
- <Grid
59
- key={field.toString()}
60
- md={size?.md} xs={size?.xs} sm={size?.sm}
61
- >
63
+ <Grid key={field.toString()} md={size?.md} xs={size?.xs} sm={size?.sm}>
62
64
  <Slider
63
65
  onChange={(e, value) => {
64
66
  setDataSearch({
@@ -78,7 +80,7 @@ export const FilterGod = ({ filters, elementSize = "small" }) => {
78
80
  );
79
81
  }
80
82
  return (
81
- <Grid key={field} md={size?.md} xs={size?.xs} sm={size?.sm} >
83
+ <Grid key={field} md={size?.md} xs={size?.xs} sm={size?.sm}>
82
84
  <FilterElement name={field} {...rest} size={elementSize} />
83
85
  </Grid>
84
86
  );
@@ -1,8 +1,10 @@
1
1
  import { Checkbox, TableRow, TableCell, TableHead as MuiTableHead, useTheme, useMediaQuery } from "@mui/material";
2
- import { useDataTable, usePermission } from "./hooks";
2
+ import { useDataTable } from "./hooks";
3
+ import { usePermission } from "../../hooks";
3
4
  export function TableHead({ numSelected, rowCount, onSelectAllClick, headLabel }) {
4
- const { canEdit } = usePermission();
5
- const { disableStatus,disableCellThaoTac } = useDataTable();
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, usePermission } from "./hooks";
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 && <TableCell align="center">
73
- {canEdit && (
74
- <Tooltip title="Chỉnh sửa">
75
- <IconButton size={downXl ? "small" : "medium"} onClick={() => onEdit(row)}>
76
- <EditOutlined fontSize="inherit" color="primary" />
77
- </IconButton>
78
- </Tooltip>
79
- )}
80
- {canView && !tableActions?.some(({ permissionType }) => permissionType == "view") && (
81
- <Tooltip title="Xem chi tiết">
82
- <IconButton onClick={() => onView(row)}>
83
- <RemoveRedEyeOutlinedIcon color="info" />
84
- </IconButton>
85
- </Tooltip>
86
- )}
87
- {canDelete && (
88
- <Tooltip title="Xóa">
89
- <IconButton size={downXl ? "small" : "medium"}
90
- onClick={() => {
91
- onDelete(row[selectedField]);
92
- }}
93
- >
94
- <DeleteOutlineIcon fontSize="inherit" color="error" />
95
- </IconButton>
96
- </Tooltip>
97
- )}
98
- {tableActionsOnTable.map(({ title, onClick, element }) => (
99
- <Tooltip key={title} title={title}>
100
- <IconButton size={downXl ? "small" : "medium"}
101
- onClick={() => {
102
- onClick(row);
103
- }}
104
- >
105
- {element}
106
- </IconButton>
107
- </Tooltip>
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
- {<MoreMenu actions={tableActionsOnMoreMenu} data={row} />}
111
- </TableCell>}
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
- import { usePermission } from "./hooks";
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 { canDeleteMulti } = usePermission();
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 "trithuc-mvc-react/components/DataManagement/EditorForm";
14
- import { useDataTable, usePermission } from "trithuc-mvc-react/components/DataManagement/hooks";
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} >{tenFile}</Link>}
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 = () => { }, fields = [] }) {
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={'body'}>
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,4 +1,3 @@
1
1
  import { createContext } from "react";
2
2
 
3
3
  export const DataTableContext = createContext({ tableName: null });
4
- export const PermissionContext = createContext({});
@@ -1,22 +1,6 @@
1
- import { useContext, useMemo } from "react";
2
- import { DataTableContext, PermissionContext } from "./context";
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
- }