admin_lsac 2.0.6 → 2.0.8

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/README.md CHANGED
@@ -63,14 +63,6 @@ You will need to create an array of schemas for your own admin panel.
63
63
  ## What is a schema?
64
64
 
65
65
  ```
66
- export interface PageSchema {
67
- name: string;
68
- actions: Action[];
69
- rowActions: RowAction[];
70
- getRequest: () => Promise<any[]>;
71
- tableFields: TableField[];
72
- }
73
-
74
66
  export interface TableField {
75
67
  name: string;
76
68
  access: (obj: any) => string | number | React.ReactElement;
@@ -79,7 +71,7 @@ export interface TableField {
79
71
  export interface SimpleField {
80
72
  name: string;
81
73
  label: string;
82
- type: "string" | "number" | "file";
74
+ type: 'string' | 'number' | 'file' | 'date';
83
75
  validationSchema: any;
84
76
  }
85
77
 
@@ -91,22 +83,23 @@ export interface Option {
91
83
  export interface DropdownField {
92
84
  name: string;
93
85
  label: string;
94
- type: "dropdown";
95
- options?: Option[] | undefined;
96
- getOptions: () => Promise<Option[]>;
86
+ type: 'dropdown';
87
+ validationSchema?: any;
88
+ options?: Option[];
89
+ getOptions?: () => Promise<Option[]>;
97
90
  }
98
91
 
99
92
  export interface ObjectField {
100
93
  name: string;
101
94
  label: string;
102
- type: "object";
95
+ type: 'object';
103
96
  fields: FormField[];
104
97
  }
105
98
 
106
99
  export interface ArrayField {
107
100
  name: string;
108
101
  label: string;
109
- type: "array";
102
+ type: 'array';
110
103
  element: Exclude<FormField, ArrayField>;
111
104
  }
112
105
 
@@ -115,20 +108,28 @@ export type FormField = SimpleField | DropdownField | ObjectField | ArrayField;
115
108
  export interface Action {
116
109
  name: string;
117
110
  fields?: FormField[];
118
- onSubmit: (obj1: any, obj2?: any) => Promise<any>;
111
+ onSubmit: (obj1: any, obj2?: any, obj3?: any) => Promise<any>;
119
112
  }
120
113
 
121
114
  export interface RowAction {
122
115
  name: string;
123
116
  fields?: FormField[];
124
- initialise?: (obj: any) => any;
125
- onSubmit: (obj1: any, obj2?: any) => Promise<any>;
117
+ initialise?: (obj: any) => Promise<any>;
118
+ onSubmit: (obj1: any, obj2?: any, obj3?: any) => Promise<any>;
119
+ }
120
+
121
+ export interface PageSchema {
122
+ name: string;
123
+ actions: Action[];
124
+ rowActions: RowAction[];
125
+ getRequest: () => Promise<any[]>;
126
+ tableFields: TableField[];
126
127
  }
127
128
  ```
128
129
 
129
130
  A page schema is based on these interfaces, and it describes how one table of your admin panel would need to be structured to accomplish what the user needs to do regarding an entity. (i.e. users, teams, companies, quizzes)
130
131
 
131
- The most important interface is `PageSchema`, as it is at the top of the relations between all these interfaces.
132
+ The most important interface is `PageSchema`, as it stands at the top of the relations between all these interfaces.
132
133
 
133
134
  What do the fields of `PageSchema` refer to?
134
135
 
@@ -140,7 +141,7 @@ What do the fields of `PageSchema` refer to?
140
141
 
141
142
  The operations for the rowActions and actions will generally have a form to complete before executing it. There are 4 types of inputs for the form part:
142
143
 
143
- - simpleField = simple data like numbers, strings or files
144
+ - simpleField = simple data like numbers, strings, files and dates
144
145
  - dropdownField = enable the user to choose an option from a predefined list
145
146
  - arrayField = arrays of data
146
147
  - objectField = an object containing more fields/inputs, or even other objects (some cool recursion)
@@ -148,20 +149,15 @@ The operations for the rowActions and actions will generally have a form to comp
148
149
  #### Schema example
149
150
 
