@sonicjs-cms/core 2.3.12 → 2.3.14
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/dist/{chunk-REY542YK.js → chunk-AVPUX57O.js} +3 -3
- package/dist/{chunk-REY542YK.js.map → chunk-AVPUX57O.js.map} +1 -1
- package/dist/{chunk-RIOIKM3Y.cjs → chunk-AZLU3ROK.cjs} +4 -2
- package/dist/chunk-AZLU3ROK.cjs.map +1 -0
- package/dist/{chunk-NTXPL746.js → chunk-CAJOP354.js} +34 -2
- package/dist/chunk-CAJOP354.js.map +1 -0
- package/dist/{chunk-HTJLBF6F.cjs → chunk-D4PJFFOV.cjs} +652 -475
- package/dist/chunk-D4PJFFOV.cjs.map +1 -0
- package/dist/{chunk-P6NMVNJJ.cjs → chunk-ETS5XSAG.cjs} +34 -2
- package/dist/chunk-ETS5XSAG.cjs.map +1 -0
- package/dist/{chunk-EIE35JCC.js → chunk-H34L445M.js} +3 -3
- package/dist/{chunk-EIE35JCC.js.map → chunk-H34L445M.js.map} +1 -1
- package/dist/{chunk-74RYBO6J.js → chunk-SKPETEM5.js} +10 -5
- package/dist/chunk-SKPETEM5.js.map +1 -0
- package/dist/{chunk-IB6UBZVD.cjs → chunk-SZE3XVET.cjs} +10 -5
- package/dist/chunk-SZE3XVET.cjs.map +1 -0
- package/dist/{chunk-HDSRB23N.js → chunk-T4XRPNX2.js} +507 -330
- package/dist/chunk-T4XRPNX2.js.map +1 -0
- package/dist/{chunk-KQCYQKSV.js → chunk-V5LBQN3I.js} +4 -2
- package/dist/chunk-V5LBQN3I.js.map +1 -0
- package/dist/{chunk-OJ5WUCSH.cjs → chunk-XWPGIFS7.cjs} +4 -4
- package/dist/{chunk-OJ5WUCSH.cjs.map → chunk-XWPGIFS7.cjs.map} +1 -1
- package/dist/{chunk-K6BFUYJH.cjs → chunk-YIXSSJWD.cjs} +5 -5
- package/dist/{chunk-K6BFUYJH.cjs.map → chunk-YIXSSJWD.cjs.map} +1 -1
- package/dist/index.cjs +1080 -87
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1003 -10
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +23 -23
- package/dist/middleware.js +2 -2
- package/dist/migrations-3A53GREK.cjs +13 -0
- package/dist/{migrations-DQ74P6V4.cjs.map → migrations-3A53GREK.cjs.map} +1 -1
- package/dist/migrations-WF6VIVU2.js +4 -0
- package/dist/{migrations-YAFC5JVO.js.map → migrations-WF6VIVU2.js.map} +1 -1
- package/dist/routes.cjs +25 -25
- package/dist/routes.js +5 -5
- package/dist/services.cjs +2 -2
- package/dist/services.js +1 -1
- package/dist/templates.cjs +17 -17
- package/dist/templates.js +2 -2
- package/dist/utils.cjs +11 -11
- package/dist/utils.js +1 -1
- package/migrations/025_add_easymde_plugin.sql +25 -0
- package/package.json +8 -3
- package/dist/chunk-74RYBO6J.js.map +0 -1
- package/dist/chunk-HDSRB23N.js.map +0 -1
- package/dist/chunk-HTJLBF6F.cjs.map +0 -1
- package/dist/chunk-IB6UBZVD.cjs.map +0 -1
- package/dist/chunk-KQCYQKSV.js.map +0 -1
- package/dist/chunk-NTXPL746.js.map +0 -1
- package/dist/chunk-P6NMVNJJ.cjs.map +0 -1
- package/dist/chunk-RIOIKM3Y.cjs.map +0 -1
- package/dist/migrations-DQ74P6V4.cjs +0 -13
- package/dist/migrations-YAFC5JVO.js +0 -4
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunk7FOAMNTI_cjs = require('./chunk-7FOAMNTI.cjs');
|
|
4
|
-
var
|
|
4
|
+
var chunkXWPGIFS7_cjs = require('./chunk-XWPGIFS7.cjs');
|
|
5
5
|
var chunkILZ3DP4I_cjs = require('./chunk-ILZ3DP4I.cjs');
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
var
|
|
6
|
+
var chunkETS5XSAG_cjs = require('./chunk-ETS5XSAG.cjs');
|
|
7
|
+
var chunkAZLU3ROK_cjs = require('./chunk-AZLU3ROK.cjs');
|
|
8
|
+
var chunkSZE3XVET_cjs = require('./chunk-SZE3XVET.cjs');
|
|
9
9
|
var chunkRCQ2HIQD_cjs = require('./chunk-RCQ2HIQD.cjs');
|
|
10
10
|
var hono = require('hono');
|
|
11
11
|
var cors = require('hono/cors');
|
|
@@ -44,7 +44,7 @@ apiContentCrudRoutes.get("/:id", async (c) => {
|
|
|
44
44
|
}, 500);
|
|
45
45
|
}
|
|
46
46
|
});
|
|
47
|
-
apiContentCrudRoutes.post("/",
|
|
47
|
+
apiContentCrudRoutes.post("/", chunkXWPGIFS7_cjs.requireAuth(), async (c) => {
|
|
48
48
|
try {
|
|
49
49
|
const db = c.env.DB;
|
|
50
50
|
const user = c.get("user");
|
|
@@ -110,7 +110,7 @@ apiContentCrudRoutes.post("/", chunkOJ5WUCSH_cjs.requireAuth(), async (c) => {
|
|
|
110
110
|
}, 500);
|
|
111
111
|
}
|
|
112
112
|
});
|
|
113
|
-
apiContentCrudRoutes.put("/:id",
|
|
113
|
+
apiContentCrudRoutes.put("/:id", chunkXWPGIFS7_cjs.requireAuth(), async (c) => {
|
|
114
114
|
try {
|
|
115
115
|
const id = c.req.param("id");
|
|
116
116
|
const db = c.env.DB;
|
|
@@ -174,7 +174,7 @@ apiContentCrudRoutes.put("/:id", chunkOJ5WUCSH_cjs.requireAuth(), async (c) => {
|
|
|
174
174
|
}, 500);
|
|
175
175
|
}
|
|
176
176
|
});
|
|
177
|
-
apiContentCrudRoutes.delete("/:id",
|
|
177
|
+
apiContentCrudRoutes.delete("/:id", chunkXWPGIFS7_cjs.requireAuth(), async (c) => {
|
|
178
178
|
try {
|
|
179
179
|
const id = c.req.param("id");
|
|
180
180
|
const db = c.env.DB;
|
|
@@ -210,7 +210,7 @@ apiRoutes.use("*", async (c, next) => {
|
|
|
210
210
|
c.header("X-Response-Time", `${totalTime}ms`);
|
|
211
211
|
});
|
|
212
212
|
apiRoutes.use("*", async (c, next) => {
|
|
213
|
-
const cacheEnabled = await
|
|
213
|
+
const cacheEnabled = await chunkXWPGIFS7_cjs.isPluginActive(c.env.DB, "core-cache");
|
|
214
214
|
c.set("cacheEnabled", cacheEnabled);
|
|
215
215
|
await next();
|
|
216
216
|
});
|
|
@@ -335,12 +335,12 @@ apiRoutes.get("/content", async (c) => {
|
|
|
335
335
|
});
|
|
336
336
|
}
|
|
337
337
|
}
|
|
338
|
-
const filter =
|
|
338
|
+
const filter = chunkSZE3XVET_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
|
|
339
339
|
if (!filter.limit) {
|
|
340
340
|
filter.limit = 50;
|
|
341
341
|
}
|
|
342
342
|
filter.limit = Math.min(filter.limit, 1e3);
|
|
343
|
-
const builder3 = new
|
|
343
|
+
const builder3 = new chunkSZE3XVET_cjs.QueryFilterBuilder();
|
|
344
344
|
const queryResult = builder3.build("content", filter);
|
|
345
345
|
if (queryResult.errors.length > 0) {
|
|
346
346
|
return c.json({
|
|
@@ -427,7 +427,7 @@ apiRoutes.get("/collections/:collection/content", async (c) => {
|
|
|
427
427
|
if (!collectionResult) {
|
|
428
428
|
return c.json({ error: "Collection not found" }, 404);
|
|
429
429
|
}
|
|
430
|
-
const filter =
|
|
430
|
+
const filter = chunkSZE3XVET_cjs.QueryFilterBuilder.parseFromQuery(queryParams);
|
|
431
431
|
if (!filter.where) {
|
|
432
432
|
filter.where = { and: [] };
|
|
433
433
|
}
|
|
@@ -443,7 +443,7 @@ apiRoutes.get("/collections/:collection/content", async (c) => {
|
|
|
443
443
|
filter.limit = 50;
|
|
444
444
|
}
|
|
445
445
|
filter.limit = Math.min(filter.limit, 1e3);
|
|
446
|
-
const builder3 = new
|
|
446
|
+
const builder3 = new chunkSZE3XVET_cjs.QueryFilterBuilder();
|
|
447
447
|
const queryResult = builder3.build("content", filter);
|
|
448
448
|
if (queryResult.errors.length > 0) {
|
|
449
449
|
return c.json({
|
|
@@ -568,7 +568,7 @@ var fileValidationSchema = zod.z.object({
|
|
|
568
568
|
// 50MB max
|
|
569
569
|
});
|
|
570
570
|
var apiMediaRoutes = new hono.Hono();
|
|
571
|
-
apiMediaRoutes.use("*",
|
|
571
|
+
apiMediaRoutes.use("*", chunkXWPGIFS7_cjs.requireAuth());
|
|
572
572
|
apiMediaRoutes.post("/upload", async (c) => {
|
|
573
573
|
try {
|
|
574
574
|
const user = c.get("user");
|
|
@@ -1312,8 +1312,8 @@ apiSystemRoutes.get("/env", (c) => {
|
|
|
1312
1312
|
});
|
|
1313
1313
|
var api_system_default = apiSystemRoutes;
|
|
1314
1314
|
var adminApiRoutes = new hono.Hono();
|
|
1315
|
-
adminApiRoutes.use("*",
|
|
1316
|
-
adminApiRoutes.use("*",
|
|
1315
|
+
adminApiRoutes.use("*", chunkXWPGIFS7_cjs.requireAuth());
|
|
1316
|
+
adminApiRoutes.use("*", chunkXWPGIFS7_cjs.requireRole(["admin", "editor"]));
|
|
1317
1317
|
adminApiRoutes.get("/stats", async (c) => {
|
|
1318
1318
|
try {
|
|
1319
1319
|
const db = c.env.DB;
|
|
@@ -1571,7 +1571,7 @@ adminApiRoutes.post("/collections", async (c) => {
|
|
|
1571
1571
|
}
|
|
1572
1572
|
const validatedData = validation.data;
|
|
1573
1573
|
const db = c.env.DB;
|
|
1574
|
-
const
|
|
1574
|
+
const _user = c.get("user");
|
|
1575
1575
|
const displayName = validatedData.displayName || validatedData.display_name || "";
|
|
1576
1576
|
const existingStmt = db.prepare("SELECT id FROM collections WHERE name = ?");
|
|
1577
1577
|
const existing = await existingStmt.bind(validatedData.name).first();
|
|
@@ -1722,7 +1722,7 @@ adminApiRoutes.delete("/collections/:id", async (c) => {
|
|
|
1722
1722
|
});
|
|
1723
1723
|
adminApiRoutes.get("/migrations/status", async (c) => {
|
|
1724
1724
|
try {
|
|
1725
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
1725
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-3A53GREK.cjs');
|
|
1726
1726
|
const db = c.env.DB;
|
|
1727
1727
|
const migrationService = new MigrationService2(db);
|
|
1728
1728
|
const status = await migrationService.getMigrationStatus();
|
|
@@ -1747,7 +1747,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
|
|
|
1747
1747
|
error: "Unauthorized. Admin access required."
|
|
1748
1748
|
}, 403);
|
|
1749
1749
|
}
|
|
1750
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
1750
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-3A53GREK.cjs');
|
|
1751
1751
|
const db = c.env.DB;
|
|
1752
1752
|
const migrationService = new MigrationService2(db);
|
|
1753
1753
|
const result = await migrationService.runPendingMigrations();
|
|
@@ -1766,7 +1766,7 @@ adminApiRoutes.post("/migrations/run", async (c) => {
|
|
|
1766
1766
|
});
|
|
1767
1767
|
adminApiRoutes.get("/migrations/validate", async (c) => {
|
|
1768
1768
|
try {
|
|
1769
|
-
const { MigrationService: MigrationService2 } = await import('./migrations-
|
|
1769
|
+
const { MigrationService: MigrationService2 } = await import('./migrations-3A53GREK.cjs');
|
|
1770
1770
|
const db = c.env.DB;
|
|
1771
1771
|
const migrationService = new MigrationService2(db);
|
|
1772
1772
|
const validation = await migrationService.validateSchema();
|
|
@@ -1841,8 +1841,8 @@ function renderLoginPage(data, demoLoginActive = false) {
|
|
|
1841
1841
|
<div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
|
|
1842
1842
|
<div class="bg-zinc-900 shadow-sm ring-1 ring-white/10 rounded-xl px-6 py-8 sm:px-10">
|
|
1843
1843
|
<!-- Alerts -->
|
|
1844
|
-
${data.error ? `<div class="mb-6">${
|
|
1845
|
-
${data.message ? `<div class="mb-6">${
|
|
1844
|
+
${data.error ? `<div class="mb-6">${chunkAZLU3ROK_cjs.renderAlert({ type: "error", message: data.error })}</div>` : ""}
|
|
1845
|
+
${data.message ? `<div class="mb-6">${chunkAZLU3ROK_cjs.renderAlert({ type: "success", message: data.message })}</div>` : ""}
|
|
1846
1846
|
|
|
1847
1847
|
<!-- Form Response (HTMX target) -->
|
|
1848
1848
|
<div id="form-response" class="mb-6"></div>
|
|
@@ -2006,7 +2006,7 @@ function renderRegisterPage(data) {
|
|
|
2006
2006
|
<div class="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
|
|
2007
2007
|
<div class="bg-zinc-900 shadow-sm ring-1 ring-white/10 rounded-xl px-6 py-8 sm:px-10">
|
|
2008
2008
|
<!-- Alerts -->
|
|
2009
|
-
${data.error ? `<div class="mb-6">${
|
|
2009
|
+
${data.error ? `<div class="mb-6">${chunkAZLU3ROK_cjs.renderAlert({ type: "error", message: data.error })}</div>` : ""}
|
|
2010
2010
|
|
|
2011
2011
|
<!-- Form -->
|
|
2012
2012
|
<form
|
|
@@ -2119,6 +2119,27 @@ function renderRegisterPage(data) {
|
|
|
2119
2119
|
</html>
|
|
2120
2120
|
`;
|
|
2121
2121
|
}
|
|
2122
|
+
async function isRegistrationEnabled(db) {
|
|
2123
|
+
try {
|
|
2124
|
+
const plugin = await db.prepare("SELECT settings FROM plugins WHERE id = ?").bind("core-auth").first();
|
|
2125
|
+
if (plugin?.settings) {
|
|
2126
|
+
const settings = JSON.parse(plugin.settings);
|
|
2127
|
+
const enabled = settings?.registration?.enabled;
|
|
2128
|
+
return enabled !== false && enabled !== 0;
|
|
2129
|
+
}
|
|
2130
|
+
return true;
|
|
2131
|
+
} catch {
|
|
2132
|
+
return true;
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
async function isFirstUserRegistration(db) {
|
|
2136
|
+
try {
|
|
2137
|
+
const result = await db.prepare("SELECT COUNT(*) as count FROM users").first();
|
|
2138
|
+
return result?.count === 0;
|
|
2139
|
+
} catch {
|
|
2140
|
+
return false;
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2122
2143
|
var baseRegistrationSchema = zod.z.object({
|
|
2123
2144
|
email: zod.z.string().email("Valid email is required"),
|
|
2124
2145
|
password: zod.z.string().min(8, "Password must be at least 8 characters"),
|
|
@@ -2170,7 +2191,15 @@ authRoutes.get("/login", async (c) => {
|
|
|
2170
2191
|
}
|
|
2171
2192
|
return c.html(renderLoginPage(pageData, demoLoginActive));
|
|
2172
2193
|
});
|
|
2173
|
-
authRoutes.get("/register", (c) => {
|
|
2194
|
+
authRoutes.get("/register", async (c) => {
|
|
2195
|
+
const db = c.env.DB;
|
|
2196
|
+
const isFirstUser = await isFirstUserRegistration(db);
|
|
2197
|
+
if (!isFirstUser) {
|
|
2198
|
+
const registrationEnabled = await isRegistrationEnabled(db);
|
|
2199
|
+
if (!registrationEnabled) {
|
|
2200
|
+
return c.redirect("/auth/login?error=Registration is currently disabled");
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2174
2203
|
const error = c.req.query("error");
|
|
2175
2204
|
const pageData = {
|
|
2176
2205
|
error: error || void 0
|
|
@@ -2186,6 +2215,13 @@ authRoutes.post(
|
|
|
2186
2215
|
async (c) => {
|
|
2187
2216
|
try {
|
|
2188
2217
|
const db = c.env.DB;
|
|
2218
|
+
const isFirstUser = await isFirstUserRegistration(db);
|
|
2219
|
+
if (!isFirstUser) {
|
|
2220
|
+
const registrationEnabled = await isRegistrationEnabled(db);
|
|
2221
|
+
if (!registrationEnabled) {
|
|
2222
|
+
return c.json({ error: "Registration is currently disabled" }, 403);
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2189
2225
|
let requestData;
|
|
2190
2226
|
try {
|
|
2191
2227
|
requestData = await c.req.json();
|
|
@@ -2212,7 +2248,7 @@ authRoutes.post(
|
|
|
2212
2248
|
if (existingUser) {
|
|
2213
2249
|
return c.json({ error: "User with this email or username already exists" }, 400);
|
|
2214
2250
|
}
|
|
2215
|
-
const passwordHash = await
|
|
2251
|
+
const passwordHash = await chunkXWPGIFS7_cjs.AuthManager.hashPassword(password);
|
|
2216
2252
|
const userId = crypto.randomUUID();
|
|
2217
2253
|
const now = /* @__PURE__ */ new Date();
|
|
2218
2254
|
await db.prepare(`
|
|
@@ -2232,7 +2268,7 @@ authRoutes.post(
|
|
|
2232
2268
|
now.getTime(),
|
|
2233
2269
|
now.getTime()
|
|
2234
2270
|
).run();
|
|
2235
|
-
const token = await
|
|
2271
|
+
const token = await chunkXWPGIFS7_cjs.AuthManager.generateToken(userId, normalizedEmail, "viewer");
|
|
2236
2272
|
cookie.setCookie(c, "auth_token", token, {
|
|
2237
2273
|
httpOnly: true,
|
|
2238
2274
|
secure: true,
|
|
@@ -2285,11 +2321,11 @@ authRoutes.post("/login", async (c) => {
|
|
|
2285
2321
|
if (!user) {
|
|
2286
2322
|
return c.json({ error: "Invalid email or password" }, 401);
|
|
2287
2323
|
}
|
|
2288
|
-
const isValidPassword = await
|
|
2324
|
+
const isValidPassword = await chunkXWPGIFS7_cjs.AuthManager.verifyPassword(password, user.password_hash);
|
|
2289
2325
|
if (!isValidPassword) {
|
|
2290
2326
|
return c.json({ error: "Invalid email or password" }, 401);
|
|
2291
2327
|
}
|
|
2292
|
-
const token = await
|
|
2328
|
+
const token = await chunkXWPGIFS7_cjs.AuthManager.generateToken(user.id, user.email, user.role);
|
|
2293
2329
|
cookie.setCookie(c, "auth_token", token, {
|
|
2294
2330
|
httpOnly: true,
|
|
2295
2331
|
secure: true,
|
|
@@ -2338,7 +2374,7 @@ authRoutes.get("/logout", (c) => {
|
|
|
2338
2374
|
});
|
|
2339
2375
|
return c.redirect("/auth/login?message=You have been logged out successfully");
|
|
2340
2376
|
});
|
|
2341
|
-
authRoutes.get("/me",
|
|
2377
|
+
authRoutes.get("/me", chunkXWPGIFS7_cjs.requireAuth(), async (c) => {
|
|
2342
2378
|
try {
|
|
2343
2379
|
const user = c.get("user");
|
|
2344
2380
|
if (!user) {
|
|
@@ -2355,13 +2391,13 @@ authRoutes.get("/me", chunkOJ5WUCSH_cjs.requireAuth(), async (c) => {
|
|
|
2355
2391
|
return c.json({ error: "Failed to get user" }, 500);
|
|
2356
2392
|
}
|
|
2357
2393
|
});
|
|
2358
|
-
authRoutes.post("/refresh",
|
|
2394
|
+
authRoutes.post("/refresh", chunkXWPGIFS7_cjs.requireAuth(), async (c) => {
|
|
2359
2395
|
try {
|
|
2360
2396
|
const user = c.get("user");
|
|
2361
2397
|
if (!user) {
|
|
2362
2398
|
return c.json({ error: "Not authenticated" }, 401);
|
|
2363
2399
|
}
|
|
2364
|
-
const token = await
|
|
2400
|
+
const token = await chunkXWPGIFS7_cjs.AuthManager.generateToken(user.userId, user.email, user.role);
|
|
2365
2401
|
cookie.setCookie(c, "auth_token", token, {
|
|
2366
2402
|
httpOnly: true,
|
|
2367
2403
|
secure: true,
|
|
@@ -2378,6 +2414,17 @@ authRoutes.post("/refresh", chunkOJ5WUCSH_cjs.requireAuth(), async (c) => {
|
|
|
2378
2414
|
authRoutes.post("/register/form", async (c) => {
|
|
2379
2415
|
try {
|
|
2380
2416
|
const db = c.env.DB;
|
|
2417
|
+
const isFirstUser = await isFirstUserRegistration(db);
|
|
2418
|
+
if (!isFirstUser) {
|
|
2419
|
+
const registrationEnabled = await isRegistrationEnabled(db);
|
|
2420
|
+
if (!registrationEnabled) {
|
|
2421
|
+
return c.html(html.html`
|
|
2422
|
+
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded">
|
|
2423
|
+
Registration is currently disabled. Please contact an administrator.
|
|
2424
|
+
</div>
|
|
2425
|
+
`);
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2381
2428
|
const formData = await c.req.formData();
|
|
2382
2429
|
const requestData = {
|
|
2383
2430
|
email: formData.get("email"),
|
|
@@ -2410,7 +2457,8 @@ authRoutes.post("/register/form", async (c) => {
|
|
|
2410
2457
|
</div>
|
|
2411
2458
|
`);
|
|
2412
2459
|
}
|
|
2413
|
-
const passwordHash = await
|
|
2460
|
+
const passwordHash = await chunkXWPGIFS7_cjs.AuthManager.hashPassword(password);
|
|
2461
|
+
const role = isFirstUser ? "admin" : "viewer";
|
|
2414
2462
|
const userId = crypto.randomUUID();
|
|
2415
2463
|
const now = /* @__PURE__ */ new Date();
|
|
2416
2464
|
await db.prepare(`
|
|
@@ -2423,14 +2471,13 @@ authRoutes.post("/register/form", async (c) => {
|
|
|
2423
2471
|
firstName,
|
|
2424
2472
|
lastName,
|
|
2425
2473
|
passwordHash,
|
|
2426
|
-
|
|
2427
|
-
// First user gets admin role
|
|
2474
|
+
role,
|
|
2428
2475
|
1,
|
|
2429
2476
|
// is_active
|
|
2430
2477
|
now.getTime(),
|
|
2431
2478
|
now.getTime()
|
|
2432
2479
|
).run();
|
|
2433
|
-
const token = await
|
|
2480
|
+
const token = await chunkXWPGIFS7_cjs.AuthManager.generateToken(userId, normalizedEmail, role);
|
|
2434
2481
|
cookie.setCookie(c, "auth_token", token, {
|
|
2435
2482
|
httpOnly: true,
|
|
2436
2483
|
secure: false,
|
|
@@ -2439,12 +2486,13 @@ authRoutes.post("/register/form", async (c) => {
|
|
|
2439
2486
|
maxAge: 60 * 60 * 24
|
|
2440
2487
|
// 24 hours
|
|
2441
2488
|
});
|
|
2489
|
+
const redirectUrl = role === "admin" ? "/admin/dashboard" : "/admin/dashboard";
|
|
2442
2490
|
return c.html(html.html`
|
|
2443
2491
|
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded">
|
|
2444
|
-
Account created successfully! Redirecting
|
|
2492
|
+
Account created successfully! Redirecting...
|
|
2445
2493
|
<script>
|
|
2446
2494
|
setTimeout(() => {
|
|
2447
|
-
window.location.href = '
|
|
2495
|
+
window.location.href = '${redirectUrl}';
|
|
2448
2496
|
}, 2000);
|
|
2449
2497
|
</script>
|
|
2450
2498
|
</div>
|
|
@@ -2481,7 +2529,7 @@ authRoutes.post("/login/form", async (c) => {
|
|
|
2481
2529
|
</div>
|
|
2482
2530
|
`);
|
|
2483
2531
|
}
|
|
2484
|
-
const isValidPassword = await
|
|
2532
|
+
const isValidPassword = await chunkXWPGIFS7_cjs.AuthManager.verifyPassword(password, user.password_hash);
|
|
2485
2533
|
if (!isValidPassword) {
|
|
2486
2534
|
return c.html(html.html`
|
|
2487
2535
|
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded">
|
|
@@ -2489,7 +2537,7 @@ authRoutes.post("/login/form", async (c) => {
|
|
|
2489
2537
|
</div>
|
|
2490
2538
|
`);
|
|
2491
2539
|
}
|
|
2492
|
-
const token = await
|
|
2540
|
+
const token = await chunkXWPGIFS7_cjs.AuthManager.generateToken(user.id, user.email, user.role);
|
|
2493
2541
|
cookie.setCookie(c, "auth_token", token, {
|
|
2494
2542
|
httpOnly: true,
|
|
2495
2543
|
secure: false,
|
|
@@ -2548,7 +2596,7 @@ authRoutes.post("/seed-admin", async (c) => {
|
|
|
2548
2596
|
`).run();
|
|
2549
2597
|
const existingAdmin = await db.prepare("SELECT id FROM users WHERE email = ? OR username = ?").bind("admin@sonicjs.com", "admin").first();
|
|
2550
2598
|
if (existingAdmin) {
|
|
2551
|
-
const passwordHash2 = await
|
|
2599
|
+
const passwordHash2 = await chunkXWPGIFS7_cjs.AuthManager.hashPassword("sonicjs!");
|
|
2552
2600
|
await db.prepare("UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?").bind(passwordHash2, Date.now(), existingAdmin.id).run();
|
|
2553
2601
|
return c.json({
|
|
2554
2602
|
message: "Admin user already exists (password updated)",
|
|
@@ -2560,7 +2608,7 @@ authRoutes.post("/seed-admin", async (c) => {
|
|
|
2560
2608
|
}
|
|
2561
2609
|
});
|
|
2562
2610
|
}
|
|
2563
|
-
const passwordHash = await
|
|
2611
|
+
const passwordHash = await chunkXWPGIFS7_cjs.AuthManager.hashPassword("sonicjs!");
|
|
2564
2612
|
const userId = "admin-user-id";
|
|
2565
2613
|
const now = Date.now();
|
|
2566
2614
|
const adminEmail = "admin@sonicjs.com".toLowerCase();
|
|
@@ -2780,7 +2828,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
2780
2828
|
if (existingUsername) {
|
|
2781
2829
|
return c.json({ error: "Username is already taken" }, 400);
|
|
2782
2830
|
}
|
|
2783
|
-
const passwordHash = await
|
|
2831
|
+
const passwordHash = await chunkXWPGIFS7_cjs.AuthManager.hashPassword(password);
|
|
2784
2832
|
const updateStmt = db.prepare(`
|
|
2785
2833
|
UPDATE users SET
|
|
2786
2834
|
username = ?,
|
|
@@ -2799,7 +2847,7 @@ authRoutes.post("/accept-invitation", async (c) => {
|
|
|
2799
2847
|
Date.now(),
|
|
2800
2848
|
invitedUser.id
|
|
2801
2849
|
).run();
|
|
2802
|
-
const authToken = await
|
|
2850
|
+
const authToken = await chunkXWPGIFS7_cjs.AuthManager.generateToken(invitedUser.id, invitedUser.email, invitedUser.role);
|
|
2803
2851
|
cookie.setCookie(c, "auth_token", authToken, {
|
|
2804
2852
|
httpOnly: true,
|
|
2805
2853
|
secure: true,
|
|
@@ -3029,7 +3077,7 @@ authRoutes.post("/reset-password", async (c) => {
|
|
|
3029
3077
|
if (Date.now() > user.password_reset_expires) {
|
|
3030
3078
|
return c.json({ error: "Reset token has expired" }, 400);
|
|
3031
3079
|
}
|
|
3032
|
-
const newPasswordHash = await
|
|
3080
|
+
const newPasswordHash = await chunkXWPGIFS7_cjs.AuthManager.hashPassword(password);
|
|
3033
3081
|
try {
|
|
3034
3082
|
const historyStmt = db.prepare(`
|
|
3035
3083
|
INSERT INTO password_history (id, user_id, password_hash, created_at)
|
|
@@ -3287,7 +3335,7 @@ app.post("/test-cleanup/content", async (c) => {
|
|
|
3287
3335
|
var test_cleanup_default = app;
|
|
3288
3336
|
|
|
3289
3337
|
// src/templates/pages/admin-content-form.template.ts
|
|
3290
|
-
|
|
3338
|
+
chunkAZLU3ROK_cjs.init_admin_layout_catalyst_template();
|
|
3291
3339
|
|
|
3292
3340
|
// src/templates/components/dynamic-field.template.ts
|
|
3293
3341
|
function renderDynamicField(field, options = {}) {
|
|
@@ -4428,6 +4476,13 @@ function getMDXEditorInitScript(config) {
|
|
|
4428
4476
|
// Store reference to editor instance
|
|
4429
4477
|
textarea.easyMDEInstance = easyMDE;
|
|
4430
4478
|
|
|
4479
|
+
// Sync changes back to textarea
|
|
4480
|
+
easyMDE.codemirror.on("change", () => {
|
|
4481
|
+
textarea.value = easyMDE.value();
|
|
4482
|
+
textarea.dispatchEvent(new Event("input", { bubbles: true }));
|
|
4483
|
+
textarea.dispatchEvent(new Event("change", { bubbles: true }));
|
|
4484
|
+
});
|
|
4485
|
+
|
|
4431
4486
|
console.log('EasyMDE initialized for field:', textarea.id || textarea.name);
|
|
4432
4487
|
} catch (error) {
|
|
4433
4488
|
console.error('Error initializing EasyMDE:', error);
|
|
@@ -4526,8 +4581,8 @@ function renderContentFormPage(data) {
|
|
|
4526
4581
|
<!-- Form Content -->
|
|
4527
4582
|
<div class="px-6 py-6">
|
|
4528
4583
|
<div id="form-messages">
|
|
4529
|
-
${data.error ?
|
|
4530
|
-
${data.success ?
|
|
4584
|
+
${data.error ? chunkAZLU3ROK_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
|
|
4585
|
+
${data.success ? chunkAZLU3ROK_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
|
|
4531
4586
|
</div>
|
|
4532
4587
|
|
|
4533
4588
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
@@ -4762,7 +4817,7 @@ function renderContentFormPage(data) {
|
|
|
4762
4817
|
</div>
|
|
4763
4818
|
|
|
4764
4819
|
<!-- Confirmation Dialogs -->
|
|
4765
|
-
${
|
|
4820
|
+
${chunkAZLU3ROK_cjs.renderConfirmationDialog({
|
|
4766
4821
|
id: "duplicate-content-confirm",
|
|
4767
4822
|
title: "Duplicate Content",
|
|
4768
4823
|
message: "Create a copy of this content?",
|
|
@@ -4773,7 +4828,7 @@ function renderContentFormPage(data) {
|
|
|
4773
4828
|
onConfirm: "performDuplicateContent()"
|
|
4774
4829
|
})}
|
|
4775
4830
|
|
|
4776
|
-
${
|
|
4831
|
+
${chunkAZLU3ROK_cjs.renderConfirmationDialog({
|
|
4777
4832
|
id: "delete-content-confirm",
|
|
4778
4833
|
title: "Delete Content",
|
|
4779
4834
|
message: "Are you sure you want to delete this content? This action cannot be undone.",
|
|
@@ -4784,7 +4839,7 @@ function renderContentFormPage(data) {
|
|
|
4784
4839
|
onConfirm: `performDeleteContent('${data.id}')`
|
|
4785
4840
|
})}
|
|
4786
4841
|
|
|
4787
|
-
${
|
|
4842
|
+
${chunkAZLU3ROK_cjs.getConfirmationDialogScript()}
|
|
4788
4843
|
|
|
4789
4844
|
${data.tinymceEnabled ? getTinyMCEScript(data.tinymceSettings?.apiKey) : "<!-- TinyMCE plugin not active -->"}
|
|
4790
4845
|
|
|
@@ -5089,11 +5144,11 @@ function renderContentFormPage(data) {
|
|
|
5089
5144
|
content: pageContent,
|
|
5090
5145
|
version: data.version
|
|
5091
5146
|
};
|
|
5092
|
-
return
|
|
5147
|
+
return chunkAZLU3ROK_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
5093
5148
|
}
|
|
5094
5149
|
|
|
5095
5150
|
// src/templates/pages/admin-content-list.template.ts
|
|
5096
|
-
|
|
5151
|
+
chunkAZLU3ROK_cjs.init_admin_layout_catalyst_template();
|
|
5097
5152
|
function renderContentListPage(data) {
|
|
5098
5153
|
const urlParams = new URLSearchParams();
|
|
5099
5154
|
if (data.modelName && data.modelName !== "all") urlParams.set("model", data.modelName);
|
|
@@ -5498,8 +5553,8 @@ function renderContentListPage(data) {
|
|
|
5498
5553
|
|
|
5499
5554
|
<!-- Content List -->
|
|
5500
5555
|
<div id="content-list">
|
|
5501
|
-
${
|
|
5502
|
-
${
|
|
5556
|
+
${chunkAZLU3ROK_cjs.renderTable(tableData)}
|
|
5557
|
+
${chunkAZLU3ROK_cjs.renderPagination(paginationData)}
|
|
5503
5558
|
</div>
|
|
5504
5559
|
|
|
5505
5560
|
</div>
|
|
@@ -5708,7 +5763,7 @@ function renderContentListPage(data) {
|
|
|
5708
5763
|
</script>
|
|
5709
5764
|
|
|
5710
5765
|
<!-- Confirmation Dialog for Bulk Actions -->
|
|
5711
|
-
${
|
|
5766
|
+
${chunkAZLU3ROK_cjs.renderConfirmationDialog({
|
|
5712
5767
|
id: "bulk-action-confirm",
|
|
5713
5768
|
title: "Confirm Bulk Action",
|
|
5714
5769
|
message: "Are you sure you want to perform this action? This operation will affect multiple items.",
|
|
@@ -5720,7 +5775,7 @@ function renderContentListPage(data) {
|
|
|
5720
5775
|
})}
|
|
5721
5776
|
|
|
5722
5777
|
<!-- Confirmation Dialog Script -->
|
|
5723
|
-
${
|
|
5778
|
+
${chunkAZLU3ROK_cjs.getConfirmationDialogScript()}
|
|
5724
5779
|
`;
|
|
5725
5780
|
const layoutData = {
|
|
5726
5781
|
title: "Content Management",
|
|
@@ -5730,7 +5785,7 @@ function renderContentListPage(data) {
|
|
|
5730
5785
|
version: data.version,
|
|
5731
5786
|
content: pageContent
|
|
5732
5787
|
};
|
|
5733
|
-
return
|
|
5788
|
+
return chunkAZLU3ROK_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
5734
5789
|
}
|
|
5735
5790
|
|
|
5736
5791
|
// src/templates/components/version-history.template.ts
|
|
@@ -5924,7 +5979,7 @@ async function isPluginActive2(db, pluginId) {
|
|
|
5924
5979
|
|
|
5925
5980
|
// src/routes/admin-content.ts
|
|
5926
5981
|
var adminContentRoutes = new hono.Hono();
|
|
5927
|
-
adminContentRoutes.use("*",
|
|
5982
|
+
adminContentRoutes.use("*", chunkXWPGIFS7_cjs.requireAuth());
|
|
5928
5983
|
async function getCollectionFields(db, collectionId) {
|
|
5929
5984
|
const cache = chunk7FOAMNTI_cjs.getCacheService(chunk7FOAMNTI_cjs.CACHE_CONFIGS.collection);
|
|
5930
5985
|
return cache.getOrSet(
|
|
@@ -6457,10 +6512,9 @@ adminContentRoutes.post("/", async (c) => {
|
|
|
6457
6512
|
const insertStmt = db.prepare(`
|
|
6458
6513
|
INSERT INTO content (
|
|
6459
6514
|
id, collection_id, slug, title, data, status,
|
|
6460
|
-
|
|
6461
|
-
meta_title, meta_description, author_id, created_by, created_at, updated_at
|
|
6515
|
+
author_id, created_at, updated_at
|
|
6462
6516
|
)
|
|
6463
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?,
|
|
6517
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
6464
6518
|
`);
|
|
6465
6519
|
await insertStmt.bind(
|
|
6466
6520
|
contentId,
|
|
@@ -6469,11 +6523,6 @@ adminContentRoutes.post("/", async (c) => {
|
|
|
6469
6523
|
data.title || "Untitled",
|
|
6470
6524
|
JSON.stringify(data),
|
|
6471
6525
|
status,
|
|
6472
|
-
scheduledPublishAt ? new Date(scheduledPublishAt).getTime() : null,
|
|
6473
|
-
scheduledUnpublishAt ? new Date(scheduledUnpublishAt).getTime() : null,
|
|
6474
|
-
data.meta_title || null,
|
|
6475
|
-
data.meta_description || null,
|
|
6476
|
-
user?.userId || "unknown",
|
|
6477
6526
|
user?.userId || "unknown",
|
|
6478
6527
|
now,
|
|
6479
6528
|
now
|
|
@@ -7139,7 +7188,7 @@ ${JSON.stringify(data, null, 2)}
|
|
|
7139
7188
|
var admin_content_default = adminContentRoutes;
|
|
7140
7189
|
|
|
7141
7190
|
// src/templates/pages/admin-profile.template.ts
|
|
7142
|
-
|
|
7191
|
+
chunkAZLU3ROK_cjs.init_admin_layout_catalyst_template();
|
|
7143
7192
|
function renderAvatarImage(avatarUrl, firstName, lastName) {
|
|
7144
7193
|
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">
|
|
7145
7194
|
${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>`}
|
|
@@ -7159,8 +7208,8 @@ function renderProfilePage(data) {
|
|
|
7159
7208
|
</div>
|
|
7160
7209
|
|
|
7161
7210
|
<!-- Alert Messages -->
|
|
7162
|
-
${data.error ?
|
|
7163
|
-
${data.success ?
|
|
7211
|
+
${data.error ? chunkAZLU3ROK_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
|
|
7212
|
+
${data.success ? chunkAZLU3ROK_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
|
|
7164
7213
|
|
|
7165
7214
|
<!-- Profile Form -->
|
|
7166
7215
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
|
@@ -7547,7 +7596,7 @@ function renderProfilePage(data) {
|
|
|
7547
7596
|
version: data.version,
|
|
7548
7597
|
content: pageContent
|
|
7549
7598
|
};
|
|
7550
|
-
return
|
|
7599
|
+
return chunkAZLU3ROK_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
7551
7600
|
}
|
|
7552
7601
|
|
|
7553
7602
|
// src/templates/components/alert.template.ts
|
|
@@ -7830,7 +7879,7 @@ function renderActivityLogsPage(data) {
|
|
|
7830
7879
|
user: data.user,
|
|
7831
7880
|
content: pageContent
|
|
7832
7881
|
};
|
|
7833
|
-
return
|
|
7882
|
+
return chunkAZLU3ROK_cjs.renderAdminLayout(layoutData);
|
|
7834
7883
|
}
|
|
7835
7884
|
function getActionBadgeClass(action) {
|
|
7836
7885
|
if (action.includes("login") || action.includes("logout")) {
|
|
@@ -7850,7 +7899,7 @@ function formatAction(action) {
|
|
|
7850
7899
|
}
|
|
7851
7900
|
|
|
7852
7901
|
// src/templates/pages/admin-user-edit.template.ts
|
|
7853
|
-
|
|
7902
|
+
chunkAZLU3ROK_cjs.init_admin_layout_catalyst_template();
|
|
7854
7903
|
|
|
7855
7904
|
// src/templates/components/confirmation-dialog.template.ts
|
|
7856
7905
|
function renderConfirmationDialog2(options) {
|
|
@@ -7971,8 +8020,8 @@ function renderUserEditPage(data) {
|
|
|
7971
8020
|
|
|
7972
8021
|
<!-- Alert Messages -->
|
|
7973
8022
|
<div id="form-messages">
|
|
7974
|
-
${data.error ?
|
|
7975
|
-
${data.success ?
|
|
8023
|
+
${data.error ? chunkAZLU3ROK_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
|
|
8024
|
+
${data.success ? chunkAZLU3ROK_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
|
|
7976
8025
|
</div>
|
|
7977
8026
|
|
|
7978
8027
|
<!-- User Edit Form -->
|
|
@@ -7991,7 +8040,7 @@ function renderUserEditPage(data) {
|
|
|
7991
8040
|
<input
|
|
7992
8041
|
type="text"
|
|
7993
8042
|
name="first_name"
|
|
7994
|
-
value="${
|
|
8043
|
+
value="${chunkSZE3XVET_cjs.escapeHtml(data.userToEdit.firstName || "")}"
|
|
7995
8044
|
required
|
|
7996
8045
|
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"
|
|
7997
8046
|
/>
|
|
@@ -8002,7 +8051,7 @@ function renderUserEditPage(data) {
|
|
|
8002
8051
|
<input
|
|
8003
8052
|
type="text"
|
|
8004
8053
|
name="last_name"
|
|
8005
|
-
value="${
|
|
8054
|
+
value="${chunkSZE3XVET_cjs.escapeHtml(data.userToEdit.lastName || "")}"
|
|
8006
8055
|
required
|
|
8007
8056
|
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"
|
|
8008
8057
|
/>
|
|
@@ -8013,7 +8062,7 @@ function renderUserEditPage(data) {
|
|
|
8013
8062
|
<input
|
|
8014
8063
|
type="text"
|
|
8015
8064
|
name="username"
|
|
8016
|
-
value="${
|
|
8065
|
+
value="${chunkSZE3XVET_cjs.escapeHtml(data.userToEdit.username || "")}"
|
|
8017
8066
|
required
|
|
8018
8067
|
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"
|
|
8019
8068
|
/>
|
|
@@ -8024,7 +8073,7 @@ function renderUserEditPage(data) {
|
|
|
8024
8073
|
<input
|
|
8025
8074
|
type="email"
|
|
8026
8075
|
name="email"
|
|
8027
|
-
value="${
|
|
8076
|
+
value="${chunkSZE3XVET_cjs.escapeHtml(data.userToEdit.email || "")}"
|
|
8028
8077
|
required
|
|
8029
8078
|
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"
|
|
8030
8079
|
/>
|
|
@@ -8035,7 +8084,7 @@ function renderUserEditPage(data) {
|
|
|
8035
8084
|
<input
|
|
8036
8085
|
type="tel"
|
|
8037
8086
|
name="phone"
|
|
8038
|
-
value="${
|
|
8087
|
+
value="${chunkSZE3XVET_cjs.escapeHtml(data.userToEdit.phone || "")}"
|
|
8039
8088
|
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"
|
|
8040
8089
|
/>
|
|
8041
8090
|
</div>
|
|
@@ -8049,7 +8098,7 @@ function renderUserEditPage(data) {
|
|
|
8049
8098
|
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"
|
|
8050
8099
|
>
|
|
8051
8100
|
${data.roles.map((role) => `
|
|
8052
|
-
<option value="${
|
|
8101
|
+
<option value="${chunkSZE3XVET_cjs.escapeHtml(role.value)}" ${data.userToEdit.role === role.value ? "selected" : ""}>${chunkSZE3XVET_cjs.escapeHtml(role.label)}</option>
|
|
8053
8102
|
`).join("")}
|
|
8054
8103
|
</select>
|
|
8055
8104
|
<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">
|
|
@@ -8065,7 +8114,7 @@ function renderUserEditPage(data) {
|
|
|
8065
8114
|
name="bio"
|
|
8066
8115
|
rows="3"
|
|
8067
8116
|
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"
|
|
8068
|
-
>${
|
|
8117
|
+
>${chunkSZE3XVET_cjs.escapeHtml(data.userToEdit.bio || "")}</textarea>
|
|
8069
8118
|
</div>
|
|
8070
8119
|
</div>
|
|
8071
8120
|
|
|
@@ -8265,11 +8314,11 @@ function renderUserEditPage(data) {
|
|
|
8265
8314
|
user: data.user,
|
|
8266
8315
|
content: pageContent
|
|
8267
8316
|
};
|
|
8268
|
-
return
|
|
8317
|
+
return chunkAZLU3ROK_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
8269
8318
|
}
|
|
8270
8319
|
|
|
8271
8320
|
// src/templates/pages/admin-user-new.template.ts
|
|
8272
|
-
|
|
8321
|
+
chunkAZLU3ROK_cjs.init_admin_layout_catalyst_template();
|
|
8273
8322
|
function renderUserNewPage(data) {
|
|
8274
8323
|
const pageContent = `
|
|
8275
8324
|
<div>
|
|
@@ -8308,8 +8357,8 @@ function renderUserNewPage(data) {
|
|
|
8308
8357
|
|
|
8309
8358
|
<!-- Alert Messages -->
|
|
8310
8359
|
<div id="form-messages">
|
|
8311
|
-
${data.error ?
|
|
8312
|
-
${data.success ?
|
|
8360
|
+
${data.error ? chunkAZLU3ROK_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
|
|
8361
|
+
${data.success ? chunkAZLU3ROK_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
|
|
8313
8362
|
</div>
|
|
8314
8363
|
|
|
8315
8364
|
<!-- User New Form -->
|
|
@@ -8553,11 +8602,11 @@ function renderUserNewPage(data) {
|
|
|
8553
8602
|
user: data.user,
|
|
8554
8603
|
content: pageContent
|
|
8555
8604
|
};
|
|
8556
|
-
return
|
|
8605
|
+
return chunkAZLU3ROK_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
8557
8606
|
}
|
|
8558
8607
|
|
|
8559
8608
|
// src/templates/pages/admin-users-list.template.ts
|
|
8560
|
-
|
|
8609
|
+
chunkAZLU3ROK_cjs.init_admin_layout_catalyst_template();
|
|
8561
8610
|
function renderUsersListPage(data) {
|
|
8562
8611
|
const columns = [
|
|
8563
8612
|
{
|
|
@@ -8708,8 +8757,8 @@ function renderUsersListPage(data) {
|
|
|
8708
8757
|
</div>
|
|
8709
8758
|
|
|
8710
8759
|
<!-- Alert Messages -->
|
|
8711
|
-
${data.error ?
|
|
8712
|
-
${data.success ?
|
|
8760
|
+
${data.error ? chunkAZLU3ROK_cjs.renderAlert({ type: "error", message: data.error, dismissible: true }) : ""}
|
|
8761
|
+
${data.success ? chunkAZLU3ROK_cjs.renderAlert({ type: "success", message: data.success, dismissible: true }) : ""}
|
|
8713
8762
|
|
|
8714
8763
|
<!-- Stats -->
|
|
8715
8764
|
<div class="mb-6">
|
|
@@ -8886,10 +8935,10 @@ function renderUsersListPage(data) {
|
|
|
8886
8935
|
</div>
|
|
8887
8936
|
|
|
8888
8937
|
<!-- Users Table -->
|
|
8889
|
-
${
|
|
8938
|
+
${chunkAZLU3ROK_cjs.renderTable(tableData)}
|
|
8890
8939
|
|
|
8891
8940
|
<!-- Pagination -->
|
|
8892
|
-
${data.pagination ?
|
|
8941
|
+
${data.pagination ? chunkAZLU3ROK_cjs.renderPagination(data.pagination) : ""}
|
|
8893
8942
|
</div>
|
|
8894
8943
|
|
|
8895
8944
|
<script>
|
|
@@ -8960,12 +9009,12 @@ function renderUsersListPage(data) {
|
|
|
8960
9009
|
version: data.version,
|
|
8961
9010
|
content: pageContent
|
|
8962
9011
|
};
|
|
8963
|
-
return
|
|
9012
|
+
return chunkAZLU3ROK_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
8964
9013
|
}
|
|
8965
9014
|
|
|
8966
9015
|
// src/routes/admin-users.ts
|
|
8967
9016
|
var userRoutes = new hono.Hono();
|
|
8968
|
-
userRoutes.use("*",
|
|
9017
|
+
userRoutes.use("*", chunkXWPGIFS7_cjs.requireAuth());
|
|
8969
9018
|
userRoutes.get("/", (c) => {
|
|
8970
9019
|
return c.redirect("/admin/dashboard");
|
|
8971
9020
|
});
|
|
@@ -9064,12 +9113,12 @@ userRoutes.put("/profile", async (c) => {
|
|
|
9064
9113
|
const db = c.env.DB;
|
|
9065
9114
|
try {
|
|
9066
9115
|
const formData = await c.req.formData();
|
|
9067
|
-
const firstName =
|
|
9068
|
-
const lastName =
|
|
9069
|
-
const username =
|
|
9116
|
+
const firstName = chunkSZE3XVET_cjs.sanitizeInput(formData.get("first_name")?.toString());
|
|
9117
|
+
const lastName = chunkSZE3XVET_cjs.sanitizeInput(formData.get("last_name")?.toString());
|
|
9118
|
+
const username = chunkSZE3XVET_cjs.sanitizeInput(formData.get("username")?.toString());
|
|
9070
9119
|
const email = formData.get("email")?.toString()?.trim().toLowerCase() || "";
|
|
9071
|
-
const phone =
|
|
9072
|
-
const bio =
|
|
9120
|
+
const phone = chunkSZE3XVET_cjs.sanitizeInput(formData.get("phone")?.toString()) || null;
|
|
9121
|
+
const bio = chunkSZE3XVET_cjs.sanitizeInput(formData.get("bio")?.toString()) || null;
|
|
9073
9122
|
const timezone = formData.get("timezone")?.toString() || "UTC";
|
|
9074
9123
|
const language = formData.get("language")?.toString() || "en";
|
|
9075
9124
|
const emailNotifications = formData.get("email_notifications") === "1";
|
|
@@ -9120,7 +9169,7 @@ userRoutes.put("/profile", async (c) => {
|
|
|
9120
9169
|
Date.now(),
|
|
9121
9170
|
user.userId
|
|
9122
9171
|
).run();
|
|
9123
|
-
await
|
|
9172
|
+
await chunkXWPGIFS7_cjs.logActivity(
|
|
9124
9173
|
db,
|
|
9125
9174
|
user.userId,
|
|
9126
9175
|
"profile.update",
|
|
@@ -9183,7 +9232,7 @@ userRoutes.post("/profile/avatar", async (c) => {
|
|
|
9183
9232
|
SELECT first_name, last_name FROM users WHERE id = ?
|
|
9184
9233
|
`);
|
|
9185
9234
|
const userData = await userStmt.bind(user.userId).first();
|
|
9186
|
-
await
|
|
9235
|
+
await chunkXWPGIFS7_cjs.logActivity(
|
|
9187
9236
|
db,
|
|
9188
9237
|
user.userId,
|
|
9189
9238
|
"profile.avatar_update",
|
|
@@ -9254,7 +9303,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
9254
9303
|
dismissible: true
|
|
9255
9304
|
}));
|
|
9256
9305
|
}
|
|
9257
|
-
const validPassword = await
|
|
9306
|
+
const validPassword = await chunkXWPGIFS7_cjs.AuthManager.verifyPassword(currentPassword, userData.password_hash);
|
|
9258
9307
|
if (!validPassword) {
|
|
9259
9308
|
return c.html(renderAlert2({
|
|
9260
9309
|
type: "error",
|
|
@@ -9262,7 +9311,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
9262
9311
|
dismissible: true
|
|
9263
9312
|
}));
|
|
9264
9313
|
}
|
|
9265
|
-
const newPasswordHash = await
|
|
9314
|
+
const newPasswordHash = await chunkXWPGIFS7_cjs.AuthManager.hashPassword(newPassword);
|
|
9266
9315
|
const historyStmt = db.prepare(`
|
|
9267
9316
|
INSERT INTO password_history (id, user_id, password_hash, created_at)
|
|
9268
9317
|
VALUES (?, ?, ?, ?)
|
|
@@ -9278,7 +9327,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
9278
9327
|
WHERE id = ?
|
|
9279
9328
|
`);
|
|
9280
9329
|
await updateStmt.bind(newPasswordHash, Date.now(), user.userId).run();
|
|
9281
|
-
await
|
|
9330
|
+
await chunkXWPGIFS7_cjs.logActivity(
|
|
9282
9331
|
db,
|
|
9283
9332
|
user.userId,
|
|
9284
9333
|
"profile.password_change",
|
|
@@ -9345,7 +9394,7 @@ userRoutes.get("/users", async (c) => {
|
|
|
9345
9394
|
`);
|
|
9346
9395
|
const countResult = await countStmt.bind(...params).first();
|
|
9347
9396
|
const totalUsers = countResult?.total || 0;
|
|
9348
|
-
await
|
|
9397
|
+
await chunkXWPGIFS7_cjs.logActivity(
|
|
9349
9398
|
db,
|
|
9350
9399
|
user.userId,
|
|
9351
9400
|
"users.list_view",
|
|
@@ -9447,12 +9496,12 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
9447
9496
|
const user = c.get("user");
|
|
9448
9497
|
try {
|
|
9449
9498
|
const formData = await c.req.formData();
|
|
9450
|
-
const firstName =
|
|
9451
|
-
const lastName =
|
|
9452
|
-
const username =
|
|
9499
|
+
const firstName = chunkSZE3XVET_cjs.sanitizeInput(formData.get("first_name")?.toString());
|
|
9500
|
+
const lastName = chunkSZE3XVET_cjs.sanitizeInput(formData.get("last_name")?.toString());
|
|
9501
|
+
const username = chunkSZE3XVET_cjs.sanitizeInput(formData.get("username")?.toString());
|
|
9453
9502
|
const email = formData.get("email")?.toString()?.trim().toLowerCase() || "";
|
|
9454
|
-
const phone =
|
|
9455
|
-
const bio =
|
|
9503
|
+
const phone = chunkSZE3XVET_cjs.sanitizeInput(formData.get("phone")?.toString()) || null;
|
|
9504
|
+
const bio = chunkSZE3XVET_cjs.sanitizeInput(formData.get("bio")?.toString()) || null;
|
|
9456
9505
|
const role = formData.get("role")?.toString() || "viewer";
|
|
9457
9506
|
const password = formData.get("password")?.toString() || "";
|
|
9458
9507
|
const confirmPassword = formData.get("confirm_password")?.toString() || "";
|
|
@@ -9499,7 +9548,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
9499
9548
|
dismissible: true
|
|
9500
9549
|
}));
|
|
9501
9550
|
}
|
|
9502
|
-
const passwordHash = await
|
|
9551
|
+
const passwordHash = await chunkXWPGIFS7_cjs.AuthManager.hashPassword(password);
|
|
9503
9552
|
const userId = crypto.randomUUID();
|
|
9504
9553
|
const createStmt = db.prepare(`
|
|
9505
9554
|
INSERT INTO users (
|
|
@@ -9522,7 +9571,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
9522
9571
|
Date.now(),
|
|
9523
9572
|
Date.now()
|
|
9524
9573
|
).run();
|
|
9525
|
-
await
|
|
9574
|
+
await chunkXWPGIFS7_cjs.logActivity(
|
|
9526
9575
|
db,
|
|
9527
9576
|
user.userId,
|
|
9528
9577
|
"user!.create",
|
|
@@ -9560,7 +9609,7 @@ userRoutes.get("/users/:id", async (c) => {
|
|
|
9560
9609
|
if (!userRecord) {
|
|
9561
9610
|
return c.json({ error: "User not found" }, 404);
|
|
9562
9611
|
}
|
|
9563
|
-
await
|
|
9612
|
+
await chunkXWPGIFS7_cjs.logActivity(
|
|
9564
9613
|
db,
|
|
9565
9614
|
user.userId,
|
|
9566
9615
|
"user!.view",
|
|
@@ -9653,12 +9702,12 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
9653
9702
|
const userId = c.req.param("id");
|
|
9654
9703
|
try {
|
|
9655
9704
|
const formData = await c.req.formData();
|
|
9656
|
-
const firstName =
|
|
9657
|
-
const lastName =
|
|
9658
|
-
const username =
|
|
9705
|
+
const firstName = chunkSZE3XVET_cjs.sanitizeInput(formData.get("first_name")?.toString());
|
|
9706
|
+
const lastName = chunkSZE3XVET_cjs.sanitizeInput(formData.get("last_name")?.toString());
|
|
9707
|
+
const username = chunkSZE3XVET_cjs.sanitizeInput(formData.get("username")?.toString());
|
|
9659
9708
|
const email = formData.get("email")?.toString()?.trim().toLowerCase() || "";
|
|
9660
|
-
const phone =
|
|
9661
|
-
const bio =
|
|
9709
|
+
const phone = chunkSZE3XVET_cjs.sanitizeInput(formData.get("phone")?.toString()) || null;
|
|
9710
|
+
const bio = chunkSZE3XVET_cjs.sanitizeInput(formData.get("bio")?.toString()) || null;
|
|
9662
9711
|
const role = formData.get("role")?.toString() || "viewer";
|
|
9663
9712
|
const isActive = formData.get("is_active") === "1";
|
|
9664
9713
|
const emailVerified = formData.get("email_verified") === "1";
|
|
@@ -9709,7 +9758,7 @@ userRoutes.put("/users/:id", async (c) => {
|
|
|
9709
9758
|
Date.now(),
|
|
9710
9759
|
userId
|
|
9711
9760
|
).run();
|
|
9712
|
-
await
|
|
9761
|
+
await chunkXWPGIFS7_cjs.logActivity(
|
|
9713
9762
|
db,
|
|
9714
9763
|
user.userId,
|
|
9715
9764
|
"user!.update",
|
|
@@ -9754,7 +9803,7 @@ userRoutes.post("/users/:id/toggle", async (c) => {
|
|
|
9754
9803
|
UPDATE users SET is_active = ?, updated_at = ? WHERE id = ?
|
|
9755
9804
|
`);
|
|
9756
9805
|
await toggleStmt.bind(active ? 1 : 0, Date.now(), userId).run();
|
|
9757
|
-
await
|
|
9806
|
+
await chunkXWPGIFS7_cjs.logActivity(
|
|
9758
9807
|
db,
|
|
9759
9808
|
user.userId,
|
|
9760
9809
|
active ? "user.activate" : "user.deactivate",
|
|
@@ -9795,7 +9844,7 @@ userRoutes.delete("/users/:id", async (c) => {
|
|
|
9795
9844
|
DELETE FROM users WHERE id = ?
|
|
9796
9845
|
`);
|
|
9797
9846
|
await deleteStmt.bind(userId).run();
|
|
9798
|
-
await
|
|
9847
|
+
await chunkXWPGIFS7_cjs.logActivity(
|
|
9799
9848
|
db,
|
|
9800
9849
|
user.userId,
|
|
9801
9850
|
"user!.hard_delete",
|
|
@@ -9814,7 +9863,7 @@ userRoutes.delete("/users/:id", async (c) => {
|
|
|
9814
9863
|
UPDATE users SET is_active = 0, updated_at = ? WHERE id = ?
|
|
9815
9864
|
`);
|
|
9816
9865
|
await deleteStmt.bind(Date.now(), userId).run();
|
|
9817
|
-
await
|
|
9866
|
+
await chunkXWPGIFS7_cjs.logActivity(
|
|
9818
9867
|
db,
|
|
9819
9868
|
user.userId,
|
|
9820
9869
|
"user!.soft_delete",
|
|
@@ -9841,8 +9890,8 @@ userRoutes.post("/invite-user", async (c) => {
|
|
|
9841
9890
|
const formData = await c.req.formData();
|
|
9842
9891
|
const email = formData.get("email")?.toString()?.trim().toLowerCase() || "";
|
|
9843
9892
|
const role = formData.get("role")?.toString()?.trim() || "viewer";
|
|
9844
|
-
const firstName =
|
|
9845
|
-
const lastName =
|
|
9893
|
+
const firstName = chunkSZE3XVET_cjs.sanitizeInput(formData.get("first_name")?.toString());
|
|
9894
|
+
const lastName = chunkSZE3XVET_cjs.sanitizeInput(formData.get("last_name")?.toString());
|
|
9846
9895
|
if (!email || !firstName || !lastName) {
|
|
9847
9896
|
return c.json({ error: "Email, first name, and last name are required" }, 400);
|
|
9848
9897
|
}
|
|
@@ -9880,7 +9929,7 @@ userRoutes.post("/invite-user", async (c) => {
|
|
|
9880
9929
|
Date.now(),
|
|
9881
9930
|
Date.now()
|
|
9882
9931
|
).run();
|
|
9883
|
-
await
|
|
9932
|
+
await chunkXWPGIFS7_cjs.logActivity(
|
|
9884
9933
|
db,
|
|
9885
9934
|
user.userId,
|
|
9886
9935
|
"user!.invite_sent",
|
|
@@ -9937,7 +9986,7 @@ userRoutes.post("/resend-invitation/:id", async (c) => {
|
|
|
9937
9986
|
Date.now(),
|
|
9938
9987
|
userId
|
|
9939
9988
|
).run();
|
|
9940
|
-
await
|
|
9989
|
+
await chunkXWPGIFS7_cjs.logActivity(
|
|
9941
9990
|
db,
|
|
9942
9991
|
user.userId,
|
|
9943
9992
|
"user!.invitation_resent",
|
|
@@ -9973,7 +10022,7 @@ userRoutes.delete("/cancel-invitation/:id", async (c) => {
|
|
|
9973
10022
|
}
|
|
9974
10023
|
const deleteStmt = db.prepare(`DELETE FROM users WHERE id = ?`);
|
|
9975
10024
|
await deleteStmt.bind(userId).run();
|
|
9976
|
-
await
|
|
10025
|
+
await chunkXWPGIFS7_cjs.logActivity(
|
|
9977
10026
|
db,
|
|
9978
10027
|
user.userId,
|
|
9979
10028
|
"user!.invitation_cancelled",
|
|
@@ -10056,7 +10105,7 @@ userRoutes.get("/activity-logs", async (c) => {
|
|
|
10056
10105
|
...log,
|
|
10057
10106
|
details: log.details ? JSON.parse(log.details) : null
|
|
10058
10107
|
}));
|
|
10059
|
-
await
|
|
10108
|
+
await chunkXWPGIFS7_cjs.logActivity(
|
|
10060
10109
|
db,
|
|
10061
10110
|
user.userId,
|
|
10062
10111
|
"activity.logs_viewed",
|
|
@@ -10163,7 +10212,7 @@ userRoutes.get("/activity-logs/export", async (c) => {
|
|
|
10163
10212
|
csvRows.push(row.join(","));
|
|
10164
10213
|
}
|
|
10165
10214
|
const csvContent = csvRows.join("\n");
|
|
10166
|
-
await
|
|
10215
|
+
await chunkXWPGIFS7_cjs.logActivity(
|
|
10167
10216
|
db,
|
|
10168
10217
|
user.userId,
|
|
10169
10218
|
"activity.logs_exported",
|
|
@@ -10381,7 +10430,7 @@ function getFileIcon(mimeType) {
|
|
|
10381
10430
|
}
|
|
10382
10431
|
|
|
10383
10432
|
// src/templates/pages/admin-media-library.template.ts
|
|
10384
|
-
|
|
10433
|
+
chunkAZLU3ROK_cjs.init_admin_layout_catalyst_template();
|
|
10385
10434
|
function renderMediaLibraryPage(data) {
|
|
10386
10435
|
const pageContent = `
|
|
10387
10436
|
<div>
|
|
@@ -11316,7 +11365,7 @@ function renderMediaLibraryPage(data) {
|
|
|
11316
11365
|
version: data.version,
|
|
11317
11366
|
content: pageContent
|
|
11318
11367
|
};
|
|
11319
|
-
return
|
|
11368
|
+
return chunkAZLU3ROK_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
11320
11369
|
}
|
|
11321
11370
|
|
|
11322
11371
|
// src/templates/components/media-file-details.template.ts
|
|
@@ -11502,7 +11551,7 @@ var fileValidationSchema2 = zod.z.object({
|
|
|
11502
11551
|
// 50MB max
|
|
11503
11552
|
});
|
|
11504
11553
|
var adminMediaRoutes = new hono.Hono();
|
|
11505
|
-
adminMediaRoutes.use("*",
|
|
11554
|
+
adminMediaRoutes.use("*", chunkXWPGIFS7_cjs.requireAuth());
|
|
11506
11555
|
adminMediaRoutes.get("/", async (c) => {
|
|
11507
11556
|
try {
|
|
11508
11557
|
const user = c.get("user");
|
|
@@ -11511,7 +11560,7 @@ adminMediaRoutes.get("/", async (c) => {
|
|
|
11511
11560
|
const type = searchParams.get("type") || "all";
|
|
11512
11561
|
const view = searchParams.get("view") || "grid";
|
|
11513
11562
|
const page = parseInt(searchParams.get("page") || "1");
|
|
11514
|
-
const
|
|
11563
|
+
const _cacheBust = searchParams.get("t");
|
|
11515
11564
|
const limit = 24;
|
|
11516
11565
|
const offset = (page - 1) * limit;
|
|
11517
11566
|
const db = c.env.DB;
|
|
@@ -12088,7 +12137,7 @@ adminMediaRoutes.put("/:id", async (c) => {
|
|
|
12088
12137
|
`);
|
|
12089
12138
|
}
|
|
12090
12139
|
});
|
|
12091
|
-
adminMediaRoutes.delete("/cleanup",
|
|
12140
|
+
adminMediaRoutes.delete("/cleanup", chunkXWPGIFS7_cjs.requireRole("admin"), async (c) => {
|
|
12092
12141
|
try {
|
|
12093
12142
|
const db = c.env.DB;
|
|
12094
12143
|
const allMediaStmt = db.prepare("SELECT id, r2_key, filename FROM media WHERE deleted_at IS NULL");
|
|
@@ -12338,12 +12387,39 @@ function formatFileSize(bytes) {
|
|
|
12338
12387
|
}
|
|
12339
12388
|
|
|
12340
12389
|
// src/templates/pages/admin-plugins-list.template.ts
|
|
12341
|
-
|
|
12390
|
+
chunkAZLU3ROK_cjs.init_admin_layout_catalyst_template();
|
|
12342
12391
|
function renderPluginsListPage(data) {
|
|
12392
|
+
const categories = [
|
|
12393
|
+
{ value: "content", label: "Content Management" },
|
|
12394
|
+
{ value: "media", label: "Media" },
|
|
12395
|
+
{ value: "editor", label: "Editors" },
|
|
12396
|
+
{ value: "seo", label: "SEO & Analytics" },
|
|
12397
|
+
{ value: "security", label: "Security" },
|
|
12398
|
+
{ value: "utilities", label: "Utilities" },
|
|
12399
|
+
{ value: "system", label: "System" },
|
|
12400
|
+
{ value: "development", label: "Development" },
|
|
12401
|
+
{ value: "demo", label: "Demo" }
|
|
12402
|
+
];
|
|
12403
|
+
const statuses = [
|
|
12404
|
+
{ value: "active", label: "Active" },
|
|
12405
|
+
{ value: "inactive", label: "Inactive" },
|
|
12406
|
+
{ value: "uninstalled", label: "Available to Install" },
|
|
12407
|
+
{ value: "error", label: "Error" }
|
|
12408
|
+
];
|
|
12409
|
+
const categoryCounts = {};
|
|
12410
|
+
categories.forEach((cat) => {
|
|
12411
|
+
categoryCounts[cat.value] = data.plugins.filter((p) => p.category === cat.value).length;
|
|
12412
|
+
});
|
|
12413
|
+
categories.sort((a, b) => (categoryCounts[b.value] || 0) - (categoryCounts[a.value] || 0));
|
|
12414
|
+
const statusCounts = {};
|
|
12415
|
+
statuses.forEach((status) => {
|
|
12416
|
+
statusCounts[status.value] = data.plugins.filter((p) => p.status === status.value).length;
|
|
12417
|
+
});
|
|
12418
|
+
statuses.sort((a, b) => (statusCounts[b.value] || 0) - (statusCounts[a.value] || 0));
|
|
12343
12419
|
const pageContent = `
|
|
12344
12420
|
<div>
|
|
12345
12421
|
<!-- Header -->
|
|
12346
|
-
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-
|
|
12422
|
+
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-8">
|
|
12347
12423
|
<div>
|
|
12348
12424
|
<h1 class="text-2xl/8 font-semibold text-zinc-950 dark:text-white sm:text-xl/8">Plugins</h1>
|
|
12349
12425
|
<p class="mt-2 text-sm/6 text-zinc-500 dark:text-zinc-400">Manage and extend functionality with plugins</p>
|
|
@@ -12351,7 +12427,7 @@ function renderPluginsListPage(data) {
|
|
|
12351
12427
|
</div>
|
|
12352
12428
|
|
|
12353
12429
|
<!-- Experimental Notice -->
|
|
12354
|
-
<div class="mb-
|
|
12430
|
+
<div class="mb-8 rounded-lg bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800/50 p-4">
|
|
12355
12431
|
<div class="flex items-start">
|
|
12356
12432
|
<div class="flex-shrink-0">
|
|
12357
12433
|
<svg class="h-5 w-5 text-amber-600 dark:text-amber-400" viewBox="0 0 20 20" fill="currentColor">
|
|
@@ -12372,176 +12448,174 @@ function renderPluginsListPage(data) {
|
|
|
12372
12448
|
</div>
|
|
12373
12449
|
</div>
|
|
12374
12450
|
|
|
12375
|
-
|
|
12376
|
-
|
|
12377
|
-
<
|
|
12378
|
-
|
|
12379
|
-
<div
|
|
12380
|
-
<
|
|
12381
|
-
<
|
|
12382
|
-
|
|
12383
|
-
|
|
12384
|
-
|
|
12385
|
-
|
|
12386
|
-
<
|
|
12387
|
-
<
|
|
12388
|
-
|
|
12389
|
-
|
|
12390
|
-
|
|
12391
|
-
|
|
12392
|
-
|
|
12393
|
-
|
|
12394
|
-
|
|
12395
|
-
|
|
12396
|
-
|
|
12397
|
-
|
|
12398
|
-
|
|
12399
|
-
|
|
12400
|
-
|
|
12401
|
-
|
|
12402
|
-
|
|
12403
|
-
</svg>
|
|
12404
|
-
<span class="sr-only">Increased by</span>
|
|
12405
|
-
12.3%
|
|
12406
|
-
</div>
|
|
12407
|
-
</dd>
|
|
12451
|
+
<div class="flex flex-col lg:flex-row gap-8">
|
|
12452
|
+
<!-- Sidebar Filters -->
|
|
12453
|
+
<aside class="w-full lg:w-48 flex-shrink-0 space-y-8 lg:sticky lg:top-6 lg:self-start">
|
|
12454
|
+
<!-- Categories Filter -->
|
|
12455
|
+
<div>
|
|
12456
|
+
<h3 class="text-sm font-semibold text-zinc-950 dark:text-white mb-4">Categories</h3>
|
|
12457
|
+
<div class="space-y-3">
|
|
12458
|
+
${categories.map((cat) => {
|
|
12459
|
+
const count = categoryCounts[cat.value] || 0;
|
|
12460
|
+
const isDisabled = count === 0;
|
|
12461
|
+
return `
|
|
12462
|
+
<div class="flex items-center ${isDisabled ? "opacity-50" : ""}">
|
|
12463
|
+
<input
|
|
12464
|
+
id="category-${cat.value}"
|
|
12465
|
+
name="category"
|
|
12466
|
+
value="${cat.value}"
|
|
12467
|
+
type="checkbox"
|
|
12468
|
+
onchange="filterAndSortPlugins()"
|
|
12469
|
+
class="h-4 w-4 rounded border-zinc-300 dark:border-zinc-700 text-zinc-900 focus:ring-zinc-600 dark:bg-zinc-900 disabled:cursor-not-allowed"
|
|
12470
|
+
${isDisabled ? "disabled" : ""}
|
|
12471
|
+
>
|
|
12472
|
+
<label for="category-${cat.value}" class="ml-3 text-sm text-zinc-600 dark:text-zinc-400 select-none ${isDisabled ? "cursor-not-allowed" : ""}">
|
|
12473
|
+
${cat.label} <span class="text-zinc-400 dark:text-zinc-500">(${count})</span>
|
|
12474
|
+
</label>
|
|
12475
|
+
</div>
|
|
12476
|
+
`;
|
|
12477
|
+
}).join("")}
|
|
12478
|
+
</div>
|
|
12408
12479
|
</div>
|
|
12409
|
-
|
|
12410
|
-
|
|
12411
|
-
|
|
12412
|
-
|
|
12413
|
-
|
|
12414
|
-
|
|
12415
|
-
|
|
12416
|
-
|
|
12417
|
-
|
|
12418
|
-
|
|
12419
|
-
|
|
12420
|
-
|
|
12421
|
-
|
|
12422
|
-
|
|
12480
|
+
|
|
12481
|
+
<div class="h-px bg-zinc-200 dark:bg-zinc-800 lg:hidden"></div>
|
|
12482
|
+
|
|
12483
|
+
<!-- Status Filter -->
|
|
12484
|
+
<div>
|
|
12485
|
+
<h3 class="text-sm font-semibold text-zinc-950 dark:text-white mb-4">Status</h3>
|
|
12486
|
+
<div class="space-y-3">
|
|
12487
|
+
${statuses.map((status) => {
|
|
12488
|
+
const count = statusCounts[status.value] || 0;
|
|
12489
|
+
const isDisabled = count === 0;
|
|
12490
|
+
let colorClass = "";
|
|
12491
|
+
let ringClass = "";
|
|
12492
|
+
let dotClass = "";
|
|
12493
|
+
switch (status.value) {
|
|
12494
|
+
case "active":
|
|
12495
|
+
colorClass = "text-emerald-700 dark:text-emerald-400 bg-emerald-50 dark:bg-emerald-500/10";
|
|
12496
|
+
ringClass = "ring-emerald-600/20";
|
|
12497
|
+
dotClass = "bg-emerald-500 dark:bg-emerald-400";
|
|
12498
|
+
break;
|
|
12499
|
+
case "inactive":
|
|
12500
|
+
colorClass = "text-zinc-700 dark:text-zinc-400 bg-zinc-50 dark:bg-zinc-500/10";
|
|
12501
|
+
ringClass = "ring-zinc-600/20";
|
|
12502
|
+
dotClass = "bg-zinc-500 dark:bg-zinc-400";
|
|
12503
|
+
break;
|
|
12504
|
+
case "error":
|
|
12505
|
+
colorClass = "text-red-700 dark:text-red-400 bg-red-50 dark:bg-red-500/10";
|
|
12506
|
+
ringClass = "ring-red-600/20";
|
|
12507
|
+
dotClass = "bg-red-500 dark:bg-red-400";
|
|
12508
|
+
break;
|
|
12509
|
+
case "uninstalled":
|
|
12510
|
+
colorClass = "text-yellow-700 dark:text-yellow-400 bg-yellow-50 dark:bg-yellow-500/10";
|
|
12511
|
+
ringClass = "ring-yellow-600/20";
|
|
12512
|
+
dotClass = "bg-yellow-500 dark:bg-yellow-400";
|
|
12513
|
+
break;
|
|
12514
|
+
default:
|
|
12515
|
+
colorClass = "text-zinc-700 dark:text-zinc-400 bg-zinc-50 dark:bg-zinc-500/10";
|
|
12516
|
+
ringClass = "ring-zinc-600/20";
|
|
12517
|
+
dotClass = "bg-zinc-500 dark:bg-zinc-400";
|
|
12518
|
+
}
|
|
12519
|
+
return `
|
|
12520
|
+
<div class="flex items-center ${isDisabled ? "opacity-50" : ""}">
|
|
12521
|
+
<input
|
|
12522
|
+
id="status-${status.value}"
|
|
12523
|
+
name="status"
|
|
12524
|
+
value="${status.value}"
|
|
12525
|
+
type="checkbox"
|
|
12526
|
+
onchange="filterAndSortPlugins()"
|
|
12527
|
+
class="h-4 w-4 rounded border-zinc-300 dark:border-zinc-700 text-zinc-900 focus:ring-zinc-600 dark:bg-zinc-900 disabled:cursor-not-allowed"
|
|
12528
|
+
${isDisabled ? "disabled" : ""}
|
|
12529
|
+
>
|
|
12530
|
+
<label for="status-${status.value}" class="ml-3 cursor-pointer select-none flex items-center ${isDisabled ? "cursor-not-allowed" : ""}">
|
|
12531
|
+
<span class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium ring-1 ring-inset ${colorClass} ${ringClass}">
|
|
12532
|
+
<span class="mr-1.5 h-1.5 w-1.5 rounded-full ${dotClass}"></span>
|
|
12533
|
+
${status.label}
|
|
12534
|
+
</span>
|
|
12535
|
+
<span class="ml-2 text-xs text-zinc-500 dark:text-zinc-400">(${count})</span>
|
|
12536
|
+
</label>
|
|
12537
|
+
</div>
|
|
12538
|
+
`;
|
|
12539
|
+
}).join("")}
|
|
12540
|
+
</div>
|
|
12423
12541
|
</div>
|
|
12424
|
-
|
|
12425
|
-
|
|
12426
|
-
|
|
12427
|
-
|
|
12428
|
-
|
|
12429
|
-
|
|
12430
|
-
|
|
12431
|
-
|
|
12432
|
-
|
|
12433
|
-
|
|
12434
|
-
|
|
12435
|
-
|
|
12436
|
-
</div>
|
|
12437
|
-
</
|
|
12542
|
+
</aside>
|
|
12543
|
+
|
|
12544
|
+
<!-- Main Content -->
|
|
12545
|
+
<div class="flex-1 min-w-0">
|
|
12546
|
+
<!-- Stats Row (Compact) -->
|
|
12547
|
+
<div class="flex flex-wrap gap-4 mb-6">
|
|
12548
|
+
<div class="min-w-[140px] rounded-lg bg-zinc-50 dark:bg-zinc-800/50 p-3 ring-1 ring-inset ring-zinc-950/5 dark:ring-white/5">
|
|
12549
|
+
<div class="text-xs font-medium text-zinc-500 dark:text-zinc-400">Total</div>
|
|
12550
|
+
<div class="mt-1 text-lg font-semibold text-zinc-900 dark:text-white">${data.stats?.total || 0}</div>
|
|
12551
|
+
</div>
|
|
12552
|
+
<div class="min-w-[140px] rounded-lg bg-zinc-50 dark:bg-zinc-800/50 p-3 ring-1 ring-inset ring-zinc-950/5 dark:ring-white/5">
|
|
12553
|
+
<div class="text-xs font-medium text-zinc-500 dark:text-zinc-400">Active</div>
|
|
12554
|
+
<div class="mt-1 text-lg font-semibold text-emerald-600 dark:text-emerald-400">${data.stats?.active || 0}</div>
|
|
12555
|
+
</div>
|
|
12556
|
+
<div class="min-w-[140px] rounded-lg bg-zinc-50 dark:bg-zinc-800/50 p-3 ring-1 ring-inset ring-zinc-950/5 dark:ring-white/5">
|
|
12557
|
+
<div class="text-xs font-medium text-zinc-500 dark:text-zinc-400">Available</div>
|
|
12558
|
+
<div class="mt-1 text-lg font-semibold text-zinc-600 dark:text-zinc-400">${data.stats?.uninstalled || 0}</div>
|
|
12559
|
+
</div>
|
|
12560
|
+
<div class="min-w-[140px] rounded-lg bg-zinc-50 dark:bg-zinc-800/50 p-3 ring-1 ring-inset ring-zinc-950/5 dark:ring-white/5">
|
|
12561
|
+
<div class="text-xs font-medium text-zinc-500 dark:text-zinc-400">Errors</div>
|
|
12562
|
+
<div class="mt-1 text-lg font-semibold text-red-600 dark:text-red-400">${data.stats?.errors || 0}</div>
|
|
12563
|
+
</div>
|
|
12438
12564
|
</div>
|
|
12439
|
-
|
|
12440
|
-
|
|
12441
|
-
|
|
12442
|
-
|
|
12443
|
-
|
|
12444
|
-
|
|
12445
|
-
|
|
12446
|
-
<svg viewBox="0 0 20 20" fill="currentColor" class="-ml-1 mr-0.5 size-5 shrink-0 self-center">
|
|
12447
|
-
<path d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z" />
|
|
12565
|
+
|
|
12566
|
+
<!-- Toolbar -->
|
|
12567
|
+
<div class="flex flex-col sm:flex-row gap-4 items-start sm:items-center justify-between mb-6">
|
|
12568
|
+
<div class="relative flex-1 w-full">
|
|
12569
|
+
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
|
|
12570
|
+
<svg class="h-4 w-4 text-zinc-400" viewBox="0 0 20 20" fill="currentColor">
|
|
12571
|
+
<path fill-rule="evenodd" d="M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z" clip-rule="evenodd" />
|
|
12448
12572
|
</svg>
|
|
12449
|
-
<span class="sr-only">Available</span>
|
|
12450
|
-
Ready
|
|
12451
12573
|
</div>
|
|
12452
|
-
|
|
12453
|
-
|
|
12454
|
-
|
|
12455
|
-
|
|
12574
|
+
<input
|
|
12575
|
+
id="search-input"
|
|
12576
|
+
type="text"
|
|
12577
|
+
placeholder="Search plugins..."
|
|
12578
|
+
oninput="filterAndSortPlugins()"
|
|
12579
|
+
class="block w-full h-9 rounded-md border-0 py-1.5 pl-10 text-zinc-900 ring-1 ring-inset ring-zinc-300 placeholder:text-zinc-400 focus:ring-2 focus:ring-inset focus:ring-zinc-600 dark:bg-zinc-900 dark:text-white dark:ring-zinc-700 dark:focus:ring-zinc-500 sm:text-sm sm:leading-6"
|
|
12580
|
+
>
|
|
12581
|
+
</div>
|
|
12456
12582
|
|
|
12457
|
-
|
|
12458
|
-
|
|
12459
|
-
|
|
12460
|
-
|
|
12583
|
+
<div class="flex items-center gap-3 w-full sm:w-auto">
|
|
12584
|
+
<select id="sort-filter" onchange="filterAndSortPlugins()" class="block w-full sm:w-auto h-9 rounded-md border-0 py-1.5 pl-3 pr-8 text-zinc-900 ring-1 ring-inset ring-zinc-300 focus:ring-2 focus:ring-inset focus:ring-zinc-600 dark:bg-zinc-900 dark:text-white dark:ring-zinc-700 dark:focus:ring-zinc-500 sm:text-sm sm:leading-6">
|
|
12585
|
+
<option value="name-asc">Name (A-Z)</option>
|
|
12586
|
+
<option value="name-desc">Name (Z-A)</option>
|
|
12587
|
+
<option value="newest">Newest Installed</option>
|
|
12588
|
+
<option value="updated">Recently Updated</option>
|
|
12589
|
+
<option value="popular">Popularity</option>
|
|
12590
|
+
<option value="rating">Highest Rated</option>
|
|
12591
|
+
</select>
|
|
12461
12592
|
|
|
12462
|
-
|
|
12463
|
-
|
|
12464
|
-
|
|
12465
|
-
|
|
12466
|
-
<
|
|
12467
|
-
<
|
|
12468
|
-
|
|
12469
|
-
|
|
12470
|
-
<option value="">All Categories</option>
|
|
12471
|
-
<option value="content">Content Management</option>
|
|
12472
|
-
<option value="media">Media</option>
|
|
12473
|
-
<option value="seo">SEO & Analytics</option>
|
|
12474
|
-
<option value="security">Security</option>
|
|
12475
|
-
<option value="utilities">Utilities</option>
|
|
12476
|
-
<option value="system">System</option>
|
|
12477
|
-
<option value="development">Development</option>
|
|
12478
|
-
<option value="demo">Demo</option>
|
|
12479
|
-
</select>
|
|
12480
|
-
<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-cyan-600 dark:text-cyan-400 sm:size-4">
|
|
12481
|
-
<path d="M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" fill-rule="evenodd" />
|
|
12482
|
-
</svg>
|
|
12483
|
-
</div>
|
|
12484
|
-
</div>
|
|
12485
|
-
<div>
|
|
12486
|
-
<label class="block text-sm/6 font-medium text-zinc-950 dark:text-white">Status</label>
|
|
12487
|
-
<div class="mt-2 grid grid-cols-1">
|
|
12488
|
-
<select id="status-filter" onchange="filterPlugins()" 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-cyan-500/30 dark:outline-cyan-400/30 *:bg-white dark:*:bg-zinc-800 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-cyan-500 dark:focus-visible:outline-cyan-400 sm:text-sm/6 min-w-48">
|
|
12489
|
-
<option value="">All Status</option>
|
|
12490
|
-
<option value="active">Active</option>
|
|
12491
|
-
<option value="inactive">Inactive</option>
|
|
12492
|
-
<option value="uninstalled">Available to Install</option>
|
|
12493
|
-
<option value="error">Error</option>
|
|
12494
|
-
</select>
|
|
12495
|
-
<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-cyan-600 dark:text-cyan-400 sm:size-4">
|
|
12496
|
-
<path d="M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" fill-rule="evenodd" />
|
|
12497
|
-
</svg>
|
|
12498
|
-
</div>
|
|
12499
|
-
</div>
|
|
12500
|
-
<div class="flex-1 max-w-md">
|
|
12501
|
-
<label class="block text-sm font-medium text-zinc-950 dark:text-white mb-2">Search</label>
|
|
12502
|
-
<div class="relative group">
|
|
12503
|
-
<div class="absolute left-3.5 top-2.5 flex items-center justify-center w-5 h-5 rounded-full bg-gradient-to-br from-cyan-400 to-blue-500 dark:from-cyan-300 dark:to-blue-400 opacity-90 group-focus-within:opacity-100 transition-opacity">
|
|
12504
|
-
<svg class="h-3 w-3 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2.5">
|
|
12505
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
|
|
12506
|
-
</svg>
|
|
12507
|
-
</div>
|
|
12508
|
-
<input
|
|
12509
|
-
id="search-input"
|
|
12510
|
-
type="text"
|
|
12511
|
-
placeholder="Search plugins..."
|
|
12512
|
-
oninput="filterPlugins()"
|
|
12513
|
-
class="w-full rounded-full bg-transparent px-11 py-2 text-sm text-zinc-950 dark:text-white placeholder-zinc-500 dark:placeholder-zinc-400 border-2 border-cyan-200/50 dark:border-cyan-700/50 focus:outline-none focus:border-cyan-500 dark:focus:border-cyan-400 focus:shadow-lg focus:shadow-cyan-500/20 dark:focus:shadow-cyan-400/20 transition-all duration-300"
|
|
12514
|
-
/>
|
|
12515
|
-
</div>
|
|
12516
|
-
</div>
|
|
12517
|
-
</div>
|
|
12518
|
-
<div class="flex items-center gap-x-3 ml-4">
|
|
12519
|
-
<button
|
|
12520
|
-
onclick="location.reload()"
|
|
12521
|
-
class="inline-flex items-center gap-x-1.5 px-3 py-1.5 bg-white/90 dark:bg-zinc-800/90 backdrop-blur-sm text-zinc-950 dark:text-white text-sm font-medium rounded-full ring-1 ring-inset ring-cyan-200/50 dark:ring-cyan-700/50 hover:bg-gradient-to-r hover:from-cyan-50 hover:to-blue-50 dark:hover:from-cyan-900/30 dark:hover:to-blue-900/30 hover:ring-cyan-300 dark:hover:ring-cyan-600 transition-all duration-200"
|
|
12522
|
-
>
|
|
12523
|
-
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12524
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/>
|
|
12525
|
-
</svg>
|
|
12526
|
-
Refresh
|
|
12527
|
-
</button>
|
|
12528
|
-
</div>
|
|
12593
|
+
<button
|
|
12594
|
+
onclick="location.reload()"
|
|
12595
|
+
class="inline-flex items-center gap-x-1.5 rounded-md bg-white dark:bg-zinc-900 px-3 py-1.5 h-9 text-sm font-semibold text-zinc-900 dark:text-white shadow-sm ring-1 ring-inset ring-zinc-300 dark:ring-zinc-700 hover:bg-zinc-50 dark:hover:bg-zinc-800"
|
|
12596
|
+
>
|
|
12597
|
+
<svg class="h-4 w-4 text-zinc-500 dark:text-zinc-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12598
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/>
|
|
12599
|
+
</svg>
|
|
12600
|
+
</button>
|
|
12529
12601
|
</div>
|
|
12530
12602
|
</div>
|
|
12603
|
+
|
|
12604
|
+
<!-- Plugins Grid -->
|
|
12605
|
+
<div id="plugins-grid" class="grid gap-6" style="grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));">
|
|
12606
|
+
${data.plugins.map((plugin) => renderPluginCard(plugin)).join("")}
|
|
12607
|
+
</div>
|
|
12531
12608
|
</div>
|
|
12532
12609
|
</div>
|
|
12533
|
-
|
|
12534
|
-
<!-- Plugins Grid -->
|
|
12535
|
-
<div id="plugins-grid" class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
|
|
12536
|
-
${data.plugins.map((plugin) => renderPluginCard(plugin)).join("")}
|
|
12537
12610
|
</div>
|
|
12538
12611
|
|
|
12539
12612
|
<script>
|
|
12540
|
-
async function togglePlugin(pluginId, action) {
|
|
12541
|
-
const button = event.target;
|
|
12542
|
-
|
|
12613
|
+
async function togglePlugin(pluginId, action, event) {
|
|
12614
|
+
const button = event.target.closest('button');
|
|
12615
|
+
if (!button) return;
|
|
12616
|
+
|
|
12543
12617
|
button.disabled = true;
|
|
12544
|
-
button.
|
|
12618
|
+
button.classList.add('opacity-50', 'cursor-wait');
|
|
12545
12619
|
|
|
12546
12620
|
try {
|
|
12547
12621
|
const response = await fetch(\`/admin/plugins/\${pluginId}/\${action}\`, {
|
|
@@ -12557,27 +12631,36 @@ function renderPluginsListPage(data) {
|
|
|
12557
12631
|
// Update UI
|
|
12558
12632
|
const card = button.closest('.plugin-card');
|
|
12559
12633
|
const statusBadge = card.querySelector('.status-badge');
|
|
12634
|
+
const knob = button.querySelector('.toggle-knob');
|
|
12560
12635
|
|
|
12561
12636
|
if (action === 'activate') {
|
|
12562
12637
|
// Update status badge
|
|
12563
|
-
statusBadge.className = 'status-badge inline-flex items-center rounded-
|
|
12564
|
-
statusBadge.innerHTML = '<div class="w-
|
|
12565
|
-
|
|
12566
|
-
|
|
12567
|
-
|
|
12568
|
-
button.
|
|
12569
|
-
button.onclick = () => togglePlugin(pluginId, 'deactivate');
|
|
12570
|
-
|
|
12638
|
+
statusBadge.className = 'status-badge inline-flex items-center rounded-full px-1.5 py-0.5 text-[10px] font-medium ring-1 ring-inset bg-emerald-50 dark:bg-emerald-500/10 text-emerald-700 dark:text-emerald-400 ring-emerald-600/20';
|
|
12639
|
+
statusBadge.innerHTML = '<div class="w-1.5 h-1.5 bg-emerald-500 dark:bg-emerald-400 rounded-full mr-1.5"></div>Active';
|
|
12640
|
+
|
|
12641
|
+
// Update button state to Active
|
|
12642
|
+
button.className = 'bg-emerald-600 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-emerald-600 focus:ring-offset-2 toggle-button';
|
|
12643
|
+
button.setAttribute('aria-checked', 'true');
|
|
12644
|
+
button.onclick = (event) => togglePlugin(pluginId, 'deactivate', event);
|
|
12645
|
+
|
|
12646
|
+
// Update knob position
|
|
12647
|
+
if (knob) {
|
|
12648
|
+
knob.className = 'translate-x-5 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out toggle-knob';
|
|
12649
|
+
}
|
|
12571
12650
|
} else {
|
|
12572
12651
|
// Update status badge
|
|
12573
|
-
statusBadge.className = 'status-badge inline-flex items-center rounded-
|
|
12574
|
-
statusBadge.innerHTML = '<div class="w-
|
|
12575
|
-
|
|
12576
|
-
|
|
12577
|
-
|
|
12578
|
-
button.
|
|
12579
|
-
button.onclick = () => togglePlugin(pluginId, 'activate');
|
|
12580
|
-
|
|
12652
|
+
statusBadge.className = 'status-badge inline-flex items-center rounded-full px-1.5 py-0.5 text-[10px] font-medium ring-1 ring-inset bg-zinc-50 dark:bg-zinc-500/10 text-zinc-700 dark:text-zinc-400 ring-zinc-600/20';
|
|
12653
|
+
statusBadge.innerHTML = '<div class="w-1.5 h-1.5 bg-zinc-500 dark:bg-zinc-400 rounded-full mr-1.5"></div>Inactive';
|
|
12654
|
+
|
|
12655
|
+
// Update button state to Inactive
|
|
12656
|
+
button.className = 'bg-zinc-200 dark:bg-zinc-700 relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-emerald-600 focus:ring-offset-2 toggle-button';
|
|
12657
|
+
button.setAttribute('aria-checked', 'false');
|
|
12658
|
+
button.onclick = (event) => togglePlugin(pluginId, 'activate', event);
|
|
12659
|
+
|
|
12660
|
+
// Update knob position
|
|
12661
|
+
if (knob) {
|
|
12662
|
+
knob.className = 'translate-x-0 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out toggle-knob';
|
|
12663
|
+
}
|
|
12581
12664
|
}
|
|
12582
12665
|
|
|
12583
12666
|
showNotification(\`Plugin \${action}d successfully\`, 'success');
|
|
@@ -12586,9 +12669,9 @@ function renderPluginsListPage(data) {
|
|
|
12586
12669
|
}
|
|
12587
12670
|
} catch (error) {
|
|
12588
12671
|
showNotification(error.message, 'error');
|
|
12589
|
-
button.textContent = originalText;
|
|
12590
12672
|
} finally {
|
|
12591
12673
|
button.disabled = false;
|
|
12674
|
+
button.classList.remove('opacity-50', 'cursor-wait');
|
|
12592
12675
|
}
|
|
12593
12676
|
}
|
|
12594
12677
|
|
|
@@ -12672,81 +12755,92 @@ function renderPluginsListPage(data) {
|
|
|
12672
12755
|
showNotification('Plugin details coming soon!', 'info');
|
|
12673
12756
|
}
|
|
12674
12757
|
|
|
12675
|
-
function
|
|
12676
|
-
|
|
12677
|
-
const
|
|
12678
|
-
|
|
12679
|
-
|
|
12680
|
-
|
|
12681
|
-
|
|
12682
|
-
|
|
12683
|
-
|
|
12684
|
-
}, 3000);
|
|
12685
|
-
}
|
|
12686
|
-
|
|
12687
|
-
function filterPlugins() {
|
|
12688
|
-
const categoryFilter = document.getElementById('category-filter').value.toLowerCase();
|
|
12689
|
-
const statusFilter = document.getElementById('status-filter').value.toLowerCase();
|
|
12758
|
+
function filterAndSortPlugins() {
|
|
12759
|
+
// Get checked categories
|
|
12760
|
+
const checkedCategories = Array.from(document.querySelectorAll('input[name="category"]:checked'))
|
|
12761
|
+
.map(cb => cb.value.toLowerCase());
|
|
12762
|
+
|
|
12763
|
+
// Get checked statuses
|
|
12764
|
+
const checkedStatuses = Array.from(document.querySelectorAll('input[name="status"]:checked'))
|
|
12765
|
+
.map(cb => cb.value.toLowerCase());
|
|
12766
|
+
|
|
12690
12767
|
const searchInput = document.getElementById('search-input').value.toLowerCase();
|
|
12768
|
+
const sortValue = document.getElementById('sort-filter').value;
|
|
12691
12769
|
|
|
12692
|
-
const
|
|
12693
|
-
|
|
12694
|
-
|
|
12695
|
-
|
|
12696
|
-
|
|
12770
|
+
const pluginsGrid = document.getElementById('plugins-grid');
|
|
12771
|
+
const pluginCards = Array.from(pluginsGrid.querySelectorAll('.plugin-card'));
|
|
12772
|
+
|
|
12773
|
+
// Filter
|
|
12774
|
+
const visibleCards = pluginCards.filter(card => {
|
|
12697
12775
|
const category = card.getAttribute('data-category')?.toLowerCase() || '';
|
|
12698
12776
|
const status = card.getAttribute('data-status')?.toLowerCase() || '';
|
|
12699
12777
|
const name = card.getAttribute('data-name')?.toLowerCase() || '';
|
|
12700
12778
|
const description = card.getAttribute('data-description')?.toLowerCase() || '';
|
|
12701
12779
|
|
|
12702
|
-
//
|
|
12703
|
-
|
|
12704
|
-
|
|
12705
|
-
//
|
|
12706
|
-
if (
|
|
12707
|
-
|
|
12708
|
-
|
|
12709
|
-
|
|
12710
|
-
|
|
12711
|
-
|
|
12712
|
-
|
|
12713
|
-
}
|
|
12714
|
-
|
|
12715
|
-
// Search filter - check if search term is in name or description
|
|
12716
|
-
if (searchInput && !name.includes(searchInput) && !description.includes(searchInput)) {
|
|
12717
|
-
matches = false;
|
|
12718
|
-
}
|
|
12780
|
+
// Category filter: if any selected, must match one of them
|
|
12781
|
+
if (checkedCategories.length > 0 && !checkedCategories.includes(category)) return false;
|
|
12782
|
+
|
|
12783
|
+
// Status filter: if any selected, must match one of them
|
|
12784
|
+
if (checkedStatuses.length > 0 && !checkedStatuses.includes(status)) return false;
|
|
12785
|
+
|
|
12786
|
+
// Search filter
|
|
12787
|
+
if (searchInput && !name.includes(searchInput) && !description.includes(searchInput)) return false;
|
|
12788
|
+
|
|
12789
|
+
return true;
|
|
12790
|
+
});
|
|
12719
12791
|
|
|
12720
|
-
|
|
12721
|
-
|
|
12722
|
-
|
|
12723
|
-
|
|
12724
|
-
|
|
12725
|
-
|
|
12792
|
+
// Sort
|
|
12793
|
+
visibleCards.sort((a, b) => {
|
|
12794
|
+
const aName = a.getAttribute('data-name') || '';
|
|
12795
|
+
const bName = b.getAttribute('data-name') || '';
|
|
12796
|
+
const aInstalled = parseInt(a.getAttribute('data-installed') || '0');
|
|
12797
|
+
const bInstalled = parseInt(b.getAttribute('data-installed') || '0');
|
|
12798
|
+
const aUpdated = parseInt(a.getAttribute('data-updated') || '0');
|
|
12799
|
+
const bUpdated = parseInt(b.getAttribute('data-updated') || '0');
|
|
12800
|
+
const aDownloads = parseInt(a.getAttribute('data-downloads') || '0');
|
|
12801
|
+
const bDownloads = parseInt(b.getAttribute('data-downloads') || '0');
|
|
12802
|
+
const aRating = parseFloat(a.getAttribute('data-rating') || '0');
|
|
12803
|
+
const bRating = parseFloat(b.getAttribute('data-rating') || '0');
|
|
12804
|
+
|
|
12805
|
+
switch (sortValue) {
|
|
12806
|
+
case 'name-desc': return bName.localeCompare(aName);
|
|
12807
|
+
case 'newest': return bInstalled - aInstalled;
|
|
12808
|
+
case 'updated': return bUpdated - aUpdated;
|
|
12809
|
+
case 'popular': return bDownloads - aDownloads;
|
|
12810
|
+
case 'rating': return bRating - aRating;
|
|
12811
|
+
case 'name-asc':
|
|
12812
|
+
default: return aName.localeCompare(bName);
|
|
12726
12813
|
}
|
|
12727
12814
|
});
|
|
12728
12815
|
|
|
12729
|
-
//
|
|
12816
|
+
// Re-append
|
|
12817
|
+
pluginCards.forEach(card => card.style.display = 'none'); // Hide all first
|
|
12818
|
+
|
|
12819
|
+
// If no results
|
|
12730
12820
|
let noResultsMsg = document.getElementById('no-results-message');
|
|
12731
|
-
if (
|
|
12821
|
+
if (visibleCards.length === 0) {
|
|
12732
12822
|
if (!noResultsMsg) {
|
|
12733
12823
|
noResultsMsg = document.createElement('div');
|
|
12734
12824
|
noResultsMsg.id = 'no-results-message';
|
|
12735
|
-
noResultsMsg.className = 'col-span-full text-center py-12';
|
|
12825
|
+
noResultsMsg.className = 'col-span-full text-center py-12 bg-zinc-50 dark:bg-zinc-800/50 rounded-lg border border-dashed border-zinc-300 dark:border-zinc-700';
|
|
12736
12826
|
noResultsMsg.innerHTML = \`
|
|
12737
12827
|
<div class="flex flex-col items-center">
|
|
12738
|
-
<svg class="w-
|
|
12828
|
+
<svg class="w-12 h-12 text-zinc-400 dark:text-zinc-600 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12739
12829
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
12740
12830
|
</svg>
|
|
12741
|
-
<h3 class="text-
|
|
12831
|
+
<h3 class="text-base font-semibold text-zinc-950 dark:text-white mb-1">No plugins found</h3>
|
|
12742
12832
|
<p class="text-sm text-zinc-500 dark:text-zinc-400">Try adjusting your filters or search terms</p>
|
|
12743
12833
|
</div>
|
|
12744
12834
|
\`;
|
|
12745
|
-
|
|
12835
|
+
pluginsGrid.appendChild(noResultsMsg);
|
|
12746
12836
|
}
|
|
12747
12837
|
noResultsMsg.style.display = '';
|
|
12748
|
-
} else
|
|
12749
|
-
noResultsMsg.style.display = 'none';
|
|
12838
|
+
} else {
|
|
12839
|
+
if (noResultsMsg) noResultsMsg.style.display = 'none';
|
|
12840
|
+
visibleCards.forEach(card => {
|
|
12841
|
+
card.style.display = '';
|
|
12842
|
+
pluginsGrid.appendChild(card); // Re-appending moves it to the end, effectively sorting
|
|
12843
|
+
});
|
|
12750
12844
|
}
|
|
12751
12845
|
}
|
|
12752
12846
|
</script>
|
|
@@ -12773,120 +12867,115 @@ function renderPluginsListPage(data) {
|
|
|
12773
12867
|
version: data.version,
|
|
12774
12868
|
content: pageContent
|
|
12775
12869
|
};
|
|
12776
|
-
return
|
|
12870
|
+
return chunkAZLU3ROK_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
12777
12871
|
}
|
|
12778
12872
|
function renderPluginCard(plugin) {
|
|
12779
12873
|
const statusColors = {
|
|
12780
|
-
active: "bg-
|
|
12781
|
-
inactive: "bg-zinc-50 dark:bg-zinc-500/10 text-zinc-700 dark:text-zinc-400 ring-zinc-
|
|
12782
|
-
error: "bg-red-50 dark:bg-red-500/10 text-red-700 dark:text-red-400 ring-red-
|
|
12783
|
-
uninstalled: "bg-zinc-
|
|
12874
|
+
active: "bg-emerald-50 dark:bg-emerald-500/10 text-emerald-700 dark:text-emerald-400 ring-emerald-600/20",
|
|
12875
|
+
inactive: "bg-zinc-50 dark:bg-zinc-500/10 text-zinc-700 dark:text-zinc-400 ring-zinc-600/20",
|
|
12876
|
+
error: "bg-red-50 dark:bg-red-500/10 text-red-700 dark:text-red-400 ring-red-600/20",
|
|
12877
|
+
uninstalled: "bg-zinc-50 dark:bg-zinc-500/10 text-zinc-600 dark:text-zinc-500 ring-zinc-600/20"
|
|
12784
12878
|
};
|
|
12785
12879
|
const statusIcons = {
|
|
12786
|
-
active: '<div class="w-
|
|
12787
|
-
inactive: '<div class="w-
|
|
12788
|
-
error: '<div class="w-
|
|
12789
|
-
uninstalled: '<div class="w-
|
|
12790
|
-
};
|
|
12791
|
-
const borderColors = {
|
|
12792
|
-
active: "ring-[3px] ring-lime-500 dark:ring-lime-400",
|
|
12793
|
-
inactive: "ring-[3px] ring-pink-500 dark:ring-pink-400",
|
|
12794
|
-
error: "ring-[3px] ring-red-500 dark:ring-red-400",
|
|
12795
|
-
uninstalled: "ring-[3px] ring-zinc-400 dark:ring-zinc-600"
|
|
12880
|
+
active: '<div class="w-1.5 h-1.5 bg-emerald-500 dark:bg-emerald-400 rounded-full mr-1.5"></div>',
|
|
12881
|
+
inactive: '<div class="w-1.5 h-1.5 bg-zinc-500 dark:bg-zinc-400 rounded-full mr-1.5"></div>',
|
|
12882
|
+
error: '<div class="w-1.5 h-1.5 bg-red-500 dark:bg-red-400 rounded-full mr-1.5"></div>',
|
|
12883
|
+
uninstalled: '<div class="w-1.5 h-1.5 bg-zinc-400 dark:bg-zinc-600 rounded-full mr-1.5"></div>'
|
|
12796
12884
|
};
|
|
12797
12885
|
const criticalCorePlugins = ["core-auth", "core-media"];
|
|
12798
12886
|
const canToggle = !criticalCorePlugins.includes(plugin.id);
|
|
12799
12887
|
let actionButton = "";
|
|
12800
12888
|
if (plugin.status === "uninstalled") {
|
|
12801
|
-
actionButton = `<button onclick="installPlugin('${plugin.name}')" class="bg-
|
|
12802
|
-
} else if (plugin.status === "active") {
|
|
12803
|
-
actionButton = `<button onclick="togglePlugin('${plugin.id}', 'deactivate')" class="bg-red-600 dark:bg-red-700 hover:bg-red-700 dark:hover:bg-red-600 text-white px-3 py-1.5 rounded-lg text-sm font-medium transition-colors">Deactivate</button>`;
|
|
12889
|
+
actionButton = `<button onclick="installPlugin('${plugin.name}')" class="w-full sm:w-auto bg-zinc-900 dark:bg-white hover:bg-zinc-800 dark:hover:bg-zinc-100 text-white dark:text-zinc-900 px-3 py-1.5 rounded-md text-xs font-medium transition-colors shadow-sm">Install</button>`;
|
|
12804
12890
|
} else {
|
|
12805
|
-
|
|
12891
|
+
const isActive = plugin.status === "active";
|
|
12892
|
+
const action = isActive ? "deactivate" : "activate";
|
|
12893
|
+
const bgClass = isActive ? "bg-emerald-600" : "bg-zinc-200 dark:bg-zinc-700";
|
|
12894
|
+
const translateClass = isActive ? "translate-x-5" : "translate-x-0";
|
|
12895
|
+
if (canToggle) {
|
|
12896
|
+
actionButton = `
|
|
12897
|
+
<button onclick="togglePlugin('${plugin.id}', '${action}', event)" type="button" class="${bgClass} relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-emerald-600 focus:ring-offset-2 toggle-button" role="switch" aria-checked="${isActive}">
|
|
12898
|
+
<span class="sr-only">Toggle plugin</span>
|
|
12899
|
+
<span aria-hidden="true" class="${translateClass} pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out toggle-knob"></span>
|
|
12900
|
+
</button>
|
|
12901
|
+
`;
|
|
12902
|
+
} else {
|
|
12903
|
+
actionButton = `
|
|
12904
|
+
<div class="relative inline-flex h-6 w-11 flex-shrink-0 cursor-not-allowed rounded-full border-2 border-transparent bg-emerald-600/50 opacity-50" title="Core plugin cannot be disabled">
|
|
12905
|
+
<span class="translate-x-5 pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0"></span>
|
|
12906
|
+
</div>
|
|
12907
|
+
`;
|
|
12908
|
+
}
|
|
12806
12909
|
}
|
|
12807
12910
|
return `
|
|
12808
|
-
<div class="plugin-card rounded-
|
|
12911
|
+
<div class="plugin-card flex flex-col h-full rounded-md bg-white dark:bg-zinc-900 ring-1 ring-zinc-950/10 dark:ring-white/10 p-5 transition-all hover:shadow-md"
|
|
12912
|
+
data-category="${plugin.category}"
|
|
12913
|
+
data-status="${plugin.status}"
|
|
12914
|
+
data-name="${plugin.displayName}"
|
|
12915
|
+
data-description="${plugin.description}"
|
|
12916
|
+
data-downloads="${plugin.downloadCount || 0}"
|
|
12917
|
+
data-rating="${plugin.rating || 0}">
|
|
12809
12918
|
<div class="flex items-start justify-between mb-4">
|
|
12810
12919
|
<div class="flex items-center gap-3">
|
|
12811
|
-
<div class="w-
|
|
12920
|
+
<div class="w-10 h-10 rounded-md flex items-center justify-center bg-zinc-50 dark:bg-zinc-800 text-zinc-600 dark:text-zinc-400 ring-1 ring-inset ring-zinc-200 dark:ring-zinc-700/50">
|
|
12812
12921
|
${plugin.icon || getDefaultPluginIcon(plugin.category)}
|
|
12813
12922
|
</div>
|
|
12814
12923
|
<div>
|
|
12815
|
-
<
|
|
12816
|
-
|
|
12924
|
+
<div class="flex items-center gap-2">
|
|
12925
|
+
<h3 class="text-sm font-semibold text-zinc-900 dark:text-white">${plugin.displayName}</h3>
|
|
12926
|
+
<span class="status-badge inline-flex items-center rounded-full px-1.5 py-0.5 text-[10px] font-medium ring-1 ring-inset ${statusColors[plugin.status]}">
|
|
12927
|
+
${statusIcons[plugin.status]}${plugin.status.charAt(0).toUpperCase() + plugin.status.slice(1)}
|
|
12928
|
+
</span>
|
|
12929
|
+
</div>
|
|
12930
|
+
<p class="text-xs text-zinc-500 dark:text-zinc-400">v${plugin.version} \u2022 ${plugin.author}</p>
|
|
12817
12931
|
</div>
|
|
12818
12932
|
</div>
|
|
12819
|
-
|
|
12820
|
-
|
|
12821
|
-
|
|
12822
|
-
|
|
12823
|
-
|
|
12933
|
+
|
|
12934
|
+
<div class="flex items-center gap-1">
|
|
12935
|
+
${plugin.status !== "uninstalled" ? `
|
|
12936
|
+
<button onclick="showPluginDetails('${plugin.id}')" class="text-zinc-400 hover:text-zinc-600 dark:text-zinc-500 dark:hover:text-zinc-300 p-1.5 rounded-md hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors" title="Plugin Details">
|
|
12937
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12938
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
|
12939
|
+
</svg>
|
|
12940
|
+
</button>
|
|
12941
|
+
` : ""}
|
|
12942
|
+
|
|
12943
|
+
${!plugin.isCore && plugin.status !== "uninstalled" ? `
|
|
12944
|
+
<button onclick="uninstallPlugin('${plugin.id}')" class="text-zinc-400 hover:text-red-600 dark:text-zinc-500 dark:hover:text-red-400 p-1.5 rounded-md hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors" title="Uninstall Plugin">
|
|
12945
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12946
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
|
|
12947
|
+
</svg>
|
|
12948
|
+
</button>
|
|
12949
|
+
` : ""}
|
|
12824
12950
|
</div>
|
|
12825
12951
|
</div>
|
|
12826
12952
|
|
|
12827
|
-
<p class="text-zinc-600 dark:text-zinc-
|
|
12953
|
+
<p class="text-zinc-600 dark:text-zinc-400 text-sm mb-4 line-clamp-2 flex-grow">${plugin.description}</p>
|
|
12828
12954
|
|
|
12829
|
-
<div class="flex items-center gap-
|
|
12830
|
-
<span class="flex items-center
|
|
12831
|
-
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12832
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"/>
|
|
12833
|
-
</svg>
|
|
12955
|
+
<div class="flex flex-wrap items-center gap-2 mb-5">
|
|
12956
|
+
<span class="inline-flex items-center rounded-md bg-zinc-100 dark:bg-zinc-800 px-2 py-1 text-xs font-medium text-zinc-600 dark:text-zinc-400">
|
|
12834
12957
|
${plugin.category}
|
|
12835
12958
|
</span>
|
|
12836
|
-
|
|
12837
|
-
|
|
12838
|
-
|
|
12839
|
-
<
|
|
12840
|
-
|
|
12841
|
-
</
|
|
12842
|
-
|
|
12843
|
-
</span>
|
|
12844
|
-
` : ""}
|
|
12845
|
-
|
|
12846
|
-
${plugin.rating ? `
|
|
12847
|
-
<span class="flex items-center gap-1">
|
|
12848
|
-
<svg class="w-4 h-4 text-yellow-500 dark:text-yellow-400 fill-current" viewBox="0 0 24 24">
|
|
12849
|
-
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
|
|
12850
|
-
</svg>
|
|
12851
|
-
${plugin.rating}
|
|
12852
|
-
</span>
|
|
12853
|
-
` : ""}
|
|
12854
|
-
|
|
12855
|
-
<span>${plugin.lastUpdated}</span>
|
|
12856
|
-
</div>
|
|
12857
|
-
|
|
12858
|
-
${plugin.dependencies && plugin.dependencies.length > 0 ? `
|
|
12859
|
-
<div class="mb-4">
|
|
12860
|
-
<p class="text-xs text-zinc-500 dark:text-zinc-400 mb-2">Dependencies:</p>
|
|
12861
|
-
<div class="flex flex-wrap gap-1">
|
|
12862
|
-
${plugin.dependencies.map((dep) => `<span class="inline-block bg-zinc-100 dark:bg-zinc-800 text-zinc-700 dark:text-zinc-300 text-xs px-2 py-1 rounded">${dep}</span>`).join("")}
|
|
12863
|
-
</div>
|
|
12959
|
+
${plugin.isCore ? '<span class="inline-flex items-center rounded-md bg-zinc-100 dark:bg-zinc-800 px-2 py-1 text-xs font-medium text-zinc-600 dark:text-zinc-400">Core</span>' : ""}
|
|
12960
|
+
|
|
12961
|
+
${plugin.dependencies && plugin.dependencies.map((dep) => `
|
|
12962
|
+
<span class="inline-flex items-center rounded-md bg-zinc-100 dark:bg-zinc-800 px-2 py-1 text-xs font-medium text-zinc-600 dark:text-zinc-400">
|
|
12963
|
+
${dep}
|
|
12964
|
+
</span>
|
|
12965
|
+
`).join("") || ""}
|
|
12864
12966
|
</div>
|
|
12865
|
-
` : ""}
|
|
12866
12967
|
|
|
12867
|
-
<div class="flex items-center justify-between">
|
|
12968
|
+
<div class="flex items-center justify-between pt-4 border-t border-zinc-100 dark:border-zinc-800 mt-auto">
|
|
12868
12969
|
<div class="flex gap-2">
|
|
12869
|
-
${
|
|
12870
|
-
${plugin.status !== "uninstalled" ? `
|
|
12871
|
-
<button onclick="openPluginSettings('${plugin.id}')" class="bg-white dark:bg-zinc-800 hover:bg-zinc-50 dark:hover:bg-zinc-700 text-zinc-950 dark:text-white ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 px-3 py-1.5 rounded-lg text-sm font-medium transition-colors">
|
|
12872
|
-
Settings
|
|
12873
|
-
</button>
|
|
12874
|
-
` : ""}
|
|
12970
|
+
${actionButton}
|
|
12875
12971
|
</div>
|
|
12876
12972
|
|
|
12877
12973
|
<div class="flex items-center gap-2">
|
|
12878
12974
|
${plugin.status !== "uninstalled" ? `
|
|
12879
|
-
<button onclick="
|
|
12880
|
-
<svg class="w-
|
|
12881
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="
|
|
12882
|
-
|
|
12883
|
-
</button>
|
|
12884
|
-
` : ""}
|
|
12885
|
-
|
|
12886
|
-
${!plugin.isCore && plugin.status !== "uninstalled" ? `
|
|
12887
|
-
<button onclick="uninstallPlugin('${plugin.id}')" class="text-zinc-500 dark:text-zinc-400 hover:text-red-600 dark:hover:text-red-400 p-1.5 rounded-lg hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors" title="Uninstall Plugin">
|
|
12888
|
-
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12889
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
|
|
12975
|
+
<button onclick="openPluginSettings('${plugin.id}')" class="text-zinc-400 hover:text-zinc-600 dark:text-zinc-500 dark:hover:text-zinc-300 p-1.5 rounded-md hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors" title="Settings">
|
|
12976
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
12977
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
|
|
12978
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
|
|
12890
12979
|
</svg>
|
|
12891
12980
|
</button>
|
|
12892
12981
|
` : ""}
|
|
@@ -13430,7 +13519,7 @@ function renderPluginSettingsPage(data) {
|
|
|
13430
13519
|
user,
|
|
13431
13520
|
content: pageContent
|
|
13432
13521
|
};
|
|
13433
|
-
return
|
|
13522
|
+
return chunkAZLU3ROK_cjs.renderAdminLayout(layoutData);
|
|
13434
13523
|
}
|
|
13435
13524
|
function renderStatusBadge(status) {
|
|
13436
13525
|
const statusColors = {
|
|
@@ -13693,7 +13782,7 @@ function formatTimestamp(timestamp) {
|
|
|
13693
13782
|
|
|
13694
13783
|
// src/routes/admin-plugins.ts
|
|
13695
13784
|
var adminPluginRoutes = new hono.Hono();
|
|
13696
|
-
adminPluginRoutes.use("*",
|
|
13785
|
+
adminPluginRoutes.use("*", chunkXWPGIFS7_cjs.requireAuth());
|
|
13697
13786
|
var AVAILABLE_PLUGINS = [
|
|
13698
13787
|
{
|
|
13699
13788
|
id: "third-party-faq",
|
|
@@ -14209,7 +14298,7 @@ function formatLastUpdated(timestamp) {
|
|
|
14209
14298
|
}
|
|
14210
14299
|
|
|
14211
14300
|
// src/templates/pages/admin-logs-list.template.ts
|
|
14212
|
-
|
|
14301
|
+
chunkAZLU3ROK_cjs.init_admin_layout_catalyst_template();
|
|
14213
14302
|
function renderLogsListPage(data) {
|
|
14214
14303
|
const { logs, pagination, filters, user } = data;
|
|
14215
14304
|
const content = `
|
|
@@ -14520,7 +14609,7 @@ function renderLogsListPage(data) {
|
|
|
14520
14609
|
user,
|
|
14521
14610
|
content
|
|
14522
14611
|
};
|
|
14523
|
-
return
|
|
14612
|
+
return chunkAZLU3ROK_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
14524
14613
|
}
|
|
14525
14614
|
function renderLogDetailsPage(data) {
|
|
14526
14615
|
const { log, user } = data;
|
|
@@ -14732,7 +14821,7 @@ function renderLogDetailsPage(data) {
|
|
|
14732
14821
|
</div>
|
|
14733
14822
|
</div>
|
|
14734
14823
|
`;
|
|
14735
|
-
return
|
|
14824
|
+
return chunkAZLU3ROK_cjs.adminLayoutV2({
|
|
14736
14825
|
title: `Log Details - ${log.id}`,
|
|
14737
14826
|
user,
|
|
14738
14827
|
content
|
|
@@ -14975,7 +15064,7 @@ function renderLogConfigPage(data) {
|
|
|
14975
15064
|
|
|
14976
15065
|
<script src="https://unpkg.com/htmx.org@1.9.6"></script>
|
|
14977
15066
|
`;
|
|
14978
|
-
return
|
|
15067
|
+
return chunkAZLU3ROK_cjs.adminLayoutV2({
|
|
14979
15068
|
title: "Log Configuration",
|
|
14980
15069
|
user,
|
|
14981
15070
|
content
|
|
@@ -14984,7 +15073,7 @@ function renderLogConfigPage(data) {
|
|
|
14984
15073
|
|
|
14985
15074
|
// src/routes/admin-logs.ts
|
|
14986
15075
|
var adminLogsRoutes = new hono.Hono();
|
|
14987
|
-
adminLogsRoutes.use("*",
|
|
15076
|
+
adminLogsRoutes.use("*", chunkXWPGIFS7_cjs.requireAuth());
|
|
14988
15077
|
adminLogsRoutes.get("/", async (c) => {
|
|
14989
15078
|
try {
|
|
14990
15079
|
const user = c.get("user");
|
|
@@ -15356,7 +15445,7 @@ adminDesignRoutes.get("/", (c) => {
|
|
|
15356
15445
|
role: user.role
|
|
15357
15446
|
} : void 0
|
|
15358
15447
|
};
|
|
15359
|
-
return c.html(
|
|
15448
|
+
return c.html(chunkAZLU3ROK_cjs.renderDesignPage(pageData));
|
|
15360
15449
|
});
|
|
15361
15450
|
var adminCheckboxRoutes = new hono.Hono();
|
|
15362
15451
|
adminCheckboxRoutes.get("/", (c) => {
|
|
@@ -15368,7 +15457,7 @@ adminCheckboxRoutes.get("/", (c) => {
|
|
|
15368
15457
|
role: user.role
|
|
15369
15458
|
} : void 0
|
|
15370
15459
|
};
|
|
15371
|
-
return c.html(
|
|
15460
|
+
return c.html(chunkAZLU3ROK_cjs.renderCheckboxPage(pageData));
|
|
15372
15461
|
});
|
|
15373
15462
|
|
|
15374
15463
|
// src/templates/pages/admin-testimonials-form.template.ts
|
|
@@ -15396,7 +15485,7 @@ function renderTestimonialsForm(data) {
|
|
|
15396
15485
|
</div>
|
|
15397
15486
|
</div>
|
|
15398
15487
|
|
|
15399
|
-
${message ?
|
|
15488
|
+
${message ? chunkAZLU3ROK_cjs.renderAlert({ type: messageType || "info", message, dismissible: true }) : ""}
|
|
15400
15489
|
|
|
15401
15490
|
<!-- Form -->
|
|
15402
15491
|
<div class="backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl">
|
|
@@ -15625,7 +15714,7 @@ function renderTestimonialsForm(data) {
|
|
|
15625
15714
|
user: data.user,
|
|
15626
15715
|
content: pageContent
|
|
15627
15716
|
};
|
|
15628
|
-
return
|
|
15717
|
+
return chunkAZLU3ROK_cjs.renderAdminLayout(layoutData);
|
|
15629
15718
|
}
|
|
15630
15719
|
function escapeHtml4(unsafe) {
|
|
15631
15720
|
return unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
@@ -15651,7 +15740,7 @@ adminTestimonialsRoutes.get("/", async (c) => {
|
|
|
15651
15740
|
const offset = (currentPage - 1) * limit;
|
|
15652
15741
|
const db = c.env?.DB;
|
|
15653
15742
|
if (!db) {
|
|
15654
|
-
return c.html(
|
|
15743
|
+
return c.html(chunkAZLU3ROK_cjs.renderTestimonialsList({
|
|
15655
15744
|
testimonials: [],
|
|
15656
15745
|
totalCount: 0,
|
|
15657
15746
|
currentPage: 1,
|
|
@@ -15691,7 +15780,7 @@ adminTestimonialsRoutes.get("/", async (c) => {
|
|
|
15691
15780
|
`;
|
|
15692
15781
|
const { results: testimonials } = await db.prepare(dataQuery).bind(...params, limit, offset).all();
|
|
15693
15782
|
const totalPages = Math.ceil(totalCount / limit);
|
|
15694
|
-
return c.html(
|
|
15783
|
+
return c.html(chunkAZLU3ROK_cjs.renderTestimonialsList({
|
|
15695
15784
|
testimonials: testimonials || [],
|
|
15696
15785
|
totalCount,
|
|
15697
15786
|
currentPage,
|
|
@@ -15705,7 +15794,7 @@ adminTestimonialsRoutes.get("/", async (c) => {
|
|
|
15705
15794
|
} catch (error) {
|
|
15706
15795
|
console.error("Error fetching testimonials:", error);
|
|
15707
15796
|
const user = c.get("user");
|
|
15708
|
-
return c.html(
|
|
15797
|
+
return c.html(chunkAZLU3ROK_cjs.renderTestimonialsList({
|
|
15709
15798
|
testimonials: [],
|
|
15710
15799
|
totalCount: 0,
|
|
15711
15800
|
currentPage: 1,
|
|
@@ -16024,7 +16113,7 @@ function renderCodeExamplesForm(data) {
|
|
|
16024
16113
|
</div>
|
|
16025
16114
|
</div>
|
|
16026
16115
|
|
|
16027
|
-
${message ?
|
|
16116
|
+
${message ? chunkAZLU3ROK_cjs.renderAlert({ type: messageType || "info", message, dismissible: true }) : ""}
|
|
16028
16117
|
|
|
16029
16118
|
<!-- Form -->
|
|
16030
16119
|
<div class="backdrop-blur-xl bg-white/10 rounded-xl border border-white/20 shadow-2xl">
|
|
@@ -16294,7 +16383,7 @@ function renderCodeExamplesForm(data) {
|
|
|
16294
16383
|
user: data.user,
|
|
16295
16384
|
content: pageContent
|
|
16296
16385
|
};
|
|
16297
|
-
return
|
|
16386
|
+
return chunkAZLU3ROK_cjs.renderAdminLayout(layoutData);
|
|
16298
16387
|
}
|
|
16299
16388
|
function escapeHtml5(unsafe) {
|
|
16300
16389
|
return unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
@@ -16321,7 +16410,7 @@ adminCodeExamplesRoutes.get("/", async (c) => {
|
|
|
16321
16410
|
const offset = (currentPage - 1) * limit;
|
|
16322
16411
|
const db = c.env?.DB;
|
|
16323
16412
|
if (!db) {
|
|
16324
|
-
return c.html(
|
|
16413
|
+
return c.html(chunkAZLU3ROK_cjs.renderCodeExamplesList({
|
|
16325
16414
|
codeExamples: [],
|
|
16326
16415
|
totalCount: 0,
|
|
16327
16416
|
currentPage: 1,
|
|
@@ -16361,7 +16450,7 @@ adminCodeExamplesRoutes.get("/", async (c) => {
|
|
|
16361
16450
|
`;
|
|
16362
16451
|
const { results: codeExamples } = await db.prepare(dataQuery).bind(...params, limit, offset).all();
|
|
16363
16452
|
const totalPages = Math.ceil(totalCount / limit);
|
|
16364
|
-
return c.html(
|
|
16453
|
+
return c.html(chunkAZLU3ROK_cjs.renderCodeExamplesList({
|
|
16365
16454
|
codeExamples: codeExamples || [],
|
|
16366
16455
|
totalCount,
|
|
16367
16456
|
currentPage,
|
|
@@ -16375,7 +16464,7 @@ adminCodeExamplesRoutes.get("/", async (c) => {
|
|
|
16375
16464
|
} catch (error) {
|
|
16376
16465
|
console.error("Error fetching code examples:", error);
|
|
16377
16466
|
const user = c.get("user");
|
|
16378
|
-
return c.html(
|
|
16467
|
+
return c.html(chunkAZLU3ROK_cjs.renderCodeExamplesList({
|
|
16379
16468
|
codeExamples: [],
|
|
16380
16469
|
totalCount: 0,
|
|
16381
16470
|
currentPage: 1,
|
|
@@ -16764,7 +16853,7 @@ function renderDashboardPage(data) {
|
|
|
16764
16853
|
version: data.version,
|
|
16765
16854
|
content: pageContent
|
|
16766
16855
|
};
|
|
16767
|
-
return
|
|
16856
|
+
return chunkAZLU3ROK_cjs.renderAdminLayout(layoutData);
|
|
16768
16857
|
}
|
|
16769
16858
|
function renderStatsCards(stats) {
|
|
16770
16859
|
const cards = [
|
|
@@ -17312,9 +17401,9 @@ function renderStorageUsage(databaseSizeBytes, mediaSizeBytes) {
|
|
|
17312
17401
|
}
|
|
17313
17402
|
|
|
17314
17403
|
// src/routes/admin-dashboard.ts
|
|
17315
|
-
var VERSION =
|
|
17404
|
+
var VERSION = chunkSZE3XVET_cjs.getCoreVersion();
|
|
17316
17405
|
var router = new hono.Hono();
|
|
17317
|
-
router.use("*",
|
|
17406
|
+
router.use("*", chunkXWPGIFS7_cjs.requireAuth());
|
|
17318
17407
|
router.get("/", async (c) => {
|
|
17319
17408
|
const user = c.get("user");
|
|
17320
17409
|
try {
|
|
@@ -17539,7 +17628,7 @@ router.get("/system-status", async (c) => {
|
|
|
17539
17628
|
});
|
|
17540
17629
|
|
|
17541
17630
|
// src/templates/pages/admin-collections-list.template.ts
|
|
17542
|
-
|
|
17631
|
+
chunkAZLU3ROK_cjs.init_admin_layout_catalyst_template();
|
|
17543
17632
|
|
|
17544
17633
|
// src/templates/components/table.template.ts
|
|
17545
17634
|
function renderTable2(data) {
|
|
@@ -18013,11 +18102,11 @@ function renderCollectionsListPage(data) {
|
|
|
18013
18102
|
version: data.version,
|
|
18014
18103
|
content: pageContent
|
|
18015
18104
|
};
|
|
18016
|
-
return
|
|
18105
|
+
return chunkAZLU3ROK_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
18017
18106
|
}
|
|
18018
18107
|
|
|
18019
18108
|
// src/templates/pages/admin-collections-form.template.ts
|
|
18020
|
-
|
|
18109
|
+
chunkAZLU3ROK_cjs.init_admin_layout_catalyst_template();
|
|
18021
18110
|
function getFieldTypeBadge(fieldType) {
|
|
18022
18111
|
const typeLabels = {
|
|
18023
18112
|
"text": "Text",
|
|
@@ -18278,7 +18367,7 @@ function renderCollectionFormPage(data) {
|
|
|
18278
18367
|
}
|
|
18279
18368
|
</style>
|
|
18280
18369
|
|
|
18281
|
-
${
|
|
18370
|
+
${chunkAZLU3ROK_cjs.renderForm(formData)}
|
|
18282
18371
|
|
|
18283
18372
|
${isEdit && data.managed ? `
|
|
18284
18373
|
<!-- Read-Only Fields Display for Managed Collections -->
|
|
@@ -18959,6 +19048,8 @@ function renderCollectionFormPage(data) {
|
|
|
18959
19048
|
})
|
|
18960
19049
|
.then(data => {
|
|
18961
19050
|
if (data.success) {
|
|
19051
|
+
// Close modal before reloading
|
|
19052
|
+
closeFieldModal();
|
|
18962
19053
|
location.reload();
|
|
18963
19054
|
} else {
|
|
18964
19055
|
alert('Error saving field: ' + (data.error || 'Unknown error'));
|
|
@@ -19065,12 +19156,12 @@ function renderCollectionFormPage(data) {
|
|
|
19065
19156
|
version: data.version,
|
|
19066
19157
|
content: pageContent
|
|
19067
19158
|
};
|
|
19068
|
-
return
|
|
19159
|
+
return chunkAZLU3ROK_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
19069
19160
|
}
|
|
19070
19161
|
|
|
19071
19162
|
// src/routes/admin-collections.ts
|
|
19072
19163
|
var adminCollectionsRoutes = new hono.Hono();
|
|
19073
|
-
adminCollectionsRoutes.use("*",
|
|
19164
|
+
adminCollectionsRoutes.use("*", chunkXWPGIFS7_cjs.requireAuth());
|
|
19074
19165
|
adminCollectionsRoutes.get("/", async (c) => {
|
|
19075
19166
|
try {
|
|
19076
19167
|
const user = c.get("user");
|
|
@@ -19509,11 +19600,65 @@ adminCollectionsRoutes.post("/:id/fields", async (c) => {
|
|
|
19509
19600
|
return c.json({ success: false, error: "Field name must contain only lowercase letters, numbers, and underscores." });
|
|
19510
19601
|
}
|
|
19511
19602
|
const db = c.env.DB;
|
|
19603
|
+
const getCollectionStmt = db.prepare("SELECT * FROM collections WHERE id = ?");
|
|
19604
|
+
const collection = await getCollectionStmt.bind(collectionId).first();
|
|
19605
|
+
if (!collection) {
|
|
19606
|
+
return c.json({ success: false, error: "Collection not found." });
|
|
19607
|
+
}
|
|
19608
|
+
let schema = collection.schema ? typeof collection.schema === "string" ? JSON.parse(collection.schema) : collection.schema : null;
|
|
19609
|
+
if (schema && schema.properties && schema.properties[fieldName]) {
|
|
19610
|
+
return c.json({ success: false, error: "A field with this name already exists." });
|
|
19611
|
+
}
|
|
19512
19612
|
const existingStmt = db.prepare("SELECT id FROM content_fields WHERE collection_id = ? AND field_name = ?");
|
|
19513
19613
|
const existing = await existingStmt.bind(collectionId, fieldName).first();
|
|
19514
19614
|
if (existing) {
|
|
19515
19615
|
return c.json({ success: false, error: "A field with this name already exists." });
|
|
19516
19616
|
}
|
|
19617
|
+
let parsedOptions = {};
|
|
19618
|
+
try {
|
|
19619
|
+
parsedOptions = fieldOptions ? JSON.parse(fieldOptions) : {};
|
|
19620
|
+
} catch (e) {
|
|
19621
|
+
console.error("Error parsing field options:", e);
|
|
19622
|
+
}
|
|
19623
|
+
if (schema) {
|
|
19624
|
+
if (!schema.properties) {
|
|
19625
|
+
schema.properties = {};
|
|
19626
|
+
}
|
|
19627
|
+
if (!schema.required) {
|
|
19628
|
+
schema.required = [];
|
|
19629
|
+
}
|
|
19630
|
+
const fieldConfig = {
|
|
19631
|
+
type: fieldType === "number" ? "number" : fieldType === "boolean" ? "boolean" : "string",
|
|
19632
|
+
title: fieldLabel,
|
|
19633
|
+
searchable: isSearchable,
|
|
19634
|
+
...parsedOptions
|
|
19635
|
+
};
|
|
19636
|
+
if (fieldType === "richtext") {
|
|
19637
|
+
fieldConfig.format = "richtext";
|
|
19638
|
+
} else if (fieldType === "date") {
|
|
19639
|
+
fieldConfig.format = "date-time";
|
|
19640
|
+
} else if (fieldType === "select") {
|
|
19641
|
+
fieldConfig.enum = parsedOptions.options || [];
|
|
19642
|
+
} else if (fieldType === "media") {
|
|
19643
|
+
fieldConfig.format = "media";
|
|
19644
|
+
} else if (fieldType === "quill") {
|
|
19645
|
+
fieldConfig.type = "quill";
|
|
19646
|
+
} else if (fieldType === "mdxeditor") {
|
|
19647
|
+
fieldConfig.type = "mdxeditor";
|
|
19648
|
+
}
|
|
19649
|
+
schema.properties[fieldName] = fieldConfig;
|
|
19650
|
+
if (isRequired && !schema.required.includes(fieldName)) {
|
|
19651
|
+
schema.required.push(fieldName);
|
|
19652
|
+
}
|
|
19653
|
+
const updateSchemaStmt = db.prepare(`
|
|
19654
|
+
UPDATE collections
|
|
19655
|
+
SET schema = ?, updated_at = ?
|
|
19656
|
+
WHERE id = ?
|
|
19657
|
+
`);
|
|
19658
|
+
await updateSchemaStmt.bind(JSON.stringify(schema), Date.now(), collectionId).run();
|
|
19659
|
+
console.log("[Add Field] Added field to schema:", fieldName, fieldConfig);
|
|
19660
|
+
return c.json({ success: true, fieldId: `schema-${fieldName}` });
|
|
19661
|
+
}
|
|
19517
19662
|
const orderStmt = db.prepare("SELECT MAX(field_order) as max_order FROM content_fields WHERE collection_id = ?");
|
|
19518
19663
|
const orderResult = await orderStmt.bind(collectionId).first();
|
|
19519
19664
|
const nextOrder = (orderResult?.max_order || 0) + 1;
|
|
@@ -19654,7 +19799,39 @@ adminCollectionsRoutes.put("/:collectionId/fields/:fieldId", async (c) => {
|
|
|
19654
19799
|
adminCollectionsRoutes.delete("/:collectionId/fields/:fieldId", async (c) => {
|
|
19655
19800
|
try {
|
|
19656
19801
|
const fieldId = c.req.param("fieldId");
|
|
19802
|
+
const collectionId = c.req.param("collectionId");
|
|
19657
19803
|
const db = c.env.DB;
|
|
19804
|
+
if (fieldId.startsWith("schema-")) {
|
|
19805
|
+
const fieldName = fieldId.replace("schema-", "");
|
|
19806
|
+
const getCollectionStmt = db.prepare("SELECT * FROM collections WHERE id = ?");
|
|
19807
|
+
const collection = await getCollectionStmt.bind(collectionId).first();
|
|
19808
|
+
if (!collection) {
|
|
19809
|
+
return c.json({ success: false, error: "Collection not found." });
|
|
19810
|
+
}
|
|
19811
|
+
let schema = typeof collection.schema === "string" ? JSON.parse(collection.schema) : collection.schema;
|
|
19812
|
+
if (!schema || !schema.properties) {
|
|
19813
|
+
return c.json({ success: false, error: "Field not found in schema." });
|
|
19814
|
+
}
|
|
19815
|
+
if (schema.properties[fieldName]) {
|
|
19816
|
+
delete schema.properties[fieldName];
|
|
19817
|
+
if (schema.required && Array.isArray(schema.required)) {
|
|
19818
|
+
const requiredIndex = schema.required.indexOf(fieldName);
|
|
19819
|
+
if (requiredIndex !== -1) {
|
|
19820
|
+
schema.required.splice(requiredIndex, 1);
|
|
19821
|
+
}
|
|
19822
|
+
}
|
|
19823
|
+
const updateCollectionStmt = db.prepare(`
|
|
19824
|
+
UPDATE collections
|
|
19825
|
+
SET schema = ?, updated_at = ?
|
|
19826
|
+
WHERE id = ?
|
|
19827
|
+
`);
|
|
19828
|
+
await updateCollectionStmt.bind(JSON.stringify(schema), Date.now(), collectionId).run();
|
|
19829
|
+
console.log("[Delete Field] Removed field from schema:", fieldName);
|
|
19830
|
+
return c.json({ success: true });
|
|
19831
|
+
} else {
|
|
19832
|
+
return c.json({ success: false, error: "Field not found in schema." });
|
|
19833
|
+
}
|
|
19834
|
+
}
|
|
19658
19835
|
const deleteStmt = db.prepare("DELETE FROM content_fields WHERE id = ?");
|
|
19659
19836
|
await deleteStmt.bind(fieldId).run();
|
|
19660
19837
|
return c.json({ success: true });
|
|
@@ -19683,7 +19860,7 @@ adminCollectionsRoutes.post("/:collectionId/fields/reorder", async (c) => {
|
|
|
19683
19860
|
});
|
|
19684
19861
|
|
|
19685
19862
|
// src/templates/pages/admin-settings.template.ts
|
|
19686
|
-
|
|
19863
|
+
chunkAZLU3ROK_cjs.init_admin_layout_catalyst_template();
|
|
19687
19864
|
function renderSettingsPage(data) {
|
|
19688
19865
|
const activeTab = data.activeTab || "general";
|
|
19689
19866
|
const pageContent = `
|
|
@@ -20065,7 +20242,7 @@ function renderSettingsPage(data) {
|
|
|
20065
20242
|
version: data.version,
|
|
20066
20243
|
content: pageContent
|
|
20067
20244
|
};
|
|
20068
|
-
return
|
|
20245
|
+
return chunkAZLU3ROK_cjs.renderAdminLayoutCatalyst(layoutData);
|
|
20069
20246
|
}
|
|
20070
20247
|
function renderTabButton(tabId, label, iconPath, activeTab) {
|
|
20071
20248
|
const isActive = activeTab === tabId;
|
|
@@ -21147,7 +21324,7 @@ function renderDatabaseToolsSettings(settings) {
|
|
|
21147
21324
|
|
|
21148
21325
|
// src/routes/admin-settings.ts
|
|
21149
21326
|
var adminSettingsRoutes = new hono.Hono();
|
|
21150
|
-
adminSettingsRoutes.use("*",
|
|
21327
|
+
adminSettingsRoutes.use("*", chunkXWPGIFS7_cjs.requireAuth());
|
|
21151
21328
|
function getMockSettings(user) {
|
|
21152
21329
|
return {
|
|
21153
21330
|
general: {
|
|
@@ -21315,7 +21492,7 @@ adminSettingsRoutes.get("/database-tools", (c) => {
|
|
|
21315
21492
|
adminSettingsRoutes.get("/api/migrations/status", async (c) => {
|
|
21316
21493
|
try {
|
|
21317
21494
|
const db = c.env.DB;
|
|
21318
|
-
const migrationService = new
|
|
21495
|
+
const migrationService = new chunkETS5XSAG_cjs.MigrationService(db);
|
|
21319
21496
|
const status = await migrationService.getMigrationStatus();
|
|
21320
21497
|
return c.json({
|
|
21321
21498
|
success: true,
|
|
@@ -21339,7 +21516,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
|
|
|
21339
21516
|
}, 403);
|
|
21340
21517
|
}
|
|
21341
21518
|
const db = c.env.DB;
|
|
21342
|
-
const migrationService = new
|
|
21519
|
+
const migrationService = new chunkETS5XSAG_cjs.MigrationService(db);
|
|
21343
21520
|
const result = await migrationService.runPendingMigrations();
|
|
21344
21521
|
return c.json({
|
|
21345
21522
|
success: result.success,
|
|
@@ -21357,7 +21534,7 @@ adminSettingsRoutes.post("/api/migrations/run", async (c) => {
|
|
|
21357
21534
|
adminSettingsRoutes.get("/api/migrations/validate", async (c) => {
|
|
21358
21535
|
try {
|
|
21359
21536
|
const db = c.env.DB;
|
|
21360
|
-
const migrationService = new
|
|
21537
|
+
const migrationService = new chunkETS5XSAG_cjs.MigrationService(db);
|
|
21361
21538
|
const validation = await migrationService.validateSchema();
|
|
21362
21539
|
return c.json({
|
|
21363
21540
|
success: true,
|
|
@@ -21602,5 +21779,5 @@ exports.auth_default = auth_default;
|
|
|
21602
21779
|
exports.router = router;
|
|
21603
21780
|
exports.test_cleanup_default = test_cleanup_default;
|
|
21604
21781
|
exports.userRoutes = userRoutes;
|
|
21605
|
-
//# sourceMappingURL=chunk-
|
|
21606
|
-
//# sourceMappingURL=chunk-
|
|
21782
|
+
//# sourceMappingURL=chunk-D4PJFFOV.cjs.map
|
|
21783
|
+
//# sourceMappingURL=chunk-D4PJFFOV.cjs.map
|