admin_lsac 1.1.0 → 1.1.3

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
@@ -1,46 +1,127 @@
1
- # Getting Started with Create React App
1
+ # Generic Admin Panel
2
+
3
+ For configuring your own admin panel, follow the next instructions.
4
+
5
+ ### `npm install admin_lsac`
2
6
 
3
- This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4
-
5
- ## Available Scripts
6
-
7
- In the project directory, you can run:
8
-
9
- ### `npm start`
10
-
11
- Runs the app in the development mode.\
12
- Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
13
-
14
- The page will reload if you make edits.\
15
- You will also see any lint errors in the console.
16
-
17
- ### `npm test`
18
-
19
- Launches the test runner in the interactive watch mode.\
20
- See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21
-
22
- ### `npm run build`
23
-
24
- Builds the app for production to the `build` folder.\
25
- It correctly bundles React in production mode and optimizes the build for the best performance.
26
-
27
- The build is minified and the filenames include the hashes.\
28
- Your app is ready to be deployed!
29
-
30
- See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31
-
32
- ### `npm run eject`
33
-
34
- **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
35
-
36
- If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37
-
38
- Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
39
-
40
- You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
7
+ This command will download and install the specified package and its dependencies into your project's node_modules directory, making it available for use in your project.
8
+
9
+ ### `npm install export-to-csv@1.2.1`
10
+
11
+ Export-to-csv package latest version is not working properly, so make sure you have the last functional version of this package install.
12
+
13
+ ### `import AdminPanel from 'admin_lsac'`
14
+
15
+ You can import this component in the root file of your project (i.e index.js) or in App.js. If your project is TypeScript-based, you need to write the following line as well:
16
+
17
+ ### `import PageSchema from 'admin_lsac'`
18
+
19
+ You need to create an array of schemas to pass it as props to the component.
20
+
21
+ ### `<AdminPanel pages={your_array} />`
22
+
23
+ ## What is a schema?
24
+
25
+ ```
26
+ export interface PageSchema {
27
+ name: string;
28
+ actions: Action[];
29
+ rowActions: RowAction[];
30
+ getRequest: () => Promise<any[]>;
31
+ tableFields: TableField[];
32
+ }
33
+
34
+ export interface TableField {
35
+ name: string;
36
+ access: (obj: any) => string | number | React.ReactElement;
37
+ }
38
+
39
+ export interface SimpleField {
40
+ name: string;
41
+ label: string;
42
+ type: "string" | "number" | "file";
43
+ validationSchema: any;
44
+ }
45
+
46
+ export interface Option {
47
+ value: string | number | boolean;
48
+ display: string;
49
+ }
50
+
51
+ export interface DropdownField {
52
+ name: string;
53
+ label: string;
54
+ type: "dropdown";
55
+ options?: Option[] | undefined;
56
+ getOptions: () => Promise<Option[]>;
57
+ }
58
+
59
+ export interface ObjectField {
60
+ name: string;
61
+ label: string;
62
+ type: "object";
63
+ fields: FormField[];
64
+ }
65
+
66
+ export interface ArrayField {
67
+ name: string;
68
+ label: string;
69
+ type: "array";
70
+ element: Exclude<FormField, ArrayField>;
71
+ }
72
+
73
+ export type FormField = SimpleField | DropdownField | ObjectField | ArrayField;
74
+
75
+ export interface Action {
76
+ name: string;
77
+ fields?: FormField[];
78
+ onSubmit: (obj1: any, obj2?: any) => Promise<any>;
79
+ }
80
+
81
+ export interface RowAction {
82
+ name: string;
83
+ fields?: FormField[];
84
+ initialise?: (obj: any) => any;
85
+ onSubmit: (obj1: any, obj2?: any) => Promise<any>;
86
+ }
87
+ ```
88
+
89
+ A page schema is based on these interfaces, which can be imported into your files. A page schema describes how one table of your admin panel would need to be structured to accomplish what the user needs regarding an entity. (i.e. users, teams, companies, quizzes)
90
+
91
+ #### In JavaScript, an array of schemas would be defined as follows:
92
+
93
+ ```
94
+ const your_array = [
95
+ {
96
+ // schema 1
97
+ },
98
+ {
99
+ // schema 2
100
+ },
101
+ ...
102
+ ];
103
+ ```
104
+
105
+ #### In TypeScript, an array of schemas would be defined as follows:
106
+
107
+ ```
108
+ const your_array: PageSchema[] = [
109
+ {
110
+ // schema 1
111
+ },
112
+ {
113
+ // schema 2
114
+ },
115
+ ...
116
+ ];
117
+ ```
118
+
119
+ ## Other Specifications
120
+
121
+ Due to some corrupt dependencies, you need a Node version >= 20.5.0 to use this package in a Vite app.
122
+
123
+ For every entity you describe through a page schema, getRequest and onSubmit functions will use routes created for the entity. `getRequest` function will make a GET request, while `onSumbit` will probably make a POST, PATCH or DELETE request.
41
124
 
