drf-react-by-schema
Version:
Components and Tools for building a React App having Django Rest Framework (DRF) as server
333 lines (332 loc) • 17.7 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = __importStar(require("react"));
const x_data_grid_1 = require("@mui/x-data-grid");
const Check_1 = __importDefault(require("@mui/icons-material/Check"));
const Close_1 = __importDefault(require("@mui/icons-material/Close"));
const Edit_1 = __importDefault(require("@mui/icons-material/Edit"));
const Delete_1 = __importDefault(require("@mui/icons-material/Delete"));
const Box_1 = __importDefault(require("@mui/material/Box"));
const CircularProgress_1 = __importDefault(require("@mui/material/CircularProgress"));
const styles_1 = require("../../styles");
const APIWrapperContext_1 = require("../../context/APIWrapperContext");
const utils_1 = require("../../utils");
const CustomToolbar_1 = require("./CustomToolbar");
const FooterToolbar_1 = require("./FooterToolbar");
const useOptionsAC_1 = require("./hooks/useOptionsAC");
const usePreparedColumns_1 = require("./hooks/usePreparedColumns");
const useDataGridActions_1 = require("./hooks/useDataGridActions");
const useProcessRowUpdate_1 = require("./hooks/useProcessRowUpdate");
function DataGridDesktop({ schema, dataGrid, setDataGrid, rowCount = 0, columns, columnVisibilityModel, model, name = Math.floor(Math.random() * 1000000).toString(), indexField = 'nome', addExistingModel, indexFieldMinWidth = 350, indexFieldBasePath = '', indexFieldViewBasePath, stateToLink = {}, minWidth = 80, loading, modelParent, modelParentId, customColumnOperations, customFieldFormLayouts, customLinkDestination, LinkComponent, onProcessRow, onDataChange, onEditModel, isEditable = false, hasBulkSelect, onSelectActions, sx: sxProp, isAutoHeight, defaultValues, hideFooterPagination, setVisibleRows, paginationModel, setPaginationModel, hideFooterComponent, hideToolbarComponent, tableAutoHeight, actions = ['editInline', 'remove'], customActions, hideColumnsButton, hideFilterButton, hideDensityButton, hideExportButton, hideQuickFilterBar, optionsAC: optionsACExternal, extraValidators, emptyItem, handleDeleteClick, setSnackBar, yupValidationSchema, }) {
const [dataGridLoading, setDataGridLoading] = (0, react_1.useState)(false);
const [isRowEditing, setIsRowEditing] = (0, react_1.useState)();
const [validationErrors, setValidationErrors] = (0, react_1.useState)({});
const [selectionModel, setSelectionModel] = (0, react_1.useState)([]);
const [selectionModelIds, setSelectionModelIds] = (0, react_1.useState)([]);
const processingRow = (0, react_1.useRef)(null);
const apiRef = (0, x_data_grid_1.useGridApiRef)();
const handleStopEditing = () => {
setIsRowEditing(undefined);
};
const handleStartEditing = (id) => {
setIsRowEditing(id);
};
const { setDialog, onEditModel: APIOnEditModel } = (0, APIWrapperContext_1.useAPIWrapper)();
if (!onEditModel) {
onEditModel = APIOnEditModel;
}
const handleSaveRow = (0, react_1.useCallback)((id) => {
if (id) {
apiRef.current.stopRowEditMode({ id });
}
}, [apiRef]);
const handleCancelRow = (0, react_1.useCallback)((id) => {
if (id) {
apiRef.current.stopRowEditMode({ id, ignoreModifications: true });
handleStopEditing();
if ((0, utils_1.isTmpId)(id)) {
const newData = dataGrid.data.filter(({ id: rowId }) => id !== rowId);
setDataGrid({ data: newData });
}
}
}, [apiRef, dataGrid.data]);
const { optionsAC, updateOptionsAC } = (0, useOptionsAC_1.useOptionsAC)({
columns,
schema,
optionsACExternal,
});
const { handleAddItem, bulkUpdateData, bulkDeleteData, bulkCreateData } = (0, useDataGridActions_1.useDataGridActions)({
apiRef,
dataGrid,
setDataGrid,
setSnackBar,
emptyItem,
defaultValues,
model,
schema,
setSelectionModel,
setSelectionModelIds,
setDataGridLoading,
indexField,
handleStartEditing,
isRowEditing,
});
const { preparedColumns, setPreparedColumns } = (0, usePreparedColumns_1.usePreparedColumns)({
schema,
columns,
isEditable,
actions,
customActions,
LinkComponent,
indexFieldBasePath,
indexFieldViewBasePath,
stateToLink,
validationErrors,
optionsAC,
onEditModel,
customFieldFormLayouts,
setDialog,
indexField,
addExistingModel,
indexFieldMinWidth,
minWidth,
customColumnOperations,
customLinkDestination,
});
const { processRowUpdate } = (0, useProcessRowUpdate_1.useProcessRowUpdate)({
preparedColumns,
indexField,
schema,
model,
yupValidationSchema,
extraValidators,
onEditModel,
onProcessRow,
onDataChange,
updateOptionsAC,
dataGrid,
setDataGrid,
setDataGridLoading,
setValidationErrors,
processingRow,
modelParent,
modelParentId,
addExistingModel,
handleStopEditing,
});
const InternalToolbar = (0, react_1.useCallback)((_props) => (react_1.default.createElement(CustomToolbar_1.CustomToolbar, { preparedColumns: preparedColumns || [], setPreparedColumns: setPreparedColumns, selectionModel: selectionModel, onSelectActions: onSelectActions, bulkUpdateData: bulkUpdateData, bulkDeleteData: bulkDeleteData, bulkCreateData: bulkCreateData, hideColumnsButton: hideColumnsButton, hideFilterButton: hideFilterButton, hideDensityButton: hideDensityButton, hideExportButton: hideExportButton, hideQuickFilterBar: hideQuickFilterBar })), [
preparedColumns,
selectionModel,
onSelectActions,
bulkUpdateData,
bulkDeleteData,
bulkCreateData,
hideColumnsButton,
hideFilterButton,
hideDensityButton,
hideExportButton,
hideQuickFilterBar,
]);
const actionColumn = (0, react_1.useMemo)(() => ({
field: 'actions',
type: 'actions',
headerName: '',
width: 100,
getActions: (params) => {
const { id } = params;
if (isRowEditing === id) {
return [
react_1.default.createElement(x_data_grid_1.GridActionsCellItem, { key: "save", icon: react_1.default.createElement(Check_1.default, null), label: "Salvar", onClick: () => handleSaveRow(id), color: "success" }),
react_1.default.createElement(x_data_grid_1.GridActionsCellItem, { key: "cancel", icon: react_1.default.createElement(Close_1.default, null), label: "Cancelar", onClick: () => {
handleCancelRow(id);
}, color: "inherit" }),
];
}
return [
react_1.default.createElement(x_data_grid_1.GridActionsCellItem, { key: "edit", icon: react_1.default.createElement(Edit_1.default, null), label: "Editar", onClick: () => {
const visibleColumns = apiRef.current.getAllColumns();
const firstEditableCol = visibleColumns.find((col) => col.editable && col.field !== 'actions');
const fieldToFocus = firstEditableCol === null || firstEditableCol === void 0 ? void 0 : firstEditableCol.field;
apiRef.current.startRowEditMode({ id, fieldToFocus });
handleStartEditing(id);
}, color: "inherit" }),
react_1.default.createElement(x_data_grid_1.GridActionsCellItem, { key: "delete", icon: react_1.default.createElement(Delete_1.default, null), label: "Apagar", onClick: () => {
if ((0, utils_1.isTmpId)(id)) {
const newData = dataGrid.data.filter(({ id: rowId }) => id !== rowId);
setDataGrid({ data: newData });
return;
}
handleDeleteClick(id);
}, color: "error" }),
];
},
}), [apiRef, handleDeleteClick, isRowEditing, dataGrid.data]);
const InternalFooter = (0, react_1.useCallback)(() => (react_1.default.createElement(FooterToolbar_1.FooterToolbar, { isEditable: isEditable, handleAddItem: handleAddItem, isRowEditing: isRowEditing, handleSaveRow: handleSaveRow, handleCancelRow: handleCancelRow })), [isEditable, handleAddItem, isRowEditing, handleSaveRow, handleCancelRow]);
const checkboxSelection = hasBulkSelect ? true : undefined;
const disableRowSelectionOnClick = hasBulkSelect ? true : undefined;
const sx = Object.assign(Object.assign({}, sxProp), (isAutoHeight || tableAutoHeight
? {
'&.MuiDataGrid-root--densityCompact .MuiDataGrid-cell': { py: '8px' },
'&.MuiDataGrid-root--densityStandard .MuiDataGrid-cell': { py: '15px' },
'&.MuiDataGrid-root--densityComfortable .MuiDataGrid-cell': { py: '22px' },
}
: {}));
return (react_1.default.createElement(Box_1.default, { className: `dataGrid_${name}`, sx: Object.assign({ height: '100%', width: '100%', maxWidth: '100%', display: 'grid' }, sxProp) }, preparedColumns === null ? (react_1.default.createElement(Box_1.default, { sx: styles_1.Layout.loadingBox },
react_1.default.createElement(CircularProgress_1.default, null))) : (react_1.default.createElement(x_data_grid_1.DataGrid, { apiRef: apiRef, rows: dataGrid.data, columns: isEditable ? [actionColumn, ...(preparedColumns || [])] : preparedColumns || [], getCellClassName: ({ id, cellMode, field }) => {
if (cellMode !== 'edit') {
return '';
}
const rowError = validationErrors[id];
return rowError && rowError[field] ? 'cell--error' : '';
}, editMode: "row", loading: dataGridLoading || loading, hideFooterPagination: hideFooterPagination, getRowHeight: ({ id }) => {
if (isRowEditing === id || isAutoHeight || tableAutoHeight) {
return 'auto';
}
return null;
}, isCellEditable: ({ row, field }) => {
// const isRowEditing = apiRef.current.getRowMode(row.id) === 'edit';
const isPermanentRow = !(0, utils_1.isTmpId)(row.id);
const isIndexField = field === indexField;
const indexColumn = preparedColumns === null || preparedColumns === void 0 ? void 0 : preparedColumns.find((col) => col.field === indexField);
const hasValueFormatter = (indexColumn === null || indexColumn === void 0 ? void 0 : indexColumn.valueFormatter) !== undefined;
const isIndexFieldEditable = !(indexField in optionsAC) || hasValueFormatter;
return (
// isRowEditing &&
isPermanentRow || ((0, utils_1.isTmpId)(row.id) && (isIndexField || isIndexFieldEditable)));
}, checkboxSelection: checkboxSelection, onRowSelectionModelChange: (newSelectionModel) => {
const selectedData = dataGrid.data.filter((item) => newSelectionModel.includes(item.id));
setSelectionModel(selectedData);
setSelectionModelIds([...newSelectionModel]);
}, rowSelectionModel: selectionModelIds, disableRowSelectionOnClick: disableRowSelectionOnClick, onRowEditStart: (params) => {
console.log({ onRowEditStart: params.reason, id: params.id, isRowEditing });
if (isRowEditing) {
handleSaveRow(isRowEditing);
}
handleStartEditing(params.id);
}, onRowEditStop: (params, event) => {
console.log({ onRowEditStop: params.reason });
if (params.reason === 'rowFocusOut') {
const isInsideGrid = !('target' in event);
if (!isInsideGrid) {
event.defaultMuiPrevented = true;
}
return;
}
const fieldSchema = params.field ? schema[params.field] : undefined;
if (params.reason === 'enterKeyDown' &&
['date', 'datetime', 'nested object', 'field', 'choice', 'list'].includes((fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema.type) || '')) {
event.defaultMuiPrevented = true;
return;
}
// Escape key prevents saving:
if (params.reason === 'escapeKeyDown') {
handleCancelRow(params.id);
}
}, processRowUpdate: processRowUpdate, onProcessRowUpdateError: (e) => {
setDataGridLoading(false);
if (e.message === 'CANCEL_TMP_ROW') {
return;
}
// if (processingRow.current) {
// apiRef.current.startRowEditMode({ id: processingRow.current });
// }
let msg = 'Ocorreu um erro desconhecido ao salvar.';
if (e.message === 'Validation Error') {
msg = 'Não foi possível salvar os dados. Confira os erros nos campos.';
}
else if (e.message) {
msg = e.message;
}
setSnackBar({
open: true,
severity: 'error',
msg,
});
console.log(e);
}, slots: {
toolbar: hideToolbarComponent ? () => react_1.default.createElement(react_1.default.Fragment, null) : InternalToolbar,
footer: hideFooterComponent ? () => react_1.default.createElement(react_1.default.Fragment, null) : InternalFooter,
}, slotProps: {
toolbar: {
showQuickFilter: true,
quickFilterProps: { debounceMs: 500 },
},
filterPanel: {
sx: {
'& .MuiDataGrid-filterFormValueInput': {
width: 300,
},
},
},
},
// sx={sx}
sx: Object.assign(Object.assign({}, sx), { width: '100%', minWidth: 0 }), paginationMode: paginationModel ? 'server' : 'client', paginationModel: paginationModel
? { page: paginationModel.page, pageSize: paginationModel.pageSize }
: undefined, onPaginationModelChange: (newModel) => {
if (setPaginationModel && paginationModel) {
setPaginationModel(Object.assign(Object.assign({}, paginationModel), { page: newModel.page, pageSize: newModel.pageSize }));
}
}, initialState: {
columns: { columnVisibilityModel },
pagination: !paginationModel ? { paginationModel: { pageSize: 100 } } : undefined,
}, rowCount: paginationModel && typeof rowCount !== 'undefined' ? rowCount : undefined, pageSizeOptions: paginationModel ? [paginationModel.pageSize] : [5, 10, 25, 50, 100], filterMode: paginationModel ? 'server' : 'client', onFilterModelChange: (newFilter) => {
if (setPaginationModel && paginationModel) {
setPaginationModel(Object.assign(Object.assign({}, paginationModel), { filter: newFilter }));
}
}, sortingMode: paginationModel ? 'server' : 'client', onSortModelChange: (newSorting) => {
if (setPaginationModel && paginationModel) {
setPaginationModel(Object.assign(Object.assign({}, paginationModel), { sort: newSorting }));
}
}, onStateChange: (state) => {
if (setVisibleRows) {
const visibleRows = (0, x_data_grid_1.gridFilteredSortedRowIdsSelector)(state, apiRef.current.instanceId);
setVisibleRows(visibleRows);
}
} }))));
}
// const shouldMemoUpdate = (prevProps: DataGridDesktopProps, nextProps: DataGridDesktopProps) => {
// return (
// prevProps.dataGrid === nextProps.dataGrid &&
// prevProps.loading === nextProps.loading &&
// prevProps.schema === nextProps.schema &&
// prevProps.columns === nextProps.columns
// );
// };
// export default React.memo(DataGridDesktop, shouldMemoUpdate);
exports.default = DataGridDesktop;