@sonicjs-cms/core 2.0.8 → 2.0.10
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 +1 -1
- package/dist/{chunk-CHMO2DOC.cjs → chunk-3PHG75W4.cjs} +3 -3
- package/dist/chunk-3PHG75W4.cjs.map +1 -0
- package/dist/chunk-6FR25MPC.js.map +1 -1
- package/dist/{chunk-KHNSPJ6X.cjs → chunk-CAP6QQR2.cjs} +5 -5
- package/dist/{chunk-KHNSPJ6X.cjs.map → chunk-CAP6QQR2.cjs.map} +1 -1
- package/dist/{chunk-4MBTSUI6.js → chunk-COBUPOMD.js} +22 -6
- package/dist/chunk-COBUPOMD.js.map +1 -0
- package/dist/chunk-DOR2IU73.cjs.map +1 -1
- package/dist/{chunk-HJZOA2O5.cjs → chunk-F5ESJXI2.cjs} +25 -3
- package/dist/chunk-F5ESJXI2.cjs.map +1 -0
- package/dist/chunk-FICTAGD4.js.map +1 -1
- package/dist/{chunk-LS5CMDNL.js → chunk-FTMKKKNH.js} +3 -3
- package/dist/{chunk-LS5CMDNL.js.map → chunk-FTMKKKNH.js.map} +1 -1
- package/dist/{chunk-EAELJXRV.js → chunk-HKEK7UNV.js} +25 -3
- package/dist/chunk-HKEK7UNV.js.map +1 -0
- package/dist/{chunk-3R7EQNGO.cjs → chunk-HXA5QSI3.cjs} +15 -11
- package/dist/chunk-HXA5QSI3.cjs.map +1 -0
- package/dist/{chunk-YHLLVUJC.js → chunk-LW33AOBF.js} +6 -8
- package/dist/chunk-LW33AOBF.js.map +1 -0
- package/dist/{chunk-7XEESVSX.cjs → chunk-MU3MR2QR.cjs} +6 -8
- package/dist/chunk-MU3MR2QR.cjs.map +1 -0
- package/dist/{chunk-Z2CZC6TC.js → chunk-MXJJN4IA.js} +3 -3
- package/dist/chunk-MXJJN4IA.js.map +1 -0
- package/dist/{chunk-YGVWY6KO.cjs → chunk-NBDPIRQS.cjs} +22 -5
- package/dist/chunk-NBDPIRQS.cjs.map +1 -0
- package/dist/{chunk-GN7Q6V5C.cjs → chunk-Q7SL7U43.cjs} +397 -273
- package/dist/chunk-Q7SL7U43.cjs.map +1 -0
- package/dist/chunk-RCQ2HIQD.cjs.map +1 -1
- package/dist/{chunk-O7LMFJMZ.js → chunk-YHG45LMU.js} +13 -9
- package/dist/chunk-YHG45LMU.js.map +1 -0
- package/dist/{chunk-CUEIM4FE.js → chunk-Z4H6DBVF.js} +241 -117
- package/dist/chunk-Z4H6DBVF.js.map +1 -0
- package/dist/index.cjs +108 -104
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +12 -12
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +23 -23
- package/dist/middleware.js +2 -2
- package/dist/plugins.cjs +7 -7
- package/dist/plugins.js +1 -1
- package/dist/routes.cjs +25 -25
- package/dist/routes.js +5 -5
- package/dist/services.cjs +18 -14
- package/dist/services.js +1 -1
- package/dist/templates.cjs +18 -18
- package/dist/templates.js +2 -2
- package/dist/utils.cjs +11 -11
- package/dist/utils.js +1 -1
- package/migrations/019_remove_blog_posts_collection.sql +15 -0
- package/package.json +1 -1
- package/dist/chunk-3R7EQNGO.cjs.map +0 -1
- package/dist/chunk-4MBTSUI6.js.map +0 -1
- package/dist/chunk-7XEESVSX.cjs.map +0 -1
- package/dist/chunk-CHMO2DOC.cjs.map +0 -1
- package/dist/chunk-CUEIM4FE.js.map +0 -1
- package/dist/chunk-EAELJXRV.js.map +0 -1
- package/dist/chunk-GN7Q6V5C.cjs.map +0 -1
- package/dist/chunk-HJZOA2O5.cjs.map +0 -1
- package/dist/chunk-O7LMFJMZ.js.map +0 -1
- package/dist/chunk-YGVWY6KO.cjs.map +0 -1
- package/dist/chunk-YHLLVUJC.js.map +0 -1
- package/dist/chunk-Z2CZC6TC.js.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunkDOR2IU73_cjs = require('./chunk-DOR2IU73.cjs');
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
4
|
+
var chunkHXA5QSI3_cjs = require('./chunk-HXA5QSI3.cjs');
|
|
5
|
+
var chunkNBDPIRQS_cjs = require('./chunk-NBDPIRQS.cjs');
|
|
6
|
+
var chunkMU3MR2QR_cjs = require('./chunk-MU3MR2QR.cjs');
|
|
7
|
+
var chunk3PHG75W4_cjs = require('./chunk-3PHG75W4.cjs');
|
|
8
8
|
var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
|
|
9
9
|
var hono = require('hono');
|
|
10
10
|
var cors = require('hono/cors');
|
|
@@ -43,7 +43,7 @@ apiContentCrudRoutes.get("/:id", async (c) => {
|
|
|
43
43
|
}, 500);
|
|
44
44
|
}
|
|
45
45
|
});
|
|
46
|
-
apiContentCrudRoutes.post("/",
|
|
46
|
+
apiContentCrudRoutes.post("/", chunkHXA5QSI3_cjs.requireAuth(), async (c) => {
|
|
47
47
|
try {
|
|
48
48
|
const db = c.env.DB;
|
|
49
49
|
const user = c.get("user");
|
|
@@ -109,7 +109,7 @@ apiContentCrudRoutes.post("/", chunk3R7EQNGO_cjs.requireAuth(), async (c) => {
|
|
|
109
109
|
}, 500);
|
|
110
110
|
}
|
|
111
111
|
});
|
|
112
|
-
apiContentCrudRoutes.put("/:id",
|
|
112
|
+
apiContentCrudRoutes.put("/:id", chunkHXA5QSI3_cjs.requireAuth(), async (c) => {
|
|
113
113
|
try {
|
|
114
114
|
const id = c.req.param("id");
|
|
115
115
|
const db = c.env.DB;
|
|
@@ -173,7 +173,7 @@ apiContentCrudRoutes.put("/:id", chunk3R7EQNGO_cjs.requireAuth(), async (c) => {
|
|
|
173
173
|
}, 500);
|
|
174
174
|
}
|
|
175
175
|
});
|
|
176
|
-
apiContentCrudRoutes.delete("/:id",
|
|
176
|
+
apiContentCrudRoutes.delete("/:id", chunkHXA5QSI3_cjs.requireAuth(), async (c) => {
|
|
177
177
|
try {
|
|
178
178
|
const id = c.req.param("id");
|
|
179
179
|
const db = c.env.DB;
|
|
@@ -209,7 +209,7 @@ apiRoutes.use("*", async (c, next) => {
|
|
|
209
209
|
c.header("X-Response-Time", `${totalTime}ms`);
|
|
210
210
|
});
|
|
211
211
|
apiRoutes.use("*", async (c, next) => {
|
|
212
|
-
const cacheEnabled = await
|
|
212
|
+
const cacheEnabled = await chunkHXA5QSI3_cjs.isPluginActive(c.env.DB, "core-cache");
|
|
213
213
|
c.set("cacheEnabled", cacheEnabled);
|
|
214
214
|
await next();
|
|
215
215
|
});
|
|
@@ -334,12 +334,12 @@ apiRoutes.get("/content", async (c) => {
|
|
|
334
334
|
});
|
|
335
335
|
}
|
|
336
336
|
}
|
|
337
|
-
const filter =
|
|
337
|
+
const filter = chunk3PHG75W4_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
|
|
338
338
|
if (!filter.limit) {
|
|
339
339
|
filter.limit = 50;
|
|
340
340
|
}
|
|
341
341
|
filter.limit = Math.min(filter.limit, 1e3);
|
|
342
|
-
const builder = new
|
|
342
|
+
const builder = new chunk3PHG75W4_cjs.QueryFilterBuilder();
|
|
343
343
|
const queryResult = builder.build("content", filter);
|
|
344
344
|
if (queryResult.errors.length > 0) {
|
|
345
345
|
return c.json({
|
|
@@ -426,7 +426,7 @@ apiRoutes.get("/collections/:collection/content", async (c) => {
|
|
|
426
426
|
if (!collectionResult) {
|
|
427
427
|
return c.json({ error: "Collection not found" }, 404);
|
|
428
428
|
}
|
|
429
|
-
const filter =
|
|
429
|
+
const filter = chunk3PHG75W4_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
|
|
430
430
|
if (!filter.where) {
|
|
431
431
|
filter.where = { and: [] };
|
|
432
432
|
}
|
|
@@ -442,7 +442,7 @@ apiRoutes.get("/collections/:collection/content", async (c) => {
|
|
|
442
442
|
filter.limit = 50;
|
|
443
443
|
}
|
|
444
444
|
filter.limit = Math.min(filter.limit, 1e3);
|
|
445
|
-
const builder = new
|
|
445
|
+
const builder = new chunk3PHG75W4_cjs.QueryFilterBuilder();
|
|
446
446
|
const queryResult = builder.build("content", filter);
|
|
447
447
|
if (queryResult.errors.length > 0) {
|
|
448
448
|
return c.json({
|
|
@@ -567,7 +567,7 @@ var fileValidationSchema = zod.z.object({
|
|
|
567
567
|
// 50MB max
|
|
568
568
|
});
|
|
569
569
|
var apiMediaRoutes = new hono.Hono();
|
|
570
|
-
apiMediaRoutes.use("*",
|
|
570
|
+
apiMediaRoutes.use("*", chunkHXA5QSI3_cjs.requireAuth());
|
|
571
571
|
apiMediaRoutes.post("/upload", async (c) => {
|
|
572
572
|
try {
|
|
573
573
|
const user = c.get("user");
|
|
@@ -1086,10 +1086,10 @@ apiMediaRoutes.patch("/:id", async (c) => {
|
|
|
1086
1086
|
const allowedFields = ["alt", "caption", "tags", "folder"];
|
|
1087
1087
|
const updates = [];
|
|
1088
1088
|
const values = [];
|
|
1089
|
-
for (const [key,
|
|
1089
|
+
for (const [key, value2] of Object.entries(body)) {
|
|
1090
1090
|
if (allowedFields.includes(key)) {
|
|
1091
1091
|
updates.push(`${key} = ?`);
|
|
1092
|
-
values.push(key === "tags" ? JSON.stringify(
|
|
1092
|
+
values.push(key === "tags" ? JSON.stringify(value2) : value2);
|
|
1093
1093
|
}
|
|
1094
1094
|
}
|
|
1095
1095
|
if (updates.length === 0) {
|
|
@@ -1311,8 +1311,8 @@ apiSystemRoutes.get("/env", (c) => {
|
|
|
1311
1311
|
});
|
|
1312
1312
|
var api_system_default = apiSystemRoutes;
|
|
1313
1313
|
var adminApiRoutes = new hono.Hono();
|
|
1314
|
-
adminApiRoutes.use("*",
|
|
1315
|
-
adminApiRoutes.use("*",
|
|
1314
|
+
adminApiRoutes.use("*", chunkHXA5QSI3_cjs.requireAuth());
|
|
1315
|
+
adminApiRoutes.use("*", chunkHXA5QSI3_cjs.requireRole(["admin", "editor"]));
|
|
1316
1316
|
adminApiRoutes.get("/stats", async (c) => {
|
|
1317
1317
|
try {
|
|
1318
1318
|
const db = c.env.DB;
|
|
@@ -1570,7 +1570,7 @@ adminApiRoutes.post("/collections", async (c) => {
|
|
|
1570
1570
|
}
|
|
1571
1571
|
const validatedData = validation.data;
|
|
1572
1572
|
const db = c.env.DB;
|
|
1573
|
-
const
|
|
1573
|
+
const ____user = c.get("user");
|
|
1574
1574
|
const displayName = validatedData.displayName || validatedData.display_name || "";
|
|
1575
1575
|
const existingStmt = db.prepare("SELECT id FROM collections WHERE name = ?");
|
|
1576
1576
|
const existing = await existingStmt.bind(validatedData.name).first();
|
|
@@ -1778,8 +1778,8 @@ function renderLoginPage(data, demoLoginActive = false) {
|
|
|
1778
1778
|
<div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
|
|
1779
1779
|
<div class="bg-zinc-900 shadow-sm ring-1 ring-white/10 rounded-xl px-6 py-8 sm:px-10">
|
|
1780
1780
|
<!-- Alerts -->
|
|
1781
|
-
${data.error ? `<div class="mb-6">${
|
|
1782
|
-
${data.message ? `<div class="mb-6">${
|
|
1781
|
+
${data.error ? `<div class="mb-6">${chunkMU3MR2QR_cjs.renderAlert({ type: "error", message: data.error })}</div>` : ""}
|
|
1782
|
+
${data.message ? `<div class="mb-6">${chunkMU3MR2QR_cjs.renderAlert({ type: "success", message: data.message })}</div>` : ""}
|
|
1783
1783
|
|
|
1784
1784
|
<!-- Form Response (HTMX target) -->
|
|
1785
1785
|
<div id="form-response" class="mb-6"></div>
|
|
@@ -1943,7 +1943,7 @@ function renderRegisterPage(data) {
|
|
|
1943
1943
|
<div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
|
|
1944
1944
|
<div class="bg-zinc-900 shadow-sm ring-1 ring-white/10 rounded-xl px-6 py-8 sm:px-10">
|
|
1945
1945
|
<!-- Alerts -->
|
|
1946
|
-
${data.error ? `<div class="mb-6">${
|
|
1946
|
+
${data.error ? `<div class="mb-6">${chunkMU3MR2QR_cjs.renderAlert({ type: "error", message: data.error })}</div>` : ""}
|
|
1947
1947
|
|
|
1948
1948
|
<!-- Form -->
|
|
1949
1949
|
<form
|
|
@@ -2142,7 +2142,7 @@ authRoutes.post(
|
|
|
2142
2142
|
if (existingUser) {
|
|
2143
2143
|
return c.json({ error: "User with this email or username already exists" }, 400);
|
|
2144
2144
|
}
|
|
2145
|
-
const passwordHash = await
|
|
2145
|
+
const passwordHash = await chunkHXA5QSI3_cjs.AuthManager.hashPassword(password);
|
|
2146
2146
|
const userId = crypto.randomUUID();
|
|
2147
2147
|
const now = /* @__PURE__ */ new Date();
|
|
2148
2148
|
await db.prepare(`
|
|
@@ -2162,7 +2162,7 @@ authRoutes.post(
|
|
|
2162
2162
|
now.getTime(),
|
|
2163
2163
|
now.getTime()
|
|
2164
2164
|
).run();
|
|
2165
|
-
const token = await
|
|
2165
|
+
const token = await chunkHXA5QSI3_cjs.AuthManager.generateToken(userId, normalizedEmail, "viewer");
|
|
2166
2166
|
cookie.setCookie(c, "auth_token", token, {
|
|
2167
2167
|
httpOnly: true,
|
|
2168
2168
|
secure: true,
|
|
@@ -2209,11 +2209,11 @@ authRoutes.post("/login", async (c) => {
|
|
|
2209
2209
|
if (!user) {
|
|
2210
2210
|
return c.json({ error: "Invalid email or password" }, 401);
|
|
2211
2211
|
}
|
|
2212
|
-
const isValidPassword = await
|
|
2212
|
+
const isValidPassword = await chunkHXA5QSI3_cjs.AuthManager.verifyPassword(password, user.password_hash);
|
|
2213
2213
|
if (!isValidPassword) {
|
|
2214
2214
|
return c.json({ error: "Invalid email or password" }, 401);
|
|
2215
2215
|
}
|
|
2216
|
-
const token = await
|
|
2216
|
+
const token = await chunkHXA5QSI3_cjs.AuthManager.generateToken(user.id, user.email, user.role);
|
|
2217
2217
|
cookie.setCookie(c, "auth_token", token, {
|
|
2218
2218
|
httpOnly: true,
|
|
2219
2219
|
secure: true,
|
|
@@ -2262,7 +2262,7 @@ authRoutes.get("/logout", (c) => {
|
|
|
2262
2262
|
});
|
|
2263
2263
|
return c.redirect("/auth/login?message=You have been logged out successfully");
|
|
2264
2264
|
});
|
|
2265
|
-
authRoutes.get("/me",
|
|
2265
|
+
authRoutes.get("/me", chunkHXA5QSI3_cjs.requireAuth(), async (c) => {
|
|
2266
2266
|
try {
|
|
2267
2267
|
const user = c.get("user");
|
|
2268
2268
|
if (!user) {
|
|
@@ -2279,13 +2279,13 @@ authRoutes.get("/me", chunk3R7EQNGO_cjs.requireAuth(), async (c) => {
|
|
|
2279
2279
|
return c.json({ error: "Failed to get user" }, 500);
|
|
2280
2280
|
}
|
|
2281
2281
|
});
|
|
2282
|
-
authRoutes.post("/refresh",
|
|
2282
|
+
authRoutes.post("/refresh", chunkHXA5QSI3_cjs.requireAuth(), async (c) => {
|
|
2283
2283
|
try {
|
|
2284
2284
|
const user = c.get("user");
|
|
2285
2285
|
if (!user) {
|
|
2286
2286
|
return c.json({ error: "Not authenticated" }, 401);
|
|
2287
2287
|
}
|
|
2288
|
-
const token = await
|
|
2288
|
+
const token = await chunkHXA5QSI3_cjs.AuthManager.generateToken(user.userId, user.email, user.role);
|
|
2289
2289
|
cookie.setCookie(c, "auth_token", token, {
|
|
2290
2290
|
httpOnly: true,
|
|
2291
2291
|
secure: true,
|
|
@@ -2322,7 +2322,6 @@ authRoutes.post("/register/form", async (c) => {
|
|
|
2322
2322
|
`);
|
|
2323
2323
|
}
|
|
2324
2324
|
const validatedData = validation.data;
|
|
2325
|
-
const email = validatedData.email;
|
|
2326
2325
|
const password = validatedData.password;
|
|
2327
2326
|
const username = validatedData.username || authValidationService.generateDefaultValue("username", validatedData);
|
|
2328
2327
|
const firstName = validatedData.firstName || authValidationService.generateDefaultValue("firstName", validatedData);
|
|
@@ -2335,7 +2334,7 @@ authRoutes.post("/register/form", async (c) => {
|
|
|
2335
2334
|
</div>
|
|
2336
2335
|
`);
|
|
2337
2336
|
}
|
|
2338
|
-
const passwordHash = await
|
|
2337
|
+
const passwordHash = await chunkHXA5QSI3_cjs.AuthManager.hashPassword(password);
|
|
2339
2338
|
const userId = crypto.randomUUID();
|
|
2340
2339
|
const now = /* @__PURE__ */ new Date();
|
|
2341
2340
|
await db.prepare(`
|
|
@@ -2355,7 +2354,7 @@ authRoutes.post("/register/form", async (c) => {
|
|
|
2355
2354
|
now.getTime(),
|
|
2356
2355
|
now.getTime()
|
|
2357
2356
|
).run();
|
|
2358
|
-
const token = await
|
|
2357
|
+
const token = await chunkHXA5QSI3_cjs.AuthManager.generateToken(userId, normalizedEmail, "admin");
|
|
2359
2358
|
cookie.setCookie(c, "auth_token", token, {
|
|
2360
2359
|
httpOnly: true,
|
|
2361
2360
|
secure: false,
|
|
@@ -2406,7 +2405,7 @@ authRoutes.post("/login/form", async (c) => {
|
|
|
2406
2405
|
</div>
|
|
2407
2406
|
`);
|
|
2408
2407
|
}
|
|
2409
|
-
const isValidPassword = await
|
|
2408
|
+
const isValidPassword = await chunkHXA5QSI3_cjs.AuthManager.verifyPassword(password, user.password_hash);
|
|
2410
2409
|
if (!isValidPassword) {
|
|
2411
2410
|
return c.html(html.html`
|
|
2412
2411
|
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded">
|
|
@@ -2414,7 +2413,7 @@ authRoutes.post("/login/form", async (c) => {
|
|
|
2414
2413
|
</div>
|
|
2415
2414
|
`);
|
|
2416
2415
|
}
|
|
2417
|
-
const token = await
|
|
2416
|
+
const token = await chunkHXA5QSI3_cjs.AuthManager.generateToken(user.id, user.email, user.role);
|
|
2418
2417
|
cookie.setCookie(c, "auth_token", token, {
|
|
2419
2418
|
httpOnly: true,
|
|
2420
2419
|
secure: false,
|
|
@@ -2483,7 +2482,7 @@ authRoutes.post("/seed-admin", async (c) => {
|
|
|
2483
2482
|
}
|
|
2484
2483
|
});
|
|
2485
2484
|
}
|
|
2486
|
-
const passwordHash = await
|
|
2485
|
+
const passwordHash = await chunkHXA5QSI3_cjs.AuthManager.hashPassword("admin123");
|
|
2487
2486
|
const userId = "admin-user-id";
|
|
2488
2487
|
const now = Date.now();
|
|
2489
2488
|
const adminEmail = "admin@sonicjs.com".toLowerCase();
|
|
@@ -2703,7 +2702,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
2703
2702
|
if (existingUsername) {
|
|
2704
2703
|
return c.json({ error: "Username is already taken" }, 400);
|
|
2705
2704
|
}
|
|
2706
|
-
const passwordHash = await
|
|
2705
|
+
const passwordHash = await chunkHXA5QSI3_cjs.AuthManager.hashPassword(password);
|
|
2707
2706
|
const updateStmt = db.prepare(`
|
|
2708
2707
|
UPDATE users SET
|
|
2709
2708
|
username = ?,
|
|
@@ -2722,7 +2721,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
2722
2721
|
Date.now(),
|
|
2723
2722
|
invitedUser.id
|
|
2724
2723
|
).run();
|
|
2725
|
-
const authToken = await
|
|
2724
|
+
const authToken = await chunkHXA5QSI3_cjs.AuthManager.generateToken(invitedUser.id, invitedUser.email, invitedUser.role);
|
|
2726
2725
|
cookie.setCookie(c, "auth_token", authToken, {
|
|
2727
2726
|
httpOnly: true,
|
|
2728
2727
|
secure: true,
|
|
@@ -2952,7 +2951,7 @@ authRoutes.post("/reset-password", async (c) => {
|
|
|
2952
2951
|
if (Date.now() > user.password_reset_expires) {
|
|
2953
2952
|
return c.json({ error: "Reset token has expired" }, 400);
|
|
2954
2953
|
}
|
|
2955
|
-
const newPasswordHash = await
|
|
2954
|
+
const newPasswordHash = await chunkHXA5QSI3_cjs.AuthManager.hashPassword(password);
|
|
2956
2955
|
try {
|
|
2957
2956
|
const historyStmt = db.prepare(`
|
|
2958
2957
|
INSERT INTO password_history (id, user_id, password_hash, created_at)
|
|
@@ -2989,11 +2988,11 @@ authRoutes.post("/reset-password", async (c) => {
|
|
|
2989
2988
|
var auth_default = authRoutes;
|
|
2990
2989
|
|
|
2991
2990
|
// src/templates/pages/admin-content-form.template.ts
|
|
2992
|
-
|
|
2991
|
+
chunkMU3MR2QR_cjs.init_admin_layout_catalyst_template();
|
|
2993
2992
|
|
|
2994
2993
|
// src/templates/components/dynamic-field.template.ts
|
|
2995
2994
|
function renderDynamicField(field, options = {}) {
|
|
2996
|
-
const { value = "", errors = [], disabled = false, className = "" } = options;
|
|
2995
|
+
const { value: value2 = "", errors = [], disabled = false, className = "" } = options;
|
|
2997
2996
|
const opts = field.field_options || {};
|
|
2998
2997
|
const required = field.is_required ? "required" : "";
|
|
2999
2998
|
const baseClasses = `w-full rounded-lg px-3 py-2 text-sm text-zinc-950 dark:text-white bg-white dark:bg-zinc-800 shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow ${className}`;
|
|
@@ -3050,7 +3049,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3050
3049
|
type="text"
|
|
3051
3050
|
id="${fieldId}"
|
|
3052
3051
|
name="${fieldName}"
|
|
3053
|
-
value="${escapeHtml2(
|
|
3052
|
+
value="${escapeHtml2(value2)}"
|
|
3054
3053
|
placeholder="${opts.placeholder || ""}"
|
|
3055
3054
|
maxlength="${opts.maxLength || ""}"
|
|
3056
3055
|
${opts.pattern ? `data-pattern="${opts.pattern}"` : ""}
|
|
@@ -3095,7 +3094,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3095
3094
|
class="${baseClasses} ${errorClasses} min-h-[${opts.height || 300}px]"
|
|
3096
3095
|
${required}
|
|
3097
3096
|
${disabled ? "disabled" : ""}
|
|
3098
|
-
>${escapeHtml2(
|
|
3097
|
+
>${escapeHtml2(value2)}</textarea>
|
|
3099
3098
|
<script>
|
|
3100
3099
|
// Initialize TinyMCE for this field
|
|
3101
3100
|
if (typeof tinymce !== 'undefined') {
|
|
@@ -3129,7 +3128,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3129
3128
|
type="number"
|
|
3130
3129
|
id="${fieldId}"
|
|
3131
3130
|
name="${fieldName}"
|
|
3132
|
-
value="${
|
|
3131
|
+
value="${value2}"
|
|
3133
3132
|
min="${opts.min || ""}"
|
|
3134
3133
|
max="${opts.max || ""}"
|
|
3135
3134
|
step="${opts.step || ""}"
|
|
@@ -3141,7 +3140,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3141
3140
|
`;
|
|
3142
3141
|
break;
|
|
3143
3142
|
case "boolean":
|
|
3144
|
-
const checked =
|
|
3143
|
+
const checked = value2 === true || value2 === "true" || value2 === "1" ? "checked" : "";
|
|
3145
3144
|
fieldHTML = `
|
|
3146
3145
|
<div class="flex items-center space-x-3">
|
|
3147
3146
|
<input
|
|
@@ -3166,7 +3165,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3166
3165
|
type="date"
|
|
3167
3166
|
id="${fieldId}"
|
|
3168
3167
|
name="${fieldName}"
|
|
3169
|
-
value="${
|
|
3168
|
+
value="${value2}"
|
|
3170
3169
|
min="${opts.min || ""}"
|
|
3171
3170
|
max="${opts.max || ""}"
|
|
3172
3171
|
class="${baseClasses} ${errorClasses}"
|
|
@@ -3178,7 +3177,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3178
3177
|
case "select":
|
|
3179
3178
|
const options2 = opts.options || [];
|
|
3180
3179
|
const multiple = opts.multiple ? "multiple" : "";
|
|
3181
|
-
const selectedValues = Array.isArray(
|
|
3180
|
+
const selectedValues = Array.isArray(value2) ? value2 : [value2];
|
|
3182
3181
|
fieldHTML = `
|
|
3183
3182
|
<select
|
|
3184
3183
|
id="${fieldId}"
|
|
@@ -3211,9 +3210,9 @@ function renderDynamicField(field, options = {}) {
|
|
|
3211
3210
|
case "media":
|
|
3212
3211
|
fieldHTML = `
|
|
3213
3212
|
<div class="media-field-container">
|
|
3214
|
-
<input type="hidden" id="${fieldId}" name="${fieldName}" value="${
|
|
3215
|
-
<div class="media-preview ${
|
|
3216
|
-
${
|
|
3213
|
+
<input type="hidden" id="${fieldId}" name="${fieldName}" value="${value2}">
|
|
3214
|
+
<div class="media-preview ${value2 ? "" : "hidden"}" id="${fieldId}-preview">
|
|
3215
|
+
${value2 ? `<img src="${value2}" alt="Selected media" class="w-32 h-32 object-cover rounded-lg border border-white/20">` : ""}
|
|
3217
3216
|
</div>
|
|
3218
3217
|
<div class="media-actions mt-2 space-x-2">
|
|
3219
3218
|
<button
|
|
@@ -3227,7 +3226,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3227
3226
|
</svg>
|
|
3228
3227
|
Select Media
|
|
3229
3228
|
</button>
|
|
3230
|
-
${
|
|
3229
|
+
${value2 ? `
|
|
3231
3230
|
<button
|
|
3232
3231
|
type="button"
|
|
3233
3232
|
onclick="clearMediaField('${fieldId}')"
|
|
@@ -3248,7 +3247,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3248
3247
|
type="text"
|
|
3249
3248
|
id="${fieldId}"
|
|
3250
3249
|
name="${fieldName}"
|
|
3251
|
-
value="${escapeHtml2(
|
|
3250
|
+
value="${escapeHtml2(value2)}"
|
|
3252
3251
|
class="${baseClasses} bg-zinc-100 dark:bg-zinc-800/50 cursor-not-allowed"
|
|
3253
3252
|
readonly
|
|
3254
3253
|
disabled
|
|
@@ -3258,7 +3257,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3258
3257
|
<path stroke-linecap="round" stroke-linejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z"/>
|
|
3259
3258
|
</svg>
|
|
3260
3259
|
<div class="text-xs text-zinc-600 dark:text-zinc-400">
|
|
3261
|
-
${
|
|
3260
|
+
${value2 ? "This unique identifier was automatically generated and cannot be changed." : "A unique identifier (UUID) will be automatically generated when you save this content."}
|
|
3262
3261
|
</div>
|
|
3263
3262
|
</div>
|
|
3264
3263
|
</div>
|
|
@@ -3270,7 +3269,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3270
3269
|
type="text"
|
|
3271
3270
|
id="${fieldId}"
|
|
3272
3271
|
name="${fieldName}"
|
|
3273
|
-
value="${escapeHtml2(
|
|
3272
|
+
value="${escapeHtml2(value2)}"
|
|
3274
3273
|
class="${baseClasses} ${errorClasses}"
|
|
3275
3274
|
${required}
|
|
3276
3275
|
${disabled ? "disabled" : ""}
|
|
@@ -3393,8 +3392,8 @@ function renderContentFormPage(data) {
|
|
|
3393
3392
|
<!-- Form Content -->
|
|
3394
3393
|
<div class="px-6 py-6">
|
|
3395
3394
|
<div id="form-messages">
|
|
3396
|
-
${data.error ?
|
|
3397
|
-
${data.success ?
|
|
3395
|
+
${data.error ? chunkMU3MR2QR_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
|
|
3396
|
+
${data.success ? chunkMU3MR2QR_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
|
|
3398
3397
|
</div>
|
|
3399
3398
|
|
|
3400
3399
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
@@ -3629,7 +3628,7 @@ function renderContentFormPage(data) {
|
|
|
3629
3628
|
</div>
|
|
3630
3629
|
|
|
3631
3630
|
<!-- Confirmation Dialogs -->
|
|
3632
|
-
${
|
|
3631
|
+
${chunkMU3MR2QR_cjs.renderConfirmationDialog({
|
|
3633
3632
|
id: "duplicate-content-confirm",
|
|
3634
3633
|
title: "Duplicate Content",
|
|
3635
3634
|
message: "Create a copy of this content?",
|
|
@@ -3640,7 +3639,7 @@ function renderContentFormPage(data) {
|
|
|
3640
3639
|
onConfirm: "performDuplicateContent()"
|
|
3641
3640
|
})}
|
|
3642
3641
|
|
|
3643
|
-
${
|
|
3642
|
+
${chunkMU3MR2QR_cjs.renderConfirmationDialog({
|
|
3644
3643
|
id: "delete-content-confirm",
|
|
3645
3644
|
title: "Delete Content",
|
|
3646
3645
|
message: "Are you sure you want to delete this content? This action cannot be undone.",
|
|
@@ -3651,7 +3650,7 @@ function renderContentFormPage(data) {
|
|
|
3651
3650
|
onConfirm: `performDeleteContent('${data.id}')`
|
|
3652
3651
|
})}
|
|
3653
3652
|
|
|
3654
|
-
${
|
|
3653
|
+
${chunkMU3MR2QR_cjs.getConfirmationDialogScript()}
|
|
3655
3654
|
|
|
3656
3655
|
<!-- TinyMCE CDN -->
|
|
3657
3656
|
<script src="https://cdn.tiny.cloud/1/no-api-key/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>
|
|
@@ -3939,11 +3938,11 @@ function renderContentFormPage(data) {
|
|
|
3939
3938
|
content: pageContent,
|
|
3940
3939
|
version: data.version
|
|
3941
3940
|
};
|
|
3942
|
-
return
|
|
3941
|
+
return chunkMU3MR2QR_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
3943
3942
|
}
|
|
3944
3943
|
|
|
3945
3944
|
// src/templates/pages/admin-content-list.template.ts
|
|
3946
|
-
|
|
3945
|
+
chunkMU3MR2QR_cjs.init_admin_layout_catalyst_template();
|
|
3947
3946
|
function renderContentListPage(data) {
|
|
3948
3947
|
const urlParams = new URLSearchParams();
|
|
3949
3948
|
if (data.modelName && data.modelName !== "all") urlParams.set("model", data.modelName);
|
|
@@ -3958,9 +3957,9 @@ function renderContentListPage(data) {
|
|
|
3958
3957
|
name: "model",
|
|
3959
3958
|
label: "Model",
|
|
3960
3959
|
options: [
|
|
3961
|
-
{
|
|
3960
|
+
{ __value: "all", label: "All Models", selected: data.modelName === "all" },
|
|
3962
3961
|
...data.models.map((model) => ({
|
|
3963
|
-
|
|
3962
|
+
__value: model.name,
|
|
3964
3963
|
label: model.displayName,
|
|
3965
3964
|
selected: data.modelName === model.name
|
|
3966
3965
|
}))
|
|
@@ -3970,13 +3969,13 @@ function renderContentListPage(data) {
|
|
|
3970
3969
|
name: "status",
|
|
3971
3970
|
label: "Status",
|
|
3972
3971
|
options: [
|
|
3973
|
-
{
|
|
3974
|
-
{
|
|
3975
|
-
{
|
|
3976
|
-
{
|
|
3977
|
-
{
|
|
3978
|
-
{
|
|
3979
|
-
{
|
|
3972
|
+
{ __value: "all", label: "All Status", selected: data.status === "all" },
|
|
3973
|
+
{ __value: "draft", label: "Draft", selected: data.status === "draft" },
|
|
3974
|
+
{ __value: "review", label: "Under Review", selected: data.status === "review" },
|
|
3975
|
+
{ __value: "scheduled", label: "Scheduled", selected: data.status === "scheduled" },
|
|
3976
|
+
{ __value: "published", label: "Published", selected: data.status === "published" },
|
|
3977
|
+
{ __value: "archived", label: "Archived", selected: data.status === "archived" },
|
|
3978
|
+
{ __value: "deleted", label: "Deleted", selected: data.status === "deleted" }
|
|
3980
3979
|
]
|
|
3981
3980
|
}
|
|
3982
3981
|
],
|
|
@@ -3988,9 +3987,9 @@ function renderContentListPage(data) {
|
|
|
3988
3987
|
}
|
|
3989
3988
|
],
|
|
3990
3989
|
bulkActions: [
|
|
3991
|
-
{ label: "Publish",
|
|
3992
|
-
{ label: "Unpublish",
|
|
3993
|
-
{ label: "Delete",
|
|
3990
|
+
{ label: "Publish", ___value: "publish", icon: "check-circle" },
|
|
3991
|
+
{ label: "Unpublish", ___value: "unpublish", icon: "x-circle" },
|
|
3992
|
+
{ label: "Delete", ___value: "delete", icon: "trash", className: "text-pink-600" }
|
|
3994
3993
|
]
|
|
3995
3994
|
};
|
|
3996
3995
|
const tableColumns = [
|
|
@@ -3999,7 +3998,7 @@ function renderContentListPage(data) {
|
|
|
3999
3998
|
label: "Title",
|
|
4000
3999
|
sortable: true,
|
|
4001
4000
|
sortType: "string",
|
|
4002
|
-
render: (
|
|
4001
|
+
render: (value2, row) => `
|
|
4003
4002
|
<div class="flex items-center">
|
|
4004
4003
|
<div>
|
|
4005
4004
|
<div class="text-sm font-medium text-zinc-950 dark:text-white">
|
|
@@ -4022,7 +4021,7 @@ function renderContentListPage(data) {
|
|
|
4022
4021
|
label: "Status",
|
|
4023
4022
|
sortable: true,
|
|
4024
4023
|
sortType: "string",
|
|
4025
|
-
render: (
|
|
4024
|
+
render: (value2) => value2
|
|
4026
4025
|
},
|
|
4027
4026
|
{
|
|
4028
4027
|
key: "authorName",
|
|
@@ -4043,7 +4042,7 @@ function renderContentListPage(data) {
|
|
|
4043
4042
|
label: "Actions",
|
|
4044
4043
|
sortable: false,
|
|
4045
4044
|
className: "text-sm font-medium",
|
|
4046
|
-
render: (
|
|
4045
|
+
render: (value2, row) => `
|
|
4047
4046
|
<div class="flex space-x-2">
|
|
4048
4047
|
<button
|
|
4049
4048
|
class="inline-flex items-center justify-center p-1.5 rounded-lg bg-cyan-50 dark:bg-cyan-500/10 text-cyan-700 dark:text-cyan-400 ring-1 ring-inset ring-cyan-600/20 dark:ring-cyan-500/20 hover:bg-cyan-100 dark:hover:bg-cyan-500/20 transition-colors"
|
|
@@ -4339,8 +4338,8 @@ function renderContentListPage(data) {
|
|
|
4339
4338
|
|
|
4340
4339
|
<!-- Content List -->
|
|
4341
4340
|
<div id="content-list">
|
|
4342
|
-
${
|
|
4343
|
-
${
|
|
4341
|
+
${chunkMU3MR2QR_cjs.renderTable(tableData)}
|
|
4342
|
+
${chunkMU3MR2QR_cjs.renderPagination(paginationData)}
|
|
4344
4343
|
</div>
|
|
4345
4344
|
|
|
4346
4345
|
</div>
|
|
@@ -4549,7 +4548,7 @@ function renderContentListPage(data) {
|
|
|
4549
4548
|
</script>
|
|
4550
4549
|
|
|
4551
4550
|
<!-- Confirmation Dialog for Bulk Actions -->
|
|
4552
|
-
${
|
|
4551
|
+
${chunkMU3MR2QR_cjs.renderConfirmationDialog({
|
|
4553
4552
|
id: "bulk-action-confirm",
|
|
4554
4553
|
title: "Confirm Bulk Action",
|
|
4555
4554
|
message: "Are you sure you want to perform this action? This operation will affect multiple items.",
|
|
@@ -4561,7 +4560,7 @@ function renderContentListPage(data) {
|
|
|
4561
4560
|
})}
|
|
4562
4561
|
|
|
4563
4562
|
<!-- Confirmation Dialog Script -->
|
|
4564
|
-
${
|
|
4563
|
+
${chunkMU3MR2QR_cjs.getConfirmationDialogScript()}
|
|
4565
4564
|
`;
|
|
4566
4565
|
const layoutData = {
|
|
4567
4566
|
title: "Content Management",
|
|
@@ -4571,7 +4570,7 @@ function renderContentListPage(data) {
|
|
|
4571
4570
|
version: data.version,
|
|
4572
4571
|
content: pageContent
|
|
4573
4572
|
};
|
|
4574
|
-
return
|
|
4573
|
+
return chunkMU3MR2QR_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
4575
4574
|
}
|
|
4576
4575
|
|
|
4577
4576
|
// src/templates/components/version-history.template.ts
|
|
@@ -4757,12 +4756,34 @@ var isPluginActive2 = () => false;
|
|
|
4757
4756
|
|
|
4758
4757
|
// src/routes/admin-content.ts
|
|
4759
4758
|
var adminContentRoutes = new hono.Hono();
|
|
4760
|
-
adminContentRoutes.use("*",
|
|
4759
|
+
adminContentRoutes.use("*", chunkHXA5QSI3_cjs.requireAuth());
|
|
4761
4760
|
async function getCollectionFields(db, collectionId) {
|
|
4762
4761
|
const cache = chunkDOR2IU73_cjs.getCacheService(chunkDOR2IU73_cjs.CACHE_CONFIGS.collection);
|
|
4763
4762
|
return cache.getOrSet(
|
|
4764
4763
|
cache.generateKey("fields", collectionId),
|
|
4765
4764
|
async () => {
|
|
4765
|
+
const collectionStmt = db.prepare("SELECT schema FROM collections WHERE id = ?");
|
|
4766
|
+
const collectionRow = await collectionStmt.bind(collectionId).first();
|
|
4767
|
+
if (collectionRow && collectionRow.schema) {
|
|
4768
|
+
try {
|
|
4769
|
+
const schema = typeof collectionRow.schema === "string" ? JSON.parse(collectionRow.schema) : collectionRow.schema;
|
|
4770
|
+
if (schema && schema.properties) {
|
|
4771
|
+
let fieldOrder = 0;
|
|
4772
|
+
return Object.entries(schema.properties).map(([fieldName, fieldConfig]) => ({
|
|
4773
|
+
id: `schema-${fieldName}`,
|
|
4774
|
+
field_name: fieldName,
|
|
4775
|
+
field_type: fieldConfig.type || "string",
|
|
4776
|
+
field_label: fieldConfig.title || fieldName,
|
|
4777
|
+
field_options: fieldConfig,
|
|
4778
|
+
field_order: fieldOrder++,
|
|
4779
|
+
is_required: fieldConfig.required === true || schema.required && schema.required.includes(fieldName),
|
|
4780
|
+
is_searchable: false
|
|
4781
|
+
}));
|
|
4782
|
+
}
|
|
4783
|
+
} catch (e) {
|
|
4784
|
+
console.error("Error parsing collection schema:", e);
|
|
4785
|
+
}
|
|
4786
|
+
}
|
|
4766
4787
|
const stmt = db.prepare(`
|
|
4767
4788
|
SELECT * FROM content_fields
|
|
4768
4789
|
WHERE collection_id = ?
|
|
@@ -5142,7 +5163,7 @@ adminContentRoutes.post("/", async (c) => {
|
|
|
5142
5163
|
const data = {};
|
|
5143
5164
|
const errors = {};
|
|
5144
5165
|
for (const field of fields) {
|
|
5145
|
-
const
|
|
5166
|
+
const value2 = formData.get(field.field_name);
|
|
5146
5167
|
if (field.field_type === "guid") {
|
|
5147
5168
|
const options = field.field_options || {};
|
|
5148
5169
|
if (options.autoGenerate) {
|
|
@@ -5150,33 +5171,33 @@ adminContentRoutes.post("/", async (c) => {
|
|
|
5150
5171
|
continue;
|
|
5151
5172
|
}
|
|
5152
5173
|
}
|
|
5153
|
-
if (field.is_required && (!
|
|
5174
|
+
if (field.is_required && (!value2 || value2.toString().trim() === "")) {
|
|
5154
5175
|
errors[field.field_name] = [`${field.field_label} is required`];
|
|
5155
5176
|
continue;
|
|
5156
5177
|
}
|
|
5157
5178
|
switch (field.field_type) {
|
|
5158
5179
|
case "number":
|
|
5159
|
-
if (
|
|
5180
|
+
if (value2 && isNaN(Number(value2))) {
|
|
5160
5181
|
errors[field.field_name] = [`${field.field_label} must be a valid number`];
|
|
5161
5182
|
} else {
|
|
5162
|
-
data[field.field_name] =
|
|
5183
|
+
data[field.field_name] = value2 ? Number(value2) : null;
|
|
5163
5184
|
}
|
|
5164
5185
|
break;
|
|
5165
5186
|
case "boolean":
|
|
5166
|
-
data[field.field_name] = formData.get(`${field.field_name}_submitted`) ?
|
|
5187
|
+
data[field.field_name] = formData.get(`${field.field_name}_submitted`) ? value2 === "true" : false;
|
|
5167
5188
|
break;
|
|
5168
5189
|
case "select":
|
|
5169
5190
|
if (field.field_options?.multiple) {
|
|
5170
5191
|
data[field.field_name] = formData.getAll(`${field.field_name}[]`);
|
|
5171
5192
|
} else {
|
|
5172
|
-
data[field.field_name] =
|
|
5193
|
+
data[field.field_name] = value2;
|
|
5173
5194
|
}
|
|
5174
5195
|
break;
|
|
5175
5196
|
case "guid":
|
|
5176
|
-
data[field.field_name] =
|
|
5197
|
+
data[field.field_name] = value2 || null;
|
|
5177
5198
|
break;
|
|
5178
5199
|
default:
|
|
5179
|
-
data[field.field_name] =
|
|
5200
|
+
data[field.field_name] = value2;
|
|
5180
5201
|
}
|
|
5181
5202
|
}
|
|
5182
5203
|
if (Object.keys(errors).length > 0) {
|
|
@@ -5210,9 +5231,9 @@ adminContentRoutes.post("/", async (c) => {
|
|
|
5210
5231
|
INSERT INTO content (
|
|
5211
5232
|
id, collection_id, slug, title, data, status,
|
|
5212
5233
|
scheduled_publish_at, scheduled_unpublish_at,
|
|
5213
|
-
meta_title, meta_description, author_id,
|
|
5234
|
+
meta_title, meta_description, author_id, created_at, updated_at
|
|
5214
5235
|
)
|
|
5215
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
|
|
5236
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
5216
5237
|
`);
|
|
5217
5238
|
await insertStmt.bind(
|
|
5218
5239
|
contentId,
|
|
@@ -5226,7 +5247,6 @@ adminContentRoutes.post("/", async (c) => {
|
|
|
5226
5247
|
data.meta_title || null,
|
|
5227
5248
|
data.meta_description || null,
|
|
5228
5249
|
user?.userId || "unknown",
|
|
5229
|
-
user?.userId || "unknown",
|
|
5230
5250
|
now,
|
|
5231
5251
|
now
|
|
5232
5252
|
).run();
|
|
@@ -5304,31 +5324,31 @@ adminContentRoutes.put("/:id", async (c) => {
|
|
|
5304
5324
|
const data = {};
|
|
5305
5325
|
const errors = {};
|
|
5306
5326
|
for (const field of fields) {
|
|
5307
|
-
const
|
|
5308
|
-
if (field.is_required && (!
|
|
5327
|
+
const value2 = formData.get(field.field_name);
|
|
5328
|
+
if (field.is_required && (!value2 || value2.toString().trim() === "")) {
|
|
5309
5329
|
errors[field.field_name] = [`${field.field_label} is required`];
|
|
5310
5330
|
continue;
|
|
5311
5331
|
}
|
|
5312
5332
|
switch (field.field_type) {
|
|
5313
5333
|
case "number":
|
|
5314
|
-
if (
|
|
5334
|
+
if (value2 && isNaN(Number(value2))) {
|
|
5315
5335
|
errors[field.field_name] = [`${field.field_label} must be a valid number`];
|
|
5316
5336
|
} else {
|
|
5317
|
-
data[field.field_name] =
|
|
5337
|
+
data[field.field_name] = value2 ? Number(value2) : null;
|
|
5318
5338
|
}
|
|
5319
5339
|
break;
|
|
5320
5340
|
case "boolean":
|
|
5321
|
-
data[field.field_name] = formData.get(`${field.field_name}_submitted`) ?
|
|
5341
|
+
data[field.field_name] = formData.get(`${field.field_name}_submitted`) ? value2 === "true" : false;
|
|
5322
5342
|
break;
|
|
5323
5343
|
case "select":
|
|
5324
5344
|
if (field.field_options?.multiple) {
|
|
5325
5345
|
data[field.field_name] = formData.getAll(`${field.field_name}[]`);
|
|
5326
5346
|
} else {
|
|
5327
|
-
data[field.field_name] =
|
|
5347
|
+
data[field.field_name] = value2;
|
|
5328
5348
|
}
|
|
5329
5349
|
break;
|
|
5330
5350
|
default:
|
|
5331
|
-
data[field.field_name] =
|
|
5351
|
+
data[field.field_name] = value2;
|
|
5332
5352
|
}
|
|
5333
5353
|
}
|
|
5334
5354
|
if (Object.keys(errors).length > 0) {
|
|
@@ -5445,23 +5465,23 @@ adminContentRoutes.post("/preview", async (c) => {
|
|
|
5445
5465
|
const fields = await getCollectionFields(db, collectionId);
|
|
5446
5466
|
const data = {};
|
|
5447
5467
|
for (const field of fields) {
|
|
5448
|
-
const
|
|
5468
|
+
const value2 = formData.get(field.field_name);
|
|
5449
5469
|
switch (field.field_type) {
|
|
5450
5470
|
case "number":
|
|
5451
|
-
data[field.field_name] =
|
|
5471
|
+
data[field.field_name] = value2 ? Number(value2) : null;
|
|
5452
5472
|
break;
|
|
5453
5473
|
case "boolean":
|
|
5454
|
-
data[field.field_name] =
|
|
5474
|
+
data[field.field_name] = value2 === "true";
|
|
5455
5475
|
break;
|
|
5456
5476
|
case "select":
|
|
5457
5477
|
if (field.field_options?.multiple) {
|
|
5458
5478
|
data[field.field_name] = formData.getAll(`${field.field_name}[]`);
|
|
5459
5479
|
} else {
|
|
5460
|
-
data[field.field_name] =
|
|
5480
|
+
data[field.field_name] = value2;
|
|
5461
5481
|
}
|
|
5462
5482
|
break;
|
|
5463
5483
|
default:
|
|
5464
|
-
data[field.field_name] =
|
|
5484
|
+
data[field.field_name] = value2;
|
|
5465
5485
|
}
|
|
5466
5486
|
}
|
|
5467
5487
|
const previewHTML = `
|
|
@@ -5529,9 +5549,9 @@ adminContentRoutes.post("/duplicate", async (c) => {
|
|
|
5529
5549
|
const insertStmt = db.prepare(`
|
|
5530
5550
|
INSERT INTO content (
|
|
5531
5551
|
id, collection_id, slug, title, data, status,
|
|
5532
|
-
author_id,
|
|
5552
|
+
author_id, created_at, updated_at
|
|
5533
5553
|
)
|
|
5534
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?,
|
|
5554
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
5535
5555
|
`);
|
|
5536
5556
|
await insertStmt.bind(
|
|
5537
5557
|
newId,
|
|
@@ -5542,7 +5562,6 @@ adminContentRoutes.post("/duplicate", async (c) => {
|
|
|
5542
5562
|
"draft",
|
|
5543
5563
|
// Always start as draft
|
|
5544
5564
|
user?.userId || "unknown",
|
|
5545
|
-
user?.userId || "unknown",
|
|
5546
5565
|
now,
|
|
5547
5566
|
now
|
|
5548
5567
|
).run();
|
|
@@ -5892,7 +5911,7 @@ ${JSON.stringify(data, null, 2)}
|
|
|
5892
5911
|
var admin_content_default = adminContentRoutes;
|
|
5893
5912
|
|
|
5894
5913
|
// src/templates/pages/admin-profile.template.ts
|
|
5895
|
-
|
|
5914
|
+
chunkMU3MR2QR_cjs.init_admin_layout_catalyst_template();
|
|
5896
5915
|
function renderAvatarImage(avatarUrl, firstName, lastName) {
|
|
5897
5916
|
return `<div id="avatar-image-container" class="w-24 h-24 rounded-full mx-auto mb-4 overflow-hidden bg-gradient-to-br from-cyan-400 to-purple-400 flex items-center justify-center ring-4 ring-zinc-950/5 dark:ring-white/10">
|
|
5898
5917
|
${avatarUrl ? `<img src="${avatarUrl}" alt="Profile picture" class="w-full h-full object-cover">` : `<span class="text-2xl font-bold text-white">${firstName.charAt(0)}${lastName.charAt(0)}</span>`}
|
|
@@ -5912,8 +5931,8 @@ function renderProfilePage(data) {
|
|
|
5912
5931
|
</div>
|
|
5913
5932
|
|
|
5914
5933
|
<!-- Alert Messages -->
|
|
5915
|
-
${data.error ?
|
|
5916
|
-
${data.success ?
|
|
5934
|
+
${data.error ? chunkMU3MR2QR_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
|
|
5935
|
+
${data.success ? chunkMU3MR2QR_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
|
|
5917
5936
|
|
|
5918
5937
|
<!-- Profile Form -->
|
|
5919
5938
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
|
@@ -6300,7 +6319,7 @@ function renderProfilePage(data) {
|
|
|
6300
6319
|
version: data.version,
|
|
6301
6320
|
content: pageContent
|
|
6302
6321
|
};
|
|
6303
|
-
return
|
|
6322
|
+
return chunkMU3MR2QR_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
6304
6323
|
}
|
|
6305
6324
|
|
|
6306
6325
|
// src/templates/components/alert.template.ts
|
|
@@ -6583,7 +6602,7 @@ function renderActivityLogsPage(data) {
|
|
|
6583
6602
|
user: data.user,
|
|
6584
6603
|
content: pageContent
|
|
6585
6604
|
};
|
|
6586
|
-
return
|
|
6605
|
+
return chunkMU3MR2QR_cjs.renderAdminLayout(layoutData);
|
|
6587
6606
|
}
|
|
6588
6607
|
function getActionBadgeClass(action) {
|
|
6589
6608
|
if (action.includes("login") || action.includes("logout")) {
|
|
@@ -6603,7 +6622,7 @@ function formatAction(action) {
|
|
|
6603
6622
|
}
|
|
6604
6623
|
|
|
6605
6624
|
// src/templates/pages/admin-user-edit.template.ts
|
|
6606
|
-
|
|
6625
|
+
chunkMU3MR2QR_cjs.init_admin_layout_catalyst_template();
|
|
6607
6626
|
|
|
6608
6627
|
// src/templates/components/confirmation-dialog.template.ts
|
|
6609
6628
|
function renderConfirmationDialog2(options) {
|
|
@@ -6724,8 +6743,8 @@ function renderUserEditPage(data) {
|
|
|
6724
6743
|
|
|
6725
6744
|
<!-- Alert Messages -->
|
|
6726
6745
|
<div id="form-messages">
|
|
6727
|
-
${data.error ?
|
|
6728
|
-
${data.success ?
|
|
6746
|
+
${data.error ? chunkMU3MR2QR_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
|
|
6747
|
+
${data.success ? chunkMU3MR2QR_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
|
|
6729
6748
|
</div>
|
|
6730
6749
|
|
|
6731
6750
|
<!-- User Edit Form -->
|
|
@@ -6744,7 +6763,7 @@ function renderUserEditPage(data) {
|
|
|
6744
6763
|
<input
|
|
6745
6764
|
type="text"
|
|
6746
6765
|
name="first_name"
|
|
6747
|
-
value="${
|
|
6766
|
+
value="${chunk3PHG75W4_cjs.escapeHtml(data.userToEdit.firstName || "")}"
|
|
6748
6767
|
required
|
|
6749
6768
|
class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow"
|
|
6750
6769
|
/>
|
|
@@ -6755,7 +6774,7 @@ function renderUserEditPage(data) {
|
|
|
6755
6774
|
<input
|
|
6756
6775
|
type="text"
|
|
6757
6776
|
name="last_name"
|
|
6758
|
-
value="${
|
|
6777
|
+
value="${chunk3PHG75W4_cjs.escapeHtml(data.userToEdit.lastName || "")}"
|
|
6759
6778
|
required
|
|
6760
6779
|
class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow"
|
|
6761
6780
|
/>
|
|
@@ -6766,7 +6785,7 @@ function renderUserEditPage(data) {
|
|
|
6766
6785
|
<input
|
|
6767
6786
|
type="text"
|
|
6768
6787
|
name="username"
|
|
6769
|
-
value="${
|
|
6788
|
+
value="${chunk3PHG75W4_cjs.escapeHtml(data.userToEdit.username || "")}"
|
|
6770
6789
|
required
|
|
6771
6790
|
class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow"
|
|
6772
6791
|
/>
|
|
@@ -6777,7 +6796,7 @@ function renderUserEditPage(data) {
|
|
|
6777
6796
|
<input
|
|
6778
6797
|
type="email"
|
|
6779
6798
|
name="email"
|
|
6780
|
-
value="${
|
|
6799
|
+
value="${chunk3PHG75W4_cjs.escapeHtml(data.userToEdit.email || "")}"
|
|
6781
6800
|
required
|
|
6782
6801
|
class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow"
|
|
6783
6802
|
/>
|
|
@@ -6788,7 +6807,7 @@ function renderUserEditPage(data) {
|
|
|
6788
6807
|
<input
|
|
6789
6808
|
type="tel"
|
|
6790
6809
|
name="phone"
|
|
6791
|
-
value="${
|
|
6810
|
+
value="${chunk3PHG75W4_cjs.escapeHtml(data.userToEdit.phone || "")}"
|
|
6792
6811
|
class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow"
|
|
6793
6812
|
/>
|
|
6794
6813
|
</div>
|
|
@@ -6802,7 +6821,7 @@ function renderUserEditPage(data) {
|
|
|
6802
6821
|
class="col-start-1 row-start-1 w-full appearance-none rounded-md bg-white/5 dark:bg-white/5 py-1.5 pl-3 pr-8 text-base text-zinc-950 dark:text-white outline outline-1 -outline-offset-1 outline-zinc-500/30 dark:outline-zinc-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-zinc-500 dark:focus-visible:outline-zinc-400 sm:text-sm/6"
|
|
6803
6822
|
>
|
|
6804
6823
|
${data.roles.map((role) => `
|
|
6805
|
-
<option value="${
|
|
6824
|
+
<option value="${chunk3PHG75W4_cjs.escapeHtml(role.value)}" ${data.userToEdit.role === role.value ? "selected" : ""}>${chunk3PHG75W4_cjs.escapeHtml(role.label)}</option>
|
|
6806
6825
|
`).join("")}
|
|
6807
6826
|
</select>
|
|
6808
6827
|
<svg viewBox="0 0 16 16" fill="currentColor" data-slot="icon" aria-hidden="true" class="pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-zinc-600 dark:text-zinc-400 sm:size-4">
|
|
@@ -6818,7 +6837,7 @@ function renderUserEditPage(data) {
|
|
|
6818
6837
|
name="bio"
|
|
6819
6838
|
rows="3"
|
|
6820
6839
|
class="w-full rounded-lg bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-950 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow"
|
|
6821
|
-
>${
|
|
6840
|
+
>${chunk3PHG75W4_cjs.escapeHtml(data.userToEdit.bio || "")}</textarea>
|
|
6822
6841
|
</div>
|
|
6823
6842
|
</div>
|
|
6824
6843
|
|
|
@@ -7018,11 +7037,11 @@ function renderUserEditPage(data) {
|
|
|
7018
7037
|
user: data.user,
|
|
7019
7038
|
content: pageContent
|
|
7020
7039
|
};
|
|
7021
|
-
return
|
|
7040
|
+
return chunkMU3MR2QR_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
7022
7041
|
}
|
|
7023
7042
|
|
|
7024
7043
|
// src/templates/pages/admin-user-new.template.ts
|
|
7025
|
-
|
|
7044
|
+
chunkMU3MR2QR_cjs.init_admin_layout_catalyst_template();
|
|
7026
7045
|
function renderUserNewPage(data) {
|
|
7027
7046
|
const pageContent = `
|
|
7028
7047
|
<div>
|
|
@@ -7061,8 +7080,8 @@ function renderUserNewPage(data) {
|
|
|
7061
7080
|
|
|
7062
7081
|
<!-- Alert Messages -->
|
|
7063
7082
|
<div id="form-messages">
|
|
7064
|
-
${data.error ?
|
|
7065
|
-
${data.success ?
|
|
7083
|
+
${data.error ? chunkMU3MR2QR_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
|
|
7084
|
+
${data.success ? chunkMU3MR2QR_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
|
|
7066
7085
|
</div>
|
|
7067
7086
|
|
|
7068
7087
|
<!-- User New Form -->
|
|
@@ -7306,11 +7325,11 @@ function renderUserNewPage(data) {
|
|
|
7306
7325
|
user: data.user,
|
|
7307
7326
|
content: pageContent
|
|
7308
7327
|
};
|
|
7309
|
-
return
|
|
7328
|
+
return chunkMU3MR2QR_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
7310
7329
|
}
|
|
7311
7330
|
|
|
7312
7331
|
// src/templates/pages/admin-users-list.template.ts
|
|
7313
|
-
|
|
7332
|
+
chunkMU3MR2QR_cjs.init_admin_layout_catalyst_template();
|
|
7314
7333
|
function renderUsersListPage(data) {
|
|
7315
7334
|
const columns = [
|
|
7316
7335
|
{
|
|
@@ -7318,10 +7337,10 @@ function renderUsersListPage(data) {
|
|
|
7318
7337
|
label: "",
|
|
7319
7338
|
className: "w-12",
|
|
7320
7339
|
sortable: false,
|
|
7321
|
-
render: (
|
|
7340
|
+
render: (value2, row) => {
|
|
7322
7341
|
const initials = `${row.firstName.charAt(0)}${row.lastName.charAt(0)}`.toUpperCase();
|
|
7323
|
-
if (
|
|
7324
|
-
return `<img src="${
|
|
7342
|
+
if (value2) {
|
|
7343
|
+
return `<img src="${value2}" alt="${row.firstName} ${row.lastName}" class="w-8 h-8 rounded-full">`;
|
|
7325
7344
|
}
|
|
7326
7345
|
return `
|
|
7327
7346
|
<div class="w-8 h-8 bg-gradient-to-br from-cyan-400 to-blue-500 dark:from-cyan-300 dark:to-blue-400 rounded-full flex items-center justify-center">
|
|
@@ -7335,7 +7354,7 @@ function renderUsersListPage(data) {
|
|
|
7335
7354
|
label: "Name",
|
|
7336
7355
|
sortable: true,
|
|
7337
7356
|
sortType: "string",
|
|
7338
|
-
render: (
|
|
7357
|
+
render: (_value, row) => {
|
|
7339
7358
|
const escapeHtml7 = (text) => text.replace(/[&<>"']/g, (char) => ({
|
|
7340
7359
|
"&": "&",
|
|
7341
7360
|
"<": "<",
|
|
@@ -7362,7 +7381,7 @@ function renderUsersListPage(data) {
|
|
|
7362
7381
|
label: "Email",
|
|
7363
7382
|
sortable: true,
|
|
7364
7383
|
sortType: "string",
|
|
7365
|
-
render: (
|
|
7384
|
+
render: (value2) => {
|
|
7366
7385
|
const escapeHtml7 = (text) => text.replace(/[&<>"']/g, (char) => ({
|
|
7367
7386
|
"&": "&",
|
|
7368
7387
|
"<": "<",
|
|
@@ -7370,7 +7389,7 @@ function renderUsersListPage(data) {
|
|
|
7370
7389
|
'"': """,
|
|
7371
7390
|
"'": "'"
|
|
7372
7391
|
})[char] || char);
|
|
7373
|
-
const escapedEmail = escapeHtml7(
|
|
7392
|
+
const escapedEmail = escapeHtml7(value2);
|
|
7374
7393
|
return `<a href="mailto:${escapedEmail}" class="text-cyan-600 dark:text-cyan-400 hover:text-cyan-700 dark:hover:text-cyan-300 transition-colors">${escapedEmail}</a>`;
|
|
7375
7394
|
}
|
|
7376
7395
|
},
|
|
@@ -7379,7 +7398,7 @@ function renderUsersListPage(data) {
|
|
|
7379
7398
|
label: "Role",
|
|
7380
7399
|
sortable: true,
|
|
7381
7400
|
sortType: "string",
|
|
7382
|
-
render: (
|
|
7401
|
+
render: (_value) => {
|
|
7383
7402
|
const roleColors = {
|
|
7384
7403
|
admin: "bg-red-50 dark:bg-red-500/10 text-red-700 dark:text-red-400 ring-1 ring-inset ring-red-700/10 dark:ring-red-500/20",
|
|
7385
7404
|
editor: "bg-blue-50 dark:bg-blue-500/10 text-blue-700 dark:text-blue-400 ring-1 ring-inset ring-blue-700/10 dark:ring-blue-500/20",
|
|
@@ -7395,7 +7414,7 @@ function renderUsersListPage(data) {
|
|
|
7395
7414
|
label: "Last Login",
|
|
7396
7415
|
sortable: true,
|
|
7397
7416
|
sortType: "date",
|
|
7398
|
-
render: (
|
|
7417
|
+
render: (_value) => {
|
|
7399
7418
|
if (!value) return '<span class="text-zinc-500 dark:text-zinc-400">Never</span>';
|
|
7400
7419
|
return `<span class="text-sm text-zinc-500 dark:text-zinc-400">${new Date(value).toLocaleDateString()}</span>`;
|
|
7401
7420
|
}
|
|
@@ -7405,14 +7424,14 @@ function renderUsersListPage(data) {
|
|
|
7405
7424
|
label: "Created",
|
|
7406
7425
|
sortable: true,
|
|
7407
7426
|
sortType: "date",
|
|
7408
|
-
render: (
|
|
7427
|
+
render: (_value) => `<span class="text-sm text-zinc-500 dark:text-zinc-400">${new Date(value).toLocaleDateString()}</span>`
|
|
7409
7428
|
},
|
|
7410
7429
|
{
|
|
7411
7430
|
key: "actions",
|
|
7412
7431
|
label: "Actions",
|
|
7413
7432
|
className: "text-right",
|
|
7414
7433
|
sortable: false,
|
|
7415
|
-
render: (
|
|
7434
|
+
render: (_value, row) => `
|
|
7416
7435
|
<div class="flex justify-end space-x-2">
|
|
7417
7436
|
${row.isActive ? `<button onclick="toggleUserStatus('${row.id}', false)" title="Deactivate user" class="inline-flex items-center justify-center p-2 text-sm font-medium rounded-lg bg-gradient-to-r from-red-500 to-pink-500 dark:from-red-400 dark:to-pink-400 text-white hover:from-red-600 hover:to-pink-600 dark:hover:from-red-500 dark:hover:to-pink-500 shadow-sm transition-all duration-200">
|
|
7418
7437
|
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
@@ -7461,8 +7480,8 @@ function renderUsersListPage(data) {
|
|
|
7461
7480
|
</div>
|
|
7462
7481
|
|
|
7463
7482
|
<!-- Alert Messages -->
|
|
7464
|
-
${data.error ?
|
|
7465
|
-
${data.success ?
|
|
7483
|
+
${data.error ? chunkMU3MR2QR_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
|
|
7484
|
+
${data.success ? chunkMU3MR2QR_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
|
|
7466
7485
|
|
|
7467
7486
|
<!-- Stats -->
|
|
7468
7487
|
<div class="mb-6">
|
|
@@ -7639,10 +7658,10 @@ function renderUsersListPage(data) {
|
|
|
7639
7658
|
</div>
|
|
7640
7659
|
|
|
7641
7660
|
<!-- Users Table -->
|
|
7642
|
-
${
|
|
7661
|
+
${chunkMU3MR2QR_cjs.renderTable(tableData)}
|
|
7643
7662
|
|
|
7644
7663
|
<!-- Pagination -->
|
|
7645
|
-
${data.pagination ?
|
|
7664
|
+
${data.pagination ? chunkMU3MR2QR_cjs.renderPagination(data.pagination) : ""}
|
|
7646
7665
|
</div>
|
|
7647
7666
|
|
|
7648
7667
|
<script>
|
|
@@ -7713,12 +7732,12 @@ function renderUsersListPage(data) {
|
|
|
7713
7732
|
version: data.version,
|
|
7714
7733
|
content: pageContent
|
|
7715
7734
|
};
|
|
7716
|
-
return
|
|
7735
|
+
return chunkMU3MR2QR_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
7717
7736
|
}
|
|
7718
7737
|
|
|
7719
7738
|
// src/routes/admin-users.ts
|
|
7720
7739
|
var userRoutes = new hono.Hono();
|
|
7721
|
-
userRoutes.use("*",
|
|
7740
|
+
userRoutes.use("*", chunkHXA5QSI3_cjs.requireAuth());
|
|
7722
7741
|
userRoutes.get("/", (c) => {
|
|
7723
7742
|
return c.redirect("/admin/dashboard");
|
|
7724
7743
|
});
|
|
@@ -7817,12 +7836,12 @@ userRoutes.put("/profile", async (c) => {
|
|
|
7817
7836
|
const db = c.env.DB;
|
|
7818
7837
|
try {
|
|
7819
7838
|
const formData = await c.req.formData();
|
|
7820
|
-
const firstName =
|
|
7821
|
-
const lastName =
|
|
7822
|
-
const username =
|
|
7839
|
+
const firstName = chunk3PHG75W4_cjs.sanitizeInput(formData.get("first_name")?.toString());
|
|
7840
|
+
const lastName = chunk3PHG75W4_cjs.sanitizeInput(formData.get("last_name")?.toString());
|
|
7841
|
+
const username = chunk3PHG75W4_cjs.sanitizeInput(formData.get("username")?.toString());
|
|
7823
7842
|
const email = formData.get("email")?.toString()?.trim().toLowerCase() || "";
|
|
7824
|
-
const phone =
|
|
7825
|
-
const bio =
|
|
7843
|
+
const phone = chunk3PHG75W4_cjs.sanitizeInput(formData.get("phone")?.toString()) || null;
|
|
7844
|
+
const bio = chunk3PHG75W4_cjs.sanitizeInput(formData.get("bio")?.toString()) || null;
|
|
7826
7845
|
const timezone = formData.get("timezone")?.toString() || "UTC";
|
|
7827
7846
|
const language = formData.get("language")?.toString() || "en";
|
|
7828
7847
|
const emailNotifications = formData.get("email_notifications") === "1";
|
|
@@ -7873,7 +7892,7 @@ userRoutes.put("/profile", async (c) => {
|
|
|
7873
7892
|
Date.now(),
|
|
7874
7893
|
user.userId
|
|
7875
7894
|
).run();
|
|
7876
|
-
await
|
|
7895
|
+
await chunkHXA5QSI3_cjs.logActivity(
|
|
7877
7896
|
db,
|
|
7878
7897
|
user.userId,
|
|
7879
7898
|
"profile.update",
|
|
@@ -7903,7 +7922,7 @@ userRoutes.post("/profile/avatar", async (c) => {
|
|
|
7903
7922
|
try {
|
|
7904
7923
|
const formData = await c.req.formData();
|
|
7905
7924
|
const avatarFile = formData.get("avatar");
|
|
7906
|
-
if (!avatarFile || !avatarFile.name) {
|
|
7925
|
+
if (!avatarFile || !(avatarFile instanceof File) || !avatarFile.name) {
|
|
7907
7926
|
return c.html(renderAlert2({
|
|
7908
7927
|
type: "error",
|
|
7909
7928
|
message: "Please select an image file.",
|
|
@@ -7936,7 +7955,7 @@ userRoutes.post("/profile/avatar", async (c) => {
|
|
|
7936
7955
|
SELECT first_name, last_name FROM users WHERE id = ?
|
|
7937
7956
|
`);
|
|
7938
7957
|
const userData = await userStmt.bind(user.userId).first();
|
|
7939
|
-
await
|
|
7958
|
+
await chunkHXA5QSI3_cjs.logActivity(
|
|
7940
7959
|
db,
|
|
7941
7960
|
user.userId,
|
|
7942
7961
|
"profile.avatar_update",
|
|
@@ -8007,7 +8026,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
8007
8026
|
dismissible: true
|
|
8008
8027
|
}));
|
|
8009
8028
|
}
|
|
8010
|
-
const validPassword = await
|
|
8029
|
+
const validPassword = await chunkHXA5QSI3_cjs.AuthManager.verifyPassword(currentPassword, userData.password_hash);
|
|
8011
8030
|
if (!validPassword) {
|
|
8012
8031
|
return c.html(renderAlert2({
|
|
8013
8032
|
type: "error",
|
|
@@ -8015,13 +8034,13 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
8015
8034
|
dismissible: true
|
|
8016
8035
|
}));
|
|
8017
8036
|
}
|
|
8018
|
-
const newPasswordHash = await
|
|
8037
|
+
const newPasswordHash = await chunkHXA5QSI3_cjs.AuthManager.hashPassword(newPassword);
|
|
8019
8038
|
const historyStmt = db.prepare(`
|
|
8020
8039
|
INSERT INTO password_history (id, user_id, password_hash, created_at)
|
|
8021
8040
|
VALUES (?, ?, ?, ?)
|
|
8022
8041
|
`);
|
|
8023
8042
|
await historyStmt.bind(
|
|
8024
|
-
|
|
8043
|
+
crypto.randomUUID(),
|
|
8025
8044
|
user.userId,
|
|
8026
8045
|
userData.password_hash,
|
|
8027
8046
|
Date.now()
|
|
@@ -8031,7 +8050,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
8031
8050
|
WHERE id = ?
|
|
8032
8051
|
`);
|
|
8033
8052
|
await updateStmt.bind(newPasswordHash, Date.now(), user.userId).run();
|
|
8034
|
-
await
|
|
8053
|
+
await chunkHXA5QSI3_cjs.logActivity(
|
|
8035
8054
|
db,
|
|
8036
8055
|
user.userId,
|
|
8037
8056
|
"profile.password_change",
|
|
@@ -8098,7 +8117,7 @@ userRoutes.get("/users", async (c) => {
|
|
|
8098
8117
|
`);
|
|
8099
8118
|
const countResult = await countStmt.bind(...params).first();
|
|
8100
8119
|
const totalUsers = countResult?.total || 0;
|
|
8101
|
-
await
|
|
8120
|
+
await chunkHXA5QSI3_cjs.logActivity(
|
|
8102
8121
|
db,
|
|
8103
8122
|
user.userId,
|
|
8104
8123
|
"users.list_view",
|
|
@@ -8200,12 +8219,12 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
8200
8219
|
const user = c.get("user");
|
|
8201
8220
|
try {
|
|
8202
8221
|
const formData = await c.req.formData();
|
|
8203
|
-
const firstName =
|
|
8204
|
-
const lastName =
|
|
8205
|
-
const username =
|
|
8222
|
+
const firstName = chunk3PHG75W4_cjs.sanitizeInput(formData.get("first_name")?.toString());
|
|
8223
|
+
const lastName = chunk3PHG75W4_cjs.sanitizeInput(formData.get("last_name")?.toString());
|
|
8224
|
+
const username = chunk3PHG75W4_cjs.sanitizeInput(formData.get("username")?.toString());
|
|
8206
8225
|
const email = formData.get("email")?.toString()?.trim().toLowerCase() || "";
|
|
8207
|
-
const phone =
|
|
8208
|
-
const bio =
|
|
8226
|
+
const phone = chunk3PHG75W4_cjs.sanitizeInput(formData.get("phone")?.toString()) || null;
|
|
8227
|
+
const bio = chunk3PHG75W4_cjs.sanitizeInput(formData.get("bio")?.toString()) || null;
|
|
8209
8228
|
const role = formData.get("role")?.toString() || "viewer";
|
|
8210
8229
|
const password = formData.get("password")?.toString() || "";
|
|
8211
8230
|
const confirmPassword = formData.get("confirm_password")?.toString() || "";
|
|
@@ -8252,8 +8271,8 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
8252
8271
|
dismissible: true
|
|
8253
8272
|
}));
|
|
8254
8273
|
}
|
|
8255
|
-
const passwordHash = await
|
|
8256
|
-
const userId =
|
|
8274
|
+
const passwordHash = await chunkHXA5QSI3_cjs.AuthManager.hashPassword(password);
|
|
8275
|
+
const userId = crypto.randomUUID();
|
|
8257
8276
|
const createStmt = db.prepare(`
|
|
8258
8277
|
INSERT INTO users (
|
|
8259
8278
|
id, email, username, first_name, last_name, phone, bio,
|
|
@@ -8275,7 +8294,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
8275
8294
|
Date.now(),
|
|
8276
8295
|
Date.now()
|
|
8277
8296
|
).run();
|
|
8278
|
-
await
|
|
8297
|
+
await chunkHXA5QSI3_cjs.logActivity(
|
|
8279
8298
|
db,
|
|
8280
8299
|
user.userId,
|
|
8281
8300
|
"user!.create",
|
|
@@ -8313,7 +8332,7 @@ userRoutes.get("/users/:id", async (c) => {
|
|
|
8313
8332
|
if (!userRecord) {
|
|
8314
8333
|
return c.json({ error: "User not found" }, 404);
|
|
8315
8334
|
}
|
|
8316
|
-
await
|
|
8335
|
+
await chunkHXA5QSI3_cjs.logActivity(
|
|
8317
8336
|
db,
|
|
8318
8337
|
user.userId,
|
|
8319
8338
|
"user!.view",
|
|
@@ -8406,12 +8425,12 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
8406
8425
|
const userId = c.req.param("id");
|
|
8407
8426
|
try {
|
|
8408
8427
|
const formData = await c.req.formData();
|
|
8409
|
-
const firstName =
|
|
8410
|
-
const lastName =
|
|
8411
|
-
const username =
|
|
8428
|
+
const firstName = chunk3PHG75W4_cjs.sanitizeInput(formData.get("first_name")?.toString());
|
|
8429
|
+
const lastName = chunk3PHG75W4_cjs.sanitizeInput(formData.get("last_name")?.toString());
|
|
8430
|
+
const username = chunk3PHG75W4_cjs.sanitizeInput(formData.get("username")?.toString());
|
|
8412
8431
|
const email = formData.get("email")?.toString()?.trim().toLowerCase() || "";
|
|
8413
|
-
const phone =
|
|
8414
|
-
const bio =
|
|
8432
|
+
const phone = chunk3PHG75W4_cjs.sanitizeInput(formData.get("phone")?.toString()) || null;
|
|
8433
|
+
const bio = chunk3PHG75W4_cjs.sanitizeInput(formData.get("bio")?.toString()) || null;
|
|
8415
8434
|
const role = formData.get("role")?.toString() || "viewer";
|
|
8416
8435
|
const isActive = formData.get("is_active") === "1";
|
|
8417
8436
|
const emailVerified = formData.get("email_verified") === "1";
|
|
@@ -8462,7 +8481,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
8462
8481
|
Date.now(),
|
|
8463
8482
|
userId
|
|
8464
8483
|
).run();
|
|
8465
|
-
await
|
|
8484
|
+
await chunkHXA5QSI3_cjs.logActivity(
|
|
8466
8485
|
db,
|
|
8467
8486
|
user.userId,
|
|
8468
8487
|
"user!.update",
|
|
@@ -8508,7 +8527,7 @@ userRoutes.delete("/users/:id", async (c) => {
|
|
|
8508
8527
|
DELETE FROM users WHERE id = ?
|
|
8509
8528
|
`);
|
|
8510
8529
|
await deleteStmt.bind(userId).run();
|
|
8511
|
-
await
|
|
8530
|
+
await chunkHXA5QSI3_cjs.logActivity(
|
|
8512
8531
|
db,
|
|
8513
8532
|
user.userId,
|
|
8514
8533
|
"user!.hard_delete",
|
|
@@ -8527,7 +8546,7 @@ userRoutes.delete("/users/:id", async (c) => {
|
|
|
8527
8546
|
UPDATE users SET is_active = 0, updated_at = ? WHERE id = ?
|
|
8528
8547
|
`);
|
|
8529
8548
|
await deleteStmt.bind(Date.now(), userId).run();
|
|
8530
|
-
await
|
|
8549
|
+
await chunkHXA5QSI3_cjs.logActivity(
|
|
8531
8550
|
db,
|
|
8532
8551
|
user.userId,
|
|
8533
8552
|
"user!.soft_delete",
|
|
@@ -8554,8 +8573,8 @@ userRoutes.post("/invite-user", async (c) => {
|
|
|
8554
8573
|
const formData = await c.req.formData();
|
|
8555
8574
|
const email = formData.get("email")?.toString()?.trim().toLowerCase() || "";
|
|
8556
8575
|
const role = formData.get("role")?.toString()?.trim() || "viewer";
|
|
8557
|
-
const firstName =
|
|
8558
|
-
const lastName =
|
|
8576
|
+
const firstName = chunk3PHG75W4_cjs.sanitizeInput(formData.get("first_name")?.toString());
|
|
8577
|
+
const lastName = chunk3PHG75W4_cjs.sanitizeInput(formData.get("last_name")?.toString());
|
|
8559
8578
|
if (!email || !firstName || !lastName) {
|
|
8560
8579
|
return c.json({ error: "Email, first name, and last name are required" }, 400);
|
|
8561
8580
|
}
|
|
@@ -8570,9 +8589,8 @@ userRoutes.post("/invite-user", async (c) => {
|
|
|
8570
8589
|
if (existingUser) {
|
|
8571
8590
|
return c.json({ error: "A user with this email already exists" }, 400);
|
|
8572
8591
|
}
|
|
8573
|
-
const invitationToken =
|
|
8574
|
-
const
|
|
8575
|
-
const userId = globalThis.crypto.randomUUID();
|
|
8592
|
+
const invitationToken = crypto.randomUUID();
|
|
8593
|
+
const userId = crypto.randomUUID();
|
|
8576
8594
|
const createUserStmt = db.prepare(`
|
|
8577
8595
|
INSERT INTO users (
|
|
8578
8596
|
id, email, first_name, last_name, role,
|
|
@@ -8594,7 +8612,7 @@ userRoutes.post("/invite-user", async (c) => {
|
|
|
8594
8612
|
Date.now(),
|
|
8595
8613
|
Date.now()
|
|
8596
8614
|
).run();
|
|
8597
|
-
await
|
|
8615
|
+
await chunkHXA5QSI3_cjs.logActivity(
|
|
8598
8616
|
db,
|
|
8599
8617
|
user.userId,
|
|
8600
8618
|
"user!.invite_sent",
|
|
@@ -8637,7 +8655,7 @@ userRoutes.post("/resend-invitation/:id", async (c) => {
|
|
|
8637
8655
|
if (!invitedUser) {
|
|
8638
8656
|
return c.json({ error: "User not found or invitation not valid" }, 404);
|
|
8639
8657
|
}
|
|
8640
|
-
const newInvitationToken =
|
|
8658
|
+
const newInvitationToken = crypto.randomUUID();
|
|
8641
8659
|
const updateStmt = db.prepare(`
|
|
8642
8660
|
UPDATE users SET
|
|
8643
8661
|
invitation_token = ?,
|
|
@@ -8651,7 +8669,7 @@ userRoutes.post("/resend-invitation/:id", async (c) => {
|
|
|
8651
8669
|
Date.now(),
|
|
8652
8670
|
userId
|
|
8653
8671
|
).run();
|
|
8654
|
-
await
|
|
8672
|
+
await chunkHXA5QSI3_cjs.logActivity(
|
|
8655
8673
|
db,
|
|
8656
8674
|
user.userId,
|
|
8657
8675
|
"user!.invitation_resent",
|
|
@@ -8687,7 +8705,7 @@ userRoutes.delete("/cancel-invitation/:id", async (c) => {
|
|
|
8687
8705
|
}
|
|
8688
8706
|
const deleteStmt = db.prepare(`DELETE FROM users WHERE id = ?`);
|
|
8689
8707
|
await deleteStmt.bind(userId).run();
|
|
8690
|
-
await
|
|
8708
|
+
await chunkHXA5QSI3_cjs.logActivity(
|
|
8691
8709
|
db,
|
|
8692
8710
|
user.userId,
|
|
8693
8711
|
"user!.invitation_cancelled",
|
|
@@ -8770,7 +8788,7 @@ userRoutes.get("/activity-logs", async (c) => {
|
|
|
8770
8788
|
...log,
|
|
8771
8789
|
details: log.details ? JSON.parse(log.details) : null
|
|
8772
8790
|
}));
|
|
8773
|
-
await
|
|
8791
|
+
await chunkHXA5QSI3_cjs.logActivity(
|
|
8774
8792
|
db,
|
|
8775
8793
|
user.userId,
|
|
8776
8794
|
"activity.logs_viewed",
|
|
@@ -8877,7 +8895,7 @@ userRoutes.get("/activity-logs/export", async (c) => {
|
|
|
8877
8895
|
csvRows.push(row.join(","));
|
|
8878
8896
|
}
|
|
8879
8897
|
const csvContent = csvRows.join("\n");
|
|
8880
|
-
await
|
|
8898
|
+
await chunkHXA5QSI3_cjs.logActivity(
|
|
8881
8899
|
db,
|
|
8882
8900
|
user.userId,
|
|
8883
8901
|
"activity.logs_exported",
|
|
@@ -9095,7 +9113,7 @@ function getFileIcon(mimeType) {
|
|
|
9095
9113
|
}
|
|
9096
9114
|
|
|
9097
9115
|
// src/templates/pages/admin-media-library.template.ts
|
|
9098
|
-
|
|
9116
|
+
chunkMU3MR2QR_cjs.init_admin_layout_catalyst_template();
|
|
9099
9117
|
function renderMediaLibraryPage(data) {
|
|
9100
9118
|
const pageContent = `
|
|
9101
9119
|
<div>
|
|
@@ -10030,7 +10048,7 @@ function renderMediaLibraryPage(data) {
|
|
|
10030
10048
|
version: data.version,
|
|
10031
10049
|
content: pageContent
|
|
10032
10050
|
};
|
|
10033
|
-
return
|
|
10051
|
+
return chunkMU3MR2QR_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
10034
10052
|
}
|
|
10035
10053
|
|
|
10036
10054
|
// src/templates/components/media-file-details.template.ts
|
|
@@ -10216,7 +10234,7 @@ var fileValidationSchema2 = zod.z.object({
|
|
|
10216
10234
|
// 50MB max
|
|
10217
10235
|
});
|
|
10218
10236
|
var adminMediaRoutes = new hono.Hono();
|
|
10219
|
-
adminMediaRoutes.use("*",
|
|
10237
|
+
adminMediaRoutes.use("*", chunkHXA5QSI3_cjs.requireAuth());
|
|
10220
10238
|
adminMediaRoutes.get("/", async (c) => {
|
|
10221
10239
|
try {
|
|
10222
10240
|
const user = c.get("user");
|
|
@@ -10225,7 +10243,7 @@ adminMediaRoutes.get("/", async (c) => {
|
|
|
10225
10243
|
const type = searchParams.get("type") || "all";
|
|
10226
10244
|
const view = searchParams.get("view") || "grid";
|
|
10227
10245
|
const page = parseInt(searchParams.get("page") || "1");
|
|
10228
|
-
const
|
|
10246
|
+
const ____cacheBust = searchParams.get("t");
|
|
10229
10247
|
const limit = 24;
|
|
10230
10248
|
const offset = (page - 1) * limit;
|
|
10231
10249
|
const db = c.env.DB;
|
|
@@ -10651,7 +10669,7 @@ adminMediaRoutes.post("/upload", async (c) => {
|
|
|
10651
10669
|
});
|
|
10652
10670
|
}
|
|
10653
10671
|
}
|
|
10654
|
-
let
|
|
10672
|
+
let __mediaGridHTML = "";
|
|
10655
10673
|
if (uploadResults.length > 0) {
|
|
10656
10674
|
try {
|
|
10657
10675
|
const folder = formData.get("folder") || "uploads";
|
|
@@ -10795,7 +10813,7 @@ adminMediaRoutes.put("/:id", async (c) => {
|
|
|
10795
10813
|
`);
|
|
10796
10814
|
}
|
|
10797
10815
|
});
|
|
10798
|
-
adminMediaRoutes.delete("/cleanup",
|
|
10816
|
+
adminMediaRoutes.delete("/cleanup", chunkHXA5QSI3_cjs.requireRole("admin"), async (c) => {
|
|
10799
10817
|
try {
|
|
10800
10818
|
const db = c.env.DB;
|
|
10801
10819
|
const allMediaStmt = db.prepare("SELECT id, r2_key, filename FROM media WHERE deleted_at IS NULL");
|
|
@@ -11044,7 +11062,7 @@ function formatFileSize(bytes) {
|
|
|
11044
11062
|
}
|
|
11045
11063
|
|
|
11046
11064
|
// src/templates/pages/admin-plugins-list.template.ts
|
|
11047
|
-
|
|
11065
|
+
chunkMU3MR2QR_cjs.init_admin_layout_catalyst_template();
|
|
11048
11066
|
function renderPluginsListPage(data) {
|
|
11049
11067
|
const pageContent = `
|
|
11050
11068
|
<div>
|
|
@@ -11094,6 +11112,28 @@ function renderPluginsListPage(data) {
|
|
|
11094
11112
|
</div>
|
|
11095
11113
|
</div>
|
|
11096
11114
|
|
|
11115
|
+
<!-- Experimental Notice -->
|
|
11116
|
+
<div class="mb-6 rounded-lg bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800/50 p-4">
|
|
11117
|
+
<div class="flex items-start">
|
|
11118
|
+
<div class="flex-shrink-0">
|
|
11119
|
+
<svg class="h-5 w-5 text-amber-600 dark:text-amber-400" viewBox="0 0 20 20" fill="currentColor">
|
|
11120
|
+
<path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd" />
|
|
11121
|
+
</svg>
|
|
11122
|
+
</div>
|
|
11123
|
+
<div class="ml-3 flex-1">
|
|
11124
|
+
<h3 class="text-sm font-semibold text-amber-800 dark:text-amber-200">
|
|
11125
|
+
Experimental Feature
|
|
11126
|
+
</h3>
|
|
11127
|
+
<div class="mt-2 text-sm text-amber-700 dark:text-amber-300">
|
|
11128
|
+
<p>
|
|
11129
|
+
Plugin management is currently under active development. While functional, some features may change or have limitations.
|
|
11130
|
+
Please report any issues you encounter on our <a href="https://discord.gg/8bMy6bv3sZ" target="_blank" class="font-medium underline hover:text-amber-900 dark:hover:text-amber-100">Discord community</a>.
|
|
11131
|
+
</p>
|
|
11132
|
+
</div>
|
|
11133
|
+
</div>
|
|
11134
|
+
</div>
|
|
11135
|
+
</div>
|
|
11136
|
+
|
|
11097
11137
|
<!-- Stats -->
|
|
11098
11138
|
<div class="mb-6">
|
|
11099
11139
|
<h3 class="text-base font-semibold text-zinc-950 dark:text-white">Plugin Statistics</h3>
|
|
@@ -11418,7 +11458,7 @@ function renderPluginsListPage(data) {
|
|
|
11418
11458
|
version: data.version,
|
|
11419
11459
|
content: pageContent
|
|
11420
11460
|
};
|
|
11421
|
-
return
|
|
11461
|
+
return chunkMU3MR2QR_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
11422
11462
|
}
|
|
11423
11463
|
function renderPluginCard(plugin) {
|
|
11424
11464
|
const statusColors = {
|
|
@@ -12068,7 +12108,7 @@ function renderPluginSettingsPage(data) {
|
|
|
12068
12108
|
user,
|
|
12069
12109
|
content: pageContent
|
|
12070
12110
|
};
|
|
12071
|
-
return
|
|
12111
|
+
return chunkMU3MR2QR_cjs.renderAdminLayout(layoutData);
|
|
12072
12112
|
}
|
|
12073
12113
|
function renderStatusBadge(status) {
|
|
12074
12114
|
const statusColors = {
|
|
@@ -12147,10 +12187,10 @@ function renderSettingsTab(plugin) {
|
|
|
12147
12187
|
`;
|
|
12148
12188
|
}
|
|
12149
12189
|
function renderSettingsFields(settings) {
|
|
12150
|
-
return Object.entries(settings).map(([key,
|
|
12190
|
+
return Object.entries(settings).map(([key, value2]) => {
|
|
12151
12191
|
const fieldId = `setting_${key}`;
|
|
12152
12192
|
const displayName = key.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase());
|
|
12153
|
-
if (typeof
|
|
12193
|
+
if (typeof value2 === "boolean") {
|
|
12154
12194
|
return `
|
|
12155
12195
|
<div class="flex items-center justify-between">
|
|
12156
12196
|
<div>
|
|
@@ -12158,12 +12198,12 @@ function renderSettingsFields(settings) {
|
|
|
12158
12198
|
<p class="text-xs text-gray-400">Enable or disable this feature</p>
|
|
12159
12199
|
</div>
|
|
12160
12200
|
<label class="relative inline-flex items-center cursor-pointer">
|
|
12161
|
-
<input type="checkbox" name="${fieldId}" id="${fieldId}" ${
|
|
12201
|
+
<input type="checkbox" name="${fieldId}" id="${fieldId}" ${value2 ? "checked" : ""} class="sr-only peer">
|
|
12162
12202
|
<div class="w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600"></div>
|
|
12163
12203
|
</label>
|
|
12164
12204
|
</div>
|
|
12165
12205
|
`;
|
|
12166
|
-
} else if (typeof
|
|
12206
|
+
} else if (typeof value2 === "number") {
|
|
12167
12207
|
return `
|
|
12168
12208
|
<div>
|
|
12169
12209
|
<label for="${fieldId}" class="block text-sm font-medium text-gray-300 mb-2">${displayName}</label>
|
|
@@ -12171,7 +12211,7 @@ function renderSettingsFields(settings) {
|
|
|
12171
12211
|
type="number"
|
|
12172
12212
|
name="${fieldId}"
|
|
12173
12213
|
id="${fieldId}"
|
|
12174
|
-
value="${
|
|
12214
|
+
value="${value2}"
|
|
12175
12215
|
class="backdrop-blur-sm bg-white/10 border border-white/20 rounded-lg px-3 py-2 text-white placeholder-gray-300 focus:border-blue-400 focus:outline-none transition-colors w-full"
|
|
12176
12216
|
>
|
|
12177
12217
|
</div>
|
|
@@ -12184,7 +12224,7 @@ function renderSettingsFields(settings) {
|
|
|
12184
12224
|
type="text"
|
|
12185
12225
|
name="${fieldId}"
|
|
12186
12226
|
id="${fieldId}"
|
|
12187
|
-
value="${
|
|
12227
|
+
value="${value2}"
|
|
12188
12228
|
class="backdrop-blur-sm bg-white/10 border border-white/20 rounded-lg px-3 py-2 text-white placeholder-gray-300 focus:border-blue-400 focus:outline-none transition-colors w-full"
|
|
12189
12229
|
>
|
|
12190
12230
|
</div>
|
|
@@ -12331,7 +12371,7 @@ function formatTimestamp(timestamp) {
|
|
|
12331
12371
|
|
|
12332
12372
|
// src/routes/admin-plugins.ts
|
|
12333
12373
|
var adminPluginRoutes = new hono.Hono();
|
|
12334
|
-
adminPluginRoutes.use("*",
|
|
12374
|
+
adminPluginRoutes.use("*", chunkHXA5QSI3_cjs.requireAuth());
|
|
12335
12375
|
adminPluginRoutes.get("/", async (c) => {
|
|
12336
12376
|
try {
|
|
12337
12377
|
const user = c.get("user");
|
|
@@ -12339,7 +12379,7 @@ adminPluginRoutes.get("/", async (c) => {
|
|
|
12339
12379
|
if (user?.role !== "admin") {
|
|
12340
12380
|
return c.text("Access denied", 403);
|
|
12341
12381
|
}
|
|
12342
|
-
const pluginService = new
|
|
12382
|
+
const pluginService = new chunkNBDPIRQS_cjs.PluginService(db);
|
|
12343
12383
|
let plugins = [];
|
|
12344
12384
|
let stats = { total: 0, active: 0, inactive: 0, errors: 0 };
|
|
12345
12385
|
try {
|
|
@@ -12389,7 +12429,7 @@ adminPluginRoutes.get("/:id", async (c) => {
|
|
|
12389
12429
|
if (user?.role !== "admin") {
|
|
12390
12430
|
return c.redirect("/admin/plugins");
|
|
12391
12431
|
}
|
|
12392
|
-
const pluginService = new
|
|
12432
|
+
const pluginService = new chunkNBDPIRQS_cjs.PluginService(db);
|
|
12393
12433
|
const plugin = await pluginService.getPlugin(pluginId);
|
|
12394
12434
|
if (!plugin) {
|
|
12395
12435
|
return c.text("Plugin not found", 404);
|
|
@@ -12443,7 +12483,7 @@ adminPluginRoutes.post("/:id/activate", async (c) => {
|
|
|
12443
12483
|
if (user?.role !== "admin") {
|
|
12444
12484
|
return c.json({ error: "Access denied" }, 403);
|
|
12445
12485
|
}
|
|
12446
|
-
const pluginService = new
|
|
12486
|
+
const pluginService = new chunkNBDPIRQS_cjs.PluginService(db);
|
|
12447
12487
|
await pluginService.activatePlugin(pluginId);
|
|
12448
12488
|
return c.json({ success: true });
|
|
12449
12489
|
} catch (error) {
|
|
@@ -12460,7 +12500,7 @@ adminPluginRoutes.post("/:id/deactivate", async (c) => {
|
|
|
12460
12500
|
if (user?.role !== "admin") {
|
|
12461
12501
|
return c.json({ error: "Access denied" }, 403);
|
|
12462
12502
|
}
|
|
12463
|
-
const pluginService = new
|
|
12503
|
+
const pluginService = new chunkNBDPIRQS_cjs.PluginService(db);
|
|
12464
12504
|
await pluginService.deactivatePlugin(pluginId);
|
|
12465
12505
|
return c.json({ success: true });
|
|
12466
12506
|
} catch (error) {
|
|
@@ -12477,7 +12517,7 @@ adminPluginRoutes.post("/install", async (c) => {
|
|
|
12477
12517
|
return c.json({ error: "Access denied" }, 403);
|
|
12478
12518
|
}
|
|
12479
12519
|
const body = await c.req.json();
|
|
12480
|
-
const pluginService = new
|
|
12520
|
+
const pluginService = new chunkNBDPIRQS_cjs.PluginService(db);
|
|
12481
12521
|
if (body.name === "faq-plugin") {
|
|
12482
12522
|
const faqPlugin = await pluginService.installPlugin({
|
|
12483
12523
|
id: "third-party-faq",
|
|
@@ -12627,7 +12667,7 @@ adminPluginRoutes.post("/:id/uninstall", async (c) => {
|
|
|
12627
12667
|
if (user?.role !== "admin") {
|
|
12628
12668
|
return c.json({ error: "Access denied" }, 403);
|
|
12629
12669
|
}
|
|
12630
|
-
const pluginService = new
|
|
12670
|
+
const pluginService = new chunkNBDPIRQS_cjs.PluginService(db);
|
|
12631
12671
|
await pluginService.uninstallPlugin(pluginId);
|
|
12632
12672
|
return c.json({ success: true });
|
|
12633
12673
|
} catch (error) {
|
|
@@ -12645,7 +12685,7 @@ adminPluginRoutes.post("/:id/settings", async (c) => {
|
|
|
12645
12685
|
return c.json({ error: "Access denied" }, 403);
|
|
12646
12686
|
}
|
|
12647
12687
|
const settings = await c.req.json();
|
|
12648
|
-
const pluginService = new
|
|
12688
|
+
const pluginService = new chunkNBDPIRQS_cjs.PluginService(db);
|
|
12649
12689
|
await pluginService.updatePluginSettings(pluginId, settings);
|
|
12650
12690
|
return c.json({ success: true });
|
|
12651
12691
|
} catch (error) {
|
|
@@ -12666,7 +12706,7 @@ function formatLastUpdated(timestamp) {
|
|
|
12666
12706
|
}
|
|
12667
12707
|
|
|
12668
12708
|
// src/templates/pages/admin-logs-list.template.ts
|
|
12669
|
-
|
|
12709
|
+
chunkMU3MR2QR_cjs.init_admin_layout_catalyst_template();
|
|
12670
12710
|
function renderLogsListPage(data) {
|
|
12671
12711
|
const { logs, pagination, filters, user } = data;
|
|
12672
12712
|
const content = `
|
|
@@ -12977,7 +13017,7 @@ function renderLogsListPage(data) {
|
|
|
12977
13017
|
user,
|
|
12978
13018
|
content
|
|
12979
13019
|
};
|
|
12980
|
-
return
|
|
13020
|
+
return chunkMU3MR2QR_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
12981
13021
|
}
|
|
12982
13022
|
function renderLogDetailsPage(data) {
|
|
12983
13023
|
const { log, user } = data;
|
|
@@ -13189,7 +13229,7 @@ function renderLogDetailsPage(data) {
|
|
|
13189
13229
|
</div>
|
|
13190
13230
|
</div>
|
|
13191
13231
|
`;
|
|
13192
|
-
return
|
|
13232
|
+
return chunkMU3MR2QR_cjs.adminLayoutV2({
|
|
13193
13233
|
title: `Log Details - ${log.id}`,
|
|
13194
13234
|
user,
|
|
13195
13235
|
content
|
|
@@ -13432,7 +13472,7 @@ function renderLogConfigPage(data) {
|
|
|
13432
13472
|
|
|
13433
13473
|
<script src="https://unpkg.com/htmx.org@1.9.6"></script>
|
|
13434
13474
|
`;
|
|
13435
|
-
return
|
|
13475
|
+
return chunkMU3MR2QR_cjs.adminLayoutV2({
|
|
13436
13476
|
title: "Log Configuration",
|
|
13437
13477
|
user,
|
|
13438
13478
|
content
|
|
@@ -13441,7 +13481,7 @@ function renderLogConfigPage(data) {
|
|
|
13441
13481
|
|
|
13442
13482
|
// src/routes/admin-logs.ts
|
|
13443
13483
|
var adminLogsRoutes = new hono.Hono();
|
|
13444
|
-
adminLogsRoutes.use("*",
|
|
13484
|
+
adminLogsRoutes.use("*", chunkHXA5QSI3_cjs.requireAuth());
|
|
13445
13485
|
adminLogsRoutes.get("/", async (c) => {
|
|
13446
13486
|
try {
|
|
13447
13487
|
const user = c.get("user");
|
|
@@ -13813,7 +13853,7 @@ adminDesignRoutes.get("/", (c) => {
|
|
|
13813
13853
|
role: user.role
|
|
13814
13854
|
} : void 0
|
|
13815
13855
|
};
|
|
13816
|
-
return c.html(
|
|
13856
|
+
return c.html(chunkMU3MR2QR_cjs.renderDesignPage(pageData));
|
|
13817
13857
|
});
|
|
13818
13858
|
var adminCheckboxRoutes = new hono.Hono();
|
|
13819
13859
|
adminCheckboxRoutes.get("/", (c) => {
|
|
@@ -13825,7 +13865,7 @@ adminCheckboxRoutes.get("/", (c) => {
|
|
|
13825
13865
|
role: user.role
|
|
13826
13866
|
} : void 0
|
|
13827
13867
|
};
|
|
13828
|
-
return c.html(
|
|
13868
|
+
return c.html(chunkMU3MR2QR_cjs.renderCheckboxPage(pageData));
|
|
13829
13869
|
});
|
|
13830
13870
|
|
|
13831
13871
|
// src/templates/pages/admin-faq-form.template.ts
|
|
@@ -13853,7 +13893,7 @@ function renderFAQForm(data) {
|
|
|
13853
13893
|
</div>
|
|
13854
13894
|
</div>
|
|
13855
13895
|
|
|
13856
|
-
${message ?
|
|
13896
|
+
${message ? chunkMU3MR2QR_cjs.renderAlert({ type: messageType || "info", message, dismissible: true }) : ""}
|
|
13857
13897
|
|
|
13858
13898
|
<!-- Form -->
|
|
13859
13899
|
<div class="backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl">
|
|
@@ -14066,7 +14106,7 @@ function renderFAQForm(data) {
|
|
|
14066
14106
|
user: data.user,
|
|
14067
14107
|
content: pageContent
|
|
14068
14108
|
};
|
|
14069
|
-
return
|
|
14109
|
+
return chunkMU3MR2QR_cjs.renderAdminLayout(layoutData);
|
|
14070
14110
|
}
|
|
14071
14111
|
function escapeHtml4(unsafe) {
|
|
14072
14112
|
return unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
@@ -14091,7 +14131,7 @@ adminFAQRoutes.get("/", async (c) => {
|
|
|
14091
14131
|
const offset = (currentPage - 1) * limit;
|
|
14092
14132
|
const db = c.env?.DB;
|
|
14093
14133
|
if (!db) {
|
|
14094
|
-
return c.html(
|
|
14134
|
+
return c.html(chunkMU3MR2QR_cjs.renderFAQList({
|
|
14095
14135
|
faqs: [],
|
|
14096
14136
|
totalCount: 0,
|
|
14097
14137
|
currentPage: 1,
|
|
@@ -14131,7 +14171,7 @@ adminFAQRoutes.get("/", async (c) => {
|
|
|
14131
14171
|
`;
|
|
14132
14172
|
const { results: faqs } = await db.prepare(dataQuery).bind(...params, limit, offset).all();
|
|
14133
14173
|
const totalPages = Math.ceil(totalCount / limit);
|
|
14134
|
-
return c.html(
|
|
14174
|
+
return c.html(chunkMU3MR2QR_cjs.renderFAQList({
|
|
14135
14175
|
faqs: faqs || [],
|
|
14136
14176
|
totalCount,
|
|
14137
14177
|
currentPage,
|
|
@@ -14145,7 +14185,7 @@ adminFAQRoutes.get("/", async (c) => {
|
|
|
14145
14185
|
} catch (error) {
|
|
14146
14186
|
console.error("Error fetching FAQs:", error);
|
|
14147
14187
|
const user = c.get("user");
|
|
14148
|
-
return c.html(
|
|
14188
|
+
return c.html(chunkMU3MR2QR_cjs.renderFAQList({
|
|
14149
14189
|
faqs: [],
|
|
14150
14190
|
totalCount: 0,
|
|
14151
14191
|
currentPage: 1,
|
|
@@ -14458,7 +14498,7 @@ function renderTestimonialsForm(data) {
|
|
|
14458
14498
|
</div>
|
|
14459
14499
|
</div>
|
|
14460
14500
|
|
|
14461
|
-
${message ?
|
|
14501
|
+
${message ? chunkMU3MR2QR_cjs.renderAlert({ type: messageType || "info", message, dismissible: true }) : ""}
|
|
14462
14502
|
|
|
14463
14503
|
<!-- Form -->
|
|
14464
14504
|
<div class="backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl">
|
|
@@ -14687,7 +14727,7 @@ function renderTestimonialsForm(data) {
|
|
|
14687
14727
|
user: data.user,
|
|
14688
14728
|
content: pageContent
|
|
14689
14729
|
};
|
|
14690
|
-
return
|
|
14730
|
+
return chunkMU3MR2QR_cjs.renderAdminLayout(layoutData);
|
|
14691
14731
|
}
|
|
14692
14732
|
function escapeHtml5(unsafe) {
|
|
14693
14733
|
return unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
@@ -14713,7 +14753,7 @@ adminTestimonialsRoutes.get("/", async (c) => {
|
|
|
14713
14753
|
const offset = (currentPage - 1) * limit;
|
|
14714
14754
|
const db = c.env?.DB;
|
|
14715
14755
|
if (!db) {
|
|
14716
|
-
return c.html(
|
|
14756
|
+
return c.html(chunkMU3MR2QR_cjs.renderTestimonialsList({
|
|
14717
14757
|
testimonials: [],
|
|
14718
14758
|
totalCount: 0,
|
|
14719
14759
|
currentPage: 1,
|
|
@@ -14753,7 +14793,7 @@ adminTestimonialsRoutes.get("/", async (c) => {
|
|
|
14753
14793
|
`;
|
|
14754
14794
|
const { results: testimonials } = await db.prepare(dataQuery).bind(...params, limit, offset).all();
|
|
14755
14795
|
const totalPages = Math.ceil(totalCount / limit);
|
|
14756
|
-
return c.html(
|
|
14796
|
+
return c.html(chunkMU3MR2QR_cjs.renderTestimonialsList({
|
|
14757
14797
|
testimonials: testimonials || [],
|
|
14758
14798
|
totalCount,
|
|
14759
14799
|
currentPage,
|
|
@@ -14767,7 +14807,7 @@ adminTestimonialsRoutes.get("/", async (c) => {
|
|
|
14767
14807
|
} catch (error) {
|
|
14768
14808
|
console.error("Error fetching testimonials:", error);
|
|
14769
14809
|
const user = c.get("user");
|
|
14770
|
-
return c.html(
|
|
14810
|
+
return c.html(chunkMU3MR2QR_cjs.renderTestimonialsList({
|
|
14771
14811
|
testimonials: [],
|
|
14772
14812
|
totalCount: 0,
|
|
14773
14813
|
currentPage: 1,
|
|
@@ -15086,7 +15126,7 @@ function renderCodeExamplesForm(data) {
|
|
|
15086
15126
|
</div>
|
|
15087
15127
|
</div>
|
|
15088
15128
|
|
|
15089
|
-
${message ?
|
|
15129
|
+
${message ? chunkMU3MR2QR_cjs.renderAlert({ type: messageType || "info", message, dismissible: true }) : ""}
|
|
15090
15130
|
|
|
15091
15131
|
<!-- Form -->
|
|
15092
15132
|
<div class="backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl">
|
|
@@ -15356,7 +15396,7 @@ function renderCodeExamplesForm(data) {
|
|
|
15356
15396
|
user: data.user,
|
|
15357
15397
|
content: pageContent
|
|
15358
15398
|
};
|
|
15359
|
-
return
|
|
15399
|
+
return chunkMU3MR2QR_cjs.renderAdminLayout(layoutData);
|
|
15360
15400
|
}
|
|
15361
15401
|
function escapeHtml6(unsafe) {
|
|
15362
15402
|
return unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
@@ -15383,7 +15423,7 @@ adminCodeExamplesRoutes.get("/", async (c) => {
|
|
|
15383
15423
|
const offset = (currentPage - 1) * limit;
|
|
15384
15424
|
const db = c.env?.DB;
|
|
15385
15425
|
if (!db) {
|
|
15386
|
-
return c.html(
|
|
15426
|
+
return c.html(chunkMU3MR2QR_cjs.renderCodeExamplesList({
|
|
15387
15427
|
codeExamples: [],
|
|
15388
15428
|
totalCount: 0,
|
|
15389
15429
|
currentPage: 1,
|
|
@@ -15423,7 +15463,7 @@ adminCodeExamplesRoutes.get("/", async (c) => {
|
|
|
15423
15463
|
`;
|
|
15424
15464
|
const { results: codeExamples } = await db.prepare(dataQuery).bind(...params, limit, offset).all();
|
|
15425
15465
|
const totalPages = Math.ceil(totalCount / limit);
|
|
15426
|
-
return c.html(
|
|
15466
|
+
return c.html(chunkMU3MR2QR_cjs.renderCodeExamplesList({
|
|
15427
15467
|
codeExamples: codeExamples || [],
|
|
15428
15468
|
totalCount,
|
|
15429
15469
|
currentPage,
|
|
@@ -15437,7 +15477,7 @@ adminCodeExamplesRoutes.get("/", async (c) => {
|
|
|
15437
15477
|
} catch (error) {
|
|
15438
15478
|
console.error("Error fetching code examples:", error);
|
|
15439
15479
|
const user = c.get("user");
|
|
15440
|
-
return c.html(
|
|
15480
|
+
return c.html(chunkMU3MR2QR_cjs.renderCodeExamplesList({
|
|
15441
15481
|
codeExamples: [],
|
|
15442
15482
|
totalCount: 0,
|
|
15443
15483
|
currentPage: 1,
|
|
@@ -15826,7 +15866,7 @@ function renderDashboardPage(data) {
|
|
|
15826
15866
|
version: data.version,
|
|
15827
15867
|
content: pageContent
|
|
15828
15868
|
};
|
|
15829
|
-
return
|
|
15869
|
+
return chunkMU3MR2QR_cjs.renderAdminLayout(layoutData);
|
|
15830
15870
|
}
|
|
15831
15871
|
function renderStatsCards(stats) {
|
|
15832
15872
|
const cards = [
|
|
@@ -16374,9 +16414,9 @@ function renderStorageUsage(databaseSizeBytes, mediaSizeBytes) {
|
|
|
16374
16414
|
}
|
|
16375
16415
|
|
|
16376
16416
|
// src/routes/admin-dashboard.ts
|
|
16377
|
-
var VERSION =
|
|
16417
|
+
var VERSION = chunk3PHG75W4_cjs.getCoreVersion();
|
|
16378
16418
|
var router = new hono.Hono();
|
|
16379
|
-
router.use("*",
|
|
16419
|
+
router.use("*", chunkHXA5QSI3_cjs.requireAuth());
|
|
16380
16420
|
router.get("/", async (c) => {
|
|
16381
16421
|
const user = c.get("user");
|
|
16382
16422
|
try {
|
|
@@ -16601,7 +16641,7 @@ router.get("/system-status", async (c) => {
|
|
|
16601
16641
|
});
|
|
16602
16642
|
|
|
16603
16643
|
// src/templates/pages/admin-collections-list.template.ts
|
|
16604
|
-
|
|
16644
|
+
chunkMU3MR2QR_cjs.init_admin_layout_catalyst_template();
|
|
16605
16645
|
|
|
16606
16646
|
// src/templates/components/table.template.ts
|
|
16607
16647
|
function renderTable2(data) {
|
|
@@ -16692,8 +16732,8 @@ function renderTable2(data) {
|
|
|
16692
16732
|
</td>
|
|
16693
16733
|
` : ""}
|
|
16694
16734
|
${data.columns.map((column, colIndex) => {
|
|
16695
|
-
const
|
|
16696
|
-
const displayValue = column.render ? column.render(
|
|
16735
|
+
const value2 = row[column.key];
|
|
16736
|
+
const displayValue = column.render ? column.render(value2, row) : value2;
|
|
16697
16737
|
const stopPropagation = column.key === "actions" ? 'onclick="event.stopPropagation()"' : "";
|
|
16698
16738
|
const isFirst = colIndex === 0 && !data.selectable;
|
|
16699
16739
|
const isLast = colIndex === data.columns.length - 1;
|
|
@@ -16830,7 +16870,7 @@ function renderCollectionsListPage(data) {
|
|
|
16830
16870
|
label: "Name",
|
|
16831
16871
|
sortable: true,
|
|
16832
16872
|
sortType: "string",
|
|
16833
|
-
render: (
|
|
16873
|
+
render: (_value, collection) => `
|
|
16834
16874
|
<div class="flex items-center gap-2 ml-2">
|
|
16835
16875
|
<span class="inline-flex items-center rounded-md bg-cyan-50 dark:bg-cyan-500/10 px-2.5 py-1 text-sm font-medium text-cyan-700 dark:text-cyan-300 ring-1 ring-inset ring-cyan-700/10 dark:ring-cyan-400/20">
|
|
16836
16876
|
${collection.name}
|
|
@@ -16857,14 +16897,14 @@ function renderCollectionsListPage(data) {
|
|
|
16857
16897
|
label: "Description",
|
|
16858
16898
|
sortable: true,
|
|
16859
16899
|
sortType: "string",
|
|
16860
|
-
render: (
|
|
16900
|
+
render: (_value, collection) => collection.description || '<span class="text-zinc-500 dark:text-zinc-400">-</span>'
|
|
16861
16901
|
},
|
|
16862
16902
|
{
|
|
16863
16903
|
key: "field_count",
|
|
16864
16904
|
label: "Fields",
|
|
16865
16905
|
sortable: true,
|
|
16866
16906
|
sortType: "number",
|
|
16867
|
-
render: (
|
|
16907
|
+
render: (_value, collection) => {
|
|
16868
16908
|
const count = collection.field_count || 0;
|
|
16869
16909
|
return `
|
|
16870
16910
|
<div class="flex items-center">
|
|
@@ -16880,7 +16920,7 @@ function renderCollectionsListPage(data) {
|
|
|
16880
16920
|
label: "Source",
|
|
16881
16921
|
sortable: true,
|
|
16882
16922
|
sortType: "string",
|
|
16883
|
-
render: (
|
|
16923
|
+
render: (_value, collection) => {
|
|
16884
16924
|
if (collection.managed) {
|
|
16885
16925
|
return `
|
|
16886
16926
|
<div class="flex items-center gap-1.5">
|
|
@@ -16914,7 +16954,7 @@ function renderCollectionsListPage(data) {
|
|
|
16914
16954
|
key: "actions",
|
|
16915
16955
|
label: "Content",
|
|
16916
16956
|
sortable: false,
|
|
16917
|
-
render: (
|
|
16957
|
+
render: (_value, collection) => {
|
|
16918
16958
|
if (!collection || !collection.id) return '<span class="text-zinc-500 dark:text-zinc-400">-</span>';
|
|
16919
16959
|
return `
|
|
16920
16960
|
<div class="flex items-center space-x-2">
|
|
@@ -17075,11 +17115,11 @@ function renderCollectionsListPage(data) {
|
|
|
17075
17115
|
version: data.version,
|
|
17076
17116
|
content: pageContent
|
|
17077
17117
|
};
|
|
17078
|
-
return
|
|
17118
|
+
return chunkMU3MR2QR_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
17079
17119
|
}
|
|
17080
17120
|
|
|
17081
17121
|
// src/templates/pages/admin-collections-form.template.ts
|
|
17082
|
-
|
|
17122
|
+
chunkMU3MR2QR_cjs.init_admin_layout_catalyst_template();
|
|
17083
17123
|
function renderCollectionFormPage(data) {
|
|
17084
17124
|
const isEdit = data.isEdit || !!data.id;
|
|
17085
17125
|
const title = isEdit ? "Edit Collection" : "Create New Collection";
|
|
@@ -17308,8 +17348,56 @@ function renderCollectionFormPage(data) {
|
|
|
17308
17348
|
}
|
|
17309
17349
|
</style>
|
|
17310
17350
|
|
|
17311
|
-
${
|
|
17312
|
-
|
|
17351
|
+
${chunkMU3MR2QR_cjs.renderForm(formData)}
|
|
17352
|
+
|
|
17353
|
+
${isEdit && data.managed ? `
|
|
17354
|
+
<!-- Read-Only Fields Display for Managed Collections -->
|
|
17355
|
+
<div class="mt-8 pt-8 border-t border-zinc-950/5 dark:border-white/10">
|
|
17356
|
+
<div class="mb-6">
|
|
17357
|
+
<h3 class="text-base/7 font-semibold text-zinc-950 dark:text-white">Collection Fields</h3>
|
|
17358
|
+
<p class="text-sm/6 text-zinc-500 dark:text-zinc-400 mt-1">Fields defined in the configuration file (read-only)</p>
|
|
17359
|
+
</div>
|
|
17360
|
+
|
|
17361
|
+
<!-- Fields List (Read-Only) -->
|
|
17362
|
+
<div class="space-y-3">
|
|
17363
|
+
${(data.fields || []).map((field) => `
|
|
17364
|
+
<div class="bg-zinc-50 dark:bg-zinc-800/50 rounded-lg border border-zinc-950/5 dark:border-white/10 p-4">
|
|
17365
|
+
<div class="flex items-center justify-between">
|
|
17366
|
+
<div class="flex items-center gap-x-4">
|
|
17367
|
+
<div>
|
|
17368
|
+
<div class="flex items-center gap-x-2">
|
|
17369
|
+
<span class="text-sm/6 font-medium text-zinc-950 dark:text-white">${field.field_label}</span>
|
|
17370
|
+
<span class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium bg-cyan-500/10 dark:bg-cyan-400/10 text-cyan-700 dark:text-cyan-300 ring-1 ring-inset ring-cyan-500/20 dark:ring-cyan-400/20">
|
|
17371
|
+
${field.field_type}
|
|
17372
|
+
</span>
|
|
17373
|
+
${field.is_required ? `
|
|
17374
|
+
<span class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium bg-rose-500/10 dark:bg-rose-400/10 text-rose-700 dark:text-rose-300 ring-1 ring-inset ring-rose-500/20 dark:ring-rose-400/20">
|
|
17375
|
+
Required
|
|
17376
|
+
</span>
|
|
17377
|
+
` : ""}
|
|
17378
|
+
</div>
|
|
17379
|
+
<div class="text-xs text-zinc-500 dark:text-zinc-400 mt-1">
|
|
17380
|
+
<code class="px-1.5 py-0.5 rounded bg-zinc-100 dark:bg-zinc-800 font-mono">${field.field_name}</code>
|
|
17381
|
+
</div>
|
|
17382
|
+
</div>
|
|
17383
|
+
</div>
|
|
17384
|
+
</div>
|
|
17385
|
+
</div>
|
|
17386
|
+
`).join("")}
|
|
17387
|
+
|
|
17388
|
+
${(data.fields || []).length === 0 ? `
|
|
17389
|
+
<div class="text-center py-12 text-zinc-500 dark:text-zinc-400">
|
|
17390
|
+
<svg class="mx-auto h-12 w-12 text-zinc-400 dark:text-zinc-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
|
|
17391
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z"/>
|
|
17392
|
+
</svg>
|
|
17393
|
+
<p class="mt-4 text-base/7 font-semibold text-zinc-950 dark:text-white">No fields defined</p>
|
|
17394
|
+
<p class="mt-2 text-sm/6">Add fields to your collection configuration file to see them here.</p>
|
|
17395
|
+
</div>
|
|
17396
|
+
` : ""}
|
|
17397
|
+
</div>
|
|
17398
|
+
</div>
|
|
17399
|
+
` : ""}
|
|
17400
|
+
|
|
17313
17401
|
${isEdit && !data.managed ? `
|
|
17314
17402
|
<!-- Fields Management Section -->
|
|
17315
17403
|
<div class="mt-8 pt-8 border-t border-zinc-950/5 dark:border-white/10">
|
|
@@ -17852,12 +17940,12 @@ function renderCollectionFormPage(data) {
|
|
|
17852
17940
|
version: data.version,
|
|
17853
17941
|
content: pageContent
|
|
17854
17942
|
};
|
|
17855
|
-
return
|
|
17943
|
+
return chunkMU3MR2QR_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
17856
17944
|
}
|
|
17857
17945
|
|
|
17858
17946
|
// src/routes/admin-collections.ts
|
|
17859
17947
|
var adminCollectionsRoutes = new hono.Hono();
|
|
17860
|
-
adminCollectionsRoutes.use("*",
|
|
17948
|
+
adminCollectionsRoutes.use("*", chunkHXA5QSI3_cjs.requireAuth());
|
|
17861
17949
|
adminCollectionsRoutes.get("/", async (c) => {
|
|
17862
17950
|
try {
|
|
17863
17951
|
const user = c.get("user");
|
|
@@ -17868,7 +17956,7 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
17868
17956
|
let results;
|
|
17869
17957
|
if (search) {
|
|
17870
17958
|
stmt = db.prepare(`
|
|
17871
|
-
SELECT id, name, display_name, description, created_at, managed
|
|
17959
|
+
SELECT id, name, display_name, description, created_at, managed, schema
|
|
17872
17960
|
FROM collections
|
|
17873
17961
|
WHERE is_active = 1
|
|
17874
17962
|
AND (name LIKE ? OR display_name LIKE ? OR description LIKE ?)
|
|
@@ -17878,7 +17966,7 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
17878
17966
|
const queryResults = await stmt.bind(searchParam, searchParam, searchParam).all();
|
|
17879
17967
|
results = queryResults.results;
|
|
17880
17968
|
} else {
|
|
17881
|
-
stmt = db.prepare("SELECT id, name, display_name, description, created_at, managed FROM collections WHERE is_active = 1 ORDER BY created_at DESC");
|
|
17969
|
+
stmt = db.prepare("SELECT id, name, display_name, description, created_at, managed, schema FROM collections WHERE is_active = 1 ORDER BY created_at DESC");
|
|
17882
17970
|
const queryResults = await stmt.all();
|
|
17883
17971
|
results = queryResults.results;
|
|
17884
17972
|
}
|
|
@@ -17886,6 +17974,19 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
17886
17974
|
const { results: fieldCountResults } = await fieldCountStmt.all();
|
|
17887
17975
|
const fieldCounts = new Map((fieldCountResults || []).map((row) => [String(row.collection_id), Number(row.count)]));
|
|
17888
17976
|
const collections = (results || []).filter((row) => row && row.id).map((row) => {
|
|
17977
|
+
let fieldCount = 0;
|
|
17978
|
+
if (row.schema) {
|
|
17979
|
+
try {
|
|
17980
|
+
const schema = typeof row.schema === "string" ? JSON.parse(row.schema) : row.schema;
|
|
17981
|
+
if (schema && schema.properties) {
|
|
17982
|
+
fieldCount = Object.keys(schema.properties).length;
|
|
17983
|
+
}
|
|
17984
|
+
} catch (e) {
|
|
17985
|
+
fieldCount = fieldCounts.get(String(row.id)) || 0;
|
|
17986
|
+
}
|
|
17987
|
+
} else {
|
|
17988
|
+
fieldCount = fieldCounts.get(String(row.id)) || 0;
|
|
17989
|
+
}
|
|
17889
17990
|
return {
|
|
17890
17991
|
id: String(row.id || ""),
|
|
17891
17992
|
name: String(row.name || ""),
|
|
@@ -17893,7 +17994,7 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
17893
17994
|
description: row.description ? String(row.description) : void 0,
|
|
17894
17995
|
created_at: Number(row.created_at || 0),
|
|
17895
17996
|
formattedDate: row.created_at ? new Date(Number(row.created_at)).toLocaleDateString() : "Unknown",
|
|
17896
|
-
field_count:
|
|
17997
|
+
field_count: fieldCount,
|
|
17897
17998
|
managed: row.managed === 1
|
|
17898
17999
|
};
|
|
17899
18000
|
});
|
|
@@ -18067,22 +18168,45 @@ adminCollectionsRoutes.get("/:id", async (c) => {
|
|
|
18067
18168
|
};
|
|
18068
18169
|
return c.html(renderCollectionFormPage(formData2));
|
|
18069
18170
|
}
|
|
18070
|
-
|
|
18071
|
-
|
|
18072
|
-
|
|
18073
|
-
|
|
18074
|
-
|
|
18075
|
-
|
|
18076
|
-
|
|
18077
|
-
|
|
18078
|
-
|
|
18079
|
-
|
|
18080
|
-
|
|
18081
|
-
|
|
18082
|
-
|
|
18083
|
-
|
|
18084
|
-
|
|
18085
|
-
|
|
18171
|
+
let fields = [];
|
|
18172
|
+
if (collection.schema) {
|
|
18173
|
+
try {
|
|
18174
|
+
const schema = typeof collection.schema === "string" ? JSON.parse(collection.schema) : collection.schema;
|
|
18175
|
+
if (schema && schema.properties) {
|
|
18176
|
+
let fieldOrder = 0;
|
|
18177
|
+
fields = Object.entries(schema.properties).map(([fieldName, fieldConfig]) => ({
|
|
18178
|
+
id: `schema-${fieldName}`,
|
|
18179
|
+
field_name: fieldName,
|
|
18180
|
+
field_type: fieldConfig.type || "string",
|
|
18181
|
+
field_label: fieldConfig.title || fieldName,
|
|
18182
|
+
field_options: fieldConfig,
|
|
18183
|
+
field_order: fieldOrder++,
|
|
18184
|
+
is_required: fieldConfig.required === true || schema.required && schema.required.includes(fieldName),
|
|
18185
|
+
is_searchable: false
|
|
18186
|
+
}));
|
|
18187
|
+
}
|
|
18188
|
+
} catch (e) {
|
|
18189
|
+
console.error("Error parsing collection schema:", e);
|
|
18190
|
+
}
|
|
18191
|
+
}
|
|
18192
|
+
if (fields.length === 0) {
|
|
18193
|
+
const fieldsStmt = db.prepare(`
|
|
18194
|
+
SELECT * FROM content_fields
|
|
18195
|
+
WHERE collection_id = ?
|
|
18196
|
+
ORDER BY field_order ASC
|
|
18197
|
+
`);
|
|
18198
|
+
const { results: fieldsResults } = await fieldsStmt.bind(id).all();
|
|
18199
|
+
fields = (fieldsResults || []).map((row) => ({
|
|
18200
|
+
id: row.id,
|
|
18201
|
+
field_name: row.field_name,
|
|
18202
|
+
field_type: row.field_type,
|
|
18203
|
+
field_label: row.field_label,
|
|
18204
|
+
field_options: row.field_options ? JSON.parse(row.field_options) : {},
|
|
18205
|
+
field_order: row.field_order,
|
|
18206
|
+
is_required: row.is_required === 1,
|
|
18207
|
+
is_searchable: row.is_searchable === 1
|
|
18208
|
+
}));
|
|
18209
|
+
}
|
|
18086
18210
|
const formData = {
|
|
18087
18211
|
id: collection.id,
|
|
18088
18212
|
name: collection.name,
|
|
@@ -18289,7 +18413,7 @@ adminCollectionsRoutes.post("/:collectionId/fields/reorder", async (c) => {
|
|
|
18289
18413
|
});
|
|
18290
18414
|
|
|
18291
18415
|
// src/templates/pages/admin-settings.template.ts
|
|
18292
|
-
|
|
18416
|
+
chunkMU3MR2QR_cjs.init_admin_layout_catalyst_template();
|
|
18293
18417
|
function renderSettingsPage(data) {
|
|
18294
18418
|
const activeTab = data.activeTab || "general";
|
|
18295
18419
|
const pageContent = `
|
|
@@ -18720,7 +18844,7 @@ function renderSettingsPage(data) {
|
|
|
18720
18844
|
version: data.version,
|
|
18721
18845
|
content: pageContent
|
|
18722
18846
|
};
|
|
18723
|
-
return
|
|
18847
|
+
return chunkMU3MR2QR_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
18724
18848
|
}
|
|
18725
18849
|
function renderTabButton(tabId, label, iconPath, activeTab) {
|
|
18726
18850
|
const isActive = activeTab === tabId;
|
|
@@ -19737,7 +19861,7 @@ function renderDatabaseToolsSettings(settings) {
|
|
|
19737
19861
|
|
|
19738
19862
|
// src/routes/admin-settings.ts
|
|
19739
19863
|
var adminSettingsRoutes = new hono.Hono();
|
|
19740
|
-
adminSettingsRoutes.use("*",
|
|
19864
|
+
adminSettingsRoutes.use("*", chunkHXA5QSI3_cjs.requireAuth());
|
|
19741
19865
|
function getMockSettings(user) {
|
|
19742
19866
|
return {
|
|
19743
19867
|
general: {
|
|
@@ -19905,7 +20029,7 @@ adminSettingsRoutes.get("/database-tools", (c) => {
|
|
|
19905
20029
|
adminSettingsRoutes.get("/api/migrations/status", async (c) => {
|
|
19906
20030
|
try {
|
|
19907
20031
|
const db = c.env.DB;
|
|
19908
|
-
const migrationService = new
|
|
20032
|
+
const migrationService = new chunkNBDPIRQS_cjs.MigrationService(db);
|
|
19909
20033
|
const status = await migrationService.getMigrationStatus();
|
|
19910
20034
|
return c.json({
|
|
19911
20035
|
success: true,
|
|
@@ -19929,7 +20053,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
|
|
|
19929
20053
|
}, 403);
|
|
19930
20054
|
}
|
|
19931
20055
|
const db = c.env.DB;
|
|
19932
|
-
const migrationService = new
|
|
20056
|
+
const migrationService = new chunkNBDPIRQS_cjs.MigrationService(db);
|
|
19933
20057
|
const result = await migrationService.runPendingMigrations();
|
|
19934
20058
|
return c.json({
|
|
19935
20059
|
success: result.success,
|
|
@@ -19947,7 +20071,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
|
|
|
19947
20071
|
adminSettingsRoutes.get("/api/migrations/validate", async (c) => {
|
|
19948
20072
|
try {
|
|
19949
20073
|
const db = c.env.DB;
|
|
19950
|
-
const migrationService = new
|
|
20074
|
+
const migrationService = new chunkNBDPIRQS_cjs.MigrationService(db);
|
|
19951
20075
|
const validation = await migrationService.validateSchema();
|
|
19952
20076
|
return c.json({
|
|
19953
20077
|
success: true,
|
|
@@ -20191,5 +20315,5 @@ exports.api_system_default = api_system_default;
|
|
|
20191
20315
|
exports.auth_default = auth_default;
|
|
20192
20316
|
exports.router = router;
|
|
20193
20317
|
exports.userRoutes = userRoutes;
|
|
20194
|
-
//# sourceMappingURL=chunk-
|
|
20195
|
-
//# sourceMappingURL=chunk-
|
|
20318
|
+
//# sourceMappingURL=chunk-Q7SL7U43.cjs.map
|
|
20319
|
+
//# sourceMappingURL=chunk-Q7SL7U43.cjs.map
|