drf-react-by-schema 0.13.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api.d.ts CHANGED
@@ -3,7 +3,7 @@ import { Item, SchemaType, modelOptionsType, DataSchemaColumnsType, ItemSchemaCo
3
3
  import { GridFilterModel, GridSortModel } from '@mui/x-data-grid';
4
4
  import { AlertColor } from '@mui/material/Alert';
5
5
  type Id = string | number | null;
6
- interface TargetApiParams {
6
+ export interface TargetApiParams {
7
7
  path: string;
8
8
  serverEndPoint: serverEndPointType | null;
9
9
  data: Item;
@@ -1,11 +1,13 @@
1
1
  /// <reference types="react" />
2
- import { GridSelectionModel } from '@mui/x-data-grid';
3
- import { GridEnrichedBySchemaColDef, OnSelectActions } from '../../utils';
2
+ import { BulkDeleteData, BulkUpdateData, GridEnrichedBySchemaColDef, Id, Item, OnSelectActions } from '../../utils';
4
3
  type CustomToolbarProps = {
5
4
  preparedColumns: GridEnrichedBySchemaColDef[];
6
5
  setPreparedColumns: (p: null | GridEnrichedBySchemaColDef[]) => void;
7
6
  onSelectActions?: OnSelectActions[];
8
- selectionModel: GridSelectionModel;
7
+ selectionModel: Item[];
8
+ bulkUpdateData: BulkUpdateData;
9
+ bulkDeleteData: BulkDeleteData;
10
+ bulkCreateData: (p: Id[]) => void;
9
11
  };
10
12
  /**
11
13
  *
@@ -15,8 +17,11 @@ type CustomToolbarProps = {
15
17
  * setPreparedColumns,
16
18
  * onSelectActions,
17
19
  * selectionModel,
20
+ * bulkUpdateData,
21
+ * bulkDeleteData,
22
+ * bulkCreateData,
18
23
  * }
19
24
  * @returns Custom Toolbar for the grid
20
25
  */
21
- export declare const CustomToolbar: ({ preparedColumns, setPreparedColumns, onSelectActions, selectionModel, }: CustomToolbarProps) => JSX.Element;
26
+ export declare const CustomToolbar: ({ preparedColumns, setPreparedColumns, onSelectActions, selectionModel, bulkUpdateData, bulkDeleteData, bulkCreateData, }: CustomToolbarProps) => JSX.Element;
22
27
  export {};
@@ -43,10 +43,13 @@ const utils_1 = require("./utils");
43
43
  * setPreparedColumns,
44
44
  * onSelectActions,
45
45
  * selectionModel,
46
+ * bulkUpdateData,
47
+ * bulkDeleteData,
48
+ * bulkCreateData,
46
49
  * }
47
50
  * @returns Custom Toolbar for the grid
48
51
  */
49
- const CustomToolbar = ({ preparedColumns, setPreparedColumns, onSelectActions, selectionModel, }) => {
52
+ const CustomToolbar = ({ preparedColumns, setPreparedColumns, onSelectActions, selectionModel, bulkUpdateData, bulkDeleteData, bulkCreateData, }) => {
50
53
  const apiRef = (0, x_data_grid_1.useGridApiContext)();
51
54
  const [resizeMenuAnchorEl, setResizeMenuAnchorEl] = (0, react_1.useState)(null);
52
55
  const isResizeMenuOpen = Boolean(resizeMenuAnchorEl);
@@ -74,7 +77,18 @@ const CustomToolbar = ({ preparedColumns, setPreparedColumns, onSelectActions, s
74
77
  ")"),
75
78
  react_1.default.createElement(Menu_1.default, { anchorEl: actionsMenuAnchorEl, open: isActionsMenuOpen, onClose: closeActionsMenu }, onSelectActions.map((selectAction, index) => (react_1.default.createElement(MenuItem_1.default, { key: `onSelectAction_${index}`, onClick: () => {
76
79
  closeActionsMenu();
77
- selectAction.action(selectionModel);
80
+ if (typeof selectAction.action === 'string') {
81
+ const ids = selectionModel.map((item) => item.id);
82
+ if (selectAction.action === 'bulkDelete') {
83
+ bulkDeleteData(ids);
84
+ return;
85
+ }
86
+ if (selectAction.action === 'bulkCreate') {
87
+ bulkCreateData(ids);
88
+ return;
89
+ }
90
+ }
91
+ selectAction.action(selectionModel, bulkUpdateData);
78
92
  } }, selectAction.title)))))),
79
93
  react_1.default.createElement(x_data_grid_1.GridToolbarColumnsButton, { sx: { ml: '10px', fontSize: '13px' } }),
80
94
  react_1.default.createElement(x_data_grid_1.GridToolbarFilterButton, { sx: { ml: '10px', fontSize: '13px' } }),
@@ -1,17 +1,7 @@
1
1
  /// <reference types="react" />
2
- import { Item } from '../../utils';
3
2
  type FooterToolbarProps = {
4
- name: string;
5
- setRowModesModel: (p: any) => any;
6
- dataGrid: {
7
- data: Item[];
8
- };
9
- setDataGrid: (p: any) => any;
10
- emptyItem: {
11
- current: Record<string, any>;
12
- };
13
- indexField: string;
14
3
  isEditable: boolean;
4
+ handleAddItem: () => void;
15
5
  };
16
- export declare const FooterToolbar: ({ name, setRowModesModel, dataGrid, setDataGrid, emptyItem, indexField, isEditable, }: FooterToolbarProps) => JSX.Element;
6
+ export declare const FooterToolbar: ({ isEditable, handleAddItem }: FooterToolbarProps) => JSX.Element;
17
7
  export {};
@@ -8,28 +8,9 @@ const react_1 = __importDefault(require("react"));
8
8
  const x_data_grid_1 = require("@mui/x-data-grid");
9
9
  const Button_1 = __importDefault(require("@mui/material/Button"));
10
10
  const Add_1 = __importDefault(require("@mui/icons-material/Add"));
11
- const utils_1 = require("../../utils");
12
- const FooterToolbar = ({ name, setRowModesModel, dataGrid, setDataGrid, emptyItem, indexField, isEditable, }) => {
13
- const handleClick = () => {
14
- const id = (0, utils_1.getTmpId)();
15
- emptyItem.current.id = id;
16
- const newData = [Object.assign({}, emptyItem.current), ...dataGrid.data];
17
- setDataGrid({
18
- data: newData,
19
- });
20
- setRowModesModel((oldModel) => (Object.assign(Object.assign({}, oldModel), { [id]: { mode: x_data_grid_1.GridRowModes.Edit, fieldToFocus: indexField } })));
21
- // Ugly hack to scroll to top, since scroll to cell is only available in Pro
22
- const el = document.querySelector(`.dataGrid_${name} .MuiDataGrid-virtualScroller`);
23
- // console.log(el, name);
24
- if (el) {
25
- el.scrollTop = 0;
26
- setTimeout(() => {
27
- el.scrollTop = 0;
28
- }, 10);
29
- }
30
- };
11
+ const FooterToolbar = ({ isEditable, handleAddItem }) => {
31
12
  return (react_1.default.createElement(x_data_grid_1.GridFooterContainer, null,
32
- isEditable && (react_1.default.createElement(Button_1.default, { color: "primary", startIcon: react_1.default.createElement(Add_1.default, null), onClick: handleClick, sx: { ml: 2 } }, "Adicionar")),
13
+ isEditable && (react_1.default.createElement(Button_1.default, { color: "primary", startIcon: react_1.default.createElement(Add_1.default, null), onClick: handleAddItem, sx: { ml: 2 } }, "Adicionar")),
33
14
  react_1.default.createElement(x_data_grid_1.GridFooter, { sx: isEditable ? { border: 'none' } : { width: '100%' } })));
34
15
  };
35
16
  exports.FooterToolbar = FooterToolbar;
@@ -92,6 +92,7 @@ const DataGridBySchemaEditable = (0, react_1.forwardRef)((_a, ref) => {
92
92
  const [rowModesModel, setRowModesModel] = (0, react_1.useState)({});
93
93
  const [dialogOpen, setDialogOpen] = (0, react_1.useState)(false);
94
94
  const [selectionModel, setSelectionModel] = (0, react_1.useState)([]);
95
+ const [selectionModelIds, setSelectionModelIds] = (0, react_1.useState)([]);
95
96
  const optionsAC = (0, react_1.useRef)(null);
96
97
  const emptyItem = (0, react_1.useRef)({});
97
98
  const yupValidationSchema = (0, react_1.useRef)(null);
@@ -388,6 +389,99 @@ const DataGridBySchemaEditable = (0, react_1.forwardRef)((_a, ref) => {
388
389
  });
389
390
  setPreparedColumns(cols);
390
391
  };
392
+ const handleAddItems = (numberOfRows = 1) => {
393
+ const newRows = [];
394
+ for (let i = 0; i < numberOfRows; i++) {
395
+ const id = (0, utils_1.getTmpId)();
396
+ newRows.push(Object.assign(Object.assign({}, emptyItem.current), { id }));
397
+ }
398
+ const newData = [...newRows, ...dataGrid.data];
399
+ setDataGrid({
400
+ data: newData,
401
+ });
402
+ setRowModesModel((oldModel) => {
403
+ const newModel = Object.assign({}, oldModel);
404
+ newRows.map((newRow) => {
405
+ newModel[newRow.id] = { mode: x_data_grid_1.GridRowModes.Edit, fieldToFocus: indexField };
406
+ });
407
+ return newModel;
408
+ });
409
+ // Ugly hack to scroll to top, since scroll to cell is only available in Pro
410
+ const el = document.querySelector(`.dataGrid_${name} .MuiDataGrid-virtualScroller`);
411
+ // console.log(el, name);
412
+ if (el) {
413
+ el.scrollTop = 0;
414
+ setTimeout(() => {
415
+ el.scrollTop = 0;
416
+ }, 10);
417
+ }
418
+ };
419
+ const bulkUpdateData = (newData) => __awaiter(void 0, void 0, void 0, function* () {
420
+ const promises = [];
421
+ const ids = [];
422
+ newData.map((item) => {
423
+ promises.push((0, api_1.updateDataBySchema)({
424
+ model,
425
+ modelObjectId: item.id,
426
+ serverEndPoint,
427
+ data: item,
428
+ schema,
429
+ }));
430
+ ids.push(item.id);
431
+ });
432
+ const results = yield Promise.all(promises);
433
+ setSelectionModel([]);
434
+ setSelectionModelIds([]);
435
+ setDataGrid({
436
+ data: newData,
437
+ });
438
+ setSnackBar({
439
+ open: true,
440
+ severity: 'success',
441
+ msg: 'Alterações salvas com sucesso',
442
+ });
443
+ return results.map((result, index) => {
444
+ return {
445
+ id: ids[index],
446
+ success: typeof result !== 'object' && !isNaN(parseInt(result)),
447
+ };
448
+ });
449
+ });
450
+ const bulkDeleteData = (ids) => __awaiter(void 0, void 0, void 0, function* () {
451
+ const promises = [];
452
+ ids.map((id) => {
453
+ promises.push((0, api_1.deleteData)(model, serverEndPoint, id));
454
+ });
455
+ setDataGridLoading(true);
456
+ const results = yield Promise.all(promises);
457
+ setSelectionModel([]);
458
+ setSelectionModelIds([]);
459
+ setDataGrid({
460
+ data: data.filter((item) => !ids.includes(item.id)),
461
+ });
462
+ setDataGridLoading(false);
463
+ setSnackBar({
464
+ open: true,
465
+ severity: 'success',
466
+ msg: 'Itens apagados com sucesso',
467
+ });
468
+ return results.map((result, index) => {
469
+ return {
470
+ id: ids[index],
471
+ success: result,
472
+ };
473
+ });
474
+ });
475
+ const bulkCreateData = (ids) => __awaiter(void 0, void 0, void 0, function* () {
476
+ handleAddItems(ids.length);
477
+ setSelectionModel([]);
478
+ setSelectionModelIds([]);
479
+ setSnackBar({
480
+ open: true,
481
+ severity: 'success',
482
+ msg: 'Linhas adicionadas com sucesso',
483
+ });
484
+ });
391
485
  const handleDialogClose = () => {
392
486
  setDialogOpen(false);
393
487
  };
@@ -617,8 +711,10 @@ const DataGridBySchemaEditable = (0, react_1.forwardRef)((_a, ref) => {
617
711
  (preparedColumns.find((col) => col.field === indexField) &&
618
712
  Object.prototype.hasOwnProperty.call(preparedColumns.find((col) => col.field === indexField), 'valueFormatter'))))));
619
713
  }, checkboxSelection: checkboxSelection, onSelectionModelChange: (newSelectionModel) => {
620
- setSelectionModel(newSelectionModel);
621
- }, disableRowSelectionOnClick: disableRowSelectionOnClick, rowModesModel: rowModesModel, onRowEditStart: handleRowEditStart, onRowEditStop: handleRowEditStop, processRowUpdate: processRowUpdate, onProcessRowUpdateError: (e) => {
714
+ const selectedData = dataGrid.data.filter((item) => newSelectionModel.includes(item.id));
715
+ setSelectionModel(selectedData);
716
+ setSelectionModelIds(newSelectionModel);
717
+ }, selectionModel: selectionModelIds, disableRowSelectionOnClick: disableRowSelectionOnClick, rowModesModel: rowModesModel, onRowEditStart: handleRowEditStart, onRowEditStop: handleRowEditStop, processRowUpdate: processRowUpdate, onProcessRowUpdateError: (e) => {
622
718
  setDataGridLoading(false);
623
719
  if (processingRow.current) {
624
720
  setRowModesModel(Object.assign(Object.assign({}, rowModesModel), { [processingRow.current]: {
@@ -647,15 +743,13 @@ const DataGridBySchemaEditable = (0, react_1.forwardRef)((_a, ref) => {
647
743
  },
648
744
  selectionModel,
649
745
  onSelectActions,
746
+ bulkUpdateData,
747
+ bulkDeleteData,
748
+ bulkCreateData,
650
749
  },
651
750
  footer: {
652
- name,
653
- setRowModesModel,
654
- dataGrid,
655
- setDataGrid,
656
- emptyItem,
657
- indexField,
658
751
  isEditable,
752
+ handleAddItem: handleAddItems,
659
753
  },
660
754
  filterPanel: {
661
755
  sx: {
@@ -403,6 +403,9 @@ function APIWrapper({ handleLoading, setSnackBar, setDialog, children }) {
403
403
  return yield (0, api_1.getSignUpOptions)(serverEndPoint);
404
404
  });
405
405
  }
406
+ function localUpdateModel(params) {
407
+ return (0, api_1.updateData)(Object.assign(Object.assign({}, params), { serverEndPoint }));
408
+ }
406
409
  return (react_1.default.createElement(APIWrapperContext_1.APIWrapperContext.Provider, { value: {
407
410
  usuaria,
408
411
  updateUsuaria,
@@ -430,6 +433,7 @@ function APIWrapper({ handleLoading, setSnackBar, setDialog, children }) {
430
433
  // Remove after integrating new "onEditModel" to package:
431
434
  serverEndPoint,
432
435
  editModel,
436
+ updateModel: localUpdateModel,
433
437
  populateOptionsAC,
434
438
  } }, children));
435
439
  }
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { FieldValues, SubmitHandler, UseFormGetValues, UseFormSetValue } from 'react-hook-form';
3
3
  import { AxiosResponse } from 'axios';
4
4
  import { ItemSchemaColumnsType, Id, Item, SchemaType, DataSchemaColumnsType } from '../utils';
5
- import { GetGenericModelListProps } from '../api';
5
+ import { GetGenericModelListProps, TargetApiParams } from '../api';
6
6
  import { serverEndPointType } from './DRFReactBySchemaContext';
7
7
  export interface LoadSinglePageDataProps {
8
8
  model: string;
@@ -92,6 +92,7 @@ export interface APIWrapperContextType {
92
92
  } | undefined>;
93
93
  serverEndPoint: serverEndPointType;
94
94
  editModel: React.MutableRefObject<Item>;
95
+ updateModel: (p: Omit<TargetApiParams, 'serverEndPoint'>) => Promise<boolean>;
95
96
  populateOptionsAC: (optionsACModels: string[]) => void;
96
97
  }
97
98
  export declare const APIWrapperContext: React.Context<APIWrapperContextType>;
@@ -41,6 +41,7 @@ exports.APIWrapperContext = react_1.default.createContext({
41
41
  // Remove after integrating new "onEditModel" to package:
42
42
  serverEndPoint: { url: '', apiTokenUrl: '' },
43
43
  editModel: { current: {} },
44
+ updateModel: () => __awaiter(void 0, void 0, void 0, function* () { return false; }),
44
45
  populateOptionsAC: () => undefined,
45
46
  });
46
47
  const useAPIWrapper = () => {
package/dist/utils.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import { CalendarPickerView } from '@mui/x-date-pickers/CalendarPicker';
3
- import { GridActionsColDef, GridColDef, GridFilterModel, GridSortModel, GridSelectionModel } from '@mui/x-data-grid';
3
+ import { GridActionsColDef, GridColDef, GridFilterModel, GridSortModel } from '@mui/x-data-grid';
4
4
  import { Control, FieldValues, UseFormGetValues, UseFormSetValue } from 'react-hook-form';
5
5
  import { AutocompleteRenderOptionState, SxProps } from '@mui/material';
6
6
  import { OnEditModelType } from './context/APIWrapperContext';
@@ -157,8 +157,18 @@ export declare const slugToCamelCase: (str: string) => string;
157
157
  export declare const slugify: (text: string) => string;
158
158
  export declare function mergeFilterItems(defaultFilter: GridFilterModel | undefined, filter: GridFilterModel | undefined): any;
159
159
  export type ActionType = 'editInline' | 'remove' | 'edit' | 'view';
160
+ export type BulkUpdateData = (newData: Item[]) => Promise<{
161
+ id: Id;
162
+ success: boolean;
163
+ }[]>;
164
+ export type BulkDeleteData = (ids: Id[]) => Promise<{
165
+ id: Id;
166
+ success: boolean;
167
+ }[]>;
168
+ export type OnSelectActionCustom = (selectedData: Item[], bulkUpdateData: BulkUpdateData) => void;
169
+ export type OnSelectActionTypes = OnSelectActionCustom | 'bulkDelete' | 'bulkCreate';
160
170
  export type OnSelectActions = {
161
171
  title: string;
162
- action: (p: GridSelectionModel) => void;
172
+ action: OnSelectActionTypes;
163
173
  };
164
174
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drf-react-by-schema",
3
- "version": "0.13.1",
3
+ "version": "0.14.0",
4
4
  "description": "Components and Tools for building a React App having Django Rest Framework (DRF) as server",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",