42
125
  ## Learn More
43
126
 
44
- You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45
-
46
- To learn React, check out the [React documentation](https://reactjs.org/).
127
+ For more details, especially about page schemas, contact the owner. :)
package/dist/App.d.ts ADDED
@@ -0,0 +1,78 @@
1
+ import * as React from "react";
2
+
3
+ declare module "admin_lsac" {
4
+ export interface TableField {
5
+ name: string;
6
+ access: (obj: any) => string | number | React.ReactElement;
7
+ }
8
+
9
+ export interface SimpleField {
10
+ name: string;
11
+ label: string;
12
+ type: "string" | "number" | "file";
13
+ validationSchema: any;
14
+ }
15
+
16
+ export interface Option {
17
+ value: string | number | boolean;
18
+ display: string;
19
+ }
20
+
21
+ export interface DropdownField {
22
+ name: string;
23
+ label: string;
24
+ type: "dropdown";
25
+ options?: Option[] | undefined;
26
+ getOptions: () => Promise<Option[]>;
27
+ }
28
+
29
+ export interface ObjectField {
30
+ name: string;
31
+ label: string;
32
+ type: "object";
33
+ fields: FormField[];
34
+ }
35
+
36
+ export interface ArrayField {
37
+ name: string;
38
+ label: string;
39
+ type: "array";
40
+ element: Exclude<FormField, ArrayField>;
41
+ }
42
+
43
+ export type FormField = SimpleField | DropdownField | ObjectField | ArrayField;
44
+
45
+ export interface Action {
46
+ name: string;
47
+ fields?: FormField[];
48
+ onSubmit: (obj1: any, obj2?: any) => Promise<any>;
49
+ }
50
+
51
+ export interface RowAction {
52
+ name: string;
53
+ fields?: FormField[];
54
+ initialise?: (obj: any) => any;
55
+ onSubmit: (obj1: any, obj2?: any) => Promise<any>;
56
+ }
57
+
58
+ export interface PageSchema {
59
+ name: string;
60
+ actions: Action[];
61
+ rowActions: RowAction[];
62
+ getRequest: () => Promise<any[]>;
63
+ tableFields: TableField[];
64
+ }
65
+
66
+ interface AdminPanelProps {
67
+ pages: PageSchema[];
68
+ }
69
+
70
+ export default function AdminPanel({ pages }: AdminPanelProps): React.ReactElement;
71
+
72
+ interface PageProps {
73
+ pages: PageSchema[];
74
+ selectedPage: PageSchema;
75
+ }
76
+
77
+ export function Page(props: PageProps): React.ReactElement;
78
+ }
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ChakraProvider } from "@chakra-ui/react";
3
+ import { BrowserRouter, Route, Routes } from "react-router-dom";
4
+ import { Page } from "./components/Page";
5
+ import { pageToUrl } from "./schema/schema";
6
+ function AdminPanel(_a) {
7
+ var pages = _a.pages;
8
+ return (_jsx(ChakraProvider, { children: _jsx(BrowserRouter, { children: _jsxs(Routes, { children: [pages.map(function (page) { return (_jsx(Route, { path: pageToUrl(page), element: _jsx(Page, { pages: pages, selectedPage: page }) })); }), pages[0] ?
9
+ _jsx(Route, { path: "*", element: _jsx(Page, { pages: pages, selectedPage: pages[0] }) })
10
+ : null] }) }) }));
11
+ }
12
+ export default AdminPanel;
@@ -0,0 +1,243 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
+ return new (P || (P = Promise))(function (resolve, reject) {
15
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
19
+ });
20
+ };
21
+ var __generator = (this && this.__generator) || function (thisArg, body) {
22
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
23
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
24
+ function verb(n) { return function (v) { return step([n, v]); }; }
25
+ function step(op) {
26
+ if (f) throw new TypeError("Generator is already executing.");
27
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
28
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
29
+ if (y = 0, t) op = [op[0] & 2, t.value];
30
+ switch (op[0]) {
31
+ case 0: case 1: t = op; break;
32
+ case 4: _.label++; return { value: op[1], done: false };
33
+ case 5: _.label++; y = op[1]; op = [0]; continue;
34
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
35
+ default:
36
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
37
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
38
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
39
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
40
+ if (t[2]) _.ops.pop();
41
+ _.trys.pop(); continue;
42
+ }
43
+ op = body.call(thisArg, _);
44
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
45
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
+ }
47
+ };
48
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
49
+ import { Box, Button, FormControl, FormErrorMessage, FormLabel, Input, Select, } from "@chakra-ui/react";
50
+ import { Field, Form, Formik, FieldArray, getIn } from "formik";
51
+ import * as Yup from "yup";
52
+ import Swal from "sweetalert2";
53
+ import { useEffect, useState } from "react";
54
+ function parseValidation(fields) {
55
+ if (!fields) {
56
+ return {};
57
+ }
58
+ return fields.reduce(function (acc, field) {
59
+ if (field.type !== "dropdown" &&
60
+ field.type !== "object" &&
61
+ field.type !== "array") {
62
+ acc[field.name] = field.validationSchema;
63
+ }
64
+ else if (field.type === "array") {
65
+ if (field.element.type === "dropdown") {
66
+ acc[field.name] = Yup.array().of(Yup.string().required());
67
+ }
68
+ else if (field.element.type === "object") {
69
+ acc[field.name] = Yup.array().of(Yup.object(parseValidation(field.element.fields)));
70
+ }
71
+ else {
72
+ acc[field.name] = Yup.array().of(field.element.validationSchema);
73
+ }
74
+ }
75
+ else if (field.type === "object") {
76
+ acc[field.name] = Yup.object(parseValidation(field.fields));
77
+ }
78
+ if (field.type === "dropdown") {
79
+ acc[field.name] = Yup.string().required();
80
+ }
81
+ return acc;
82
+ }, {});
83
+ }
84
+ function generateSingleField(formfield, fieldName, key) {
85
+ return (_jsx(Field, __assign({ name: fieldName }, { children: function (_a) {
86
+ var _b;
87
+ var field = _a.field, form = _a.form;
88
+ return (_jsxs(FormControl, __assign({ isInvalid: getIn(form.touched, fieldName) && getIn(form.errors, fieldName) }, { children: [_jsx(FormLabel, __assign({ marginTop: 2 }, { children: formfield.label })), formfield.type === "string" || formfield.type === "number" ? (_jsx(Input, __assign({}, field, { type: formfield.type === "number" ? "number" : "text", placeholder: "" }))) : formfield.type === "file" ? (_jsx(Input, { type: "file", name: fieldName, onChange: function (event) {
89
+ if (event.currentTarget.files != null) {
90
+ form.setFieldValue(fieldName, event.currentTarget.files[0]);
91
+ }
92
+ } })) : (_jsxs(Select, __assign({}, field, { defaultValue: "" }, { children: [_jsx("option", __assign({ disabled: true, value: "" }, { children: "Select an option!" })), (_b = formfield.options) === null || _b === void 0 ? void 0 : _b.map(function (option, key) { return (_jsx("option", __assign({ value: "".concat(option.value) }, { children: option.display }), key)); })] }))), _jsx(FormErrorMessage, { children: getIn(form.errors, fieldName) })] })));
93
+ } }), key));
94
+ }
95
+ function parseFields(fields, previous) {
96
+ if (!fields) {
97
+ return [];
98
+ }
99
+ var computedFields = fields.map(function (formfield, key) {
100
+ var fieldName = previous !== undefined ? previous + "." + formfield.name : formfield.name;
101
+ if (formfield.type === "object") {
102
+ var objectFields = parseFields(formfield.fields, fieldName);
103
+ return _jsx(FormControl, { children: objectFields }, fieldName);
104
+ }
105
+ else if (formfield.type === "array") {
106
+ return (_jsx(FieldArray, __assign({ name: fieldName }, { children: function (_a) {
107
+ var remove = _a.remove, push = _a.push, form = _a.form;
108
+ return (_jsxs("div", { children: [_jsx(FormLabel, __assign({ marginTop: 2 }, { children: formfield.label })), getIn(form.values, fieldName).length > 0 &&
109
+ getIn(form.values, fieldName).map(function (element, index) { return (_jsxs(Box, __assign({ paddingLeft: 10 }, { children: [_jsx("h4", { children: _jsx("b", { children: "".concat(fieldName, ".").concat(index) }) }), _jsx(Box, __assign({ paddingLeft: 10 }, { children: formfield.element.type === "object"
110
+ ? parseFields(formfield.element.fields, "".concat(fieldName, ".").concat(index))
111
+ : generateSingleField(formfield.element, "".concat(fieldName, ".").concat(index), key) })), _jsxs(Button, __assign({ type: "button", colorScheme: "red", marginY: 2, onClick: function () { return remove(index); } }, { children: ["Remove ", "".concat(fieldName, ".").concat(index)] }))] }))); }), _jsxs(Button, __assign({ type: "button", marginY: 2, colorScheme: "blue", onClick: function () {
112
+ var value = undefined;
113
+ if (formfield.element.type === "object") {
114
+ value = getInitialValues(formfield.element.fields);
115
+ }
116
+ else {
117
+ value = getInitialValues([formfield.element])[0];
118
+ }
119
+ push(value);
120
+ } }, { children: ["Add ", fieldName] }))] }));
121
+ } })));
122
+ }
123
+ else {
124
+ return generateSingleField(formfield, fieldName, key);
125
+ }
126
+ });
127
+ return computedFields;
128
+ }
129
+ function getInitialValues(fields) {
130
+ var obj = {};
131
+ if (!fields) {
132
+ return obj;
133
+ }
134
+ fields.forEach(function (field) {
135
+ if (field.type === "array")
136
+ obj[field.name] = [];
137
+ else if (field.type === "object")
138
+ obj[field.name] = getInitialValues(field.fields);
139
+ else if (field.type === "string")
140
+ obj[field.name] = "";
141
+ else if (field.type === "number")
142
+ obj[field.name] = 0;
143
+ else
144
+ obj[field.name] = null;
145
+ });
146
+ return obj;
147
+ }
148
+ function setOptions(fields) {
149
+ return __awaiter(this, void 0, void 0, function () {
150
+ var promises;
151
+ var _this = this;
152
+ return __generator(this, function (_a) {
153
+ switch (_a.label) {
154
+ case 0:
155
+ if (!fields) {
156
+ return [2 /*return*/];
157
+ }
158
+ promises = fields.map(function (field) { return __awaiter(_this, void 0, void 0, function () {
159
+ var _a;
160
+ return __generator(this, function (_b) {
161
+ switch (_b.label) {
162
+ case 0:
163
+ if (!(field.type === "dropdown")) return [3 /*break*/, 2];
164
+ _a = field;
165
+ return [4 /*yield*/, field.getOptions()];
166
+ case 1:
167
+ _a.options = _b.sent();
168
+ return [3 /*break*/, 6];
169
+ case 2:
170
+ if (!(field.type === "array")) return [3 /*break*/, 4];
171
+ return [4 /*yield*/, setOptions([field.element])];
172
+ case 3:
173
+ _b.sent();
174
+ return [3 /*break*/, 6];
175
+ case 4:
176
+ if (!(field.type === "object")) return [3 /*break*/, 6];
177
+ return [4 /*yield*/, setOptions(field.fields)];
178
+ case 5:
179
+ _b.sent();
180
+ _b.label = 6;
181
+ case 6: return [2 /*return*/];
182
+ }
183
+ });
184
+ }); });
185
+ return [4 /*yield*/, Promise.all(promises)];
186
+ case 1:
187
+ _a.sent();
188
+ return [2 /*return*/];
189
+ }
190
+ });
191
+ });
192
+ }
193
+ export function GenericForm(_a) {
194
+ var _this = this;
195
+ var action = _a.action, onClose = _a.onClose, rowId = _a.rowId;
196
+ var _b = useState(parseFields(action.fields)), formFields = _b[0], setFormFields = _b[1];
197
+ var initialValues = useState(getInitialValues(action.fields))[0];
198
+ var validationSchema = useState(parseValidation(action.fields))[0];
199
+ useEffect(function () {
200
+ setOptions(action.fields).then(function () {
201
+ setFormFields(parseFields(action.fields));
202
+ });
203
+ }, []);
204
+ if (!action.fields)
205
+ return _jsx(_Fragment, {});
206
+ return (_jsx(_Fragment, { children: _jsx(Formik, __assign({ initialValues: initialValues, validationSchema: Yup.object(validationSchema), onSubmit: function (values) { return __awaiter(_this, void 0, void 0, function () {
207
+ var res, e_1, err;
208
+ return __generator(this, function (_a) {
209
+ switch (_a.label) {
210
+ case 0:
211
+ _a.trys.push([0, 5, , 6]);
212
+ res = void 0;
213
+ if (!rowId) return [3 /*break*/, 2];
214
+ return [4 /*yield*/, action.onSubmit(values, rowId)];
215
+ case 1:
216
+ res = _a.sent();
217
+ return [3 /*break*/, 4];
218
+ case 2: return [4 /*yield*/, action.onSubmit(values)];
219
+ case 3:
220
+ res = _a.sent();
221
+ _a.label = 4;
222
+ case 4:
223
+ if (onClose)
224
+ onClose();
225
+ Swal.fire("Ok");
226
+ return [3 /*break*/, 6];
227
+ case 5:
228
+ e_1 = _a.sent();
229
+ if (onClose)
230
+ onClose();
231
+ err = e_1.request.response;
232
+ Swal.fire({
233
+ text: "Error: " + err,
234
+ });
235
+ return [3 /*break*/, 6];
236
+ case 6: return [2 /*return*/];
237
+ }
238
+ });
239
+ }); } }, { children: function (_a) {
240
+ var isSubmitting = _a.isSubmitting;
241
+ return (_jsxs(Form, { children: [formFields, _jsx(Button, __assign({ mt: 4, colorScheme: "teal", isLoading: isSubmitting, type: "submit" }, { children: "Submit" }))] }));
242
+ } })) }));
243
+ }
@@ -0,0 +1,99 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
13
+ import { useEffect, useState } from "react";
14
+ import { ChakraProvider } from "@chakra-ui/react";
15
+ import { pageToUrl } from "../schema/schema";
16
+ import { Button, Modal, ModalHeader, ModalBody, useDisclosure, ModalOverlay, ModalContent, ModalCloseButton, Box, Stack, } from "@chakra-ui/react";
17
+ import { GenericForm } from "./GenericForm";
18
+ import { useNavigate } from "react-router";
19
+ import { ThemeProvider } from "@emotion/react";
20
+ import { createTheme } from "@mui/material/styles";
21
+ import { MaterialReactTable } from "material-react-table";
22
+ import { mkConfig, generateCsv, download } from "export-to-csv";
23
+ import Swal from "sweetalert2";
24
+ import MenuItem from "@mui/material/MenuItem";
25
+ function Header(_a) {
26
+ var pages = _a.pages, data = _a.data;
27
+ var nav = useNavigate();
28
+ return (_jsx(Box, __assign({ background: "blue.50", padding: 1 }, { children: _jsxs(Stack, __assign({ margin: 3, direction: "row", justifyContent: "space-between", alignItems: "center" }, { children: [_jsx(Stack, __assign({ margin: 4, gap: 10, direction: "row", alignItems: "center" }, { children: pages.map(function (p) { return (_jsx(Box, __assign({ as: "a", href: pageToUrl(p) }, { children: p.name }))); }) })), _jsx(Stack, __assign({ direction: "row" }, { children: _jsx(Button, __assign({ colorScheme: "red", onClick: function () {
29
+ var filename = prompt("Enter filename:");
30
+ if (filename)
31
+ exportToCSV(data, filename);
32
+ } }, { children: "Export Data" })) }))] })) })));
33
+ }
34
+ function exportToCSV(data, filename) {
35
+ var formatImageData = function (obj) {
36
+ var formattedObj = {};
37
+ for (var key in obj) {
38
+ if (typeof obj[key] !== "object") {
39
+ formattedObj[key] = obj[key];
40
+ }
41
+ }
42
+ return formattedObj;
43
+ };
44
+ var formattedData = data.map(formatImageData);
45
+ var csvConfig = mkConfig({
46
+ useKeysAsHeaders: true,
47
+ filename: filename,
48
+ });
49
+ if (formattedData.length > 0) {
50
+ var csv = generateCsv(csvConfig)(formattedData);
51
+ download(csvConfig)(csv);
52
+ }
53
+ else {
54
+ Swal.fire({
55
+ title: "Error while exporting CSV!",
56
+ text: "There is no data to export.",
57
+ });
58
+ }
59
+ }
60
+ export function Page(_a) {
61
+ var _b;
62
+ var pages = _a.pages, selectedPage = _a.selectedPage;
63
+ var _c = useDisclosure(), isOpen = _c.isOpen, onOpen = _c.onOpen, onClose = _c.onClose;
64
+ var _d = useState({}), selectedAction = _d[0], setSelectedAction = _d[1];
65
+ var _e = useState([]), data = _e[0], setData = _e[1];
66
+ var _f = useState([]), displayData = _f[0], setDisplayData = _f[1];
67
+ var _g = useState(), rowId = _g[0], setRowId = _g[1];
68
+ useEffect(function () {
69
+ selectedPage.getRequest().then(function (resArray) {
70
+ setData(resArray);
71
+ });
72
+ }, []);
73
+ useEffect(function () {
74
+ setDisplayData(data.map(function (table_data) {
75
+ return selectedPage.tableFields.map(function (field) { return field.access(table_data); });
76
+ }));
77
+ }, [data]);
78
+ return (_jsxs(_Fragment, { children: [_jsx(Header, { pages: pages, data: data }), _jsx(ThemeProvider, __assign({ theme: createTheme() }, { children: _jsx(MaterialReactTable, { columns: selectedPage.tableFields.map(function (field, index) { return ({
79
+ accessorFn: function (row) { return row[index]; },
80
+ header: field.name,
81
+ }); }), data: displayData, muiTableContainerProps: { sx: { maxHeight: "70vh" } }, enableColumnResizing: true, enableColumnPinning: true, enableGlobalFilterModes: true, enablePagination: true, paginationDisplayMode: "pages", enableRowVirtualization: true, rowVirtualizerOptions: { overscan: 20 }, renderTopToolbarCustomActions: function () { return (_jsx(ChakraProvider, { children: _jsx(Stack, __assign({ margin: 0, padding: 3, direction: "row" }, { children: selectedPage.actions.map(function (action) { return (_jsx(Button, __assign({ colorScheme: "blue", onClick: function () {
82
+ setSelectedAction(action);
83
+ onOpen();
84
+ } }, { children: action.name }))); }) })) })); }, enableRowActions: true, renderRowActionMenuItems: function (obj) {
85
+ return selectedPage.rowActions.map(function (rowAction) { return (_jsx(MenuItem, __assign({ onClick: function () {
86
+ setSelectedAction(rowAction);
87
+ setRowId(obj.row.original[0]);
88
+ onOpen();
89
+ var rowActionsMenu = document.querySelector(".MuiPaper-root.MuiPopover-paper.MuiMenu-paper");
90
+ if (rowActionsMenu) {
91
+ rowActionsMenu.remove();
92
+ }
93
+ } }, { children: rowAction.name + " " + obj.row.original[0] }))); });
94
+ } }) })), _jsxs(Modal, __assign({ size: "6xl", isOpen: isOpen, onClose: onClose }, { children: [_jsx(ModalOverlay, {}), _jsxs(ModalContent, { children: [_jsx(ModalHeader, { children: selectedAction.name }), _jsx(ModalCloseButton, {}), _jsxs(ModalBody, { children: [selectedAction.fields && ((_b = selectedAction.fields) === null || _b === void 0 ? void 0 : _b.length) > 0 ? (_jsx(GenericForm, { action: selectedAction, onClose: onClose, rowId: rowId })) : (_jsx(Button, __assign({ colorScheme: "blue", mr: 3, onClick: function () {
95
+ selectedAction.onSubmit(rowId);
96
+ onClose();
97
+ window.location.reload();
98
+ } }, { children: "Confirm Action" }))), _jsx(Button, __assign({ colorScheme: "red", mr: 3, onClick: onClose }, { children: "Close" }))] })] })] }))] }));
99
+ }
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React from "react";
3
+ import ReactDOM from "react-dom/client";
4
+ import "./index.css";
5
+ import AdminPanel from "./App";
6
+ import reportWebVitals from "./reportWebVitals";
7
+ import { event } from "./pages/event";
8
+ var root = ReactDOM.createRoot(document.getElementById("root"));
9
+ root.render(_jsx(React.StrictMode, { children: _jsx(AdminPanel, { pages: [event] }) }));
10
+ // If you want to start measuring performance in your app, pass a function
11
+ // to log results (for example: reportWebVitals(console.log))
12
+ // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
13
+ reportWebVitals();
@@ -0,0 +1,104 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __generator = (this && this.__generator) || function (thisArg, body) {
11
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
+ function verb(n) { return function (v) { return step([n, v]); }; }
14
+ function step(op) {
15
+ if (f) throw new TypeError("Generator is already executing.");
16
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
+ if (y = 0, t) op = [op[0] & 2, t.value];
19
+ switch (op[0]) {
20
+ case 0: case 1: t = op; break;
21
+ case 4: _.label++; return { value: op[1], done: false };
22
+ case 5: _.label++; y = op[1]; op = [0]; continue;
23
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
+ default:
25
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
+ if (t[2]) _.ops.pop();
30
+ _.trys.pop(); continue;
31
+ }
32
+ op = body.call(thisArg, _);
33
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
+ }
36
+ };
37
+ import React from "react";
38
+ var domain = "http://localhost:3001";
39
+ export var event = {
40
+ name: "Events",
41
+ actions: [],
42
+ rowActions: [],
43
+ getRequest: function () { return __awaiter(void 0, void 0, void 0, function () {
44
+ return __generator(this, function (_a) {
45
+ // const res = await axios.get(domain + "/events");
46
+ // return res.data;
47
+ return [2 /*return*/, []];
48
+ });
49
+ }); },
50
+ tableFields: [
51
+ {
52
+ name: "Id",
53
+ access: function (obj) { return obj.id; },
54
+ },
55
+ {
56
+ name: "Event Name",
57
+ access: function (obj) { return obj.name; },
58
+ },
59
+ {
60
+ name: "Description",
61
+ access: function (obj) { return obj.description; },
62
+ },
63
+ {
64
+ name: "Category",
65
+ access: function (obj) { return obj.category; },
66
+ },
67
+ {
68
+ name: "Ticket Type",
69
+ access: function (obj) { return obj.ticketType; },
70
+ },
71
+ {
72
+ name: "Date",
73
+ access: function (obj) { return obj.date; },
74
+ },
75
+ {
76
+ name: "Release",
77
+ access: function (obj) { return obj.release; },
78
+ },
79
+ {
80
+ name: "Is Released",
81
+ access: function (obj) { return (obj.isReleased ? "Is Released" : "Not Released"); },
82
+ },
83
+ {
84
+ name: "Available Tickets",
85
+ access: function (obj) { return obj.availableTickets; },
86
+ },
87
+ {
88
+ name: "Max Tickets",
89
+ access: function (obj) { return obj.maxTickets; },
90
+ },
91
+ {
92
+ name: "Image",
93
+ access: function (obj) {
94
+ return obj.imgUrl
95
+ ? React.createElement("img", {
96
+ src: obj.imgUrl,
97
+ alt: "ERROR",
98
+ style: { width: "100px" },
99
+ })
100
+ : "No Image Available";
101
+ },
102
+ },
103
+ ],
104
+ };
@@ -0,0 +1,13 @@
1
+ var reportWebVitals = function (onPerfEntry) {
2
+ if (onPerfEntry && onPerfEntry instanceof Function) {
3
+ import("web-vitals").then(function (_a) {
4
+ var getCLS = _a.getCLS, getFID = _a.getFID, getFCP = _a.getFCP, getLCP = _a.getLCP, getTTFB = _a.getTTFB;
5
+ getCLS(onPerfEntry);
6
+ getFID(onPerfEntry);
7
+ getFCP(onPerfEntry);
8
+ getLCP(onPerfEntry);
9
+ getTTFB(onPerfEntry);
10
+ });
11
+ }
12
+ };
13
+ export default reportWebVitals;
@@ -0,0 +1,4 @@
1
+ import { event } from "../pages/event";
2
+ export var pages = [
3
+ event, // example schema
4
+ ];
@@ -0,0 +1,3 @@
1
+ export function pageToUrl(page) {
2
+ return "/".concat(page.name.toLowerCase().replace(" ", "_"));
3
+ }
@@ -0,0 +1,5 @@
1
+ // jest-dom adds custom jest matchers for asserting on DOM nodes.
2
+ // allows you to do things like:
3
+ // expect(element).toHaveTextContent(/react/i)
4
+ // learn more: https://github.com/testing-library/jest-dom
5
+ import "@testing-library/jest-dom";
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "admin_lsac",
3
- "version": "1.1.0",
3
+ "version": "1.1.3",
4
+ "description": "Generic Admin Panel created for storing events' data",
4
5
  "private": false,