150
151
  ```
152
+ import axios from "axios";
153
+ import React from "react";
151
154
  const domain = "http://localhost:3001"; // dev mode
152
155
 
153
- // helper function
154
- const getAuth = () => {
155
- // return a token or whatever :)
156
- };
157
-
158
156
  const companies: PageSchema = {
159
157
  name: "Companies",
160
158
 
161
159
  getRequest: async () => { // retrieve all entries from the database
162
- const res = await axios.get(domain + "/something", {
163
- headers: getAuth(),
164
- });
160
+ const res = await axios.get(domain + "/something");
165
161
  return res.data;
166
162
  },
167
163
 
@@ -217,6 +213,7 @@ const companies: PageSchema = {
217
213
  name: "type",
218
214
  label: "Question Type",
219
215
  type: "dropdown",
216
+ // validationSchema is missing here (optional), so it will not be a required field
220
217
  getOptions: async () => [
221
218
  {
222
219
  value: "OPEN",
@@ -238,13 +235,8 @@ const companies: PageSchema = {
238
235
  ],
239
236
  onSubmit: async (formValues: any) => { // onSubmit function can also be complex
240
237
  // for actions, onSubmit will always have one param (formValues - you can change the name though)
241
- // process formVaues as you wish
242
-
243
- // Nevertheless, submitting the actual data is the most important thing
244
- const result = await axios.post(domain + "/something", formValues, {
245
- headers: getAuth(),
246
- });
247
-
238
+ // you can also process formVaues as you wish
239
+ const result = await axios.post(domain + "/something", formValues);
248
240
  return result.data;
249
241
  }
250
242
  },
@@ -252,16 +244,14 @@ const companies: PageSchema = {
252
244
 
253
245
  rowActions: [
254
246
  {
255
- name: "Delete Event - Variant 1", // without form
247
+ name: "Modify Event - Variant 1", // without form
256
248
  onSubmit: async (eventId: number) => { // onSubmit has only param, the row's ID
257
- const res = await axios.delete(
258
- domain + "/something/" + eventId
259
- );
249
+ const res = await axios.delete(domain + "/something/" + eventId);
260
250
  return res.data;
261
251
  },
262
252
  },
263
253
  {
264
- name: "Delete Event - Variant 2", // with form
254
+ name: "Modify Event - Variant 2", // with form
265
255
  fields: [
266
256
  {
267
257
  name: "input",
@@ -271,18 +261,16 @@ const companies: PageSchema = {
271
261
  },
272
262
  ],
273
263
  onSubmit: async (formValues: any, eventId: number) => { // onSubmit has two params
274
- // the first param - formValues, while the second is the row's ID
275
- const res = await axios.delete(
276
- domain + "/something/" + eventId
277
- );
278
- return res.data;
264
+ // the first param - formValues, while the second is the row's ID
265
+ const result = await axios.patch(domain + "/something" + eventId, formValues);
266
+ return result.data;
279
267
  },
280
268
  },
281
269
  ],
282
270
  }
283
271
  ```
284
272
 
285
- Please note that the schema above is not related to any entity, and the fields of PageSchema do not necessarily have any relation between them. These are just random examples to teach you how to create your own schemas.
273
+ Please note that the schema above is not related to any entity, and the fields of PageSchema do not necessarily have any relation between them. These are just random examples to teach you how to create your own schema.
286
274
 
287
275
  #### An array of schemas must be defined as below:
288
276
 
