admin_lsac 2.0.32 → 2.0.33
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 +150 -0
- package/app/routes.ts +5 -0
- package/app/wrapper.tsx +26 -0
- package/dist/esm/app/entry.client.d.ts +1 -0
- package/dist/esm/app/entry.client.js +6 -0
- package/dist/esm/app/entry.server.d.ts +2 -0
- package/dist/esm/app/entry.server.js +11 -0
- package/dist/esm/app/root.d.ts +1 -0
- package/dist/esm/app/root.js +5 -0
- package/dist/esm/app/routes.d.ts +2 -0
- package/dist/esm/app/routes.js +4 -0
- package/dist/esm/app/wrapper.d.ts +2 -0
- package/dist/esm/app/wrapper.js +15 -0
- package/dist/esm/src/App.js +39 -1
- package/dist/esm/src/entry.client.d.ts +1 -0
- package/dist/esm/src/entry.client.js +6 -0
- package/package.json +9 -2
package/README.md
CHANGED
|
@@ -56,6 +56,156 @@ You will need to create an array of schemas (if more than one schema) for your o
|
|
|
56
56
|
) : null}
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
+
## More info
|
|
60
|
+
|
|
61
|
+
<details>
|
|
62
|
+
<summary>Declarative Mode (Standard SPA)</summary>
|
|
63
|
+
|
|
64
|
+
## Declarative Mode (Standard SPA)
|
|
65
|
+
|
|
66
|
+
This mode represents the classic Single Page Application (SPA) approach, using standard JSX components to define the routing context. It is the most straightforward way to integrate the admin panel into an existing React application.
|
|
67
|
+
|
|
68
|
+
### How to Implement
|
|
69
|
+
|
|
70
|
+
To set up the Declarative Mode, you must wrap your component tree (or just the admin section) inside a `<BrowserRouter>`. The `AdminPage` component requires four main props to function correctly:
|
|
71
|
+
|
|
72
|
+
- `pages`: An array of your data schemas.
|
|
73
|
+
- `selectedPage`: The specific schema object to render.
|
|
74
|
+
- `basePath`: The URL prefix where the admin panel will reside (e.g., `/admin`).
|
|
75
|
+
- `apiURL`: The base URL of your backend API.
|
|
76
|
+
|
|
77
|
+
The `AdminPage` will automatically handle internal navigation and path matching based on these props.
|
|
78
|
+
|
|
79
|
+
### Implementation Example
|
|
80
|
+
|
|
81
|
+
Below is a minimal setup showing how to wrap the `AdminPage` and pass the required configuration:
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
import { BrowserRouter } from 'react-router';
|
|
85
|
+
import { AdminPage } from 'admin_lsac';
|
|
86
|
+
// Import your defined schemas
|
|
87
|
+
import { coursesPage } from './testSchemas/course';
|
|
88
|
+
|
|
89
|
+
export default function App() {
|
|
90
|
+
return (
|
|
91
|
+
<BrowserRouter>
|
|
92
|
+
<AdminPage
|
|
93
|
+
apiURL="http://localhost:3001/"
|
|
94
|
+
basePath="/admin"
|
|
95
|
+
pages="{[coursesPage]}"
|
|
96
|
+
selectedPage="{coursesPage}"
|
|
97
|
+
/>
|
|
98
|
+
</BrowserRouter>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
</details>
|
|
104
|
+
|
|
105
|
+
<details>
|
|
106
|
+
<summary>Data Mode (Data Router)</summary>
|
|
107
|
+
|
|
108
|
+
## Data Mode (Data Router)
|
|
109
|
+
|
|
110
|
+
This mode utilizes an object-based routing configuration rather than a declarative JSX component tree. It is the recommended approach for modern React applications, as it decouples the route definitions from the UI, enabling advanced data fetching and performance optimizations.
|
|
111
|
+
|
|
112
|
+
### How to Implement
|
|
113
|
+
|
|
114
|
+
To implement Data Mode, you will transition away from `<BrowserRouter>`. Instead, you define your routes as an array of objects using the `createBrowserRouter` function. This router instance is then passed to a `<RouterProvider>` component at the root of your application.
|
|
115
|
+
|
|
116
|
+
The `AdminPage` must be assigned to the `element` property of a route object. It is crucial to append a wildcard (`*`) to the `path` string (e.g., `/admin/*`) so the admin panel can successfully catch and manage its own internal sub-routes.
|
|
117
|
+
|
|
118
|
+
### Implementation Example
|
|
119
|
+
|
|
120
|
+
Below is the standard setup for integrating the admin panel using the Data Router approach:
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
import { createBrowserRouter, RouterProvider } from 'react-router';
|
|
124
|
+
import { AdminPage } from 'admin_lsac';
|
|
125
|
+
// Import your defined schemas
|
|
126
|
+
import { coursesPage } from './testSchemas/course';
|
|
127
|
+
|
|
128
|
+
const router = createBrowserRouter([
|
|
129
|
+
{
|
|
130
|
+
path: '/admin/*', // The wildcard (*) is required for internal navigation
|
|
131
|
+
element: (
|
|
132
|
+
<AdminPage
|
|
133
|
+
apiURL="http://localhost:3001/"
|
|
134
|
+
basePath="/admin"
|
|
135
|
+
pages="{[coursesPage]}"
|
|
136
|
+
selectedPage="{coursesPage}"
|
|
137
|
+
/>
|
|
138
|
+
),
|
|
139
|
+
},
|
|
140
|
+
]);
|
|
141
|
+
|
|
142
|
+
export default function App() {
|
|
143
|
+
// Provide the router configuration to the application
|
|
144
|
+
return <RouterProvider router="{router}" />;
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
</details>
|
|
149
|
+
|
|
150
|
+
<details>
|
|
151
|
+
<summary>Framework Mode (Vite Plugin / App Directory)</summary>
|
|
152
|
+
|
|
153
|
+
## Framework Mode (Vite Plugin / App Directory)
|
|
154
|
+
|
|
155
|
+
This mode is used when your project takes advantage of React Router v7's framework capabilities, utilizing the Vite plugin and file-based routing within an `app/` directory.
|
|
156
|
+
|
|
157
|
+
### How to Implement
|
|
158
|
+
|
|
159
|
+
To integrate the admin panel in Framework Mode, you need to configure file-based routing. You achieve this by defining a wildcard route in your route configuration file (`routes.ts`) that delegates traffic to a dedicated wrapper component.
|
|
160
|
+
|
|
161
|
+
The wrapper component is responsible for extracting the dynamic URL parameters (using the `useParams` hook) and determining which schema to render before returning the `AdminPage` component.
|
|
162
|
+
|
|
163
|
+
### Implementation Example
|
|
164
|
+
|
|
165
|
+
Below are the two files required to set up the Framework Mode:
|
|
166
|
+
|
|
167
|
+
**1. Define the Route Configuration (`app/routes.ts`)**
|
|
168
|
+
Map the base path followed by a wildcard (`*`) directly to your wrapper component.
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
import { type RouteConfig, route } from '@react-router/dev/routes';
|
|
172
|
+
|
|
173
|
+
export default [route('admin/*', './wrapper.tsx')] satisfies RouteConfig;
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**2. Create the Wrapper Component (`app/wrapper.tsx`)**
|
|
177
|
+
This component handles the logic for matching the URL to your data schema.
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
import { useParams } from 'react-router';
|
|
181
|
+
import { AdminPage, pageToUrl } from 'admin_lsac';
|
|
182
|
+
// Import your defined schemas
|
|
183
|
+
import { coursesPage } from '../src/testSchemas/course';
|
|
184
|
+
|
|
185
|
+
export default function AdminWrapper() {
|
|
186
|
+
const params = useParams();
|
|
187
|
+
const splitPath = params['*'];
|
|
188
|
+
|
|
189
|
+
const pages = [coursesPage];
|
|
190
|
+
const basePath = '/admin';
|
|
191
|
+
|
|
192
|
+
// Dynamically resolve the selected page or fallback to the first one
|
|
193
|
+
const selectedPage = pages.find((page) => pageToUrl(page) === splitPath);
|
|
194
|
+
const currentPage = selectedPage || pages[0];
|
|
195
|
+
|
|
196
|
+
return (
|
|
197
|
+
<AdminPage
|
|
198
|
+
pages={pages}
|
|
199
|
+
selectedPage={currentPage}
|
|
200
|
+
basePath={basePath}
|
|
201
|
+
apiURL="http://localhost:3001/"
|
|
202
|
+
/>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
</details>
|
|
208
|
+
|
|
59
209
|
## What is a schema?
|
|
60
210
|
|
|
61
211
|
```
|
package/app/routes.ts
ADDED
package/app/wrapper.tsx
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useParams } from "react-router";
|
|
2
|
+
import { AdminPage, pageToUrl } from "../src/components/AdminPage";
|
|
3
|
+
import { coursesPage } from "../src/testSchemas/course";
|
|
4
|
+
|
|
5
|
+
// React Router v7 - Framework Mode
|
|
6
|
+
function AdminWrapper() {
|
|
7
|
+
const params = useParams();
|
|
8
|
+
const splitPath = params["*"];
|
|
9
|
+
|
|
10
|
+
const pages = [coursesPage];
|
|
11
|
+
const basePath = "/admin";
|
|
12
|
+
|
|
13
|
+
const selectedPage = pages.find((page) => pageToUrl(page) === splitPath);
|
|
14
|
+
const currentPage = selectedPage || pages[0];
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<AdminPage
|
|
18
|
+
pages={pages}
|
|
19
|
+
selectedPage={currentPage}
|
|
20
|
+
basePath={basePath}
|
|
21
|
+
apiURL="http://localhost:3001/"
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default AdminWrapper;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "../src/index.css";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import ReactDOM from "react-dom/client";
|
|
4
|
+
import { HydratedRouter } from "react-router/dom";
|
|
5
|
+
import "../src/index.css";
|
|
6
|
+
ReactDOM.hydrateRoot(document, _jsx(React.StrictMode, { children: _jsx(HydratedRouter, {}) }));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { renderToString } from "react-dom/server";
|
|
3
|
+
import { ServerRouter } from "react-router";
|
|
4
|
+
export default function handleRequest(request, responseStatusCode, responseHeaders, routerContext) {
|
|
5
|
+
const markup = renderToString(_jsx(ServerRouter, { context: routerContext, url: request.url }));
|
|
6
|
+
responseHeaders.set("Content-Type", "text/html");
|
|
7
|
+
return new Response(`<!DOCTYPE html>${markup}`, {
|
|
8
|
+
status: responseStatusCode,
|
|
9
|
+
headers: responseHeaders,
|
|
10
|
+
});
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function Root(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useParams } from "react-router";
|
|
3
|
+
import { AdminPage, pageToUrl } from "../src/components/AdminPage";
|
|
4
|
+
import { coursesPage } from "../src/testSchemas/course";
|
|
5
|
+
// React Router v7 - Framework Mode
|
|
6
|
+
function AdminWrapper() {
|
|
7
|
+
const params = useParams();
|
|
8
|
+
const splitPath = params["*"];
|
|
9
|
+
const pages = [coursesPage];
|
|
10
|
+
const basePath = "/admin";
|
|
11
|
+
const selectedPage = pages.find((page) => pageToUrl(page) === splitPath);
|
|
12
|
+
const currentPage = selectedPage || pages[0];
|
|
13
|
+
return (_jsx(AdminPage, { pages: pages, selectedPage: currentPage, basePath: basePath, apiURL: "http://localhost:3001/" }));
|
|
14
|
+
}
|
|
15
|
+
export default AdminWrapper;
|
package/dist/esm/src/App.js
CHANGED
|
@@ -1,8 +1,46 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { BrowserRouter, Route, Routes } from 'react-router-dom';
|
|
3
2
|
import { AdminPage } from './components/AdminPage';
|
|
4
3
|
import { pageToUrl } from './components/AdminPage';
|
|
5
4
|
import './App.css';
|
|
5
|
+
// React Router v7 - Data Mode
|
|
6
|
+
/*
|
|
7
|
+
import { createBrowserRouter, RouterProvider } from "react-router";
|
|
8
|
+
|
|
9
|
+
function AppDataMode({ pages, basePath }: { pages: PageSchema[]; basePath: string }) {
|
|
10
|
+
const dataRouter = createBrowserRouter([
|
|
11
|
+
...pages.map((page) => (
|
|
12
|
+
{
|
|
13
|
+
path: `${basePath}/${pageToUrl(page)}`,
|
|
14
|
+
element:
|
|
15
|
+
<AdminPage
|
|
16
|
+
pages={pages}
|
|
17
|
+
selectedPage={page}
|
|
18
|
+
basePath={basePath}
|
|
19
|
+
apiURL="http://localhost:3001/"
|
|
20
|
+
/>
|
|
21
|
+
}
|
|
22
|
+
)),
|
|
23
|
+
|
|
24
|
+
{
|
|
25
|
+
path: `${basePath}/*`,
|
|
26
|
+
element: pages[0] ? (
|
|
27
|
+
<AdminPage
|
|
28
|
+
pages={pages}
|
|
29
|
+
selectedPage={pages[0]}
|
|
30
|
+
basePath={basePath}
|
|
31
|
+
apiURL="http://localhost:3001/"
|
|
32
|
+
/>
|
|
33
|
+
) : null
|
|
34
|
+
}
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
return <RouterProvider router={dataRouter}/>
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default AppDataMode;
|
|
41
|
+
*/
|
|
42
|
+
// React Router v7 - Declarative Mode
|
|
43
|
+
import { BrowserRouter, Route, Routes } from 'react-router';
|
|
6
44
|
function App({ pages, basePath }) {
|
|
7
45
|
return (_jsx(BrowserRouter, { children: _jsxs(Routes, { children: [pages.map((page, index) => (_jsx(Route, { path: `${basePath}/${pageToUrl(page)}`, element: _jsx(AdminPage, { pages: pages, selectedPage: page, basePath: basePath, apiURL: "http://localhost:3001/" }) }, index))), pages[0] ? (_jsx(Route, { path: `${basePath}/*`, element: _jsx(AdminPage, { pages: pages, selectedPage: pages[0], basePath: basePath, apiURL: "http://localhost:3001/" }) })) : null] }) }));
|
|
8
46
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "./index.css";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import ReactDOM from "react-dom/client";
|
|
4
|
+
import { HydratedRouter } from "react-router/dom";
|
|
5
|
+
import "./index.css";
|
|
6
|
+
ReactDOM.hydrateRoot(document, _jsx(React.StrictMode, { children: _jsx(HydratedRouter, {}) }));
|
package/package.json
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "admin_lsac",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.33",
|
|
5
5
|
"description": "Generic Admin Panel created for storing events' data",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/LSAC-ONG/Generic-Admin.git",
|
|
9
|
+
"directory": "admin"
|
|
10
|
+
},
|
|
6
11
|
"scripts": {
|
|
7
12
|
"dev": "vite",
|
|
8
13
|
"build": "tsc -b && vite build",
|
|
@@ -29,12 +34,14 @@
|
|
|
29
34
|
"material-react-table": "^2.13.0",
|
|
30
35
|
"react": "^18.3.1",
|
|
31
36
|
"react-dom": "^18.3.1",
|
|
32
|
-
"react-router
|
|
37
|
+
"react-router": "^7.18.0",
|
|
38
|
+
"react-router-dom": "^7.18.0",
|
|
33
39
|
"socket.io-client": "^4.7.5",
|
|
34
40
|
"sweetalert2": "^11.12.0",
|
|
35
41
|
"yup": "^1.4.0"
|
|
36
42
|
},
|
|
37
43
|
"devDependencies": {
|
|
44
|
+
"@react-router/dev": "^7.18.0",
|
|
38
45
|
"@types/react": "^18.3.3",
|
|
39
46
|
"@types/react-dom": "^18.3.0",
|
|
40
47
|
"@typescript-eslint/eslint-plugin": "^7.13.1",
|