5
6
  "dependencies": {
6
7
  "@chakra-ui/react": "^2.5.5",
@@ -65,5 +66,7 @@
65
66
  "ts-loader": "^9.5.1",
66
67
  "webpack-cli": "^5.1.4"
67
68
  },
68
- "main": "dist/App.js"
69
+ "main": "dist/App.js",
70
+ "module": "dist/esm/App.js",
71
+ "types": "dist/App.d.ts"
69
72
  }
package/src/App.tsx CHANGED
@@ -4,24 +4,24 @@ import { Page } from "./components/Page";
4
4
  import { pageToUrl } from "./schema/schema";
5
5
  import * as React from "react";
6
6
 
7
- export interface TableField {
7
+ interface TableField {
8
8
  name: string;
9
9
  access: (obj: any) => string | number | React.ReactElement;
10
10
  }
11
11
 
12
- export interface SimpleField {
12
+ interface SimpleField {
13
13
  name: string;
14
14
  label: string;
15
15
  type: "string" | "number" | "file";
16
16
  validationSchema: any;
17
17
  }
18
18
 
19
- export interface Option {
19
+ interface Option {
20
20
  value: string | number | boolean;
21
21
  display: string;
22
22
  }
23
23
 
24
- export interface DropdownField {
24
+ interface DropdownField {
25
25
  name: string;
26
26
  label: string;
27
27
  type: "dropdown";
@@ -29,36 +29,36 @@ export interface DropdownField {
29
29
  getOptions: () => Promise<Option[]>;
30
30
  }
31
31
 
32
- export interface ObjectField {
32
+ interface ObjectField {
33
33
  name: string;
34
34
  label: string;
35
35
  type: "object";
36
36
  fields: FormField[];
37
37
  }
38
38
 
39
- export interface ArrayField {
39
+ interface ArrayField {
40
40
  name: string;
41
41
  label: string;
42
42
  type: "array";
43
43
  element: Exclude<FormField, ArrayField>;
44
44
  }
45
45
 
46
- export type FormField = SimpleField | DropdownField | ObjectField | ArrayField;
46
+ type FormField = SimpleField | DropdownField | ObjectField | ArrayField;
47
47
 
48
- export interface Action {
48
+ interface Action {
49
49
  name: string;
50
50
  fields?: FormField[];
51
51
  onSubmit: (obj1: any, obj2?: any) => Promise<any>;
52
52
  }
53
53
 
54
- export interface RowAction {
54
+ interface RowAction {
55
55
  name: string;
56
56
  fields?: FormField[];
57
57
  initialise?: (obj: any) => any;
58
58
  onSubmit: (obj1: any, obj2?: any) => Promise<any>;
59
59
  }
60
60
 
61
- export interface PageSchema {
61
+ interface PageSchema {
62
62
  name: string;
63
63
  actions: Action[];
64
64
  rowActions: RowAction[];