package/admin_lsac.d.ts CHANGED
@@ -7,7 +7,7 @@ declare module 'admin_lsac' {
7
7
  export interface SimpleField {
8
8
  name: string;
9
9
  label: string;
10
- type: 'string' | 'number' | 'file';
10
+ type: 'string' | 'number' | 'file' | 'date';
11
11
  validationSchema: any;
12
12
  }
13
13
  export interface Option {
@@ -19,8 +19,8 @@ declare module 'admin_lsac' {
19
19
  label: string;
20
20
  type: 'dropdown';
21
21
  validationSchema?: any;
22
- options?: Option[] | undefined;
23
- getOptions: () => Promise<Option[]>;
22
+ options?: Option[];
23
+ getOptions?: () => Promise<Option[]>;
24
24
  }
25
25
  export interface ObjectField {
26
26
  name: string;
@@ -38,13 +38,13 @@ declare module 'admin_lsac' {
38
38
  export interface Action {
39
39
  name: string;
40
40
  fields?: FormField[];
41
- onSubmit: (obj1: any, obj2?: any) => Promise<any>;
41
+ onSubmit: (obj1: any, obj2?: any, obj3?: any) => Promise<any>;
42
42
  }
43
43
  export interface RowAction {
44
44
  name: string;
45
45
  fields?: FormField[];
46
- initialise?: (obj: any) => any;
47
- onSubmit: (obj1: any, obj2?: any) => Promise<any>;
46
+ initialise?: (obj: any) => Promise<any>;
47
+ onSubmit: (obj1: any, obj2?: any, obj3?: any) => Promise<any>;
48
48
  }
49
49
  export interface PageSchema {
50
50
  name: string;
@@ -7,7 +7,7 @@ declare module 'admin_lsac' {
7
7
  export interface SimpleField {
8
8
  name: string;
9
9
  label: string;
10
- type: 'string' | 'number' | 'file';
10
+ type: 'string' | 'number' | 'file' | 'date';
11
11
  validationSchema: any;
12
12
  }
13
13
  export interface Option {
@@ -19,8 +19,8 @@ declare module 'admin_lsac' {
19
19
  label: string;
20
20
  type: 'dropdown';
21
21
  validationSchema?: any;
22
- options?: Option[] | undefined;
23
- getOptions: () => Promise<Option[]>;
22
+ options?: Option[];
23
+ getOptions?: () => Promise<Option[]>;
24
24
  }
25
25
  export interface ObjectField {
26
26
  name: string;
@@ -38,13 +38,13 @@ declare module 'admin_lsac' {
38
38
  export interface Action {
39
39
  name: string;
40
40
  fields?: FormField[];
41
- onSubmit: (obj1: any, obj2?: any) => Promise<any>;
41
+ onSubmit: (obj1: any, obj2?: any, obj3?: any) => Promise<any>;
42
42
  }
43
43
  export interface RowAction {
44
44
  name: string;
45
45
  fields?: FormField[];
46
- initialise?: (obj: any) => any;
47
- onSubmit: (obj1: any, obj2?: any) => Promise<any>;
46
+ initialise?: (obj: any) => Promise<any>;
47
+ onSubmit: (obj1: any, obj2?: any, obj3?: any) => Promise<any>;
48
48
  }
49
49
  export interface PageSchema {
50
50
  name: string;
@@ -74,6 +74,7 @@ export function AdminPage({ pages, selectedPage, basePath, apiURL = '', }) {
74
74
  const [data, setData] = useState([]);
75
75
  const [displayData, setDisplayData] = useState([]);
76
76
  const [rowId, setRowId] = useState();
77
+ const [rowObject, setRowObject] = useState([]);
77
78
  const [refetch, setRefetch] = useState(false);
78
79
  const [socket, setSocket] = useState(io);
79
80
  newSocket(setSocket, apiURL);
@@ -111,13 +112,16 @@ export function AdminPage({ pages, selectedPage, basePath, apiURL = '', }) {
111
112
  return selectedPage.rowActions.map((rowAction, index) => (_jsx(MenuItem, { onClick: () => {
112
113
  setSelectedAction(rowAction);
113
114
  setRowId(obj.row.original[0]);
115
+ if (obj.staticRowIndex !== undefined) {
116
+ setRowObject(data[obj.staticRowIndex]);
117
+ }
114
118
  onOpen();
115
119
  const rowActionsMenu = document.querySelector('.MuiPaper-root.MuiPopover-paper.MuiMenu-paper');
116
120
  if (rowActionsMenu) {
117
121
  rowActionsMenu.remove();
118
122
  }
119
- }, children: rowAction.name + ' ' + obj.row.original[0] }, index)));
120
- } }) }), _jsxs(Modal, { size: '6xl', isOpen: isOpen, onClose: onClose, children: [_jsx(ModalOverlay, {}), _jsxs(ModalContent, { children: [_jsx(ModalHeader, { children: selectedAction.name }), _jsx(ModalCloseButton, {}), _jsxs(ModalBody, { children: [selectedAction.fields && selectedAction.fields?.length > 0 ? (_jsx(GenericForm, { action: selectedAction, onClose: onClose, rowId: rowId })) : (_jsx(Button, { colorScheme: "blue", mr: 3, onClick: () => {
123
+ }, children: rowAction.name }, index)));
124
+ } }) }), _jsxs(Modal, { size: '6xl', isOpen: isOpen, onClose: onClose, children: [_jsx(ModalOverlay, {}), _jsxs(ModalContent, { children: [_jsx(ModalHeader, { children: selectedAction.name }), _jsx(ModalCloseButton, {}), _jsxs(ModalBody, { children: [selectedAction.fields && selectedAction.fields?.length > 0 ? (_jsx(GenericForm, { action: selectedAction, onClose: onClose, rowId: rowId, rowObject: rowObject })) : (_jsx(Button, { colorScheme: "blue", mr: 3, onClick: () => {
121
125
  selectedAction.onSubmit(rowId);
122
126
  onClose();
123
127
  }, children: "Confirm Action" })), _jsx(Button, { colorScheme: "red", mr: 3, onClick: onClose, children: "Close" })] })] })] })] }));
@@ -3,6 +3,7 @@ interface GenericFormProps {
3
3
  action: Action | RowAction;
4
4
  onClose?: () => void;
5
5
  rowId?: number;
6
+ rowObject?: any;
6
7
  }
7
- export declare function GenericForm({ action, onClose, rowId }: GenericFormProps): import("react/jsx-runtime").JSX.Element;
8
+ export declare function GenericForm({ action, onClose, rowId, rowObject }: GenericFormProps): import("react/jsx-runtime").JSX.Element;
8
9
  export {};
@@ -36,7 +36,7 @@ function generateSingleField(formfield, fieldName, key) {
36
36
  if (event.currentTarget.files != null) {
37
37
  form.setFieldValue(fieldName, event.currentTarget.files[0]);
38
38
  }
39
- } })) : formfield.type === 'date' ? (_jsx(Input, { ...field, type: "date", placeholder: "" })) : (_jsxs(Select, { ...field, defaultValue: "", children: [_jsx("option", { disabled: true, value: "", children: "Select an option!" }), formfield.options?.map((option, key) => (_jsx("option", { value: `${option.value}`, children: option.display }, key)))] })), _jsx(FormErrorMessage, { children: getIn(form.errors, fieldName) })] })) }, key));
39
+ } })) : formfield.type === 'date' ? (_jsx(Input, { ...field, type: "date", placeholder: "" })) : (_jsxs(Select, { ...field, value: field.value || '', children: [_jsx("option", { disabled: true, value: "", children: "Select an option!" }), formfield.options?.map((option, key) => (_jsx("option", { value: `${option.value}`, children: option.display }, key)))] })), _jsx(FormErrorMessage, { children: getIn(form.errors, fieldName) })] })) }, key));
40
40
  }
