complete hide action part with button for hide or show all table header

This commit is contained in:
2024-07-27 11:32:27 +03:30
parent d3bc855f39
commit f974363790
9 changed files with 239 additions and 57 deletions

View File

@@ -18,6 +18,7 @@
"@mui/material": "^5.15.6", "@mui/material": "^5.15.6",
"@mui/material-nextjs": "^5.15.6", "@mui/material-nextjs": "^5.15.6",
"@mui/x-date-pickers": "^6.19.5", "@mui/x-date-pickers": "^6.19.5",
"@mui/x-tree-view": "^7.11.0",
"axios": "^1.7.2", "axios": "^1.7.2",
"date-fns": "^3.3.1", "date-fns": "^3.3.1",
"date-fns-jalali": "^2.13.0-0", "date-fns-jalali": "^2.13.0-0",

View File

@@ -10,25 +10,41 @@ const InquiryPrivacyFencingPage = () => {
() => [ () => [
{ {
accessorKey: "fullname", accessorKey: "fullname",
header: "fullname", header: "نام کامل",
id: "fullname", id: "fullname",
columns: [ columns: [
{ {
accessorKey: "first_name", accessorKey: "first_name",
header: "first_name", header: "اسم",
id: "first_name", id: "first_name",
columns: [ columns: [
{ {
accessorKey: "first_name_first", accessorKey: "part1",
header: "first_name_first", header: "فامیل",
id: "first_name_first", id: "part1",
enableColumnFilter: false, enableColumnFilter: false,
datatype: "text", datatype: "text",
columns: [
{
accessorKey: "part1_1",
header: "part1_1",
id: "part1_1",
enableColumnFilter: false,
datatype: "text",
},
{
accessorKey: "part1_2",
header: "part1_2",
id: "part1_2",
enableColumnFilter: false,
datatype: "text",
},
],
}, },
{ {
accessorKey: "first_name_last", accessorKey: "part2",
header: "first_name_last", header: "part2",
id: "first_name_last", id: "part2",
enableColumnFilter: false, enableColumnFilter: false,
datatype: "text", datatype: "text",
}, },
@@ -43,6 +59,25 @@ const InquiryPrivacyFencingPage = () => {
}, },
], ],
}, },
{
accessorKey: "something",
header: "something",
id: "something",
columns: [
{
accessorKey: "something1",
header: "something1",
id: "something1",
},
{
accessorKey: "something2",
header: "something2",
id: "something2",
enableColumnFilter: false,
datatype: "text",
},
],
},
{ {
accessorKey: "dabirkhaneh_number", accessorKey: "dabirkhaneh_number",
header: "شماره دبیرخانه درخواست", header: "شماره دبیرخانه درخواست",

View File

@@ -6,13 +6,15 @@ import useDataTable from "@/lib/hooks/useDataTable";
import { useMemo, useState } from "react"; import { useMemo, useState } from "react";
import useRequest from "@/lib/hooks/useRequest"; import useRequest from "@/lib/hooks/useRequest";
import useSWR from "swr"; import useSWR from "swr";
import { flattenObjectOfObjects } from "@/core/utils/flattenObjectOfObjects";
const DataTable_Main = (props) => { const DataTable_Main = (props) => {
const request = useRequest(); const request = useRequest();
const { filterData, sortData, setSortData, hideData, setHideData } = useDataTable(); const { filterData, sortData, setSortData, hideData } = useDataTable();
const { need_filter, table_url, user_id, page_name, table_name, columns, initialStateProps, TableToolbar } = props; const { need_filter, table_url, user_id, page_name, table_name, columns, initialStateProps, TableToolbar } = props;
const flatColumns = flattenArrayOfObjects(columns, "columns"); const flatColumns = flattenArrayOfObjects(columns, "columns");
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 }); const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 });
const flattenHideData = flattenObjectOfObjects(hideData);
const onSortingChange = (event) => { const onSortingChange = (event) => {
setSortData(event); setSortData(event);
}; };
@@ -58,13 +60,13 @@ const DataTable_Main = (props) => {
data: data?.data ?? [], data: data?.data ?? [],
initialState: { initialState: {
density: "compact", density: "compact",
columnVisibility: hideData, columnVisibility: flattenHideData,
sorting: sortData, sorting: sortData,
...initialStateProps, ...initialStateProps,
}, },
state: { state: {
showProgressBars: isValidating, showProgressBars: isValidating,
columnVisibility: hideData, columnVisibility: flattenHideData,
sorting: sortData, sorting: sortData,
pagination, pagination,
}, },

View File

@@ -1,9 +1,10 @@
"use client"; "use client";
import { Box, Drawer, styled } from "@mui/material"; import { Box, Drawer, styled } from "@mui/material";
import useDataTable from "@/lib/hooks/useDataTable";
import HideBodyField from "@/core/components/DataTable/hide/HideBodyField"; import HideBodyField from "@/core/components/DataTable/hide/HideBodyField";
import HideHeader from "@/core/components/DataTable/hide/HideHeader"; import HideHeader from "@/core/components/DataTable/hide/HideHeader";
import useDataTable from "@/lib/hooks/useDataTable";
import HideOrShowAll from "@/core/components/DataTable/hide/HideOrShowAll";
const ScrollBox = styled(Box)({ const ScrollBox = styled(Box)({
flexGrow: 1, flexGrow: 1,
@@ -23,7 +24,7 @@ const ScrollBox = styled(Box)({
}); });
function HideBody({ columns, drawerState, setDrawerState }) { function HideBody({ columns, drawerState, setDrawerState }) {
const { hideData } = useDataTable(); const { hideData, setHideData } = useDataTable();
return ( return (
<Drawer <Drawer
@@ -32,13 +33,19 @@ function HideBody({ columns, drawerState, setDrawerState }) {
sx={{ overflowY: "hidden", display: "flex", flexDirection: "column", height: "100%" }} sx={{ overflowY: "hidden", display: "flex", flexDirection: "column", height: "100%" }}
> >
<HideHeader setDrawerState={setDrawerState} /> <HideHeader setDrawerState={setDrawerState} />
{Object.keys(hideData).length > 0 && ( <HideOrShowAll hideData={hideData} setHideData={setHideData} />
<ScrollBox> <ScrollBox>
<Box sx={{ px: 1, py: 2, display: "flex", flexDirection: "column" }}> <Box sx={{ px: 1, py: 2, display: "flex", flexDirection: "column" }}>
{columns.map((column) => (<HideBodyField key={column.id} column={column} />))} {columns.map((column) => (
</Box> <HideBodyField
</ScrollBox> key={column.id}
)} column={column}
hideData={hideData}
setHideData={setHideData}
/>
))}
</Box>
</ScrollBox>
</Drawer> </Drawer>
); );
} }

View File

@@ -1,37 +1,79 @@
import { Box, FormControlLabel, Switch, Typography } from "@mui/material"; import { alpha, Box, Checkbox, styled, Typography } from "@mui/material";
import useDataTable from "@/lib/hooks/useDataTable"; import { SimpleTreeView } from "@mui/x-tree-view";
import { TreeItem, treeItemClasses } from "@mui/x-tree-view/TreeItem";
function HideBodyField({ column, level = 0 }) { const CustomTreeItem = styled(TreeItem)(({ theme }) => ({
const { hideData, setHideData } = useDataTable(); [`& .${treeItemClasses.content}`]: {
const paddingLeft = 2 * level; padding: theme.spacing(0.5, 0.5),
margin: theme.spacing(0.2, 0),
gap: 0,
},
[`& .${treeItemClasses.iconContainer}`]: {
"& .close": {
opacity: 0.3,
},
},
[`& .${treeItemClasses.groupTransition}`]: {
marginLeft: 16,
paddingLeft: 16,
borderLeft: `1px dashed ${alpha(theme.palette.text.primary, 0.4)}`,
},
}));
return ( function HideBodyField({ column, hideData, setHideData }) {
<Box sx={{ py: 1, px: 1, pl: paddingLeft }}> const handleCheckboxChange = () => {
<FormControlLabel setHideData(prevData => {
control={ const updateHideData = (data, id) => {
<Switch if (data.hasOwnProperty(id)) {
return { ...data, [id]: !data[id] };
}
const updatedData = { ...data };
for (const key in data) {
if (data[key] && typeof data[key] === "object") {
updatedData[key] = updateHideData(data[key], id);
}
}
return updatedData;
};
return updateHideData(prevData, column.id);
});
};
const labelContent = (() => {
if (typeof hideData[column.id] === "boolean") {
return (
<Box sx={{ display: "flex", alignItems: "center" }}>
<Checkbox
checked={hideData[column.id]} checked={hideData[column.id]}
onChange={() => { onChange={handleCheckboxChange}
setHideData(hideData => ({
...hideData,
[column.id]: !hideData[column.id],
}));
}}
name={column.id} name={column.id}
/> />
}
label={
<Typography variant="subtitle1">{column.header}</Typography> <Typography variant="subtitle1">{column.header}</Typography>
} </Box>
/> );
{column.columns?.map((subColumn) => ( } else {
<HideBodyField return (
key={subColumn.id} <Box sx={{ display: "flex", alignItems: "center", p: 1 }}>
column={subColumn} <Typography variant="subtitle1">{column.header}</Typography>
level={level + 1} </Box>
/> );
))} }
</Box> })();
return (
<SimpleTreeView disableSelection>
<CustomTreeItem itemId={column.id} label={labelContent}>
{column.columns?.map((subColumn) => (
<HideBodyField
key={subColumn.id}
column={subColumn}
hideData={hideData[column.id]}
setHideData={setHideData}
/>
))}
</CustomTreeItem>
</SimpleTreeView>
); );
} }

View File

@@ -0,0 +1,70 @@
"use client";
import { Box, Button } from "@mui/material";
import VisibilityIcon from "@mui/icons-material/Visibility";
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
const setAllValues = (obj, value) => {
const result = {};
for (const key in obj) {
if (typeof obj[key] === "object" && obj[key] !== null) {
result[key] = setAllValues(obj[key], value);
} else {
result[key] = value;
}
}
return result;
};
const allValuesAre = (obj, value) => {
for (const key in obj) {
if (typeof obj[key] === "object" && obj[key] !== null) {
if (!allValuesAre(obj[key], value)) {
return false;
}
} else if (obj[key] !== value) {
return false;
}
}
return true;
};
function HideOrShowAll({ hideData, setHideData }) {
const handleShowAll = () => {
const newHideData = setAllValues(hideData, true);
setHideData(newHideData);
};
const handleHideAll = () => {
const newHideData = setAllValues(hideData, false);
setHideData(newHideData);
};
const allHidden = allValuesAre(hideData, false);
const allVisible = allValuesAre(hideData, true);
return (
<Box sx={{ mx: 2, my: 1, display: "flex", justifyContent: "space-between" }}>
<Button
color="info"
disabled={allVisible}
variant="contained"
startIcon={<VisibilityIcon />}
onClick={handleShowAll}
>
نمایش همه
</Button>
<Button
color="error"
disabled={allHidden}
variant="contained"
startIcon={<VisibilityOffIcon />}
onClick={handleHideAll}
>
مخفی کردن همه
</Button>
</Box>
);
}
export default HideOrShowAll;

View File

@@ -5,9 +5,11 @@ import { Box, Button, Typography } from "@mui/material";
import DownloadIcon from "@mui/icons-material/Download"; import DownloadIcon from "@mui/icons-material/Download";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import useTableSetting from "@/lib/hooks/useTableSetting"; import useTableSetting from "@/lib/hooks/useTableSetting";
import { flattenObjectOfObjects } from "@/core/utils/flattenObjectOfObjects";
function AskForKeepData({ filterData, sortData, hideData, user_id, page_name, table_name, columns }) { function AskForKeepData({ filterData, sortData, hideData, user_id, page_name, table_name, columns }) {
const { filterAction, sortAction, hideAction } = useTableSetting(); const { filterAction, sortAction, hideAction } = useTableSetting();
const flattenHideData = flattenObjectOfObjects(hideData);
const onSaveFilter = () => { const onSaveFilter = () => {
const filteredItems = Object.keys(filterData) const filteredItems = Object.keys(filterData)
@@ -26,7 +28,7 @@ function AskForKeepData({ filterData, sortData, hideData, user_id, page_name, ta
.filter(Boolean); .filter(Boolean);
filterAction(user_id, page_name, table_name, filteredItems, columns); filterAction(user_id, page_name, table_name, filteredItems, columns);
sortAction(user_id, page_name, table_name, sortData, columns); sortAction(user_id, page_name, table_name, sortData, columns);
hideAction(user_id, page_name, table_name, hideData, columns); hideAction(user_id, page_name, table_name, flattenHideData, columns);
toast.dismiss({ containerId: "datatable" }); toast.dismiss({ containerId: "datatable" });
}; };

View File

@@ -0,0 +1,12 @@
export const flattenObjectOfObjects = (obj, res = {}) => {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === "object" && obj[key] !== null) {
flattenObjectOfObjects(obj[key], res);
} else {
res[key] = obj[key];
}
}
}
return res;
};

View File

@@ -56,12 +56,23 @@ const DataTableProvider = ({ children, user_id, page_name, table_name, columns }
}, [settingStore, isInitStates]); }, [settingStore, isInitStates]);
useEffect(() => { useEffect(() => {
const hideValues = flatColumns.reduce((acc, column) => { const getHideValues = (columns) => {
const columnId = column.id; return columns.reduce((acc, column) => {
const storeHide = settingStore?.[user_id]?.[page_name]?.[table_name]?.["hides"]?.[columnId]; const columnId = column.id;
acc[columnId] = storeHide !== undefined ? storeHide : true; const storeHide = settingStore?.[user_id]?.[page_name]?.[table_name]?.["hides"]?.[columnId];
return acc;
}, {}); // If the column has nested columns, process them recursively
if (column.columns && column.columns.length > 0) {
acc[columnId] = getHideValues(column.columns);
} else {
acc[columnId] = storeHide !== undefined ? storeHide : true;
}
return acc;
}, {});
};
const hideValues = getHideValues(columns);
setHideData(hideValues); setHideData(hideValues);
setInitHide(hideValues); setInitHide(hideValues);
}, [settingStore, isInitStates]); }, [settingStore, isInitStates]);