@sonicjs-cms/core 2.0.7 → 2.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{chunk-OOV64BK4.cjs → chunk-4I25AGUR.cjs} +349 -267
- package/dist/chunk-4I25AGUR.cjs.map +1 -0
- package/dist/chunk-6FR25MPC.js.map +1 -1
- package/dist/{chunk-JB2NUJJ5.js → chunk-ABYMIXRN.js} +193 -111
- package/dist/chunk-ABYMIXRN.js.map +1 -0
- package/dist/{chunk-4MBTSUI6.js → chunk-COBUPOMD.js} +22 -6
- package/dist/chunk-COBUPOMD.js.map +1 -0
- package/dist/chunk-DOR2IU73.cjs.map +1 -1
- package/dist/{chunk-3R7EQNGO.cjs → chunk-DYYAXDXI.cjs} +6 -6
- package/dist/chunk-DYYAXDXI.cjs.map +1 -0
- package/dist/{chunk-7XEESVSX.cjs → chunk-EYMHWJTW.cjs} +2 -2
- package/dist/chunk-EYMHWJTW.cjs.map +1 -0
- package/dist/{chunk-HJZOA2O5.cjs → chunk-F5ESJXI2.cjs} +25 -3
- package/dist/chunk-F5ESJXI2.cjs.map +1 -0
- package/dist/chunk-FICTAGD4.js.map +1 -1
- package/dist/{chunk-EAELJXRV.js → chunk-HKEK7UNV.js} +25 -3
- package/dist/chunk-HKEK7UNV.js.map +1 -0
- package/dist/{chunk-KHNSPJ6X.cjs → chunk-MABBKINE.cjs} +5 -5
- package/dist/{chunk-KHNSPJ6X.cjs.map → chunk-MABBKINE.cjs.map} +1 -1
- package/dist/{chunk-YGVWY6KO.cjs → chunk-NBDPIRQS.cjs} +22 -5
- package/dist/chunk-NBDPIRQS.cjs.map +1 -0
- package/dist/{chunk-O7LMFJMZ.js → chunk-OKPDQO2Y.js} +3 -3
- package/dist/chunk-OKPDQO2Y.js.map +1 -0
- package/dist/{chunk-LS5CMDNL.js → chunk-OPGDMS7L.js} +3 -3
- package/dist/{chunk-LS5CMDNL.js.map → chunk-OPGDMS7L.js.map} +1 -1
- package/dist/chunk-RCQ2HIQD.cjs.map +1 -1
- package/dist/{chunk-RSFXIU6A.cjs → chunk-TMIRVVQ7.cjs} +4 -4
- package/dist/chunk-TMIRVVQ7.cjs.map +1 -0
- package/dist/{chunk-YHLLVUJC.js → chunk-VEC5MLT3.js} +2 -2
- package/dist/chunk-VEC5MLT3.js.map +1 -0
- package/dist/{chunk-YURRY22X.js → chunk-WRRLB6KG.js} +4 -4
- package/dist/chunk-WRRLB6KG.js.map +1 -0
- package/dist/index.cjs +108 -104
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +11 -11
- package/dist/index.js.map +1 -1
- package/dist/middleware.cjs +23 -23
- package/dist/middleware.js +2 -2
- package/dist/plugins.cjs +7 -7
- package/dist/plugins.js +1 -1
- package/dist/routes.cjs +25 -25
- package/dist/routes.js +5 -5
- package/dist/services.cjs +18 -14
- package/dist/services.js +1 -1
- package/dist/templates.cjs +18 -18
- package/dist/templates.js +2 -2
- package/dist/utils.cjs +11 -11
- package/dist/utils.js +1 -1
- package/migrations/019_remove_blog_posts_collection.sql +15 -0
- package/package.json +2 -2
- package/dist/chunk-3R7EQNGO.cjs.map +0 -1
- package/dist/chunk-4MBTSUI6.js.map +0 -1
- package/dist/chunk-7XEESVSX.cjs.map +0 -1
- package/dist/chunk-EAELJXRV.js.map +0 -1
- package/dist/chunk-HJZOA2O5.cjs.map +0 -1
- package/dist/chunk-JB2NUJJ5.js.map +0 -1
- package/dist/chunk-O7LMFJMZ.js.map +0 -1
- package/dist/chunk-OOV64BK4.cjs.map +0 -1
- package/dist/chunk-RSFXIU6A.cjs.map +0 -1
- package/dist/chunk-YGVWY6KO.cjs.map +0 -1
- package/dist/chunk-YHLLVUJC.js.map +0 -1
- package/dist/chunk-YURRY22X.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { getCacheService, CACHE_CONFIGS, getLogger, SettingsService } from './chunk-6FR25MPC.js';
|
|
2
|
-
import { requireAuth, isPluginActive, requireRole, AuthManager, logActivity } from './chunk-
|
|
3
|
-
import { PluginService, MigrationService } from './chunk-
|
|
4
|
-
import { init_admin_layout_catalyst_template, renderDesignPage, renderCheckboxPage, renderFAQList, renderTestimonialsList, renderCodeExamplesList, renderAlert, renderTable, renderPagination, renderConfirmationDialog, getConfirmationDialogScript, renderAdminLayoutCatalyst, renderAdminLayout, adminLayoutV2, renderForm } from './chunk-
|
|
5
|
-
import { QueryFilterBuilder, sanitizeInput, getCoreVersion, escapeHtml } from './chunk-
|
|
2
|
+
import { requireAuth, isPluginActive, requireRole, AuthManager, logActivity } from './chunk-OKPDQO2Y.js';
|
|
3
|
+
import { PluginService, MigrationService } from './chunk-COBUPOMD.js';
|
|
4
|
+
import { init_admin_layout_catalyst_template, renderDesignPage, renderCheckboxPage, renderFAQList, renderTestimonialsList, renderCodeExamplesList, renderAlert, renderTable, renderPagination, renderConfirmationDialog, getConfirmationDialogScript, renderAdminLayoutCatalyst, renderAdminLayout, adminLayoutV2, renderForm } from './chunk-VEC5MLT3.js';
|
|
5
|
+
import { QueryFilterBuilder, sanitizeInput, getCoreVersion, escapeHtml } from './chunk-WRRLB6KG.js';
|
|
6
6
|
import { metricsTracker } from './chunk-FICTAGD4.js';
|
|
7
7
|
import { Hono } from 'hono';
|
|
8
8
|
import { cors } from 'hono/cors';
|
|
@@ -1084,10 +1084,10 @@ apiMediaRoutes.patch("/:id", async (c) => {
|
|
|
1084
1084
|
const allowedFields = ["alt", "caption", "tags", "folder"];
|
|
1085
1085
|
const updates = [];
|
|
1086
1086
|
const values = [];
|
|
1087
|
-
for (const [key,
|
|
1087
|
+
for (const [key, value2] of Object.entries(body)) {
|
|
1088
1088
|
if (allowedFields.includes(key)) {
|
|
1089
1089
|
updates.push(`${key} = ?`);
|
|
1090
|
-
values.push(key === "tags" ? JSON.stringify(
|
|
1090
|
+
values.push(key === "tags" ? JSON.stringify(value2) : value2);
|
|
1091
1091
|
}
|
|
1092
1092
|
}
|
|
1093
1093
|
if (updates.length === 0) {
|
|
@@ -1568,7 +1568,7 @@ adminApiRoutes.post("/collections", async (c) => {
|
|
|
1568
1568
|
}
|
|
1569
1569
|
const validatedData = validation.data;
|
|
1570
1570
|
const db = c.env.DB;
|
|
1571
|
-
const
|
|
1571
|
+
const ____user = c.get("user");
|
|
1572
1572
|
const displayName = validatedData.displayName || validatedData.display_name || "";
|
|
1573
1573
|
const existingStmt = db.prepare("SELECT id FROM collections WHERE name = ?");
|
|
1574
1574
|
const existing = await existingStmt.bind(validatedData.name).first();
|
|
@@ -2320,7 +2320,6 @@ authRoutes.post("/register/form", async (c) => {
|
|
|
2320
2320
|
`);
|
|
2321
2321
|
}
|
|
2322
2322
|
const validatedData = validation.data;
|
|
2323
|
-
const email = validatedData.email;
|
|
2324
2323
|
const password = validatedData.password;
|
|
2325
2324
|
const username = validatedData.username || authValidationService.generateDefaultValue("username", validatedData);
|
|
2326
2325
|
const firstName = validatedData.firstName || authValidationService.generateDefaultValue("firstName", validatedData);
|
|
@@ -2991,7 +2990,7 @@ init_admin_layout_catalyst_template();
|
|
|
2991
2990
|
|
|
2992
2991
|
// src/templates/components/dynamic-field.template.ts
|
|
2993
2992
|
function renderDynamicField(field, options = {}) {
|
|
2994
|
-
const { value = "", errors = [], disabled = false, className = "" } = options;
|
|
2993
|
+
const { value: value2 = "", errors = [], disabled = false, className = "" } = options;
|
|
2995
2994
|
const opts = field.field_options || {};
|
|
2996
2995
|
const required = field.is_required ? "required" : "";
|
|
2997
2996
|
const baseClasses = `w-full rounded-lg px-3 py-2 text-sm text-zinc-950 dark:text-white bg-white dark:bg-zinc-800 shadow-sm ring-1 ring-inset ring-zinc-950/10 dark:ring-white/10 placeholder:text-zinc-400 dark:placeholder:text-zinc-500 focus:outline-none focus:ring-2 focus:ring-zinc-950 dark:focus:ring-white transition-shadow ${className}`;
|
|
@@ -3048,7 +3047,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3048
3047
|
type="text"
|
|
3049
3048
|
id="${fieldId}"
|
|
3050
3049
|
name="${fieldName}"
|
|
3051
|
-
value="${escapeHtml2(
|
|
3050
|
+
value="${escapeHtml2(value2)}"
|
|
3052
3051
|
placeholder="${opts.placeholder || ""}"
|
|
3053
3052
|
maxlength="${opts.maxLength || ""}"
|
|
3054
3053
|
${opts.pattern ? `data-pattern="${opts.pattern}"` : ""}
|
|
@@ -3093,7 +3092,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3093
3092
|
class="${baseClasses} ${errorClasses} min-h-[${opts.height || 300}px]"
|
|
3094
3093
|
${required}
|
|
3095
3094
|
${disabled ? "disabled" : ""}
|
|
3096
|
-
>${escapeHtml2(
|
|
3095
|
+
>${escapeHtml2(value2)}</textarea>
|
|
3097
3096
|
<script>
|
|
3098
3097
|
// Initialize TinyMCE for this field
|
|
3099
3098
|
if (typeof tinymce !== 'undefined') {
|
|
@@ -3127,7 +3126,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3127
3126
|
type="number"
|
|
3128
3127
|
id="${fieldId}"
|
|
3129
3128
|
name="${fieldName}"
|
|
3130
|
-
value="${
|
|
3129
|
+
value="${value2}"
|
|
3131
3130
|
min="${opts.min || ""}"
|
|
3132
3131
|
max="${opts.max || ""}"
|
|
3133
3132
|
step="${opts.step || ""}"
|
|
@@ -3139,7 +3138,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3139
3138
|
`;
|
|
3140
3139
|
break;
|
|
3141
3140
|
case "boolean":
|
|
3142
|
-
const checked =
|
|
3141
|
+
const checked = value2 === true || value2 === "true" || value2 === "1" ? "checked" : "";
|
|
3143
3142
|
fieldHTML = `
|
|
3144
3143
|
<div class="flex items-center space-x-3">
|
|
3145
3144
|
<input
|
|
@@ -3164,7 +3163,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3164
3163
|
type="date"
|
|
3165
3164
|
id="${fieldId}"
|
|
3166
3165
|
name="${fieldName}"
|
|
3167
|
-
value="${
|
|
3166
|
+
value="${value2}"
|
|
3168
3167
|
min="${opts.min || ""}"
|
|
3169
3168
|
max="${opts.max || ""}"
|
|
3170
3169
|
class="${baseClasses} ${errorClasses}"
|
|
@@ -3176,7 +3175,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3176
3175
|
case "select":
|
|
3177
3176
|
const options2 = opts.options || [];
|
|
3178
3177
|
const multiple = opts.multiple ? "multiple" : "";
|
|
3179
|
-
const selectedValues = Array.isArray(
|
|
3178
|
+
const selectedValues = Array.isArray(value2) ? value2 : [value2];
|
|
3180
3179
|
fieldHTML = `
|
|
3181
3180
|
<select
|
|
3182
3181
|
id="${fieldId}"
|
|
@@ -3209,9 +3208,9 @@ function renderDynamicField(field, options = {}) {
|
|
|
3209
3208
|
case "media":
|
|
3210
3209
|
fieldHTML = `
|
|
3211
3210
|
<div class="media-field-container">
|
|
3212
|
-
<input type="hidden" id="${fieldId}" name="${fieldName}" value="${
|
|
3213
|
-
<div class="media-preview ${
|
|
3214
|
-
${
|
|
3211
|
+
<input type="hidden" id="${fieldId}" name="${fieldName}" value="${value2}">
|
|
3212
|
+
<div class="media-preview ${value2 ? "" : "hidden"}" id="${fieldId}-preview">
|
|
3213
|
+
${value2 ? `<img src="${value2}" alt="Selected media" class="w-32 h-32 object-cover rounded-lg border border-white/20">` : ""}
|
|
3215
3214
|
</div>
|
|
3216
3215
|
<div class="media-actions mt-2 space-x-2">
|
|
3217
3216
|
<button
|
|
@@ -3225,7 +3224,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3225
3224
|
</svg>
|
|
3226
3225
|
Select Media
|
|
3227
3226
|
</button>
|
|
3228
|
-
${
|
|
3227
|
+
${value2 ? `
|
|
3229
3228
|
<button
|
|
3230
3229
|
type="button"
|
|
3231
3230
|
onclick="clearMediaField('${fieldId}')"
|
|
@@ -3246,7 +3245,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3246
3245
|
type="text"
|
|
3247
3246
|
id="${fieldId}"
|
|
3248
3247
|
name="${fieldName}"
|
|
3249
|
-
value="${escapeHtml2(
|
|
3248
|
+
value="${escapeHtml2(value2)}"
|
|
3250
3249
|
class="${baseClasses} bg-zinc-100 dark:bg-zinc-800/50 cursor-not-allowed"
|
|
3251
3250
|
readonly
|
|
3252
3251
|
disabled
|
|
@@ -3256,7 +3255,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3256
3255
|
<path stroke-linecap="round" stroke-linejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z"/>
|
|
3257
3256
|
</svg>
|
|
3258
3257
|
<div class="text-xs text-zinc-600 dark:text-zinc-400">
|
|
3259
|
-
${
|
|
3258
|
+
${value2 ? "This unique identifier was automatically generated and cannot be changed." : "A unique identifier (UUID) will be automatically generated when you save this content."}
|
|
3260
3259
|
</div>
|
|
3261
3260
|
</div>
|
|
3262
3261
|
</div>
|
|
@@ -3268,7 +3267,7 @@ function renderDynamicField(field, options = {}) {
|
|
|
3268
3267
|
type="text"
|
|
3269
3268
|
id="${fieldId}"
|
|
3270
3269
|
name="${fieldName}"
|
|
3271
|
-
value="${escapeHtml2(
|
|
3270
|
+
value="${escapeHtml2(value2)}"
|
|
3272
3271
|
class="${baseClasses} ${errorClasses}"
|
|
3273
3272
|
${required}
|
|
3274
3273
|
${disabled ? "disabled" : ""}
|
|
@@ -3956,9 +3955,9 @@ function renderContentListPage(data) {
|
|
|
3956
3955
|
name: "model",
|
|
3957
3956
|
label: "Model",
|
|
3958
3957
|
options: [
|
|
3959
|
-
{
|
|
3958
|
+
{ __value: "all", label: "All Models", selected: data.modelName === "all" },
|
|
3960
3959
|
...data.models.map((model) => ({
|
|
3961
|
-
|
|
3960
|
+
__value: model.name,
|
|
3962
3961
|
label: model.displayName,
|
|
3963
3962
|
selected: data.modelName === model.name
|
|
3964
3963
|
}))
|
|
@@ -3968,13 +3967,13 @@ function renderContentListPage(data) {
|
|
|
3968
3967
|
name: "status",
|
|
3969
3968
|
label: "Status",
|
|
3970
3969
|
options: [
|
|
3971
|
-
{
|
|
3972
|
-
{
|
|
3973
|
-
{
|
|
3974
|
-
{
|
|
3975
|
-
{
|
|
3976
|
-
{
|
|
3977
|
-
{
|
|
3970
|
+
{ __value: "all", label: "All Status", selected: data.status === "all" },
|
|
3971
|
+
{ __value: "draft", label: "Draft", selected: data.status === "draft" },
|
|
3972
|
+
{ __value: "review", label: "Under Review", selected: data.status === "review" },
|
|
3973
|
+
{ __value: "scheduled", label: "Scheduled", selected: data.status === "scheduled" },
|
|
3974
|
+
{ __value: "published", label: "Published", selected: data.status === "published" },
|
|
3975
|
+
{ __value: "archived", label: "Archived", selected: data.status === "archived" },
|
|
3976
|
+
{ __value: "deleted", label: "Deleted", selected: data.status === "deleted" }
|
|
3978
3977
|
]
|
|
3979
3978
|
}
|
|
3980
3979
|
],
|
|
@@ -3986,9 +3985,9 @@ function renderContentListPage(data) {
|
|
|
3986
3985
|
}
|
|
3987
3986
|
],
|
|
3988
3987
|
bulkActions: [
|
|
3989
|
-
{ label: "Publish",
|
|
3990
|
-
{ label: "Unpublish",
|
|
3991
|
-
{ label: "Delete",
|
|
3988
|
+
{ label: "Publish", ___value: "publish", icon: "check-circle" },
|
|
3989
|
+
{ label: "Unpublish", ___value: "unpublish", icon: "x-circle" },
|
|
3990
|
+
{ label: "Delete", ___value: "delete", icon: "trash", className: "text-pink-600" }
|
|
3992
3991
|
]
|
|
3993
3992
|
};
|
|
3994
3993
|
const tableColumns = [
|
|
@@ -3997,7 +3996,7 @@ function renderContentListPage(data) {
|
|
|
3997
3996
|
label: "Title",
|
|
3998
3997
|
sortable: true,
|
|
3999
3998
|
sortType: "string",
|
|
4000
|
-
render: (
|
|
3999
|
+
render: (value2, row) => `
|
|
4001
4000
|
<div class="flex items-center">
|
|
4002
4001
|
<div>
|
|
4003
4002
|
<div class="text-sm font-medium text-zinc-950 dark:text-white">
|
|
@@ -4020,7 +4019,7 @@ function renderContentListPage(data) {
|
|
|
4020
4019
|
label: "Status",
|
|
4021
4020
|
sortable: true,
|
|
4022
4021
|
sortType: "string",
|
|
4023
|
-
render: (
|
|
4022
|
+
render: (value2) => value2
|
|
4024
4023
|
},
|
|
4025
4024
|
{
|
|
4026
4025
|
key: "authorName",
|
|
@@ -4041,7 +4040,7 @@ function renderContentListPage(data) {
|
|
|
4041
4040
|
label: "Actions",
|
|
4042
4041
|
sortable: false,
|
|
4043
4042
|
className: "text-sm font-medium",
|
|
4044
|
-
render: (
|
|
4043
|
+
render: (value2, row) => `
|
|
4045
4044
|
<div class="flex space-x-2">
|
|
4046
4045
|
<button
|
|
4047
4046
|
class="inline-flex items-center justify-center p-1.5 rounded-lg bg-cyan-50 dark:bg-cyan-500/10 text-cyan-700 dark:text-cyan-400 ring-1 ring-inset ring-cyan-600/20 dark:ring-cyan-500/20 hover:bg-cyan-100 dark:hover:bg-cyan-500/20 transition-colors"
|
|
@@ -5140,7 +5139,7 @@ adminContentRoutes.post("/", async (c) => {
|
|
|
5140
5139
|
const data = {};
|
|
5141
5140
|
const errors = {};
|
|
5142
5141
|
for (const field of fields) {
|
|
5143
|
-
const
|
|
5142
|
+
const value2 = formData.get(field.field_name);
|
|
5144
5143
|
if (field.field_type === "guid") {
|
|
5145
5144
|
const options = field.field_options || {};
|
|
5146
5145
|
if (options.autoGenerate) {
|
|
@@ -5148,33 +5147,33 @@ adminContentRoutes.post("/", async (c) => {
|
|
|
5148
5147
|
continue;
|
|
5149
5148
|
}
|
|
5150
5149
|
}
|
|
5151
|
-
if (field.is_required && (!
|
|
5150
|
+
if (field.is_required && (!value2 || value2.toString().trim() === "")) {
|
|
5152
5151
|
errors[field.field_name] = [`${field.field_label} is required`];
|
|
5153
5152
|
continue;
|
|
5154
5153
|
}
|
|
5155
5154
|
switch (field.field_type) {
|
|
5156
5155
|
case "number":
|
|
5157
|
-
if (
|
|
5156
|
+
if (value2 && isNaN(Number(value2))) {
|
|
5158
5157
|
errors[field.field_name] = [`${field.field_label} must be a valid number`];
|
|
5159
5158
|
} else {
|
|
5160
|
-
data[field.field_name] =
|
|
5159
|
+
data[field.field_name] = value2 ? Number(value2) : null;
|
|
5161
5160
|
}
|
|
5162
5161
|
break;
|
|
5163
5162
|
case "boolean":
|
|
5164
|
-
data[field.field_name] = formData.get(`${field.field_name}_submitted`) ?
|
|
5163
|
+
data[field.field_name] = formData.get(`${field.field_name}_submitted`) ? value2 === "true" : false;
|
|
5165
5164
|
break;
|
|
5166
5165
|
case "select":
|
|
5167
5166
|
if (field.field_options?.multiple) {
|
|
5168
5167
|
data[field.field_name] = formData.getAll(`${field.field_name}[]`);
|
|
5169
5168
|
} else {
|
|
5170
|
-
data[field.field_name] =
|
|
5169
|
+
data[field.field_name] = value2;
|
|
5171
5170
|
}
|
|
5172
5171
|
break;
|
|
5173
5172
|
case "guid":
|
|
5174
|
-
data[field.field_name] =
|
|
5173
|
+
data[field.field_name] = value2 || null;
|
|
5175
5174
|
break;
|
|
5176
5175
|
default:
|
|
5177
|
-
data[field.field_name] =
|
|
5176
|
+
data[field.field_name] = value2;
|
|
5178
5177
|
}
|
|
5179
5178
|
}
|
|
5180
5179
|
if (Object.keys(errors).length > 0) {
|
|
@@ -5302,31 +5301,31 @@ adminContentRoutes.put("/:id", async (c) => {
|
|
|
5302
5301
|
const data = {};
|
|
5303
5302
|
const errors = {};
|
|
5304
5303
|
for (const field of fields) {
|
|
5305
|
-
const
|
|
5306
|
-
if (field.is_required && (!
|
|
5304
|
+
const value2 = formData.get(field.field_name);
|
|
5305
|
+
if (field.is_required && (!value2 || value2.toString().trim() === "")) {
|
|
5307
5306
|
errors[field.field_name] = [`${field.field_label} is required`];
|
|
5308
5307
|
continue;
|
|
5309
5308
|
}
|
|
5310
5309
|
switch (field.field_type) {
|
|
5311
5310
|
case "number":
|
|
5312
|
-
if (
|
|
5311
|
+
if (value2 && isNaN(Number(value2))) {
|
|
5313
5312
|
errors[field.field_name] = [`${field.field_label} must be a valid number`];
|
|
5314
5313
|
} else {
|
|
5315
|
-
data[field.field_name] =
|
|
5314
|
+
data[field.field_name] = value2 ? Number(value2) : null;
|
|
5316
5315
|
}
|
|
5317
5316
|
break;
|
|
5318
5317
|
case "boolean":
|
|
5319
|
-
data[field.field_name] = formData.get(`${field.field_name}_submitted`) ?
|
|
5318
|
+
data[field.field_name] = formData.get(`${field.field_name}_submitted`) ? value2 === "true" : false;
|
|
5320
5319
|
break;
|
|
5321
5320
|
case "select":
|
|
5322
5321
|
if (field.field_options?.multiple) {
|
|
5323
5322
|
data[field.field_name] = formData.getAll(`${field.field_name}[]`);
|
|
5324
5323
|
} else {
|
|
5325
|
-
data[field.field_name] =
|
|
5324
|
+
data[field.field_name] = value2;
|
|
5326
5325
|
}
|
|
5327
5326
|
break;
|
|
5328
5327
|
default:
|
|
5329
|
-
data[field.field_name] =
|
|
5328
|
+
data[field.field_name] = value2;
|
|
5330
5329
|
}
|
|
5331
5330
|
}
|
|
5332
5331
|
if (Object.keys(errors).length > 0) {
|
|
@@ -5443,23 +5442,23 @@ adminContentRoutes.post("/preview", async (c) => {
|
|
|
5443
5442
|
const fields = await getCollectionFields(db, collectionId);
|
|
5444
5443
|
const data = {};
|
|
5445
5444
|
for (const field of fields) {
|
|
5446
|
-
const
|
|
5445
|
+
const value2 = formData.get(field.field_name);
|
|
5447
5446
|
switch (field.field_type) {
|
|
5448
5447
|
case "number":
|
|
5449
|
-
data[field.field_name] =
|
|
5448
|
+
data[field.field_name] = value2 ? Number(value2) : null;
|
|
5450
5449
|
break;
|
|
5451
5450
|
case "boolean":
|
|
5452
|
-
data[field.field_name] =
|
|
5451
|
+
data[field.field_name] = value2 === "true";
|
|
5453
5452
|
break;
|
|
5454
5453
|
case "select":
|
|
5455
5454
|
if (field.field_options?.multiple) {
|
|
5456
5455
|
data[field.field_name] = formData.getAll(`${field.field_name}[]`);
|
|
5457
5456
|
} else {
|
|
5458
|
-
data[field.field_name] =
|
|
5457
|
+
data[field.field_name] = value2;
|
|
5459
5458
|
}
|
|
5460
5459
|
break;
|
|
5461
5460
|
default:
|
|
5462
|
-
data[field.field_name] =
|
|
5461
|
+
data[field.field_name] = value2;
|
|
5463
5462
|
}
|
|
5464
5463
|
}
|
|
5465
5464
|
const previewHTML = `
|
|
@@ -7316,10 +7315,10 @@ function renderUsersListPage(data) {
|
|
|
7316
7315
|
label: "",
|
|
7317
7316
|
className: "w-12",
|
|
7318
7317
|
sortable: false,
|
|
7319
|
-
render: (
|
|
7318
|
+
render: (value2, row) => {
|
|
7320
7319
|
const initials = `${row.firstName.charAt(0)}${row.lastName.charAt(0)}`.toUpperCase();
|
|
7321
|
-
if (
|
|
7322
|
-
return `<img src="${
|
|
7320
|
+
if (value2) {
|
|
7321
|
+
return `<img src="${value2}" alt="${row.firstName} ${row.lastName}" class="w-8 h-8 rounded-full">`;
|
|
7323
7322
|
}
|
|
7324
7323
|
return `
|
|
7325
7324
|
<div class="w-8 h-8 bg-gradient-to-br from-cyan-400 to-blue-500 dark:from-cyan-300 dark:to-blue-400 rounded-full flex items-center justify-center">
|
|
@@ -7333,7 +7332,7 @@ function renderUsersListPage(data) {
|
|
|
7333
7332
|
label: "Name",
|
|
7334
7333
|
sortable: true,
|
|
7335
7334
|
sortType: "string",
|
|
7336
|
-
render: (
|
|
7335
|
+
render: (_value, row) => {
|
|
7337
7336
|
const escapeHtml7 = (text) => text.replace(/[&<>"']/g, (char) => ({
|
|
7338
7337
|
"&": "&",
|
|
7339
7338
|
"<": "<",
|
|
@@ -7360,7 +7359,7 @@ function renderUsersListPage(data) {
|
|
|
7360
7359
|
label: "Email",
|
|
7361
7360
|
sortable: true,
|
|
7362
7361
|
sortType: "string",
|
|
7363
|
-
render: (
|
|
7362
|
+
render: (value2) => {
|
|
7364
7363
|
const escapeHtml7 = (text) => text.replace(/[&<>"']/g, (char) => ({
|
|
7365
7364
|
"&": "&",
|
|
7366
7365
|
"<": "<",
|
|
@@ -7368,7 +7367,7 @@ function renderUsersListPage(data) {
|
|
|
7368
7367
|
'"': """,
|
|
7369
7368
|
"'": "'"
|
|
7370
7369
|
})[char] || char);
|
|
7371
|
-
const escapedEmail = escapeHtml7(
|
|
7370
|
+
const escapedEmail = escapeHtml7(value2);
|
|
7372
7371
|
return `<a href="mailto:${escapedEmail}" class="text-cyan-600 dark:text-cyan-400 hover:text-cyan-700 dark:hover:text-cyan-300 transition-colors">${escapedEmail}</a>`;
|
|
7373
7372
|
}
|
|
7374
7373
|
},
|
|
@@ -7377,7 +7376,7 @@ function renderUsersListPage(data) {
|
|
|
7377
7376
|
label: "Role",
|
|
7378
7377
|
sortable: true,
|
|
7379
7378
|
sortType: "string",
|
|
7380
|
-
render: (
|
|
7379
|
+
render: (_value) => {
|
|
7381
7380
|
const roleColors = {
|
|
7382
7381
|
admin: "bg-red-50 dark:bg-red-500/10 text-red-700 dark:text-red-400 ring-1 ring-inset ring-red-700/10 dark:ring-red-500/20",
|
|
7383
7382
|
editor: "bg-blue-50 dark:bg-blue-500/10 text-blue-700 dark:text-blue-400 ring-1 ring-inset ring-blue-700/10 dark:ring-blue-500/20",
|
|
@@ -7393,7 +7392,7 @@ function renderUsersListPage(data) {
|
|
|
7393
7392
|
label: "Last Login",
|
|
7394
7393
|
sortable: true,
|
|
7395
7394
|
sortType: "date",
|
|
7396
|
-
render: (
|
|
7395
|
+
render: (_value) => {
|
|
7397
7396
|
if (!value) return '<span class="text-zinc-500 dark:text-zinc-400">Never</span>';
|
|
7398
7397
|
return `<span class="text-sm text-zinc-500 dark:text-zinc-400">${new Date(value).toLocaleDateString()}</span>`;
|
|
7399
7398
|
}
|
|
@@ -7403,14 +7402,14 @@ function renderUsersListPage(data) {
|
|
|
7403
7402
|
label: "Created",
|
|
7404
7403
|
sortable: true,
|
|
7405
7404
|
sortType: "date",
|
|
7406
|
-
render: (
|
|
7405
|
+
render: (_value) => `<span class="text-sm text-zinc-500 dark:text-zinc-400">${new Date(value).toLocaleDateString()}</span>`
|
|
7407
7406
|
},
|
|
7408
7407
|
{
|
|
7409
7408
|
key: "actions",
|
|
7410
7409
|
label: "Actions",
|
|
7411
7410
|
className: "text-right",
|
|
7412
7411
|
sortable: false,
|
|
7413
|
-
render: (
|
|
7412
|
+
render: (_value, row) => `
|
|
7414
7413
|
<div class="flex justify-end space-x-2">
|
|
7415
7414
|
${row.isActive ? `<button onclick="toggleUserStatus('${row.id}', false)" title="Deactivate user" class="inline-flex items-center justify-center p-2 text-sm font-medium rounded-lg bg-gradient-to-r from-red-500 to-pink-500 dark:from-red-400 dark:to-pink-400 text-white hover:from-red-600 hover:to-pink-600 dark:hover:from-red-500 dark:hover:to-pink-500 shadow-sm transition-all duration-200">
|
|
7416
7415
|
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
@@ -7901,7 +7900,7 @@ userRoutes.post("/profile/avatar", async (c) => {
|
|
|
7901
7900
|
try {
|
|
7902
7901
|
const formData = await c.req.formData();
|
|
7903
7902
|
const avatarFile = formData.get("avatar");
|
|
7904
|
-
if (!avatarFile || !avatarFile.name) {
|
|
7903
|
+
if (!avatarFile || !(avatarFile instanceof File) || !avatarFile.name) {
|
|
7905
7904
|
return c.html(renderAlert2({
|
|
7906
7905
|
type: "error",
|
|
7907
7906
|
message: "Please select an image file.",
|
|
@@ -8019,7 +8018,7 @@ userRoutes.post("/profile/password", async (c) => {
|
|
|
8019
8018
|
VALUES (?, ?, ?, ?)
|
|
8020
8019
|
`);
|
|
8021
8020
|
await historyStmt.bind(
|
|
8022
|
-
|
|
8021
|
+
crypto.randomUUID(),
|
|
8023
8022
|
user.userId,
|
|
8024
8023
|
userData.password_hash,
|
|
8025
8024
|
Date.now()
|
|
@@ -8251,7 +8250,7 @@ userRoutes.post("/users/new", async (c) => {
|
|
|
8251
8250
|
}));
|
|
8252
8251
|
}
|
|
8253
8252
|
const passwordHash = await AuthManager.hashPassword(password);
|
|
8254
|
-
const userId =
|
|
8253
|
+
const userId = crypto.randomUUID();
|
|
8255
8254
|
const createStmt = db.prepare(`
|
|
8256
8255
|
INSERT INTO users (
|
|
8257
8256
|
id, email, username, first_name, last_name, phone, bio,
|
|
@@ -8568,9 +8567,8 @@ userRoutes.post("/invite-user", async (c) => {
|
|
|
8568
8567
|
if (existingUser) {
|
|
8569
8568
|
return c.json({ error: "A user with this email already exists" }, 400);
|
|
8570
8569
|
}
|
|
8571
|
-
const invitationToken =
|
|
8572
|
-
const
|
|
8573
|
-
const userId = globalThis.crypto.randomUUID();
|
|
8570
|
+
const invitationToken = crypto.randomUUID();
|
|
8571
|
+
const userId = crypto.randomUUID();
|
|
8574
8572
|
const createUserStmt = db.prepare(`
|
|
8575
8573
|
INSERT INTO users (
|
|
8576
8574
|
id, email, first_name, last_name, role,
|
|
@@ -8635,7 +8633,7 @@ userRoutes.post("/resend-invitation/:id", async (c) => {
|
|
|
8635
8633
|
if (!invitedUser) {
|
|
8636
8634
|
return c.json({ error: "User not found or invitation not valid" }, 404);
|
|
8637
8635
|
}
|
|
8638
|
-
const newInvitationToken =
|
|
8636
|
+
const newInvitationToken = crypto.randomUUID();
|
|
8639
8637
|
const updateStmt = db.prepare(`
|
|
8640
8638
|
UPDATE users SET
|
|
8641
8639
|
invitation_token = ?,
|
|
@@ -10223,7 +10221,7 @@ adminMediaRoutes.get("/", async (c) => {
|
|
|
10223
10221
|
const type = searchParams.get("type") || "all";
|
|
10224
10222
|
const view = searchParams.get("view") || "grid";
|
|
10225
10223
|
const page = parseInt(searchParams.get("page") || "1");
|
|
10226
|
-
const
|
|
10224
|
+
const ____cacheBust = searchParams.get("t");
|
|
10227
10225
|
const limit = 24;
|
|
10228
10226
|
const offset = (page - 1) * limit;
|
|
10229
10227
|
const db = c.env.DB;
|
|
@@ -10649,7 +10647,7 @@ adminMediaRoutes.post("/upload", async (c) => {
|
|
|
10649
10647
|
});
|
|
10650
10648
|
}
|
|
10651
10649
|
}
|
|
10652
|
-
let
|
|
10650
|
+
let __mediaGridHTML = "";
|
|
10653
10651
|
if (uploadResults.length > 0) {
|
|
10654
10652
|
try {
|
|
10655
10653
|
const folder = formData.get("folder") || "uploads";
|
|
@@ -12145,10 +12143,10 @@ function renderSettingsTab(plugin) {
|
|
|
12145
12143
|
`;
|
|
12146
12144
|
}
|
|
12147
12145
|
function renderSettingsFields(settings) {
|
|
12148
|
-
return Object.entries(settings).map(([key,
|
|
12146
|
+
return Object.entries(settings).map(([key, value2]) => {
|
|
12149
12147
|
const fieldId = `setting_${key}`;
|
|
12150
12148
|
const displayName = key.replace(/([A-Z])/g, " $1").replace(/^./, (str) => str.toUpperCase());
|
|
12151
|
-
if (typeof
|
|
12149
|
+
if (typeof value2 === "boolean") {
|
|
12152
12150
|
return `
|
|
12153
12151
|
<div class="flex items-center justify-between">
|
|
12154
12152
|
<div>
|
|
@@ -12156,12 +12154,12 @@ function renderSettingsFields(settings) {
|
|
|
12156
12154
|
<p class="text-xs text-gray-400">Enable or disable this feature</p>
|
|
12157
12155
|
</div>
|
|
12158
12156
|
<label class="relative inline-flex items-center cursor-pointer">
|
|
12159
|
-
<input type="checkbox" name="${fieldId}" id="${fieldId}" ${
|
|
12157
|
+
<input type="checkbox" name="${fieldId}" id="${fieldId}" ${value2 ? "checked" : ""} class="sr-only peer">
|
|
12160
12158
|
<div class="w-11 h-6 bg-gray-600 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600"></div>
|
|
12161
12159
|
</label>
|
|
12162
12160
|
</div>
|
|
12163
12161
|
`;
|
|
12164
|
-
} else if (typeof
|
|
12162
|
+
} else if (typeof value2 === "number") {
|
|
12165
12163
|
return `
|
|
12166
12164
|
<div>
|
|
12167
12165
|
<label for="${fieldId}" class="block text-sm font-medium text-gray-300 mb-2">${displayName}</label>
|
|
@@ -12169,7 +12167,7 @@ function renderSettingsFields(settings) {
|
|
|
12169
12167
|
type="number"
|
|
12170
12168
|
name="${fieldId}"
|
|
12171
12169
|
id="${fieldId}"
|
|
12172
|
-
value="${
|
|
12170
|
+
value="${value2}"
|
|
12173
12171
|
class="backdrop-blur-sm bg-white/10 border border-white/20 rounded-lg px-3 py-2 text-white placeholder-gray-300 focus:border-blue-400 focus:outline-none transition-colors w-full"
|
|
12174
12172
|
>
|
|
12175
12173
|
</div>
|
|
@@ -12182,7 +12180,7 @@ function renderSettingsFields(settings) {
|
|
|
12182
12180
|
type="text"
|
|
12183
12181
|
name="${fieldId}"
|
|
12184
12182
|
id="${fieldId}"
|
|
12185
|
-
value="${
|
|
12183
|
+
value="${value2}"
|
|
12186
12184
|
class="backdrop-blur-sm bg-white/10 border border-white/20 rounded-lg px-3 py-2 text-white placeholder-gray-300 focus:border-blue-400 focus:outline-none transition-colors w-full"
|
|
12187
12185
|
>
|
|
12188
12186
|
</div>
|
|
@@ -16690,8 +16688,8 @@ function renderTable2(data) {
|
|
|
16690
16688
|
</td>
|
|
16691
16689
|
` : ""}
|
|
16692
16690
|
${data.columns.map((column, colIndex) => {
|
|
16693
|
-
const
|
|
16694
|
-
const displayValue = column.render ? column.render(
|
|
16691
|
+
const value2 = row[column.key];
|
|
16692
|
+
const displayValue = column.render ? column.render(value2, row) : value2;
|
|
16695
16693
|
const stopPropagation = column.key === "actions" ? 'onclick="event.stopPropagation()"' : "";
|
|
16696
16694
|
const isFirst = colIndex === 0 && !data.selectable;
|
|
16697
16695
|
const isLast = colIndex === data.columns.length - 1;
|
|
@@ -16828,7 +16826,7 @@ function renderCollectionsListPage(data) {
|
|
|
16828
16826
|
label: "Name",
|
|
16829
16827
|
sortable: true,
|
|
16830
16828
|
sortType: "string",
|
|
16831
|
-
render: (
|
|
16829
|
+
render: (_value, collection) => `
|
|
16832
16830
|
<div class="flex items-center gap-2 ml-2">
|
|
16833
16831
|
<span class="inline-flex items-center rounded-md bg-cyan-50 dark:bg-cyan-500/10 px-2.5 py-1 text-sm font-medium text-cyan-700 dark:text-cyan-300 ring-1 ring-inset ring-cyan-700/10 dark:ring-cyan-400/20">
|
|
16834
16832
|
${collection.name}
|
|
@@ -16855,14 +16853,14 @@ function renderCollectionsListPage(data) {
|
|
|
16855
16853
|
label: "Description",
|
|
16856
16854
|
sortable: true,
|
|
16857
16855
|
sortType: "string",
|
|
16858
|
-
render: (
|
|
16856
|
+
render: (_value, collection) => collection.description || '<span class="text-zinc-500 dark:text-zinc-400">-</span>'
|
|
16859
16857
|
},
|
|
16860
16858
|
{
|
|
16861
16859
|
key: "field_count",
|
|
16862
16860
|
label: "Fields",
|
|
16863
16861
|
sortable: true,
|
|
16864
16862
|
sortType: "number",
|
|
16865
|
-
render: (
|
|
16863
|
+
render: (_value, collection) => {
|
|
16866
16864
|
const count = collection.field_count || 0;
|
|
16867
16865
|
return `
|
|
16868
16866
|
<div class="flex items-center">
|
|
@@ -16878,7 +16876,7 @@ function renderCollectionsListPage(data) {
|
|
|
16878
16876
|
label: "Source",
|
|
16879
16877
|
sortable: true,
|
|
16880
16878
|
sortType: "string",
|
|
16881
|
-
render: (
|
|
16879
|
+
render: (_value, collection) => {
|
|
16882
16880
|
if (collection.managed) {
|
|
16883
16881
|
return `
|
|
16884
16882
|
<div class="flex items-center gap-1.5">
|
|
@@ -16912,7 +16910,7 @@ function renderCollectionsListPage(data) {
|
|
|
16912
16910
|
key: "actions",
|
|
16913
16911
|
label: "Content",
|
|
16914
16912
|
sortable: false,
|
|
16915
|
-
render: (
|
|
16913
|
+
render: (_value, collection) => {
|
|
16916
16914
|
if (!collection || !collection.id) return '<span class="text-zinc-500 dark:text-zinc-400">-</span>';
|
|
16917
16915
|
return `
|
|
16918
16916
|
<div class="flex items-center space-x-2">
|
|
@@ -17307,7 +17305,55 @@ function renderCollectionFormPage(data) {
|
|
|
17307
17305
|
</style>
|
|
17308
17306
|
|
|
17309
17307
|
${renderForm(formData)}
|
|
17310
|
-
|
|
17308
|
+
|
|
17309
|
+
${isEdit && data.managed ? `
|
|
17310
|
+
<!-- Read-Only Fields Display for Managed Collections -->
|
|
17311
|
+
<div class="mt-8 pt-8 border-t border-zinc-950/5 dark:border-white/10">
|
|
17312
|
+
<div class="mb-6">
|
|
17313
|
+
<h3 class="text-base/7 font-semibold text-zinc-950 dark:text-white">Collection Fields</h3>
|
|
17314
|
+
<p class="text-sm/6 text-zinc-500 dark:text-zinc-400 mt-1">Fields defined in the configuration file (read-only)</p>
|
|
17315
|
+
</div>
|
|
17316
|
+
|
|
17317
|
+
<!-- Fields List (Read-Only) -->
|
|
17318
|
+
<div class="space-y-3">
|
|
17319
|
+
${(data.fields || []).map((field) => `
|
|
17320
|
+
<div class="bg-zinc-50 dark:bg-zinc-800/50 rounded-lg border border-zinc-950/5 dark:border-white/10 p-4">
|
|
17321
|
+
<div class="flex items-center justify-between">
|
|
17322
|
+
<div class="flex items-center gap-x-4">
|
|
17323
|
+
<div>
|
|
17324
|
+
<div class="flex items-center gap-x-2">
|
|
17325
|
+
<span class="text-sm/6 font-medium text-zinc-950 dark:text-white">${field.field_label}</span>
|
|
17326
|
+
<span class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium bg-cyan-500/10 dark:bg-cyan-400/10 text-cyan-700 dark:text-cyan-300 ring-1 ring-inset ring-cyan-500/20 dark:ring-cyan-400/20">
|
|
17327
|
+
${field.field_type}
|
|
17328
|
+
</span>
|
|
17329
|
+
${field.is_required ? `
|
|
17330
|
+
<span class="inline-flex items-center rounded-md px-2 py-1 text-xs font-medium bg-rose-500/10 dark:bg-rose-400/10 text-rose-700 dark:text-rose-300 ring-1 ring-inset ring-rose-500/20 dark:ring-rose-400/20">
|
|
17331
|
+
Required
|
|
17332
|
+
</span>
|
|
17333
|
+
` : ""}
|
|
17334
|
+
</div>
|
|
17335
|
+
<div class="text-xs text-zinc-500 dark:text-zinc-400 mt-1">
|
|
17336
|
+
<code class="px-1.5 py-0.5 rounded bg-zinc-100 dark:bg-zinc-800 font-mono">${field.field_name}</code>
|
|
17337
|
+
</div>
|
|
17338
|
+
</div>
|
|
17339
|
+
</div>
|
|
17340
|
+
</div>
|
|
17341
|
+
</div>
|
|
17342
|
+
`).join("")}
|
|
17343
|
+
|
|
17344
|
+
${(data.fields || []).length === 0 ? `
|
|
17345
|
+
<div class="text-center py-12 text-zinc-500 dark:text-zinc-400">
|
|
17346
|
+
<svg class="mx-auto h-12 w-12 text-zinc-400 dark:text-zinc-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
|
|
17347
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z"/>
|
|
17348
|
+
</svg>
|
|
17349
|
+
<p class="mt-4 text-base/7 font-semibold text-zinc-950 dark:text-white">No fields defined</p>
|
|
17350
|
+
<p class="mt-2 text-sm/6">Add fields to your collection configuration file to see them here.</p>
|
|
17351
|
+
</div>
|
|
17352
|
+
` : ""}
|
|
17353
|
+
</div>
|
|
17354
|
+
</div>
|
|
17355
|
+
` : ""}
|
|
17356
|
+
|
|
17311
17357
|
${isEdit && !data.managed ? `
|
|
17312
17358
|
<!-- Fields Management Section -->
|
|
17313
17359
|
<div class="mt-8 pt-8 border-t border-zinc-950/5 dark:border-white/10">
|
|
@@ -17866,7 +17912,7 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
17866
17912
|
let results;
|
|
17867
17913
|
if (search) {
|
|
17868
17914
|
stmt = db.prepare(`
|
|
17869
|
-
SELECT id, name, display_name, description, created_at, managed
|
|
17915
|
+
SELECT id, name, display_name, description, created_at, managed, schema
|
|
17870
17916
|
FROM collections
|
|
17871
17917
|
WHERE is_active = 1
|
|
17872
17918
|
AND (name LIKE ? OR display_name LIKE ? OR description LIKE ?)
|
|
@@ -17876,7 +17922,7 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
17876
17922
|
const queryResults = await stmt.bind(searchParam, searchParam, searchParam).all();
|
|
17877
17923
|
results = queryResults.results;
|
|
17878
17924
|
} else {
|
|
17879
|
-
stmt = db.prepare("SELECT id, name, display_name, description, created_at, managed FROM collections WHERE is_active = 1 ORDER BY created_at DESC");
|
|
17925
|
+
stmt = db.prepare("SELECT id, name, display_name, description, created_at, managed, schema FROM collections WHERE is_active = 1 ORDER BY created_at DESC");
|
|
17880
17926
|
const queryResults = await stmt.all();
|
|
17881
17927
|
results = queryResults.results;
|
|
17882
17928
|
}
|
|
@@ -17884,6 +17930,19 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
17884
17930
|
const { results: fieldCountResults } = await fieldCountStmt.all();
|
|
17885
17931
|
const fieldCounts = new Map((fieldCountResults || []).map((row) => [String(row.collection_id), Number(row.count)]));
|
|
17886
17932
|
const collections = (results || []).filter((row) => row && row.id).map((row) => {
|
|
17933
|
+
let fieldCount = 0;
|
|
17934
|
+
if (row.schema) {
|
|
17935
|
+
try {
|
|
17936
|
+
const schema = typeof row.schema === "string" ? JSON.parse(row.schema) : row.schema;
|
|
17937
|
+
if (schema && schema.properties) {
|
|
17938
|
+
fieldCount = Object.keys(schema.properties).length;
|
|
17939
|
+
}
|
|
17940
|
+
} catch (e) {
|
|
17941
|
+
fieldCount = fieldCounts.get(String(row.id)) || 0;
|
|
17942
|
+
}
|
|
17943
|
+
} else {
|
|
17944
|
+
fieldCount = fieldCounts.get(String(row.id)) || 0;
|
|
17945
|
+
}
|
|
17887
17946
|
return {
|
|
17888
17947
|
id: String(row.id || ""),
|
|
17889
17948
|
name: String(row.name || ""),
|
|
@@ -17891,7 +17950,7 @@ adminCollectionsRoutes.get("/", async (c) => {
|
|
|
17891
17950
|
description: row.description ? String(row.description) : void 0,
|
|
17892
17951
|
created_at: Number(row.created_at || 0),
|
|
17893
17952
|
formattedDate: row.created_at ? new Date(Number(row.created_at)).toLocaleDateString() : "Unknown",
|
|
17894
|
-
field_count:
|
|
17953
|
+
field_count: fieldCount,
|
|
17895
17954
|
managed: row.managed === 1
|
|
17896
17955
|
};
|
|
17897
17956
|
});
|
|
@@ -18065,22 +18124,45 @@ adminCollectionsRoutes.get("/:id", async (c) => {
|
|
|
18065
18124
|
};
|
|
18066
18125
|
return c.html(renderCollectionFormPage(formData2));
|
|
18067
18126
|
}
|
|
18068
|
-
|
|
18069
|
-
|
|
18070
|
-
|
|
18071
|
-
|
|
18072
|
-
|
|
18073
|
-
|
|
18074
|
-
|
|
18075
|
-
|
|
18076
|
-
|
|
18077
|
-
|
|
18078
|
-
|
|
18079
|
-
|
|
18080
|
-
|
|
18081
|
-
|
|
18082
|
-
|
|
18083
|
-
|
|
18127
|
+
let fields = [];
|
|
18128
|
+
if (collection.schema) {
|
|
18129
|
+
try {
|
|
18130
|
+
const schema = typeof collection.schema === "string" ? JSON.parse(collection.schema) : collection.schema;
|
|
18131
|
+
if (schema && schema.properties) {
|
|
18132
|
+
let fieldOrder = 0;
|
|
18133
|
+
fields = Object.entries(schema.properties).map(([fieldName, fieldConfig]) => ({
|
|
18134
|
+
id: `schema-${fieldName}`,
|
|
18135
|
+
field_name: fieldName,
|
|
18136
|
+
field_type: fieldConfig.type || "string",
|
|
18137
|
+
field_label: fieldConfig.title || fieldName,
|
|
18138
|
+
field_options: fieldConfig,
|
|
18139
|
+
field_order: fieldOrder++,
|
|
18140
|
+
is_required: fieldConfig.required === true || schema.required && schema.required.includes(fieldName),
|
|
18141
|
+
is_searchable: false
|
|
18142
|
+
}));
|
|
18143
|
+
}
|
|
18144
|
+
} catch (e) {
|
|
18145
|
+
console.error("Error parsing collection schema:", e);
|
|
18146
|
+
}
|
|
18147
|
+
}
|
|
18148
|
+
if (fields.length === 0) {
|
|
18149
|
+
const fieldsStmt = db.prepare(`
|
|
18150
|
+
SELECT * FROM content_fields
|
|
18151
|
+
WHERE collection_id = ?
|
|
18152
|
+
ORDER BY field_order ASC
|
|
18153
|
+
`);
|
|
18154
|
+
const { results: fieldsResults } = await fieldsStmt.bind(id).all();
|
|
18155
|
+
fields = (fieldsResults || []).map((row) => ({
|
|
18156
|
+
id: row.id,
|
|
18157
|
+
field_name: row.field_name,
|
|
18158
|
+
field_type: row.field_type,
|
|
18159
|
+
field_label: row.field_label,
|
|
18160
|
+
field_options: row.field_options ? JSON.parse(row.field_options) : {},
|
|
18161
|
+
field_order: row.field_order,
|
|
18162
|
+
is_required: row.is_required === 1,
|
|
18163
|
+
is_searchable: row.is_searchable === 1
|
|
18164
|
+
}));
|
|
18165
|
+
}
|
|
18084
18166
|
const formData = {
|
|
18085
18167
|
id: collection.id,
|
|
18086
18168
|
name: collection.name,
|
|
@@ -20170,5 +20252,5 @@ var ROUTES_INFO = {
|
|
|
20170
20252
|
};
|
|
20171
20253
|
|
|
20172
20254
|
export { ROUTES_INFO, adminCheckboxRoutes, adminCollectionsRoutes, adminDesignRoutes, adminLogsRoutes, adminMediaRoutes, adminPluginRoutes, adminSettingsRoutes, admin_api_default, admin_code_examples_default, admin_content_default, admin_faq_default, admin_testimonials_default, api_content_crud_default, api_default, api_media_default, api_system_default, auth_default, router, userRoutes };
|
|
20173
|
-
//# sourceMappingURL=chunk-
|
|
20174
|
-
//# sourceMappingURL=chunk-
|
|
20255
|
+
//# sourceMappingURL=chunk-ABYMIXRN.js.map
|
|
20256
|
+
//# sourceMappingURL=chunk-ABYMIXRN.js.map
|