drf-react-by-schema 0.2.1 → 0.3.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.
@@ -0,0 +1,84 @@
1
+ import React from 'react';
2
+ import { ItemSchemaColumnsType, Id, Item, SchemaType } from '../utils';
3
+
4
+ export interface LoadSinglePageDataProps {
5
+ model: string;
6
+ objId: Id;
7
+ objTitleField?: string;
8
+ optionsACModels: string[];
9
+ basePath?: string;
10
+ formPath?: string | null;
11
+ extraValidators: Item;
12
+ };
13
+
14
+ // export interface LoadingStateType {
15
+ // loading: boolean,
16
+ // setLoading: React.Dispatch<React.SetStateAction<boolean>>;
17
+ // };
18
+
19
+ export type OptionsACType = Record<string, Item[]>;
20
+
21
+ export interface PageFormType {
22
+ id: Id;
23
+ schema: SchemaType | null;
24
+ initialValues: Item | null;
25
+ validationSchema: Item | null;
26
+ };
27
+
28
+ export interface OnEditModelType {
29
+ fieldKey: string;
30
+ index: string;
31
+ model: string;
32
+ id: Id;
33
+ labelKey: string;
34
+ setValue: (p: any) => void;
35
+ getValues: (p: any) => any;
36
+ };
37
+
38
+ export interface OnEditRelatedModelType {
39
+ model: string;
40
+ id: Id;
41
+ relatedModel: string;
42
+ relatedModelId: Id;
43
+ newRow: Item;
44
+ schema: SchemaType;
45
+ onlyAddExisting: boolean;
46
+ };
47
+
48
+ export interface OnDeleteRelatedModelType {
49
+ model: string;
50
+ id: Id;
51
+ relatedModel: string;
52
+ relatedModelId: Id;
53
+ };
54
+
55
+ export interface SnackBarType {
56
+ open?: boolean;
57
+ msg?: string;
58
+ severity?: string
59
+ };
60
+
61
+ export interface DialogType {
62
+ open: boolean;
63
+ loading?: boolean;
64
+ title?: string;
65
+ Body?: React.ReactNode;
66
+ Actions?: React.ReactNode;
67
+ }
68
+
69
+ export interface APIWrapperContextType {
70
+ usuaria: Item | null;
71
+ onSubmit: (model: string, id: Id, data: Item, e: React.SyntheticEvent<HTMLButtonElement, SubmitEvent>) => Promise<false | Id>;
72
+ loadSinglePageData: (p: LoadSinglePageDataProps) => boolean | Item;
73
+ handleLoading: (p: boolean) => void;
74
+ optionsACState: [{ [x: string]: any; }, React.Dispatch<OptionsACType>];
75
+ pageFormState: [{ [x: string]: any; }, React.Dispatch<PageFormType>];
76
+ onEditModel: (p: OnEditModelType) => void;
77
+ onDeleteModel: (model:string, id:Id, onSuccess:()=>void | null) => void;
78
+ onEditRelatedModelSave: (p: OnEditRelatedModelType) => Promise<boolean | Id | ItemSchemaColumnsType>;
79
+ onDeleteRelatedModel: (p: OnDeleteRelatedModelType) => Promise<boolean>;
80
+ onTriggerSnackBar: (p: SnackBarType) => void;
81
+ setDialog: React.Dispatch<React.SetStateAction<DialogType>>;
82
+ };
83
+
84
+ export const APIWrapperContext = React.createContext<APIWrapperContextType | null>(null);
@@ -0,0 +1,33 @@
1
+ import React from 'react';
2
+ import { Theme } from '@mui/material/styles';
3
+
4
+ import defaultTheme from '../styles/theme';
5
+
6
+ export interface serverEndPointType {
7
+ url: string;
8
+ autocomplete?: string;
9
+ api?: string;
10
+ JSONSchema?: string;
11
+ apiTokenUrl: string;
12
+ getToken?: string;
13
+ refreshToken?: string,
14
+ verifyToken?: string
15
+ }
16
+ export interface DRFReactBySchemaContextType {
17
+ serverEndPoint: serverEndPointType | null;
18
+ theme: Theme;
19
+ isInBatches?: boolean;
20
+ firstBatchLength?: number;
21
+ }
22
+
23
+ export const DRFReactBySchemaContext = React.createContext<DRFReactBySchemaContextType>({
24
+ serverEndPoint: null,
25
+ theme: defaultTheme,
26
+ isInBatches: true,
27
+ firstBatchLength: 100
28
+ });
29
+
30
+ export const useTheme = () => {
31
+ const context = React.useContext(DRFReactBySchemaContext);
32
+ return context.theme;
33
+ }
@@ -1,7 +1,9 @@
1
- DRFReactBySchemaProvider example:
2
-
3
1
  ```js
2
+ /*
3
+ import Box from '@mui/material/Box';
4
4
  import DataGridBySchemaEditable from '../components/DataGridBySchemaEditable';
5
+ import { APIWrapperContext } from '../context/APIWrapperContext';
6
+
5
7
  const data = {
6
8
  data: [],
7
9
  columns: [],
@@ -25,26 +27,31 @@ const Link = null;
25
27
  apiTokenUrl: 'https://icv.eita.org.br/api-auth/token'
26
28
  }}
27
29
  >
28
- <DataGridBySchemaEditable
29
- data={data.data}
30
- columns={data.columns}
31
- schema={data.schema}
32
- model={model}
33
- indexField={indexField}
34
- indexFieldBasePath={indexFieldBasePath}
35
- isEditable={false}
36
- isAutoHeight={isAutoHeight}
37
- hideFooterPagination={hideFooterPagination}
38
- customColumnOperations={finalCustomColumnOperations}
39
- customLinkDestination={customLinkDestination}
40
- setVisibleRows={setVisibleRows}
41
- onDataChange={newData => {
42
- setData({
43
- ...data,
44
- data: newData
45
- });
46
- }}
47
- LinkComponent={Link}
48
- />
30
+ <Box sx={{ height: 300px }}>
31
+ <DataGridBySchemaEditable
32
+ data={data.data}
33
+ columns={data.columns}
34
+ schema={data.schema}
35
+ model={model}
36
+ indexField={indexField}
37
+ indexFieldBasePath={indexFieldBasePath}
38
+ isEditable={false}
39
+ isAutoHeight={isAutoHeight}
40
+ hideFooterPagination={hideFooterPagination}
41
+ customColumnOperations={finalCustomColumnOperations}
42
+ customLinkDestination={customLinkDestination}
43
+ setVisibleRows={setVisibleRows}
44
+ onDataChange={newData => {
45
+ const apiContext = React.useContext(APIWrapperContext);
46
+ apiContext.handleLoading(false);
47
+ setData({
48
+ ...data,
49
+ data: newData
50
+ });
51
+ }}
52
+ LinkComponent={Link}
53
+ />
54
+ </Box>
49
55
  </DRFReactBySchemaProvider>
56
+ */
50
57
  ```
