diff --git a/src/components/dashboard/inquiryPrivacyFencing/index.jsx b/src/components/dashboard/inquiryPrivacyFencing/index.jsx index c7f3404..3ee9a28 100644 --- a/src/components/dashboard/inquiryPrivacyFencing/index.jsx +++ b/src/components/dashboard/inquiryPrivacyFencing/index.jsx @@ -8,6 +8,41 @@ import { GET_INQUIRY_PRIVACY_FENCING_ROUTE } from "@/core/utils/routes"; const InquiryPrivacyFencingPage = () => { const columns = useMemo( () => [ + { + accessorKey: "fullname", + header: "fullname", + id: "fullname", + columns: [ + { + accessorKey: "first_name", + header: "first_name", + id: "first_name", + columns: [ + { + accessorKey: "first_name_first", + header: "first_name_first", + id: "first_name_first", + enableColumnFilter: false, + datatype: "text", + }, + { + accessorKey: "first_name_last", + header: "first_name_last", + id: "first_name_last", + enableColumnFilter: false, + datatype: "text", + }, + ], + }, + { + accessorKey: "last_name", + header: "last_name", + id: "last_name", + enableColumnFilter: false, + datatype: "text", + }, + ], + }, { accessorKey: "dabirkhaneh_number", header: "شماره دبیرخانه درخواست", diff --git a/src/core/components/DataTable/Main.js b/src/core/components/DataTable/Main.js index f18084c..4a3908b 100644 --- a/src/core/components/DataTable/Main.js +++ b/src/core/components/DataTable/Main.js @@ -1,7 +1,6 @@ import DataTable_Paper from "./table/Paper"; import { useMaterialReactTable } from "material-react-table"; import { FA_DATATABLE_LOCALIZATION } from "./localization/fa/datatable"; -import useTableSetting from "@/lib/hooks/useTableSetting"; import { flattenArrayOfObjects } from "@/core/utils/flattenArrayOfObjects"; import useDataTable from "@/lib/hooks/useDataTable"; import { useMemo, useState } from "react"; @@ -10,17 +9,10 @@ import useSWR from "swr"; const DataTable_Main = (props) => { const request = useRequest(); - const isEmptyObject = (obj) => obj && Object.keys(obj).length === 0 && obj.constructor === Object; const { filterData, sortData, setSortData, hideData, setHideData } = useDataTable(); const { need_filter, table_url, user_id, page_name, table_name, columns, initialStateProps, TableToolbar } = props; const flatColumns = flattenArrayOfObjects(columns, "columns"); - const { settingStore, hideAction } = useTableSetting(); const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 }); - - const onColumnVisibilityChange = (event) => { - setHideData(event); - }; - const onSortingChange = (event) => { setSortData(event); }; @@ -103,7 +95,6 @@ const DataTable_Main = (props) => { manualPagination: true, manualSorting: true, onPaginationChange: setPagination, - onColumnVisibilityChange: onColumnVisibilityChange, onSortingChange: onSortingChange, renderTopToolbarCustomActions: ({ table }) => ( <> diff --git a/src/core/components/DataTable/buttons/ShowHideColumnsButton.js b/src/core/components/DataTable/buttons/ShowHideColumnsButton.js deleted file mode 100644 index cd6c8ac..0000000 --- a/src/core/components/DataTable/buttons/ShowHideColumnsButton.js +++ /dev/null @@ -1,30 +0,0 @@ -import { IconButton, Tooltip } from "@mui/material"; -import { useState } from "react"; -import DataTable_ShowHideColumnsMenu from "../menus/ShowHideColumnsMenu"; - -const DataTable_ShowHideColumnsButton = ({ table, ...rest }) => { - const { - options: { - icons: { ViewColumnIcon }, - localization, - }, - } = table; - - const [anchorEl, setAnchorEl] = useState(null); - - const handleClick = (event) => { - setAnchorEl(event.currentTarget); - }; - - return ( - <> - - - - - - {anchorEl && } - - ); -}; -export default DataTable_ShowHideColumnsButton; diff --git a/src/core/components/DataTable/filter/FilterHeader.jsx b/src/core/components/DataTable/filter/FilterHeader.jsx index 76980ce..50d00d8 100644 --- a/src/core/components/DataTable/filter/FilterHeader.jsx +++ b/src/core/components/DataTable/filter/FilterHeader.jsx @@ -19,7 +19,7 @@ function FilterHeader({ setDrawerState }) { }} > - + فیلتر diff --git a/src/core/components/DataTable/hide/HideBody.jsx b/src/core/components/DataTable/hide/HideBody.jsx new file mode 100644 index 0000000..adf4c12 --- /dev/null +++ b/src/core/components/DataTable/hide/HideBody.jsx @@ -0,0 +1,46 @@ +"use client"; + +import { Box, Drawer, styled } from "@mui/material"; +import useDataTable from "@/lib/hooks/useDataTable"; +import HideBodyField from "@/core/components/DataTable/hide/HideBodyField"; +import HideHeader from "@/core/components/DataTable/hide/HideHeader"; + +const ScrollBox = styled(Box)({ + flexGrow: 1, + overflowY: "scroll", + maxWidth: "450px", + "::-webkit-scrollbar": { + width: "5px", + }, + "::-webkit-scrollbar-track": { + boxShadow: "inset 0 0 5px #fff", + borderRadius: "5px", + }, + "::-webkit-scrollbar-thumb": { + background: "#155175", + borderRadius: "0px", + }, +}); + +function HideBody({ columns, drawerState, setDrawerState }) { + const { hideData } = useDataTable(); + + return ( + setDrawerState(false)} + sx={{ overflowY: "hidden", display: "flex", flexDirection: "column", height: "100%" }} + > + + {Object.keys(hideData).length > 0 && ( + + + {columns.map((column) => ())} + + + )} + + ); +} + +export default HideBody; diff --git a/src/core/components/DataTable/hide/HideBodyField.jsx b/src/core/components/DataTable/hide/HideBodyField.jsx new file mode 100644 index 0000000..e8123af --- /dev/null +++ b/src/core/components/DataTable/hide/HideBodyField.jsx @@ -0,0 +1,38 @@ +import { Box, FormControlLabel, Switch, Typography } from "@mui/material"; +import useDataTable from "@/lib/hooks/useDataTable"; + +function HideBodyField({ column, level = 0 }) { + const { hideData, setHideData } = useDataTable(); + const paddingLeft = 2 * level; + + return ( + + { + setHideData(hideData => ({ + ...hideData, + [column.id]: !hideData[column.id], + })); + }} + name={column.id} + /> + } + label={ + {column.header} + } + /> + {column.columns?.map((subColumn) => ( + + ))} + + ); +} + +export default HideBodyField; \ No newline at end of file diff --git a/src/core/components/DataTable/hide/HideButton.jsx b/src/core/components/DataTable/hide/HideButton.jsx new file mode 100644 index 0000000..de919fe --- /dev/null +++ b/src/core/components/DataTable/hide/HideButton.jsx @@ -0,0 +1,21 @@ +"use client"; + +import ViewColumnIcon from "@mui/icons-material/ViewColumn"; +import { IconButton, Tooltip } from "@mui/material"; + +function HideButton({ drawerState, setDrawerState }) { + return ( + + { + setDrawerState(!drawerState); + }} + aria-label="hide table column" + > + + + + ); +} + +export default HideButton; diff --git a/src/core/components/DataTable/hide/HideHeader.jsx b/src/core/components/DataTable/hide/HideHeader.jsx new file mode 100644 index 0000000..5adcf25 --- /dev/null +++ b/src/core/components/DataTable/hide/HideHeader.jsx @@ -0,0 +1,34 @@ +"use client"; + +import { Box, IconButton, Typography } from "@mui/material"; +import CancelIcon from "@mui/icons-material/Cancel"; +import ViewColumnIcon from "@mui/icons-material/ViewColumn"; + +function FilterHeader({ setDrawerState }) { + return ( + + + + + نمایش/مخفی کردن ستون ها + + + setDrawerState(false)}> + + + + ); +} + +export default FilterHeader; diff --git a/src/core/components/DataTable/hide/index.jsx b/src/core/components/DataTable/hide/index.jsx new file mode 100644 index 0000000..b917c56 --- /dev/null +++ b/src/core/components/DataTable/hide/index.jsx @@ -0,0 +1,24 @@ +"use client"; + +import { useState } from "react"; +import HideButton from "@/core/components/DataTable/hide/HideButton"; +import HideBody from "@/core/components/DataTable/hide/HideBody"; + +function HideColumn({ columns, user_id, page_name, table_name }) { + const [open, setOpen] = useState(false); + return ( + <> + + + + ); +} + +export default HideColumn; diff --git a/src/core/components/DataTable/menus/ShowHideColumnsMenu.js b/src/core/components/DataTable/menus/ShowHideColumnsMenu.js deleted file mode 100644 index cb0423c..0000000 --- a/src/core/components/DataTable/menus/ShowHideColumnsMenu.js +++ /dev/null @@ -1,116 +0,0 @@ -import { Box, Button, Divider, Menu } from "@mui/material"; -import { useMemo, useState } from "react"; -import DataTable_ShowHideColumnsMenuItems from "./ShowHideColumnsMenuItems"; - -const DataTable_ShowHideColumnsMenu = ({ anchorEl, setAnchorEl, table, ...rest }) => { - const { - getAllColumns, - getAllLeafColumns, - getCenterLeafColumns, - getIsAllColumnsVisible, - getIsSomeColumnsPinned, - getIsSomeColumnsVisible, - getLeftLeafColumns, - getRightLeafColumns, - getState, - options: { - enableColumnOrdering, - enableColumnPinning, - enableHiding, - localization, - mrtTheme: { menuBackgroundColor }, - }, - } = table; - - const { columnOrder, columnPinning, density } = getState(); - - const handleToggleAllColumns = (value) => { - getAllLeafColumns() - .filter((col) => col.columnDef.enableHiding !== false) - .forEach((col) => col.toggleVisibility(value)); - }; - - const allColumns = useMemo(() => { - const columns = getAllColumns(); - if (columnOrder.length > 0 && !columns.some((col) => col.columnDef.columnDefType === "group")) { - return [ - ...getLeftLeafColumns(), - ...Array.from(new Set(columnOrder)).map((colId) => - getCenterLeafColumns().find((col) => col?.id === colId) - ), - ...getRightLeafColumns(), - ].filter(Boolean); - } - return columns; - }, [ - columnOrder, - columnPinning, - getAllColumns(), - getCenterLeafColumns(), - getLeftLeafColumns(), - getRightLeafColumns(), - ]); - - const isNestedColumns = allColumns.some((col) => col.columnDef.columnDefType === "group"); - - const [hoveredColumn, setHoveredColumn] = useState(null); - - return ( - setAnchorEl(null)} - open={!!anchorEl} - {...rest} - > - - {enableHiding && ( - - )} - {enableColumnOrdering && ( - - )} - {enableColumnPinning && ( - - )} - {enableHiding && ( - - )} - - - {allColumns.map((column, index) => ( - - ))} - - ); -}; -export default DataTable_ShowHideColumnsMenu; diff --git a/src/core/components/DataTable/menus/ShowHideColumnsMenuItems.js b/src/core/components/DataTable/menus/ShowHideColumnsMenuItems.js deleted file mode 100644 index 97c2e5d..0000000 --- a/src/core/components/DataTable/menus/ShowHideColumnsMenuItems.js +++ /dev/null @@ -1,154 +0,0 @@ -import { getCommonTooltipProps, parseFromValuesOrFunc } from "@/core/utils/utils"; -import { Box, FormControlLabel, MenuItem, Switch, Tooltip, Typography } from "@mui/material"; -import { useRef, useState } from "react"; -import DataTable_GrabHandleButton from "../buttons/GrabHandleButton"; - -const DataTable_ShowHideColumnsMenuItems = ({ - allColumns, - column, - hoveredColumn, - isNestedColumns, - setHoveredColumn, - table, - ...rest -}) => { - const { - getState, - options: { - enableColumnOrdering, - enableHiding, - localization, - mrtTheme: { draggingBorderColor }, - }, - setColumnOrder, - } = table; - - const { columnOrder } = getState(); - const { columnDef } = column; - const { columnDefType } = columnDef; - - const switchChecked = column.getIsVisible(); - - const handleToggleColumnHidden = (column) => { - if (columnDefType === "group") { - column?.columns?.forEach?.((childColumn) => { - childColumn.toggleVisibility(!switchChecked); - }); - } else { - column.toggleVisibility(); - } - }; - - const menuItemRef = useRef(null); - - const [isDragging, setIsDragging] = useState(false); - - const handleDragStart = (e) => { - setIsDragging(true); - try { - e.dataTransfer.setDragImage(menuItemRef.current, 0, 0); - } catch (e) { - console.error(e); - } - }; - - const handleDragEnd = (_e) => { - setIsDragging(false); - setHoveredColumn(null); - if (hoveredColumn) { - setColumnOrder(reorderColumn(column, hoveredColumn, columnOrder)); - } - }; - - const handleDragEnter = (_e) => { - if (!isDragging && columnDef.enableColumnOrdering !== false) { - setHoveredColumn(column); - } - }; - - if (!columnDef.header || columnDef.visibleInShowHideMenu === false) { - return null; - } - - return ( - <> - ({ - alignItems: "center", - justifyContent: "flex-start", - my: 0, - opacity: isDragging ? 0.5 : 1, - outline: isDragging - ? `2px dashed ${theme.palette.grey[500]}` - : hoveredColumn?.id === column.id - ? `2px dashed ${draggingBorderColor}` - : "none", - outlineOffset: "-2px", - pl: `${(column.depth + 0.5) * 2}rem`, - py: "6px", - ...parseFromValuesOrFunc(rest?.sx, theme), - })} - > - - {columnDefType !== "group" && - enableColumnOrdering && - !isNestedColumns && - (columnDef.enableColumnOrdering !== false ? ( - - ) : ( - - ))} - {enableHiding ? ( - - - - } - disabled={!column.getCanHide()} - label={columnDef.header} - onChange={() => handleToggleColumnHidden(column)} - /> - ) : ( - {columnDef.header} - )} - - - {column.columns?.map((c, i) => ( - - ))} - - ); -}; -export default DataTable_ShowHideColumnsMenuItems; diff --git a/src/core/components/DataTable/toolbar/ToolbarInternalButtons.js b/src/core/components/DataTable/toolbar/ToolbarInternalButtons.js deleted file mode 100644 index 9250b89..0000000 --- a/src/core/components/DataTable/toolbar/ToolbarInternalButtons.js +++ /dev/null @@ -1,44 +0,0 @@ -import { parseFromValuesOrFunc } from "@/core/utils/utils"; -import { Box } from "@mui/material"; -import DataTable_ShowHideColumnsButton from "../buttons/ShowHideColumnsButton"; -import DataTable_ToggleFiltersButton from "../buttons/ToggleFiltersButton"; - -const DataTable_ToolbarInternalButtons = ({ table, ...rest }) => { - const { - options: { - columnFilterDisplayMode, - enableColumnFilters, - enableColumnOrdering, - enableColumnPinning, - enableFilters, - enableHiding, - renderToolbarInternalActions, - }, - } = table; - - return ( - ({ - alignItems: "center", - display: "flex", - zIndex: 3, - ...parseFromValuesOrFunc(rest?.sx, theme), - })} - > - {renderToolbarInternalActions?.({ - table, - }) ?? ( - <> - {enableFilters && enableColumnFilters && columnFilterDisplayMode !== "popover" && ( - - )} - {(enableHiding || enableColumnOrdering || enableColumnPinning) && ( - - )} - - )} - - ); -}; -export default DataTable_ToolbarInternalButtons; diff --git a/src/core/components/DataTable/toolbar/TopToolbar.js b/src/core/components/DataTable/toolbar/TopToolbar.js index 09836e2..e5dc946 100644 --- a/src/core/components/DataTable/toolbar/TopToolbar.js +++ b/src/core/components/DataTable/toolbar/TopToolbar.js @@ -2,10 +2,10 @@ import { getCommonToolbarStyles, parseFromValuesOrFunc } from "@/core/utils/util import { Box, useMediaQuery } from "@mui/material"; import DataTable_LinearProgressBar from "./LinearProgressBar"; import DataTable_TablePagination from "./TablePagination"; -import DataTable_ToolbarInternalButtons from "./ToolbarInternalButtons"; import FilterColumn from "@/core/components/DataTable/filter"; import UpdateTable from "@/core/components/DataTable/update/UpdateTable"; import ResetStorage from "@/core/components/DataTable/reset/ResetStorage"; +import HideColumn from "@/core/components/DataTable/hide"; const DataTable_TopToolbar = ({ mutate, need_filter, table, columns, table_url, user_id, page_name, table_name }) => { const { @@ -74,6 +74,11 @@ const DataTable_TopToolbar = ({ mutate, need_filter, table, columns, table_url, page_name={page_name} table_name={table_name} /> + {need_filter && ( )} - )} diff --git a/src/core/utils/flattenArrayOfObjects.js b/src/core/utils/flattenArrayOfObjects.js index 5b1564c..ec3cc23 100644 --- a/src/core/utils/flattenArrayOfObjects.js +++ b/src/core/utils/flattenArrayOfObjects.js @@ -1,10 +1,10 @@ export const flattenArrayOfObjects = (array, key) => { return array.reduce((acc, obj) => { + acc.push(obj); if (Array.isArray(obj[key])) { - acc.push(...flattenArrayOfObjects(obj[key])); - } else { - acc.push(obj); + acc.push(...flattenArrayOfObjects(obj[key], key)); } return acc; }, []); }; + diff --git a/src/lib/contexts/DataTable.js b/src/lib/contexts/DataTable.js index 85f521f..4d50a7f 100644 --- a/src/lib/contexts/DataTable.js +++ b/src/lib/contexts/DataTable.js @@ -19,44 +19,53 @@ const DataTableProvider = ({ children, user_id, page_name, table_name, columns } useEffect(() => { if (!settingStore) return; - const values = flatColumns.reduce((acc, column) => { + const filterValues = flatColumns.reduce((acc, column) => { if (!column.enableColumnFilter) return acc; - const filter = settingStore?.[user_id]?.[page_name]?.[table_name]?.["filters"]?.find( + const storeFilter = settingStore?.[user_id]?.[page_name]?.[table_name]?.["filters"]?.find( (filter) => filter.id === column.id, ); if (column.datatype === "array") { acc[column.id] = { id: column.id, - value: filter?.value || [], - filterFn: filter?.filterFn || column._filterFn, + value: storeFilter?.value || [], + filterFn: storeFilter?.filterFn || column._filterFn, datatype: column.datatype, }; } else if (column._filterFn === "between") { acc[column.id] = { id: column.id, - value: filter?.value || ["", ""], - filterFn: filter?.filterFn || column._filterFn, + value: storeFilter?.value || ["", ""], + filterFn: storeFilter?.filterFn || column._filterFn, datatype: column.datatype, }; } else { acc[column.id] = { id: column.id, - value: filter?.value || "", - filterFn: filter?.filterFn || column._filterFn, + value: storeFilter?.value || "", + filterFn: storeFilter?.filterFn || column._filterFn, datatype: column.datatype, }; } return acc; }, {}); - setFilterData(values); - setInitFilter(values); + setFilterData(filterValues); + setInitFilter(filterValues); setSortData(settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || []); setInitSort(settingStore?.[user_id]?.[page_name]?.[table_name]?.["sorts"] || []); - setHideData(settingStore?.[user_id]?.[page_name]?.[table_name]?.["hides"] || {}); - setInitHide(settingStore?.[user_id]?.[page_name]?.[table_name]?.["hides"] || {}); setInitStates(true); }, [settingStore, isInitStates]); + useEffect(() => { + const hideValues = flatColumns.reduce((acc, column) => { + const columnId = column.id; + const storeHide = settingStore?.[user_id]?.[page_name]?.[table_name]?.["hides"]?.[columnId]; + acc[columnId] = storeHide !== undefined ? storeHide : true; + return acc; + }, {}); + setHideData(hideValues); + setInitHide(hideValues); + }, [settingStore, isInitStates]); + useEffect(() => { if ( JSON.stringify(initFilter) !== JSON.stringify(filterData) ||