41
41
  function parseFields(fields, previous) {
42
42
  if (!fields) {
@@ -102,7 +102,7 @@ async function setOptions(fields) {
102
102
  }
103
103
  const promises = fields.map(async (field) => {
104
104
  if (field.type === 'dropdown')
105
- field.options = await field.getOptions();
105
+ field.options = field.options || (field.getOptions && (await field.getOptions()));
106
106
  else if (field.type === 'array')
107
107
  await setOptions([field.element]);
108
108
  else if (field.type === 'object')
@@ -110,7 +110,7 @@ async function setOptions(fields) {
110
110
  });
111
111
  await Promise.all(promises);
112
112
  }
113
- export function GenericForm({ action, onClose, rowId }) {
113
+ export function GenericForm({ action, onClose, rowId, rowObject }) {
114
114
  const [formFields, setFormFields] = useState(parseFields(action.fields));
115
115
  const [initialValues, setInitialValues] = useState(getCustomInitialValues(action.fields));
116
116
  const [validationSchema, _] = useState(parseValidation(action.fields));
@@ -127,7 +127,9 @@ export function GenericForm({ action, onClose, rowId }) {
127
127
  return _jsx(_Fragment, {});
128
128
  return (_jsx(_Fragment, { children: _jsx(Formik, { enableReinitialize: true, initialValues: initialValues, validationSchema: Yup.object(validationSchema), onReset: handleFormReset, onSubmit: async (values) => {
129
129
  try {
130
- if (rowId)
130
+ if (rowObject !== undefined)
131
+ await action.onSubmit(values, rowId, rowObject);
132
+ else if (rowId !== undefined)
131
133
  await action.onSubmit(values, rowId);
132
134
  else
133
135
  await action.onSubmit(values);
@@ -138,7 +140,7 @@ export function GenericForm({ action, onClose, rowId }) {
138
140
  catch (e) {
139
141
  if (onClose)
140
142
  onClose();
141
- const err = e.request.response;
143
+ const err = e.message;
142
144
  Swal.fire({
143
145
  text: 'Error: ' + err,
144
146
  });
@@ -18,8 +18,8 @@ export interface DropdownField {
18
18
  label: string;
19
19
  type: 'dropdown';
20
20
  validationSchema?: any;
21
- options?: Option[] | undefined;
22
- getOptions: () => Promise<Option[]>;
21
+ options?: Option[];
22
+ getOptions?: () => Promise<Option[]>;
23
23
  }
24
24
  export interface ObjectField {
25
25
  name: string;
@@ -37,13 +37,13 @@ export type FormField = SimpleField | DropdownField | ObjectField | ArrayField;
37
37
  export interface Action {
38
38
  name: string;
39
39
  fields?: FormField[];
40
- onSubmit: (obj1: any, obj2?: any) => Promise<any>;
40
+ onSubmit: (obj1: any, obj2?: any, obj3?: any) => Promise<any>;
41
41
  }
42
42
  export interface RowAction {
43
43
  name: string;
44
44
  fields?: FormField[];
45
- initialise?: (obj: any) => any;
46
- onSubmit: (obj1: any, obj2?: any) => Promise<any>;
45
+ initialise?: (obj: any) => Promise<any>;
46
+ onSubmit: (obj1: any, obj2?: any, obj3?: any) => Promise<any>;
47
47
  }
48
48
  export interface PageSchema {
49
49
  name: string;
@@ -1,36 +1,65 @@
1
- // import axios from "axios";
1
+ import axios from 'axios';
2
2
  import React from 'react';
3
- // const domain = "http://localhost:3001";
3
+ const domain = 'http://localhost:3001';
4
4
  export const event = {
5
5
  name: 'Events',
6
6
  actions: [],
7
7
  rowActions: [
8
- // {
9
- // name: "Delete Event",
10
- // fields: [
11
- // {
12
- // name: "input",
13
- // label: "Mock Field",
14
- // type: "string",
15
- // validationSchema: "",
16
- // },
17
- // ],
18
- // initialise: async (eventId: number) => {
19
- // const res = await axios.get(domain + "/events/" + eventId);
20
- // let obj: any = {};
21
- // obj.input = res.data.name;
22
- // return obj;
23
- // },
24
- // onSubmit: async (_: any, eventId: number) => {
25
- // const res = await axios.delete(
26
- // domain + "/events/" + eventId
27
- // );
28
- // return res.data;
29
- // },
30
- // }
8
+ {
9
+ name: 'Delete Event - Variant 1', // without form
10
+ onSubmit: async (eventId) => {
11
+ // onSubmit has only param, the row's ID
12
+ const res = await axios.delete(domain + '/something/' + eventId);
13
+ return res.data;
14
+ },
15
+ },
16
+ {
17
+ name: 'Delete Event - Variant 2', // with form
18
+ fields: [
19
+ {
20
+ name: 'input',
21
+ label: 'Mock Field',
22
+ type: 'string',
23
+ validationSchema: '',
24
+ },
25
+ {
26
+ name: 'type',
27
+ label: 'Question Type',
28
+ type: 'dropdown',
29
+ // validationSchema is missing here (optional), so it will not be a required field
30
+ getOptions: async () => [
31
+ {
32
+ value: 'OPEN',
33
+ display: 'Open',
34
+ },
35
+ {
36
+ value: 'SINGLE',
37
+ display: 'Single',
38
+ },
39
+ {
40
+ value: 'MULTIPLE',
41
+ display: 'Multiple',
42
+ },
43
+ ],
44
+ },
45
+ ],
46
+ initialise: async (eventId) => {
47
+ const res = await axios.get(domain + '/events/' + eventId);
48
+ const obj = {};
49
+ obj.input = res.data.name;
50
+ return obj;
51
+ },
52
+ onSubmit: async (formValues, eventId) => {
53
+ // onSubmit has two params
54
+ // the first param - formValues, while the second is the row's ID
55
+ console.log(formValues);
56
+ const res = await axios.delete(domain + '/something/' + eventId);
57
+ return res.data;
58
+ },
59
+ },
31
60
  ],
32
61
  getRequest: async () => {
33
- // const res = await axios.get(domain + "/events");
62
+ // const res = await axios.get(domain + '/events');
34
63
  // return res.data;
35
64
  return [];
36
65
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "admin_lsac",
3
3
  "private": false,
4
- "version": "2.0.6",
4
+ "version": "2.0.8",
5
5
  "description": "Generic Admin Panel created for storing events' data",
6
6
  "scripts": {
7
7
  "dev": "vite",