@@ -1,44 +1,28 @@
1
- import { ServerResponse } from 'http';
2
1
  import React from 'react';
2
+ import { ThemeProvider, Theme } from '@mui/material/styles';
3
+ import CssBaseline from '@mui/material/CssBaseline';
3
4
 
4
- export interface serverEndPointType {
5
- url: string;
6
- autocomplete?: string;
7
- api?: string;
8
- JSONSchema?: string;
9
- apiTokenUrl: string;
10
- getToken?: string;
11
- refreshToken?: string,
12
- verifyToken?: string
13
- }
14
- export interface DRFReactBySchemaContextType {
15
- serverEndPoint: serverEndPointType | null;
16
- isInBatches?: boolean;
17
- firstBatchLength?: number;
18
- }
5
+ import defaultTheme from '../styles/theme';
6
+ import Overlays from './Overlays';
7
+ import { DRFReactBySchemaContextType, serverEndPointType, DRFReactBySchemaContext } from './DRFReactBySchemaContext';
19
8
 
20
9
  interface DRFReactBySchemaProviderProps extends DRFReactBySchemaContextType {
21
10
  children: React.ReactNode;
22
11
  }
23
12
 
24
- export const DRFReactBySchemaContext = React.createContext<DRFReactBySchemaContextType>({
25
- serverEndPoint: null,
26
- isInBatches: true,
27
- firstBatchLength: 100
28
- });
29
-
30
13
  /**
31
14
  *
32
15
  *
33
16
  * @param {*} props
34
17
  * @returns {*}
35
18
  */
