UNPKG

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
"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;