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 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
@@ -0,0 +1,5 @@
1
+ import { type RouteConfig, route } from "@react-router/dev/routes";
2
+
3
+ export default [
4
+ route("admin/*", "./wrapper.tsx")
5
+ ] satisfies RouteConfig;
@@ -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,2 @@
1
+ import type { EntryContext } from "react-router";
2
+ export default function handleRequest(request: Request, responseStatusCode: number, responseHeaders: Headers, routerContext: EntryContext): Response;
@@ -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,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Outlet } from "react-router";
3
+ export default function Root() {
4
+ return _jsx(Outlet, {});
5
+ }
@@ -0,0 +1,2 @@
1
+ declare const _default: import("@react-router/dev/routes").RouteConfigEntry[];
2
+ export default _default;
@@ -0,0 +1,4 @@
1
+ import { route } from "@react-router/dev/routes";
2
+ export default [
3
+ route("admin/*", "./wrapper.tsx")
4
+ ];
@@ -0,0 +1,2 @@
1
+ declare function AdminWrapper(): import("react/jsx-runtime").JSX.Element;
2
+ export default AdminWrapper;
@@ -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;
@@ -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.32",
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-dom": "^6.24.0",
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",