admin_lsac 1.2.3 → 1.2.4

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.
@@ -1,209 +1,219 @@
1
- import { useEffect, useState } from "react";
2
- import { ChakraProvider } from "@chakra-ui/react";
3
- import { PageSchema, Action, pageToUrl } from "../schema/schema";
4
- import {
5
- Button,
6
- Modal,
7
- ModalHeader,
8
- ModalBody,
9
- useDisclosure,
10
- ModalOverlay,
11
- ModalContent,
12
- ModalCloseButton,
13
- Box,
14
- Stack,
15
- } from "@chakra-ui/react";
16
- import { GenericForm } from "./GenericForm";
17
- import { useNavigate } from "react-router";
18
- import { ThemeProvider } from "@emotion/react";
19
- import { createTheme } from "@mui/material/styles";
20
- import { MaterialReactTable } from "material-react-table";
21
- import { mkConfig, generateCsv, download } from "export-to-csv";
22
- import Swal from "sweetalert2";
23
- import MenuItem from "@mui/material/MenuItem";
24
-
25
- function Header({ pages, data, basePath }: { pages: PageSchema[]; data: any[], basePath: string }) {
26
- const nav = useNavigate();
27
- return (
28
- <Box background="blue.50" padding={1}>
29
- <Stack
30
- margin={3}
31
- direction="row"
32
- justifyContent="space-between"
33
- alignItems="center"
34
- >
35
- <Stack margin={4} gap={10} direction="row" alignItems="center">
36
- {pages.map((p) => (
37
- <Box as="a" href={`${basePath}/${pageToUrl(p)}`}>
38
- {p.name}
39
- </Box>
40
- ))}
41
- </Stack>
42
- <Stack direction="row">
43
- <Button
44
- colorScheme="red"
45
- onClick={() => {
46
- const filename = prompt("Enter filename:");
47
- if (filename) exportToCSV(data, filename);
48
- }}
49
- >
50
- Export Data
51
- </Button>
52
- </Stack>
53
- </Stack>
54
- </Box>
55
- );
56
- }
57
-
58
- function exportToCSV(data: any[], filename: string) {
59
- const formatImageData = (obj: any) => {
60
- const formattedObj: any = {};
61
- for (const key in obj) {
62
- if (typeof obj[key] !== "object") {
63
- formattedObj[key] = obj[key];
64
- }
65
- }
66
- return formattedObj;
67
- };
68
-
69
- const formattedData = data.map(formatImageData);
70
-
71
- const csvConfig = mkConfig({
72
- useKeysAsHeaders: true,
73
- filename: filename,
74
- });
75
-
76
- if (formattedData.length > 0) {
77
- const csv = generateCsv(csvConfig)(formattedData);
78
- download(csvConfig)(csv);
79
- } else {
80
- Swal.fire({
81
- title: "Error while exporting CSV!",
82
- text: "There is no data to export.",
83
- });
84
- }
85
- }
86
-
87
- export function Page({
88
- pages,
89
- selectedPage,
90
- basePath
91
- }: {
92
- pages: PageSchema[];
93
- selectedPage: PageSchema;
94
- basePath: string;
95
- }) {
96
- const { isOpen, onOpen, onClose } = useDisclosure();
97
- const [selectedAction, setSelectedAction] = useState({} as Action);
98
- const [data, setData] = useState<any[]>([]);
99
- const [displayData, setDisplayData] = useState<any[][]>([]);
100
- const [rowId, setRowId] = useState<number>();
101
-
102
- useEffect(() => {
103
- selectedPage.getRequest().then((resArray) => {
104
- setData(resArray);
105
- });
106
- }, []);
107
-
108
- useEffect(() => {
109
- setDisplayData(
110
- data.map((table_data) =>
111
- selectedPage.tableFields.map((field) => field.access(table_data))
112
- )
113
- );
114
- }, [data]);
115
-
116
- return (
117
- <>
118
- <Header pages={pages} data={data} basePath={basePath} />
119
-
120
- <ThemeProvider theme={createTheme()}>
121
- <MaterialReactTable
122
- columns={selectedPage.tableFields.map((field, index) => ({
123
- accessorFn: (row: any) => row[index],
124
- header: field.name,
125
- }))}
126
- data={displayData}
127
- muiTableContainerProps={{ sx: { maxHeight: "70vh" } }}
128
- enableColumnResizing
129
- enableColumnPinning
130
- enableGlobalFilterModes
131
- enablePagination={true}
132
- paginationDisplayMode="pages"
133
- enableRowVirtualization
134
- rowVirtualizerOptions={{ overscan: 20 }}
135
- renderTopToolbarCustomActions={() => (
136
- <ChakraProvider>
137
- <Stack margin={0} padding={3} direction="row">
138
- {selectedPage.actions.map((action) => (
139
- <Button
140
- colorScheme="blue"
141
- onClick={() => {
142
- setSelectedAction(action);
143
- onOpen();
144
- }}
145
- >
146
- {action.name}
147
- </Button>
148
- ))}
149
- </Stack>
150
- </ChakraProvider>
151
- )}
152
- enableRowActions
153
- renderRowActionMenuItems={(obj: any) => {
154
- return selectedPage.rowActions.map((rowAction) => (
155
- <MenuItem
156
- onClick={() => {
157
- setSelectedAction(rowAction);
158
- setRowId(obj.row.original[0]);
159
- onOpen();
160
-
161
- const rowActionsMenu = document.querySelector(
162
- ".MuiPaper-root.MuiPopover-paper.MuiMenu-paper"
163
- );
164
- if (rowActionsMenu) {
165
- rowActionsMenu.remove();
166
- }
167
- }}
168
- >
169
- {rowAction.name + " " + obj.row.original[0]}
170
- </MenuItem>
171
- ));
172
- }}
173
- />
174
- </ThemeProvider>
175
-
176
- <Modal size={"6xl"} isOpen={isOpen} onClose={onClose}>
177
- <ModalOverlay />
178
- <ModalContent>
179
- <ModalHeader>{selectedAction.name}</ModalHeader>
180
- <ModalCloseButton />
181
- <ModalBody>
182
- {selectedAction.fields && selectedAction.fields?.length > 0 ? (
183
- <GenericForm
184
- action={selectedAction}
185
- onClose={onClose}
186
- rowId={rowId}
187
- />
188
- ) : (
189
- <Button
190
- colorScheme="blue"
191
- mr={3}
192
- onClick={() => {
193
- selectedAction.onSubmit(rowId);
194
- onClose();
195
- window.location.reload();
196
- }}
197
- >
198
- Confirm Action
199
- </Button>
200
- )}
201
- <Button colorScheme="red" mr={3} onClick={onClose}>
202
- Close
203
- </Button>
204
- </ModalBody>
205
- </ModalContent>
206
- </Modal>
207
- </>
208
- );
209
- }
1
+ import { useEffect, useState } from "react";
2
+ import { ChakraProvider } from "@chakra-ui/react";
3
+ import { PageSchema, Action, pageToUrl } from "../schema/schema";
4
+ import {
5
+ Button,
6
+ Modal,
7
+ ModalHeader,
8
+ ModalBody,
9
+ useDisclosure,
10
+ ModalOverlay,
11
+ ModalContent,
12
+ ModalCloseButton,
13
+ Box,
14
+ Stack,
15
+ } from "@chakra-ui/react";
16
+ import { GenericForm } from "./GenericForm";
17
+ import { ThemeProvider } from "@emotion/react";
18
+ import { createTheme } from "@mui/material/styles";
19
+ import { MaterialReactTable } from "material-react-table";
20
+ import { mkConfig, generateCsv, download } from "export-to-csv";
21
+ import Swal from "sweetalert2";
22
+ import MenuItem from "@mui/material/MenuItem";
23
+
24
+ function Header({
25
+ pages,
26
+ data,
27
+ basePath,
28
+ }: {
29
+ pages: PageSchema[];
30
+ data: any[];
31
+ basePath: string;
32
+ }) {
33
+ return (
34
+ <Box background="blue.50" padding={1}>
35
+ <Stack
36
+ margin={3}
37
+ direction="row"
38
+ justifyContent="space-between"
39
+ alignItems="center"
40
+ >
41
+ <Stack margin={4} gap={10} direction="row" alignItems="center">
42
+ {pages.map((p) => (
43
+ <Box as="a" href={`${basePath}/${pageToUrl(p)}`}>
44
+ {p.name}
45
+ </Box>
46
+ ))}
47
+ </Stack>
48
+ <Stack direction="row">
49
+ <Button
50
+ colorScheme="red"
51
+ onClick={() => {
52
+ const filename = prompt("Enter filename:");
53
+ if (filename) exportToCSV(data, filename);
54
+ }}
55
+ >
56
+ Export Data
57
+ </Button>
58
+ </Stack>
59
+ </Stack>
60
+ </Box>
61
+ );
62
+ }
63
+
64
+ function exportToCSV(data: any[], filename: string) {
65
+ const formatImageData = (obj: any) => {
66
+ const formattedObj: any = {};
67
+ for (const key in obj) {
68
+ if (typeof obj[key] !== "object") {
69
+ formattedObj[key] = obj[key];
70
+ } else if (typeof obj[key] === "object" && obj[key] != null) {
71
+ Object.keys(obj[key]).forEach((k: any) => {
72
+ formattedObj[`${key}.${k}`] = obj[key][k];
73
+ });
74
+ }
75
+ }
76
+ return formattedObj;
77
+ };
78
+
79
+ const formattedData = data.map(formatImageData);
80
+
81
+ const csvConfig = mkConfig({
82
+ useKeysAsHeaders: true,
83
+ filename: filename,
84
+ });
85
+
86
+ if (formattedData.length > 0) {
87
+ const csv = generateCsv(csvConfig)(formattedData);
88
+ download(csvConfig)(csv);
89
+ } else {
90
+ Swal.fire({
91
+ title: "Error while exporting CSV!",
92
+ text: "There is no data to export.",
93
+ });
94
+ }
95
+ }
96
+
97
+ export function AdminPage({
98
+ pages,
99
+ selectedPage,
100
+ basePath,
101
+ }: {
102
+ pages: PageSchema[];
103
+ selectedPage: PageSchema;
104
+ basePath: string;
105
+ }) {
106
+ const { isOpen, onOpen, onClose } = useDisclosure();
107
+ const [selectedAction, setSelectedAction] = useState({} as Action);
108
+ const [data, setData] = useState<any[]>([]);
109
+ const [displayData, setDisplayData] = useState<any[][]>([]);
110
+ const [rowId, setRowId] = useState<number>();
111
+
112
+ useEffect(() => {
113
+ selectedPage.getRequest().then((resArray) => {
114
+ setData(resArray);
115
+ });
116
+ }, []);
117
+
118
+ useEffect(() => {
119
+ setDisplayData(
120
+ data.map((table_data) =>
121
+ selectedPage.tableFields.map((field) => field.access(table_data))
122
+ )
123
+ );
124
+ }, [data]);
125
+
126
+ return (
127
+ <>
128
+ <Header pages={pages} data={data} basePath={basePath} />
129
+
130
+ <ThemeProvider theme={createTheme()}>
131
+ <MaterialReactTable
132
+ columns={selectedPage.tableFields.map((field, index) => ({
133
+ accessorFn: (row: any) => row[index],
134
+ header: field.name,
135
+ }))}
136
+ data={displayData}
137
+ muiTableContainerProps={{ sx: { maxHeight: "70vh" } }}
138
+ enableColumnResizing
139
+ enableColumnPinning
140
+ enableGlobalFilterModes
141
+ enablePagination={true}
142
+ paginationDisplayMode="pages"
143
+ enableRowVirtualization
144
+ rowVirtualizerOptions={{ overscan: 20 }}
145
+ renderTopToolbarCustomActions={() => (
146
+ <ChakraProvider>
147
+ <Stack margin={0} padding={3} direction="row">
148
+ {selectedPage.actions.map((action) => (
149
+ <Button
150
+ colorScheme="blue"
151
+ onClick={() => {
152
+ setSelectedAction(action);
153
+ onOpen();
154
+ }}
155
+ >
156
+ {action.name}
157
+ </Button>
158
+ ))}
159
+ </Stack>
160
+ </ChakraProvider>
161
+ )}
162
+ enableRowActions
163
+ renderRowActionMenuItems={(obj: any) => {
164
+ return selectedPage.rowActions.map((rowAction) => (
165
+ <MenuItem
166
+ onClick={() => {
167
+ setSelectedAction(rowAction);
168
+ setRowId(obj.row.original[0]);
169
+ onOpen();
170
+
171
+ const rowActionsMenu = document.querySelector(
172
+ ".MuiPaper-root.MuiPopover-paper.MuiMenu-paper"
173
+ );
174
+ if (rowActionsMenu) {
175
+ rowActionsMenu.remove();
176
+ }
177
+ }}
178
+ >
179
+ {rowAction.name + " " + obj.row.original[0]}
180
+ </MenuItem>
181
+ ));
182
+ }}
183
+ />
184
+ </ThemeProvider>
185
+
186
+ <Modal size={"6xl"} isOpen={isOpen} onClose={onClose}>
187
+ <ModalOverlay />
188
+ <ModalContent>
189
+ <ModalHeader>{selectedAction.name}</ModalHeader>
190
+ <ModalCloseButton />
191
+ <ModalBody>
192
+ {selectedAction.fields && selectedAction.fields?.length > 0 ? (
193
+ <GenericForm
194
+ action={selectedAction}
195
+ onClose={onClose}
196
+ rowId={rowId}
197
+ />
198
+ ) : (
199
+ <Button
200
+ colorScheme="blue"
201
+ mr={3}
202
+ onClick={() => {
203
+ selectedAction.onSubmit(rowId);
204
+ onClose();
205
+ window.location.reload();
206
+ }}
207
+ >
208
+ Confirm Action
209
+ </Button>
210
+ )}
211
+ <Button colorScheme="red" mr={3} onClick={onClose}>
212
+ Close
213
+ </Button>
214
+ </ModalBody>
215
+ </ModalContent>
216
+ </Modal>
217
+ </>
218
+ );
219
+ }
package/src/index.tsx CHANGED
@@ -1,20 +1,20 @@
1
- import React from "react";
2
- import ReactDOM from "react-dom/client";
3
- import "./index.css";
4
- import AdminPanel from "./App";
5
- import reportWebVitals from "./reportWebVitals";
6
- import { event } from "./pages/event";
7
-
8
- const root = ReactDOM.createRoot(
9
- document.getElementById("root") as HTMLElement
10
- );
11
- root.render(
12
- <React.StrictMode>
13
- <AdminPanel pages={[event]} basePath="" />
14
- </React.StrictMode>
15
- );
16
-
17
- // If you want to start measuring performance in your app, pass a function
18
- // to log results (for example: reportWebVitals(console.log))
19
- // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
20
- reportWebVitals();
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import "./index.css";
4
+ import AdminPanel from "./App";
5
+ import reportWebVitals from "./reportWebVitals";
6
+ import { event } from "./pages/event";
7
+
8
+ const root = ReactDOM.createRoot(
9
+ document.getElementById("root") as HTMLElement
10
+ );
11
+ root.render(
12
+ <React.StrictMode>
13
+ <AdminPanel pages={[event]} basePath="" />
14
+ </React.StrictMode>
15
+ );
16
+
17
+ // If you want to start measuring performance in your app, pass a function
18
+ // to log results (for example: reportWebVitals(console.log))
19
+ // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
20
+ reportWebVitals();
@@ -1,69 +1,69 @@
1
- import axios from "axios";
2
- import React from "react";
3
- import { PageSchema } from "../schema/schema";
4
-
5
- const domain = "http://localhost:3001";
6
-
7
- export const event: PageSchema = {
8
- name: "Events",
9
- actions: [],
10
- rowActions: [],
11
- getRequest: async () => {
12
- // const res = await axios.get(domain + "/events");
13
- // return res.data;
14
- return [];
15
- },
16
- tableFields: [
17
- {
18
- name: "Id",
19
- access: (obj: any) => obj.id,
20
- },
21
- {
22
- name: "Event Name",
23
- access: (obj: any) => obj.name,
24
- },
25
- {
26
- name: "Description",
27
- access: (obj: any) => obj.description,
28
- },
29
- {
30
- name: "Category",
31
- access: (obj: any) => obj.category,
32
- },
33
- {
34
- name: "Ticket Type",
35
- access: (obj: any) => obj.ticketType,
36
- },
37
- {
38
- name: "Date",
39
- access: (obj: any) => obj.date,
40
- },
41
- {
42
- name: "Release",
43
- access: (obj: any) => obj.release,
44
- },
45
- {
46
- name: "Is Released",
47
- access: (obj: any) => (obj.isReleased ? "Is Released" : "Not Released"),
48
- },
49
- {
50
- name: "Available Tickets",
51
- access: (obj: any) => obj.availableTickets,
52
- },
53
- {
54
- name: "Max Tickets",
55
- access: (obj: any) => obj.maxTickets,
56
- },
57
- {
58
- name: "Image",
59
- access: (obj: any) =>
60
- obj.imgUrl
61
- ? React.createElement("img", {
62
- src: obj.imgUrl,
63
- alt: "ERROR",
64
- style: { width: "100px" },
65
- })
66
- : "No Image Available",
67
- },
68
- ],
69
- };
1
+ import axios from "axios";
2
+ import React from "react";
3
+ import { PageSchema } from "../schema/schema";
4
+
5
+ const domain = "http://localhost:3001";
6
+
7
+ export const event: PageSchema = {
8
+ name: "Events",
9
+ actions: [],
10
+ rowActions: [],
11
+ getRequest: async () => {
12
+ // const res = await axios.get(domain + "/events");
13
+ // return res.data;
14
+ return [];
15
+ },
16
+ tableFields: [
17
+ {
18
+ name: "Id",
19
+ access: (obj: any) => obj.id,
20
+ },
21
+ {
22
+ name: "Event Name",
23
+ access: (obj: any) => obj.name,
24
+ },
25
+ {
26
+ name: "Description",
27
+ access: (obj: any) => obj.description,
28
+ },
29
+ {
30
+ name: "Category",
31
+ access: (obj: any) => obj.category,
32
+ },
33
+ {
34
+ name: "Ticket Type",
35
+ access: (obj: any) => obj.ticketType,
36
+ },
37
+ {
38
+ name: "Date",
39
+ access: (obj: any) => obj.date,
40
+ },
41
+ {
42
+ name: "Release",
43
+ access: (obj: any) => obj.release,
44
+ },
45
+ {
46
+ name: "Is Released",
47
+ access: (obj: any) => (obj.isReleased ? "Is Released" : "Not Released"),
48
+ },
49
+ {
50
+ name: "Available Tickets",
51
+ access: (obj: any) => obj.availableTickets,
52
+ },
53
+ {
54
+ name: "Max Tickets",
55
+ access: (obj: any) => obj.maxTickets,
56
+ },
57
+ {
58
+ name: "Image",
59
+ access: (obj: any) =>
60
+ obj.imgUrl
61
+ ? React.createElement("img", {
62
+ src: obj.imgUrl,
63
+ alt: "ERROR",
64
+ style: { width: "100px" },
65
+ })
66
+ : "No Image Available",
67
+ },
68
+ ],
69
+ };