complete hide action part with button for hide or show all table header
This commit is contained in:
@@ -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",
|
||||||
|
|||||||
@@ -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: "شماره دبیرخانه درخواست",
|
||||||
|
|||||||
@@ -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,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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,15 +33,21 @@ 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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default HideBody;
|
export default HideBody;
|
||||||
@@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
70
src/core/components/DataTable/hide/HideOrShowAll.jsx
Normal file
70
src/core/components/DataTable/hide/HideOrShowAll.jsx
Normal 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;
|
||||||
@@ -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" });
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -75,4 +77,4 @@ function AskForKeepData({ filterData, sortData, hideData, user_id, page_name, ta
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AskForKeepData;
|
export default AskForKeepData;
|
||||||
12
src/core/utils/flattenObjectOfObjects.jsx
Normal file
12
src/core/utils/flattenObjectOfObjects.jsx
Normal 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;
|
||||||
|
};
|
||||||
@@ -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]);
|
||||||
|
|||||||
Reference in New Issue
Block a user