36
- const DRFReactBySchemaProvider: React.FC<DRFReactBySchemaProviderProps> = ({
19
+ const DRFReactBySchemaProvider = ({
37
20
  serverEndPoint,
21
+ theme,
38
22
  isInBatches,
39
23
  firstBatchLength,
40
24
  children
41
- }) => {
25
+ }: DRFReactBySchemaProviderProps) => {
42
26
  if (serverEndPoint) {
43
27
  const defaultKeys = [
44
28
  'autocomplete',
@@ -62,16 +46,26 @@ const DRFReactBySchemaProvider: React.FC<DRFReactBySchemaProviderProps> = ({
62
46
  }
63
47
  }
64
48
 
49
+ const mergedTheme = (theme)
50
+ ? { ...defaultTheme, ...theme }
51
+ : defaultTheme;
52
+
65
53
  return (
66
- <DRFReactBySchemaContext.Provider
67
- value={{
68
- serverEndPoint,
69
- isInBatches,
70
- firstBatchLength
71
- }}
72
- >
73
- {children}
74
- </DRFReactBySchemaContext.Provider>
54
+ <ThemeProvider theme={mergedTheme}>
55
+ <CssBaseline />
56
+ <DRFReactBySchemaContext.Provider
57
+ value={{
58
+ serverEndPoint,
59
+ theme,
60
+ isInBatches,
61
+ firstBatchLength
62
+ }}
63
+ >
64
+ <Overlays
65
+ children = {children}
66
+ />
67
+ </DRFReactBySchemaContext.Provider>
68
+ </ThemeProvider>
75
69
  );
76
70
  }
77
71
 
@@ -0,0 +1,94 @@
1
+ import React, { useState, useReducer } from 'react';
2
+ import Backdrop from '@mui/material/Backdrop';
3
+ import CircularProgress from '@mui/material/CircularProgress';
4
+ import Snackbar from '@mui/material/Snackbar';
5
+ import Alert from '@mui/material/Alert';
6
+ import Dialog from '@mui/material/Dialog';
7
+ import DialogActions from '@mui/material/DialogActions';
8
+ import DialogContent from '@mui/material/DialogContent';
9
+ import DialogTitle from '@mui/material/DialogTitle';
10
+ import Box from '@mui/material/Box';
11
+
12
+ import { reducer } from '../utils';
13
+ import APIWrapper from './APIWrapper';
14
+ import { DialogType, SnackBarType } from './APIWrapperContext';
15
+
16
+ export default function Overlays ({ children }: { children:React.ReactNode }) {
17
+ const initialSnackBar:SnackBarType = {
18
+ open: false,
19
+ msg: '',
20
+ severity: 'info'
21
+ };
22
+
23
+ const initialDialog:DialogType = {
24
+ open: false,
25
+ loading: true,
26
+ title: '',
27
+ Body: null,
28
+ Actions: null
29
+ };
30
+ const [snackBar, setSnackBar] = useReducer(reducer, initialSnackBar);
31
+ const [dialog, setDialog] = useReducer(reducer, initialDialog);
32
+ const [loading, setLoading] = useState<boolean>(true);
33
+
34
+ // give some time to stop loading when data is retrieved and must render before loading rendering:
35
+ const handleLoading = (loadingState:boolean) => {
36
+ if (loadingState) {
37
+ setLoading(true);
38
+ return;
39
+ }
40
+ setTimeout(() => {
41
+ setLoading(false);
42
+ }, 300);
43
+ };
44
+
45
+ const handleDialogClose = () => {
46
+ setDialog({
47
+ open: false
48
+ });
49
+ };
50
+
51
+ return (
52
+ <>
53
+ <APIWrapper
54
+ setLoading={setLoading}
55
+ handleLoading={handleLoading}
56
+ setSnackBar={setSnackBar}
57
+ setDialog={setDialog}
58
+ children={children}
59
+ />
60
+ <Backdrop
61
+ sx={{ color: '#fff', zIndex: (theme) => theme.zIndex.drawer + 1 }}
62
+ open={loading}
63
+ >
64
+ <CircularProgress />
65
+ </Backdrop>
66
+ <Snackbar
67
+ open={snackBar.open}
68
+ autoHideDuration={3000}
69
+ onClose={() => { setSnackBar({ open: false }); }}
70
+ anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
71
+ >
72
+ <Alert severity={snackBar.severity}>
73
+ {snackBar.msg}
74
+ </Alert>
75
+ </Snackbar>
76
+ <Dialog open={dialog.open} onClose={handleDialogClose}>
77
+ <DialogTitle>
78
+ {dialog.loading ? 'Carregando...' : dialog.title}
79
+ </DialogTitle>
80
+ <DialogContent>
81
+ {dialog.loading
82
+ ? <Box sx={{ display: 'flex' }}><CircularProgress /></Box>
83
+ : <>{dialog.Body}</>
84
+ }
85
+ </DialogContent>
86
+ <DialogActions>
87
+ {!dialog.loading &&
88
+ <>{dialog.Actions}</>
89
+ }
90
+ </DialogActions>
91
+ </Dialog>
92
+ </>
93
+ );
94
+ }
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ // Methods:
1
2
  import {
2
3
  updateData,
3
4
  partialUpdateData,
@@ -26,18 +27,30 @@ import {
26
27
  getPatternFormat
27
28
  } from './utils';
28
29
 
29
- // Components:
30
- import DRFReactBySchemaProvider, { DRFReactBySchemaContext } from './context/DRFReactBySchemaProvider';
30
+ // Wrappers/Providers:
31
+ import DRFReactBySchemaProvider from './context/DRFReactBySchemaProvider';
32
+ import { DRFReactBySchemaContext, useTheme } from './context/DRFReactBySchemaContext';
33
+ import { APIWrapperContext } from './context/APIWrapperContext';
34
+ // Components
31
35
  import DataGridBySchemaEditable from './components/DataGridBySchemaEditable';
32
36
  import GenericModelList from './components/GenericModelList';
37
+ import GenericRelatedModelList from './components/GenericRelatedModelList';
33
38
  import DataTotals from './components/DataTotals';
39
+ import DialogActions from './components/DialogActions';
34
40
 
35
41
  export {
42
+ // Wrappers/Providers:
36
43
  DRFReactBySchemaProvider,
37
44
  DRFReactBySchemaContext,
45
+ APIWrapperContext,
46
+ useTheme,
47
+ // Components:
38
48
  DataGridBySchemaEditable,
39
49
  GenericModelList,
50
+ GenericRelatedModelList,
40
51
  DataTotals,
52
+ DialogActions,
53
+ // Methods:
41
54
  updateData,
42
55
  partialUpdateData,
43
56
  createData,
@@ -113,7 +113,7 @@ const palette = {
113
113
  }
114
114
  };
115
115
 
116
- const theme = createTheme(
116
+ const defaultTheme = createTheme(
117
117
  {
118
118
  palette,
119
119
  components: {
@@ -187,4 +187,4 @@ const theme = createTheme(
187
187
  pickersPtBR
188
188
  );
189
189
 
190
- export default theme;
190
+ export default defaultTheme;
package/src/utils.ts CHANGED
@@ -33,6 +33,16 @@ interface GridActionsBySchemaColDef extends GridActionsColDef {
33
33
  patternFormat?: string
34
34
  };
35
35
  export type GridEnrichedBySchemaColDef = GridBySchemaColDef | GridActionsBySchemaColDef;
36
+ export interface DataSchemaColumnsType {
37
+ data: Item[];
38
+ schema: SchemaType;
39
+ columns?: GridEnrichedBySchemaColDef[];
40
+ }
41
+ export interface ItemSchemaColumnsType {
42
+ data: Item;
43
+ schema: SchemaType;
44
+ columns?: GridEnrichedBySchemaColDef[];
45
+ }
36
46
 
37
47
  export const emptyByType: any = (field:Field, forDatabase:boolean = false) => {
38
48
  if (field.model_default) {
@@ -76,11 +86,9 @@ export const getChoiceByValue = (
76
86
  };
77
87
 
78
88
  export const populateValues = ({
79
- model,
80
89
  data,
81
90
  schema
82
91
  }: {
83
- model:string,
84
92
  data:Item,
85
93
  schema:SchemaType
86
94
  }) => {
@@ -101,7 +109,6 @@ export const populateValues = ({
101
109
  const arValues = [];
102
110
  for (const row of data[key]) {
103
111
  const value = populateValues({
104
- model,
105
112
  data: row,
106
113
  schema: field.child.children
107
114
  });
@@ -112,7 +119,6 @@ export const populateValues = ({
112
119
  }
113
120
 
114
121
  values[key] = populateValues({
115
- model,
116
122
  data: data[key],
117
123
  schema: field.child.children
118
124
  });
@@ -318,4 +324,4 @@ export const getPatternFormat = (type:string) => {
318
324
  break;
319
325
  }
320
326
  return format;
321
- };
327
+ };
@@ -2,13 +2,8 @@ const path = require('path');
2
2
  const glob = require('glob');
3
3
 
4
4
  module.exports = {
5
- title: 'React Style Guide Example',
6
- // components: function () {
7
- // return glob.sync(path.resolve(__dirname, 'src/components/**/*.tsx'))
8
- // .filter(function (module) {
9
- // return /\/[A-Z]\w*\.tsx$/.test(module);
10
- // });
11
- // },
5
+ title: 'Styleguides for DRF React By Schema Package',
6
+ styleguideDir: 'public',
12
7
  components: [
13
8
  'src/components/*.tsx',
14
9
  'src/context/*.tsx'