Files
universal_is/client/src/components/TableEditable.tsx
cracklesparkle b88d83cd74 Fix build errors
2024-09-26 12:09:38 +09:00

233 lines
7.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useEffect, useState } from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import AddIcon from '@mui/icons-material/Add';
import EditIcon from '@mui/icons-material/Edit';
import DeleteIcon from '@mui/icons-material/DeleteOutlined';
import SaveIcon from '@mui/icons-material/Save';
import CancelIcon from '@mui/icons-material/Close';
import {
GridRowsProp,
GridRowModesModel,
GridRowModes,
DataGrid,
GridColDef,
GridToolbarContainer,
GridActionsCellItem,
GridEventListener,
GridRowId,
GridRowModel,
GridRowEditStopReasons,
GridSlots,
} from '@mui/x-data-grid';
interface EditToolbarProps {
setRows: (newRows: (oldRows: GridRowsProp) => GridRowsProp) => void
setRowModesModel: (
newModel: (oldModel: GridRowModesModel) => GridRowModesModel,
) => void
columns: GridColDef[]
autoComplete?: React.ReactElement | null
}
function EditToolbar(props: EditToolbarProps) {
const { setRows, setRowModesModel, columns, autoComplete } = props
const handleClick = () => {
const id = Date.now().toString(36)
const newValues: any = {}
columns.forEach(column => {
if (column.type === 'number') {
newValues[column.field] = 0
} else if (column.type === 'string') {
newValues[column.field] = ''
} else if (column.type === 'boolean') {
newValues[column.field] = false
} else {
newValues[column.field] = undefined
}
if (column.field === 'region_id') {
// column.valueGetter = (value: any) => {
// console.log(value)
// }
}
})
setRows((oldRows) => [...oldRows, { id, ...newValues, isNew: true }]);
setRowModesModel((oldModel) => ({
...oldModel,
[id]: { mode: GridRowModes.Edit, fieldToFocus: columns[0].field },
}))
};
return (
<GridToolbarContainer sx={{ px: '16px', py: '16px' }}>
{autoComplete &&
<Box sx={{ flexGrow: '1' }}>
{autoComplete}
</Box>
}
<Button color="primary" startIcon={<AddIcon />} onClick={handleClick}>
Добавить
</Button>
</GridToolbarContainer>
);
}
interface DataGridProps {
initialRows: GridRowsProp;
columns: GridColDef[];
actions: boolean;
onRowClick: GridEventListener<"rowClick">;
onSave: any;
onDelete: any;
autoComplete?: React.ReactElement | null;
loading: boolean;
}
export default function FullFeaturedCrudGrid({
initialRows,
columns,
actions = false,
//onRowClick,
onSave,
onDelete,
autoComplete,
loading
}: DataGridProps) {
const [rows, setRows] = useState(initialRows);
const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({});
const handleRowEditStop: GridEventListener<'rowEditStop'> = (params, event) => {
if (params.reason === GridRowEditStopReasons.rowFocusOut) {
event.defaultMuiPrevented = true;
}
};
const handleEditClick = (id: GridRowId) => () => {
setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.Edit } });
};
const handleSaveClick = (id: GridRowId) => () => {
setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } });
onSave?.(id)
};
const handleDeleteClick = (id: GridRowId) => () => {
setRows(rows.filter((row) => row.id !== id));
onDelete?.(id)
};
const handleCancelClick = (id: GridRowId) => () => {
setRowModesModel({
...rowModesModel,
[id]: { mode: GridRowModes.View, ignoreModifications: true },
});
const editedRow = rows.find((row) => row.id === id);
if (editedRow!.isNew) {
setRows(rows.filter((row) => row.id !== id));
}
};
const processRowUpdate = (newRow: GridRowModel) => {
const updatedRow = { ...newRow, isNew: false };
setRows(rows.map((row) => (row.id === newRow.id ? updatedRow : row)));
return updatedRow;
};
const handleRowModesModelChange = (newRowModesModel: GridRowModesModel) => {
setRowModesModel(newRowModesModel);
};
useEffect(() => {
if (initialRows) {
setRows(initialRows)
}
}, [initialRows])
const actionColumns: GridColDef[] = [
{
field: 'actions',
type: 'actions',
headerName: 'Действия',
width: 100,
cellClassName: 'actions',
getActions: ({ id }) => {
const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit;
if (isInEditMode) {
return [
<GridActionsCellItem
icon={<SaveIcon />}
label="Save"
sx={{
color: 'primary.main',
}}
onClick={handleSaveClick(id)}
/>,
<GridActionsCellItem
icon={<CancelIcon />}
label="Cancel"
className="textPrimary"
onClick={handleCancelClick(id)}
color="inherit"
/>,
];
}
return [
<GridActionsCellItem
icon={<EditIcon />}
label="Edit"
className="textPrimary"
onClick={handleEditClick(id)}
color="inherit"
/>,
<GridActionsCellItem
icon={<DeleteIcon />}
label="Delete"
onClick={handleDeleteClick(id)}
color="inherit"
/>,
];
},
}
]
return (
<Box
sx={{
height: 500,
width: '100%',
'& .actions': {
color: 'text.secondary',
},
'& .textPrimary': {
color: 'text.primary',
},
}}
>
<DataGrid
loading={loading}
rows={rows || []}
columns={actions ? [...columns, ...actionColumns] : columns}
editMode="row"
rowModesModel={rowModesModel}
//onRowClick={onRowClick}
onRowModesModelChange={handleRowModesModelChange}
onRowEditStop={handleRowEditStop}
processRowUpdate={processRowUpdate}
slots={{
toolbar: EditToolbar as GridSlots['toolbar'],
}}
slotProps={{
toolbar: { setRows, setRowModesModel, columns, autoComplete },
}}
/>
</Box>
);
}