@orion-studios/payload-studio 0.6.0-beta.7 → 0.6.0-beta.70
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/admin/client.js +2076 -618
- package/dist/admin/client.mjs +2037 -590
- package/dist/admin/index.d.mts +2 -2
- package/dist/admin/index.d.ts +2 -2
- package/dist/admin/index.js +140 -17
- package/dist/admin/index.mjs +1 -1
- package/dist/admin-app/client.js +11 -4
- package/dist/admin-app/client.mjs +1 -1
- package/dist/admin-app/index.d.mts +2 -2
- package/dist/admin-app/index.d.ts +2 -2
- package/dist/admin-app/styles.css +343 -41
- package/dist/admin.css +18 -2
- package/dist/builder-v2/client.d.mts +18 -0
- package/dist/builder-v2/client.d.ts +18 -0
- package/dist/builder-v2/client.js +1662 -0
- package/dist/builder-v2/client.mjs +1537 -0
- package/dist/builder-v2/index.d.mts +237 -0
- package/dist/builder-v2/index.d.ts +237 -0
- package/dist/builder-v2/index.js +735 -0
- package/dist/builder-v2/index.mjs +685 -0
- package/dist/builder-v2/styles.css +1524 -0
- package/dist/{chunk-KPIX7OSV.mjs → chunk-2XH7X34N.mjs} +11 -4
- package/dist/{chunk-PF3EBZXF.mjs → chunk-7ZMXZRBP.mjs} +39 -3
- package/dist/{chunk-5FNTVRCR.mjs → chunk-JC3UV74N.mjs} +140 -17
- package/dist/{chunk-XKUTZ7IU.mjs → chunk-NGLIA2OE.mjs} +53 -2
- package/dist/{chunk-OTHERBGX.mjs → chunk-ZADL33R6.mjs} +1 -1
- package/dist/{index-QPDAedIX.d.ts → index-BV0vEGl6.d.ts} +4 -2
- package/dist/{index-Cv-6qnrw.d.mts → index-D5zrOdyv.d.mts} +3 -1
- package/dist/{index-52HdVLQq.d.ts → index-DAdN56fM.d.ts} +1 -1
- package/dist/{index-DyMmaRfI.d.mts → index-DLfPOqYA.d.mts} +4 -2
- package/dist/{index-Crx_MtPw.d.ts → index-Dv-Alx4h.d.ts} +3 -1
- package/dist/{index-DEQC3Dwj.d.mts → index-G_uTNffQ.d.mts} +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +231 -21
- package/dist/index.mjs +4 -4
- package/dist/nextjs/index.js +39 -3
- package/dist/nextjs/index.mjs +2 -2
- package/dist/{sitePreviewTypes-BkHCWxNW.d.mts → sitePreviewTypes-BrJwGzJj.d.mts} +1 -1
- package/dist/{sitePreviewTypes-BkHCWxNW.d.ts → sitePreviewTypes-BrJwGzJj.d.ts} +1 -1
- package/dist/studio-pages/builder.css +24 -5
- package/dist/studio-pages/client.js +574 -64
- package/dist/studio-pages/client.mjs +574 -64
- package/dist/studio-pages/index.d.mts +1 -1
- package/dist/studio-pages/index.d.ts +1 -1
- package/dist/studio-pages/index.js +91 -4
- package/dist/studio-pages/index.mjs +2 -2
- package/package.json +22 -3
package/dist/admin/client.js
CHANGED
|
@@ -749,7 +749,7 @@ var init_OrionBlocksFieldImpl = __esm({
|
|
|
749
749
|
const schemaPath = schemaPathFromProps ?? name;
|
|
750
750
|
const minRows = minRowsProp ?? (required ? 1 : 0);
|
|
751
751
|
const { setDocFieldPreferences } = (0, import_DocumentInfo.useDocumentInfo)();
|
|
752
|
-
const { addFieldRow, dispatchFields, getFields, moveFieldRow, removeFieldRow, replaceState, setModified } = (0, import_Form.useForm)();
|
|
752
|
+
const { addFieldRow, dispatchFields, getFields: getFields2, moveFieldRow, removeFieldRow, replaceState, setModified } = (0, import_Form.useForm)();
|
|
753
753
|
const { code: locale } = (0, import_Locale.useLocale)();
|
|
754
754
|
const configContext = (0, import_Config.useConfig)();
|
|
755
755
|
const config = configContext?.config ?? {};
|
|
@@ -911,7 +911,7 @@ var init_OrionBlocksFieldImpl = __esm({
|
|
|
911
911
|
(rowIndex) => {
|
|
912
912
|
const result = clipboardCopy({
|
|
913
913
|
getDataToCopy: () => reduceFormStateByPath({
|
|
914
|
-
formState:
|
|
914
|
+
formState: getFields2(),
|
|
915
915
|
path: safePath,
|
|
916
916
|
rowIndex
|
|
917
917
|
}),
|
|
@@ -929,13 +929,13 @@ var init_OrionBlocksFieldImpl = __esm({
|
|
|
929
929
|
import_sonner.toast.success(t("general:copied"));
|
|
930
930
|
}
|
|
931
931
|
},
|
|
932
|
-
[clientBlocks,
|
|
932
|
+
[clientBlocks, getFields2, safePath, t, type]
|
|
933
933
|
);
|
|
934
934
|
const pasteRow = (0, import_react10.useCallback)(
|
|
935
935
|
(rowIndex) => {
|
|
936
936
|
const result = clipboardPaste({
|
|
937
937
|
onPaste: (dataFromClipboard) => {
|
|
938
|
-
const formState =
|
|
938
|
+
const formState = getFields2();
|
|
939
939
|
const newState = mergeFormStateFromClipboard({
|
|
940
940
|
dataFromClipboard,
|
|
941
941
|
formState,
|
|
@@ -952,11 +952,11 @@ var init_OrionBlocksFieldImpl = __esm({
|
|
|
952
952
|
import_sonner.toast.error(result);
|
|
953
953
|
}
|
|
954
954
|
},
|
|
955
|
-
[clientBlocks,
|
|
955
|
+
[clientBlocks, getFields2, replaceState, safePath, setModified, t]
|
|
956
956
|
);
|
|
957
957
|
const pasteBlocks = (0, import_react10.useCallback)(
|
|
958
958
|
(dataFromClipboard) => {
|
|
959
|
-
const formState =
|
|
959
|
+
const formState = getFields2();
|
|
960
960
|
const newState = mergeFormStateFromClipboard({
|
|
961
961
|
dataFromClipboard,
|
|
962
962
|
formState,
|
|
@@ -965,7 +965,7 @@ var init_OrionBlocksFieldImpl = __esm({
|
|
|
965
965
|
replaceState(newState);
|
|
966
966
|
setModified(true);
|
|
967
967
|
},
|
|
968
|
-
[
|
|
968
|
+
[getFields2, replaceState, safePath, setModified]
|
|
969
969
|
);
|
|
970
970
|
const hasMaxRows = Boolean(maxRows && rows.length >= maxRows);
|
|
971
971
|
const fieldErrorCount = errorPaths.length;
|
|
@@ -1042,7 +1042,7 @@ var init_OrionBlocksFieldImpl = __esm({
|
|
|
1042
1042
|
className: `${baseClass}__header-action`,
|
|
1043
1043
|
disabled,
|
|
1044
1044
|
getDataToCopy: () => reduceFormStateByPath({
|
|
1045
|
-
formState:
|
|
1045
|
+
formState: getFields2(),
|
|
1046
1046
|
path: safePath
|
|
1047
1047
|
}),
|
|
1048
1048
|
onPaste: pasteBlocks,
|
|
@@ -1171,6 +1171,9 @@ __export(client_exports, {
|
|
|
1171
1171
|
AdminStudioContactFormView: () => AdminStudioContactFormView,
|
|
1172
1172
|
AdminStudioDashboard: () => AdminStudioDashboard,
|
|
1173
1173
|
AdminStudioFooterGlobalView: () => AdminStudioFooterGlobalView,
|
|
1174
|
+
AdminStudioFormDetailView: () => AdminStudioFormDetailView,
|
|
1175
|
+
AdminStudioFormSubmissionView: () => AdminStudioFormSubmissionView,
|
|
1176
|
+
AdminStudioFormUploadView: () => AdminStudioFormUploadView,
|
|
1174
1177
|
AdminStudioFormsView: () => AdminStudioFormsView,
|
|
1175
1178
|
AdminStudioGlobalsView: () => AdminStudioGlobalsView,
|
|
1176
1179
|
AdminStudioHeaderGlobalView: () => AdminStudioHeaderGlobalView,
|
|
@@ -1196,6 +1199,7 @@ __export(client_exports, {
|
|
|
1196
1199
|
StatusBadge: () => StatusBadge,
|
|
1197
1200
|
StudioBackBreadcrumb: () => StudioBackBreadcrumb,
|
|
1198
1201
|
StudioContactFormRedirect: () => StudioContactFormRedirect,
|
|
1202
|
+
StudioDocumentRedirect: () => StudioDocumentRedirect,
|
|
1199
1203
|
StudioSectionLayout: () => StudioSectionLayout,
|
|
1200
1204
|
ThemeProvider: () => ThemeProvider,
|
|
1201
1205
|
ThemeSwitcher: () => ThemeSwitcher,
|
|
@@ -1231,17 +1235,22 @@ var resolveUploadUrl = (value) => {
|
|
|
1231
1235
|
var resolveLogoUrl = (settings) => {
|
|
1232
1236
|
return resolveUploadUrl(settings.logo) || resolveUploadUrl(settings.adminLogo) || resolveUploadUrl(settings.brandLogo) || null;
|
|
1233
1237
|
};
|
|
1238
|
+
var resolveLogoOnDarkUrl = (settings) => {
|
|
1239
|
+
return resolveUploadUrl(settings.logoOnDark) || resolveUploadUrl(settings.logoDark) || resolveUploadUrl(settings.adminLogoDark) || resolveUploadUrl(settings.adminLogoOnDark) || resolveUploadUrl(settings.brandLogoDark) || null;
|
|
1240
|
+
};
|
|
1234
1241
|
var cachedBranding = null;
|
|
1235
|
-
function useSiteBranding(defaultName, defaultLogoUrl) {
|
|
1242
|
+
function useSiteBranding(defaultName, defaultLogoUrl, defaultLogoOnDarkUrl) {
|
|
1236
1243
|
const [branding, setBranding] = (0, import_react.useState)(() => {
|
|
1237
1244
|
if (cachedBranding) {
|
|
1238
1245
|
return {
|
|
1239
1246
|
logoUrl: cachedBranding.logoUrl || defaultLogoUrl || null,
|
|
1247
|
+
logoOnDarkUrl: cachedBranding.logoOnDarkUrl || defaultLogoOnDarkUrl || null,
|
|
1240
1248
|
siteName: cachedBranding.siteName || defaultName || null
|
|
1241
1249
|
};
|
|
1242
1250
|
}
|
|
1243
1251
|
return {
|
|
1244
1252
|
logoUrl: defaultLogoUrl || null,
|
|
1253
|
+
logoOnDarkUrl: defaultLogoOnDarkUrl || null,
|
|
1245
1254
|
siteName: defaultName || null
|
|
1246
1255
|
};
|
|
1247
1256
|
});
|
|
@@ -1258,9 +1267,11 @@ function useSiteBranding(defaultName, defaultLogoUrl) {
|
|
|
1258
1267
|
if (!record) return;
|
|
1259
1268
|
const siteName = pickString(record.siteName);
|
|
1260
1269
|
const logoUrl = resolveLogoUrl(record);
|
|
1261
|
-
|
|
1270
|
+
const logoOnDarkUrl = resolveLogoOnDarkUrl(record);
|
|
1271
|
+
cachedBranding = { logoOnDarkUrl, logoUrl, siteName };
|
|
1262
1272
|
if (!cancelled) {
|
|
1263
1273
|
setBranding({
|
|
1274
|
+
logoOnDarkUrl: logoOnDarkUrl || defaultLogoOnDarkUrl || null,
|
|
1264
1275
|
logoUrl: logoUrl || defaultLogoUrl || null,
|
|
1265
1276
|
siteName: siteName || defaultName || null
|
|
1266
1277
|
});
|
|
@@ -1272,16 +1283,20 @@ function useSiteBranding(defaultName, defaultLogoUrl) {
|
|
|
1272
1283
|
return () => {
|
|
1273
1284
|
cancelled = true;
|
|
1274
1285
|
};
|
|
1275
|
-
}, [defaultLogoUrl, defaultName]);
|
|
1286
|
+
}, [defaultLogoOnDarkUrl, defaultLogoUrl, defaultName]);
|
|
1276
1287
|
return branding;
|
|
1277
1288
|
}
|
|
1278
1289
|
|
|
1279
1290
|
// src/admin/components/Logo.tsx
|
|
1280
1291
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
1281
|
-
function Logo({ brandName = "Orion Studio", logoUrl } = {}) {
|
|
1282
|
-
const branding = useSiteBranding(brandName, logoUrl);
|
|
1292
|
+
function Logo({ brandName = "Orion Studio", logoOnDarkUrl, logoUrl } = {}) {
|
|
1293
|
+
const branding = useSiteBranding(brandName, logoUrl, logoOnDarkUrl);
|
|
1283
1294
|
const resolvedName = branding.siteName || brandName;
|
|
1284
1295
|
const resolvedLogo = branding.logoUrl || logoUrl || null;
|
|
1296
|
+
const resolvedLogoOnDark = branding.logoOnDarkUrl || logoOnDarkUrl || resolvedLogo || "";
|
|
1297
|
+
const hasDarkLogoVariant = Boolean(
|
|
1298
|
+
resolvedLogo && resolvedLogoOnDark.trim().length > 0 && resolvedLogoOnDark !== resolvedLogo
|
|
1299
|
+
);
|
|
1285
1300
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1286
1301
|
"div",
|
|
1287
1302
|
{
|
|
@@ -1300,8 +1315,6 @@ function Logo({ brandName = "Orion Studio", logoUrl } = {}) {
|
|
|
1300
1315
|
className: "orion-admin-logo-mark",
|
|
1301
1316
|
style: {
|
|
1302
1317
|
alignItems: "center",
|
|
1303
|
-
background: "var(--orion-cms-logo-bg, var(--admin-accent, #3b82f6))",
|
|
1304
|
-
borderRadius: "var(--orion-cms-logo-radius, var(--admin-radius-md, 8px))",
|
|
1305
1318
|
display: "flex",
|
|
1306
1319
|
flexShrink: 0,
|
|
1307
1320
|
height: 32,
|
|
@@ -1309,14 +1322,25 @@ function Logo({ brandName = "Orion Studio", logoUrl } = {}) {
|
|
|
1309
1322
|
overflow: "hidden",
|
|
1310
1323
|
width: 32
|
|
1311
1324
|
},
|
|
1312
|
-
children: resolvedLogo ? /* @__PURE__ */ (0, import_jsx_runtime.
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1325
|
+
children: resolvedLogo ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1326
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1327
|
+
"img",
|
|
1328
|
+
{
|
|
1329
|
+
alt: `${resolvedName} logo`,
|
|
1330
|
+
className: `orion-admin-logo-image orion-admin-logo-image--default${hasDarkLogoVariant ? "" : " is-only-logo"}`,
|
|
1331
|
+
src: resolvedLogo
|
|
1332
|
+
}
|
|
1333
|
+
),
|
|
1334
|
+
hasDarkLogoVariant ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1335
|
+
"img",
|
|
1336
|
+
{
|
|
1337
|
+
alt: "",
|
|
1338
|
+
"aria-hidden": "true",
|
|
1339
|
+
className: "orion-admin-logo-image orion-admin-logo-image--dark",
|
|
1340
|
+
src: resolvedLogoOnDark
|
|
1341
|
+
}
|
|
1342
|
+
) : null
|
|
1343
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1320
1344
|
"svg",
|
|
1321
1345
|
{
|
|
1322
1346
|
fill: "none",
|
|
@@ -1424,27 +1448,13 @@ function AdminLoginIntro({ brandName = "Orion Studio", logoUrl } = {}) {
|
|
|
1424
1448
|
const branding = useSiteBranding(brandName, logoUrl);
|
|
1425
1449
|
const resolvedName = branding.siteName || brandName;
|
|
1426
1450
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "orion-admin-login-intro", children: [
|
|
1427
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "orion-admin-login-eyebrow", children: "
|
|
1451
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "orion-admin-login-eyebrow", children: "Private Admin" }),
|
|
1428
1452
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("h1", { children: [
|
|
1429
|
-
"Manage ",
|
|
1430
1453
|
resolvedName,
|
|
1431
|
-
"
|
|
1454
|
+
" admin"
|
|
1432
1455
|
] }),
|
|
1433
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: "Sign in to update
|
|
1434
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
1435
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { className: "orion-admin-login-note", children: [
|
|
1436
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: "Branded workspace" }),
|
|
1437
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "The admin mirrors the live site instead of dropping editors into a generic CMS shell." })
|
|
1438
|
-
] }),
|
|
1439
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { className: "orion-admin-login-note", children: [
|
|
1440
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: "One editorial flow" }),
|
|
1441
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Pages, globals, media, forms, and analytics stay in one place once you are inside." })
|
|
1442
|
-
] }),
|
|
1443
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { className: "orion-admin-login-note", children: [
|
|
1444
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: "Protected entry" }),
|
|
1445
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Only authorized administrators and editors can access this workspace." })
|
|
1446
|
-
] })
|
|
1447
|
-
] })
|
|
1456
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: "Sign in to update pages, review forms, manage media, and adjust site settings." }),
|
|
1457
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "orion-admin-login-caption", children: "For owners and authorized team members." })
|
|
1448
1458
|
] });
|
|
1449
1459
|
}
|
|
1450
1460
|
|
|
@@ -2568,7 +2578,7 @@ var navItemIsActive = (pathname, item) => {
|
|
|
2568
2578
|
};
|
|
2569
2579
|
|
|
2570
2580
|
// src/shared/studioSections.ts
|
|
2571
|
-
var studioRoles = /* @__PURE__ */ new Set(["admin", "editor", "client"]);
|
|
2581
|
+
var studioRoles = /* @__PURE__ */ new Set(["admin", "developer", "editor", "client"]);
|
|
2572
2582
|
var studioIcons = new Set(adminNavIcons);
|
|
2573
2583
|
var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2574
2584
|
var isAbsoluteExternalURL2 = (value) => /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(value) || value.startsWith("//");
|
|
@@ -2766,7 +2776,7 @@ var buildStudioNavItems = (props, adminBasePath) => {
|
|
|
2766
2776
|
icon: "tools",
|
|
2767
2777
|
label: "Admin Tools",
|
|
2768
2778
|
matchPrefixes: [toolsPath, resolveAdminPath(adminBasePath, "/collections/users")],
|
|
2769
|
-
roles: ["admin"]
|
|
2779
|
+
roles: ["admin", "developer"]
|
|
2770
2780
|
};
|
|
2771
2781
|
const extensionItems = sections.map((section) => ({
|
|
2772
2782
|
href: resolveAdminPath(adminBasePath, section.href),
|
|
@@ -3049,14 +3059,21 @@ function AdminShellClient({
|
|
|
3049
3059
|
onLogout,
|
|
3050
3060
|
storageKey = "orion-admin-shell-collapsed"
|
|
3051
3061
|
}) {
|
|
3052
|
-
const [collapsed, setCollapsed] = (0, import_react14.useState)(
|
|
3062
|
+
const [collapsed, setCollapsed] = (0, import_react14.useState)(() => {
|
|
3063
|
+
if (typeof window === "undefined") {
|
|
3064
|
+
return true;
|
|
3065
|
+
}
|
|
3066
|
+
try {
|
|
3067
|
+
return window.localStorage.getItem(storageKey) === "1";
|
|
3068
|
+
} catch {
|
|
3069
|
+
return false;
|
|
3070
|
+
}
|
|
3071
|
+
});
|
|
3053
3072
|
const [loggingOut, setLoggingOut] = (0, import_react14.useState)(false);
|
|
3054
3073
|
(0, import_react14.useEffect)(() => {
|
|
3055
3074
|
try {
|
|
3056
3075
|
const stored = window.localStorage.getItem(storageKey);
|
|
3057
|
-
|
|
3058
|
-
setCollapsed(true);
|
|
3059
|
-
}
|
|
3076
|
+
setCollapsed(stored === "1");
|
|
3060
3077
|
} catch {
|
|
3061
3078
|
}
|
|
3062
3079
|
}, [storageKey]);
|
|
@@ -3207,9 +3224,9 @@ var import_react16 = require("react");
|
|
|
3207
3224
|
var import_link = __toESM(require("next/link"));
|
|
3208
3225
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
3209
3226
|
var SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
3210
|
-
var isRole = (value) => value === "admin" || value === "
|
|
3211
|
-
var canReviewForms = (role) => role === "admin" || role === "editor";
|
|
3212
|
-
var canCreatePages = (role) => role === "admin" || role === "editor";
|
|
3227
|
+
var isRole = (value) => value === "admin" || value === "client" || value === "developer" || value === "editor";
|
|
3228
|
+
var canReviewForms = (role) => role === "admin" || role === "developer" || role === "editor";
|
|
3229
|
+
var canCreatePages = (role) => role === "admin" || role === "developer" || role === "editor";
|
|
3213
3230
|
var canAccess = (role, roles) => {
|
|
3214
3231
|
if (!roles || roles.length === 0) {
|
|
3215
3232
|
return true;
|
|
@@ -3685,7 +3702,7 @@ function AdminStudioDashboardClient({
|
|
|
3685
3702
|
label: "Manage Media",
|
|
3686
3703
|
tone: "ghost"
|
|
3687
3704
|
});
|
|
3688
|
-
if (role === "admin") {
|
|
3705
|
+
if (role === "admin" || role === "developer") {
|
|
3689
3706
|
actions.push({
|
|
3690
3707
|
description: "Manage users, roles, and fallback tools.",
|
|
3691
3708
|
href: toolsPath,
|
|
@@ -3964,7 +3981,7 @@ var buildSectionLinks = (adminBasePath, sections, formsEnabled, globalsBasePath)
|
|
|
3964
3981
|
href: resolveAdminPath2(adminBasePath, "/tools"),
|
|
3965
3982
|
id: "admin-tools",
|
|
3966
3983
|
label: "Admin Tools",
|
|
3967
|
-
roles: ["admin"]
|
|
3984
|
+
roles: ["admin", "developer"]
|
|
3968
3985
|
}
|
|
3969
3986
|
];
|
|
3970
3987
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -4030,15 +4047,16 @@ function AdminStudioDashboard(rawProps) {
|
|
|
4030
4047
|
}
|
|
4031
4048
|
|
|
4032
4049
|
// src/admin/components/studio/AdminStudioPagesListView.tsx
|
|
4033
|
-
var
|
|
4050
|
+
var import_react19 = require("react");
|
|
4034
4051
|
var import_link2 = __toESM(require("next/link"));
|
|
4052
|
+
var import_navigation3 = require("next/navigation");
|
|
4053
|
+
var import_ui7 = require("@payloadcms/ui");
|
|
4054
|
+
|
|
4055
|
+
// src/admin/components/studio/AdminStudioNewPageView.tsx
|
|
4056
|
+
var import_react17 = require("react");
|
|
4035
4057
|
var import_ui5 = require("@payloadcms/ui");
|
|
4036
4058
|
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
4037
|
-
var
|
|
4038
|
-
if (!user || typeof user !== "object") return false;
|
|
4039
|
-
const role = user.role;
|
|
4040
|
-
return typeof role === "string" && role === "admin";
|
|
4041
|
-
};
|
|
4059
|
+
var pageTemplates = ["standard", "landing", "services", "contact"];
|
|
4042
4060
|
var getPropString3 = (props, key, fallback) => {
|
|
4043
4061
|
if (!props || typeof props !== "object") return fallback;
|
|
4044
4062
|
const direct = props[key];
|
|
@@ -4050,83 +4068,107 @@ var getPropString3 = (props, key, fallback) => {
|
|
|
4050
4068
|
}
|
|
4051
4069
|
return fallback;
|
|
4052
4070
|
};
|
|
4053
|
-
|
|
4071
|
+
var canManagePages = (user) => {
|
|
4072
|
+
if (!user || typeof user !== "object") return false;
|
|
4073
|
+
const role = user.role;
|
|
4074
|
+
return role === "admin" || role === "developer" || role === "editor";
|
|
4075
|
+
};
|
|
4076
|
+
var slugify = (value) => value.toLowerCase().trim().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-");
|
|
4077
|
+
function AdminStudioNewPageView(props) {
|
|
4054
4078
|
const { user } = (0, import_ui5.useAuth)();
|
|
4055
|
-
const pagesCollectionSlug = getPropString3(props, "pagesCollectionSlug", "pages");
|
|
4056
4079
|
const adminBasePath = useAdminBasePath();
|
|
4057
|
-
const
|
|
4058
|
-
const [
|
|
4080
|
+
const pagesCollectionSlug = getPropString3(props, "pagesCollectionSlug", "pages");
|
|
4081
|
+
const [submitting, setSubmitting] = (0, import_react17.useState)(false);
|
|
4059
4082
|
const [error, setError] = (0, import_react17.useState)(null);
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
try {
|
|
4076
|
-
const res = await fetch(apiURL, { credentials: "include" });
|
|
4077
|
-
if (!res.ok) {
|
|
4078
|
-
const body = await res.text();
|
|
4079
|
-
throw new Error(body || "Failed to fetch pages");
|
|
4080
|
-
}
|
|
4081
|
-
const data = await res.json();
|
|
4082
|
-
if (!cancelled) {
|
|
4083
|
-
setDocs(Array.isArray(data.docs) ? data.docs : []);
|
|
4084
|
-
}
|
|
4085
|
-
} catch (err) {
|
|
4086
|
-
if (!cancelled) {
|
|
4087
|
-
setError(err instanceof Error ? err.message : "Failed to fetch pages");
|
|
4088
|
-
}
|
|
4089
|
-
} finally {
|
|
4090
|
-
if (!cancelled) {
|
|
4091
|
-
setLoading(false);
|
|
4092
|
-
}
|
|
4083
|
+
if (!canManagePages(user)) {
|
|
4084
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4085
|
+
AdminPage,
|
|
4086
|
+
{
|
|
4087
|
+
breadcrumbs: [
|
|
4088
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
4089
|
+
{ label: "Pages", href: resolveAdminPath(adminBasePath, "/pages") },
|
|
4090
|
+
{ label: "New Page" }
|
|
4091
|
+
],
|
|
4092
|
+
description: "You do not have access to create pages.",
|
|
4093
|
+
title: "New Page",
|
|
4094
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "orion-admin-card", children: [
|
|
4095
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("strong", { children: "Access denied" }),
|
|
4096
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { children: "This section is restricted to administrator, developer, and editor accounts." })
|
|
4097
|
+
] })
|
|
4093
4098
|
}
|
|
4094
|
-
};
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4099
|
+
) });
|
|
4100
|
+
}
|
|
4101
|
+
const createPage = async (event) => {
|
|
4102
|
+
event.preventDefault();
|
|
4103
|
+
setSubmitting(true);
|
|
4104
|
+
setError(null);
|
|
4105
|
+
try {
|
|
4106
|
+
const formData = new FormData(event.currentTarget);
|
|
4107
|
+
const titleValue = String(formData.get("title") || "").trim();
|
|
4108
|
+
const slugValue = String(formData.get("slug") || "").trim();
|
|
4109
|
+
const templateValue = String(formData.get("template") || "standard").trim();
|
|
4110
|
+
const template = pageTemplates.includes(templateValue) ? templateValue : "standard";
|
|
4111
|
+
const title = titleValue || "Untitled Page";
|
|
4112
|
+
const slug = slugValue || slugify(title) || "untitled-page";
|
|
4113
|
+
const response = await fetch(`/api/${pagesCollectionSlug}`, {
|
|
4114
|
+
body: JSON.stringify({
|
|
4115
|
+
_status: "draft",
|
|
4116
|
+
slug,
|
|
4117
|
+
template,
|
|
4118
|
+
title
|
|
4119
|
+
}),
|
|
4120
|
+
credentials: "include",
|
|
4121
|
+
headers: {
|
|
4122
|
+
"Content-Type": "application/json"
|
|
4123
|
+
},
|
|
4124
|
+
method: "POST"
|
|
4125
|
+
});
|
|
4126
|
+
if (!response.ok) {
|
|
4127
|
+
throw new Error(`Failed to create page (${response.status}).`);
|
|
4128
|
+
}
|
|
4129
|
+
const payload = await response.json();
|
|
4130
|
+
const id = typeof payload.id === "string" || typeof payload.id === "number" ? String(payload.id) : "";
|
|
4131
|
+
if (!id) {
|
|
4132
|
+
throw new Error("Page created but no document ID was returned.");
|
|
4133
|
+
}
|
|
4134
|
+
window.location.assign(resolveAdminPath(adminBasePath, `/pages/${id}`));
|
|
4135
|
+
} catch (createError) {
|
|
4136
|
+
setError(createError instanceof Error ? createError.message : "Failed to create page.");
|
|
4137
|
+
} finally {
|
|
4138
|
+
setSubmitting(false);
|
|
4139
|
+
}
|
|
4140
|
+
};
|
|
4141
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4101
4142
|
AdminPage,
|
|
4102
4143
|
{
|
|
4103
|
-
actions: isAdmin(user) ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_link2.default, { className: "orion-admin-action-button", href: newPagePath, children: "New Page" }) : null,
|
|
4104
4144
|
breadcrumbs: [
|
|
4105
4145
|
{ label: "Dashboard", href: adminBasePath },
|
|
4106
|
-
{ label: "Pages" }
|
|
4146
|
+
{ label: "Pages", href: resolveAdminPath(adminBasePath, "/pages") },
|
|
4147
|
+
{ label: "New Page" }
|
|
4107
4148
|
],
|
|
4108
|
-
description: "
|
|
4109
|
-
title: "
|
|
4110
|
-
children: [
|
|
4111
|
-
loading ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
|
|
4149
|
+
description: "Create a new page and open it in the custom editor.",
|
|
4150
|
+
title: "New Page",
|
|
4151
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("form", { className: "orion-admin-form", onSubmit: createPage, children: [
|
|
4112
4152
|
error ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "orion-admin-error", children: error }) : null,
|
|
4113
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4153
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { children: [
|
|
4154
|
+
"Title",
|
|
4155
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { name: "title", placeholder: "Services", required: true, type: "text" })
|
|
4156
|
+
] }),
|
|
4157
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { children: [
|
|
4158
|
+
"Slug",
|
|
4159
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("input", { name: "slug", placeholder: "services", type: "text" })
|
|
4160
|
+
] }),
|
|
4161
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("label", { children: [
|
|
4162
|
+
"Template",
|
|
4163
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("select", { defaultValue: "standard", name: "template", children: [
|
|
4164
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: "standard", children: "Standard" }),
|
|
4165
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: "landing", children: "Landing" }),
|
|
4166
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: "contact", children: "Contact" }),
|
|
4167
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("option", { value: "services", children: "Services" })
|
|
4168
|
+
] })
|
|
4169
|
+
] }),
|
|
4170
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { disabled: submitting, type: "submit", children: submitting ? "Creating..." : "Create Page" })
|
|
4171
|
+
] })
|
|
4130
4172
|
}
|
|
4131
4173
|
) });
|
|
4132
4174
|
}
|
|
@@ -4135,16 +4177,6 @@ function AdminStudioPagesListView(props) {
|
|
|
4135
4177
|
var import_react18 = require("react");
|
|
4136
4178
|
var import_ui6 = require("@payloadcms/ui");
|
|
4137
4179
|
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
4138
|
-
var isAdmin2 = (user) => {
|
|
4139
|
-
if (!user || typeof user !== "object") return false;
|
|
4140
|
-
const role = user.role;
|
|
4141
|
-
return typeof role === "string" && role === "admin";
|
|
4142
|
-
};
|
|
4143
|
-
var isEditor = (user) => {
|
|
4144
|
-
if (!user || typeof user !== "object") return false;
|
|
4145
|
-
const role = user.role;
|
|
4146
|
-
return typeof role === "string" && role === "editor";
|
|
4147
|
-
};
|
|
4148
4180
|
var getPropString4 = (props, key, fallback) => {
|
|
4149
4181
|
if (!props || typeof props !== "object") return fallback;
|
|
4150
4182
|
const direct = props[key];
|
|
@@ -4172,14 +4204,8 @@ var getPageIDFromPathname = (pathname) => {
|
|
|
4172
4204
|
return pagePart ? decodeURIComponent(pagePart) : null;
|
|
4173
4205
|
};
|
|
4174
4206
|
function AdminStudioPageEditView(props) {
|
|
4175
|
-
const { user } = (0, import_ui6.useAuth)();
|
|
4176
4207
|
const adminBasePath = useAdminBasePath();
|
|
4177
4208
|
const iframeRef = (0, import_react18.useRef)(null);
|
|
4178
|
-
const [saving, setSaving] = (0, import_react18.useState)(null);
|
|
4179
|
-
const [dirty, setDirty] = (0, import_react18.useState)(false);
|
|
4180
|
-
const [hasUnpublishedChanges, setHasUnpublishedChanges] = (0, import_react18.useState)(false);
|
|
4181
|
-
const [canUndo, setCanUndo] = (0, import_react18.useState)(false);
|
|
4182
|
-
const [canRedo, setCanRedo] = (0, import_react18.useState)(false);
|
|
4183
4209
|
const builderBasePath = getPropString4(props, "builderBasePath", "/builder");
|
|
4184
4210
|
const pagesPath = resolveAdminPath(adminBasePath, "/pages");
|
|
4185
4211
|
const pageIDFromParams = (0, import_react18.useMemo)(() => getParam(props.params, "id"), [props.params]);
|
|
@@ -4196,96 +4222,6 @@ function AdminStudioPageEditView(props) {
|
|
|
4196
4222
|
}
|
|
4197
4223
|
setDidResolvePathFallback(true);
|
|
4198
4224
|
}, [pageIDFromParams]);
|
|
4199
|
-
const canPublish = isAdmin2(user) || isEditor(user);
|
|
4200
|
-
const refreshUnpublishedState = async (id) => {
|
|
4201
|
-
try {
|
|
4202
|
-
const response = await fetch(
|
|
4203
|
-
`/api/pages/versions?depth=0&limit=25&sort=-updatedAt&where[parent][equals]=${encodeURIComponent(id)}`,
|
|
4204
|
-
{
|
|
4205
|
-
credentials: "include"
|
|
4206
|
-
}
|
|
4207
|
-
);
|
|
4208
|
-
if (!response.ok) {
|
|
4209
|
-
return;
|
|
4210
|
-
}
|
|
4211
|
-
const payload = await response.json();
|
|
4212
|
-
const docs = Array.isArray(payload.docs) ? payload.docs : [];
|
|
4213
|
-
let latestDraft = 0;
|
|
4214
|
-
let latestPublished = 0;
|
|
4215
|
-
docs.forEach((doc) => {
|
|
4216
|
-
const status = doc.version?._status;
|
|
4217
|
-
const millis = typeof doc.updatedAt === "string" ? Date.parse(doc.updatedAt) : Number.NaN;
|
|
4218
|
-
if (!Number.isFinite(millis)) {
|
|
4219
|
-
return;
|
|
4220
|
-
}
|
|
4221
|
-
if (status === "draft") {
|
|
4222
|
-
latestDraft = Math.max(latestDraft, millis);
|
|
4223
|
-
}
|
|
4224
|
-
if (status === "published") {
|
|
4225
|
-
latestPublished = Math.max(latestPublished, millis);
|
|
4226
|
-
}
|
|
4227
|
-
});
|
|
4228
|
-
setHasUnpublishedChanges(latestDraft > 0 && latestDraft >= latestPublished);
|
|
4229
|
-
} catch {
|
|
4230
|
-
}
|
|
4231
|
-
};
|
|
4232
|
-
(0, import_react18.useEffect)(() => {
|
|
4233
|
-
if (!pageID) {
|
|
4234
|
-
return;
|
|
4235
|
-
}
|
|
4236
|
-
void refreshUnpublishedState(pageID);
|
|
4237
|
-
}, [pageID]);
|
|
4238
|
-
const requestSave = (status) => {
|
|
4239
|
-
const iframe = iframeRef.current;
|
|
4240
|
-
if (!iframe?.contentWindow) {
|
|
4241
|
-
import_ui6.toast.error("Editor is not ready yet. Please try again.");
|
|
4242
|
-
return;
|
|
4243
|
-
}
|
|
4244
|
-
setSaving(status);
|
|
4245
|
-
iframe.contentWindow.postMessage({ source: "payload-visual-builder-parent", type: "save", status }, "*");
|
|
4246
|
-
};
|
|
4247
|
-
const requestHistoryAction = (type) => {
|
|
4248
|
-
const iframe = iframeRef.current;
|
|
4249
|
-
if (!iframe?.contentWindow) {
|
|
4250
|
-
import_ui6.toast.error("Editor is not ready yet. Please try again.");
|
|
4251
|
-
return;
|
|
4252
|
-
}
|
|
4253
|
-
iframe.contentWindow.postMessage({ source: "payload-visual-builder-parent", type }, "*");
|
|
4254
|
-
};
|
|
4255
|
-
(0, import_react18.useEffect)(() => {
|
|
4256
|
-
const onMessage = (event) => {
|
|
4257
|
-
const data = event.data;
|
|
4258
|
-
if (!data || data.source !== "payload-visual-builder-child" || typeof data.type !== "string") {
|
|
4259
|
-
return;
|
|
4260
|
-
}
|
|
4261
|
-
if (data.type === "dirty-state") {
|
|
4262
|
-
setDirty(Boolean(data.dirty));
|
|
4263
|
-
return;
|
|
4264
|
-
}
|
|
4265
|
-
if (data.type === "history-state") {
|
|
4266
|
-
setCanUndo(Boolean(data.canUndo));
|
|
4267
|
-
setCanRedo(Boolean(data.canRedo));
|
|
4268
|
-
return;
|
|
4269
|
-
}
|
|
4270
|
-
if (data.type === "save-result") {
|
|
4271
|
-
setSaving(null);
|
|
4272
|
-
if (data.ok) {
|
|
4273
|
-
if (data.status === "draft") {
|
|
4274
|
-
setHasUnpublishedChanges(true);
|
|
4275
|
-
} else if (data.status === "published") {
|
|
4276
|
-
setHasUnpublishedChanges(false);
|
|
4277
|
-
} else if (pageID) {
|
|
4278
|
-
void refreshUnpublishedState(pageID);
|
|
4279
|
-
}
|
|
4280
|
-
import_ui6.toast.success(typeof data.message === "string" ? data.message : "Saved.");
|
|
4281
|
-
} else {
|
|
4282
|
-
import_ui6.toast.error(typeof data.message === "string" ? data.message : "Save failed.");
|
|
4283
|
-
}
|
|
4284
|
-
}
|
|
4285
|
-
};
|
|
4286
|
-
window.addEventListener("message", onMessage);
|
|
4287
|
-
return () => window.removeEventListener("message", onMessage);
|
|
4288
|
-
}, []);
|
|
4289
4225
|
if (!pageID && !didResolvePathFallback) {
|
|
4290
4226
|
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
4291
4227
|
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
@@ -4326,155 +4262,25 @@ function AdminStudioPageEditView(props) {
|
|
|
4326
4262
|
]
|
|
4327
4263
|
}
|
|
4328
4264
|
),
|
|
4329
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
gap: "0.6rem",
|
|
4339
|
-
justifyContent: "space-between",
|
|
4340
|
-
padding: "0.65rem 0.9rem",
|
|
4341
|
-
position: "sticky",
|
|
4342
|
-
top: 0,
|
|
4343
|
-
zIndex: 20
|
|
4344
|
-
},
|
|
4345
|
-
children: [
|
|
4346
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { minWidth: 0 }, children: [
|
|
4347
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { fontWeight: 900 }, children: "Page Editor" }),
|
|
4348
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
4349
|
-
"div",
|
|
4350
|
-
{
|
|
4351
|
-
style: {
|
|
4352
|
-
color: "var(--theme-elevation-600)",
|
|
4353
|
-
fontSize: "0.85rem",
|
|
4354
|
-
overflow: "hidden",
|
|
4355
|
-
textOverflow: "ellipsis"
|
|
4356
|
-
},
|
|
4357
|
-
children: [
|
|
4358
|
-
"Editing: ",
|
|
4359
|
-
pageID
|
|
4360
|
-
]
|
|
4361
|
-
}
|
|
4362
|
-
)
|
|
4363
|
-
] }),
|
|
4364
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { style: { alignItems: "center", display: "flex", gap: "0.5rem" }, children: [
|
|
4365
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { color: dirty ? "var(--theme-elevation-900)" : "var(--theme-elevation-600)", fontSize: "0.85rem", fontWeight: 700 }, children: dirty ? "Unsaved changes" : "All changes saved" }),
|
|
4366
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4367
|
-
"div",
|
|
4368
|
-
{
|
|
4369
|
-
style: {
|
|
4370
|
-
background: hasUnpublishedChanges ? "#fff3cd" : "var(--theme-success-50)",
|
|
4371
|
-
border: `1px solid ${hasUnpublishedChanges ? "#f0c36d" : "var(--theme-success-300)"}`,
|
|
4372
|
-
borderRadius: 999,
|
|
4373
|
-
color: hasUnpublishedChanges ? "#6a4a00" : "var(--theme-success-700)",
|
|
4374
|
-
fontSize: "0.75rem",
|
|
4375
|
-
fontWeight: 800,
|
|
4376
|
-
padding: "0.2rem 0.55rem",
|
|
4377
|
-
whiteSpace: "nowrap"
|
|
4378
|
-
},
|
|
4379
|
-
title: hasUnpublishedChanges ? "There are saved draft changes not yet published." : "The live page matches the latest published content.",
|
|
4380
|
-
children: hasUnpublishedChanges ? "Unpublished draft changes" : "Live is up to date"
|
|
4381
|
-
}
|
|
4382
|
-
),
|
|
4383
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4384
|
-
"button",
|
|
4385
|
-
{
|
|
4386
|
-
disabled: !canUndo,
|
|
4387
|
-
onClick: () => requestHistoryAction("undo"),
|
|
4388
|
-
style: {
|
|
4389
|
-
border: "1px solid var(--theme-elevation-300)",
|
|
4390
|
-
borderRadius: 12,
|
|
4391
|
-
cursor: canUndo ? "pointer" : "not-allowed",
|
|
4392
|
-
fontWeight: 800,
|
|
4393
|
-
padding: "0.5rem 0.65rem"
|
|
4394
|
-
},
|
|
4395
|
-
type: "button",
|
|
4396
|
-
children: "Undo"
|
|
4397
|
-
}
|
|
4398
|
-
),
|
|
4399
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4400
|
-
"button",
|
|
4401
|
-
{
|
|
4402
|
-
disabled: !canRedo,
|
|
4403
|
-
onClick: () => requestHistoryAction("redo"),
|
|
4404
|
-
style: {
|
|
4405
|
-
border: "1px solid var(--theme-elevation-300)",
|
|
4406
|
-
borderRadius: 12,
|
|
4407
|
-
cursor: canRedo ? "pointer" : "not-allowed",
|
|
4408
|
-
fontWeight: 800,
|
|
4409
|
-
padding: "0.5rem 0.65rem"
|
|
4410
|
-
},
|
|
4411
|
-
type: "button",
|
|
4412
|
-
children: "Redo"
|
|
4413
|
-
}
|
|
4414
|
-
),
|
|
4415
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4416
|
-
"button",
|
|
4417
|
-
{
|
|
4418
|
-
disabled: saving !== null,
|
|
4419
|
-
onClick: () => requestSave("draft"),
|
|
4420
|
-
style: {
|
|
4421
|
-
border: "1px solid var(--theme-elevation-300)",
|
|
4422
|
-
borderRadius: 12,
|
|
4423
|
-
cursor: saving ? "not-allowed" : "pointer",
|
|
4424
|
-
fontWeight: 800,
|
|
4425
|
-
padding: "0.5rem 0.75rem"
|
|
4426
|
-
},
|
|
4427
|
-
type: "button",
|
|
4428
|
-
children: saving === "draft" ? "Saving\u2026" : "Save Draft"
|
|
4429
|
-
}
|
|
4430
|
-
),
|
|
4431
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4432
|
-
"button",
|
|
4433
|
-
{
|
|
4434
|
-
disabled: !canPublish || saving !== null,
|
|
4435
|
-
onClick: () => requestSave("published"),
|
|
4436
|
-
style: {
|
|
4437
|
-
background: canPublish ? "var(--theme-success-700)" : "var(--theme-elevation-300)",
|
|
4438
|
-
border: "none",
|
|
4439
|
-
borderRadius: 12,
|
|
4440
|
-
color: canPublish ? "var(--theme-elevation-0)" : "var(--theme-elevation-700)",
|
|
4441
|
-
cursor: !canPublish || saving ? "not-allowed" : "pointer",
|
|
4442
|
-
fontWeight: 900,
|
|
4443
|
-
padding: "0.5rem 0.75rem"
|
|
4444
|
-
},
|
|
4445
|
-
type: "button",
|
|
4446
|
-
title: !canPublish ? "You do not have publish permissions." : void 0,
|
|
4447
|
-
children: saving === "published" ? "Publishing\u2026" : "Publish"
|
|
4448
|
-
}
|
|
4449
|
-
)
|
|
4450
|
-
] })
|
|
4451
|
-
]
|
|
4452
|
-
}
|
|
4453
|
-
),
|
|
4454
|
-
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4455
|
-
"iframe",
|
|
4456
|
-
{
|
|
4457
|
-
ref: iframeRef,
|
|
4458
|
-
src: `${builderBasePath.replace(/\/$/, "")}/${pageID}`,
|
|
4459
|
-
style: { border: "none", height: "100%", width: "100%" },
|
|
4460
|
-
title: "Page Builder",
|
|
4461
|
-
onLoad: () => {
|
|
4462
|
-
const iframe = iframeRef.current;
|
|
4463
|
-
if (!iframe?.contentWindow) return;
|
|
4464
|
-
iframe.contentWindow.postMessage({ source: "payload-visual-builder-parent", type: "dirty-check-request" }, "*");
|
|
4465
|
-
iframe.contentWindow.postMessage({ source: "payload-visual-builder-parent", type: "history-check-request" }, "*");
|
|
4466
|
-
}
|
|
4467
|
-
}
|
|
4468
|
-
)
|
|
4469
|
-
] })
|
|
4265
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { style: { height: "calc(100vh - 80px)" }, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
4266
|
+
"iframe",
|
|
4267
|
+
{
|
|
4268
|
+
ref: iframeRef,
|
|
4269
|
+
src: `${builderBasePath.replace(/\/$/, "")}/${pageID}`,
|
|
4270
|
+
style: { border: "none", height: "100%", width: "100%" },
|
|
4271
|
+
title: "Page Builder"
|
|
4272
|
+
}
|
|
4273
|
+
) })
|
|
4470
4274
|
] }) });
|
|
4471
4275
|
}
|
|
4472
4276
|
|
|
4473
|
-
// src/admin/components/studio/
|
|
4474
|
-
var import_react19 = require("react");
|
|
4475
|
-
var import_ui7 = require("@payloadcms/ui");
|
|
4277
|
+
// src/admin/components/studio/AdminStudioPagesListView.tsx
|
|
4476
4278
|
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
4477
|
-
var
|
|
4279
|
+
var hasAdminAccess = (user) => {
|
|
4280
|
+
if (!user || typeof user !== "object") return false;
|
|
4281
|
+
const role = user.role;
|
|
4282
|
+
return typeof role === "string" && (role === "admin" || role === "developer");
|
|
4283
|
+
};
|
|
4478
4284
|
var getPropString5 = (props, key, fallback) => {
|
|
4479
4285
|
if (!props || typeof props !== "object") return fallback;
|
|
4480
4286
|
const direct = props[key];
|
|
@@ -4486,107 +4292,98 @@ var getPropString5 = (props, key, fallback) => {
|
|
|
4486
4292
|
}
|
|
4487
4293
|
return fallback;
|
|
4488
4294
|
};
|
|
4489
|
-
|
|
4490
|
-
if (!user || typeof user !== "object") return false;
|
|
4491
|
-
const role = user.role;
|
|
4492
|
-
return role === "admin" || role === "editor";
|
|
4493
|
-
};
|
|
4494
|
-
var slugify = (value) => value.toLowerCase().trim().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-");
|
|
4495
|
-
function AdminStudioNewPageView(props) {
|
|
4496
|
-
const { user } = (0, import_ui7.useAuth)();
|
|
4295
|
+
function AdminStudioPagesListView(props) {
|
|
4497
4296
|
const adminBasePath = useAdminBasePath();
|
|
4297
|
+
const pathname = (0, import_navigation3.usePathname)();
|
|
4298
|
+
const pagesPath = resolveAdminPath(adminBasePath, "/pages");
|
|
4299
|
+
const nestedPagePath = pathname && pathname.startsWith(`${pagesPath}/`) ? pathname.slice(`${pagesPath}/`.length).split("/")[0] : "";
|
|
4300
|
+
if (nestedPagePath === "new") {
|
|
4301
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AdminStudioNewPageView, { ...props });
|
|
4302
|
+
}
|
|
4303
|
+
if (nestedPagePath) {
|
|
4304
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AdminStudioPageEditView, { ...props });
|
|
4305
|
+
}
|
|
4306
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(AdminStudioPagesIndexView, { ...props, adminBasePath });
|
|
4307
|
+
}
|
|
4308
|
+
function AdminStudioPagesIndexView({
|
|
4309
|
+
adminBasePath,
|
|
4310
|
+
...props
|
|
4311
|
+
}) {
|
|
4312
|
+
const { user } = (0, import_ui7.useAuth)();
|
|
4498
4313
|
const pagesCollectionSlug = getPropString5(props, "pagesCollectionSlug", "pages");
|
|
4499
|
-
const
|
|
4314
|
+
const newPagePath = resolveAdminPath(adminBasePath, "/pages/new");
|
|
4315
|
+
const [loading, setLoading] = (0, import_react19.useState)(true);
|
|
4500
4316
|
const [error, setError] = (0, import_react19.useState)(null);
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
slug,
|
|
4535
|
-
template,
|
|
4536
|
-
title
|
|
4537
|
-
}),
|
|
4538
|
-
credentials: "include",
|
|
4539
|
-
headers: {
|
|
4540
|
-
"Content-Type": "application/json"
|
|
4541
|
-
},
|
|
4542
|
-
method: "POST"
|
|
4543
|
-
});
|
|
4544
|
-
if (!response.ok) {
|
|
4545
|
-
throw new Error(`Failed to create page (${response.status}).`);
|
|
4546
|
-
}
|
|
4547
|
-
const payload = await response.json();
|
|
4548
|
-
const id = typeof payload.id === "string" || typeof payload.id === "number" ? String(payload.id) : "";
|
|
4549
|
-
if (!id) {
|
|
4550
|
-
throw new Error("Page created but no document ID was returned.");
|
|
4317
|
+
const [docs, setDocs] = (0, import_react19.useState)([]);
|
|
4318
|
+
const apiURL = (0, import_react19.useMemo)(() => {
|
|
4319
|
+
const params = new URLSearchParams({
|
|
4320
|
+
depth: "0",
|
|
4321
|
+
limit: "100",
|
|
4322
|
+
sort: "-updatedAt",
|
|
4323
|
+
draft: "true"
|
|
4324
|
+
});
|
|
4325
|
+
return `/api/${pagesCollectionSlug}?${params.toString()}`;
|
|
4326
|
+
}, [pagesCollectionSlug]);
|
|
4327
|
+
(0, import_react19.useEffect)(() => {
|
|
4328
|
+
let cancelled = false;
|
|
4329
|
+
const run = async () => {
|
|
4330
|
+
setLoading(true);
|
|
4331
|
+
setError(null);
|
|
4332
|
+
try {
|
|
4333
|
+
const res = await fetch(apiURL, { credentials: "include" });
|
|
4334
|
+
if (!res.ok) {
|
|
4335
|
+
const body = await res.text();
|
|
4336
|
+
throw new Error(body || "Failed to fetch pages");
|
|
4337
|
+
}
|
|
4338
|
+
const data = await res.json();
|
|
4339
|
+
if (!cancelled) {
|
|
4340
|
+
setDocs(Array.isArray(data.docs) ? data.docs : []);
|
|
4341
|
+
}
|
|
4342
|
+
} catch (err) {
|
|
4343
|
+
if (!cancelled) {
|
|
4344
|
+
setError(err instanceof Error ? err.message : "Failed to fetch pages");
|
|
4345
|
+
}
|
|
4346
|
+
} finally {
|
|
4347
|
+
if (!cancelled) {
|
|
4348
|
+
setLoading(false);
|
|
4349
|
+
}
|
|
4551
4350
|
}
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
4351
|
+
};
|
|
4352
|
+
void run();
|
|
4353
|
+
return () => {
|
|
4354
|
+
cancelled = true;
|
|
4355
|
+
};
|
|
4356
|
+
}, [apiURL]);
|
|
4357
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
4560
4358
|
AdminPage,
|
|
4561
4359
|
{
|
|
4360
|
+
actions: hasAdminAccess(user) ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_link2.default, { className: "orion-admin-action-button", href: newPagePath, children: "New Page" }) : null,
|
|
4562
4361
|
breadcrumbs: [
|
|
4563
4362
|
{ label: "Dashboard", href: adminBasePath },
|
|
4564
|
-
{ label: "Pages"
|
|
4565
|
-
{ label: "New Page" }
|
|
4363
|
+
{ label: "Pages" }
|
|
4566
4364
|
],
|
|
4567
|
-
description: "
|
|
4568
|
-
title: "
|
|
4569
|
-
children:
|
|
4365
|
+
description: "Open a page to edit it in the inline custom builder.",
|
|
4366
|
+
title: "Pages",
|
|
4367
|
+
children: [
|
|
4368
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
|
|
4570
4369
|
error ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "orion-admin-error", children: error }) : null,
|
|
4571
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("
|
|
4572
|
-
"
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("button", { disabled: submitting, type: "submit", children: submitting ? "Creating..." : "Create Page" })
|
|
4589
|
-
] })
|
|
4370
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "orion-admin-list", children: [
|
|
4371
|
+
!loading && !error && docs.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "orion-admin-card", children: [
|
|
4372
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("strong", { children: "No pages yet" }),
|
|
4373
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "Create the first page to start building content." })
|
|
4374
|
+
] }) : null,
|
|
4375
|
+
docs.map((doc) => {
|
|
4376
|
+
const id = typeof doc.id === "string" || typeof doc.id === "number" ? String(doc.id) : "";
|
|
4377
|
+
if (!id) return null;
|
|
4378
|
+
const title = typeof doc.title === "string" ? doc.title : "Untitled Page";
|
|
4379
|
+
const status = typeof doc._status === "string" ? doc._status : "draft";
|
|
4380
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_link2.default, { className: "orion-admin-list-item", href: resolveAdminPath(adminBasePath, `/pages/${id}`), children: [
|
|
4381
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("strong", { children: title }) }),
|
|
4382
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "orion-admin-pill", children: status })
|
|
4383
|
+
] }, id);
|
|
4384
|
+
})
|
|
4385
|
+
] })
|
|
4386
|
+
]
|
|
4590
4387
|
}
|
|
4591
4388
|
) });
|
|
4592
4389
|
}
|
|
@@ -6855,7 +6652,7 @@ function MediaListItem({
|
|
|
6855
6652
|
|
|
6856
6653
|
// src/admin-app/components/MediaUploadForm.tsx
|
|
6857
6654
|
var import_react27 = require("react");
|
|
6858
|
-
var
|
|
6655
|
+
var import_navigation4 = require("next/navigation");
|
|
6859
6656
|
|
|
6860
6657
|
// src/shared/clientImageUploadOptimization.ts
|
|
6861
6658
|
var MAX_DIRECT_UPLOAD_BYTES = 4e6;
|
|
@@ -6990,7 +6787,7 @@ var parseUploadError = async (response) => {
|
|
|
6990
6787
|
return fallback;
|
|
6991
6788
|
};
|
|
6992
6789
|
function MediaUploadForm() {
|
|
6993
|
-
const router = (0,
|
|
6790
|
+
const router = (0, import_navigation4.useRouter)();
|
|
6994
6791
|
const fileInputRef = (0, import_react27.useRef)(null);
|
|
6995
6792
|
const [alt, setAlt] = (0, import_react27.useState)("");
|
|
6996
6793
|
const [file, setFile] = (0, import_react27.useState)(null);
|
|
@@ -7525,17 +7322,17 @@ var FORM_TONE_OVERRIDES = {
|
|
|
7525
7322
|
var IDENTITY_KEYS = /* @__PURE__ */ new Set(["contactEmail", "email", "firstName", "lastName", "name"]);
|
|
7526
7323
|
var RESPONSE_FIELD_PREVIEW_LIMIT = 3;
|
|
7527
7324
|
var RESPONSE_SCROLL_THRESHOLD = 3;
|
|
7528
|
-
var
|
|
7325
|
+
var hasAdminAccess2 = (user) => {
|
|
7529
7326
|
if (!user || typeof user !== "object") return false;
|
|
7530
7327
|
const role = user.role;
|
|
7531
|
-
return typeof role === "string" && role === "admin";
|
|
7328
|
+
return typeof role === "string" && (role === "admin" || role === "developer");
|
|
7532
7329
|
};
|
|
7533
|
-
var
|
|
7330
|
+
var isEditor = (user) => {
|
|
7534
7331
|
if (!user || typeof user !== "object") return false;
|
|
7535
7332
|
const role = user.role;
|
|
7536
7333
|
return typeof role === "string" && role === "editor";
|
|
7537
7334
|
};
|
|
7538
|
-
var canReviewForms2 = (user) =>
|
|
7335
|
+
var canReviewForms2 = (user) => hasAdminAccess2(user) || isEditor(user);
|
|
7539
7336
|
var getPropString13 = (props, key, fallback) => {
|
|
7540
7337
|
if (!props || typeof props !== "object") return fallback;
|
|
7541
7338
|
const direct = props[key];
|
|
@@ -7708,14 +7505,10 @@ function AdminStudioFormsView(props) {
|
|
|
7708
7505
|
"formSubmissionsCollectionSlug",
|
|
7709
7506
|
"form-submissions"
|
|
7710
7507
|
);
|
|
7711
|
-
const formUploadsCollectionSlug = getPropString13(props, "formUploadsCollectionSlug", "form-uploads");
|
|
7712
7508
|
const adminBasePath = useAdminBasePath();
|
|
7713
|
-
const
|
|
7714
|
-
const
|
|
7715
|
-
|
|
7716
|
-
`/collections/${formSubmissionsCollectionSlug}`
|
|
7717
|
-
);
|
|
7718
|
-
const rawUploadsPath = resolveAdminPath(adminBasePath, `/collections/${formUploadsCollectionSlug}`);
|
|
7509
|
+
const studioFormsPath = resolveAdminPath(adminBasePath, "/forms");
|
|
7510
|
+
const studioSubmissionsPath = resolveAdminPath(adminBasePath, "/forms/submissions");
|
|
7511
|
+
const studioUploadsPath = resolveAdminPath(adminBasePath, "/forms/uploads");
|
|
7719
7512
|
const [forms, setForms] = (0, import_react31.useState)([]);
|
|
7720
7513
|
const [submissions, setSubmissions] = (0, import_react31.useState)([]);
|
|
7721
7514
|
const [loading, setLoading] = (0, import_react31.useState)(true);
|
|
@@ -7875,7 +7668,7 @@ function AdminStudioFormsView(props) {
|
|
|
7875
7668
|
import_link3.default,
|
|
7876
7669
|
{
|
|
7877
7670
|
className: "orion-admin-action-button orion-admin-action-button--soft",
|
|
7878
|
-
href: `${
|
|
7671
|
+
href: `${studioFormsPath}/${id}`,
|
|
7879
7672
|
children: "Open Form"
|
|
7880
7673
|
}
|
|
7881
7674
|
)
|
|
@@ -7977,7 +7770,7 @@ function AdminStudioFormsView(props) {
|
|
|
7977
7770
|
import_link3.default,
|
|
7978
7771
|
{
|
|
7979
7772
|
className: "orion-admin-upload-chip",
|
|
7980
|
-
href: `${
|
|
7773
|
+
href: `${studioUploadsPath}/${uploadID}`,
|
|
7981
7774
|
children: uploadLabel
|
|
7982
7775
|
},
|
|
7983
7776
|
uploadID
|
|
@@ -7994,7 +7787,7 @@ function AdminStudioFormsView(props) {
|
|
|
7994
7787
|
import_link3.default,
|
|
7995
7788
|
{
|
|
7996
7789
|
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
7997
|
-
href: `${
|
|
7790
|
+
href: `${studioSubmissionsPath}/${submissionID}`,
|
|
7998
7791
|
children: "Open"
|
|
7999
7792
|
}
|
|
8000
7793
|
)
|
|
@@ -8014,87 +7807,1714 @@ function AdminStudioFormsView(props) {
|
|
|
8014
7807
|
) });
|
|
8015
7808
|
}
|
|
8016
7809
|
|
|
8017
|
-
// src/admin/components/studio/
|
|
7810
|
+
// src/admin/components/studio/AdminStudioFormDetailView.tsx
|
|
7811
|
+
var import_link4 = __toESM(require("next/link"));
|
|
8018
7812
|
var import_react32 = require("react");
|
|
8019
|
-
|
|
8020
|
-
|
|
8021
|
-
var
|
|
8022
|
-
|
|
8023
|
-
|
|
8024
|
-
|
|
8025
|
-
|
|
7813
|
+
|
|
7814
|
+
// src/admin/components/studio/formsStudioShared.ts
|
|
7815
|
+
var FORM_TONES2 = [
|
|
7816
|
+
{
|
|
7817
|
+
accent: "var(--orion-cms-tone-1, var(--orion-cms-accent, var(--orion-admin-accent)))",
|
|
7818
|
+
accentBorder: "color-mix(in srgb, var(--orion-cms-tone-1, var(--orion-cms-accent, var(--orion-admin-accent))) 24%, transparent)",
|
|
7819
|
+
accentMist: "color-mix(in srgb, var(--orion-cms-tone-1, var(--orion-cms-accent, var(--orion-admin-accent))) 12%, transparent)",
|
|
7820
|
+
accentSoft: "color-mix(in srgb, var(--orion-cms-tone-1, var(--orion-cms-accent, var(--orion-admin-accent))) 7%, transparent)"
|
|
7821
|
+
},
|
|
7822
|
+
{
|
|
7823
|
+
accent: "var(--orion-cms-tone-2, var(--brand-secondary, var(--orion-admin-accent)))",
|
|
7824
|
+
accentBorder: "color-mix(in srgb, var(--orion-cms-tone-2, var(--brand-secondary, var(--orion-admin-accent))) 24%, transparent)",
|
|
7825
|
+
accentMist: "color-mix(in srgb, var(--orion-cms-tone-2, var(--brand-secondary, var(--orion-admin-accent))) 13%, transparent)",
|
|
7826
|
+
accentSoft: "color-mix(in srgb, var(--orion-cms-tone-2, var(--brand-secondary, var(--orion-admin-accent))) 8%, transparent)"
|
|
7827
|
+
},
|
|
7828
|
+
{
|
|
7829
|
+
accent: "var(--orion-cms-tone-3, color-mix(in srgb, var(--orion-cms-accent, var(--orion-admin-accent)) 72%, #5f816b))",
|
|
7830
|
+
accentBorder: "color-mix(in srgb, var(--orion-cms-tone-3, color-mix(in srgb, var(--orion-cms-accent, var(--orion-admin-accent)) 72%, #5f816b)) 24%, transparent)",
|
|
7831
|
+
accentMist: "color-mix(in srgb, var(--orion-cms-tone-3, color-mix(in srgb, var(--orion-cms-accent, var(--orion-admin-accent)) 72%, #5f816b)) 12%, transparent)",
|
|
7832
|
+
accentSoft: "color-mix(in srgb, var(--orion-cms-tone-3, color-mix(in srgb, var(--orion-cms-accent, var(--orion-admin-accent)) 72%, #5f816b)) 8%, transparent)"
|
|
7833
|
+
},
|
|
7834
|
+
{
|
|
7835
|
+
accent: "var(--orion-cms-tone-4, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 72%, #7a652e))",
|
|
7836
|
+
accentBorder: "color-mix(in srgb, var(--orion-cms-tone-4, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 72%, #7a652e)) 24%, transparent)",
|
|
7837
|
+
accentMist: "color-mix(in srgb, var(--orion-cms-tone-4, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 72%, #7a652e)) 13%, transparent)",
|
|
7838
|
+
accentSoft: "color-mix(in srgb, var(--orion-cms-tone-4, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 72%, #7a652e)) 8%, transparent)"
|
|
7839
|
+
},
|
|
7840
|
+
{
|
|
7841
|
+
accent: "var(--orion-cms-tone-5, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 68%, #8d4a40))",
|
|
7842
|
+
accentBorder: "color-mix(in srgb, var(--orion-cms-tone-5, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 68%, #8d4a40)) 24%, transparent)",
|
|
7843
|
+
accentMist: "color-mix(in srgb, var(--orion-cms-tone-5, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 68%, #8d4a40)) 13%, transparent)",
|
|
7844
|
+
accentSoft: "color-mix(in srgb, var(--orion-cms-tone-5, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 68%, #8d4a40)) 8%, transparent)"
|
|
7845
|
+
}
|
|
7846
|
+
];
|
|
7847
|
+
var FORM_TONE_OVERRIDES2 = {
|
|
7848
|
+
"basket-request": FORM_TONES2[1],
|
|
7849
|
+
contact: FORM_TONES2[2],
|
|
7850
|
+
"vendor-inquiry": FORM_TONES2[0]
|
|
8026
7851
|
};
|
|
8027
|
-
var
|
|
8028
|
-
|
|
8029
|
-
|
|
8030
|
-
|
|
8031
|
-
const
|
|
8032
|
-
|
|
8033
|
-
const
|
|
8034
|
-
|
|
8035
|
-
|
|
8036
|
-
|
|
8037
|
-
if (!isAdmin4(user)) {
|
|
8038
|
-
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8039
|
-
AdminPage,
|
|
8040
|
-
{
|
|
8041
|
-
breadcrumbs: [
|
|
8042
|
-
{ label: "Dashboard", href: adminBasePath },
|
|
8043
|
-
{ label: "Admin Tools" }
|
|
8044
|
-
],
|
|
8045
|
-
description: "You do not have access to this section.",
|
|
8046
|
-
title: "Admin Tools",
|
|
8047
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-card", children: [
|
|
8048
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Access denied" }),
|
|
8049
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "This section is restricted to administrator accounts." })
|
|
8050
|
-
] })
|
|
8051
|
-
}
|
|
8052
|
-
) });
|
|
7852
|
+
var IDENTITY_KEYS2 = /* @__PURE__ */ new Set(["contactEmail", "email", "firstName", "lastName", "name"]);
|
|
7853
|
+
var RESPONSE_FIELD_PREVIEW_LIMIT2 = 3;
|
|
7854
|
+
var getPropString14 = (props, key, fallback) => {
|
|
7855
|
+
if (!props || typeof props !== "object") return fallback;
|
|
7856
|
+
const direct = props[key];
|
|
7857
|
+
if (typeof direct === "string" && direct.length > 0) return direct;
|
|
7858
|
+
const clientProps = props.clientProps;
|
|
7859
|
+
if (clientProps && typeof clientProps === "object") {
|
|
7860
|
+
const nested = clientProps[key];
|
|
7861
|
+
if (typeof nested === "string" && nested.length > 0) return nested;
|
|
8053
7862
|
}
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
|
|
8059
|
-
|
|
8060
|
-
|
|
8061
|
-
|
|
8062
|
-
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
|
|
8068
|
-
|
|
8069
|
-
|
|
8070
|
-
|
|
8071
|
-
|
|
8072
|
-
|
|
8073
|
-
|
|
8074
|
-
|
|
8075
|
-
|
|
8076
|
-
|
|
8077
|
-
}
|
|
8078
|
-
(
|
|
8079
|
-
|
|
8080
|
-
|
|
8081
|
-
|
|
8082
|
-
|
|
8083
|
-
|
|
8084
|
-
|
|
8085
|
-
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
|
|
8094
|
-
|
|
8095
|
-
|
|
8096
|
-
|
|
8097
|
-
|
|
7863
|
+
return fallback;
|
|
7864
|
+
};
|
|
7865
|
+
var getParam3 = (params, key) => {
|
|
7866
|
+
if (!params || typeof params !== "object") return null;
|
|
7867
|
+
const value = params[key];
|
|
7868
|
+
if (typeof value === "string") return value;
|
|
7869
|
+
if (Array.isArray(value) && typeof value[0] === "string") return value[0];
|
|
7870
|
+
return null;
|
|
7871
|
+
};
|
|
7872
|
+
var getIDFromPathname = (pathname, marker) => {
|
|
7873
|
+
const markerIndex = pathname.indexOf(marker);
|
|
7874
|
+
if (markerIndex < 0) return null;
|
|
7875
|
+
const id = pathname.slice(markerIndex + marker.length).split("/")[0];
|
|
7876
|
+
return id ? decodeURIComponent(id) : null;
|
|
7877
|
+
};
|
|
7878
|
+
var formatDate2 = (value) => {
|
|
7879
|
+
if (typeof value !== "string" || value.length === 0) return "Unknown date";
|
|
7880
|
+
const date = new Date(value);
|
|
7881
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
7882
|
+
return date.toLocaleString();
|
|
7883
|
+
};
|
|
7884
|
+
var formatFileSize4 = (value) => {
|
|
7885
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return null;
|
|
7886
|
+
if (value < 1024) return `${value} B`;
|
|
7887
|
+
if (value < 1024 * 1024) return `${(value / 1024).toFixed(1)} KB`;
|
|
7888
|
+
return `${(value / (1024 * 1024)).toFixed(1)} MB`;
|
|
7889
|
+
};
|
|
7890
|
+
var getFieldCount2 = (form) => Array.isArray(form.steps) ? form.steps.reduce((count, step) => {
|
|
7891
|
+
if (!step || typeof step !== "object") return count;
|
|
7892
|
+
const fields = step.fields;
|
|
7893
|
+
return count + (Array.isArray(fields) ? fields.length : 0);
|
|
7894
|
+
}, 0) : 0;
|
|
7895
|
+
var getFormID3 = (value) => {
|
|
7896
|
+
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
7897
|
+
if (value && typeof value === "object") {
|
|
7898
|
+
const id = value.id;
|
|
7899
|
+
if (typeof id === "string" || typeof id === "number") return String(id);
|
|
7900
|
+
}
|
|
7901
|
+
return "";
|
|
7902
|
+
};
|
|
7903
|
+
var getUploads2 = (value) => Array.isArray(value) ? value.map((entry) => {
|
|
7904
|
+
if (typeof entry === "string" || typeof entry === "number") {
|
|
7905
|
+
return { id: entry };
|
|
7906
|
+
}
|
|
7907
|
+
return entry && typeof entry === "object" ? entry : null;
|
|
7908
|
+
}).filter((entry) => Boolean(entry)) : [];
|
|
7909
|
+
var getNameAndEmail2 = (data) => {
|
|
7910
|
+
if (!data || typeof data !== "object") return {};
|
|
7911
|
+
const record = data;
|
|
7912
|
+
const email = typeof record.email === "string" ? record.email : typeof record.contactEmail === "string" ? record.contactEmail : void 0;
|
|
7913
|
+
const firstName = typeof record.firstName === "string" ? record.firstName : void 0;
|
|
7914
|
+
const lastName = typeof record.lastName === "string" ? record.lastName : void 0;
|
|
7915
|
+
const fallbackName = typeof record.name === "string" ? record.name : void 0;
|
|
7916
|
+
const joinedName = [firstName, lastName].filter(Boolean).join(" ").trim();
|
|
7917
|
+
return {
|
|
7918
|
+
...email ? { email } : {},
|
|
7919
|
+
...joinedName ? { name: joinedName } : fallbackName ? { name: fallbackName } : {}
|
|
7920
|
+
};
|
|
7921
|
+
};
|
|
7922
|
+
var humanizeKey2 = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim().replace(/^./, (char) => char.toUpperCase());
|
|
7923
|
+
var buildFieldLabelMap2 = (form) => {
|
|
7924
|
+
const labels = /* @__PURE__ */ new Map();
|
|
7925
|
+
for (const step of Array.isArray(form.steps) ? form.steps : []) {
|
|
7926
|
+
const fields = step && typeof step === "object" ? step.fields : null;
|
|
7927
|
+
for (const field of Array.isArray(fields) ? fields : []) {
|
|
7928
|
+
const name = field && typeof field === "object" && typeof field.name === "string" ? field.name.trim() : "";
|
|
7929
|
+
const label = field && typeof field === "object" && typeof field.label === "string" ? field.label.trim() : "";
|
|
7930
|
+
if (name) {
|
|
7931
|
+
labels.set(name, label || humanizeKey2(name));
|
|
7932
|
+
}
|
|
7933
|
+
}
|
|
7934
|
+
}
|
|
7935
|
+
return labels;
|
|
7936
|
+
};
|
|
7937
|
+
var truncateText2 = (value, maxLength = 64) => {
|
|
7938
|
+
const normalized = value.replace(/\s+/g, " ").trim();
|
|
7939
|
+
if (normalized.length <= maxLength) return normalized;
|
|
7940
|
+
return `${normalized.slice(0, maxLength - 1).trimEnd()}...`;
|
|
7941
|
+
};
|
|
7942
|
+
var formatPreviewValue2 = (value) => {
|
|
7943
|
+
if (value === null || value === void 0) return null;
|
|
7944
|
+
if (typeof value === "boolean") return value ? "Yes" : "No";
|
|
7945
|
+
if (typeof value === "number") return String(value);
|
|
7946
|
+
if (typeof value === "string") {
|
|
7947
|
+
const trimmed = value.trim();
|
|
7948
|
+
return trimmed ? truncateText2(trimmed, 72) : null;
|
|
7949
|
+
}
|
|
7950
|
+
if (Array.isArray(value)) {
|
|
7951
|
+
const joined = value.map((entry) => String(entry).trim()).filter(Boolean).join(", ");
|
|
7952
|
+
return joined ? truncateText2(joined, 72) : null;
|
|
7953
|
+
}
|
|
7954
|
+
if (typeof value === "object") {
|
|
7955
|
+
return truncateText2(JSON.stringify(value), 72);
|
|
7956
|
+
}
|
|
7957
|
+
return truncateText2(String(value), 72);
|
|
7958
|
+
};
|
|
7959
|
+
var getPreviewFields2 = (data, fieldLabels) => {
|
|
7960
|
+
if (!data || typeof data !== "object") return [];
|
|
7961
|
+
return Object.entries(data).filter(([key]) => !IDENTITY_KEYS2.has(key)).map(([key, value]) => {
|
|
7962
|
+
const formatted = formatPreviewValue2(value);
|
|
7963
|
+
if (!formatted) return null;
|
|
7964
|
+
return {
|
|
7965
|
+
label: fieldLabels.get(key) || humanizeKey2(key),
|
|
7966
|
+
value: formatted
|
|
7967
|
+
};
|
|
7968
|
+
}).filter((entry) => Boolean(entry)).slice(0, RESPONSE_FIELD_PREVIEW_LIMIT2);
|
|
7969
|
+
};
|
|
7970
|
+
var getInitials3 = (...values) => {
|
|
7971
|
+
const source = values.find((value) => typeof value === "string" && value.trim().length > 0);
|
|
7972
|
+
if (!source) return "FM";
|
|
7973
|
+
const cleaned = source.replace(/[^a-z0-9]+/gi, " ").trim();
|
|
7974
|
+
if (!cleaned) return "FM";
|
|
7975
|
+
const parts = cleaned.split(/\s+/).filter(Boolean);
|
|
7976
|
+
if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
|
|
7977
|
+
return `${parts[0][0] || ""}${parts[1][0] || ""}`.toUpperCase();
|
|
7978
|
+
};
|
|
7979
|
+
var getHash2 = (value) => {
|
|
7980
|
+
let hash = 0;
|
|
7981
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
7982
|
+
hash = hash * 31 + value.charCodeAt(index) >>> 0;
|
|
7983
|
+
}
|
|
7984
|
+
return hash;
|
|
7985
|
+
};
|
|
7986
|
+
var normalizeToneKey2 = (value) => value?.trim().toLowerCase() || "";
|
|
7987
|
+
var getFormTone2 = (slug, fallbackSeed) => {
|
|
7988
|
+
const normalizedSlug = normalizeToneKey2(slug);
|
|
7989
|
+
if (normalizedSlug && FORM_TONE_OVERRIDES2[normalizedSlug]) {
|
|
7990
|
+
return FORM_TONE_OVERRIDES2[normalizedSlug];
|
|
7991
|
+
}
|
|
7992
|
+
const normalizedSeed = normalizeToneKey2(fallbackSeed);
|
|
7993
|
+
if (normalizedSeed && FORM_TONE_OVERRIDES2[normalizedSeed]) {
|
|
7994
|
+
return FORM_TONE_OVERRIDES2[normalizedSeed];
|
|
7995
|
+
}
|
|
7996
|
+
return FORM_TONES2[getHash2(slug || fallbackSeed) % FORM_TONES2.length];
|
|
7997
|
+
};
|
|
7998
|
+
var getFormToneStyle2 = (slug, fallbackSeed) => {
|
|
7999
|
+
const tone = getFormTone2(slug, fallbackSeed);
|
|
8000
|
+
return {
|
|
8001
|
+
["--form-accent"]: tone.accent,
|
|
8002
|
+
["--form-accent-border"]: tone.accentBorder,
|
|
8003
|
+
["--form-accent-mist"]: tone.accentMist,
|
|
8004
|
+
["--form-accent-soft"]: tone.accentSoft
|
|
8005
|
+
};
|
|
8006
|
+
};
|
|
8007
|
+
var getFormTitle2 = (value) => {
|
|
8008
|
+
if (value && typeof value === "object" && typeof value.title === "string") {
|
|
8009
|
+
const title = value.title.trim();
|
|
8010
|
+
if (title.length > 0) return title;
|
|
8011
|
+
}
|
|
8012
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
8013
|
+
return value;
|
|
8014
|
+
}
|
|
8015
|
+
return "Untitled Form";
|
|
8016
|
+
};
|
|
8017
|
+
|
|
8018
|
+
// src/admin/components/studio/AdminStudioFormDetailView.tsx
|
|
8019
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
8020
|
+
var getNonEmptyText = (value, fallback = "") => typeof value === "string" && value.trim().length > 0 ? value : fallback;
|
|
8021
|
+
var normalizeSteps = (value) => {
|
|
8022
|
+
if (!Array.isArray(value)) {
|
|
8023
|
+
return [];
|
|
8024
|
+
}
|
|
8025
|
+
return value.map((step) => step && typeof step === "object" && !Array.isArray(step) ? step : {});
|
|
8026
|
+
};
|
|
8027
|
+
var normalizeFormResponse = (value) => {
|
|
8028
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
8029
|
+
return {};
|
|
8030
|
+
}
|
|
8031
|
+
const record = value;
|
|
8032
|
+
const nestedDoc = record.doc;
|
|
8033
|
+
if (nestedDoc && typeof nestedDoc === "object" && !Array.isArray(nestedDoc)) {
|
|
8034
|
+
return nestedDoc;
|
|
8035
|
+
}
|
|
8036
|
+
return record;
|
|
8037
|
+
};
|
|
8038
|
+
var toEditorState = (doc) => {
|
|
8039
|
+
const emails = doc.emails && typeof doc.emails === "object" ? doc.emails : null;
|
|
8040
|
+
const adminRecipients = Array.isArray(emails?.adminRecipients) ? emails?.adminRecipients.map(
|
|
8041
|
+
(entry) => entry && typeof entry === "object" && typeof entry.email === "string" ? entry.email.trim() : ""
|
|
8042
|
+
).filter(Boolean) : [];
|
|
8043
|
+
return {
|
|
8044
|
+
adminRecipientsText: adminRecipients.join("\n"),
|
|
8045
|
+
adminSubject: getNonEmptyText(emails?.adminSubject),
|
|
8046
|
+
confirmationHeading: getNonEmptyText(emails?.confirmationHeading),
|
|
8047
|
+
confirmationMessage: getNonEmptyText(emails?.confirmationMessage),
|
|
8048
|
+
confirmationSubject: getNonEmptyText(emails?.confirmationSubject),
|
|
8049
|
+
sendAdmin: emails?.sendAdmin !== false,
|
|
8050
|
+
sendConfirmation: emails?.sendConfirmation !== false,
|
|
8051
|
+
slug: getNonEmptyText(doc.slug),
|
|
8052
|
+
steps: normalizeSteps(doc.steps),
|
|
8053
|
+
submitLabel: getNonEmptyText(doc.submitLabel, "Submit"),
|
|
8054
|
+
successMessage: getNonEmptyText(doc.successMessage),
|
|
8055
|
+
title: getNonEmptyText(doc.title, "Untitled Form")
|
|
8056
|
+
};
|
|
8057
|
+
};
|
|
8058
|
+
var checkboxLabelStyle = {
|
|
8059
|
+
alignItems: "center",
|
|
8060
|
+
display: "flex",
|
|
8061
|
+
gap: "0.6rem"
|
|
8062
|
+
};
|
|
8063
|
+
var sectionGridStyle = {
|
|
8064
|
+
display: "grid",
|
|
8065
|
+
gap: "1rem",
|
|
8066
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))"
|
|
8067
|
+
};
|
|
8068
|
+
var fieldTypeOptions = [
|
|
8069
|
+
"text",
|
|
8070
|
+
"textarea",
|
|
8071
|
+
"email",
|
|
8072
|
+
"phone",
|
|
8073
|
+
"url",
|
|
8074
|
+
"select",
|
|
8075
|
+
"radio",
|
|
8076
|
+
"checkbox",
|
|
8077
|
+
"checkbox-group",
|
|
8078
|
+
"date",
|
|
8079
|
+
"file"
|
|
8080
|
+
];
|
|
8081
|
+
var getFields = (step) => Array.isArray(step.fields) ? step.fields.map(
|
|
8082
|
+
(field) => field && typeof field === "object" && !Array.isArray(field) ? field : {}
|
|
8083
|
+
) : [];
|
|
8084
|
+
var toOptionsText = (value) => Array.isArray(value) ? value.map((entry) => {
|
|
8085
|
+
if (entry && typeof entry === "object" && !Array.isArray(entry)) {
|
|
8086
|
+
const record = entry;
|
|
8087
|
+
const label = typeof record.label === "string" ? record.label : "";
|
|
8088
|
+
const optionValue = typeof record.value === "string" ? record.value : label;
|
|
8089
|
+
return label && optionValue && label !== optionValue ? `${label} | ${optionValue}` : label || optionValue;
|
|
8090
|
+
}
|
|
8091
|
+
return typeof entry === "string" ? entry : "";
|
|
8092
|
+
}).filter(Boolean).join("\n") : "";
|
|
8093
|
+
var fromOptionsText = (value) => value.split("\n").map((entry) => entry.trim()).filter(Boolean).map((entry) => {
|
|
8094
|
+
const [label, optionValue] = entry.split("|").map((part) => part.trim());
|
|
8095
|
+
return {
|
|
8096
|
+
label,
|
|
8097
|
+
value: optionValue || label
|
|
8098
|
+
};
|
|
8099
|
+
});
|
|
8100
|
+
var slugifyFieldName = (value) => value.trim().replace(/[^a-z0-9]+/gi, " ").trim().replace(/\s+([a-z0-9])/gi, (_, char) => char.toUpperCase()).replace(/^./, (char) => char.toLowerCase());
|
|
8101
|
+
var blankField = () => ({
|
|
8102
|
+
label: "New field",
|
|
8103
|
+
name: "newField",
|
|
8104
|
+
required: false,
|
|
8105
|
+
type: "text"
|
|
8106
|
+
});
|
|
8107
|
+
var blankStep = () => ({
|
|
8108
|
+
fields: [blankField()],
|
|
8109
|
+
title: "New step"
|
|
8110
|
+
});
|
|
8111
|
+
var getStepTitle = (step, stepIndex) => getNonEmptyText(step.title, `Step ${stepIndex + 1}`);
|
|
8112
|
+
var getFieldLabel = (field, fieldIndex) => getNonEmptyText(field.label, getNonEmptyText(field.name, `Field ${fieldIndex + 1}`));
|
|
8113
|
+
var formatFieldTypeLabel = (value) => getNonEmptyText(value, "text").replace(/-/g, " ").replace(/^./, (char) => char.toUpperCase());
|
|
8114
|
+
var getStepDestination = (stepIndex, stepCount) => {
|
|
8115
|
+
if (stepIndex < stepCount - 1) {
|
|
8116
|
+
return `Next: Step ${stepIndex + 2}`;
|
|
8117
|
+
}
|
|
8118
|
+
return "Then: Submit form";
|
|
8119
|
+
};
|
|
8120
|
+
var moveItem = (items, fromIndex, toIndex) => {
|
|
8121
|
+
if (toIndex < 0 || toIndex >= items.length) {
|
|
8122
|
+
return items;
|
|
8123
|
+
}
|
|
8124
|
+
const nextItems = [...items];
|
|
8125
|
+
const [item] = nextItems.splice(fromIndex, 1);
|
|
8126
|
+
nextItems.splice(toIndex, 0, item);
|
|
8127
|
+
return nextItems;
|
|
8128
|
+
};
|
|
8129
|
+
function getFormIDFromPathname(pathname) {
|
|
8130
|
+
const marker = "/forms/";
|
|
8131
|
+
const raw = getIDFromPathname(pathname, marker);
|
|
8132
|
+
if (!raw || raw === "submissions" || raw === "uploads") {
|
|
8133
|
+
return null;
|
|
8134
|
+
}
|
|
8135
|
+
return raw;
|
|
8136
|
+
}
|
|
8137
|
+
function AdminStudioFormDetailView(props) {
|
|
8138
|
+
const formsCollectionSlug = getPropString14(props, "formsCollectionSlug", "forms");
|
|
8139
|
+
const formSubmissionsCollectionSlug = getPropString14(
|
|
8140
|
+
props,
|
|
8141
|
+
"formSubmissionsCollectionSlug",
|
|
8142
|
+
"form-submissions"
|
|
8143
|
+
);
|
|
8144
|
+
const adminBasePath = useAdminBasePath();
|
|
8145
|
+
const formsPath = resolveAdminPath(adminBasePath, "/forms");
|
|
8146
|
+
const formIDFromParams = (0, import_react32.useMemo)(() => getParam3(props.params, "id"), [props.params]);
|
|
8147
|
+
const [formID, setFormID] = (0, import_react32.useState)(formIDFromParams);
|
|
8148
|
+
const [didResolvePathFallback, setDidResolvePathFallback] = (0, import_react32.useState)(false);
|
|
8149
|
+
const [doc, setDoc] = (0, import_react32.useState)(null);
|
|
8150
|
+
const [submissions, setSubmissions] = (0, import_react32.useState)([]);
|
|
8151
|
+
const [editorState, setEditorState] = (0, import_react32.useState)(null);
|
|
8152
|
+
const [loading, setLoading] = (0, import_react32.useState)(true);
|
|
8153
|
+
const [error, setError] = (0, import_react32.useState)(null);
|
|
8154
|
+
const [saving, setSaving] = (0, import_react32.useState)(false);
|
|
8155
|
+
const [savedMessage, setSavedMessage] = (0, import_react32.useState)(null);
|
|
8156
|
+
(0, import_react32.useEffect)(() => {
|
|
8157
|
+
if (formIDFromParams) {
|
|
8158
|
+
setFormID(formIDFromParams);
|
|
8159
|
+
setDidResolvePathFallback(true);
|
|
8160
|
+
return;
|
|
8161
|
+
}
|
|
8162
|
+
if (typeof window !== "undefined") {
|
|
8163
|
+
setFormID(getFormIDFromPathname(window.location.pathname));
|
|
8164
|
+
}
|
|
8165
|
+
setDidResolvePathFallback(true);
|
|
8166
|
+
}, [formIDFromParams]);
|
|
8167
|
+
const loadDoc = async (id) => {
|
|
8168
|
+
setLoading(true);
|
|
8169
|
+
setError(null);
|
|
8170
|
+
try {
|
|
8171
|
+
const submissionsParams = new URLSearchParams({
|
|
8172
|
+
depth: "1",
|
|
8173
|
+
limit: "25",
|
|
8174
|
+
sort: "-submittedAt"
|
|
8175
|
+
});
|
|
8176
|
+
submissionsParams.set("where[form][equals]", id);
|
|
8177
|
+
const [formResponse, submissionsResponse] = await Promise.all([
|
|
8178
|
+
fetch(`/api/${formsCollectionSlug}/${encodeURIComponent(id)}?depth=0&draft=true`, {
|
|
8179
|
+
credentials: "include"
|
|
8180
|
+
}),
|
|
8181
|
+
fetch(`/api/${formSubmissionsCollectionSlug}?${submissionsParams.toString()}`, {
|
|
8182
|
+
credentials: "include"
|
|
8183
|
+
})
|
|
8184
|
+
]);
|
|
8185
|
+
if (!formResponse.ok) {
|
|
8186
|
+
throw new Error(`Failed to load form (${formResponse.status}).`);
|
|
8187
|
+
}
|
|
8188
|
+
if (!submissionsResponse.ok) {
|
|
8189
|
+
throw new Error(`Failed to load submissions (${submissionsResponse.status}).`);
|
|
8190
|
+
}
|
|
8191
|
+
const nextDoc = normalizeFormResponse(await formResponse.json());
|
|
8192
|
+
const submissionsPayload = await submissionsResponse.json();
|
|
8193
|
+
const nextSubmissions = Array.isArray(submissionsPayload.docs) ? submissionsPayload.docs : [];
|
|
8194
|
+
setDoc(nextDoc);
|
|
8195
|
+
setEditorState(toEditorState(nextDoc));
|
|
8196
|
+
setSubmissions(nextSubmissions);
|
|
8197
|
+
} catch (loadError) {
|
|
8198
|
+
setError(loadError instanceof Error ? loadError.message : "Failed to load form.");
|
|
8199
|
+
setDoc(null);
|
|
8200
|
+
setEditorState(null);
|
|
8201
|
+
setSubmissions([]);
|
|
8202
|
+
} finally {
|
|
8203
|
+
setLoading(false);
|
|
8204
|
+
}
|
|
8205
|
+
};
|
|
8206
|
+
(0, import_react32.useEffect)(() => {
|
|
8207
|
+
if (!formID) {
|
|
8208
|
+
return;
|
|
8209
|
+
}
|
|
8210
|
+
void loadDoc(formID);
|
|
8211
|
+
}, [formID, formsCollectionSlug, formSubmissionsCollectionSlug]);
|
|
8212
|
+
const save = async (event) => {
|
|
8213
|
+
event.preventDefault();
|
|
8214
|
+
if (!formID || !editorState) {
|
|
8215
|
+
return;
|
|
8216
|
+
}
|
|
8217
|
+
setSaving(true);
|
|
8218
|
+
setError(null);
|
|
8219
|
+
setSavedMessage(null);
|
|
8220
|
+
try {
|
|
8221
|
+
const payload = {
|
|
8222
|
+
emails: {
|
|
8223
|
+
adminRecipients: editorState.adminRecipientsText.split("\n").map((value) => value.trim()).filter(Boolean).map((email) => ({ email })),
|
|
8224
|
+
adminSubject: editorState.adminSubject.trim(),
|
|
8225
|
+
confirmationHeading: editorState.confirmationHeading.trim(),
|
|
8226
|
+
confirmationMessage: editorState.confirmationMessage,
|
|
8227
|
+
confirmationSubject: editorState.confirmationSubject.trim(),
|
|
8228
|
+
sendAdmin: editorState.sendAdmin,
|
|
8229
|
+
sendConfirmation: editorState.sendConfirmation
|
|
8230
|
+
},
|
|
8231
|
+
slug: editorState.slug.trim(),
|
|
8232
|
+
steps: editorState.steps,
|
|
8233
|
+
submitLabel: editorState.submitLabel.trim(),
|
|
8234
|
+
successMessage: editorState.successMessage,
|
|
8235
|
+
title: editorState.title.trim()
|
|
8236
|
+
};
|
|
8237
|
+
const response = await fetch(`/api/${formsCollectionSlug}/${encodeURIComponent(formID)}`, {
|
|
8238
|
+
body: JSON.stringify(payload),
|
|
8239
|
+
credentials: "include",
|
|
8240
|
+
headers: {
|
|
8241
|
+
"Content-Type": "application/json"
|
|
8242
|
+
},
|
|
8243
|
+
method: "PATCH"
|
|
8244
|
+
});
|
|
8245
|
+
if (!response.ok) {
|
|
8246
|
+
throw new Error(`Failed to save form (${response.status}).`);
|
|
8247
|
+
}
|
|
8248
|
+
const nextDoc = normalizeFormResponse(await response.json());
|
|
8249
|
+
setDoc(nextDoc);
|
|
8250
|
+
setEditorState(toEditorState(nextDoc));
|
|
8251
|
+
setSavedMessage("Saved.");
|
|
8252
|
+
} catch (saveError) {
|
|
8253
|
+
setError(saveError instanceof Error ? saveError.message : "Failed to save form.");
|
|
8254
|
+
} finally {
|
|
8255
|
+
setSaving(false);
|
|
8256
|
+
}
|
|
8257
|
+
};
|
|
8258
|
+
if (!formID && !didResolvePathFallback) {
|
|
8259
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8260
|
+
AdminPage,
|
|
8261
|
+
{
|
|
8262
|
+
breadcrumbs: [
|
|
8263
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
8264
|
+
{ label: "Forms", href: formsPath },
|
|
8265
|
+
{ label: "Form" }
|
|
8266
|
+
],
|
|
8267
|
+
description: "Loading form workspace...",
|
|
8268
|
+
title: "Form",
|
|
8269
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_jsx_runtime41.Fragment, {})
|
|
8270
|
+
}
|
|
8271
|
+
) });
|
|
8272
|
+
}
|
|
8273
|
+
const title = doc && typeof doc.title === "string" && doc.title.trim().length > 0 ? doc.title : "Form";
|
|
8274
|
+
const slug = doc && typeof doc.slug === "string" ? doc.slug : "";
|
|
8275
|
+
const toneStyle = getFormToneStyle2(slug, title || formID || "form");
|
|
8276
|
+
const fieldLabels = doc ? buildFieldLabelMap2(doc) : /* @__PURE__ */ new Map();
|
|
8277
|
+
const latestSubmission = submissions[0];
|
|
8278
|
+
const stepCount = editorState?.steps.length || 0;
|
|
8279
|
+
const fieldCount = editorState ? editorState.steps.reduce((count, step) => count + getFields(step).length, 0) : doc ? getFieldCount2(doc) : 0;
|
|
8280
|
+
const updateStep = (stepIndex, patch) => {
|
|
8281
|
+
setEditorState(
|
|
8282
|
+
(current) => current ? {
|
|
8283
|
+
...current,
|
|
8284
|
+
steps: current.steps.map(
|
|
8285
|
+
(step, index) => index === stepIndex ? { ...step, ...patch } : step
|
|
8286
|
+
)
|
|
8287
|
+
} : current
|
|
8288
|
+
);
|
|
8289
|
+
};
|
|
8290
|
+
const updateField = (stepIndex, fieldIndex, patch) => {
|
|
8291
|
+
setEditorState((current) => {
|
|
8292
|
+
if (!current) return current;
|
|
8293
|
+
return {
|
|
8294
|
+
...current,
|
|
8295
|
+
steps: current.steps.map((step, index) => {
|
|
8296
|
+
if (index !== stepIndex) return step;
|
|
8297
|
+
const fields = getFields(step).map(
|
|
8298
|
+
(field, currentFieldIndex) => currentFieldIndex === fieldIndex ? { ...field, ...patch } : field
|
|
8299
|
+
);
|
|
8300
|
+
return { ...step, fields };
|
|
8301
|
+
})
|
|
8302
|
+
};
|
|
8303
|
+
});
|
|
8304
|
+
};
|
|
8305
|
+
const moveStep = (stepIndex, direction) => {
|
|
8306
|
+
setEditorState(
|
|
8307
|
+
(current) => current ? {
|
|
8308
|
+
...current,
|
|
8309
|
+
steps: moveItem(current.steps, stepIndex, stepIndex + direction)
|
|
8310
|
+
} : current
|
|
8311
|
+
);
|
|
8312
|
+
};
|
|
8313
|
+
const moveField = (stepIndex, fieldIndex, direction) => {
|
|
8314
|
+
setEditorState((current) => {
|
|
8315
|
+
if (!current) return current;
|
|
8316
|
+
return {
|
|
8317
|
+
...current,
|
|
8318
|
+
steps: current.steps.map(
|
|
8319
|
+
(step, index) => index === stepIndex ? { ...step, fields: moveItem(getFields(step), fieldIndex, fieldIndex + direction) } : step
|
|
8320
|
+
)
|
|
8321
|
+
};
|
|
8322
|
+
});
|
|
8323
|
+
};
|
|
8324
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
|
|
8325
|
+
AdminPage,
|
|
8326
|
+
{
|
|
8327
|
+
breadcrumbs: [
|
|
8328
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
8329
|
+
{ label: "Forms", href: formsPath },
|
|
8330
|
+
{ label: title }
|
|
8331
|
+
],
|
|
8332
|
+
description: "Manage form content and review recent responses without leaving Studio.",
|
|
8333
|
+
title: "Form",
|
|
8334
|
+
children: [
|
|
8335
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
|
|
8336
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-error", children: error }) : null,
|
|
8337
|
+
savedMessage ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-success", children: savedMessage }) : null,
|
|
8338
|
+
!loading && !error && doc && editorState && formID ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { style: { display: "grid", gap: "1rem" }, children: [
|
|
8339
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-forms-summary-grid", children: [
|
|
8340
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("article", { className: "orion-admin-overview-stat", children: [
|
|
8341
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-overview-stat-label", children: "Workflow steps" }),
|
|
8342
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: stepCount }),
|
|
8343
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { children: "Configured stages in the public form flow." })
|
|
8344
|
+
] }),
|
|
8345
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("article", { className: "orion-admin-overview-stat", children: [
|
|
8346
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-overview-stat-label", children: "Fields" }),
|
|
8347
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: fieldCount }),
|
|
8348
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { children: "Total visible and conditional fields across every step." })
|
|
8349
|
+
] }),
|
|
8350
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("article", { className: "orion-admin-overview-stat", children: [
|
|
8351
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-overview-stat-label", children: "Recent submissions" }),
|
|
8352
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: submissions.length }),
|
|
8353
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { children: latestSubmission ? `Latest response ${formatDate2(latestSubmission.submittedAt)}` : "No responses have been recorded yet." })
|
|
8354
|
+
] })
|
|
8355
|
+
] }),
|
|
8356
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("section", { className: "orion-admin-form-board", style: toneStyle, children: [
|
|
8357
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form-board-header", children: [
|
|
8358
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form-board-heading", children: [
|
|
8359
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form-board-kicker-row", children: [
|
|
8360
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-form-board-kicker", children: slug || "No slug set" }),
|
|
8361
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-form-board-meta", children: doc.updatedAt ? `Updated ${formatDate2(doc.updatedAt)}` : "Update time unavailable" })
|
|
8362
|
+
] }),
|
|
8363
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form-board-title-row", children: [
|
|
8364
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-form-board-mark", children: getInitials3(title, slug) }),
|
|
8365
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form-board-copy", children: [
|
|
8366
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("h2", { className: "orion-admin-form-board-title", children: title }),
|
|
8367
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "orion-admin-form-board-subtitle", children: editorState.successMessage.trim().length > 0 ? editorState.successMessage : "No success message set." })
|
|
8368
|
+
] })
|
|
8369
|
+
] })
|
|
8370
|
+
] }),
|
|
8371
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-form-board-actions", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form-board-count", children: [
|
|
8372
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-form-board-count-value", children: submissions.length }),
|
|
8373
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "orion-admin-form-board-count-label", children: [
|
|
8374
|
+
"response",
|
|
8375
|
+
submissions.length === 1 ? "" : "s"
|
|
8376
|
+
] })
|
|
8377
|
+
] }) })
|
|
8378
|
+
] }),
|
|
8379
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form-board-metrics", children: [
|
|
8380
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("article", { className: "orion-admin-form-metric", children: [
|
|
8381
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-form-metric-label", children: "Submit button" }),
|
|
8382
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { className: "orion-admin-form-metric-value is-copy", children: editorState.submitLabel || "Submit" })
|
|
8383
|
+
] }),
|
|
8384
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("article", { className: "orion-admin-form-metric", children: [
|
|
8385
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-form-metric-label", children: "Admin notifications" }),
|
|
8386
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { className: "orion-admin-form-metric-value", children: editorState.sendAdmin ? "On" : "Off" })
|
|
8387
|
+
] }),
|
|
8388
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("article", { className: "orion-admin-form-metric", children: [
|
|
8389
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-form-metric-label", children: "Confirmation email" }),
|
|
8390
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { className: "orion-admin-form-metric-value", children: editorState.sendConfirmation ? "On" : "Off" })
|
|
8391
|
+
] }),
|
|
8392
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("article", { className: "orion-admin-form-metric", children: [
|
|
8393
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-form-metric-label", children: "Latest response" }),
|
|
8394
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { className: "orion-admin-form-metric-value is-copy", children: latestSubmission ? formatDate2(latestSubmission.submittedAt) : "No activity yet" })
|
|
8395
|
+
] })
|
|
8396
|
+
] })
|
|
8397
|
+
] }),
|
|
8398
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { style: sectionGridStyle, children: [
|
|
8399
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { style: { display: "grid", gap: "1rem" }, children: [
|
|
8400
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-card", children: [
|
|
8401
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Step preview" }),
|
|
8402
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Review the public workflow as visitors will move through it." }),
|
|
8403
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: editorState.steps.length > 0 ? editorState.steps.map((record, stepIndex) => {
|
|
8404
|
+
const fields = getFields(record);
|
|
8405
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form", children: [
|
|
8406
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { children: [
|
|
8407
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("strong", { children: [
|
|
8408
|
+
"Step ",
|
|
8409
|
+
stepIndex + 1,
|
|
8410
|
+
": ",
|
|
8411
|
+
getNonEmptyText(record?.title, "Untitled Step")
|
|
8412
|
+
] }),
|
|
8413
|
+
getNonEmptyText(record?.subtitle) ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-meta", style: { marginTop: "0.25rem" }, children: getNonEmptyText(record?.subtitle) }) : null
|
|
8414
|
+
] }),
|
|
8415
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-inline-actions", children: [
|
|
8416
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "orion-admin-pill", children: [
|
|
8417
|
+
fields.length,
|
|
8418
|
+
" field",
|
|
8419
|
+
fields.length === 1 ? "" : "s"
|
|
8420
|
+
] }),
|
|
8421
|
+
record?.allowSkip === true ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-pill", children: "Can skip" }) : null,
|
|
8422
|
+
getNonEmptyText(record?.nextLabel) ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "orion-admin-pill", children: [
|
|
8423
|
+
"Next: ",
|
|
8424
|
+
getNonEmptyText(record?.nextLabel)
|
|
8425
|
+
] }) : null
|
|
8426
|
+
] }),
|
|
8427
|
+
fields.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list", children: fields.map((field, fieldIndex) => {
|
|
8428
|
+
const fieldRecord = field && typeof field === "object" && !Array.isArray(field) ? field : null;
|
|
8429
|
+
const type = getNonEmptyText(fieldRecord?.type, "text");
|
|
8430
|
+
const label = getNonEmptyText(
|
|
8431
|
+
fieldRecord?.label,
|
|
8432
|
+
getNonEmptyText(fieldRecord?.name, `Field ${fieldIndex + 1}`)
|
|
8433
|
+
);
|
|
8434
|
+
const helpText = getNonEmptyText(fieldRecord?.helpText);
|
|
8435
|
+
const condition = fieldRecord?.condition && typeof fieldRecord.condition === "object" && !Array.isArray(fieldRecord.condition) ? fieldRecord.condition : null;
|
|
8436
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-item", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { children: [
|
|
8437
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: label }),
|
|
8438
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-list-meta", children: [
|
|
8439
|
+
type,
|
|
8440
|
+
fieldRecord?.required === true ? " \xB7 required" : "",
|
|
8441
|
+
condition?.field && condition?.equals ? ` \xB7 when ${String(condition.field)} = ${String(condition.equals)}` : ""
|
|
8442
|
+
] }),
|
|
8443
|
+
helpText ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8444
|
+
"div",
|
|
8445
|
+
{
|
|
8446
|
+
className: "orion-admin-list-meta",
|
|
8447
|
+
style: { marginTop: "0.25rem" },
|
|
8448
|
+
children: helpText
|
|
8449
|
+
}
|
|
8450
|
+
) : null
|
|
8451
|
+
] }) }, `field-${fieldIndex}`);
|
|
8452
|
+
}) }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-meta", children: "This step has no fields." })
|
|
8453
|
+
] }, `step-${stepIndex}`);
|
|
8454
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-empty-state", children: [
|
|
8455
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "No steps configured" }),
|
|
8456
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Add at least one step in Form settings to publish this form." })
|
|
8457
|
+
] }) })
|
|
8458
|
+
] }),
|
|
8459
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-card", children: [
|
|
8460
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Recent submissions" }),
|
|
8461
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Jump from the form definition into the latest responses." }),
|
|
8462
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: submissions.length > 0 ? submissions.map((submission) => {
|
|
8463
|
+
const submissionID = typeof submission.id === "string" || typeof submission.id === "number" ? String(submission.id) : "";
|
|
8464
|
+
if (!submissionID) return null;
|
|
8465
|
+
const identity = getNameAndEmail2(submission.data);
|
|
8466
|
+
const previewFields = getPreviewFields2(submission.data, fieldLabels);
|
|
8467
|
+
const formSubmissionPath = resolveAdminPath(
|
|
8468
|
+
adminBasePath,
|
|
8469
|
+
`/forms/submissions/${submissionID}`
|
|
8470
|
+
);
|
|
8471
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_link4.default, { className: "orion-admin-list-item", href: formSubmissionPath, children: [
|
|
8472
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { children: [
|
|
8473
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: identity.name || identity.email || "Submission" }),
|
|
8474
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-meta", children: formatDate2(submission.submittedAt) }),
|
|
8475
|
+
previewFields.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-meta", style: { marginTop: "0.3rem" }, children: previewFields.map((field) => `${field.label}: ${field.value}`).join(" \xB7 ") }) : null
|
|
8476
|
+
] }),
|
|
8477
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-action-button orion-admin-action-button--ghost", children: "Open" })
|
|
8478
|
+
] }, submissionID);
|
|
8479
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-empty-state", children: [
|
|
8480
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "No responses yet" }),
|
|
8481
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "This view will populate as soon as the form starts receiving traffic." })
|
|
8482
|
+
] }) })
|
|
8483
|
+
] })
|
|
8484
|
+
] }),
|
|
8485
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("form", { className: "orion-admin-form", onSubmit: save, children: [
|
|
8486
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Form settings" }),
|
|
8487
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8488
|
+
"Title",
|
|
8489
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8490
|
+
"input",
|
|
8491
|
+
{
|
|
8492
|
+
onChange: (event) => setEditorState(
|
|
8493
|
+
(current) => current ? { ...current, title: event.target.value } : current
|
|
8494
|
+
),
|
|
8495
|
+
required: true,
|
|
8496
|
+
type: "text",
|
|
8497
|
+
value: editorState.title
|
|
8498
|
+
}
|
|
8499
|
+
)
|
|
8500
|
+
] }),
|
|
8501
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8502
|
+
"Slug",
|
|
8503
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8504
|
+
"input",
|
|
8505
|
+
{
|
|
8506
|
+
onChange: (event) => setEditorState(
|
|
8507
|
+
(current) => current ? { ...current, slug: event.target.value } : current
|
|
8508
|
+
),
|
|
8509
|
+
required: true,
|
|
8510
|
+
type: "text",
|
|
8511
|
+
value: editorState.slug
|
|
8512
|
+
}
|
|
8513
|
+
)
|
|
8514
|
+
] }),
|
|
8515
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8516
|
+
"Submit button",
|
|
8517
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8518
|
+
"input",
|
|
8519
|
+
{
|
|
8520
|
+
onChange: (event) => setEditorState(
|
|
8521
|
+
(current) => current ? { ...current, submitLabel: event.target.value } : current
|
|
8522
|
+
),
|
|
8523
|
+
type: "text",
|
|
8524
|
+
value: editorState.submitLabel
|
|
8525
|
+
}
|
|
8526
|
+
)
|
|
8527
|
+
] }),
|
|
8528
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8529
|
+
"Success message",
|
|
8530
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8531
|
+
"textarea",
|
|
8532
|
+
{
|
|
8533
|
+
onChange: (event) => setEditorState(
|
|
8534
|
+
(current) => current ? { ...current, successMessage: event.target.value } : current
|
|
8535
|
+
),
|
|
8536
|
+
rows: 4,
|
|
8537
|
+
value: editorState.successMessage
|
|
8538
|
+
}
|
|
8539
|
+
)
|
|
8540
|
+
] }),
|
|
8541
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-card", children: [
|
|
8542
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Email behavior" }),
|
|
8543
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { style: { display: "grid", gap: "0.85rem", marginTop: "0.9rem" }, children: [
|
|
8544
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { style: checkboxLabelStyle, children: [
|
|
8545
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8546
|
+
"input",
|
|
8547
|
+
{
|
|
8548
|
+
checked: editorState.sendAdmin,
|
|
8549
|
+
onChange: (event) => setEditorState(
|
|
8550
|
+
(current) => current ? { ...current, sendAdmin: event.target.checked } : current
|
|
8551
|
+
),
|
|
8552
|
+
type: "checkbox"
|
|
8553
|
+
}
|
|
8554
|
+
),
|
|
8555
|
+
"Send admin notifications"
|
|
8556
|
+
] }),
|
|
8557
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8558
|
+
"Admin recipients",
|
|
8559
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8560
|
+
"textarea",
|
|
8561
|
+
{
|
|
8562
|
+
onChange: (event) => setEditorState(
|
|
8563
|
+
(current) => current ? { ...current, adminRecipientsText: event.target.value } : current
|
|
8564
|
+
),
|
|
8565
|
+
placeholder: "one@email.com\ntwo@email.com",
|
|
8566
|
+
rows: 4,
|
|
8567
|
+
value: editorState.adminRecipientsText
|
|
8568
|
+
}
|
|
8569
|
+
)
|
|
8570
|
+
] }),
|
|
8571
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8572
|
+
"Admin subject",
|
|
8573
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8574
|
+
"input",
|
|
8575
|
+
{
|
|
8576
|
+
onChange: (event) => setEditorState(
|
|
8577
|
+
(current) => current ? { ...current, adminSubject: event.target.value } : current
|
|
8578
|
+
),
|
|
8579
|
+
type: "text",
|
|
8580
|
+
value: editorState.adminSubject
|
|
8581
|
+
}
|
|
8582
|
+
)
|
|
8583
|
+
] }),
|
|
8584
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { style: checkboxLabelStyle, children: [
|
|
8585
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8586
|
+
"input",
|
|
8587
|
+
{
|
|
8588
|
+
checked: editorState.sendConfirmation,
|
|
8589
|
+
onChange: (event) => setEditorState(
|
|
8590
|
+
(current) => current ? { ...current, sendConfirmation: event.target.checked } : current
|
|
8591
|
+
),
|
|
8592
|
+
type: "checkbox"
|
|
8593
|
+
}
|
|
8594
|
+
),
|
|
8595
|
+
"Send confirmation email"
|
|
8596
|
+
] }),
|
|
8597
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8598
|
+
"Confirmation subject",
|
|
8599
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8600
|
+
"input",
|
|
8601
|
+
{
|
|
8602
|
+
onChange: (event) => setEditorState(
|
|
8603
|
+
(current) => current ? { ...current, confirmationSubject: event.target.value } : current
|
|
8604
|
+
),
|
|
8605
|
+
type: "text",
|
|
8606
|
+
value: editorState.confirmationSubject
|
|
8607
|
+
}
|
|
8608
|
+
)
|
|
8609
|
+
] }),
|
|
8610
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8611
|
+
"Confirmation heading",
|
|
8612
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8613
|
+
"input",
|
|
8614
|
+
{
|
|
8615
|
+
onChange: (event) => setEditorState(
|
|
8616
|
+
(current) => current ? { ...current, confirmationHeading: event.target.value } : current
|
|
8617
|
+
),
|
|
8618
|
+
type: "text",
|
|
8619
|
+
value: editorState.confirmationHeading
|
|
8620
|
+
}
|
|
8621
|
+
)
|
|
8622
|
+
] }),
|
|
8623
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8624
|
+
"Confirmation message",
|
|
8625
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8626
|
+
"textarea",
|
|
8627
|
+
{
|
|
8628
|
+
onChange: (event) => setEditorState(
|
|
8629
|
+
(current) => current ? { ...current, confirmationMessage: event.target.value } : current
|
|
8630
|
+
),
|
|
8631
|
+
rows: 4,
|
|
8632
|
+
value: editorState.confirmationMessage
|
|
8633
|
+
}
|
|
8634
|
+
)
|
|
8635
|
+
] })
|
|
8636
|
+
] })
|
|
8637
|
+
] }),
|
|
8638
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-card orion-admin-workflow-editor", children: [
|
|
8639
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-workflow-editor-header", children: [
|
|
8640
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { children: [
|
|
8641
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Form steps" }),
|
|
8642
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Build the visitor flow, then edit each step's fields below." })
|
|
8643
|
+
] }),
|
|
8644
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8645
|
+
"button",
|
|
8646
|
+
{
|
|
8647
|
+
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
8648
|
+
onClick: () => setEditorState(
|
|
8649
|
+
(current) => current ? { ...current, steps: [...current.steps, blankStep()] } : current
|
|
8650
|
+
),
|
|
8651
|
+
type: "button",
|
|
8652
|
+
children: "Add step"
|
|
8653
|
+
}
|
|
8654
|
+
)
|
|
8655
|
+
] }),
|
|
8656
|
+
editorState.steps.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-empty-state", children: [
|
|
8657
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "No steps configured" }),
|
|
8658
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Add a first step to start building the public form flow." })
|
|
8659
|
+
] }) : null,
|
|
8660
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-step-editor-list", children: editorState.steps.map((step, stepIndex) => {
|
|
8661
|
+
const fields = getFields(step);
|
|
8662
|
+
const requiredCount = fields.filter((field) => field.required === true).length;
|
|
8663
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("details", { className: "orion-admin-step-editor", open: true, children: [
|
|
8664
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("summary", { className: "orion-admin-step-editor-summary", children: [
|
|
8665
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-workflow-node-number", children: stepIndex + 1 }),
|
|
8666
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-step-editor-title", children: getStepTitle(step, stepIndex) }),
|
|
8667
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "orion-admin-step-editor-meta", children: [
|
|
8668
|
+
fields.length,
|
|
8669
|
+
" field",
|
|
8670
|
+
fields.length === 1 ? "" : "s",
|
|
8671
|
+
requiredCount > 0 ? ` \xB7 ${requiredCount} required` : ""
|
|
8672
|
+
] }),
|
|
8673
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-workflow-node-destination", children: getStepDestination(stepIndex, editorState.steps.length) })
|
|
8674
|
+
] }),
|
|
8675
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-step-editor-body", children: [
|
|
8676
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-step-editor-actions", children: [
|
|
8677
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8678
|
+
"button",
|
|
8679
|
+
{
|
|
8680
|
+
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
8681
|
+
disabled: stepIndex === 0,
|
|
8682
|
+
onClick: () => moveStep(stepIndex, -1),
|
|
8683
|
+
type: "button",
|
|
8684
|
+
children: "Move up"
|
|
8685
|
+
}
|
|
8686
|
+
),
|
|
8687
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8688
|
+
"button",
|
|
8689
|
+
{
|
|
8690
|
+
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
8691
|
+
disabled: stepIndex === editorState.steps.length - 1,
|
|
8692
|
+
onClick: () => moveStep(stepIndex, 1),
|
|
8693
|
+
type: "button",
|
|
8694
|
+
children: "Move down"
|
|
8695
|
+
}
|
|
8696
|
+
),
|
|
8697
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8698
|
+
"button",
|
|
8699
|
+
{
|
|
8700
|
+
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
8701
|
+
onClick: () => setEditorState(
|
|
8702
|
+
(current) => current ? {
|
|
8703
|
+
...current,
|
|
8704
|
+
steps: current.steps.filter((_, index) => index !== stepIndex)
|
|
8705
|
+
} : current
|
|
8706
|
+
),
|
|
8707
|
+
type: "button",
|
|
8708
|
+
children: "Remove step"
|
|
8709
|
+
}
|
|
8710
|
+
)
|
|
8711
|
+
] }),
|
|
8712
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-step-settings-grid", children: [
|
|
8713
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8714
|
+
"Step title",
|
|
8715
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8716
|
+
"input",
|
|
8717
|
+
{
|
|
8718
|
+
onChange: (event) => updateStep(stepIndex, { title: event.target.value }),
|
|
8719
|
+
type: "text",
|
|
8720
|
+
value: getNonEmptyText(step.title)
|
|
8721
|
+
}
|
|
8722
|
+
)
|
|
8723
|
+
] }),
|
|
8724
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8725
|
+
"Next button label",
|
|
8726
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8727
|
+
"input",
|
|
8728
|
+
{
|
|
8729
|
+
onChange: (event) => updateStep(stepIndex, { nextLabel: event.target.value }),
|
|
8730
|
+
placeholder: "Next",
|
|
8731
|
+
type: "text",
|
|
8732
|
+
value: getNonEmptyText(step.nextLabel)
|
|
8733
|
+
}
|
|
8734
|
+
)
|
|
8735
|
+
] })
|
|
8736
|
+
] }),
|
|
8737
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8738
|
+
"Step intro text",
|
|
8739
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8740
|
+
"textarea",
|
|
8741
|
+
{
|
|
8742
|
+
onChange: (event) => updateStep(stepIndex, { subtitle: event.target.value }),
|
|
8743
|
+
rows: 3,
|
|
8744
|
+
value: getNonEmptyText(step.subtitle)
|
|
8745
|
+
}
|
|
8746
|
+
)
|
|
8747
|
+
] }),
|
|
8748
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { style: checkboxLabelStyle, children: [
|
|
8749
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8750
|
+
"input",
|
|
8751
|
+
{
|
|
8752
|
+
checked: step.allowSkip === true,
|
|
8753
|
+
onChange: (event) => updateStep(stepIndex, { allowSkip: event.target.checked }),
|
|
8754
|
+
type: "checkbox"
|
|
8755
|
+
}
|
|
8756
|
+
),
|
|
8757
|
+
"Allow visitors to skip this step"
|
|
8758
|
+
] }),
|
|
8759
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-field-list-header", children: [
|
|
8760
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { children: [
|
|
8761
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Fields in this step" }),
|
|
8762
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "These appear together before the visitor moves to the next step." })
|
|
8763
|
+
] }),
|
|
8764
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8765
|
+
"button",
|
|
8766
|
+
{
|
|
8767
|
+
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
8768
|
+
onClick: () => setEditorState(
|
|
8769
|
+
(current) => current ? {
|
|
8770
|
+
...current,
|
|
8771
|
+
steps: current.steps.map(
|
|
8772
|
+
(currentStep, index) => index === stepIndex ? { ...currentStep, fields: [...getFields(currentStep), blankField()] } : currentStep
|
|
8773
|
+
)
|
|
8774
|
+
} : current
|
|
8775
|
+
),
|
|
8776
|
+
type: "button",
|
|
8777
|
+
children: "Add field"
|
|
8778
|
+
}
|
|
8779
|
+
)
|
|
8780
|
+
] }),
|
|
8781
|
+
fields.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-field-editor-list", children: fields.map((field, fieldIndex) => {
|
|
8782
|
+
const label = getFieldLabel(field, fieldIndex);
|
|
8783
|
+
const fieldType = getNonEmptyText(field.type, "text");
|
|
8784
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("details", { className: "orion-admin-field-editor", children: [
|
|
8785
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("summary", { className: "orion-admin-field-editor-summary", children: [
|
|
8786
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-field-order", children: fieldIndex + 1 }),
|
|
8787
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-field-editor-title", children: label }),
|
|
8788
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "orion-admin-field-editor-meta", children: [
|
|
8789
|
+
formatFieldTypeLabel(fieldType),
|
|
8790
|
+
field.required === true ? " \xB7 Required" : ""
|
|
8791
|
+
] })
|
|
8792
|
+
] }),
|
|
8793
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-field-editor-body", children: [
|
|
8794
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-step-editor-actions", children: [
|
|
8795
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8796
|
+
"button",
|
|
8797
|
+
{
|
|
8798
|
+
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
8799
|
+
disabled: fieldIndex === 0,
|
|
8800
|
+
onClick: () => moveField(stepIndex, fieldIndex, -1),
|
|
8801
|
+
type: "button",
|
|
8802
|
+
children: "Move up"
|
|
8803
|
+
}
|
|
8804
|
+
),
|
|
8805
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8806
|
+
"button",
|
|
8807
|
+
{
|
|
8808
|
+
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
8809
|
+
disabled: fieldIndex === fields.length - 1,
|
|
8810
|
+
onClick: () => moveField(stepIndex, fieldIndex, 1),
|
|
8811
|
+
type: "button",
|
|
8812
|
+
children: "Move down"
|
|
8813
|
+
}
|
|
8814
|
+
),
|
|
8815
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8816
|
+
"button",
|
|
8817
|
+
{
|
|
8818
|
+
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
8819
|
+
onClick: () => setEditorState((current) => {
|
|
8820
|
+
if (!current) return current;
|
|
8821
|
+
return {
|
|
8822
|
+
...current,
|
|
8823
|
+
steps: current.steps.map(
|
|
8824
|
+
(currentStep, index) => index === stepIndex ? {
|
|
8825
|
+
...currentStep,
|
|
8826
|
+
fields: getFields(currentStep).filter(
|
|
8827
|
+
(_, currentFieldIndex) => currentFieldIndex !== fieldIndex
|
|
8828
|
+
)
|
|
8829
|
+
} : currentStep
|
|
8830
|
+
)
|
|
8831
|
+
};
|
|
8832
|
+
}),
|
|
8833
|
+
type: "button",
|
|
8834
|
+
children: "Remove field"
|
|
8835
|
+
}
|
|
8836
|
+
)
|
|
8837
|
+
] }),
|
|
8838
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-step-settings-grid", children: [
|
|
8839
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8840
|
+
"Field label",
|
|
8841
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8842
|
+
"input",
|
|
8843
|
+
{
|
|
8844
|
+
onChange: (event) => {
|
|
8845
|
+
const nextLabel = event.target.value;
|
|
8846
|
+
const currentName = getNonEmptyText(field.name);
|
|
8847
|
+
updateField(stepIndex, fieldIndex, {
|
|
8848
|
+
label: nextLabel,
|
|
8849
|
+
name: currentName || slugifyFieldName(nextLabel)
|
|
8850
|
+
});
|
|
8851
|
+
},
|
|
8852
|
+
type: "text",
|
|
8853
|
+
value: label
|
|
8854
|
+
}
|
|
8855
|
+
)
|
|
8856
|
+
] }),
|
|
8857
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8858
|
+
"Field type",
|
|
8859
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8860
|
+
"select",
|
|
8861
|
+
{
|
|
8862
|
+
onChange: (event) => updateField(stepIndex, fieldIndex, { type: event.target.value }),
|
|
8863
|
+
value: fieldType,
|
|
8864
|
+
children: fieldTypeOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("option", { value: option, children: formatFieldTypeLabel(option) }, option))
|
|
8865
|
+
}
|
|
8866
|
+
)
|
|
8867
|
+
] })
|
|
8868
|
+
] }),
|
|
8869
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8870
|
+
"Field key",
|
|
8871
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8872
|
+
"input",
|
|
8873
|
+
{
|
|
8874
|
+
onChange: (event) => updateField(stepIndex, fieldIndex, { name: event.target.value }),
|
|
8875
|
+
type: "text",
|
|
8876
|
+
value: getNonEmptyText(field.name)
|
|
8877
|
+
}
|
|
8878
|
+
)
|
|
8879
|
+
] }),
|
|
8880
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { style: checkboxLabelStyle, children: [
|
|
8881
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8882
|
+
"input",
|
|
8883
|
+
{
|
|
8884
|
+
checked: field.required === true,
|
|
8885
|
+
onChange: (event) => updateField(stepIndex, fieldIndex, { required: event.target.checked }),
|
|
8886
|
+
type: "checkbox"
|
|
8887
|
+
}
|
|
8888
|
+
),
|
|
8889
|
+
"Required"
|
|
8890
|
+
] }),
|
|
8891
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8892
|
+
"Help text",
|
|
8893
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8894
|
+
"textarea",
|
|
8895
|
+
{
|
|
8896
|
+
onChange: (event) => updateField(stepIndex, fieldIndex, { helpText: event.target.value }),
|
|
8897
|
+
rows: 2,
|
|
8898
|
+
value: getNonEmptyText(field.helpText)
|
|
8899
|
+
}
|
|
8900
|
+
)
|
|
8901
|
+
] }),
|
|
8902
|
+
["select", "radio", "checkbox-group"].includes(fieldType) ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
8903
|
+
"Options",
|
|
8904
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
8905
|
+
"textarea",
|
|
8906
|
+
{
|
|
8907
|
+
onChange: (event) => updateField(stepIndex, fieldIndex, {
|
|
8908
|
+
options: fromOptionsText(event.target.value)
|
|
8909
|
+
}),
|
|
8910
|
+
placeholder: "Option one\nOption two",
|
|
8911
|
+
rows: 4,
|
|
8912
|
+
value: toOptionsText(field.options)
|
|
8913
|
+
}
|
|
8914
|
+
)
|
|
8915
|
+
] }) : null
|
|
8916
|
+
] })
|
|
8917
|
+
] }, `edit-field-${stepIndex}-${fieldIndex}`);
|
|
8918
|
+
}) }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-empty-state", children: [
|
|
8919
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "No fields in this step" }),
|
|
8920
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Add a field so visitors have something to answer here." })
|
|
8921
|
+
] })
|
|
8922
|
+
] })
|
|
8923
|
+
] }, `edit-step-${stepIndex}`);
|
|
8924
|
+
}) })
|
|
8925
|
+
] }),
|
|
8926
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { disabled: saving, type: "submit", children: saving ? "Saving..." : "Save Form" })
|
|
8927
|
+
] })
|
|
8928
|
+
] })
|
|
8929
|
+
] }) : null
|
|
8930
|
+
]
|
|
8931
|
+
}
|
|
8932
|
+
) });
|
|
8933
|
+
}
|
|
8934
|
+
|
|
8935
|
+
// src/admin/components/studio/AdminStudioFormSubmissionView.tsx
|
|
8936
|
+
var import_link5 = __toESM(require("next/link"));
|
|
8937
|
+
var import_react33 = require("react");
|
|
8938
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
8939
|
+
var sectionGridStyle2 = {
|
|
8940
|
+
display: "grid",
|
|
8941
|
+
gap: "1rem",
|
|
8942
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))"
|
|
8943
|
+
};
|
|
8944
|
+
var nestedListStyle = {
|
|
8945
|
+
display: "grid",
|
|
8946
|
+
gap: "0.45rem",
|
|
8947
|
+
margin: 0,
|
|
8948
|
+
padding: 0
|
|
8949
|
+
};
|
|
8950
|
+
var renderFieldValue = (value) => {
|
|
8951
|
+
if (value === null || value === void 0) {
|
|
8952
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-list-meta", children: "No value" });
|
|
8953
|
+
}
|
|
8954
|
+
if (typeof value === "boolean") {
|
|
8955
|
+
return value ? "Yes" : "No";
|
|
8956
|
+
}
|
|
8957
|
+
if (typeof value === "number") {
|
|
8958
|
+
return String(value);
|
|
8959
|
+
}
|
|
8960
|
+
if (typeof value === "string") {
|
|
8961
|
+
return value.trim().length > 0 ? value : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-list-meta", children: "No value" });
|
|
8962
|
+
}
|
|
8963
|
+
if (Array.isArray(value)) {
|
|
8964
|
+
const entries = value.filter((entry) => entry !== null && entry !== void 0 && entry !== "");
|
|
8965
|
+
if (entries.length === 0) {
|
|
8966
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-list-meta", children: "No value" });
|
|
8967
|
+
}
|
|
8968
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ul", { style: nestedListStyle, children: entries.map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("li", { children: renderFieldValue(entry) }, index)) });
|
|
8969
|
+
}
|
|
8970
|
+
if (typeof value === "object") {
|
|
8971
|
+
const entries = Object.entries(value).filter(
|
|
8972
|
+
([, entryValue]) => entryValue !== null && entryValue !== void 0 && entryValue !== ""
|
|
8973
|
+
);
|
|
8974
|
+
if (entries.length === 0) {
|
|
8975
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-list-meta", children: "No value" });
|
|
8976
|
+
}
|
|
8977
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { style: { display: "grid", gap: "0.65rem" }, children: entries.map(([key, entryValue]) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-meta-row", children: [
|
|
8978
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-label", children: humanizeKey2(key) }),
|
|
8979
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-value", children: renderFieldValue(entryValue) })
|
|
8980
|
+
] }, key)) });
|
|
8981
|
+
}
|
|
8982
|
+
return String(value);
|
|
8983
|
+
};
|
|
8984
|
+
function getSubmissionIDFromPathname(pathname) {
|
|
8985
|
+
return getIDFromPathname(pathname, "/forms/submissions/");
|
|
8986
|
+
}
|
|
8987
|
+
function AdminStudioFormSubmissionView(props) {
|
|
8988
|
+
const formsCollectionSlug = getPropString14(props, "formsCollectionSlug", "forms");
|
|
8989
|
+
const formSubmissionsCollectionSlug = getPropString14(
|
|
8990
|
+
props,
|
|
8991
|
+
"formSubmissionsCollectionSlug",
|
|
8992
|
+
"form-submissions"
|
|
8993
|
+
);
|
|
8994
|
+
const adminBasePath = useAdminBasePath();
|
|
8995
|
+
const formsPath = resolveAdminPath(adminBasePath, "/forms");
|
|
8996
|
+
const submissionIDFromParams = (0, import_react33.useMemo)(() => getParam3(props.params, "id"), [props.params]);
|
|
8997
|
+
const [submissionID, setSubmissionID] = (0, import_react33.useState)(submissionIDFromParams);
|
|
8998
|
+
const [didResolvePathFallback, setDidResolvePathFallback] = (0, import_react33.useState)(false);
|
|
8999
|
+
const [doc, setDoc] = (0, import_react33.useState)(null);
|
|
9000
|
+
const [formDoc, setFormDoc] = (0, import_react33.useState)(null);
|
|
9001
|
+
const [loading, setLoading] = (0, import_react33.useState)(true);
|
|
9002
|
+
const [error, setError] = (0, import_react33.useState)(null);
|
|
9003
|
+
const [confirmDelete, setConfirmDelete] = (0, import_react33.useState)(false);
|
|
9004
|
+
const [deleting, setDeleting] = (0, import_react33.useState)(false);
|
|
9005
|
+
(0, import_react33.useEffect)(() => {
|
|
9006
|
+
if (submissionIDFromParams) {
|
|
9007
|
+
setSubmissionID(submissionIDFromParams);
|
|
9008
|
+
setDidResolvePathFallback(true);
|
|
9009
|
+
return;
|
|
9010
|
+
}
|
|
9011
|
+
if (typeof window !== "undefined") {
|
|
9012
|
+
setSubmissionID(getSubmissionIDFromPathname(window.location.pathname));
|
|
9013
|
+
}
|
|
9014
|
+
setDidResolvePathFallback(true);
|
|
9015
|
+
}, [submissionIDFromParams]);
|
|
9016
|
+
const loadDoc = async (id) => {
|
|
9017
|
+
setLoading(true);
|
|
9018
|
+
setError(null);
|
|
9019
|
+
try {
|
|
9020
|
+
const response = await fetch(
|
|
9021
|
+
`/api/${formSubmissionsCollectionSlug}/${encodeURIComponent(id)}?depth=2&draft=true`,
|
|
9022
|
+
{
|
|
9023
|
+
credentials: "include"
|
|
9024
|
+
}
|
|
9025
|
+
);
|
|
9026
|
+
if (!response.ok) {
|
|
9027
|
+
throw new Error(`Failed to load submission (${response.status}).`);
|
|
9028
|
+
}
|
|
9029
|
+
const nextDoc = await response.json();
|
|
9030
|
+
const relatedForm = nextDoc.form && typeof nextDoc.form === "object" && !Array.isArray(nextDoc.form) ? nextDoc.form : null;
|
|
9031
|
+
let nextFormDoc = relatedForm;
|
|
9032
|
+
const relatedFormID2 = getFormID3(nextDoc.form);
|
|
9033
|
+
if (!nextFormDoc && relatedFormID2) {
|
|
9034
|
+
const formResponse = await fetch(
|
|
9035
|
+
`/api/${formsCollectionSlug}/${encodeURIComponent(relatedFormID2)}?depth=0&draft=true`,
|
|
9036
|
+
{
|
|
9037
|
+
credentials: "include"
|
|
9038
|
+
}
|
|
9039
|
+
);
|
|
9040
|
+
if (formResponse.ok) {
|
|
9041
|
+
nextFormDoc = await formResponse.json();
|
|
9042
|
+
}
|
|
9043
|
+
}
|
|
9044
|
+
setDoc(nextDoc);
|
|
9045
|
+
setFormDoc(nextFormDoc);
|
|
9046
|
+
} catch (loadError) {
|
|
9047
|
+
setError(loadError instanceof Error ? loadError.message : "Failed to load submission.");
|
|
9048
|
+
setDoc(null);
|
|
9049
|
+
setFormDoc(null);
|
|
9050
|
+
} finally {
|
|
9051
|
+
setLoading(false);
|
|
9052
|
+
}
|
|
9053
|
+
};
|
|
9054
|
+
(0, import_react33.useEffect)(() => {
|
|
9055
|
+
if (!submissionID) {
|
|
9056
|
+
return;
|
|
9057
|
+
}
|
|
9058
|
+
void loadDoc(submissionID);
|
|
9059
|
+
}, [formsCollectionSlug, formSubmissionsCollectionSlug, submissionID]);
|
|
9060
|
+
const deleteSubmission = async () => {
|
|
9061
|
+
if (!submissionID) {
|
|
9062
|
+
return;
|
|
9063
|
+
}
|
|
9064
|
+
setDeleting(true);
|
|
9065
|
+
setError(null);
|
|
9066
|
+
try {
|
|
9067
|
+
const response = await fetch(`/api/${formSubmissionsCollectionSlug}/${encodeURIComponent(submissionID)}`, {
|
|
9068
|
+
credentials: "include",
|
|
9069
|
+
method: "DELETE"
|
|
9070
|
+
});
|
|
9071
|
+
if (!response.ok) {
|
|
9072
|
+
throw new Error(`Failed to delete submission (${response.status}).`);
|
|
9073
|
+
}
|
|
9074
|
+
const relatedFormID2 = doc ? getFormID3(doc.form) : "";
|
|
9075
|
+
const targetHref = relatedFormID2 ? resolveAdminPath(adminBasePath, `/forms/${relatedFormID2}`) : formsPath;
|
|
9076
|
+
window.location.assign(targetHref);
|
|
9077
|
+
} catch (deleteError) {
|
|
9078
|
+
setError(deleteError instanceof Error ? deleteError.message : "Failed to delete submission.");
|
|
9079
|
+
setDeleting(false);
|
|
9080
|
+
}
|
|
9081
|
+
};
|
|
9082
|
+
if (!submissionID && !didResolvePathFallback) {
|
|
9083
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
9084
|
+
AdminPage,
|
|
9085
|
+
{
|
|
9086
|
+
breadcrumbs: [
|
|
9087
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
9088
|
+
{ label: "Forms", href: formsPath },
|
|
9089
|
+
{ label: "Submission" }
|
|
9090
|
+
],
|
|
9091
|
+
description: "Loading submission workspace...",
|
|
9092
|
+
title: "Submission",
|
|
9093
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_jsx_runtime42.Fragment, {})
|
|
9094
|
+
}
|
|
9095
|
+
) });
|
|
9096
|
+
}
|
|
9097
|
+
const relatedFormID = doc ? getFormID3(doc.form) : "";
|
|
9098
|
+
const formPath = relatedFormID ? resolveAdminPath(adminBasePath, `/forms/${relatedFormID}`) : formsPath;
|
|
9099
|
+
const formTitle = formDoc ? getFormTitle2(formDoc) : getFormTitle2(doc?.formSlug);
|
|
9100
|
+
const uploads = doc ? getUploads2(doc.files) : [];
|
|
9101
|
+
const identity = doc ? getNameAndEmail2(doc.data) : {};
|
|
9102
|
+
const fieldLabels = formDoc ? buildFieldLabelMap2(formDoc) : /* @__PURE__ */ new Map();
|
|
9103
|
+
const previewFields = doc ? getPreviewFields2(doc.data, fieldLabels) : [];
|
|
9104
|
+
const answerEntries = doc && doc.data && typeof doc.data === "object" ? Object.entries(doc.data) : [];
|
|
9105
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
|
|
9106
|
+
AdminPage,
|
|
9107
|
+
{
|
|
9108
|
+
breadcrumbs: [
|
|
9109
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
9110
|
+
{ label: "Forms", href: formsPath },
|
|
9111
|
+
...relatedFormID ? [{ label: formTitle, href: formPath }] : [{ label: formTitle }],
|
|
9112
|
+
{ label: "Submission" }
|
|
9113
|
+
],
|
|
9114
|
+
description: "Review the submitted answers, related files, and linked form details.",
|
|
9115
|
+
title: "Submission",
|
|
9116
|
+
children: [
|
|
9117
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
|
|
9118
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "orion-admin-error", children: error }) : null,
|
|
9119
|
+
!loading && !error && doc && submissionID ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { style: { display: "grid", gap: "1rem" }, children: [
|
|
9120
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-forms-summary-grid", children: [
|
|
9121
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("article", { className: "orion-admin-overview-stat", children: [
|
|
9122
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-overview-stat-label", children: "Submitted" }),
|
|
9123
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: formatDate2(doc.submittedAt) }),
|
|
9124
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { children: "Captured timestamp for this response." })
|
|
9125
|
+
] }),
|
|
9126
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("article", { className: "orion-admin-overview-stat", children: [
|
|
9127
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-overview-stat-label", children: "Uploads" }),
|
|
9128
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: uploads.length }),
|
|
9129
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { children: "Files attached by the submitter." })
|
|
9130
|
+
] }),
|
|
9131
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("article", { className: "orion-admin-overview-stat", children: [
|
|
9132
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-overview-stat-label", children: "Highlighted answers" }),
|
|
9133
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: previewFields.length }),
|
|
9134
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { children: "Readable answer previews from this response." })
|
|
9135
|
+
] })
|
|
9136
|
+
] }),
|
|
9137
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { style: sectionGridStyle2, children: [
|
|
9138
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { style: { display: "grid", gap: "1rem" }, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-card", children: [
|
|
9139
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: "Response details" }),
|
|
9140
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { children: "Formatted answers using the current form field labels when available." }),
|
|
9141
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: answerEntries.length > 0 ? answerEntries.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-form", children: [
|
|
9142
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { children: [
|
|
9143
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: fieldLabels.get(key) || humanizeKey2(key) }),
|
|
9144
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "orion-admin-list-meta", children: key })
|
|
9145
|
+
] }),
|
|
9146
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { children: renderFieldValue(value) })
|
|
9147
|
+
] }, key)) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-empty-state", children: [
|
|
9148
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: "No answers available" }),
|
|
9149
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { children: "This submission does not contain visible response details." })
|
|
9150
|
+
] }) })
|
|
9151
|
+
] }) }),
|
|
9152
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { style: { display: "grid", gap: "1rem" }, children: [
|
|
9153
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-card orion-admin-meta-table", children: [
|
|
9154
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-meta-row", children: [
|
|
9155
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-label", children: "Form" }),
|
|
9156
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-value", children: relatedFormID ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_link5.default, { href: formPath, children: formTitle }) : formTitle })
|
|
9157
|
+
] }),
|
|
9158
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-meta-row", children: [
|
|
9159
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-label", children: "Primary contact" }),
|
|
9160
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-value", children: identity.name || identity.email || "Unknown" })
|
|
9161
|
+
] }),
|
|
9162
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-meta-row", children: [
|
|
9163
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-label", children: "Email" }),
|
|
9164
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-value", children: identity.email || "Not provided" })
|
|
9165
|
+
] }),
|
|
9166
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-meta-row", children: [
|
|
9167
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-label", children: "Submission ID" }),
|
|
9168
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-value", children: submissionID })
|
|
9169
|
+
] }),
|
|
9170
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-meta-row", children: [
|
|
9171
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-label", children: "Form slug" }),
|
|
9172
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-value", children: typeof doc.formSlug === "string" && doc.formSlug.trim().length > 0 ? doc.formSlug : "Unavailable" })
|
|
9173
|
+
] })
|
|
9174
|
+
] }),
|
|
9175
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-card", children: [
|
|
9176
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: "Attached uploads" }),
|
|
9177
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { children: "Files linked to this response remain inside the Studio workspace." }),
|
|
9178
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { style: { display: "grid", gap: "0.75rem", marginTop: "1rem" }, children: uploads.length > 0 ? uploads.map((upload) => {
|
|
9179
|
+
const uploadID = typeof upload.id === "string" || typeof upload.id === "number" ? String(upload.id) : "";
|
|
9180
|
+
if (!uploadID) return null;
|
|
9181
|
+
const uploadPath = resolveAdminPath(adminBasePath, `/forms/uploads/${uploadID}`);
|
|
9182
|
+
const meta = [formatFileSize4(upload.filesize), typeof upload.mimeType === "string" ? upload.mimeType : null].filter(Boolean).join(" \xB7 ");
|
|
9183
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_link5.default, { className: "orion-admin-list-item", href: uploadPath, children: [
|
|
9184
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { children: [
|
|
9185
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: typeof upload.filename === "string" && upload.filename.trim().length > 0 ? upload.filename : `Upload ${uploadID}` }),
|
|
9186
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "orion-admin-list-meta", children: meta || "Open file details" })
|
|
9187
|
+
] }),
|
|
9188
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-action-button orion-admin-action-button--ghost", children: "Open" })
|
|
9189
|
+
] }, uploadID);
|
|
9190
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-empty-state", children: [
|
|
9191
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: "No files attached" }),
|
|
9192
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { children: "This response did not include any uploads." })
|
|
9193
|
+
] }) })
|
|
9194
|
+
] }),
|
|
9195
|
+
confirmDelete ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-form", style: { borderColor: "#b42318" }, children: [
|
|
9196
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { style: { fontWeight: 700, margin: 0 }, children: "Delete this submission?" }),
|
|
9197
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "orion-admin-list-meta", style: { margin: 0 }, children: "This action cannot be undone and will remove the stored response." }),
|
|
9198
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-inline-actions", children: [
|
|
9199
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { disabled: deleting, onClick: deleteSubmission, type: "button", children: deleting ? "Deleting..." : "Yes, Delete" }),
|
|
9200
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { onClick: () => setConfirmDelete(false), type: "button", children: "Cancel" })
|
|
9201
|
+
] })
|
|
9202
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
9203
|
+
"button",
|
|
9204
|
+
{
|
|
9205
|
+
className: "orion-admin-action-button",
|
|
9206
|
+
onClick: () => setConfirmDelete(true),
|
|
9207
|
+
style: { background: "#b42318" },
|
|
9208
|
+
type: "button",
|
|
9209
|
+
children: "Delete Submission"
|
|
9210
|
+
}
|
|
9211
|
+
)
|
|
9212
|
+
] })
|
|
9213
|
+
] })
|
|
9214
|
+
] }) : null
|
|
9215
|
+
]
|
|
9216
|
+
}
|
|
9217
|
+
) });
|
|
9218
|
+
}
|
|
9219
|
+
|
|
9220
|
+
// src/admin/components/studio/AdminStudioFormUploadView.tsx
|
|
9221
|
+
var import_react34 = require("react");
|
|
9222
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
9223
|
+
var previewStyle = {
|
|
9224
|
+
borderRadius: 14,
|
|
9225
|
+
display: "block",
|
|
9226
|
+
maxHeight: "28rem",
|
|
9227
|
+
objectFit: "contain",
|
|
9228
|
+
width: "100%"
|
|
9229
|
+
};
|
|
9230
|
+
function getUploadIDFromPathname(pathname) {
|
|
9231
|
+
return getIDFromPathname(pathname, "/forms/uploads/");
|
|
9232
|
+
}
|
|
9233
|
+
function AdminStudioFormUploadView(props) {
|
|
9234
|
+
const formUploadsCollectionSlug = getPropString14(props, "formUploadsCollectionSlug", "form-uploads");
|
|
9235
|
+
const adminBasePath = useAdminBasePath();
|
|
9236
|
+
const formsPath = resolveAdminPath(adminBasePath, "/forms");
|
|
9237
|
+
const uploadIDFromParams = (0, import_react34.useMemo)(() => getParam3(props.params, "id"), [props.params]);
|
|
9238
|
+
const [uploadID, setUploadID] = (0, import_react34.useState)(uploadIDFromParams);
|
|
9239
|
+
const [didResolvePathFallback, setDidResolvePathFallback] = (0, import_react34.useState)(false);
|
|
9240
|
+
const [doc, setDoc] = (0, import_react34.useState)(null);
|
|
9241
|
+
const [loading, setLoading] = (0, import_react34.useState)(true);
|
|
9242
|
+
const [error, setError] = (0, import_react34.useState)(null);
|
|
9243
|
+
const [savedMessage, setSavedMessage] = (0, import_react34.useState)(null);
|
|
9244
|
+
const [saving, setSaving] = (0, import_react34.useState)(false);
|
|
9245
|
+
const [confirmDelete, setConfirmDelete] = (0, import_react34.useState)(false);
|
|
9246
|
+
const [deleting, setDeleting] = (0, import_react34.useState)(false);
|
|
9247
|
+
(0, import_react34.useEffect)(() => {
|
|
9248
|
+
if (uploadIDFromParams) {
|
|
9249
|
+
setUploadID(uploadIDFromParams);
|
|
9250
|
+
setDidResolvePathFallback(true);
|
|
9251
|
+
return;
|
|
9252
|
+
}
|
|
9253
|
+
if (typeof window !== "undefined") {
|
|
9254
|
+
setUploadID(getUploadIDFromPathname(window.location.pathname));
|
|
9255
|
+
}
|
|
9256
|
+
setDidResolvePathFallback(true);
|
|
9257
|
+
}, [uploadIDFromParams]);
|
|
9258
|
+
const loadDoc = async (id) => {
|
|
9259
|
+
setLoading(true);
|
|
9260
|
+
setError(null);
|
|
9261
|
+
try {
|
|
9262
|
+
const response = await fetch(`/api/${formUploadsCollectionSlug}/${encodeURIComponent(id)}?depth=0&draft=true`, {
|
|
9263
|
+
credentials: "include"
|
|
9264
|
+
});
|
|
9265
|
+
if (!response.ok) {
|
|
9266
|
+
throw new Error(`Failed to load upload (${response.status}).`);
|
|
9267
|
+
}
|
|
9268
|
+
const nextDoc = await response.json();
|
|
9269
|
+
setDoc(nextDoc);
|
|
9270
|
+
} catch (loadError) {
|
|
9271
|
+
setError(loadError instanceof Error ? loadError.message : "Failed to load upload.");
|
|
9272
|
+
setDoc(null);
|
|
9273
|
+
} finally {
|
|
9274
|
+
setLoading(false);
|
|
9275
|
+
}
|
|
9276
|
+
};
|
|
9277
|
+
(0, import_react34.useEffect)(() => {
|
|
9278
|
+
if (!uploadID) {
|
|
9279
|
+
return;
|
|
9280
|
+
}
|
|
9281
|
+
void loadDoc(uploadID);
|
|
9282
|
+
}, [formUploadsCollectionSlug, uploadID]);
|
|
9283
|
+
const save = async (event) => {
|
|
9284
|
+
event.preventDefault();
|
|
9285
|
+
if (!uploadID) {
|
|
9286
|
+
return;
|
|
9287
|
+
}
|
|
9288
|
+
setSaving(true);
|
|
9289
|
+
setError(null);
|
|
9290
|
+
setSavedMessage(null);
|
|
9291
|
+
try {
|
|
9292
|
+
const formData = new FormData(event.currentTarget);
|
|
9293
|
+
const alt = String(formData.get("alt") || "").trim();
|
|
9294
|
+
const response = await fetch(`/api/${formUploadsCollectionSlug}/${encodeURIComponent(uploadID)}`, {
|
|
9295
|
+
body: JSON.stringify({ alt }),
|
|
9296
|
+
credentials: "include",
|
|
9297
|
+
headers: {
|
|
9298
|
+
"Content-Type": "application/json"
|
|
9299
|
+
},
|
|
9300
|
+
method: "PATCH"
|
|
9301
|
+
});
|
|
9302
|
+
if (!response.ok) {
|
|
9303
|
+
throw new Error(`Failed to save upload (${response.status}).`);
|
|
9304
|
+
}
|
|
9305
|
+
const nextDoc = await response.json();
|
|
9306
|
+
setDoc(nextDoc);
|
|
9307
|
+
setSavedMessage("Saved.");
|
|
9308
|
+
} catch (saveError) {
|
|
9309
|
+
setError(saveError instanceof Error ? saveError.message : "Failed to save upload.");
|
|
9310
|
+
} finally {
|
|
9311
|
+
setSaving(false);
|
|
9312
|
+
}
|
|
9313
|
+
};
|
|
9314
|
+
const deleteUpload = async () => {
|
|
9315
|
+
if (!uploadID) {
|
|
9316
|
+
return;
|
|
9317
|
+
}
|
|
9318
|
+
setDeleting(true);
|
|
9319
|
+
setError(null);
|
|
9320
|
+
try {
|
|
9321
|
+
const response = await fetch(`/api/${formUploadsCollectionSlug}/${encodeURIComponent(uploadID)}`, {
|
|
9322
|
+
credentials: "include",
|
|
9323
|
+
method: "DELETE"
|
|
9324
|
+
});
|
|
9325
|
+
if (!response.ok) {
|
|
9326
|
+
throw new Error(`Failed to delete upload (${response.status}).`);
|
|
9327
|
+
}
|
|
9328
|
+
window.location.assign(formsPath);
|
|
9329
|
+
} catch (deleteError) {
|
|
9330
|
+
setError(deleteError instanceof Error ? deleteError.message : "Failed to delete upload.");
|
|
9331
|
+
setDeleting(false);
|
|
9332
|
+
}
|
|
9333
|
+
};
|
|
9334
|
+
if (!uploadID && !didResolvePathFallback) {
|
|
9335
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
9336
|
+
AdminPage,
|
|
9337
|
+
{
|
|
9338
|
+
breadcrumbs: [
|
|
9339
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
9340
|
+
{ label: "Forms", href: formsPath },
|
|
9341
|
+
{ label: "Upload" }
|
|
9342
|
+
],
|
|
9343
|
+
description: "Loading upload workspace...",
|
|
9344
|
+
title: "Upload",
|
|
9345
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_jsx_runtime43.Fragment, {})
|
|
9346
|
+
}
|
|
9347
|
+
) });
|
|
9348
|
+
}
|
|
9349
|
+
const filename = doc && typeof doc.filename === "string" && doc.filename.trim().length > 0 ? doc.filename : uploadID ? `Upload ${uploadID}` : "Upload";
|
|
9350
|
+
const mimeType = doc && typeof doc.mimeType === "string" ? doc.mimeType : "";
|
|
9351
|
+
const sourceURL = doc && typeof doc.url === "string" && doc.url.trim().length > 0 ? doc.url : null;
|
|
9352
|
+
const canPreview = Boolean(sourceURL && mimeType.startsWith("image/"));
|
|
9353
|
+
const createdAt = doc?.createdAt ?? doc?.updatedAt;
|
|
9354
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
9355
|
+
AdminPage,
|
|
9356
|
+
{
|
|
9357
|
+
breadcrumbs: [
|
|
9358
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
9359
|
+
{ label: "Forms", href: formsPath },
|
|
9360
|
+
{ label: filename }
|
|
9361
|
+
],
|
|
9362
|
+
description: "Review file metadata, update alt text, and remove private uploads from Studio.",
|
|
9363
|
+
title: "Upload",
|
|
9364
|
+
children: [
|
|
9365
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
|
|
9366
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "orion-admin-error", children: error }) : null,
|
|
9367
|
+
savedMessage ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "orion-admin-success", children: savedMessage }) : null,
|
|
9368
|
+
!loading && !error && doc && uploadID ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-grid", style: { alignItems: "start" }, children: [
|
|
9369
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { style: { display: "grid", gap: "0.8rem" }, children: [
|
|
9370
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "orion-admin-card", children: canPreview && sourceURL ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("img", { alt: filename, src: sourceURL, style: previewStyle }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
|
|
9371
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("strong", { children: "No inline preview" }),
|
|
9372
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { children: mimeType ? `Preview unavailable for ${mimeType}.` : "Preview unavailable for this file." })
|
|
9373
|
+
] }) }),
|
|
9374
|
+
sourceURL ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("a", { className: "orion-admin-action-button", href: sourceURL, rel: "noreferrer", target: "_blank", children: "Open File" }) : null
|
|
9375
|
+
] }),
|
|
9376
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { style: { display: "grid", gap: "0.8rem" }, children: [
|
|
9377
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-card orion-admin-meta-table", children: [
|
|
9378
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-meta-row", children: [
|
|
9379
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-label", children: "Filename" }),
|
|
9380
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-value", children: filename })
|
|
9381
|
+
] }),
|
|
9382
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-meta-row", children: [
|
|
9383
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-label", children: "File size" }),
|
|
9384
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-value", children: formatFileSize4(doc.filesize) || "Unavailable" })
|
|
9385
|
+
] }),
|
|
9386
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-meta-row", children: [
|
|
9387
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-label", children: "Type" }),
|
|
9388
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-value", children: mimeType || "Unavailable" })
|
|
9389
|
+
] }),
|
|
9390
|
+
typeof doc.width === "number" && typeof doc.height === "number" ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-meta-row", children: [
|
|
9391
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-label", children: "Dimensions" }),
|
|
9392
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "orion-admin-meta-value", children: [
|
|
9393
|
+
doc.width,
|
|
9394
|
+
" x ",
|
|
9395
|
+
doc.height,
|
|
9396
|
+
"px"
|
|
9397
|
+
] })
|
|
9398
|
+
] }) : null,
|
|
9399
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-meta-row", children: [
|
|
9400
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-label", children: "Uploaded" }),
|
|
9401
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "orion-admin-meta-value", children: formatDate2(createdAt) })
|
|
9402
|
+
] })
|
|
9403
|
+
] }),
|
|
9404
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("form", { className: "orion-admin-form", onSubmit: save, children: [
|
|
9405
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("strong", { children: "Asset details" }),
|
|
9406
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("label", { children: [
|
|
9407
|
+
"Alt text",
|
|
9408
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("input", { defaultValue: typeof doc.alt === "string" ? doc.alt : "", name: "alt", type: "text" })
|
|
9409
|
+
] }),
|
|
9410
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { disabled: saving, type: "submit", children: saving ? "Saving..." : "Save Upload" })
|
|
9411
|
+
] }),
|
|
9412
|
+
confirmDelete ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-form", style: { borderColor: "#b42318" }, children: [
|
|
9413
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { style: { fontWeight: 700, margin: 0 }, children: "Delete this upload?" }),
|
|
9414
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "orion-admin-list-meta", style: { margin: 0 }, children: "This removes the stored file and any linked submission attachment references." }),
|
|
9415
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "orion-admin-inline-actions", children: [
|
|
9416
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { disabled: deleting, onClick: deleteUpload, type: "button", children: deleting ? "Deleting..." : "Yes, Delete" }),
|
|
9417
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { onClick: () => setConfirmDelete(false), type: "button", children: "Cancel" })
|
|
9418
|
+
] })
|
|
9419
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
9420
|
+
"button",
|
|
9421
|
+
{
|
|
9422
|
+
className: "orion-admin-action-button",
|
|
9423
|
+
onClick: () => setConfirmDelete(true),
|
|
9424
|
+
style: { background: "#b42318" },
|
|
9425
|
+
type: "button",
|
|
9426
|
+
children: "Delete Upload"
|
|
9427
|
+
}
|
|
9428
|
+
)
|
|
9429
|
+
] })
|
|
9430
|
+
] }) : null
|
|
9431
|
+
]
|
|
9432
|
+
}
|
|
9433
|
+
) });
|
|
9434
|
+
}
|
|
9435
|
+
|
|
9436
|
+
// src/admin/components/studio/AdminStudioToolsView.tsx
|
|
9437
|
+
var import_react35 = require("react");
|
|
9438
|
+
var import_ui12 = require("@payloadcms/ui");
|
|
9439
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
9440
|
+
var userRoles = ["admin", "developer", "editor", "client"];
|
|
9441
|
+
var hasAdminAccess3 = (user) => {
|
|
9442
|
+
if (!user || typeof user !== "object") return false;
|
|
9443
|
+
const role = user.role;
|
|
9444
|
+
return typeof role === "string" && (role === "admin" || role === "developer");
|
|
9445
|
+
};
|
|
9446
|
+
var normalizeRole = (value) => userRoles.includes(value) ? value : "editor";
|
|
9447
|
+
function AdminStudioToolsView(props) {
|
|
9448
|
+
const { user } = (0, import_ui12.useAuth)();
|
|
9449
|
+
const adminBasePath = useAdminBasePath();
|
|
9450
|
+
const [docs, setDocs] = (0, import_react35.useState)([]);
|
|
9451
|
+
const [loading, setLoading] = (0, import_react35.useState)(true);
|
|
9452
|
+
const [error, setError] = (0, import_react35.useState)(null);
|
|
9453
|
+
const [savedMessage, setSavedMessage] = (0, import_react35.useState)(null);
|
|
9454
|
+
const [createSubmitting, setCreateSubmitting] = (0, import_react35.useState)(false);
|
|
9455
|
+
const [updatingUserID, setUpdatingUserID] = (0, import_react35.useState)(null);
|
|
9456
|
+
if (!hasAdminAccess3(user)) {
|
|
9457
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
9458
|
+
AdminPage,
|
|
9459
|
+
{
|
|
9460
|
+
breadcrumbs: [
|
|
9461
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
9462
|
+
{ label: "Admin Tools" }
|
|
9463
|
+
],
|
|
9464
|
+
description: "You do not have access to this section.",
|
|
9465
|
+
title: "Admin Tools",
|
|
9466
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "orion-admin-card", children: [
|
|
9467
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("strong", { children: "Access denied" }),
|
|
9468
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { children: "This section is restricted to administrator and developer accounts." })
|
|
9469
|
+
] })
|
|
9470
|
+
}
|
|
9471
|
+
) });
|
|
9472
|
+
}
|
|
9473
|
+
const loadUsers = async () => {
|
|
9474
|
+
setLoading(true);
|
|
9475
|
+
setError(null);
|
|
9476
|
+
try {
|
|
9477
|
+
const params = new URLSearchParams({
|
|
9478
|
+
depth: "0",
|
|
9479
|
+
draft: "true",
|
|
9480
|
+
limit: "200",
|
|
9481
|
+
sort: "email"
|
|
9482
|
+
});
|
|
9483
|
+
const response = await fetch(`/api/users?${params.toString()}`, {
|
|
9484
|
+
credentials: "include"
|
|
9485
|
+
});
|
|
9486
|
+
if (!response.ok) {
|
|
9487
|
+
throw new Error(`Failed to load users (${response.status}).`);
|
|
9488
|
+
}
|
|
9489
|
+
const payload = await response.json();
|
|
9490
|
+
setDocs(Array.isArray(payload.docs) ? payload.docs : []);
|
|
9491
|
+
} catch (loadError) {
|
|
9492
|
+
setError(loadError instanceof Error ? loadError.message : "Failed to load users.");
|
|
9493
|
+
} finally {
|
|
9494
|
+
setLoading(false);
|
|
9495
|
+
}
|
|
9496
|
+
};
|
|
9497
|
+
(0, import_react35.useEffect)(() => {
|
|
9498
|
+
void loadUsers();
|
|
9499
|
+
}, []);
|
|
9500
|
+
const createUser = async (event) => {
|
|
9501
|
+
event.preventDefault();
|
|
9502
|
+
const form = event.currentTarget;
|
|
9503
|
+
setCreateSubmitting(true);
|
|
9504
|
+
setError(null);
|
|
9505
|
+
setSavedMessage(null);
|
|
9506
|
+
try {
|
|
9507
|
+
const formData = new FormData(form);
|
|
9508
|
+
const email = String(formData.get("email") || "").trim();
|
|
9509
|
+
const password = String(formData.get("password") || "");
|
|
9510
|
+
const fullName = String(formData.get("fullName") || "").trim();
|
|
9511
|
+
const role = normalizeRole(String(formData.get("role") || "editor").trim());
|
|
9512
|
+
if (!email || !password) {
|
|
9513
|
+
throw new Error("Email and password are required.");
|
|
9514
|
+
}
|
|
9515
|
+
const response = await fetch("/api/users", {
|
|
9516
|
+
body: JSON.stringify({
|
|
9517
|
+
email,
|
|
8098
9518
|
fullName,
|
|
8099
9519
|
password,
|
|
8100
9520
|
role
|
|
@@ -8108,7 +9528,7 @@ function AdminStudioToolsView(props) {
|
|
|
8108
9528
|
if (!response.ok) {
|
|
8109
9529
|
throw new Error(`Failed to create user (${response.status}).`);
|
|
8110
9530
|
}
|
|
8111
|
-
|
|
9531
|
+
form.reset();
|
|
8112
9532
|
await loadUsers();
|
|
8113
9533
|
setSavedMessage("User created.");
|
|
8114
9534
|
} catch (createError) {
|
|
@@ -8146,7 +9566,7 @@ function AdminStudioToolsView(props) {
|
|
|
8146
9566
|
setUpdatingUserID(null);
|
|
8147
9567
|
}
|
|
8148
9568
|
};
|
|
8149
|
-
return /* @__PURE__ */ (0,
|
|
9569
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
8150
9570
|
AdminPage,
|
|
8151
9571
|
{
|
|
8152
9572
|
breadcrumbs: [
|
|
@@ -8156,53 +9576,44 @@ function AdminStudioToolsView(props) {
|
|
|
8156
9576
|
description: "Manage users and fallback links to Payload native admin.",
|
|
8157
9577
|
title: "Admin Tools",
|
|
8158
9578
|
children: [
|
|
8159
|
-
/* @__PURE__ */ (0,
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
|
|
8163
|
-
/* @__PURE__ */ (0,
|
|
8164
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
|
|
9579
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "orion-admin-error", style: { marginBottom: "1rem" }, children: error }) : null,
|
|
9580
|
+
savedMessage ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "orion-admin-success", style: { marginBottom: "1rem" }, children: savedMessage }) : null,
|
|
9581
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("form", { className: "orion-admin-form", onSubmit: createUser, style: { marginBottom: "1rem" }, children: [
|
|
9582
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("strong", { children: "Create User" }),
|
|
9583
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { children: [
|
|
8165
9584
|
"Email",
|
|
8166
|
-
/* @__PURE__ */ (0,
|
|
9585
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("input", { name: "email", required: true, type: "email" })
|
|
8167
9586
|
] }),
|
|
8168
|
-
/* @__PURE__ */ (0,
|
|
9587
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { children: [
|
|
8169
9588
|
"Full Name",
|
|
8170
|
-
/* @__PURE__ */ (0,
|
|
9589
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("input", { name: "fullName", type: "text" })
|
|
8171
9590
|
] }),
|
|
8172
|
-
/* @__PURE__ */ (0,
|
|
9591
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { children: [
|
|
8173
9592
|
"Password",
|
|
8174
|
-
/* @__PURE__ */ (0,
|
|
9593
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("input", { name: "password", required: true, type: "password" })
|
|
8175
9594
|
] }),
|
|
8176
|
-
/* @__PURE__ */ (0,
|
|
9595
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("label", { children: [
|
|
8177
9596
|
"Role",
|
|
8178
|
-
/* @__PURE__ */ (0,
|
|
8179
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("option", { value: "admin", children: "admin" }),
|
|
8180
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("option", { value: "editor", children: "editor" }),
|
|
8181
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("option", { value: "client", children: "client" })
|
|
8182
|
-
] })
|
|
9597
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("select", { defaultValue: "editor", name: "role", children: userRoles.map((role) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: role, children: role }, role)) })
|
|
8183
9598
|
] }),
|
|
8184
|
-
/* @__PURE__ */ (0,
|
|
9599
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { disabled: createSubmitting, type: "submit", children: createSubmitting ? "Creating..." : "Create User" })
|
|
8185
9600
|
] }),
|
|
8186
|
-
loading ? /* @__PURE__ */ (0,
|
|
8187
|
-
/* @__PURE__ */ (0,
|
|
9601
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
|
|
9602
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "orion-admin-list", children: docs.map((doc) => {
|
|
8188
9603
|
const id = typeof doc.id === "string" || typeof doc.id === "number" ? String(doc.id) : "";
|
|
8189
9604
|
if (!id) return null;
|
|
8190
9605
|
const email = typeof doc.email === "string" ? doc.email : `user-${id}`;
|
|
8191
9606
|
const fullName = typeof doc.fullName === "string" ? doc.fullName : "";
|
|
8192
9607
|
const currentRole = typeof doc.role === "string" ? normalizeRole(doc.role) : "editor";
|
|
8193
|
-
return /* @__PURE__ */ (0,
|
|
8194
|
-
/* @__PURE__ */ (0,
|
|
8195
|
-
/* @__PURE__ */ (0,
|
|
8196
|
-
/* @__PURE__ */ (0,
|
|
9608
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "orion-admin-list-item", children: [
|
|
9609
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { children: [
|
|
9610
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("strong", { children: email }),
|
|
9611
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "orion-admin-list-meta", children: fullName || "No full name set" })
|
|
8197
9612
|
] }),
|
|
8198
|
-
/* @__PURE__ */ (0,
|
|
8199
|
-
/* @__PURE__ */ (0,
|
|
8200
|
-
/* @__PURE__ */ (0,
|
|
8201
|
-
|
|
8202
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("option", { value: "editor", children: "editor" }),
|
|
8203
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("option", { value: "client", children: "client" })
|
|
8204
|
-
] }),
|
|
8205
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { disabled: updatingUserID === id, type: "submit", children: updatingUserID === id ? "Updating..." : "Update" })
|
|
9613
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("form", { className: "orion-admin-inline-actions", onSubmit: updateUserRole, children: [
|
|
9614
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("input", { name: "id", type: "hidden", value: id }),
|
|
9615
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("select", { defaultValue: currentRole, name: "role", children: userRoles.map((role) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("option", { value: role, children: role }, role)) }),
|
|
9616
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { disabled: updatingUserID === id, type: "submit", children: updatingUserID === id ? "Updating..." : "Update" })
|
|
8206
9617
|
] })
|
|
8207
9618
|
] }, id);
|
|
8208
9619
|
}) })
|
|
@@ -8213,14 +9624,14 @@ function AdminStudioToolsView(props) {
|
|
|
8213
9624
|
|
|
8214
9625
|
// src/admin/components/studio/OpenInStudioMenuItem.tsx
|
|
8215
9626
|
var import_ui13 = require("@payloadcms/ui");
|
|
8216
|
-
var
|
|
9627
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
8217
9628
|
function OpenInStudioMenuItem({ pagesPathBase = "/pages" }) {
|
|
8218
9629
|
const documentInfo = (0, import_ui13.useDocumentInfo)();
|
|
8219
9630
|
const id = documentInfo?.id;
|
|
8220
9631
|
if (!id) {
|
|
8221
9632
|
return null;
|
|
8222
9633
|
}
|
|
8223
|
-
return /* @__PURE__ */ (0,
|
|
9634
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
8224
9635
|
"a",
|
|
8225
9636
|
{
|
|
8226
9637
|
href: `${pagesPathBase}/${id}`,
|
|
@@ -8239,19 +9650,19 @@ function OpenInStudioMenuItem({ pagesPathBase = "/pages" }) {
|
|
|
8239
9650
|
}
|
|
8240
9651
|
|
|
8241
9652
|
// src/admin/components/studio/PageEditRedirectToStudio.tsx
|
|
8242
|
-
var
|
|
9653
|
+
var import_react36 = require("react");
|
|
8243
9654
|
var import_ui14 = require("@payloadcms/ui");
|
|
8244
|
-
var
|
|
9655
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
8245
9656
|
function PageEditRedirectToStudio({ pagesPathBase = "/pages" }) {
|
|
8246
9657
|
const documentInfo = (0, import_ui14.useDocumentInfo)();
|
|
8247
9658
|
const id = documentInfo?.id;
|
|
8248
|
-
(0,
|
|
9659
|
+
(0, import_react36.useEffect)(() => {
|
|
8249
9660
|
if (!id) {
|
|
8250
9661
|
return;
|
|
8251
9662
|
}
|
|
8252
9663
|
window.location.replace(`${pagesPathBase}/${id}`);
|
|
8253
9664
|
}, [id, pagesPathBase]);
|
|
8254
|
-
return /* @__PURE__ */ (0,
|
|
9665
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
|
|
8255
9666
|
"div",
|
|
8256
9667
|
{
|
|
8257
9668
|
style: {
|
|
@@ -8263,18 +9674,61 @@ function PageEditRedirectToStudio({ pagesPathBase = "/pages" }) {
|
|
|
8263
9674
|
minHeight: "50vh"
|
|
8264
9675
|
},
|
|
8265
9676
|
children: [
|
|
8266
|
-
/* @__PURE__ */ (0,
|
|
8267
|
-
/* @__PURE__ */ (0,
|
|
8268
|
-
id ? /* @__PURE__ */ (0,
|
|
9677
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("h2", { style: { margin: 0 }, children: "Opening Editor..." }),
|
|
9678
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { style: { color: "var(--theme-elevation-600)", margin: 0 }, children: "Redirecting to the custom page editor." }),
|
|
9679
|
+
id ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("a", { href: `${pagesPathBase}/${id}`, children: "Continue to Editor" }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("a", { href: pagesPathBase, children: "Open Pages" })
|
|
8269
9680
|
]
|
|
8270
9681
|
}
|
|
8271
9682
|
);
|
|
8272
9683
|
}
|
|
8273
9684
|
|
|
8274
|
-
// src/admin/components/studio/
|
|
8275
|
-
var
|
|
9685
|
+
// src/admin/components/studio/StudioDocumentRedirect.tsx
|
|
9686
|
+
var import_react37 = require("react");
|
|
8276
9687
|
var import_ui15 = require("@payloadcms/ui");
|
|
8277
|
-
var
|
|
9688
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
9689
|
+
function StudioDocumentRedirect({
|
|
9690
|
+
description = "Redirecting to the Studio view.",
|
|
9691
|
+
emptyHref,
|
|
9692
|
+
emptyLabel = "Open Studio",
|
|
9693
|
+
pathBase = "/forms",
|
|
9694
|
+
title = "Opening Studio..."
|
|
9695
|
+
}) {
|
|
9696
|
+
const adminBasePath = useAdminBasePath();
|
|
9697
|
+
const documentInfo = (0, import_ui15.useDocumentInfo)();
|
|
9698
|
+
const id = documentInfo?.id;
|
|
9699
|
+
const fallbackHref = resolveAdminPath(adminBasePath, emptyHref || pathBase);
|
|
9700
|
+
(0, import_react37.useEffect)(() => {
|
|
9701
|
+
if (!id) {
|
|
9702
|
+
return;
|
|
9703
|
+
}
|
|
9704
|
+
const targetHref = resolveAdminPath(adminBasePath, `${pathBase}/${encodeURIComponent(String(id))}`);
|
|
9705
|
+
window.location.replace(targetHref);
|
|
9706
|
+
}, [adminBasePath, id, pathBase]);
|
|
9707
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
|
|
9708
|
+
"div",
|
|
9709
|
+
{
|
|
9710
|
+
style: {
|
|
9711
|
+
alignItems: "center",
|
|
9712
|
+
display: "flex",
|
|
9713
|
+
flexDirection: "column",
|
|
9714
|
+
gap: "0.75rem",
|
|
9715
|
+
justifyContent: "center",
|
|
9716
|
+
minHeight: "50vh",
|
|
9717
|
+
textAlign: "center"
|
|
9718
|
+
},
|
|
9719
|
+
children: [
|
|
9720
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("h2", { style: { margin: 0 }, children: title }),
|
|
9721
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { style: { color: "var(--theme-elevation-600)", margin: 0 }, children: description }),
|
|
9722
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("a", { href: fallbackHref, children: emptyLabel })
|
|
9723
|
+
]
|
|
9724
|
+
}
|
|
9725
|
+
);
|
|
9726
|
+
}
|
|
9727
|
+
|
|
9728
|
+
// src/admin/components/studio/StudioBackBreadcrumb.tsx
|
|
9729
|
+
var import_react38 = require("react");
|
|
9730
|
+
var import_ui16 = require("@payloadcms/ui");
|
|
9731
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
8278
9732
|
var toTitle = (slug) => slug.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
8279
9733
|
var buildNav = (pathname, adminBasePath) => {
|
|
8280
9734
|
if (pathname.includes("/globals/")) {
|
|
@@ -8319,8 +9773,8 @@ var buildNav = (pathname, adminBasePath) => {
|
|
|
8319
9773
|
};
|
|
8320
9774
|
function StudioBackBreadcrumb() {
|
|
8321
9775
|
const adminBasePath = useAdminBasePath();
|
|
8322
|
-
const [pathname, setPathname] = (0,
|
|
8323
|
-
(0,
|
|
9776
|
+
const [pathname, setPathname] = (0, import_react38.useState)("");
|
|
9777
|
+
(0, import_react38.useEffect)(() => {
|
|
8324
9778
|
const update = () => setPathname(window.location.pathname);
|
|
8325
9779
|
update();
|
|
8326
9780
|
window.addEventListener("popstate", update);
|
|
@@ -8328,13 +9782,13 @@ function StudioBackBreadcrumb() {
|
|
|
8328
9782
|
}, []);
|
|
8329
9783
|
const nav = buildNav(pathname, adminBasePath);
|
|
8330
9784
|
if (!nav) return null;
|
|
8331
|
-
return /* @__PURE__ */ (0,
|
|
9785
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui16.SetStepNav, { nav });
|
|
8332
9786
|
}
|
|
8333
9787
|
|
|
8334
9788
|
// src/admin/components/studio/StudioContactFormRedirect.tsx
|
|
8335
|
-
var
|
|
8336
|
-
var
|
|
8337
|
-
var
|
|
9789
|
+
var import_react39 = require("react");
|
|
9790
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
9791
|
+
var getPropString15 = (props, key, fallback) => {
|
|
8338
9792
|
if (!props || typeof props !== "object") return fallback;
|
|
8339
9793
|
const direct = props[key];
|
|
8340
9794
|
if (typeof direct === "string" && direct.length > 0) return direct;
|
|
@@ -8347,13 +9801,13 @@ var getPropString14 = (props, key, fallback) => {
|
|
|
8347
9801
|
};
|
|
8348
9802
|
function StudioContactFormRedirect(props) {
|
|
8349
9803
|
const adminBasePath = useAdminBasePath();
|
|
8350
|
-
const studioContactFormPath =
|
|
9804
|
+
const studioContactFormPath = getPropString15(props, "studioContactFormPath", "/contact-form");
|
|
8351
9805
|
const targetPath = resolveAdminPath(adminBasePath, studioContactFormPath);
|
|
8352
|
-
(0,
|
|
9806
|
+
(0, import_react39.useEffect)(() => {
|
|
8353
9807
|
if (window.location.pathname === targetPath) return;
|
|
8354
9808
|
window.location.replace(targetPath);
|
|
8355
9809
|
}, [targetPath]);
|
|
8356
|
-
return /* @__PURE__ */ (0,
|
|
9810
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
|
|
8357
9811
|
"div",
|
|
8358
9812
|
{
|
|
8359
9813
|
style: {
|
|
@@ -8366,8 +9820,8 @@ function StudioContactFormRedirect(props) {
|
|
|
8366
9820
|
minHeight: "40vh"
|
|
8367
9821
|
},
|
|
8368
9822
|
children: [
|
|
8369
|
-
/* @__PURE__ */ (0,
|
|
8370
|
-
/* @__PURE__ */ (0,
|
|
9823
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("h2", { style: { margin: 0 }, children: "Opening Contact Form Editor..." }),
|
|
9824
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("a", { href: targetPath, children: "Continue" })
|
|
8371
9825
|
]
|
|
8372
9826
|
}
|
|
8373
9827
|
);
|
|
@@ -8379,6 +9833,9 @@ function StudioContactFormRedirect(props) {
|
|
|
8379
9833
|
AdminStudioContactFormView,
|
|
8380
9834
|
AdminStudioDashboard,
|
|
8381
9835
|
AdminStudioFooterGlobalView,
|
|
9836
|
+
AdminStudioFormDetailView,
|
|
9837
|
+
AdminStudioFormSubmissionView,
|
|
9838
|
+
AdminStudioFormUploadView,
|
|
8382
9839
|
AdminStudioFormsView,
|
|
8383
9840
|
AdminStudioGlobalsView,
|
|
8384
9841
|
AdminStudioHeaderGlobalView,
|
|
@@ -8404,6 +9861,7 @@ function StudioContactFormRedirect(props) {
|
|
|
8404
9861
|
StatusBadge,
|
|
8405
9862
|
StudioBackBreadcrumb,
|
|
8406
9863
|
StudioContactFormRedirect,
|
|
9864
|
+
StudioDocumentRedirect,
|
|
8407
9865
|
StudioSectionLayout,
|
|
8408
9866
|
ThemeProvider,
|
|
8409
9867
|
ThemeSwitcher,
|