implementation of datatable

This commit is contained in:
Amirhossein Mahmoodi
2024-04-16 11:45:14 +03:30
parent 78548e89e7
commit a8e28a4f8c
29 changed files with 2983 additions and 2 deletions

View File

@@ -0,0 +1,50 @@
import { Box, IconButton, ListItemIcon, MenuItem } from "@mui/material";
const DataTable_ActionMenuItem = ({
icon,
label,
onOpenSubMenu,
table,
...rest
}) => {
const {
options: {
icons: { ArrowRightIcon },
},
} = table;
return (
<MenuItem
sx={{
alignItems: 'center',
justifyContent: 'space-between',
minWidth: '120px',
my: 0,
py: '6px',
}}
{...rest}
>
<Box
sx={{
alignItems: 'center',
display: 'flex',
}}
>
<ListItemIcon>{icon}</ListItemIcon>
{label}
</Box>
{onOpenSubMenu && (
<IconButton
onClick={onOpenSubMenu}
onMouseEnter={onOpenSubMenu}
size="small"
sx={{ p: 0 }}
>
<ArrowRightIcon />
</IconButton>
)}
</MenuItem>
);
}
export default DataTable_ActionMenuItem

View File

@@ -0,0 +1,100 @@
import { parseFromValuesOrFunc } from "@/core/utils/utils";
import { Menu } from "@mui/material";
import DataTable_ActionMenuItem from "./ActionMenuItem";
const DataTable_CellActionMenu = ({
table,
...rest
}) => {
const {
getState,
options: {
editDisplayMode,
enableClickToCopy,
enableEditing,
icons: { ContentCopy, EditIcon },
localization,
mrtTheme: { menuBackgroundColor },
renderCellActionMenuItems,
},
refs: { actionCellRef },
} = table;
const { actionCell, density } = getState();
const cell = actionCell || null;
const { row } = cell;
const { column } = cell;
const { columnDef } = column;
const handleClose = (event) => {
event?.stopPropagation();
table.setActionCell(null);
actionCellRef.current = null;
};
const internalMenuItems = [
(parseFromValuesOrFunc(enableClickToCopy, cell) === 'context-menu' ||
parseFromValuesOrFunc(columnDef.enableClickToCopy, cell) ===
'context-menu') && (
<DataTable_ActionMenuItem
icon={<ContentCopy />}
key={'mrt-copy'}
label={localization.copy}
onClick={(event) => {
event.stopPropagation();
navigator.clipboard.writeText(cell.getValue());
handleClose();
}}
table={table}
/>
),
parseFromValuesOrFunc(enableEditing, row) && editDisplayMode === 'cell' && (
<DataTable_ActionMenuItem
icon={<EditIcon />}
key={'mrt-edit'}
label={localization.edit}
onClick={() => {
openEditingCell({ cell, table });
handleClose();
}}
table={table}
/>
),
].filter(Boolean);
const renderActionProps = {
cell,
closeMenu: handleClose,
column,
internalMenuItems,
row,
table,
};
const menuItems =
columnDef.renderCellActionMenuItems?.(renderActionProps) ??
renderCellActionMenuItems?.(renderActionProps);
return (
(!!menuItems?.length || !!internalMenuItems?.length) && (
<Menu
MenuListProps={{
dense: density === 'compact',
sx: {
backgroundColor: menuBackgroundColor,
},
}}
anchorEl={actionCellRef.current}
disableScrollLock
onClick={(event) => event.stopPropagation()}
onClose={handleClose}
open={!!cell}
transformOrigin={{ horizontal: -100, vertical: 8 }}
{...rest}
>
{menuItems ?? internalMenuItems}
</Menu>
)
);
}
export default DataTable_CellActionMenu

View File

@@ -0,0 +1,140 @@
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 (
<Menu
MenuListProps={{
dense: density === 'compact',
sx: {
backgroundColor: menuBackgroundColor,
},
}}
anchorEl={anchorEl}
disableScrollLock
onClose={() => setAnchorEl(null)}
open={!!anchorEl}
{...rest}
>
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
p: '0.5rem',
pt: 0,
}}
>
{enableHiding && (
<Button
disabled={!getIsSomeColumnsVisible()}
onClick={() => handleToggleAllColumns(false)}
>
{localization.hideAll}
</Button>
)}
{enableColumnOrdering && (
<Button
onClick={() =>
table.setColumnOrder(
getDefaultColumnOrderIds(table.options, true),
)
}
>
{localization.resetOrder}
</Button>
)}
{enableColumnPinning && (
<Button
disabled={!getIsSomeColumnsPinned()}
onClick={() => table.resetColumnPinning(true)}
>
{localization.unpinAll}
</Button>
)}
{enableHiding && (
<Button
disabled={getIsAllColumnsVisible()}
onClick={() => handleToggleAllColumns(true)}
>
{localization.showAll}
</Button>
)}
</Box>
<Divider />
{allColumns.map((column, index) => (
<DataTable_ShowHideColumnsMenuItems
allColumns={allColumns}
column={column}
hoveredColumn={hoveredColumn}
isNestedColumns={isNestedColumns}
key={`${index}-${column.id}`}
setHoveredColumn={setHoveredColumn}
table={table}
/>
))}
</Menu>
);
}
export default DataTable_ShowHideColumnsMenu

View File

@@ -0,0 +1,160 @@
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 (
<>
<MenuItem
disableRipple
onDragEnter={handleDragEnter}
ref={menuItemRef}
{...rest}
sx={(theme) => ({
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)),
})}
>
<Box
sx={{
display: 'flex',
flexWrap: 'nowrap',
gap: '8px',
}}
>
{columnDefType !== 'group' &&
enableColumnOrdering &&
!isNestedColumns &&
(columnDef.enableColumnOrdering !== false ? (
<DataTable_GrabHandleButton
onDragEnd={handleDragEnd}
onDragStart={handleDragStart}
table={table}
/>
) : (
<Box sx={{ width: '28px' }} />
))}
{enableHiding ? (
<FormControlLabel
checked={switchChecked}
componentsProps={{
typography: {
sx: {
mb: 0,
opacity: columnDefType !== 'display' ? 1 : 0.5,
},
},
}}
control={
<Tooltip
{...getCommonTooltipProps()}
title={localization.toggleVisibility}
>
<Switch />
</Tooltip>
}
disabled={!column.getCanHide()}
label={columnDef.header}
onChange={() => handleToggleColumnHidden(column)}
/>
) : (
<Typography sx={{ alignSelf: 'center' }}>
{columnDef.header}
</Typography>
)}
</Box>
</MenuItem>
{column.columns?.map((c, i) => (
<DataTable_ShowHideColumnsMenuItems
allColumns={allColumns}
column={c}
hoveredColumn={hoveredColumn}
isNestedColumns={isNestedColumns}
key={`${i}-${c.id}`}
setHoveredColumn={setHoveredColumn}
table={table}
/>
))}
</>
);
}
export default DataTable_ShowHideColumnsMenuItems;