@orion-studios/payload-studio 0.6.0-beta.10 → 0.6.0-beta.104
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 +2073 -610
- package/dist/admin/client.mjs +2048 -587
- package/dist/admin/index.d.mts +2 -2
- package/dist/admin/index.d.ts +2 -2
- package/dist/admin/index.js +129 -16
- package/dist/admin/index.mjs +2 -2
- package/dist/admin-app/client.js +2 -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 +316 -3
- package/dist/admin.css +98 -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 +3298 -0
- package/dist/builder-v2/client.mjs +3173 -0
- package/dist/builder-v2/index.d.mts +242 -0
- package/dist/builder-v2/index.d.ts +242 -0
- package/dist/builder-v2/index.js +805 -0
- package/dist/builder-v2/index.mjs +755 -0
- package/dist/builder-v2/styles.css +2365 -0
- package/dist/{chunk-KPIX7OSV.mjs → chunk-3ZKXHSG5.mjs} +2 -4
- package/dist/{chunk-XKUTZ7IU.mjs → chunk-7HME6R2V.mjs} +56 -5
- package/dist/{chunk-PF3EBZXF.mjs → chunk-7ZMXZRBP.mjs} +39 -3
- package/dist/{chunk-WLOPFFN2.mjs → chunk-KHK6RTGC.mjs} +132 -19
- package/dist/{chunk-OTHERBGX.mjs → chunk-ZADL33R6.mjs} +1 -1
- package/dist/{index-CkT_eyhK.d.ts → index-BV0vEGl6.d.ts} +3 -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-Bm2SaC3r.d.mts → index-DLfPOqYA.d.mts} +3 -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 +220 -20
- package/dist/index.mjs +8 -8
- 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 +66 -5
- package/dist/studio-pages/client.js +618 -73
- package/dist/studio-pages/client.mjs +641 -96
- 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 +3 -3
- package/package.json +22 -3
package/dist/admin/client.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
SiteFooterPreview,
|
|
10
10
|
adminNavIcons,
|
|
11
11
|
buildAdminPageLinkOptions
|
|
12
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-3ZKXHSG5.mjs";
|
|
13
13
|
import "../chunk-ROTPP5CU.mjs";
|
|
14
14
|
import {
|
|
15
15
|
BlockPicker,
|
|
@@ -41,17 +41,22 @@ var resolveUploadUrl = (value) => {
|
|
|
41
41
|
var resolveLogoUrl = (settings) => {
|
|
42
42
|
return resolveUploadUrl(settings.logo) || resolveUploadUrl(settings.adminLogo) || resolveUploadUrl(settings.brandLogo) || null;
|
|
43
43
|
};
|
|
44
|
+
var resolveLogoOnDarkUrl = (settings) => {
|
|
45
|
+
return resolveUploadUrl(settings.logoOnDark) || resolveUploadUrl(settings.logoDark) || resolveUploadUrl(settings.adminLogoDark) || resolveUploadUrl(settings.adminLogoOnDark) || resolveUploadUrl(settings.brandLogoDark) || null;
|
|
46
|
+
};
|
|
44
47
|
var cachedBranding = null;
|
|
45
|
-
function useSiteBranding(defaultName, defaultLogoUrl) {
|
|
48
|
+
function useSiteBranding(defaultName, defaultLogoUrl, defaultLogoOnDarkUrl) {
|
|
46
49
|
const [branding, setBranding] = useState(() => {
|
|
47
50
|
if (cachedBranding) {
|
|
48
51
|
return {
|
|
49
52
|
logoUrl: cachedBranding.logoUrl || defaultLogoUrl || null,
|
|
53
|
+
logoOnDarkUrl: cachedBranding.logoOnDarkUrl || defaultLogoOnDarkUrl || null,
|
|
50
54
|
siteName: cachedBranding.siteName || defaultName || null
|
|
51
55
|
};
|
|
52
56
|
}
|
|
53
57
|
return {
|
|
54
58
|
logoUrl: defaultLogoUrl || null,
|
|
59
|
+
logoOnDarkUrl: defaultLogoOnDarkUrl || null,
|
|
55
60
|
siteName: defaultName || null
|
|
56
61
|
};
|
|
57
62
|
});
|
|
@@ -68,9 +73,11 @@ function useSiteBranding(defaultName, defaultLogoUrl) {
|
|
|
68
73
|
if (!record) return;
|
|
69
74
|
const siteName = pickString(record.siteName);
|
|
70
75
|
const logoUrl = resolveLogoUrl(record);
|
|
71
|
-
|
|
76
|
+
const logoOnDarkUrl = resolveLogoOnDarkUrl(record);
|
|
77
|
+
cachedBranding = { logoOnDarkUrl, logoUrl, siteName };
|
|
72
78
|
if (!cancelled) {
|
|
73
79
|
setBranding({
|
|
80
|
+
logoOnDarkUrl: logoOnDarkUrl || defaultLogoOnDarkUrl || null,
|
|
74
81
|
logoUrl: logoUrl || defaultLogoUrl || null,
|
|
75
82
|
siteName: siteName || defaultName || null
|
|
76
83
|
});
|
|
@@ -82,16 +89,20 @@ function useSiteBranding(defaultName, defaultLogoUrl) {
|
|
|
82
89
|
return () => {
|
|
83
90
|
cancelled = true;
|
|
84
91
|
};
|
|
85
|
-
}, [defaultLogoUrl, defaultName]);
|
|
92
|
+
}, [defaultLogoOnDarkUrl, defaultLogoUrl, defaultName]);
|
|
86
93
|
return branding;
|
|
87
94
|
}
|
|
88
95
|
|
|
89
96
|
// src/admin/components/Logo.tsx
|
|
90
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
91
|
-
function Logo({ brandName = "Orion Studio", logoUrl } = {}) {
|
|
92
|
-
const branding = useSiteBranding(brandName, logoUrl);
|
|
97
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
98
|
+
function Logo({ brandName = "Orion Studio", logoOnDarkUrl, logoUrl } = {}) {
|
|
99
|
+
const branding = useSiteBranding(brandName, logoUrl, logoOnDarkUrl);
|
|
93
100
|
const resolvedName = branding.siteName || brandName;
|
|
94
101
|
const resolvedLogo = branding.logoUrl || logoUrl || null;
|
|
102
|
+
const resolvedLogoOnDark = branding.logoOnDarkUrl || logoOnDarkUrl || resolvedLogo || "";
|
|
103
|
+
const hasDarkLogoVariant = Boolean(
|
|
104
|
+
resolvedLogo && resolvedLogoOnDark.trim().length > 0 && resolvedLogoOnDark !== resolvedLogo
|
|
105
|
+
);
|
|
95
106
|
return /* @__PURE__ */ jsxs(
|
|
96
107
|
"div",
|
|
97
108
|
{
|
|
@@ -110,8 +121,6 @@ function Logo({ brandName = "Orion Studio", logoUrl } = {}) {
|
|
|
110
121
|
className: "orion-admin-logo-mark",
|
|
111
122
|
style: {
|
|
112
123
|
alignItems: "center",
|
|
113
|
-
background: "var(--orion-cms-logo-bg, var(--admin-accent, #3b82f6))",
|
|
114
|
-
borderRadius: "var(--orion-cms-logo-radius, var(--admin-radius-md, 8px))",
|
|
115
124
|
display: "flex",
|
|
116
125
|
flexShrink: 0,
|
|
117
126
|
height: 32,
|
|
@@ -119,14 +128,25 @@ function Logo({ brandName = "Orion Studio", logoUrl } = {}) {
|
|
|
119
128
|
overflow: "hidden",
|
|
120
129
|
width: 32
|
|
121
130
|
},
|
|
122
|
-
children: resolvedLogo ? /* @__PURE__ */
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
131
|
+
children: resolvedLogo ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
132
|
+
/* @__PURE__ */ jsx(
|
|
133
|
+
"img",
|
|
134
|
+
{
|
|
135
|
+
alt: `${resolvedName} logo`,
|
|
136
|
+
className: `orion-admin-logo-image orion-admin-logo-image--default${hasDarkLogoVariant ? "" : " is-only-logo"}`,
|
|
137
|
+
src: resolvedLogo
|
|
138
|
+
}
|
|
139
|
+
),
|
|
140
|
+
hasDarkLogoVariant ? /* @__PURE__ */ jsx(
|
|
141
|
+
"img",
|
|
142
|
+
{
|
|
143
|
+
alt: "",
|
|
144
|
+
"aria-hidden": "true",
|
|
145
|
+
className: "orion-admin-logo-image orion-admin-logo-image--dark",
|
|
146
|
+
src: resolvedLogoOnDark
|
|
147
|
+
}
|
|
148
|
+
) : null
|
|
149
|
+
] }) : /* @__PURE__ */ jsxs(
|
|
130
150
|
"svg",
|
|
131
151
|
{
|
|
132
152
|
fill: "none",
|
|
@@ -463,7 +483,7 @@ function useTheme(defaultTheme = "brand-light") {
|
|
|
463
483
|
}
|
|
464
484
|
|
|
465
485
|
// src/admin/components/ThemeSwitcher.tsx
|
|
466
|
-
import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
486
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
467
487
|
var iconSize = 16;
|
|
468
488
|
function SunIcon() {
|
|
469
489
|
return /* @__PURE__ */ jsxs5("svg", { width: iconSize, height: iconSize, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
@@ -603,7 +623,7 @@ function ThemeProvider({
|
|
|
603
623
|
} catch {
|
|
604
624
|
}
|
|
605
625
|
}, [allowThemePreference, defaultTheme]);
|
|
606
|
-
return /* @__PURE__ */ jsx5(
|
|
626
|
+
return /* @__PURE__ */ jsx5(Fragment2, { children });
|
|
607
627
|
}
|
|
608
628
|
|
|
609
629
|
// src/admin/components/HelpTooltip.tsx
|
|
@@ -1333,7 +1353,7 @@ var useAdminBasePath = (fallback = DEFAULT_ADMIN_BASE_PATH) => {
|
|
|
1333
1353
|
};
|
|
1334
1354
|
|
|
1335
1355
|
// src/shared/studioSections.ts
|
|
1336
|
-
var studioRoles = /* @__PURE__ */ new Set(["admin", "editor", "client"]);
|
|
1356
|
+
var studioRoles = /* @__PURE__ */ new Set(["admin", "developer", "editor", "client"]);
|
|
1337
1357
|
var studioIcons = new Set(adminNavIcons);
|
|
1338
1358
|
var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
1339
1359
|
var isAbsoluteExternalURL2 = (value) => /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(value) || value.startsWith("//");
|
|
@@ -1531,7 +1551,7 @@ var buildStudioNavItems = (props, adminBasePath) => {
|
|
|
1531
1551
|
icon: "tools",
|
|
1532
1552
|
label: "Admin Tools",
|
|
1533
1553
|
matchPrefixes: [toolsPath, resolveAdminPath(adminBasePath, "/collections/users")],
|
|
1534
|
-
roles: ["admin"]
|
|
1554
|
+
roles: ["admin", "developer"]
|
|
1535
1555
|
};
|
|
1536
1556
|
const extensionItems = sections.map((section) => ({
|
|
1537
1557
|
href: resolveAdminPath(adminBasePath, section.href),
|
|
@@ -1568,7 +1588,7 @@ var isStudioShellRoute = (pathname, props, adminBasePath) => {
|
|
|
1568
1588
|
};
|
|
1569
1589
|
|
|
1570
1590
|
// src/admin/components/studio/AdminStudioNav.tsx
|
|
1571
|
-
import { Fragment as
|
|
1591
|
+
import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1572
1592
|
var iconSize2 = 18;
|
|
1573
1593
|
function NavIcon({ sectionID }) {
|
|
1574
1594
|
const props = {
|
|
@@ -1726,7 +1746,7 @@ function AdminStudioNav(props) {
|
|
|
1726
1746
|
textAlign: compact ? "center" : "left"
|
|
1727
1747
|
},
|
|
1728
1748
|
children: [
|
|
1729
|
-
!compact ? /* @__PURE__ */ jsxs11(
|
|
1749
|
+
!compact ? /* @__PURE__ */ jsxs11(Fragment3, { children: [
|
|
1730
1750
|
/* @__PURE__ */ jsx12("div", { style: { color: "var(--theme-elevation-700)", fontSize: "0.85rem" }, children: "Signed in as" }),
|
|
1731
1751
|
/* @__PURE__ */ jsx12("div", { style: { fontWeight: 800, marginBottom: "0.55rem" }, children: typeof user?.email === "string" ? user.email : "User" })
|
|
1732
1752
|
] }) : null,
|
|
@@ -1824,9 +1844,9 @@ import { startTransition, useEffect as useEffect7, useMemo as useMemo3, useState
|
|
|
1824
1844
|
import Link from "next/link";
|
|
1825
1845
|
import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1826
1846
|
var SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
1827
|
-
var isRole = (value) => value === "admin" || value === "
|
|
1828
|
-
var canReviewForms = (role) => role === "admin" || role === "editor";
|
|
1829
|
-
var canCreatePages = (role) => role === "admin" || role === "editor";
|
|
1847
|
+
var isRole = (value) => value === "admin" || value === "client" || value === "developer" || value === "editor";
|
|
1848
|
+
var canReviewForms = (role) => role === "admin" || role === "developer" || role === "editor";
|
|
1849
|
+
var canCreatePages = (role) => role === "admin" || role === "developer" || role === "editor";
|
|
1830
1850
|
var canAccess = (role, roles) => {
|
|
1831
1851
|
if (!roles || roles.length === 0) {
|
|
1832
1852
|
return true;
|
|
@@ -2302,7 +2322,7 @@ function AdminStudioDashboardClient({
|
|
|
2302
2322
|
label: "Manage Media",
|
|
2303
2323
|
tone: "ghost"
|
|
2304
2324
|
});
|
|
2305
|
-
if (role === "admin") {
|
|
2325
|
+
if (role === "admin" || role === "developer") {
|
|
2306
2326
|
actions.push({
|
|
2307
2327
|
description: "Manage users, roles, and fallback tools.",
|
|
2308
2328
|
href: toolsPath,
|
|
@@ -2581,7 +2601,7 @@ var buildSectionLinks = (adminBasePath, sections, formsEnabled, globalsBasePath)
|
|
|
2581
2601
|
href: resolveAdminPath2(adminBasePath, "/tools"),
|
|
2582
2602
|
id: "admin-tools",
|
|
2583
2603
|
label: "Admin Tools",
|
|
2584
|
-
roles: ["admin"]
|
|
2604
|
+
roles: ["admin", "developer"]
|
|
2585
2605
|
}
|
|
2586
2606
|
];
|
|
2587
2607
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -2647,15 +2667,16 @@ function AdminStudioDashboard(rawProps) {
|
|
|
2647
2667
|
}
|
|
2648
2668
|
|
|
2649
2669
|
// src/admin/components/studio/AdminStudioPagesListView.tsx
|
|
2650
|
-
import { useEffect as
|
|
2670
|
+
import { useEffect as useEffect9, useMemo as useMemo5, useState as useState10 } from "react";
|
|
2651
2671
|
import Link2 from "next/link";
|
|
2672
|
+
import { usePathname as usePathname3 } from "next/navigation";
|
|
2673
|
+
import { useAuth as useAuth4 } from "@payloadcms/ui";
|
|
2674
|
+
|
|
2675
|
+
// src/admin/components/studio/AdminStudioNewPageView.tsx
|
|
2676
|
+
import { useState as useState8 } from "react";
|
|
2652
2677
|
import { useAuth as useAuth3 } from "@payloadcms/ui";
|
|
2653
2678
|
import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2654
|
-
var
|
|
2655
|
-
if (!user || typeof user !== "object") return false;
|
|
2656
|
-
const role = user.role;
|
|
2657
|
-
return typeof role === "string" && role === "admin";
|
|
2658
|
-
};
|
|
2679
|
+
var pageTemplates = ["standard", "landing", "services", "contact"];
|
|
2659
2680
|
var getPropString3 = (props, key, fallback) => {
|
|
2660
2681
|
if (!props || typeof props !== "object") return fallback;
|
|
2661
2682
|
const direct = props[key];
|
|
@@ -2667,101 +2688,115 @@ var getPropString3 = (props, key, fallback) => {
|
|
|
2667
2688
|
}
|
|
2668
2689
|
return fallback;
|
|
2669
2690
|
};
|
|
2670
|
-
|
|
2691
|
+
var canManagePages = (user) => {
|
|
2692
|
+
if (!user || typeof user !== "object") return false;
|
|
2693
|
+
const role = user.role;
|
|
2694
|
+
return role === "admin" || role === "developer" || role === "editor";
|
|
2695
|
+
};
|
|
2696
|
+
var slugify = (value) => value.toLowerCase().trim().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-");
|
|
2697
|
+
function AdminStudioNewPageView(props) {
|
|
2671
2698
|
const { user } = useAuth3();
|
|
2672
|
-
const pagesCollectionSlug = getPropString3(props, "pagesCollectionSlug", "pages");
|
|
2673
2699
|
const adminBasePath = useAdminBasePath();
|
|
2674
|
-
const
|
|
2675
|
-
const [
|
|
2700
|
+
const pagesCollectionSlug = getPropString3(props, "pagesCollectionSlug", "pages");
|
|
2701
|
+
const [submitting, setSubmitting] = useState8(false);
|
|
2676
2702
|
const [error, setError] = useState8(null);
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
try {
|
|
2693
|
-
const res = await fetch(apiURL, { credentials: "include" });
|
|
2694
|
-
if (!res.ok) {
|
|
2695
|
-
const body = await res.text();
|
|
2696
|
-
throw new Error(body || "Failed to fetch pages");
|
|
2697
|
-
}
|
|
2698
|
-
const data = await res.json();
|
|
2699
|
-
if (!cancelled) {
|
|
2700
|
-
setDocs(Array.isArray(data.docs) ? data.docs : []);
|
|
2701
|
-
}
|
|
2702
|
-
} catch (err) {
|
|
2703
|
-
if (!cancelled) {
|
|
2704
|
-
setError(err instanceof Error ? err.message : "Failed to fetch pages");
|
|
2705
|
-
}
|
|
2706
|
-
} finally {
|
|
2707
|
-
if (!cancelled) {
|
|
2708
|
-
setLoading(false);
|
|
2709
|
-
}
|
|
2703
|
+
if (!canManagePages(user)) {
|
|
2704
|
+
return /* @__PURE__ */ jsx18(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsx18(
|
|
2705
|
+
AdminPage,
|
|
2706
|
+
{
|
|
2707
|
+
breadcrumbs: [
|
|
2708
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
2709
|
+
{ label: "Pages", href: resolveAdminPath(adminBasePath, "/pages") },
|
|
2710
|
+
{ label: "New Page" }
|
|
2711
|
+
],
|
|
2712
|
+
description: "You do not have access to create pages.",
|
|
2713
|
+
title: "New Page",
|
|
2714
|
+
children: /* @__PURE__ */ jsxs15("div", { className: "orion-admin-card", children: [
|
|
2715
|
+
/* @__PURE__ */ jsx18("strong", { children: "Access denied" }),
|
|
2716
|
+
/* @__PURE__ */ jsx18("span", { children: "This section is restricted to administrator, developer, and editor accounts." })
|
|
2717
|
+
] })
|
|
2710
2718
|
}
|
|
2711
|
-
};
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2719
|
+
) });
|
|
2720
|
+
}
|
|
2721
|
+
const createPage = async (event) => {
|
|
2722
|
+
event.preventDefault();
|
|
2723
|
+
setSubmitting(true);
|
|
2724
|
+
setError(null);
|
|
2725
|
+
try {
|
|
2726
|
+
const formData = new FormData(event.currentTarget);
|
|
2727
|
+
const titleValue = String(formData.get("title") || "").trim();
|
|
2728
|
+
const slugValue = String(formData.get("slug") || "").trim();
|
|
2729
|
+
const templateValue = String(formData.get("template") || "standard").trim();
|
|
2730
|
+
const template = pageTemplates.includes(templateValue) ? templateValue : "standard";
|
|
2731
|
+
const title = titleValue || "Untitled Page";
|
|
2732
|
+
const slug = slugValue || slugify(title) || "untitled-page";
|
|
2733
|
+
const response = await fetch(`/api/${pagesCollectionSlug}`, {
|
|
2734
|
+
body: JSON.stringify({
|
|
2735
|
+
_status: "draft",
|
|
2736
|
+
slug,
|
|
2737
|
+
template,
|
|
2738
|
+
title
|
|
2739
|
+
}),
|
|
2740
|
+
credentials: "include",
|
|
2741
|
+
headers: {
|
|
2742
|
+
"Content-Type": "application/json"
|
|
2743
|
+
},
|
|
2744
|
+
method: "POST"
|
|
2745
|
+
});
|
|
2746
|
+
if (!response.ok) {
|
|
2747
|
+
throw new Error(`Failed to create page (${response.status}).`);
|
|
2748
|
+
}
|
|
2749
|
+
const payload = await response.json();
|
|
2750
|
+
const id = typeof payload.id === "string" || typeof payload.id === "number" ? String(payload.id) : "";
|
|
2751
|
+
if (!id) {
|
|
2752
|
+
throw new Error("Page created but no document ID was returned.");
|
|
2753
|
+
}
|
|
2754
|
+
window.location.assign(resolveAdminPath(adminBasePath, `/pages/${id}`));
|
|
2755
|
+
} catch (createError) {
|
|
2756
|
+
setError(createError instanceof Error ? createError.message : "Failed to create page.");
|
|
2757
|
+
} finally {
|
|
2758
|
+
setSubmitting(false);
|
|
2759
|
+
}
|
|
2760
|
+
};
|
|
2761
|
+
return /* @__PURE__ */ jsx18(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsx18(
|
|
2718
2762
|
AdminPage,
|
|
2719
2763
|
{
|
|
2720
|
-
actions: isAdmin(user) ? /* @__PURE__ */ jsx18(Link2, { className: "orion-admin-action-button", href: newPagePath, children: "New Page" }) : null,
|
|
2721
2764
|
breadcrumbs: [
|
|
2722
2765
|
{ label: "Dashboard", href: adminBasePath },
|
|
2723
|
-
{ label: "Pages" }
|
|
2766
|
+
{ label: "Pages", href: resolveAdminPath(adminBasePath, "/pages") },
|
|
2767
|
+
{ label: "New Page" }
|
|
2724
2768
|
],
|
|
2725
|
-
description: "
|
|
2726
|
-
title: "
|
|
2727
|
-
children: [
|
|
2728
|
-
loading ? /* @__PURE__ */ jsx18("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
|
|
2769
|
+
description: "Create a new page and open it in the custom editor.",
|
|
2770
|
+
title: "New Page",
|
|
2771
|
+
children: /* @__PURE__ */ jsxs15("form", { className: "orion-admin-form", onSubmit: createPage, children: [
|
|
2729
2772
|
error ? /* @__PURE__ */ jsx18("div", { className: "orion-admin-error", children: error }) : null,
|
|
2730
|
-
/* @__PURE__ */ jsxs15("
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2773
|
+
/* @__PURE__ */ jsxs15("label", { children: [
|
|
2774
|
+
"Title",
|
|
2775
|
+
/* @__PURE__ */ jsx18("input", { name: "title", placeholder: "Services", required: true, type: "text" })
|
|
2776
|
+
] }),
|
|
2777
|
+
/* @__PURE__ */ jsxs15("label", { children: [
|
|
2778
|
+
"Slug",
|
|
2779
|
+
/* @__PURE__ */ jsx18("input", { name: "slug", placeholder: "services", type: "text" })
|
|
2780
|
+
] }),
|
|
2781
|
+
/* @__PURE__ */ jsxs15("label", { children: [
|
|
2782
|
+
"Template",
|
|
2783
|
+
/* @__PURE__ */ jsxs15("select", { defaultValue: "standard", name: "template", children: [
|
|
2784
|
+
/* @__PURE__ */ jsx18("option", { value: "standard", children: "Standard" }),
|
|
2785
|
+
/* @__PURE__ */ jsx18("option", { value: "landing", children: "Landing" }),
|
|
2786
|
+
/* @__PURE__ */ jsx18("option", { value: "contact", children: "Contact" }),
|
|
2787
|
+
/* @__PURE__ */ jsx18("option", { value: "services", children: "Services" })
|
|
2788
|
+
] })
|
|
2789
|
+
] }),
|
|
2790
|
+
/* @__PURE__ */ jsx18("button", { disabled: submitting, type: "submit", children: submitting ? "Creating..." : "Create Page" })
|
|
2791
|
+
] })
|
|
2747
2792
|
}
|
|
2748
2793
|
) });
|
|
2749
2794
|
}
|
|
2750
2795
|
|
|
2751
2796
|
// src/admin/components/studio/AdminStudioPageEditView.tsx
|
|
2752
|
-
import { useEffect as
|
|
2753
|
-
import { SetStepNav
|
|
2754
|
-
import { Fragment as
|
|
2755
|
-
var isAdmin2 = (user) => {
|
|
2756
|
-
if (!user || typeof user !== "object") return false;
|
|
2757
|
-
const role = user.role;
|
|
2758
|
-
return typeof role === "string" && role === "admin";
|
|
2759
|
-
};
|
|
2760
|
-
var isEditor = (user) => {
|
|
2761
|
-
if (!user || typeof user !== "object") return false;
|
|
2762
|
-
const role = user.role;
|
|
2763
|
-
return typeof role === "string" && role === "editor";
|
|
2764
|
-
};
|
|
2797
|
+
import { useEffect as useEffect8, useMemo as useMemo4, useRef as useRef3, useState as useState9 } from "react";
|
|
2798
|
+
import { SetStepNav } from "@payloadcms/ui";
|
|
2799
|
+
import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2765
2800
|
var getPropString4 = (props, key, fallback) => {
|
|
2766
2801
|
if (!props || typeof props !== "object") return fallback;
|
|
2767
2802
|
const direct = props[key];
|
|
@@ -2789,20 +2824,14 @@ var getPageIDFromPathname = (pathname) => {
|
|
|
2789
2824
|
return pagePart ? decodeURIComponent(pagePart) : null;
|
|
2790
2825
|
};
|
|
2791
2826
|
function AdminStudioPageEditView(props) {
|
|
2792
|
-
const { user } = useAuth4();
|
|
2793
2827
|
const adminBasePath = useAdminBasePath();
|
|
2794
2828
|
const iframeRef = useRef3(null);
|
|
2795
|
-
const [saving, setSaving] = useState9(null);
|
|
2796
|
-
const [dirty, setDirty] = useState9(false);
|
|
2797
|
-
const [hasUnpublishedChanges, setHasUnpublishedChanges] = useState9(false);
|
|
2798
|
-
const [canUndo, setCanUndo] = useState9(false);
|
|
2799
|
-
const [canRedo, setCanRedo] = useState9(false);
|
|
2800
2829
|
const builderBasePath = getPropString4(props, "builderBasePath", "/builder");
|
|
2801
2830
|
const pagesPath = resolveAdminPath(adminBasePath, "/pages");
|
|
2802
|
-
const pageIDFromParams =
|
|
2831
|
+
const pageIDFromParams = useMemo4(() => getParam(props.params, "id"), [props.params]);
|
|
2803
2832
|
const [pageID, setPageID] = useState9(pageIDFromParams);
|
|
2804
2833
|
const [didResolvePathFallback, setDidResolvePathFallback] = useState9(false);
|
|
2805
|
-
|
|
2834
|
+
useEffect8(() => {
|
|
2806
2835
|
if (pageIDFromParams) {
|
|
2807
2836
|
setPageID(pageIDFromParams);
|
|
2808
2837
|
setDidResolvePathFallback(true);
|
|
@@ -2813,98 +2842,8 @@ function AdminStudioPageEditView(props) {
|
|
|
2813
2842
|
}
|
|
2814
2843
|
setDidResolvePathFallback(true);
|
|
2815
2844
|
}, [pageIDFromParams]);
|
|
2816
|
-
const canPublish = isAdmin2(user) || isEditor(user);
|
|
2817
|
-
const refreshUnpublishedState = async (id) => {
|
|
2818
|
-
try {
|
|
2819
|
-
const response = await fetch(
|
|
2820
|
-
`/api/pages/versions?depth=0&limit=25&sort=-updatedAt&where[parent][equals]=${encodeURIComponent(id)}`,
|
|
2821
|
-
{
|
|
2822
|
-
credentials: "include"
|
|
2823
|
-
}
|
|
2824
|
-
);
|
|
2825
|
-
if (!response.ok) {
|
|
2826
|
-
return;
|
|
2827
|
-
}
|
|
2828
|
-
const payload = await response.json();
|
|
2829
|
-
const docs = Array.isArray(payload.docs) ? payload.docs : [];
|
|
2830
|
-
let latestDraft = 0;
|
|
2831
|
-
let latestPublished = 0;
|
|
2832
|
-
docs.forEach((doc) => {
|
|
2833
|
-
const status = doc.version?._status;
|
|
2834
|
-
const millis = typeof doc.updatedAt === "string" ? Date.parse(doc.updatedAt) : Number.NaN;
|
|
2835
|
-
if (!Number.isFinite(millis)) {
|
|
2836
|
-
return;
|
|
2837
|
-
}
|
|
2838
|
-
if (status === "draft") {
|
|
2839
|
-
latestDraft = Math.max(latestDraft, millis);
|
|
2840
|
-
}
|
|
2841
|
-
if (status === "published") {
|
|
2842
|
-
latestPublished = Math.max(latestPublished, millis);
|
|
2843
|
-
}
|
|
2844
|
-
});
|
|
2845
|
-
setHasUnpublishedChanges(latestDraft > 0 && latestDraft >= latestPublished);
|
|
2846
|
-
} catch {
|
|
2847
|
-
}
|
|
2848
|
-
};
|
|
2849
|
-
useEffect9(() => {
|
|
2850
|
-
if (!pageID) {
|
|
2851
|
-
return;
|
|
2852
|
-
}
|
|
2853
|
-
void refreshUnpublishedState(pageID);
|
|
2854
|
-
}, [pageID]);
|
|
2855
|
-
const requestSave = (status) => {
|
|
2856
|
-
const iframe = iframeRef.current;
|
|
2857
|
-
if (!iframe?.contentWindow) {
|
|
2858
|
-
toast.error("Editor is not ready yet. Please try again.");
|
|
2859
|
-
return;
|
|
2860
|
-
}
|
|
2861
|
-
setSaving(status);
|
|
2862
|
-
iframe.contentWindow.postMessage({ source: "payload-visual-builder-parent", type: "save", status }, "*");
|
|
2863
|
-
};
|
|
2864
|
-
const requestHistoryAction = (type) => {
|
|
2865
|
-
const iframe = iframeRef.current;
|
|
2866
|
-
if (!iframe?.contentWindow) {
|
|
2867
|
-
toast.error("Editor is not ready yet. Please try again.");
|
|
2868
|
-
return;
|
|
2869
|
-
}
|
|
2870
|
-
iframe.contentWindow.postMessage({ source: "payload-visual-builder-parent", type }, "*");
|
|
2871
|
-
};
|
|
2872
|
-
useEffect9(() => {
|
|
2873
|
-
const onMessage = (event) => {
|
|
2874
|
-
const data = event.data;
|
|
2875
|
-
if (!data || data.source !== "payload-visual-builder-child" || typeof data.type !== "string") {
|
|
2876
|
-
return;
|
|
2877
|
-
}
|
|
2878
|
-
if (data.type === "dirty-state") {
|
|
2879
|
-
setDirty(Boolean(data.dirty));
|
|
2880
|
-
return;
|
|
2881
|
-
}
|
|
2882
|
-
if (data.type === "history-state") {
|
|
2883
|
-
setCanUndo(Boolean(data.canUndo));
|
|
2884
|
-
setCanRedo(Boolean(data.canRedo));
|
|
2885
|
-
return;
|
|
2886
|
-
}
|
|
2887
|
-
if (data.type === "save-result") {
|
|
2888
|
-
setSaving(null);
|
|
2889
|
-
if (data.ok) {
|
|
2890
|
-
if (data.status === "draft") {
|
|
2891
|
-
setHasUnpublishedChanges(true);
|
|
2892
|
-
} else if (data.status === "published") {
|
|
2893
|
-
setHasUnpublishedChanges(false);
|
|
2894
|
-
} else if (pageID) {
|
|
2895
|
-
void refreshUnpublishedState(pageID);
|
|
2896
|
-
}
|
|
2897
|
-
toast.success(typeof data.message === "string" ? data.message : "Saved.");
|
|
2898
|
-
} else {
|
|
2899
|
-
toast.error(typeof data.message === "string" ? data.message : "Save failed.");
|
|
2900
|
-
}
|
|
2901
|
-
}
|
|
2902
|
-
};
|
|
2903
|
-
window.addEventListener("message", onMessage);
|
|
2904
|
-
return () => window.removeEventListener("message", onMessage);
|
|
2905
|
-
}, []);
|
|
2906
2845
|
if (!pageID && !didResolvePathFallback) {
|
|
2907
|
-
return /* @__PURE__ */ jsx19(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsxs16(
|
|
2846
|
+
return /* @__PURE__ */ jsx19(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsxs16(Fragment4, { children: [
|
|
2908
2847
|
/* @__PURE__ */ jsx19(
|
|
2909
2848
|
SetStepNav,
|
|
2910
2849
|
{
|
|
@@ -2919,7 +2858,7 @@ function AdminStudioPageEditView(props) {
|
|
|
2919
2858
|
] }) });
|
|
2920
2859
|
}
|
|
2921
2860
|
if (!pageID) {
|
|
2922
|
-
return /* @__PURE__ */ jsx19(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsxs16(
|
|
2861
|
+
return /* @__PURE__ */ jsx19(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsxs16(Fragment4, { children: [
|
|
2923
2862
|
/* @__PURE__ */ jsx19(
|
|
2924
2863
|
SetStepNav,
|
|
2925
2864
|
{
|
|
@@ -2933,7 +2872,7 @@ function AdminStudioPageEditView(props) {
|
|
|
2933
2872
|
/* @__PURE__ */ jsx19("p", { style: { color: "var(--theme-elevation-600)" }, children: "Missing page ID." })
|
|
2934
2873
|
] }) });
|
|
2935
2874
|
}
|
|
2936
|
-
return /* @__PURE__ */ jsx19(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsxs16(
|
|
2875
|
+
return /* @__PURE__ */ jsx19(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsxs16(Fragment4, { children: [
|
|
2937
2876
|
/* @__PURE__ */ jsx19(
|
|
2938
2877
|
SetStepNav,
|
|
2939
2878
|
{
|
|
@@ -2943,155 +2882,25 @@ function AdminStudioPageEditView(props) {
|
|
|
2943
2882
|
]
|
|
2944
2883
|
}
|
|
2945
2884
|
),
|
|
2946
|
-
/* @__PURE__ */
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
gap: "0.6rem",
|
|
2956
|
-
justifyContent: "space-between",
|
|
2957
|
-
padding: "0.65rem 0.9rem",
|
|
2958
|
-
position: "sticky",
|
|
2959
|
-
top: 0,
|
|
2960
|
-
zIndex: 20
|
|
2961
|
-
},
|
|
2962
|
-
children: [
|
|
2963
|
-
/* @__PURE__ */ jsxs16("div", { style: { minWidth: 0 }, children: [
|
|
2964
|
-
/* @__PURE__ */ jsx19("div", { style: { fontWeight: 900 }, children: "Page Editor" }),
|
|
2965
|
-
/* @__PURE__ */ jsxs16(
|
|
2966
|
-
"div",
|
|
2967
|
-
{
|
|
2968
|
-
style: {
|
|
2969
|
-
color: "var(--theme-elevation-600)",
|
|
2970
|
-
fontSize: "0.85rem",
|
|
2971
|
-
overflow: "hidden",
|
|
2972
|
-
textOverflow: "ellipsis"
|
|
2973
|
-
},
|
|
2974
|
-
children: [
|
|
2975
|
-
"Editing: ",
|
|
2976
|
-
pageID
|
|
2977
|
-
]
|
|
2978
|
-
}
|
|
2979
|
-
)
|
|
2980
|
-
] }),
|
|
2981
|
-
/* @__PURE__ */ jsxs16("div", { style: { alignItems: "center", display: "flex", gap: "0.5rem" }, children: [
|
|
2982
|
-
/* @__PURE__ */ jsx19("div", { style: { color: dirty ? "var(--theme-elevation-900)" : "var(--theme-elevation-600)", fontSize: "0.85rem", fontWeight: 700 }, children: dirty ? "Unsaved changes" : "All changes saved" }),
|
|
2983
|
-
/* @__PURE__ */ jsx19(
|
|
2984
|
-
"div",
|
|
2985
|
-
{
|
|
2986
|
-
style: {
|
|
2987
|
-
background: hasUnpublishedChanges ? "#fff3cd" : "var(--theme-success-50)",
|
|
2988
|
-
border: `1px solid ${hasUnpublishedChanges ? "#f0c36d" : "var(--theme-success-300)"}`,
|
|
2989
|
-
borderRadius: 999,
|
|
2990
|
-
color: hasUnpublishedChanges ? "#6a4a00" : "var(--theme-success-700)",
|
|
2991
|
-
fontSize: "0.75rem",
|
|
2992
|
-
fontWeight: 800,
|
|
2993
|
-
padding: "0.2rem 0.55rem",
|
|
2994
|
-
whiteSpace: "nowrap"
|
|
2995
|
-
},
|
|
2996
|
-
title: hasUnpublishedChanges ? "There are saved draft changes not yet published." : "The live page matches the latest published content.",
|
|
2997
|
-
children: hasUnpublishedChanges ? "Unpublished draft changes" : "Live is up to date"
|
|
2998
|
-
}
|
|
2999
|
-
),
|
|
3000
|
-
/* @__PURE__ */ jsx19(
|
|
3001
|
-
"button",
|
|
3002
|
-
{
|
|
3003
|
-
disabled: !canUndo,
|
|
3004
|
-
onClick: () => requestHistoryAction("undo"),
|
|
3005
|
-
style: {
|
|
3006
|
-
border: "1px solid var(--theme-elevation-300)",
|
|
3007
|
-
borderRadius: 12,
|
|
3008
|
-
cursor: canUndo ? "pointer" : "not-allowed",
|
|
3009
|
-
fontWeight: 800,
|
|
3010
|
-
padding: "0.5rem 0.65rem"
|
|
3011
|
-
},
|
|
3012
|
-
type: "button",
|
|
3013
|
-
children: "Undo"
|
|
3014
|
-
}
|
|
3015
|
-
),
|
|
3016
|
-
/* @__PURE__ */ jsx19(
|
|
3017
|
-
"button",
|
|
3018
|
-
{
|
|
3019
|
-
disabled: !canRedo,
|
|
3020
|
-
onClick: () => requestHistoryAction("redo"),
|
|
3021
|
-
style: {
|
|
3022
|
-
border: "1px solid var(--theme-elevation-300)",
|
|
3023
|
-
borderRadius: 12,
|
|
3024
|
-
cursor: canRedo ? "pointer" : "not-allowed",
|
|
3025
|
-
fontWeight: 800,
|
|
3026
|
-
padding: "0.5rem 0.65rem"
|
|
3027
|
-
},
|
|
3028
|
-
type: "button",
|
|
3029
|
-
children: "Redo"
|
|
3030
|
-
}
|
|
3031
|
-
),
|
|
3032
|
-
/* @__PURE__ */ jsx19(
|
|
3033
|
-
"button",
|
|
3034
|
-
{
|
|
3035
|
-
disabled: saving !== null,
|
|
3036
|
-
onClick: () => requestSave("draft"),
|
|
3037
|
-
style: {
|
|
3038
|
-
border: "1px solid var(--theme-elevation-300)",
|
|
3039
|
-
borderRadius: 12,
|
|
3040
|
-
cursor: saving ? "not-allowed" : "pointer",
|
|
3041
|
-
fontWeight: 800,
|
|
3042
|
-
padding: "0.5rem 0.75rem"
|
|
3043
|
-
},
|
|
3044
|
-
type: "button",
|
|
3045
|
-
children: saving === "draft" ? "Saving\u2026" : "Save Draft"
|
|
3046
|
-
}
|
|
3047
|
-
),
|
|
3048
|
-
/* @__PURE__ */ jsx19(
|
|
3049
|
-
"button",
|
|
3050
|
-
{
|
|
3051
|
-
disabled: !canPublish || saving !== null,
|
|
3052
|
-
onClick: () => requestSave("published"),
|
|
3053
|
-
style: {
|
|
3054
|
-
background: canPublish ? "var(--theme-success-700)" : "var(--theme-elevation-300)",
|
|
3055
|
-
border: "none",
|
|
3056
|
-
borderRadius: 12,
|
|
3057
|
-
color: canPublish ? "var(--theme-elevation-0)" : "var(--theme-elevation-700)",
|
|
3058
|
-
cursor: !canPublish || saving ? "not-allowed" : "pointer",
|
|
3059
|
-
fontWeight: 900,
|
|
3060
|
-
padding: "0.5rem 0.75rem"
|
|
3061
|
-
},
|
|
3062
|
-
type: "button",
|
|
3063
|
-
title: !canPublish ? "You do not have publish permissions." : void 0,
|
|
3064
|
-
children: saving === "published" ? "Publishing\u2026" : "Publish"
|
|
3065
|
-
}
|
|
3066
|
-
)
|
|
3067
|
-
] })
|
|
3068
|
-
]
|
|
3069
|
-
}
|
|
3070
|
-
),
|
|
3071
|
-
/* @__PURE__ */ jsx19(
|
|
3072
|
-
"iframe",
|
|
3073
|
-
{
|
|
3074
|
-
ref: iframeRef,
|
|
3075
|
-
src: `${builderBasePath.replace(/\/$/, "")}/${pageID}`,
|
|
3076
|
-
style: { border: "none", height: "100%", width: "100%" },
|
|
3077
|
-
title: "Page Builder",
|
|
3078
|
-
onLoad: () => {
|
|
3079
|
-
const iframe = iframeRef.current;
|
|
3080
|
-
if (!iframe?.contentWindow) return;
|
|
3081
|
-
iframe.contentWindow.postMessage({ source: "payload-visual-builder-parent", type: "dirty-check-request" }, "*");
|
|
3082
|
-
iframe.contentWindow.postMessage({ source: "payload-visual-builder-parent", type: "history-check-request" }, "*");
|
|
3083
|
-
}
|
|
3084
|
-
}
|
|
3085
|
-
)
|
|
3086
|
-
] })
|
|
2885
|
+
/* @__PURE__ */ jsx19("div", { style: { height: "calc(100vh - 80px)" }, children: /* @__PURE__ */ jsx19(
|
|
2886
|
+
"iframe",
|
|
2887
|
+
{
|
|
2888
|
+
ref: iframeRef,
|
|
2889
|
+
src: `${builderBasePath.replace(/\/$/, "")}/${pageID}`,
|
|
2890
|
+
style: { border: "none", height: "100%", width: "100%" },
|
|
2891
|
+
title: "Page Builder"
|
|
2892
|
+
}
|
|
2893
|
+
) })
|
|
3087
2894
|
] }) });
|
|
3088
2895
|
}
|
|
3089
2896
|
|
|
3090
|
-
// src/admin/components/studio/
|
|
3091
|
-
import { useState as useState10 } from "react";
|
|
3092
|
-
import { useAuth as useAuth5 } from "@payloadcms/ui";
|
|
2897
|
+
// src/admin/components/studio/AdminStudioPagesListView.tsx
|
|
3093
2898
|
import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
3094
|
-
var
|
|
2899
|
+
var hasAdminAccess = (user) => {
|
|
2900
|
+
if (!user || typeof user !== "object") return false;
|
|
2901
|
+
const role = user.role;
|
|
2902
|
+
return typeof role === "string" && (role === "admin" || role === "developer");
|
|
2903
|
+
};
|
|
3095
2904
|
var getPropString5 = (props, key, fallback) => {
|
|
3096
2905
|
if (!props || typeof props !== "object") return fallback;
|
|
3097
2906
|
const direct = props[key];
|
|
@@ -3103,107 +2912,98 @@ var getPropString5 = (props, key, fallback) => {
|
|
|
3103
2912
|
}
|
|
3104
2913
|
return fallback;
|
|
3105
2914
|
};
|
|
3106
|
-
|
|
3107
|
-
if (!user || typeof user !== "object") return false;
|
|
3108
|
-
const role = user.role;
|
|
3109
|
-
return role === "admin" || role === "editor";
|
|
3110
|
-
};
|
|
3111
|
-
var slugify = (value) => value.toLowerCase().trim().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-");
|
|
3112
|
-
function AdminStudioNewPageView(props) {
|
|
3113
|
-
const { user } = useAuth5();
|
|
2915
|
+
function AdminStudioPagesListView(props) {
|
|
3114
2916
|
const adminBasePath = useAdminBasePath();
|
|
2917
|
+
const pathname = usePathname3();
|
|
2918
|
+
const pagesPath = resolveAdminPath(adminBasePath, "/pages");
|
|
2919
|
+
const nestedPagePath = pathname && pathname.startsWith(`${pagesPath}/`) ? pathname.slice(`${pagesPath}/`.length).split("/")[0] : "";
|
|
2920
|
+
if (nestedPagePath === "new") {
|
|
2921
|
+
return /* @__PURE__ */ jsx20(AdminStudioNewPageView, { ...props });
|
|
2922
|
+
}
|
|
2923
|
+
if (nestedPagePath) {
|
|
2924
|
+
return /* @__PURE__ */ jsx20(AdminStudioPageEditView, { ...props });
|
|
2925
|
+
}
|
|
2926
|
+
return /* @__PURE__ */ jsx20(AdminStudioPagesIndexView, { ...props, adminBasePath });
|
|
2927
|
+
}
|
|
2928
|
+
function AdminStudioPagesIndexView({
|
|
2929
|
+
adminBasePath,
|
|
2930
|
+
...props
|
|
2931
|
+
}) {
|
|
2932
|
+
const { user } = useAuth4();
|
|
3115
2933
|
const pagesCollectionSlug = getPropString5(props, "pagesCollectionSlug", "pages");
|
|
3116
|
-
const
|
|
2934
|
+
const newPagePath = resolveAdminPath(adminBasePath, "/pages/new");
|
|
2935
|
+
const [loading, setLoading] = useState10(true);
|
|
3117
2936
|
const [error, setError] = useState10(null);
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
slug,
|
|
3152
|
-
template,
|
|
3153
|
-
title
|
|
3154
|
-
}),
|
|
3155
|
-
credentials: "include",
|
|
3156
|
-
headers: {
|
|
3157
|
-
"Content-Type": "application/json"
|
|
3158
|
-
},
|
|
3159
|
-
method: "POST"
|
|
3160
|
-
});
|
|
3161
|
-
if (!response.ok) {
|
|
3162
|
-
throw new Error(`Failed to create page (${response.status}).`);
|
|
3163
|
-
}
|
|
3164
|
-
const payload = await response.json();
|
|
3165
|
-
const id = typeof payload.id === "string" || typeof payload.id === "number" ? String(payload.id) : "";
|
|
3166
|
-
if (!id) {
|
|
3167
|
-
throw new Error("Page created but no document ID was returned.");
|
|
2937
|
+
const [docs, setDocs] = useState10([]);
|
|
2938
|
+
const apiURL = useMemo5(() => {
|
|
2939
|
+
const params = new URLSearchParams({
|
|
2940
|
+
depth: "0",
|
|
2941
|
+
limit: "100",
|
|
2942
|
+
sort: "-updatedAt",
|
|
2943
|
+
draft: "true"
|
|
2944
|
+
});
|
|
2945
|
+
return `/api/${pagesCollectionSlug}?${params.toString()}`;
|
|
2946
|
+
}, [pagesCollectionSlug]);
|
|
2947
|
+
useEffect9(() => {
|
|
2948
|
+
let cancelled = false;
|
|
2949
|
+
const run = async () => {
|
|
2950
|
+
setLoading(true);
|
|
2951
|
+
setError(null);
|
|
2952
|
+
try {
|
|
2953
|
+
const res = await fetch(apiURL, { credentials: "include" });
|
|
2954
|
+
if (!res.ok) {
|
|
2955
|
+
const body = await res.text();
|
|
2956
|
+
throw new Error(body || "Failed to fetch pages");
|
|
2957
|
+
}
|
|
2958
|
+
const data = await res.json();
|
|
2959
|
+
if (!cancelled) {
|
|
2960
|
+
setDocs(Array.isArray(data.docs) ? data.docs : []);
|
|
2961
|
+
}
|
|
2962
|
+
} catch (err) {
|
|
2963
|
+
if (!cancelled) {
|
|
2964
|
+
setError(err instanceof Error ? err.message : "Failed to fetch pages");
|
|
2965
|
+
}
|
|
2966
|
+
} finally {
|
|
2967
|
+
if (!cancelled) {
|
|
2968
|
+
setLoading(false);
|
|
2969
|
+
}
|
|
3168
2970
|
}
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
return /* @__PURE__ */ jsx20(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsx20(
|
|
2971
|
+
};
|
|
2972
|
+
void run();
|
|
2973
|
+
return () => {
|
|
2974
|
+
cancelled = true;
|
|
2975
|
+
};
|
|
2976
|
+
}, [apiURL]);
|
|
2977
|
+
return /* @__PURE__ */ jsx20(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsxs17(
|
|
3177
2978
|
AdminPage,
|
|
3178
2979
|
{
|
|
2980
|
+
actions: hasAdminAccess(user) ? /* @__PURE__ */ jsx20(Link2, { className: "orion-admin-action-button", href: newPagePath, children: "New Page" }) : null,
|
|
3179
2981
|
breadcrumbs: [
|
|
3180
2982
|
{ label: "Dashboard", href: adminBasePath },
|
|
3181
|
-
{ label: "Pages"
|
|
3182
|
-
{ label: "New Page" }
|
|
2983
|
+
{ label: "Pages" }
|
|
3183
2984
|
],
|
|
3184
|
-
description: "
|
|
3185
|
-
title: "
|
|
3186
|
-
children:
|
|
2985
|
+
description: "Open a page to edit it in the inline custom builder.",
|
|
2986
|
+
title: "Pages",
|
|
2987
|
+
children: [
|
|
2988
|
+
loading ? /* @__PURE__ */ jsx20("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
|
|
3187
2989
|
error ? /* @__PURE__ */ jsx20("div", { className: "orion-admin-error", children: error }) : null,
|
|
3188
|
-
/* @__PURE__ */ jsxs17("
|
|
3189
|
-
"
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
/* @__PURE__ */ jsx20("button", { disabled: submitting, type: "submit", children: submitting ? "Creating..." : "Create Page" })
|
|
3206
|
-
] })
|
|
2990
|
+
/* @__PURE__ */ jsxs17("div", { className: "orion-admin-list", children: [
|
|
2991
|
+
!loading && !error && docs.length === 0 ? /* @__PURE__ */ jsxs17("div", { className: "orion-admin-card", children: [
|
|
2992
|
+
/* @__PURE__ */ jsx20("strong", { children: "No pages yet" }),
|
|
2993
|
+
/* @__PURE__ */ jsx20("span", { children: "Create the first page to start building content." })
|
|
2994
|
+
] }) : null,
|
|
2995
|
+
docs.map((doc) => {
|
|
2996
|
+
const id = typeof doc.id === "string" || typeof doc.id === "number" ? String(doc.id) : "";
|
|
2997
|
+
if (!id) return null;
|
|
2998
|
+
const title = typeof doc.title === "string" ? doc.title : "Untitled Page";
|
|
2999
|
+
const status = typeof doc._status === "string" ? doc._status : "draft";
|
|
3000
|
+
return /* @__PURE__ */ jsxs17(Link2, { className: "orion-admin-list-item", href: resolveAdminPath(adminBasePath, `/pages/${id}`), children: [
|
|
3001
|
+
/* @__PURE__ */ jsx20("div", { children: /* @__PURE__ */ jsx20("strong", { children: title }) }),
|
|
3002
|
+
/* @__PURE__ */ jsx20("span", { className: "orion-admin-pill", children: status })
|
|
3003
|
+
] }, id);
|
|
3004
|
+
})
|
|
3005
|
+
] })
|
|
3006
|
+
]
|
|
3207
3007
|
}
|
|
3208
3008
|
) });
|
|
3209
3009
|
}
|
|
@@ -5143,7 +4943,7 @@ function AdminStudioMediaItemView(props) {
|
|
|
5143
4943
|
// src/admin/components/studio/AdminStudioFormsView.tsx
|
|
5144
4944
|
import Link3 from "next/link";
|
|
5145
4945
|
import { useEffect as useEffect17, useMemo as useMemo13, useState as useState18 } from "react";
|
|
5146
|
-
import { useAuth as
|
|
4946
|
+
import { useAuth as useAuth5 } from "@payloadcms/ui";
|
|
5147
4947
|
import { jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
5148
4948
|
var FORM_TONES = [
|
|
5149
4949
|
{
|
|
@@ -5185,17 +4985,17 @@ var FORM_TONE_OVERRIDES = {
|
|
|
5185
4985
|
var IDENTITY_KEYS = /* @__PURE__ */ new Set(["contactEmail", "email", "firstName", "lastName", "name"]);
|
|
5186
4986
|
var RESPONSE_FIELD_PREVIEW_LIMIT = 3;
|
|
5187
4987
|
var RESPONSE_SCROLL_THRESHOLD = 3;
|
|
5188
|
-
var
|
|
4988
|
+
var hasAdminAccess2 = (user) => {
|
|
5189
4989
|
if (!user || typeof user !== "object") return false;
|
|
5190
4990
|
const role = user.role;
|
|
5191
|
-
return typeof role === "string" && role === "admin";
|
|
4991
|
+
return typeof role === "string" && (role === "admin" || role === "developer");
|
|
5192
4992
|
};
|
|
5193
|
-
var
|
|
4993
|
+
var isEditor = (user) => {
|
|
5194
4994
|
if (!user || typeof user !== "object") return false;
|
|
5195
4995
|
const role = user.role;
|
|
5196
4996
|
return typeof role === "string" && role === "editor";
|
|
5197
4997
|
};
|
|
5198
|
-
var canReviewForms2 = (user) =>
|
|
4998
|
+
var canReviewForms2 = (user) => hasAdminAccess2(user) || isEditor(user);
|
|
5199
4999
|
var getPropString13 = (props, key, fallback) => {
|
|
5200
5000
|
if (!props || typeof props !== "object") return fallback;
|
|
5201
5001
|
const direct = props[key];
|
|
@@ -5361,21 +5161,17 @@ var renderEmptyMessage = (message) => /* @__PURE__ */ jsxs26("div", { className:
|
|
|
5361
5161
|
/* @__PURE__ */ jsx29("span", { children: message })
|
|
5362
5162
|
] });
|
|
5363
5163
|
function AdminStudioFormsView(props) {
|
|
5364
|
-
const { user } =
|
|
5164
|
+
const { user } = useAuth5();
|
|
5365
5165
|
const formsCollectionSlug = getPropString13(props, "formsCollectionSlug", "forms");
|
|
5366
5166
|
const formSubmissionsCollectionSlug = getPropString13(
|
|
5367
5167
|
props,
|
|
5368
5168
|
"formSubmissionsCollectionSlug",
|
|
5369
5169
|
"form-submissions"
|
|
5370
5170
|
);
|
|
5371
|
-
const formUploadsCollectionSlug = getPropString13(props, "formUploadsCollectionSlug", "form-uploads");
|
|
5372
5171
|
const adminBasePath = useAdminBasePath();
|
|
5373
|
-
const
|
|
5374
|
-
const
|
|
5375
|
-
|
|
5376
|
-
`/collections/${formSubmissionsCollectionSlug}`
|
|
5377
|
-
);
|
|
5378
|
-
const rawUploadsPath = resolveAdminPath(adminBasePath, `/collections/${formUploadsCollectionSlug}`);
|
|
5172
|
+
const studioFormsPath = resolveAdminPath(adminBasePath, "/forms");
|
|
5173
|
+
const studioSubmissionsPath = resolveAdminPath(adminBasePath, "/forms/submissions");
|
|
5174
|
+
const studioUploadsPath = resolveAdminPath(adminBasePath, "/forms/uploads");
|
|
5379
5175
|
const [forms, setForms] = useState18([]);
|
|
5380
5176
|
const [submissions, setSubmissions] = useState18([]);
|
|
5381
5177
|
const [loading, setLoading] = useState18(true);
|
|
@@ -5535,7 +5331,7 @@ function AdminStudioFormsView(props) {
|
|
|
5535
5331
|
Link3,
|
|
5536
5332
|
{
|
|
5537
5333
|
className: "orion-admin-action-button orion-admin-action-button--soft",
|
|
5538
|
-
href: `${
|
|
5334
|
+
href: `${studioFormsPath}/${id}`,
|
|
5539
5335
|
children: "Open Form"
|
|
5540
5336
|
}
|
|
5541
5337
|
)
|
|
@@ -5637,7 +5433,7 @@ function AdminStudioFormsView(props) {
|
|
|
5637
5433
|
Link3,
|
|
5638
5434
|
{
|
|
5639
5435
|
className: "orion-admin-upload-chip",
|
|
5640
|
-
href: `${
|
|
5436
|
+
href: `${studioUploadsPath}/${uploadID}`,
|
|
5641
5437
|
children: uploadLabel
|
|
5642
5438
|
},
|
|
5643
5439
|
uploadID
|
|
@@ -5654,7 +5450,7 @@ function AdminStudioFormsView(props) {
|
|
|
5654
5450
|
Link3,
|
|
5655
5451
|
{
|
|
5656
5452
|
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
5657
|
-
href: `${
|
|
5453
|
+
href: `${studioSubmissionsPath}/${submissionID}`,
|
|
5658
5454
|
children: "Open"
|
|
5659
5455
|
}
|
|
5660
5456
|
)
|
|
@@ -5674,77 +5470,1704 @@ function AdminStudioFormsView(props) {
|
|
|
5674
5470
|
) });
|
|
5675
5471
|
}
|
|
5676
5472
|
|
|
5677
|
-
// src/admin/components/studio/
|
|
5678
|
-
import
|
|
5679
|
-
import {
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
var
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5473
|
+
// src/admin/components/studio/AdminStudioFormDetailView.tsx
|
|
5474
|
+
import Link4 from "next/link";
|
|
5475
|
+
import { useEffect as useEffect18, useMemo as useMemo14, useState as useState19 } from "react";
|
|
5476
|
+
|
|
5477
|
+
// src/admin/components/studio/formsStudioShared.ts
|
|
5478
|
+
var FORM_TONES2 = [
|
|
5479
|
+
{
|
|
5480
|
+
accent: "var(--orion-cms-tone-1, var(--orion-cms-accent, var(--orion-admin-accent)))",
|
|
5481
|
+
accentBorder: "color-mix(in srgb, var(--orion-cms-tone-1, var(--orion-cms-accent, var(--orion-admin-accent))) 24%, transparent)",
|
|
5482
|
+
accentMist: "color-mix(in srgb, var(--orion-cms-tone-1, var(--orion-cms-accent, var(--orion-admin-accent))) 12%, transparent)",
|
|
5483
|
+
accentSoft: "color-mix(in srgb, var(--orion-cms-tone-1, var(--orion-cms-accent, var(--orion-admin-accent))) 7%, transparent)"
|
|
5484
|
+
},
|
|
5485
|
+
{
|
|
5486
|
+
accent: "var(--orion-cms-tone-2, var(--brand-secondary, var(--orion-admin-accent)))",
|
|
5487
|
+
accentBorder: "color-mix(in srgb, var(--orion-cms-tone-2, var(--brand-secondary, var(--orion-admin-accent))) 24%, transparent)",
|
|
5488
|
+
accentMist: "color-mix(in srgb, var(--orion-cms-tone-2, var(--brand-secondary, var(--orion-admin-accent))) 13%, transparent)",
|
|
5489
|
+
accentSoft: "color-mix(in srgb, var(--orion-cms-tone-2, var(--brand-secondary, var(--orion-admin-accent))) 8%, transparent)"
|
|
5490
|
+
},
|
|
5491
|
+
{
|
|
5492
|
+
accent: "var(--orion-cms-tone-3, color-mix(in srgb, var(--orion-cms-accent, var(--orion-admin-accent)) 72%, #5f816b))",
|
|
5493
|
+
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)",
|
|
5494
|
+
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)",
|
|
5495
|
+
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)"
|
|
5496
|
+
},
|
|
5497
|
+
{
|
|
5498
|
+
accent: "var(--orion-cms-tone-4, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 72%, #7a652e))",
|
|
5499
|
+
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)",
|
|
5500
|
+
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)",
|
|
5501
|
+
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)"
|
|
5502
|
+
},
|
|
5503
|
+
{
|
|
5504
|
+
accent: "var(--orion-cms-tone-5, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 68%, #8d4a40))",
|
|
5505
|
+
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)",
|
|
5506
|
+
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)",
|
|
5507
|
+
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)"
|
|
5508
|
+
}
|
|
5509
|
+
];
|
|
5510
|
+
var FORM_TONE_OVERRIDES2 = {
|
|
5511
|
+
"basket-request": FORM_TONES2[1],
|
|
5512
|
+
contact: FORM_TONES2[2],
|
|
5513
|
+
"vendor-inquiry": FORM_TONES2[0]
|
|
5686
5514
|
};
|
|
5687
|
-
var
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
const
|
|
5692
|
-
|
|
5693
|
-
const
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
if (!isAdmin4(user)) {
|
|
5698
|
-
return /* @__PURE__ */ jsx30(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsx30(
|
|
5699
|
-
AdminPage,
|
|
5700
|
-
{
|
|
5701
|
-
breadcrumbs: [
|
|
5702
|
-
{ label: "Dashboard", href: adminBasePath },
|
|
5703
|
-
{ label: "Admin Tools" }
|
|
5704
|
-
],
|
|
5705
|
-
description: "You do not have access to this section.",
|
|
5706
|
-
title: "Admin Tools",
|
|
5707
|
-
children: /* @__PURE__ */ jsxs27("div", { className: "orion-admin-card", children: [
|
|
5708
|
-
/* @__PURE__ */ jsx30("strong", { children: "Access denied" }),
|
|
5709
|
-
/* @__PURE__ */ jsx30("span", { children: "This section is restricted to administrator accounts." })
|
|
5710
|
-
] })
|
|
5711
|
-
}
|
|
5712
|
-
) });
|
|
5515
|
+
var IDENTITY_KEYS2 = /* @__PURE__ */ new Set(["contactEmail", "email", "firstName", "lastName", "name"]);
|
|
5516
|
+
var RESPONSE_FIELD_PREVIEW_LIMIT2 = 3;
|
|
5517
|
+
var getPropString14 = (props, key, fallback) => {
|
|
5518
|
+
if (!props || typeof props !== "object") return fallback;
|
|
5519
|
+
const direct = props[key];
|
|
5520
|
+
if (typeof direct === "string" && direct.length > 0) return direct;
|
|
5521
|
+
const clientProps = props.clientProps;
|
|
5522
|
+
if (clientProps && typeof clientProps === "object") {
|
|
5523
|
+
const nested = clientProps[key];
|
|
5524
|
+
if (typeof nested === "string" && nested.length > 0) return nested;
|
|
5713
5525
|
}
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5526
|
+
return fallback;
|
|
5527
|
+
};
|
|
5528
|
+
var getParam3 = (params, key) => {
|
|
5529
|
+
if (!params || typeof params !== "object") return null;
|
|
5530
|
+
const value = params[key];
|
|
5531
|
+
if (typeof value === "string") return value;
|
|
5532
|
+
if (Array.isArray(value) && typeof value[0] === "string") return value[0];
|
|
5533
|
+
return null;
|
|
5534
|
+
};
|
|
5535
|
+
var getIDFromPathname = (pathname, marker) => {
|
|
5536
|
+
const markerIndex = pathname.indexOf(marker);
|
|
5537
|
+
if (markerIndex < 0) return null;
|
|
5538
|
+
const id = pathname.slice(markerIndex + marker.length).split("/")[0];
|
|
5539
|
+
return id ? decodeURIComponent(id) : null;
|
|
5540
|
+
};
|
|
5541
|
+
var formatDate2 = (value) => {
|
|
5542
|
+
if (typeof value !== "string" || value.length === 0) return "Unknown date";
|
|
5543
|
+
const date = new Date(value);
|
|
5544
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
5545
|
+
return date.toLocaleString();
|
|
5546
|
+
};
|
|
5547
|
+
var formatFileSize2 = (value) => {
|
|
5548
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return null;
|
|
5549
|
+
if (value < 1024) return `${value} B`;
|
|
5550
|
+
if (value < 1024 * 1024) return `${(value / 1024).toFixed(1)} KB`;
|
|
5551
|
+
return `${(value / (1024 * 1024)).toFixed(1)} MB`;
|
|
5552
|
+
};
|
|
5553
|
+
var getFieldCount2 = (form) => Array.isArray(form.steps) ? form.steps.reduce((count, step) => {
|
|
5554
|
+
if (!step || typeof step !== "object") return count;
|
|
5555
|
+
const fields = step.fields;
|
|
5556
|
+
return count + (Array.isArray(fields) ? fields.length : 0);
|
|
5557
|
+
}, 0) : 0;
|
|
5558
|
+
var getFormID3 = (value) => {
|
|
5559
|
+
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
5560
|
+
if (value && typeof value === "object") {
|
|
5561
|
+
const id = value.id;
|
|
5562
|
+
if (typeof id === "string" || typeof id === "number") return String(id);
|
|
5563
|
+
}
|
|
5564
|
+
return "";
|
|
5565
|
+
};
|
|
5566
|
+
var getUploads2 = (value) => Array.isArray(value) ? value.map((entry) => {
|
|
5567
|
+
if (typeof entry === "string" || typeof entry === "number") {
|
|
5568
|
+
return { id: entry };
|
|
5569
|
+
}
|
|
5570
|
+
return entry && typeof entry === "object" ? entry : null;
|
|
5571
|
+
}).filter((entry) => Boolean(entry)) : [];
|
|
5572
|
+
var getNameAndEmail2 = (data) => {
|
|
5573
|
+
if (!data || typeof data !== "object") return {};
|
|
5574
|
+
const record = data;
|
|
5575
|
+
const email = typeof record.email === "string" ? record.email : typeof record.contactEmail === "string" ? record.contactEmail : void 0;
|
|
5576
|
+
const firstName = typeof record.firstName === "string" ? record.firstName : void 0;
|
|
5577
|
+
const lastName = typeof record.lastName === "string" ? record.lastName : void 0;
|
|
5578
|
+
const fallbackName = typeof record.name === "string" ? record.name : void 0;
|
|
5579
|
+
const joinedName = [firstName, lastName].filter(Boolean).join(" ").trim();
|
|
5580
|
+
return {
|
|
5581
|
+
...email ? { email } : {},
|
|
5582
|
+
...joinedName ? { name: joinedName } : fallbackName ? { name: fallbackName } : {}
|
|
5737
5583
|
};
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
const
|
|
5742
|
-
|
|
5743
|
-
|
|
5584
|
+
};
|
|
5585
|
+
var humanizeKey2 = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim().replace(/^./, (char) => char.toUpperCase());
|
|
5586
|
+
var buildFieldLabelMap2 = (form) => {
|
|
5587
|
+
const labels = /* @__PURE__ */ new Map();
|
|
5588
|
+
for (const step of Array.isArray(form.steps) ? form.steps : []) {
|
|
5589
|
+
const fields = step && typeof step === "object" ? step.fields : null;
|
|
5590
|
+
for (const field of Array.isArray(fields) ? fields : []) {
|
|
5591
|
+
const name = field && typeof field === "object" && typeof field.name === "string" ? field.name.trim() : "";
|
|
5592
|
+
const label = field && typeof field === "object" && typeof field.label === "string" ? field.label.trim() : "";
|
|
5593
|
+
if (name) {
|
|
5594
|
+
labels.set(name, label || humanizeKey2(name));
|
|
5595
|
+
}
|
|
5596
|
+
}
|
|
5597
|
+
}
|
|
5598
|
+
return labels;
|
|
5599
|
+
};
|
|
5600
|
+
var truncateText2 = (value, maxLength = 64) => {
|
|
5601
|
+
const normalized = value.replace(/\s+/g, " ").trim();
|
|
5602
|
+
if (normalized.length <= maxLength) return normalized;
|
|
5603
|
+
return `${normalized.slice(0, maxLength - 1).trimEnd()}...`;
|
|
5604
|
+
};
|
|
5605
|
+
var formatPreviewValue2 = (value) => {
|
|
5606
|
+
if (value === null || value === void 0) return null;
|
|
5607
|
+
if (typeof value === "boolean") return value ? "Yes" : "No";
|
|
5608
|
+
if (typeof value === "number") return String(value);
|
|
5609
|
+
if (typeof value === "string") {
|
|
5610
|
+
const trimmed = value.trim();
|
|
5611
|
+
return trimmed ? truncateText2(trimmed, 72) : null;
|
|
5612
|
+
}
|
|
5613
|
+
if (Array.isArray(value)) {
|
|
5614
|
+
const joined = value.map((entry) => String(entry).trim()).filter(Boolean).join(", ");
|
|
5615
|
+
return joined ? truncateText2(joined, 72) : null;
|
|
5616
|
+
}
|
|
5617
|
+
if (typeof value === "object") {
|
|
5618
|
+
return truncateText2(JSON.stringify(value), 72);
|
|
5619
|
+
}
|
|
5620
|
+
return truncateText2(String(value), 72);
|
|
5621
|
+
};
|
|
5622
|
+
var getPreviewFields2 = (data, fieldLabels) => {
|
|
5623
|
+
if (!data || typeof data !== "object") return [];
|
|
5624
|
+
return Object.entries(data).filter(([key]) => !IDENTITY_KEYS2.has(key)).map(([key, value]) => {
|
|
5625
|
+
const formatted = formatPreviewValue2(value);
|
|
5626
|
+
if (!formatted) return null;
|
|
5627
|
+
return {
|
|
5628
|
+
label: fieldLabels.get(key) || humanizeKey2(key),
|
|
5629
|
+
value: formatted
|
|
5630
|
+
};
|
|
5631
|
+
}).filter((entry) => Boolean(entry)).slice(0, RESPONSE_FIELD_PREVIEW_LIMIT2);
|
|
5632
|
+
};
|
|
5633
|
+
var getInitials2 = (...values) => {
|
|
5634
|
+
const source = values.find((value) => typeof value === "string" && value.trim().length > 0);
|
|
5635
|
+
if (!source) return "FM";
|
|
5636
|
+
const cleaned = source.replace(/[^a-z0-9]+/gi, " ").trim();
|
|
5637
|
+
if (!cleaned) return "FM";
|
|
5638
|
+
const parts = cleaned.split(/\s+/).filter(Boolean);
|
|
5639
|
+
if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
|
|
5640
|
+
return `${parts[0][0] || ""}${parts[1][0] || ""}`.toUpperCase();
|
|
5641
|
+
};
|
|
5642
|
+
var getHash2 = (value) => {
|
|
5643
|
+
let hash = 0;
|
|
5644
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
5645
|
+
hash = hash * 31 + value.charCodeAt(index) >>> 0;
|
|
5646
|
+
}
|
|
5647
|
+
return hash;
|
|
5648
|
+
};
|
|
5649
|
+
var normalizeToneKey2 = (value) => value?.trim().toLowerCase() || "";
|
|
5650
|
+
var getFormTone2 = (slug, fallbackSeed) => {
|
|
5651
|
+
const normalizedSlug = normalizeToneKey2(slug);
|
|
5652
|
+
if (normalizedSlug && FORM_TONE_OVERRIDES2[normalizedSlug]) {
|
|
5653
|
+
return FORM_TONE_OVERRIDES2[normalizedSlug];
|
|
5654
|
+
}
|
|
5655
|
+
const normalizedSeed = normalizeToneKey2(fallbackSeed);
|
|
5656
|
+
if (normalizedSeed && FORM_TONE_OVERRIDES2[normalizedSeed]) {
|
|
5657
|
+
return FORM_TONE_OVERRIDES2[normalizedSeed];
|
|
5658
|
+
}
|
|
5659
|
+
return FORM_TONES2[getHash2(slug || fallbackSeed) % FORM_TONES2.length];
|
|
5660
|
+
};
|
|
5661
|
+
var getFormToneStyle2 = (slug, fallbackSeed) => {
|
|
5662
|
+
const tone = getFormTone2(slug, fallbackSeed);
|
|
5663
|
+
return {
|
|
5664
|
+
["--form-accent"]: tone.accent,
|
|
5665
|
+
["--form-accent-border"]: tone.accentBorder,
|
|
5666
|
+
["--form-accent-mist"]: tone.accentMist,
|
|
5667
|
+
["--form-accent-soft"]: tone.accentSoft
|
|
5668
|
+
};
|
|
5669
|
+
};
|
|
5670
|
+
var getFormTitle2 = (value) => {
|
|
5671
|
+
if (value && typeof value === "object" && typeof value.title === "string") {
|
|
5672
|
+
const title = value.title.trim();
|
|
5673
|
+
if (title.length > 0) return title;
|
|
5674
|
+
}
|
|
5675
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
5676
|
+
return value;
|
|
5677
|
+
}
|
|
5678
|
+
return "Untitled Form";
|
|
5679
|
+
};
|
|
5680
|
+
|
|
5681
|
+
// src/admin/components/studio/AdminStudioFormDetailView.tsx
|
|
5682
|
+
import { Fragment as Fragment5, jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
5683
|
+
var getNonEmptyText = (value, fallback = "") => typeof value === "string" && value.trim().length > 0 ? value : fallback;
|
|
5684
|
+
var normalizeSteps = (value) => {
|
|
5685
|
+
if (!Array.isArray(value)) {
|
|
5686
|
+
return [];
|
|
5687
|
+
}
|
|
5688
|
+
return value.map((step) => step && typeof step === "object" && !Array.isArray(step) ? step : {});
|
|
5689
|
+
};
|
|
5690
|
+
var normalizeFormResponse = (value) => {
|
|
5691
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
5692
|
+
return {};
|
|
5693
|
+
}
|
|
5694
|
+
const record = value;
|
|
5695
|
+
const nestedDoc = record.doc;
|
|
5696
|
+
if (nestedDoc && typeof nestedDoc === "object" && !Array.isArray(nestedDoc)) {
|
|
5697
|
+
return nestedDoc;
|
|
5698
|
+
}
|
|
5699
|
+
return record;
|
|
5700
|
+
};
|
|
5701
|
+
var toEditorState = (doc) => {
|
|
5702
|
+
const emails = doc.emails && typeof doc.emails === "object" ? doc.emails : null;
|
|
5703
|
+
const adminRecipients = Array.isArray(emails?.adminRecipients) ? emails?.adminRecipients.map(
|
|
5704
|
+
(entry) => entry && typeof entry === "object" && typeof entry.email === "string" ? entry.email.trim() : ""
|
|
5705
|
+
).filter(Boolean) : [];
|
|
5706
|
+
return {
|
|
5707
|
+
adminRecipientsText: adminRecipients.join("\n"),
|
|
5708
|
+
adminSubject: getNonEmptyText(emails?.adminSubject),
|
|
5709
|
+
confirmationHeading: getNonEmptyText(emails?.confirmationHeading),
|
|
5710
|
+
confirmationMessage: getNonEmptyText(emails?.confirmationMessage),
|
|
5711
|
+
confirmationSubject: getNonEmptyText(emails?.confirmationSubject),
|
|
5712
|
+
sendAdmin: emails?.sendAdmin !== false,
|
|
5713
|
+
sendConfirmation: emails?.sendConfirmation !== false,
|
|
5714
|
+
slug: getNonEmptyText(doc.slug),
|
|
5715
|
+
steps: normalizeSteps(doc.steps),
|
|
5716
|
+
submitLabel: getNonEmptyText(doc.submitLabel, "Submit"),
|
|
5717
|
+
successMessage: getNonEmptyText(doc.successMessage),
|
|
5718
|
+
title: getNonEmptyText(doc.title, "Untitled Form")
|
|
5719
|
+
};
|
|
5720
|
+
};
|
|
5721
|
+
var checkboxLabelStyle = {
|
|
5722
|
+
alignItems: "center",
|
|
5723
|
+
display: "flex",
|
|
5724
|
+
gap: "0.6rem"
|
|
5725
|
+
};
|
|
5726
|
+
var sectionGridStyle = {
|
|
5727
|
+
display: "grid",
|
|
5728
|
+
gap: "1rem",
|
|
5729
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))"
|
|
5730
|
+
};
|
|
5731
|
+
var fieldTypeOptions = [
|
|
5732
|
+
"text",
|
|
5733
|
+
"textarea",
|
|
5734
|
+
"email",
|
|
5735
|
+
"phone",
|
|
5736
|
+
"url",
|
|
5737
|
+
"select",
|
|
5738
|
+
"radio",
|
|
5739
|
+
"checkbox",
|
|
5740
|
+
"checkbox-group",
|
|
5741
|
+
"date",
|
|
5742
|
+
"file"
|
|
5743
|
+
];
|
|
5744
|
+
var getFields = (step) => Array.isArray(step.fields) ? step.fields.map(
|
|
5745
|
+
(field) => field && typeof field === "object" && !Array.isArray(field) ? field : {}
|
|
5746
|
+
) : [];
|
|
5747
|
+
var toOptionsText = (value) => Array.isArray(value) ? value.map((entry) => {
|
|
5748
|
+
if (entry && typeof entry === "object" && !Array.isArray(entry)) {
|
|
5749
|
+
const record = entry;
|
|
5750
|
+
const label = typeof record.label === "string" ? record.label : "";
|
|
5751
|
+
const optionValue = typeof record.value === "string" ? record.value : label;
|
|
5752
|
+
return label && optionValue && label !== optionValue ? `${label} | ${optionValue}` : label || optionValue;
|
|
5753
|
+
}
|
|
5754
|
+
return typeof entry === "string" ? entry : "";
|
|
5755
|
+
}).filter(Boolean).join("\n") : "";
|
|
5756
|
+
var fromOptionsText = (value) => value.split("\n").map((entry) => entry.trim()).filter(Boolean).map((entry) => {
|
|
5757
|
+
const [label, optionValue] = entry.split("|").map((part) => part.trim());
|
|
5758
|
+
return {
|
|
5759
|
+
label,
|
|
5760
|
+
value: optionValue || label
|
|
5761
|
+
};
|
|
5762
|
+
});
|
|
5763
|
+
var slugifyFieldName = (value) => value.trim().replace(/[^a-z0-9]+/gi, " ").trim().replace(/\s+([a-z0-9])/gi, (_, char) => char.toUpperCase()).replace(/^./, (char) => char.toLowerCase());
|
|
5764
|
+
var blankField = () => ({
|
|
5765
|
+
label: "New field",
|
|
5766
|
+
name: "newField",
|
|
5767
|
+
required: false,
|
|
5768
|
+
type: "text"
|
|
5769
|
+
});
|
|
5770
|
+
var blankStep = () => ({
|
|
5771
|
+
fields: [blankField()],
|
|
5772
|
+
title: "New step"
|
|
5773
|
+
});
|
|
5774
|
+
var getStepTitle = (step, stepIndex) => getNonEmptyText(step.title, `Step ${stepIndex + 1}`);
|
|
5775
|
+
var getFieldLabel = (field, fieldIndex) => getNonEmptyText(field.label, getNonEmptyText(field.name, `Field ${fieldIndex + 1}`));
|
|
5776
|
+
var formatFieldTypeLabel = (value) => getNonEmptyText(value, "text").replace(/-/g, " ").replace(/^./, (char) => char.toUpperCase());
|
|
5777
|
+
var getStepDestination = (stepIndex, stepCount) => {
|
|
5778
|
+
if (stepIndex < stepCount - 1) {
|
|
5779
|
+
return `Next: Step ${stepIndex + 2}`;
|
|
5780
|
+
}
|
|
5781
|
+
return "Then: Submit form";
|
|
5782
|
+
};
|
|
5783
|
+
var moveItem = (items, fromIndex, toIndex) => {
|
|
5784
|
+
if (toIndex < 0 || toIndex >= items.length) {
|
|
5785
|
+
return items;
|
|
5786
|
+
}
|
|
5787
|
+
const nextItems = [...items];
|
|
5788
|
+
const [item] = nextItems.splice(fromIndex, 1);
|
|
5789
|
+
nextItems.splice(toIndex, 0, item);
|
|
5790
|
+
return nextItems;
|
|
5791
|
+
};
|
|
5792
|
+
function getFormIDFromPathname(pathname) {
|
|
5793
|
+
const marker = "/forms/";
|
|
5794
|
+
const raw = getIDFromPathname(pathname, marker);
|
|
5795
|
+
if (!raw || raw === "submissions" || raw === "uploads") {
|
|
5796
|
+
return null;
|
|
5797
|
+
}
|
|
5798
|
+
return raw;
|
|
5799
|
+
}
|
|
5800
|
+
function AdminStudioFormDetailView(props) {
|
|
5801
|
+
const formsCollectionSlug = getPropString14(props, "formsCollectionSlug", "forms");
|
|
5802
|
+
const formSubmissionsCollectionSlug = getPropString14(
|
|
5803
|
+
props,
|
|
5804
|
+
"formSubmissionsCollectionSlug",
|
|
5805
|
+
"form-submissions"
|
|
5806
|
+
);
|
|
5807
|
+
const adminBasePath = useAdminBasePath();
|
|
5808
|
+
const formsPath = resolveAdminPath(adminBasePath, "/forms");
|
|
5809
|
+
const formIDFromParams = useMemo14(() => getParam3(props.params, "id"), [props.params]);
|
|
5810
|
+
const [formID, setFormID] = useState19(formIDFromParams);
|
|
5811
|
+
const [didResolvePathFallback, setDidResolvePathFallback] = useState19(false);
|
|
5812
|
+
const [doc, setDoc] = useState19(null);
|
|
5813
|
+
const [submissions, setSubmissions] = useState19([]);
|
|
5814
|
+
const [editorState, setEditorState] = useState19(null);
|
|
5815
|
+
const [loading, setLoading] = useState19(true);
|
|
5816
|
+
const [error, setError] = useState19(null);
|
|
5817
|
+
const [saving, setSaving] = useState19(false);
|
|
5818
|
+
const [savedMessage, setSavedMessage] = useState19(null);
|
|
5819
|
+
useEffect18(() => {
|
|
5820
|
+
if (formIDFromParams) {
|
|
5821
|
+
setFormID(formIDFromParams);
|
|
5822
|
+
setDidResolvePathFallback(true);
|
|
5823
|
+
return;
|
|
5824
|
+
}
|
|
5825
|
+
if (typeof window !== "undefined") {
|
|
5826
|
+
setFormID(getFormIDFromPathname(window.location.pathname));
|
|
5827
|
+
}
|
|
5828
|
+
setDidResolvePathFallback(true);
|
|
5829
|
+
}, [formIDFromParams]);
|
|
5830
|
+
const loadDoc = async (id) => {
|
|
5831
|
+
setLoading(true);
|
|
5832
|
+
setError(null);
|
|
5833
|
+
try {
|
|
5834
|
+
const submissionsParams = new URLSearchParams({
|
|
5835
|
+
depth: "1",
|
|
5836
|
+
limit: "25",
|
|
5837
|
+
sort: "-submittedAt"
|
|
5838
|
+
});
|
|
5839
|
+
submissionsParams.set("where[form][equals]", id);
|
|
5840
|
+
const [formResponse, submissionsResponse] = await Promise.all([
|
|
5841
|
+
fetch(`/api/${formsCollectionSlug}/${encodeURIComponent(id)}?depth=0&draft=true`, {
|
|
5842
|
+
credentials: "include"
|
|
5843
|
+
}),
|
|
5844
|
+
fetch(`/api/${formSubmissionsCollectionSlug}?${submissionsParams.toString()}`, {
|
|
5845
|
+
credentials: "include"
|
|
5846
|
+
})
|
|
5847
|
+
]);
|
|
5848
|
+
if (!formResponse.ok) {
|
|
5849
|
+
throw new Error(`Failed to load form (${formResponse.status}).`);
|
|
5850
|
+
}
|
|
5851
|
+
if (!submissionsResponse.ok) {
|
|
5852
|
+
throw new Error(`Failed to load submissions (${submissionsResponse.status}).`);
|
|
5853
|
+
}
|
|
5854
|
+
const nextDoc = normalizeFormResponse(await formResponse.json());
|
|
5855
|
+
const submissionsPayload = await submissionsResponse.json();
|
|
5856
|
+
const nextSubmissions = Array.isArray(submissionsPayload.docs) ? submissionsPayload.docs : [];
|
|
5857
|
+
setDoc(nextDoc);
|
|
5858
|
+
setEditorState(toEditorState(nextDoc));
|
|
5859
|
+
setSubmissions(nextSubmissions);
|
|
5860
|
+
} catch (loadError) {
|
|
5861
|
+
setError(loadError instanceof Error ? loadError.message : "Failed to load form.");
|
|
5862
|
+
setDoc(null);
|
|
5863
|
+
setEditorState(null);
|
|
5864
|
+
setSubmissions([]);
|
|
5865
|
+
} finally {
|
|
5866
|
+
setLoading(false);
|
|
5867
|
+
}
|
|
5868
|
+
};
|
|
5869
|
+
useEffect18(() => {
|
|
5870
|
+
if (!formID) {
|
|
5871
|
+
return;
|
|
5872
|
+
}
|
|
5873
|
+
void loadDoc(formID);
|
|
5874
|
+
}, [formID, formsCollectionSlug, formSubmissionsCollectionSlug]);
|
|
5875
|
+
const save = async (event) => {
|
|
5876
|
+
event.preventDefault();
|
|
5877
|
+
if (!formID || !editorState) {
|
|
5878
|
+
return;
|
|
5879
|
+
}
|
|
5880
|
+
setSaving(true);
|
|
5881
|
+
setError(null);
|
|
5882
|
+
setSavedMessage(null);
|
|
5883
|
+
try {
|
|
5884
|
+
const payload = {
|
|
5885
|
+
emails: {
|
|
5886
|
+
adminRecipients: editorState.adminRecipientsText.split("\n").map((value) => value.trim()).filter(Boolean).map((email) => ({ email })),
|
|
5887
|
+
adminSubject: editorState.adminSubject.trim(),
|
|
5888
|
+
confirmationHeading: editorState.confirmationHeading.trim(),
|
|
5889
|
+
confirmationMessage: editorState.confirmationMessage,
|
|
5890
|
+
confirmationSubject: editorState.confirmationSubject.trim(),
|
|
5891
|
+
sendAdmin: editorState.sendAdmin,
|
|
5892
|
+
sendConfirmation: editorState.sendConfirmation
|
|
5893
|
+
},
|
|
5894
|
+
slug: editorState.slug.trim(),
|
|
5895
|
+
steps: editorState.steps,
|
|
5896
|
+
submitLabel: editorState.submitLabel.trim(),
|
|
5897
|
+
successMessage: editorState.successMessage,
|
|
5898
|
+
title: editorState.title.trim()
|
|
5899
|
+
};
|
|
5900
|
+
const response = await fetch(`/api/${formsCollectionSlug}/${encodeURIComponent(formID)}`, {
|
|
5901
|
+
body: JSON.stringify(payload),
|
|
5902
|
+
credentials: "include",
|
|
5903
|
+
headers: {
|
|
5904
|
+
"Content-Type": "application/json"
|
|
5905
|
+
},
|
|
5906
|
+
method: "PATCH"
|
|
5907
|
+
});
|
|
5908
|
+
if (!response.ok) {
|
|
5909
|
+
throw new Error(`Failed to save form (${response.status}).`);
|
|
5910
|
+
}
|
|
5911
|
+
const nextDoc = normalizeFormResponse(await response.json());
|
|
5912
|
+
setDoc(nextDoc);
|
|
5913
|
+
setEditorState(toEditorState(nextDoc));
|
|
5914
|
+
setSavedMessage("Saved.");
|
|
5915
|
+
} catch (saveError) {
|
|
5916
|
+
setError(saveError instanceof Error ? saveError.message : "Failed to save form.");
|
|
5917
|
+
} finally {
|
|
5918
|
+
setSaving(false);
|
|
5919
|
+
}
|
|
5920
|
+
};
|
|
5921
|
+
if (!formID && !didResolvePathFallback) {
|
|
5922
|
+
return /* @__PURE__ */ jsx30(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsx30(
|
|
5923
|
+
AdminPage,
|
|
5924
|
+
{
|
|
5925
|
+
breadcrumbs: [
|
|
5926
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
5927
|
+
{ label: "Forms", href: formsPath },
|
|
5928
|
+
{ label: "Form" }
|
|
5929
|
+
],
|
|
5930
|
+
description: "Loading form workspace...",
|
|
5931
|
+
title: "Form",
|
|
5932
|
+
children: /* @__PURE__ */ jsx30(Fragment5, {})
|
|
5933
|
+
}
|
|
5934
|
+
) });
|
|
5935
|
+
}
|
|
5936
|
+
const title = doc && typeof doc.title === "string" && doc.title.trim().length > 0 ? doc.title : "Form";
|
|
5937
|
+
const slug = doc && typeof doc.slug === "string" ? doc.slug : "";
|
|
5938
|
+
const toneStyle = getFormToneStyle2(slug, title || formID || "form");
|
|
5939
|
+
const fieldLabels = doc ? buildFieldLabelMap2(doc) : /* @__PURE__ */ new Map();
|
|
5940
|
+
const latestSubmission = submissions[0];
|
|
5941
|
+
const stepCount = editorState?.steps.length || 0;
|
|
5942
|
+
const fieldCount = editorState ? editorState.steps.reduce((count, step) => count + getFields(step).length, 0) : doc ? getFieldCount2(doc) : 0;
|
|
5943
|
+
const updateStep = (stepIndex, patch) => {
|
|
5944
|
+
setEditorState(
|
|
5945
|
+
(current) => current ? {
|
|
5946
|
+
...current,
|
|
5947
|
+
steps: current.steps.map(
|
|
5948
|
+
(step, index) => index === stepIndex ? { ...step, ...patch } : step
|
|
5949
|
+
)
|
|
5950
|
+
} : current
|
|
5951
|
+
);
|
|
5952
|
+
};
|
|
5953
|
+
const updateField = (stepIndex, fieldIndex, patch) => {
|
|
5954
|
+
setEditorState((current) => {
|
|
5955
|
+
if (!current) return current;
|
|
5956
|
+
return {
|
|
5957
|
+
...current,
|
|
5958
|
+
steps: current.steps.map((step, index) => {
|
|
5959
|
+
if (index !== stepIndex) return step;
|
|
5960
|
+
const fields = getFields(step).map(
|
|
5961
|
+
(field, currentFieldIndex) => currentFieldIndex === fieldIndex ? { ...field, ...patch } : field
|
|
5962
|
+
);
|
|
5963
|
+
return { ...step, fields };
|
|
5964
|
+
})
|
|
5965
|
+
};
|
|
5966
|
+
});
|
|
5967
|
+
};
|
|
5968
|
+
const moveStep = (stepIndex, direction) => {
|
|
5969
|
+
setEditorState(
|
|
5970
|
+
(current) => current ? {
|
|
5971
|
+
...current,
|
|
5972
|
+
steps: moveItem(current.steps, stepIndex, stepIndex + direction)
|
|
5973
|
+
} : current
|
|
5974
|
+
);
|
|
5975
|
+
};
|
|
5976
|
+
const moveField = (stepIndex, fieldIndex, direction) => {
|
|
5977
|
+
setEditorState((current) => {
|
|
5978
|
+
if (!current) return current;
|
|
5979
|
+
return {
|
|
5980
|
+
...current,
|
|
5981
|
+
steps: current.steps.map(
|
|
5982
|
+
(step, index) => index === stepIndex ? { ...step, fields: moveItem(getFields(step), fieldIndex, fieldIndex + direction) } : step
|
|
5983
|
+
)
|
|
5984
|
+
};
|
|
5985
|
+
});
|
|
5986
|
+
};
|
|
5987
|
+
return /* @__PURE__ */ jsx30(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsxs27(
|
|
5988
|
+
AdminPage,
|
|
5989
|
+
{
|
|
5990
|
+
breadcrumbs: [
|
|
5991
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
5992
|
+
{ label: "Forms", href: formsPath },
|
|
5993
|
+
{ label: title }
|
|
5994
|
+
],
|
|
5995
|
+
description: "Manage form content and review recent responses without leaving Studio.",
|
|
5996
|
+
title: "Form",
|
|
5997
|
+
children: [
|
|
5998
|
+
loading ? /* @__PURE__ */ jsx30("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
|
|
5999
|
+
error ? /* @__PURE__ */ jsx30("div", { className: "orion-admin-error", children: error }) : null,
|
|
6000
|
+
savedMessage ? /* @__PURE__ */ jsx30("div", { className: "orion-admin-success", children: savedMessage }) : null,
|
|
6001
|
+
!loading && !error && doc && editorState && formID ? /* @__PURE__ */ jsxs27("div", { style: { display: "grid", gap: "1rem" }, children: [
|
|
6002
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-forms-summary-grid", children: [
|
|
6003
|
+
/* @__PURE__ */ jsxs27("article", { className: "orion-admin-overview-stat", children: [
|
|
6004
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-overview-stat-label", children: "Workflow steps" }),
|
|
6005
|
+
/* @__PURE__ */ jsx30("strong", { children: stepCount }),
|
|
6006
|
+
/* @__PURE__ */ jsx30("p", { children: "Configured stages in the public form flow." })
|
|
6007
|
+
] }),
|
|
6008
|
+
/* @__PURE__ */ jsxs27("article", { className: "orion-admin-overview-stat", children: [
|
|
6009
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-overview-stat-label", children: "Fields" }),
|
|
6010
|
+
/* @__PURE__ */ jsx30("strong", { children: fieldCount }),
|
|
6011
|
+
/* @__PURE__ */ jsx30("p", { children: "Total visible and conditional fields across every step." })
|
|
6012
|
+
] }),
|
|
6013
|
+
/* @__PURE__ */ jsxs27("article", { className: "orion-admin-overview-stat", children: [
|
|
6014
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-overview-stat-label", children: "Recent submissions" }),
|
|
6015
|
+
/* @__PURE__ */ jsx30("strong", { children: submissions.length }),
|
|
6016
|
+
/* @__PURE__ */ jsx30("p", { children: latestSubmission ? `Latest response ${formatDate2(latestSubmission.submittedAt)}` : "No responses have been recorded yet." })
|
|
6017
|
+
] })
|
|
6018
|
+
] }),
|
|
6019
|
+
/* @__PURE__ */ jsxs27("section", { className: "orion-admin-form-board", style: toneStyle, children: [
|
|
6020
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-form-board-header", children: [
|
|
6021
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-form-board-heading", children: [
|
|
6022
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-form-board-kicker-row", children: [
|
|
6023
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-form-board-kicker", children: slug || "No slug set" }),
|
|
6024
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-form-board-meta", children: doc.updatedAt ? `Updated ${formatDate2(doc.updatedAt)}` : "Update time unavailable" })
|
|
6025
|
+
] }),
|
|
6026
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-form-board-title-row", children: [
|
|
6027
|
+
/* @__PURE__ */ jsx30("div", { className: "orion-admin-form-board-mark", children: getInitials2(title, slug) }),
|
|
6028
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-form-board-copy", children: [
|
|
6029
|
+
/* @__PURE__ */ jsx30("h2", { className: "orion-admin-form-board-title", children: title }),
|
|
6030
|
+
/* @__PURE__ */ jsx30("p", { className: "orion-admin-form-board-subtitle", children: editorState.successMessage.trim().length > 0 ? editorState.successMessage : "No success message set." })
|
|
6031
|
+
] })
|
|
6032
|
+
] })
|
|
6033
|
+
] }),
|
|
6034
|
+
/* @__PURE__ */ jsx30("div", { className: "orion-admin-form-board-actions", children: /* @__PURE__ */ jsxs27("div", { className: "orion-admin-form-board-count", children: [
|
|
6035
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-form-board-count-value", children: submissions.length }),
|
|
6036
|
+
/* @__PURE__ */ jsxs27("span", { className: "orion-admin-form-board-count-label", children: [
|
|
6037
|
+
"response",
|
|
6038
|
+
submissions.length === 1 ? "" : "s"
|
|
6039
|
+
] })
|
|
6040
|
+
] }) })
|
|
6041
|
+
] }),
|
|
6042
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-form-board-metrics", children: [
|
|
6043
|
+
/* @__PURE__ */ jsxs27("article", { className: "orion-admin-form-metric", children: [
|
|
6044
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-form-metric-label", children: "Submit button" }),
|
|
6045
|
+
/* @__PURE__ */ jsx30("strong", { className: "orion-admin-form-metric-value is-copy", children: editorState.submitLabel || "Submit" })
|
|
6046
|
+
] }),
|
|
6047
|
+
/* @__PURE__ */ jsxs27("article", { className: "orion-admin-form-metric", children: [
|
|
6048
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-form-metric-label", children: "Admin notifications" }),
|
|
6049
|
+
/* @__PURE__ */ jsx30("strong", { className: "orion-admin-form-metric-value", children: editorState.sendAdmin ? "On" : "Off" })
|
|
6050
|
+
] }),
|
|
6051
|
+
/* @__PURE__ */ jsxs27("article", { className: "orion-admin-form-metric", children: [
|
|
6052
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-form-metric-label", children: "Confirmation email" }),
|
|
6053
|
+
/* @__PURE__ */ jsx30("strong", { className: "orion-admin-form-metric-value", children: editorState.sendConfirmation ? "On" : "Off" })
|
|
6054
|
+
] }),
|
|
6055
|
+
/* @__PURE__ */ jsxs27("article", { className: "orion-admin-form-metric", children: [
|
|
6056
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-form-metric-label", children: "Latest response" }),
|
|
6057
|
+
/* @__PURE__ */ jsx30("strong", { className: "orion-admin-form-metric-value is-copy", children: latestSubmission ? formatDate2(latestSubmission.submittedAt) : "No activity yet" })
|
|
6058
|
+
] })
|
|
6059
|
+
] })
|
|
6060
|
+
] }),
|
|
6061
|
+
/* @__PURE__ */ jsxs27("div", { style: sectionGridStyle, children: [
|
|
6062
|
+
/* @__PURE__ */ jsxs27("div", { style: { display: "grid", gap: "1rem" }, children: [
|
|
6063
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-card", children: [
|
|
6064
|
+
/* @__PURE__ */ jsx30("strong", { children: "Step preview" }),
|
|
6065
|
+
/* @__PURE__ */ jsx30("span", { children: "Review the public workflow as visitors will move through it." }),
|
|
6066
|
+
/* @__PURE__ */ jsx30("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: editorState.steps.length > 0 ? editorState.steps.map((record, stepIndex) => {
|
|
6067
|
+
const fields = getFields(record);
|
|
6068
|
+
return /* @__PURE__ */ jsxs27("div", { className: "orion-admin-form", children: [
|
|
6069
|
+
/* @__PURE__ */ jsxs27("div", { children: [
|
|
6070
|
+
/* @__PURE__ */ jsxs27("strong", { children: [
|
|
6071
|
+
"Step ",
|
|
6072
|
+
stepIndex + 1,
|
|
6073
|
+
": ",
|
|
6074
|
+
getNonEmptyText(record?.title, "Untitled Step")
|
|
6075
|
+
] }),
|
|
6076
|
+
getNonEmptyText(record?.subtitle) ? /* @__PURE__ */ jsx30("div", { className: "orion-admin-list-meta", style: { marginTop: "0.25rem" }, children: getNonEmptyText(record?.subtitle) }) : null
|
|
6077
|
+
] }),
|
|
6078
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-inline-actions", children: [
|
|
6079
|
+
/* @__PURE__ */ jsxs27("span", { className: "orion-admin-pill", children: [
|
|
6080
|
+
fields.length,
|
|
6081
|
+
" field",
|
|
6082
|
+
fields.length === 1 ? "" : "s"
|
|
6083
|
+
] }),
|
|
6084
|
+
record?.allowSkip === true ? /* @__PURE__ */ jsx30("span", { className: "orion-admin-pill", children: "Can skip" }) : null,
|
|
6085
|
+
getNonEmptyText(record?.nextLabel) ? /* @__PURE__ */ jsxs27("span", { className: "orion-admin-pill", children: [
|
|
6086
|
+
"Next: ",
|
|
6087
|
+
getNonEmptyText(record?.nextLabel)
|
|
6088
|
+
] }) : null
|
|
6089
|
+
] }),
|
|
6090
|
+
fields.length > 0 ? /* @__PURE__ */ jsx30("div", { className: "orion-admin-list", children: fields.map((field, fieldIndex) => {
|
|
6091
|
+
const fieldRecord = field && typeof field === "object" && !Array.isArray(field) ? field : null;
|
|
6092
|
+
const type = getNonEmptyText(fieldRecord?.type, "text");
|
|
6093
|
+
const label = getNonEmptyText(
|
|
6094
|
+
fieldRecord?.label,
|
|
6095
|
+
getNonEmptyText(fieldRecord?.name, `Field ${fieldIndex + 1}`)
|
|
6096
|
+
);
|
|
6097
|
+
const helpText = getNonEmptyText(fieldRecord?.helpText);
|
|
6098
|
+
const condition = fieldRecord?.condition && typeof fieldRecord.condition === "object" && !Array.isArray(fieldRecord.condition) ? fieldRecord.condition : null;
|
|
6099
|
+
return /* @__PURE__ */ jsx30("div", { className: "orion-admin-list-item", children: /* @__PURE__ */ jsxs27("div", { children: [
|
|
6100
|
+
/* @__PURE__ */ jsx30("strong", { children: label }),
|
|
6101
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-list-meta", children: [
|
|
6102
|
+
type,
|
|
6103
|
+
fieldRecord?.required === true ? " \xB7 required" : "",
|
|
6104
|
+
condition?.field && condition?.equals ? ` \xB7 when ${String(condition.field)} = ${String(condition.equals)}` : ""
|
|
6105
|
+
] }),
|
|
6106
|
+
helpText ? /* @__PURE__ */ jsx30(
|
|
6107
|
+
"div",
|
|
6108
|
+
{
|
|
6109
|
+
className: "orion-admin-list-meta",
|
|
6110
|
+
style: { marginTop: "0.25rem" },
|
|
6111
|
+
children: helpText
|
|
6112
|
+
}
|
|
6113
|
+
) : null
|
|
6114
|
+
] }) }, `field-${fieldIndex}`);
|
|
6115
|
+
}) }) : /* @__PURE__ */ jsx30("div", { className: "orion-admin-list-meta", children: "This step has no fields." })
|
|
6116
|
+
] }, `step-${stepIndex}`);
|
|
6117
|
+
}) : /* @__PURE__ */ jsxs27("div", { className: "orion-admin-empty-state", children: [
|
|
6118
|
+
/* @__PURE__ */ jsx30("strong", { children: "No steps configured" }),
|
|
6119
|
+
/* @__PURE__ */ jsx30("span", { children: "Add at least one step in Form settings to publish this form." })
|
|
6120
|
+
] }) })
|
|
6121
|
+
] }),
|
|
6122
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-card", children: [
|
|
6123
|
+
/* @__PURE__ */ jsx30("strong", { children: "Recent submissions" }),
|
|
6124
|
+
/* @__PURE__ */ jsx30("span", { children: "Jump from the form definition into the latest responses." }),
|
|
6125
|
+
/* @__PURE__ */ jsx30("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: submissions.length > 0 ? submissions.map((submission) => {
|
|
6126
|
+
const submissionID = typeof submission.id === "string" || typeof submission.id === "number" ? String(submission.id) : "";
|
|
6127
|
+
if (!submissionID) return null;
|
|
6128
|
+
const identity = getNameAndEmail2(submission.data);
|
|
6129
|
+
const previewFields = getPreviewFields2(submission.data, fieldLabels);
|
|
6130
|
+
const formSubmissionPath = resolveAdminPath(
|
|
6131
|
+
adminBasePath,
|
|
6132
|
+
`/forms/submissions/${submissionID}`
|
|
6133
|
+
);
|
|
6134
|
+
return /* @__PURE__ */ jsxs27(Link4, { className: "orion-admin-list-item", href: formSubmissionPath, children: [
|
|
6135
|
+
/* @__PURE__ */ jsxs27("div", { children: [
|
|
6136
|
+
/* @__PURE__ */ jsx30("strong", { children: identity.name || identity.email || "Submission" }),
|
|
6137
|
+
/* @__PURE__ */ jsx30("div", { className: "orion-admin-list-meta", children: formatDate2(submission.submittedAt) }),
|
|
6138
|
+
previewFields.length > 0 ? /* @__PURE__ */ jsx30("div", { className: "orion-admin-list-meta", style: { marginTop: "0.3rem" }, children: previewFields.map((field) => `${field.label}: ${field.value}`).join(" \xB7 ") }) : null
|
|
6139
|
+
] }),
|
|
6140
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-action-button orion-admin-action-button--ghost", children: "Open" })
|
|
6141
|
+
] }, submissionID);
|
|
6142
|
+
}) : /* @__PURE__ */ jsxs27("div", { className: "orion-admin-empty-state", children: [
|
|
6143
|
+
/* @__PURE__ */ jsx30("strong", { children: "No responses yet" }),
|
|
6144
|
+
/* @__PURE__ */ jsx30("span", { children: "This view will populate as soon as the form starts receiving traffic." })
|
|
6145
|
+
] }) })
|
|
6146
|
+
] })
|
|
6147
|
+
] }),
|
|
6148
|
+
/* @__PURE__ */ jsxs27("form", { className: "orion-admin-form", onSubmit: save, children: [
|
|
6149
|
+
/* @__PURE__ */ jsx30("strong", { children: "Form settings" }),
|
|
6150
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6151
|
+
"Title",
|
|
6152
|
+
/* @__PURE__ */ jsx30(
|
|
6153
|
+
"input",
|
|
6154
|
+
{
|
|
6155
|
+
onChange: (event) => setEditorState(
|
|
6156
|
+
(current) => current ? { ...current, title: event.target.value } : current
|
|
6157
|
+
),
|
|
6158
|
+
required: true,
|
|
6159
|
+
type: "text",
|
|
6160
|
+
value: editorState.title
|
|
6161
|
+
}
|
|
6162
|
+
)
|
|
6163
|
+
] }),
|
|
6164
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6165
|
+
"Slug",
|
|
6166
|
+
/* @__PURE__ */ jsx30(
|
|
6167
|
+
"input",
|
|
6168
|
+
{
|
|
6169
|
+
onChange: (event) => setEditorState(
|
|
6170
|
+
(current) => current ? { ...current, slug: event.target.value } : current
|
|
6171
|
+
),
|
|
6172
|
+
required: true,
|
|
6173
|
+
type: "text",
|
|
6174
|
+
value: editorState.slug
|
|
6175
|
+
}
|
|
6176
|
+
)
|
|
6177
|
+
] }),
|
|
6178
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6179
|
+
"Submit button",
|
|
6180
|
+
/* @__PURE__ */ jsx30(
|
|
6181
|
+
"input",
|
|
6182
|
+
{
|
|
6183
|
+
onChange: (event) => setEditorState(
|
|
6184
|
+
(current) => current ? { ...current, submitLabel: event.target.value } : current
|
|
6185
|
+
),
|
|
6186
|
+
type: "text",
|
|
6187
|
+
value: editorState.submitLabel
|
|
6188
|
+
}
|
|
6189
|
+
)
|
|
6190
|
+
] }),
|
|
6191
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6192
|
+
"Success message",
|
|
6193
|
+
/* @__PURE__ */ jsx30(
|
|
6194
|
+
"textarea",
|
|
6195
|
+
{
|
|
6196
|
+
onChange: (event) => setEditorState(
|
|
6197
|
+
(current) => current ? { ...current, successMessage: event.target.value } : current
|
|
6198
|
+
),
|
|
6199
|
+
rows: 4,
|
|
6200
|
+
value: editorState.successMessage
|
|
6201
|
+
}
|
|
6202
|
+
)
|
|
6203
|
+
] }),
|
|
6204
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-card", children: [
|
|
6205
|
+
/* @__PURE__ */ jsx30("strong", { children: "Email behavior" }),
|
|
6206
|
+
/* @__PURE__ */ jsxs27("div", { style: { display: "grid", gap: "0.85rem", marginTop: "0.9rem" }, children: [
|
|
6207
|
+
/* @__PURE__ */ jsxs27("label", { style: checkboxLabelStyle, children: [
|
|
6208
|
+
/* @__PURE__ */ jsx30(
|
|
6209
|
+
"input",
|
|
6210
|
+
{
|
|
6211
|
+
checked: editorState.sendAdmin,
|
|
6212
|
+
onChange: (event) => setEditorState(
|
|
6213
|
+
(current) => current ? { ...current, sendAdmin: event.target.checked } : current
|
|
6214
|
+
),
|
|
6215
|
+
type: "checkbox"
|
|
6216
|
+
}
|
|
6217
|
+
),
|
|
6218
|
+
"Send admin notifications"
|
|
6219
|
+
] }),
|
|
6220
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6221
|
+
"Admin recipients",
|
|
6222
|
+
/* @__PURE__ */ jsx30(
|
|
6223
|
+
"textarea",
|
|
6224
|
+
{
|
|
6225
|
+
onChange: (event) => setEditorState(
|
|
6226
|
+
(current) => current ? { ...current, adminRecipientsText: event.target.value } : current
|
|
6227
|
+
),
|
|
6228
|
+
placeholder: "one@email.com\ntwo@email.com",
|
|
6229
|
+
rows: 4,
|
|
6230
|
+
value: editorState.adminRecipientsText
|
|
6231
|
+
}
|
|
6232
|
+
)
|
|
6233
|
+
] }),
|
|
6234
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6235
|
+
"Admin subject",
|
|
6236
|
+
/* @__PURE__ */ jsx30(
|
|
6237
|
+
"input",
|
|
6238
|
+
{
|
|
6239
|
+
onChange: (event) => setEditorState(
|
|
6240
|
+
(current) => current ? { ...current, adminSubject: event.target.value } : current
|
|
6241
|
+
),
|
|
6242
|
+
type: "text",
|
|
6243
|
+
value: editorState.adminSubject
|
|
6244
|
+
}
|
|
6245
|
+
)
|
|
6246
|
+
] }),
|
|
6247
|
+
/* @__PURE__ */ jsxs27("label", { style: checkboxLabelStyle, children: [
|
|
6248
|
+
/* @__PURE__ */ jsx30(
|
|
6249
|
+
"input",
|
|
6250
|
+
{
|
|
6251
|
+
checked: editorState.sendConfirmation,
|
|
6252
|
+
onChange: (event) => setEditorState(
|
|
6253
|
+
(current) => current ? { ...current, sendConfirmation: event.target.checked } : current
|
|
6254
|
+
),
|
|
6255
|
+
type: "checkbox"
|
|
6256
|
+
}
|
|
6257
|
+
),
|
|
6258
|
+
"Send confirmation email"
|
|
6259
|
+
] }),
|
|
6260
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6261
|
+
"Confirmation subject",
|
|
6262
|
+
/* @__PURE__ */ jsx30(
|
|
6263
|
+
"input",
|
|
6264
|
+
{
|
|
6265
|
+
onChange: (event) => setEditorState(
|
|
6266
|
+
(current) => current ? { ...current, confirmationSubject: event.target.value } : current
|
|
6267
|
+
),
|
|
6268
|
+
type: "text",
|
|
6269
|
+
value: editorState.confirmationSubject
|
|
6270
|
+
}
|
|
6271
|
+
)
|
|
6272
|
+
] }),
|
|
6273
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6274
|
+
"Confirmation heading",
|
|
6275
|
+
/* @__PURE__ */ jsx30(
|
|
6276
|
+
"input",
|
|
6277
|
+
{
|
|
6278
|
+
onChange: (event) => setEditorState(
|
|
6279
|
+
(current) => current ? { ...current, confirmationHeading: event.target.value } : current
|
|
6280
|
+
),
|
|
6281
|
+
type: "text",
|
|
6282
|
+
value: editorState.confirmationHeading
|
|
6283
|
+
}
|
|
6284
|
+
)
|
|
6285
|
+
] }),
|
|
6286
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6287
|
+
"Confirmation message",
|
|
6288
|
+
/* @__PURE__ */ jsx30(
|
|
6289
|
+
"textarea",
|
|
6290
|
+
{
|
|
6291
|
+
onChange: (event) => setEditorState(
|
|
6292
|
+
(current) => current ? { ...current, confirmationMessage: event.target.value } : current
|
|
6293
|
+
),
|
|
6294
|
+
rows: 4,
|
|
6295
|
+
value: editorState.confirmationMessage
|
|
6296
|
+
}
|
|
6297
|
+
)
|
|
6298
|
+
] })
|
|
6299
|
+
] })
|
|
6300
|
+
] }),
|
|
6301
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-card orion-admin-workflow-editor", children: [
|
|
6302
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-workflow-editor-header", children: [
|
|
6303
|
+
/* @__PURE__ */ jsxs27("div", { children: [
|
|
6304
|
+
/* @__PURE__ */ jsx30("strong", { children: "Form steps" }),
|
|
6305
|
+
/* @__PURE__ */ jsx30("span", { children: "Build the visitor flow, then edit each step's fields below." })
|
|
6306
|
+
] }),
|
|
6307
|
+
/* @__PURE__ */ jsx30(
|
|
6308
|
+
"button",
|
|
6309
|
+
{
|
|
6310
|
+
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
6311
|
+
onClick: () => setEditorState(
|
|
6312
|
+
(current) => current ? { ...current, steps: [...current.steps, blankStep()] } : current
|
|
6313
|
+
),
|
|
6314
|
+
type: "button",
|
|
6315
|
+
children: "Add step"
|
|
6316
|
+
}
|
|
6317
|
+
)
|
|
6318
|
+
] }),
|
|
6319
|
+
editorState.steps.length === 0 ? /* @__PURE__ */ jsxs27("div", { className: "orion-admin-empty-state", children: [
|
|
6320
|
+
/* @__PURE__ */ jsx30("strong", { children: "No steps configured" }),
|
|
6321
|
+
/* @__PURE__ */ jsx30("span", { children: "Add a first step to start building the public form flow." })
|
|
6322
|
+
] }) : null,
|
|
6323
|
+
/* @__PURE__ */ jsx30("div", { className: "orion-admin-step-editor-list", children: editorState.steps.map((step, stepIndex) => {
|
|
6324
|
+
const fields = getFields(step);
|
|
6325
|
+
const requiredCount = fields.filter((field) => field.required === true).length;
|
|
6326
|
+
return /* @__PURE__ */ jsxs27("details", { className: "orion-admin-step-editor", open: true, children: [
|
|
6327
|
+
/* @__PURE__ */ jsxs27("summary", { className: "orion-admin-step-editor-summary", children: [
|
|
6328
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-workflow-node-number", children: stepIndex + 1 }),
|
|
6329
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-step-editor-title", children: getStepTitle(step, stepIndex) }),
|
|
6330
|
+
/* @__PURE__ */ jsxs27("span", { className: "orion-admin-step-editor-meta", children: [
|
|
6331
|
+
fields.length,
|
|
6332
|
+
" field",
|
|
6333
|
+
fields.length === 1 ? "" : "s",
|
|
6334
|
+
requiredCount > 0 ? ` \xB7 ${requiredCount} required` : ""
|
|
6335
|
+
] }),
|
|
6336
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-workflow-node-destination", children: getStepDestination(stepIndex, editorState.steps.length) })
|
|
6337
|
+
] }),
|
|
6338
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-step-editor-body", children: [
|
|
6339
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-step-editor-actions", children: [
|
|
6340
|
+
/* @__PURE__ */ jsx30(
|
|
6341
|
+
"button",
|
|
6342
|
+
{
|
|
6343
|
+
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
6344
|
+
disabled: stepIndex === 0,
|
|
6345
|
+
onClick: () => moveStep(stepIndex, -1),
|
|
6346
|
+
type: "button",
|
|
6347
|
+
children: "Move up"
|
|
6348
|
+
}
|
|
6349
|
+
),
|
|
6350
|
+
/* @__PURE__ */ jsx30(
|
|
6351
|
+
"button",
|
|
6352
|
+
{
|
|
6353
|
+
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
6354
|
+
disabled: stepIndex === editorState.steps.length - 1,
|
|
6355
|
+
onClick: () => moveStep(stepIndex, 1),
|
|
6356
|
+
type: "button",
|
|
6357
|
+
children: "Move down"
|
|
6358
|
+
}
|
|
6359
|
+
),
|
|
6360
|
+
/* @__PURE__ */ jsx30(
|
|
6361
|
+
"button",
|
|
6362
|
+
{
|
|
6363
|
+
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
6364
|
+
onClick: () => setEditorState(
|
|
6365
|
+
(current) => current ? {
|
|
6366
|
+
...current,
|
|
6367
|
+
steps: current.steps.filter((_, index) => index !== stepIndex)
|
|
6368
|
+
} : current
|
|
6369
|
+
),
|
|
6370
|
+
type: "button",
|
|
6371
|
+
children: "Remove step"
|
|
6372
|
+
}
|
|
6373
|
+
)
|
|
6374
|
+
] }),
|
|
6375
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-step-settings-grid", children: [
|
|
6376
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6377
|
+
"Step title",
|
|
6378
|
+
/* @__PURE__ */ jsx30(
|
|
6379
|
+
"input",
|
|
6380
|
+
{
|
|
6381
|
+
onChange: (event) => updateStep(stepIndex, { title: event.target.value }),
|
|
6382
|
+
type: "text",
|
|
6383
|
+
value: getNonEmptyText(step.title)
|
|
6384
|
+
}
|
|
6385
|
+
)
|
|
6386
|
+
] }),
|
|
6387
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6388
|
+
"Next button label",
|
|
6389
|
+
/* @__PURE__ */ jsx30(
|
|
6390
|
+
"input",
|
|
6391
|
+
{
|
|
6392
|
+
onChange: (event) => updateStep(stepIndex, { nextLabel: event.target.value }),
|
|
6393
|
+
placeholder: "Next",
|
|
6394
|
+
type: "text",
|
|
6395
|
+
value: getNonEmptyText(step.nextLabel)
|
|
6396
|
+
}
|
|
6397
|
+
)
|
|
6398
|
+
] })
|
|
6399
|
+
] }),
|
|
6400
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6401
|
+
"Step intro text",
|
|
6402
|
+
/* @__PURE__ */ jsx30(
|
|
6403
|
+
"textarea",
|
|
6404
|
+
{
|
|
6405
|
+
onChange: (event) => updateStep(stepIndex, { subtitle: event.target.value }),
|
|
6406
|
+
rows: 3,
|
|
6407
|
+
value: getNonEmptyText(step.subtitle)
|
|
6408
|
+
}
|
|
6409
|
+
)
|
|
6410
|
+
] }),
|
|
6411
|
+
/* @__PURE__ */ jsxs27("label", { style: checkboxLabelStyle, children: [
|
|
6412
|
+
/* @__PURE__ */ jsx30(
|
|
6413
|
+
"input",
|
|
6414
|
+
{
|
|
6415
|
+
checked: step.allowSkip === true,
|
|
6416
|
+
onChange: (event) => updateStep(stepIndex, { allowSkip: event.target.checked }),
|
|
6417
|
+
type: "checkbox"
|
|
6418
|
+
}
|
|
6419
|
+
),
|
|
6420
|
+
"Allow visitors to skip this step"
|
|
6421
|
+
] }),
|
|
6422
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-field-list-header", children: [
|
|
6423
|
+
/* @__PURE__ */ jsxs27("div", { children: [
|
|
6424
|
+
/* @__PURE__ */ jsx30("strong", { children: "Fields in this step" }),
|
|
6425
|
+
/* @__PURE__ */ jsx30("span", { children: "These appear together before the visitor moves to the next step." })
|
|
6426
|
+
] }),
|
|
6427
|
+
/* @__PURE__ */ jsx30(
|
|
6428
|
+
"button",
|
|
6429
|
+
{
|
|
6430
|
+
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
6431
|
+
onClick: () => setEditorState(
|
|
6432
|
+
(current) => current ? {
|
|
6433
|
+
...current,
|
|
6434
|
+
steps: current.steps.map(
|
|
6435
|
+
(currentStep, index) => index === stepIndex ? { ...currentStep, fields: [...getFields(currentStep), blankField()] } : currentStep
|
|
6436
|
+
)
|
|
6437
|
+
} : current
|
|
6438
|
+
),
|
|
6439
|
+
type: "button",
|
|
6440
|
+
children: "Add field"
|
|
6441
|
+
}
|
|
6442
|
+
)
|
|
6443
|
+
] }),
|
|
6444
|
+
fields.length > 0 ? /* @__PURE__ */ jsx30("div", { className: "orion-admin-field-editor-list", children: fields.map((field, fieldIndex) => {
|
|
6445
|
+
const label = getFieldLabel(field, fieldIndex);
|
|
6446
|
+
const fieldType = getNonEmptyText(field.type, "text");
|
|
6447
|
+
return /* @__PURE__ */ jsxs27("details", { className: "orion-admin-field-editor", children: [
|
|
6448
|
+
/* @__PURE__ */ jsxs27("summary", { className: "orion-admin-field-editor-summary", children: [
|
|
6449
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-field-order", children: fieldIndex + 1 }),
|
|
6450
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-field-editor-title", children: label }),
|
|
6451
|
+
/* @__PURE__ */ jsxs27("span", { className: "orion-admin-field-editor-meta", children: [
|
|
6452
|
+
formatFieldTypeLabel(fieldType),
|
|
6453
|
+
field.required === true ? " \xB7 Required" : ""
|
|
6454
|
+
] })
|
|
6455
|
+
] }),
|
|
6456
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-field-editor-body", children: [
|
|
6457
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-step-editor-actions", children: [
|
|
6458
|
+
/* @__PURE__ */ jsx30(
|
|
6459
|
+
"button",
|
|
6460
|
+
{
|
|
6461
|
+
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
6462
|
+
disabled: fieldIndex === 0,
|
|
6463
|
+
onClick: () => moveField(stepIndex, fieldIndex, -1),
|
|
6464
|
+
type: "button",
|
|
6465
|
+
children: "Move up"
|
|
6466
|
+
}
|
|
6467
|
+
),
|
|
6468
|
+
/* @__PURE__ */ jsx30(
|
|
6469
|
+
"button",
|
|
6470
|
+
{
|
|
6471
|
+
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
6472
|
+
disabled: fieldIndex === fields.length - 1,
|
|
6473
|
+
onClick: () => moveField(stepIndex, fieldIndex, 1),
|
|
6474
|
+
type: "button",
|
|
6475
|
+
children: "Move down"
|
|
6476
|
+
}
|
|
6477
|
+
),
|
|
6478
|
+
/* @__PURE__ */ jsx30(
|
|
6479
|
+
"button",
|
|
6480
|
+
{
|
|
6481
|
+
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
6482
|
+
onClick: () => setEditorState((current) => {
|
|
6483
|
+
if (!current) return current;
|
|
6484
|
+
return {
|
|
6485
|
+
...current,
|
|
6486
|
+
steps: current.steps.map(
|
|
6487
|
+
(currentStep, index) => index === stepIndex ? {
|
|
6488
|
+
...currentStep,
|
|
6489
|
+
fields: getFields(currentStep).filter(
|
|
6490
|
+
(_, currentFieldIndex) => currentFieldIndex !== fieldIndex
|
|
6491
|
+
)
|
|
6492
|
+
} : currentStep
|
|
6493
|
+
)
|
|
6494
|
+
};
|
|
6495
|
+
}),
|
|
6496
|
+
type: "button",
|
|
6497
|
+
children: "Remove field"
|
|
6498
|
+
}
|
|
6499
|
+
)
|
|
6500
|
+
] }),
|
|
6501
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-step-settings-grid", children: [
|
|
6502
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6503
|
+
"Field label",
|
|
6504
|
+
/* @__PURE__ */ jsx30(
|
|
6505
|
+
"input",
|
|
6506
|
+
{
|
|
6507
|
+
onChange: (event) => {
|
|
6508
|
+
const nextLabel = event.target.value;
|
|
6509
|
+
const currentName = getNonEmptyText(field.name);
|
|
6510
|
+
updateField(stepIndex, fieldIndex, {
|
|
6511
|
+
label: nextLabel,
|
|
6512
|
+
name: currentName || slugifyFieldName(nextLabel)
|
|
6513
|
+
});
|
|
6514
|
+
},
|
|
6515
|
+
type: "text",
|
|
6516
|
+
value: label
|
|
6517
|
+
}
|
|
6518
|
+
)
|
|
6519
|
+
] }),
|
|
6520
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6521
|
+
"Field type",
|
|
6522
|
+
/* @__PURE__ */ jsx30(
|
|
6523
|
+
"select",
|
|
6524
|
+
{
|
|
6525
|
+
onChange: (event) => updateField(stepIndex, fieldIndex, { type: event.target.value }),
|
|
6526
|
+
value: fieldType,
|
|
6527
|
+
children: fieldTypeOptions.map((option) => /* @__PURE__ */ jsx30("option", { value: option, children: formatFieldTypeLabel(option) }, option))
|
|
6528
|
+
}
|
|
6529
|
+
)
|
|
6530
|
+
] })
|
|
6531
|
+
] }),
|
|
6532
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6533
|
+
"Field key",
|
|
6534
|
+
/* @__PURE__ */ jsx30(
|
|
6535
|
+
"input",
|
|
6536
|
+
{
|
|
6537
|
+
onChange: (event) => updateField(stepIndex, fieldIndex, { name: event.target.value }),
|
|
6538
|
+
type: "text",
|
|
6539
|
+
value: getNonEmptyText(field.name)
|
|
6540
|
+
}
|
|
6541
|
+
)
|
|
6542
|
+
] }),
|
|
6543
|
+
/* @__PURE__ */ jsxs27("label", { style: checkboxLabelStyle, children: [
|
|
6544
|
+
/* @__PURE__ */ jsx30(
|
|
6545
|
+
"input",
|
|
6546
|
+
{
|
|
6547
|
+
checked: field.required === true,
|
|
6548
|
+
onChange: (event) => updateField(stepIndex, fieldIndex, { required: event.target.checked }),
|
|
6549
|
+
type: "checkbox"
|
|
6550
|
+
}
|
|
6551
|
+
),
|
|
6552
|
+
"Required"
|
|
6553
|
+
] }),
|
|
6554
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6555
|
+
"Help text",
|
|
6556
|
+
/* @__PURE__ */ jsx30(
|
|
6557
|
+
"textarea",
|
|
6558
|
+
{
|
|
6559
|
+
onChange: (event) => updateField(stepIndex, fieldIndex, { helpText: event.target.value }),
|
|
6560
|
+
rows: 2,
|
|
6561
|
+
value: getNonEmptyText(field.helpText)
|
|
6562
|
+
}
|
|
6563
|
+
)
|
|
6564
|
+
] }),
|
|
6565
|
+
["select", "radio", "checkbox-group"].includes(fieldType) ? /* @__PURE__ */ jsxs27("label", { children: [
|
|
6566
|
+
"Options",
|
|
6567
|
+
/* @__PURE__ */ jsx30(
|
|
6568
|
+
"textarea",
|
|
6569
|
+
{
|
|
6570
|
+
onChange: (event) => updateField(stepIndex, fieldIndex, {
|
|
6571
|
+
options: fromOptionsText(event.target.value)
|
|
6572
|
+
}),
|
|
6573
|
+
placeholder: "Option one\nOption two",
|
|
6574
|
+
rows: 4,
|
|
6575
|
+
value: toOptionsText(field.options)
|
|
6576
|
+
}
|
|
6577
|
+
)
|
|
6578
|
+
] }) : null
|
|
6579
|
+
] })
|
|
6580
|
+
] }, `edit-field-${stepIndex}-${fieldIndex}`);
|
|
6581
|
+
}) }) : /* @__PURE__ */ jsxs27("div", { className: "orion-admin-empty-state", children: [
|
|
6582
|
+
/* @__PURE__ */ jsx30("strong", { children: "No fields in this step" }),
|
|
6583
|
+
/* @__PURE__ */ jsx30("span", { children: "Add a field so visitors have something to answer here." })
|
|
6584
|
+
] })
|
|
6585
|
+
] })
|
|
6586
|
+
] }, `edit-step-${stepIndex}`);
|
|
6587
|
+
}) })
|
|
6588
|
+
] }),
|
|
6589
|
+
/* @__PURE__ */ jsx30("button", { disabled: saving, type: "submit", children: saving ? "Saving..." : "Save Form" })
|
|
6590
|
+
] })
|
|
6591
|
+
] })
|
|
6592
|
+
] }) : null
|
|
6593
|
+
]
|
|
6594
|
+
}
|
|
6595
|
+
) });
|
|
6596
|
+
}
|
|
6597
|
+
|
|
6598
|
+
// src/admin/components/studio/AdminStudioFormSubmissionView.tsx
|
|
6599
|
+
import Link5 from "next/link";
|
|
6600
|
+
import { useEffect as useEffect19, useMemo as useMemo15, useState as useState20 } from "react";
|
|
6601
|
+
import { Fragment as Fragment6, jsx as jsx31, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
6602
|
+
var sectionGridStyle2 = {
|
|
6603
|
+
display: "grid",
|
|
6604
|
+
gap: "1rem",
|
|
6605
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))"
|
|
6606
|
+
};
|
|
6607
|
+
var nestedListStyle = {
|
|
6608
|
+
display: "grid",
|
|
6609
|
+
gap: "0.45rem",
|
|
6610
|
+
margin: 0,
|
|
6611
|
+
padding: 0
|
|
6612
|
+
};
|
|
6613
|
+
var renderFieldValue = (value) => {
|
|
6614
|
+
if (value === null || value === void 0) {
|
|
6615
|
+
return /* @__PURE__ */ jsx31("span", { className: "orion-admin-list-meta", children: "No value" });
|
|
6616
|
+
}
|
|
6617
|
+
if (typeof value === "boolean") {
|
|
6618
|
+
return value ? "Yes" : "No";
|
|
6619
|
+
}
|
|
6620
|
+
if (typeof value === "number") {
|
|
6621
|
+
return String(value);
|
|
6622
|
+
}
|
|
6623
|
+
if (typeof value === "string") {
|
|
6624
|
+
return value.trim().length > 0 ? value : /* @__PURE__ */ jsx31("span", { className: "orion-admin-list-meta", children: "No value" });
|
|
6625
|
+
}
|
|
6626
|
+
if (Array.isArray(value)) {
|
|
6627
|
+
const entries = value.filter((entry) => entry !== null && entry !== void 0 && entry !== "");
|
|
6628
|
+
if (entries.length === 0) {
|
|
6629
|
+
return /* @__PURE__ */ jsx31("span", { className: "orion-admin-list-meta", children: "No value" });
|
|
6630
|
+
}
|
|
6631
|
+
return /* @__PURE__ */ jsx31("ul", { style: nestedListStyle, children: entries.map((entry, index) => /* @__PURE__ */ jsx31("li", { children: renderFieldValue(entry) }, index)) });
|
|
6632
|
+
}
|
|
6633
|
+
if (typeof value === "object") {
|
|
6634
|
+
const entries = Object.entries(value).filter(
|
|
6635
|
+
([, entryValue]) => entryValue !== null && entryValue !== void 0 && entryValue !== ""
|
|
6636
|
+
);
|
|
6637
|
+
if (entries.length === 0) {
|
|
6638
|
+
return /* @__PURE__ */ jsx31("span", { className: "orion-admin-list-meta", children: "No value" });
|
|
6639
|
+
}
|
|
6640
|
+
return /* @__PURE__ */ jsx31("div", { style: { display: "grid", gap: "0.65rem" }, children: entries.map(([key, entryValue]) => /* @__PURE__ */ jsxs28("div", { className: "orion-admin-meta-row", children: [
|
|
6641
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-label", children: humanizeKey2(key) }),
|
|
6642
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-value", children: renderFieldValue(entryValue) })
|
|
6643
|
+
] }, key)) });
|
|
6644
|
+
}
|
|
6645
|
+
return String(value);
|
|
6646
|
+
};
|
|
6647
|
+
function getSubmissionIDFromPathname(pathname) {
|
|
6648
|
+
return getIDFromPathname(pathname, "/forms/submissions/");
|
|
6649
|
+
}
|
|
6650
|
+
function AdminStudioFormSubmissionView(props) {
|
|
6651
|
+
const formsCollectionSlug = getPropString14(props, "formsCollectionSlug", "forms");
|
|
6652
|
+
const formSubmissionsCollectionSlug = getPropString14(
|
|
6653
|
+
props,
|
|
6654
|
+
"formSubmissionsCollectionSlug",
|
|
6655
|
+
"form-submissions"
|
|
6656
|
+
);
|
|
6657
|
+
const adminBasePath = useAdminBasePath();
|
|
6658
|
+
const formsPath = resolveAdminPath(adminBasePath, "/forms");
|
|
6659
|
+
const submissionIDFromParams = useMemo15(() => getParam3(props.params, "id"), [props.params]);
|
|
6660
|
+
const [submissionID, setSubmissionID] = useState20(submissionIDFromParams);
|
|
6661
|
+
const [didResolvePathFallback, setDidResolvePathFallback] = useState20(false);
|
|
6662
|
+
const [doc, setDoc] = useState20(null);
|
|
6663
|
+
const [formDoc, setFormDoc] = useState20(null);
|
|
6664
|
+
const [loading, setLoading] = useState20(true);
|
|
6665
|
+
const [error, setError] = useState20(null);
|
|
6666
|
+
const [confirmDelete, setConfirmDelete] = useState20(false);
|
|
6667
|
+
const [deleting, setDeleting] = useState20(false);
|
|
6668
|
+
useEffect19(() => {
|
|
6669
|
+
if (submissionIDFromParams) {
|
|
6670
|
+
setSubmissionID(submissionIDFromParams);
|
|
6671
|
+
setDidResolvePathFallback(true);
|
|
6672
|
+
return;
|
|
6673
|
+
}
|
|
6674
|
+
if (typeof window !== "undefined") {
|
|
6675
|
+
setSubmissionID(getSubmissionIDFromPathname(window.location.pathname));
|
|
6676
|
+
}
|
|
6677
|
+
setDidResolvePathFallback(true);
|
|
6678
|
+
}, [submissionIDFromParams]);
|
|
6679
|
+
const loadDoc = async (id) => {
|
|
6680
|
+
setLoading(true);
|
|
6681
|
+
setError(null);
|
|
6682
|
+
try {
|
|
6683
|
+
const response = await fetch(
|
|
6684
|
+
`/api/${formSubmissionsCollectionSlug}/${encodeURIComponent(id)}?depth=2&draft=true`,
|
|
6685
|
+
{
|
|
6686
|
+
credentials: "include"
|
|
6687
|
+
}
|
|
6688
|
+
);
|
|
6689
|
+
if (!response.ok) {
|
|
6690
|
+
throw new Error(`Failed to load submission (${response.status}).`);
|
|
6691
|
+
}
|
|
6692
|
+
const nextDoc = await response.json();
|
|
6693
|
+
const relatedForm = nextDoc.form && typeof nextDoc.form === "object" && !Array.isArray(nextDoc.form) ? nextDoc.form : null;
|
|
6694
|
+
let nextFormDoc = relatedForm;
|
|
6695
|
+
const relatedFormID2 = getFormID3(nextDoc.form);
|
|
6696
|
+
if (!nextFormDoc && relatedFormID2) {
|
|
6697
|
+
const formResponse = await fetch(
|
|
6698
|
+
`/api/${formsCollectionSlug}/${encodeURIComponent(relatedFormID2)}?depth=0&draft=true`,
|
|
6699
|
+
{
|
|
6700
|
+
credentials: "include"
|
|
6701
|
+
}
|
|
6702
|
+
);
|
|
6703
|
+
if (formResponse.ok) {
|
|
6704
|
+
nextFormDoc = await formResponse.json();
|
|
6705
|
+
}
|
|
6706
|
+
}
|
|
6707
|
+
setDoc(nextDoc);
|
|
6708
|
+
setFormDoc(nextFormDoc);
|
|
6709
|
+
} catch (loadError) {
|
|
6710
|
+
setError(loadError instanceof Error ? loadError.message : "Failed to load submission.");
|
|
6711
|
+
setDoc(null);
|
|
6712
|
+
setFormDoc(null);
|
|
6713
|
+
} finally {
|
|
6714
|
+
setLoading(false);
|
|
6715
|
+
}
|
|
6716
|
+
};
|
|
6717
|
+
useEffect19(() => {
|
|
6718
|
+
if (!submissionID) {
|
|
6719
|
+
return;
|
|
6720
|
+
}
|
|
6721
|
+
void loadDoc(submissionID);
|
|
6722
|
+
}, [formsCollectionSlug, formSubmissionsCollectionSlug, submissionID]);
|
|
6723
|
+
const deleteSubmission = async () => {
|
|
6724
|
+
if (!submissionID) {
|
|
6725
|
+
return;
|
|
6726
|
+
}
|
|
6727
|
+
setDeleting(true);
|
|
6728
|
+
setError(null);
|
|
6729
|
+
try {
|
|
6730
|
+
const response = await fetch(`/api/${formSubmissionsCollectionSlug}/${encodeURIComponent(submissionID)}`, {
|
|
6731
|
+
credentials: "include",
|
|
6732
|
+
method: "DELETE"
|
|
6733
|
+
});
|
|
6734
|
+
if (!response.ok) {
|
|
6735
|
+
throw new Error(`Failed to delete submission (${response.status}).`);
|
|
6736
|
+
}
|
|
6737
|
+
const relatedFormID2 = doc ? getFormID3(doc.form) : "";
|
|
6738
|
+
const targetHref = relatedFormID2 ? resolveAdminPath(adminBasePath, `/forms/${relatedFormID2}`) : formsPath;
|
|
6739
|
+
window.location.assign(targetHref);
|
|
6740
|
+
} catch (deleteError) {
|
|
6741
|
+
setError(deleteError instanceof Error ? deleteError.message : "Failed to delete submission.");
|
|
6742
|
+
setDeleting(false);
|
|
6743
|
+
}
|
|
6744
|
+
};
|
|
6745
|
+
if (!submissionID && !didResolvePathFallback) {
|
|
6746
|
+
return /* @__PURE__ */ jsx31(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsx31(
|
|
6747
|
+
AdminPage,
|
|
6748
|
+
{
|
|
6749
|
+
breadcrumbs: [
|
|
6750
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
6751
|
+
{ label: "Forms", href: formsPath },
|
|
6752
|
+
{ label: "Submission" }
|
|
6753
|
+
],
|
|
6754
|
+
description: "Loading submission workspace...",
|
|
6755
|
+
title: "Submission",
|
|
6756
|
+
children: /* @__PURE__ */ jsx31(Fragment6, {})
|
|
6757
|
+
}
|
|
6758
|
+
) });
|
|
6759
|
+
}
|
|
6760
|
+
const relatedFormID = doc ? getFormID3(doc.form) : "";
|
|
6761
|
+
const formPath = relatedFormID ? resolveAdminPath(adminBasePath, `/forms/${relatedFormID}`) : formsPath;
|
|
6762
|
+
const formTitle = formDoc ? getFormTitle2(formDoc) : getFormTitle2(doc?.formSlug);
|
|
6763
|
+
const uploads = doc ? getUploads2(doc.files) : [];
|
|
6764
|
+
const identity = doc ? getNameAndEmail2(doc.data) : {};
|
|
6765
|
+
const fieldLabels = formDoc ? buildFieldLabelMap2(formDoc) : /* @__PURE__ */ new Map();
|
|
6766
|
+
const previewFields = doc ? getPreviewFields2(doc.data, fieldLabels) : [];
|
|
6767
|
+
const answerEntries = doc && doc.data && typeof doc.data === "object" ? Object.entries(doc.data) : [];
|
|
6768
|
+
return /* @__PURE__ */ jsx31(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsxs28(
|
|
6769
|
+
AdminPage,
|
|
6770
|
+
{
|
|
6771
|
+
breadcrumbs: [
|
|
6772
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
6773
|
+
{ label: "Forms", href: formsPath },
|
|
6774
|
+
...relatedFormID ? [{ label: formTitle, href: formPath }] : [{ label: formTitle }],
|
|
6775
|
+
{ label: "Submission" }
|
|
6776
|
+
],
|
|
6777
|
+
description: "Review the submitted answers, related files, and linked form details.",
|
|
6778
|
+
title: "Submission",
|
|
6779
|
+
children: [
|
|
6780
|
+
loading ? /* @__PURE__ */ jsx31("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
|
|
6781
|
+
error ? /* @__PURE__ */ jsx31("div", { className: "orion-admin-error", children: error }) : null,
|
|
6782
|
+
!loading && !error && doc && submissionID ? /* @__PURE__ */ jsxs28("div", { style: { display: "grid", gap: "1rem" }, children: [
|
|
6783
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-forms-summary-grid", children: [
|
|
6784
|
+
/* @__PURE__ */ jsxs28("article", { className: "orion-admin-overview-stat", children: [
|
|
6785
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-overview-stat-label", children: "Submitted" }),
|
|
6786
|
+
/* @__PURE__ */ jsx31("strong", { children: formatDate2(doc.submittedAt) }),
|
|
6787
|
+
/* @__PURE__ */ jsx31("p", { children: "Captured timestamp for this response." })
|
|
6788
|
+
] }),
|
|
6789
|
+
/* @__PURE__ */ jsxs28("article", { className: "orion-admin-overview-stat", children: [
|
|
6790
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-overview-stat-label", children: "Uploads" }),
|
|
6791
|
+
/* @__PURE__ */ jsx31("strong", { children: uploads.length }),
|
|
6792
|
+
/* @__PURE__ */ jsx31("p", { children: "Files attached by the submitter." })
|
|
6793
|
+
] }),
|
|
6794
|
+
/* @__PURE__ */ jsxs28("article", { className: "orion-admin-overview-stat", children: [
|
|
6795
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-overview-stat-label", children: "Highlighted answers" }),
|
|
6796
|
+
/* @__PURE__ */ jsx31("strong", { children: previewFields.length }),
|
|
6797
|
+
/* @__PURE__ */ jsx31("p", { children: "Readable answer previews from this response." })
|
|
6798
|
+
] })
|
|
6799
|
+
] }),
|
|
6800
|
+
/* @__PURE__ */ jsxs28("div", { style: sectionGridStyle2, children: [
|
|
6801
|
+
/* @__PURE__ */ jsx31("div", { style: { display: "grid", gap: "1rem" }, children: /* @__PURE__ */ jsxs28("div", { className: "orion-admin-card", children: [
|
|
6802
|
+
/* @__PURE__ */ jsx31("strong", { children: "Response details" }),
|
|
6803
|
+
/* @__PURE__ */ jsx31("span", { children: "Formatted answers using the current form field labels when available." }),
|
|
6804
|
+
/* @__PURE__ */ jsx31("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: answerEntries.length > 0 ? answerEntries.map(([key, value]) => /* @__PURE__ */ jsxs28("div", { className: "orion-admin-form", children: [
|
|
6805
|
+
/* @__PURE__ */ jsxs28("div", { children: [
|
|
6806
|
+
/* @__PURE__ */ jsx31("strong", { children: fieldLabels.get(key) || humanizeKey2(key) }),
|
|
6807
|
+
/* @__PURE__ */ jsx31("div", { className: "orion-admin-list-meta", children: key })
|
|
6808
|
+
] }),
|
|
6809
|
+
/* @__PURE__ */ jsx31("div", { children: renderFieldValue(value) })
|
|
6810
|
+
] }, key)) : /* @__PURE__ */ jsxs28("div", { className: "orion-admin-empty-state", children: [
|
|
6811
|
+
/* @__PURE__ */ jsx31("strong", { children: "No answers available" }),
|
|
6812
|
+
/* @__PURE__ */ jsx31("span", { children: "This submission does not contain visible response details." })
|
|
6813
|
+
] }) })
|
|
6814
|
+
] }) }),
|
|
6815
|
+
/* @__PURE__ */ jsxs28("div", { style: { display: "grid", gap: "1rem" }, children: [
|
|
6816
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-card orion-admin-meta-table", children: [
|
|
6817
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-meta-row", children: [
|
|
6818
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-label", children: "Form" }),
|
|
6819
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-value", children: relatedFormID ? /* @__PURE__ */ jsx31(Link5, { href: formPath, children: formTitle }) : formTitle })
|
|
6820
|
+
] }),
|
|
6821
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-meta-row", children: [
|
|
6822
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-label", children: "Primary contact" }),
|
|
6823
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-value", children: identity.name || identity.email || "Unknown" })
|
|
6824
|
+
] }),
|
|
6825
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-meta-row", children: [
|
|
6826
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-label", children: "Email" }),
|
|
6827
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-value", children: identity.email || "Not provided" })
|
|
6828
|
+
] }),
|
|
6829
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-meta-row", children: [
|
|
6830
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-label", children: "Submission ID" }),
|
|
6831
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-value", children: submissionID })
|
|
6832
|
+
] }),
|
|
6833
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-meta-row", children: [
|
|
6834
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-label", children: "Form slug" }),
|
|
6835
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-value", children: typeof doc.formSlug === "string" && doc.formSlug.trim().length > 0 ? doc.formSlug : "Unavailable" })
|
|
6836
|
+
] })
|
|
6837
|
+
] }),
|
|
6838
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-card", children: [
|
|
6839
|
+
/* @__PURE__ */ jsx31("strong", { children: "Attached uploads" }),
|
|
6840
|
+
/* @__PURE__ */ jsx31("span", { children: "Files linked to this response remain inside the Studio workspace." }),
|
|
6841
|
+
/* @__PURE__ */ jsx31("div", { style: { display: "grid", gap: "0.75rem", marginTop: "1rem" }, children: uploads.length > 0 ? uploads.map((upload) => {
|
|
6842
|
+
const uploadID = typeof upload.id === "string" || typeof upload.id === "number" ? String(upload.id) : "";
|
|
6843
|
+
if (!uploadID) return null;
|
|
6844
|
+
const uploadPath = resolveAdminPath(adminBasePath, `/forms/uploads/${uploadID}`);
|
|
6845
|
+
const meta = [formatFileSize2(upload.filesize), typeof upload.mimeType === "string" ? upload.mimeType : null].filter(Boolean).join(" \xB7 ");
|
|
6846
|
+
return /* @__PURE__ */ jsxs28(Link5, { className: "orion-admin-list-item", href: uploadPath, children: [
|
|
6847
|
+
/* @__PURE__ */ jsxs28("div", { children: [
|
|
6848
|
+
/* @__PURE__ */ jsx31("strong", { children: typeof upload.filename === "string" && upload.filename.trim().length > 0 ? upload.filename : `Upload ${uploadID}` }),
|
|
6849
|
+
/* @__PURE__ */ jsx31("div", { className: "orion-admin-list-meta", children: meta || "Open file details" })
|
|
6850
|
+
] }),
|
|
6851
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-action-button orion-admin-action-button--ghost", children: "Open" })
|
|
6852
|
+
] }, uploadID);
|
|
6853
|
+
}) : /* @__PURE__ */ jsxs28("div", { className: "orion-admin-empty-state", children: [
|
|
6854
|
+
/* @__PURE__ */ jsx31("strong", { children: "No files attached" }),
|
|
6855
|
+
/* @__PURE__ */ jsx31("span", { children: "This response did not include any uploads." })
|
|
6856
|
+
] }) })
|
|
6857
|
+
] }),
|
|
6858
|
+
confirmDelete ? /* @__PURE__ */ jsxs28("div", { className: "orion-admin-form", style: { borderColor: "#b42318" }, children: [
|
|
6859
|
+
/* @__PURE__ */ jsx31("p", { style: { fontWeight: 700, margin: 0 }, children: "Delete this submission?" }),
|
|
6860
|
+
/* @__PURE__ */ jsx31("p", { className: "orion-admin-list-meta", style: { margin: 0 }, children: "This action cannot be undone and will remove the stored response." }),
|
|
6861
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-inline-actions", children: [
|
|
6862
|
+
/* @__PURE__ */ jsx31("button", { disabled: deleting, onClick: deleteSubmission, type: "button", children: deleting ? "Deleting..." : "Yes, Delete" }),
|
|
6863
|
+
/* @__PURE__ */ jsx31("button", { onClick: () => setConfirmDelete(false), type: "button", children: "Cancel" })
|
|
6864
|
+
] })
|
|
6865
|
+
] }) : /* @__PURE__ */ jsx31(
|
|
6866
|
+
"button",
|
|
6867
|
+
{
|
|
6868
|
+
className: "orion-admin-action-button",
|
|
6869
|
+
onClick: () => setConfirmDelete(true),
|
|
6870
|
+
style: { background: "#b42318" },
|
|
6871
|
+
type: "button",
|
|
6872
|
+
children: "Delete Submission"
|
|
6873
|
+
}
|
|
6874
|
+
)
|
|
6875
|
+
] })
|
|
6876
|
+
] })
|
|
6877
|
+
] }) : null
|
|
6878
|
+
]
|
|
6879
|
+
}
|
|
6880
|
+
) });
|
|
6881
|
+
}
|
|
6882
|
+
|
|
6883
|
+
// src/admin/components/studio/AdminStudioFormUploadView.tsx
|
|
6884
|
+
import { useEffect as useEffect20, useMemo as useMemo16, useState as useState21 } from "react";
|
|
6885
|
+
import { Fragment as Fragment7, jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
6886
|
+
var previewStyle = {
|
|
6887
|
+
borderRadius: 14,
|
|
6888
|
+
display: "block",
|
|
6889
|
+
maxHeight: "28rem",
|
|
6890
|
+
objectFit: "contain",
|
|
6891
|
+
width: "100%"
|
|
6892
|
+
};
|
|
6893
|
+
function getUploadIDFromPathname(pathname) {
|
|
6894
|
+
return getIDFromPathname(pathname, "/forms/uploads/");
|
|
6895
|
+
}
|
|
6896
|
+
function AdminStudioFormUploadView(props) {
|
|
6897
|
+
const formUploadsCollectionSlug = getPropString14(props, "formUploadsCollectionSlug", "form-uploads");
|
|
6898
|
+
const adminBasePath = useAdminBasePath();
|
|
6899
|
+
const formsPath = resolveAdminPath(adminBasePath, "/forms");
|
|
6900
|
+
const uploadIDFromParams = useMemo16(() => getParam3(props.params, "id"), [props.params]);
|
|
6901
|
+
const [uploadID, setUploadID] = useState21(uploadIDFromParams);
|
|
6902
|
+
const [didResolvePathFallback, setDidResolvePathFallback] = useState21(false);
|
|
6903
|
+
const [doc, setDoc] = useState21(null);
|
|
6904
|
+
const [loading, setLoading] = useState21(true);
|
|
6905
|
+
const [error, setError] = useState21(null);
|
|
6906
|
+
const [savedMessage, setSavedMessage] = useState21(null);
|
|
6907
|
+
const [saving, setSaving] = useState21(false);
|
|
6908
|
+
const [confirmDelete, setConfirmDelete] = useState21(false);
|
|
6909
|
+
const [deleting, setDeleting] = useState21(false);
|
|
6910
|
+
useEffect20(() => {
|
|
6911
|
+
if (uploadIDFromParams) {
|
|
6912
|
+
setUploadID(uploadIDFromParams);
|
|
6913
|
+
setDidResolvePathFallback(true);
|
|
6914
|
+
return;
|
|
6915
|
+
}
|
|
6916
|
+
if (typeof window !== "undefined") {
|
|
6917
|
+
setUploadID(getUploadIDFromPathname(window.location.pathname));
|
|
6918
|
+
}
|
|
6919
|
+
setDidResolvePathFallback(true);
|
|
6920
|
+
}, [uploadIDFromParams]);
|
|
6921
|
+
const loadDoc = async (id) => {
|
|
6922
|
+
setLoading(true);
|
|
6923
|
+
setError(null);
|
|
6924
|
+
try {
|
|
6925
|
+
const response = await fetch(`/api/${formUploadsCollectionSlug}/${encodeURIComponent(id)}?depth=0&draft=true`, {
|
|
6926
|
+
credentials: "include"
|
|
6927
|
+
});
|
|
6928
|
+
if (!response.ok) {
|
|
6929
|
+
throw new Error(`Failed to load upload (${response.status}).`);
|
|
6930
|
+
}
|
|
6931
|
+
const nextDoc = await response.json();
|
|
6932
|
+
setDoc(nextDoc);
|
|
6933
|
+
} catch (loadError) {
|
|
6934
|
+
setError(loadError instanceof Error ? loadError.message : "Failed to load upload.");
|
|
6935
|
+
setDoc(null);
|
|
6936
|
+
} finally {
|
|
6937
|
+
setLoading(false);
|
|
6938
|
+
}
|
|
6939
|
+
};
|
|
6940
|
+
useEffect20(() => {
|
|
6941
|
+
if (!uploadID) {
|
|
6942
|
+
return;
|
|
6943
|
+
}
|
|
6944
|
+
void loadDoc(uploadID);
|
|
6945
|
+
}, [formUploadsCollectionSlug, uploadID]);
|
|
6946
|
+
const save = async (event) => {
|
|
6947
|
+
event.preventDefault();
|
|
6948
|
+
if (!uploadID) {
|
|
6949
|
+
return;
|
|
6950
|
+
}
|
|
6951
|
+
setSaving(true);
|
|
5744
6952
|
setError(null);
|
|
5745
6953
|
setSavedMessage(null);
|
|
5746
6954
|
try {
|
|
5747
6955
|
const formData = new FormData(event.currentTarget);
|
|
6956
|
+
const alt = String(formData.get("alt") || "").trim();
|
|
6957
|
+
const response = await fetch(`/api/${formUploadsCollectionSlug}/${encodeURIComponent(uploadID)}`, {
|
|
6958
|
+
body: JSON.stringify({ alt }),
|
|
6959
|
+
credentials: "include",
|
|
6960
|
+
headers: {
|
|
6961
|
+
"Content-Type": "application/json"
|
|
6962
|
+
},
|
|
6963
|
+
method: "PATCH"
|
|
6964
|
+
});
|
|
6965
|
+
if (!response.ok) {
|
|
6966
|
+
throw new Error(`Failed to save upload (${response.status}).`);
|
|
6967
|
+
}
|
|
6968
|
+
const nextDoc = await response.json();
|
|
6969
|
+
setDoc(nextDoc);
|
|
6970
|
+
setSavedMessage("Saved.");
|
|
6971
|
+
} catch (saveError) {
|
|
6972
|
+
setError(saveError instanceof Error ? saveError.message : "Failed to save upload.");
|
|
6973
|
+
} finally {
|
|
6974
|
+
setSaving(false);
|
|
6975
|
+
}
|
|
6976
|
+
};
|
|
6977
|
+
const deleteUpload = async () => {
|
|
6978
|
+
if (!uploadID) {
|
|
6979
|
+
return;
|
|
6980
|
+
}
|
|
6981
|
+
setDeleting(true);
|
|
6982
|
+
setError(null);
|
|
6983
|
+
try {
|
|
6984
|
+
const response = await fetch(`/api/${formUploadsCollectionSlug}/${encodeURIComponent(uploadID)}`, {
|
|
6985
|
+
credentials: "include",
|
|
6986
|
+
method: "DELETE"
|
|
6987
|
+
});
|
|
6988
|
+
if (!response.ok) {
|
|
6989
|
+
throw new Error(`Failed to delete upload (${response.status}).`);
|
|
6990
|
+
}
|
|
6991
|
+
window.location.assign(formsPath);
|
|
6992
|
+
} catch (deleteError) {
|
|
6993
|
+
setError(deleteError instanceof Error ? deleteError.message : "Failed to delete upload.");
|
|
6994
|
+
setDeleting(false);
|
|
6995
|
+
}
|
|
6996
|
+
};
|
|
6997
|
+
if (!uploadID && !didResolvePathFallback) {
|
|
6998
|
+
return /* @__PURE__ */ jsx32(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsx32(
|
|
6999
|
+
AdminPage,
|
|
7000
|
+
{
|
|
7001
|
+
breadcrumbs: [
|
|
7002
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
7003
|
+
{ label: "Forms", href: formsPath },
|
|
7004
|
+
{ label: "Upload" }
|
|
7005
|
+
],
|
|
7006
|
+
description: "Loading upload workspace...",
|
|
7007
|
+
title: "Upload",
|
|
7008
|
+
children: /* @__PURE__ */ jsx32(Fragment7, {})
|
|
7009
|
+
}
|
|
7010
|
+
) });
|
|
7011
|
+
}
|
|
7012
|
+
const filename = doc && typeof doc.filename === "string" && doc.filename.trim().length > 0 ? doc.filename : uploadID ? `Upload ${uploadID}` : "Upload";
|
|
7013
|
+
const mimeType = doc && typeof doc.mimeType === "string" ? doc.mimeType : "";
|
|
7014
|
+
const sourceURL = doc && typeof doc.url === "string" && doc.url.trim().length > 0 ? doc.url : null;
|
|
7015
|
+
const canPreview = Boolean(sourceURL && mimeType.startsWith("image/"));
|
|
7016
|
+
const createdAt = doc?.createdAt ?? doc?.updatedAt;
|
|
7017
|
+
return /* @__PURE__ */ jsx32(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsxs29(
|
|
7018
|
+
AdminPage,
|
|
7019
|
+
{
|
|
7020
|
+
breadcrumbs: [
|
|
7021
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
7022
|
+
{ label: "Forms", href: formsPath },
|
|
7023
|
+
{ label: filename }
|
|
7024
|
+
],
|
|
7025
|
+
description: "Review file metadata, update alt text, and remove private uploads from Studio.",
|
|
7026
|
+
title: "Upload",
|
|
7027
|
+
children: [
|
|
7028
|
+
loading ? /* @__PURE__ */ jsx32("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
|
|
7029
|
+
error ? /* @__PURE__ */ jsx32("div", { className: "orion-admin-error", children: error }) : null,
|
|
7030
|
+
savedMessage ? /* @__PURE__ */ jsx32("div", { className: "orion-admin-success", children: savedMessage }) : null,
|
|
7031
|
+
!loading && !error && doc && uploadID ? /* @__PURE__ */ jsxs29("div", { className: "orion-admin-grid", style: { alignItems: "start" }, children: [
|
|
7032
|
+
/* @__PURE__ */ jsxs29("div", { style: { display: "grid", gap: "0.8rem" }, children: [
|
|
7033
|
+
/* @__PURE__ */ jsx32("div", { className: "orion-admin-card", children: canPreview && sourceURL ? /* @__PURE__ */ jsx32("img", { alt: filename, src: sourceURL, style: previewStyle }) : /* @__PURE__ */ jsxs29(Fragment7, { children: [
|
|
7034
|
+
/* @__PURE__ */ jsx32("strong", { children: "No inline preview" }),
|
|
7035
|
+
/* @__PURE__ */ jsx32("span", { children: mimeType ? `Preview unavailable for ${mimeType}.` : "Preview unavailable for this file." })
|
|
7036
|
+
] }) }),
|
|
7037
|
+
sourceURL ? /* @__PURE__ */ jsx32("a", { className: "orion-admin-action-button", href: sourceURL, rel: "noreferrer", target: "_blank", children: "Open File" }) : null
|
|
7038
|
+
] }),
|
|
7039
|
+
/* @__PURE__ */ jsxs29("div", { style: { display: "grid", gap: "0.8rem" }, children: [
|
|
7040
|
+
/* @__PURE__ */ jsxs29("div", { className: "orion-admin-card orion-admin-meta-table", children: [
|
|
7041
|
+
/* @__PURE__ */ jsxs29("div", { className: "orion-admin-meta-row", children: [
|
|
7042
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-label", children: "Filename" }),
|
|
7043
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-value", children: filename })
|
|
7044
|
+
] }),
|
|
7045
|
+
/* @__PURE__ */ jsxs29("div", { className: "orion-admin-meta-row", children: [
|
|
7046
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-label", children: "File size" }),
|
|
7047
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-value", children: formatFileSize2(doc.filesize) || "Unavailable" })
|
|
7048
|
+
] }),
|
|
7049
|
+
/* @__PURE__ */ jsxs29("div", { className: "orion-admin-meta-row", children: [
|
|
7050
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-label", children: "Type" }),
|
|
7051
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-value", children: mimeType || "Unavailable" })
|
|
7052
|
+
] }),
|
|
7053
|
+
typeof doc.width === "number" && typeof doc.height === "number" ? /* @__PURE__ */ jsxs29("div", { className: "orion-admin-meta-row", children: [
|
|
7054
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-label", children: "Dimensions" }),
|
|
7055
|
+
/* @__PURE__ */ jsxs29("span", { className: "orion-admin-meta-value", children: [
|
|
7056
|
+
doc.width,
|
|
7057
|
+
" x ",
|
|
7058
|
+
doc.height,
|
|
7059
|
+
"px"
|
|
7060
|
+
] })
|
|
7061
|
+
] }) : null,
|
|
7062
|
+
/* @__PURE__ */ jsxs29("div", { className: "orion-admin-meta-row", children: [
|
|
7063
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-label", children: "Uploaded" }),
|
|
7064
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-value", children: formatDate2(createdAt) })
|
|
7065
|
+
] })
|
|
7066
|
+
] }),
|
|
7067
|
+
/* @__PURE__ */ jsxs29("form", { className: "orion-admin-form", onSubmit: save, children: [
|
|
7068
|
+
/* @__PURE__ */ jsx32("strong", { children: "Asset details" }),
|
|
7069
|
+
/* @__PURE__ */ jsxs29("label", { children: [
|
|
7070
|
+
"Alt text",
|
|
7071
|
+
/* @__PURE__ */ jsx32("input", { defaultValue: typeof doc.alt === "string" ? doc.alt : "", name: "alt", type: "text" })
|
|
7072
|
+
] }),
|
|
7073
|
+
/* @__PURE__ */ jsx32("button", { disabled: saving, type: "submit", children: saving ? "Saving..." : "Save Upload" })
|
|
7074
|
+
] }),
|
|
7075
|
+
confirmDelete ? /* @__PURE__ */ jsxs29("div", { className: "orion-admin-form", style: { borderColor: "#b42318" }, children: [
|
|
7076
|
+
/* @__PURE__ */ jsx32("p", { style: { fontWeight: 700, margin: 0 }, children: "Delete this upload?" }),
|
|
7077
|
+
/* @__PURE__ */ jsx32("p", { className: "orion-admin-list-meta", style: { margin: 0 }, children: "This removes the stored file and any linked submission attachment references." }),
|
|
7078
|
+
/* @__PURE__ */ jsxs29("div", { className: "orion-admin-inline-actions", children: [
|
|
7079
|
+
/* @__PURE__ */ jsx32("button", { disabled: deleting, onClick: deleteUpload, type: "button", children: deleting ? "Deleting..." : "Yes, Delete" }),
|
|
7080
|
+
/* @__PURE__ */ jsx32("button", { onClick: () => setConfirmDelete(false), type: "button", children: "Cancel" })
|
|
7081
|
+
] })
|
|
7082
|
+
] }) : /* @__PURE__ */ jsx32(
|
|
7083
|
+
"button",
|
|
7084
|
+
{
|
|
7085
|
+
className: "orion-admin-action-button",
|
|
7086
|
+
onClick: () => setConfirmDelete(true),
|
|
7087
|
+
style: { background: "#b42318" },
|
|
7088
|
+
type: "button",
|
|
7089
|
+
children: "Delete Upload"
|
|
7090
|
+
}
|
|
7091
|
+
)
|
|
7092
|
+
] })
|
|
7093
|
+
] }) : null
|
|
7094
|
+
]
|
|
7095
|
+
}
|
|
7096
|
+
) });
|
|
7097
|
+
}
|
|
7098
|
+
|
|
7099
|
+
// src/admin/components/studio/AdminStudioToolsView.tsx
|
|
7100
|
+
import { useEffect as useEffect21, useState as useState22 } from "react";
|
|
7101
|
+
import { useAuth as useAuth6 } from "@payloadcms/ui";
|
|
7102
|
+
import { jsx as jsx33, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
7103
|
+
var userRoles = ["admin", "developer", "editor", "client"];
|
|
7104
|
+
var hasAdminAccess3 = (user) => {
|
|
7105
|
+
if (!user || typeof user !== "object") return false;
|
|
7106
|
+
const role = user.role;
|
|
7107
|
+
return typeof role === "string" && (role === "admin" || role === "developer");
|
|
7108
|
+
};
|
|
7109
|
+
var normalizeRole = (value) => userRoles.includes(value) ? value : "editor";
|
|
7110
|
+
function AdminStudioToolsView(props) {
|
|
7111
|
+
const { user } = useAuth6();
|
|
7112
|
+
const adminBasePath = useAdminBasePath();
|
|
7113
|
+
const [docs, setDocs] = useState22([]);
|
|
7114
|
+
const [loading, setLoading] = useState22(true);
|
|
7115
|
+
const [error, setError] = useState22(null);
|
|
7116
|
+
const [savedMessage, setSavedMessage] = useState22(null);
|
|
7117
|
+
const [createSubmitting, setCreateSubmitting] = useState22(false);
|
|
7118
|
+
const [updatingUserID, setUpdatingUserID] = useState22(null);
|
|
7119
|
+
if (!hasAdminAccess3(user)) {
|
|
7120
|
+
return /* @__PURE__ */ jsx33(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsx33(
|
|
7121
|
+
AdminPage,
|
|
7122
|
+
{
|
|
7123
|
+
breadcrumbs: [
|
|
7124
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
7125
|
+
{ label: "Admin Tools" }
|
|
7126
|
+
],
|
|
7127
|
+
description: "You do not have access to this section.",
|
|
7128
|
+
title: "Admin Tools",
|
|
7129
|
+
children: /* @__PURE__ */ jsxs30("div", { className: "orion-admin-card", children: [
|
|
7130
|
+
/* @__PURE__ */ jsx33("strong", { children: "Access denied" }),
|
|
7131
|
+
/* @__PURE__ */ jsx33("span", { children: "This section is restricted to administrator and developer accounts." })
|
|
7132
|
+
] })
|
|
7133
|
+
}
|
|
7134
|
+
) });
|
|
7135
|
+
}
|
|
7136
|
+
const loadUsers = async () => {
|
|
7137
|
+
setLoading(true);
|
|
7138
|
+
setError(null);
|
|
7139
|
+
try {
|
|
7140
|
+
const params = new URLSearchParams({
|
|
7141
|
+
depth: "0",
|
|
7142
|
+
draft: "true",
|
|
7143
|
+
limit: "200",
|
|
7144
|
+
sort: "email"
|
|
7145
|
+
});
|
|
7146
|
+
const response = await fetch(`/api/users?${params.toString()}`, {
|
|
7147
|
+
credentials: "include"
|
|
7148
|
+
});
|
|
7149
|
+
if (!response.ok) {
|
|
7150
|
+
throw new Error(`Failed to load users (${response.status}).`);
|
|
7151
|
+
}
|
|
7152
|
+
const payload = await response.json();
|
|
7153
|
+
setDocs(Array.isArray(payload.docs) ? payload.docs : []);
|
|
7154
|
+
} catch (loadError) {
|
|
7155
|
+
setError(loadError instanceof Error ? loadError.message : "Failed to load users.");
|
|
7156
|
+
} finally {
|
|
7157
|
+
setLoading(false);
|
|
7158
|
+
}
|
|
7159
|
+
};
|
|
7160
|
+
useEffect21(() => {
|
|
7161
|
+
void loadUsers();
|
|
7162
|
+
}, []);
|
|
7163
|
+
const createUser = async (event) => {
|
|
7164
|
+
event.preventDefault();
|
|
7165
|
+
const form = event.currentTarget;
|
|
7166
|
+
setCreateSubmitting(true);
|
|
7167
|
+
setError(null);
|
|
7168
|
+
setSavedMessage(null);
|
|
7169
|
+
try {
|
|
7170
|
+
const formData = new FormData(form);
|
|
5748
7171
|
const email = String(formData.get("email") || "").trim();
|
|
5749
7172
|
const password = String(formData.get("password") || "");
|
|
5750
7173
|
const fullName = String(formData.get("fullName") || "").trim();
|
|
@@ -5768,7 +7191,7 @@ function AdminStudioToolsView(props) {
|
|
|
5768
7191
|
if (!response.ok) {
|
|
5769
7192
|
throw new Error(`Failed to create user (${response.status}).`);
|
|
5770
7193
|
}
|
|
5771
|
-
|
|
7194
|
+
form.reset();
|
|
5772
7195
|
await loadUsers();
|
|
5773
7196
|
setSavedMessage("User created.");
|
|
5774
7197
|
} catch (createError) {
|
|
@@ -5806,7 +7229,7 @@ function AdminStudioToolsView(props) {
|
|
|
5806
7229
|
setUpdatingUserID(null);
|
|
5807
7230
|
}
|
|
5808
7231
|
};
|
|
5809
|
-
return /* @__PURE__ */
|
|
7232
|
+
return /* @__PURE__ */ jsx33(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsxs30(
|
|
5810
7233
|
AdminPage,
|
|
5811
7234
|
{
|
|
5812
7235
|
breadcrumbs: [
|
|
@@ -5816,53 +7239,44 @@ function AdminStudioToolsView(props) {
|
|
|
5816
7239
|
description: "Manage users and fallback links to Payload native admin.",
|
|
5817
7240
|
title: "Admin Tools",
|
|
5818
7241
|
children: [
|
|
5819
|
-
/* @__PURE__ */
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
/* @__PURE__ */
|
|
5824
|
-
/* @__PURE__ */ jsxs27("label", { children: [
|
|
7242
|
+
error ? /* @__PURE__ */ jsx33("div", { className: "orion-admin-error", style: { marginBottom: "1rem" }, children: error }) : null,
|
|
7243
|
+
savedMessage ? /* @__PURE__ */ jsx33("div", { className: "orion-admin-success", style: { marginBottom: "1rem" }, children: savedMessage }) : null,
|
|
7244
|
+
/* @__PURE__ */ jsxs30("form", { className: "orion-admin-form", onSubmit: createUser, style: { marginBottom: "1rem" }, children: [
|
|
7245
|
+
/* @__PURE__ */ jsx33("strong", { children: "Create User" }),
|
|
7246
|
+
/* @__PURE__ */ jsxs30("label", { children: [
|
|
5825
7247
|
"Email",
|
|
5826
|
-
/* @__PURE__ */
|
|
7248
|
+
/* @__PURE__ */ jsx33("input", { name: "email", required: true, type: "email" })
|
|
5827
7249
|
] }),
|
|
5828
|
-
/* @__PURE__ */
|
|
7250
|
+
/* @__PURE__ */ jsxs30("label", { children: [
|
|
5829
7251
|
"Full Name",
|
|
5830
|
-
/* @__PURE__ */
|
|
7252
|
+
/* @__PURE__ */ jsx33("input", { name: "fullName", type: "text" })
|
|
5831
7253
|
] }),
|
|
5832
|
-
/* @__PURE__ */
|
|
7254
|
+
/* @__PURE__ */ jsxs30("label", { children: [
|
|
5833
7255
|
"Password",
|
|
5834
|
-
/* @__PURE__ */
|
|
7256
|
+
/* @__PURE__ */ jsx33("input", { name: "password", required: true, type: "password" })
|
|
5835
7257
|
] }),
|
|
5836
|
-
/* @__PURE__ */
|
|
7258
|
+
/* @__PURE__ */ jsxs30("label", { children: [
|
|
5837
7259
|
"Role",
|
|
5838
|
-
/* @__PURE__ */
|
|
5839
|
-
/* @__PURE__ */ jsx30("option", { value: "admin", children: "admin" }),
|
|
5840
|
-
/* @__PURE__ */ jsx30("option", { value: "editor", children: "editor" }),
|
|
5841
|
-
/* @__PURE__ */ jsx30("option", { value: "client", children: "client" })
|
|
5842
|
-
] })
|
|
7260
|
+
/* @__PURE__ */ jsx33("select", { defaultValue: "editor", name: "role", children: userRoles.map((role) => /* @__PURE__ */ jsx33("option", { value: role, children: role }, role)) })
|
|
5843
7261
|
] }),
|
|
5844
|
-
/* @__PURE__ */
|
|
7262
|
+
/* @__PURE__ */ jsx33("button", { disabled: createSubmitting, type: "submit", children: createSubmitting ? "Creating..." : "Create User" })
|
|
5845
7263
|
] }),
|
|
5846
|
-
loading ? /* @__PURE__ */
|
|
5847
|
-
/* @__PURE__ */
|
|
7264
|
+
loading ? /* @__PURE__ */ jsx33("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
|
|
7265
|
+
/* @__PURE__ */ jsx33("div", { className: "orion-admin-list", children: docs.map((doc) => {
|
|
5848
7266
|
const id = typeof doc.id === "string" || typeof doc.id === "number" ? String(doc.id) : "";
|
|
5849
7267
|
if (!id) return null;
|
|
5850
7268
|
const email = typeof doc.email === "string" ? doc.email : `user-${id}`;
|
|
5851
7269
|
const fullName = typeof doc.fullName === "string" ? doc.fullName : "";
|
|
5852
7270
|
const currentRole = typeof doc.role === "string" ? normalizeRole(doc.role) : "editor";
|
|
5853
|
-
return /* @__PURE__ */
|
|
5854
|
-
/* @__PURE__ */
|
|
5855
|
-
/* @__PURE__ */
|
|
5856
|
-
/* @__PURE__ */
|
|
7271
|
+
return /* @__PURE__ */ jsxs30("div", { className: "orion-admin-list-item", children: [
|
|
7272
|
+
/* @__PURE__ */ jsxs30("div", { children: [
|
|
7273
|
+
/* @__PURE__ */ jsx33("strong", { children: email }),
|
|
7274
|
+
/* @__PURE__ */ jsx33("div", { className: "orion-admin-list-meta", children: fullName || "No full name set" })
|
|
5857
7275
|
] }),
|
|
5858
|
-
/* @__PURE__ */
|
|
5859
|
-
/* @__PURE__ */
|
|
5860
|
-
/* @__PURE__ */
|
|
5861
|
-
|
|
5862
|
-
/* @__PURE__ */ jsx30("option", { value: "editor", children: "editor" }),
|
|
5863
|
-
/* @__PURE__ */ jsx30("option", { value: "client", children: "client" })
|
|
5864
|
-
] }),
|
|
5865
|
-
/* @__PURE__ */ jsx30("button", { disabled: updatingUserID === id, type: "submit", children: updatingUserID === id ? "Updating..." : "Update" })
|
|
7276
|
+
/* @__PURE__ */ jsxs30("form", { className: "orion-admin-inline-actions", onSubmit: updateUserRole, children: [
|
|
7277
|
+
/* @__PURE__ */ jsx33("input", { name: "id", type: "hidden", value: id }),
|
|
7278
|
+
/* @__PURE__ */ jsx33("select", { defaultValue: currentRole, name: "role", children: userRoles.map((role) => /* @__PURE__ */ jsx33("option", { value: role, children: role }, role)) }),
|
|
7279
|
+
/* @__PURE__ */ jsx33("button", { disabled: updatingUserID === id, type: "submit", children: updatingUserID === id ? "Updating..." : "Update" })
|
|
5866
7280
|
] })
|
|
5867
7281
|
] }, id);
|
|
5868
7282
|
}) })
|
|
@@ -5873,14 +7287,14 @@ function AdminStudioToolsView(props) {
|
|
|
5873
7287
|
|
|
5874
7288
|
// src/admin/components/studio/OpenInStudioMenuItem.tsx
|
|
5875
7289
|
import { useDocumentInfo } from "@payloadcms/ui";
|
|
5876
|
-
import { jsx as
|
|
7290
|
+
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
5877
7291
|
function OpenInStudioMenuItem({ pagesPathBase = "/pages" }) {
|
|
5878
7292
|
const documentInfo = useDocumentInfo();
|
|
5879
7293
|
const id = documentInfo?.id;
|
|
5880
7294
|
if (!id) {
|
|
5881
7295
|
return null;
|
|
5882
7296
|
}
|
|
5883
|
-
return /* @__PURE__ */
|
|
7297
|
+
return /* @__PURE__ */ jsx34(
|
|
5884
7298
|
"a",
|
|
5885
7299
|
{
|
|
5886
7300
|
href: `${pagesPathBase}/${id}`,
|
|
@@ -5899,19 +7313,19 @@ function OpenInStudioMenuItem({ pagesPathBase = "/pages" }) {
|
|
|
5899
7313
|
}
|
|
5900
7314
|
|
|
5901
7315
|
// src/admin/components/studio/PageEditRedirectToStudio.tsx
|
|
5902
|
-
import { useEffect as
|
|
7316
|
+
import { useEffect as useEffect22 } from "react";
|
|
5903
7317
|
import { useDocumentInfo as useDocumentInfo2 } from "@payloadcms/ui";
|
|
5904
|
-
import { jsx as
|
|
7318
|
+
import { jsx as jsx35, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
5905
7319
|
function PageEditRedirectToStudio({ pagesPathBase = "/pages" }) {
|
|
5906
7320
|
const documentInfo = useDocumentInfo2();
|
|
5907
7321
|
const id = documentInfo?.id;
|
|
5908
|
-
|
|
7322
|
+
useEffect22(() => {
|
|
5909
7323
|
if (!id) {
|
|
5910
7324
|
return;
|
|
5911
7325
|
}
|
|
5912
7326
|
window.location.replace(`${pagesPathBase}/${id}`);
|
|
5913
7327
|
}, [id, pagesPathBase]);
|
|
5914
|
-
return /* @__PURE__ */
|
|
7328
|
+
return /* @__PURE__ */ jsxs31(
|
|
5915
7329
|
"div",
|
|
5916
7330
|
{
|
|
5917
7331
|
style: {
|
|
@@ -5923,18 +7337,61 @@ function PageEditRedirectToStudio({ pagesPathBase = "/pages" }) {
|
|
|
5923
7337
|
minHeight: "50vh"
|
|
5924
7338
|
},
|
|
5925
7339
|
children: [
|
|
5926
|
-
/* @__PURE__ */
|
|
5927
|
-
/* @__PURE__ */
|
|
5928
|
-
id ? /* @__PURE__ */
|
|
7340
|
+
/* @__PURE__ */ jsx35("h2", { style: { margin: 0 }, children: "Opening Editor..." }),
|
|
7341
|
+
/* @__PURE__ */ jsx35("p", { style: { color: "var(--theme-elevation-600)", margin: 0 }, children: "Redirecting to the custom page editor." }),
|
|
7342
|
+
id ? /* @__PURE__ */ jsx35("a", { href: `${pagesPathBase}/${id}`, children: "Continue to Editor" }) : /* @__PURE__ */ jsx35("a", { href: pagesPathBase, children: "Open Pages" })
|
|
7343
|
+
]
|
|
7344
|
+
}
|
|
7345
|
+
);
|
|
7346
|
+
}
|
|
7347
|
+
|
|
7348
|
+
// src/admin/components/studio/StudioDocumentRedirect.tsx
|
|
7349
|
+
import { useEffect as useEffect23 } from "react";
|
|
7350
|
+
import { useDocumentInfo as useDocumentInfo3 } from "@payloadcms/ui";
|
|
7351
|
+
import { jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
7352
|
+
function StudioDocumentRedirect({
|
|
7353
|
+
description = "Redirecting to the Studio view.",
|
|
7354
|
+
emptyHref,
|
|
7355
|
+
emptyLabel = "Open Studio",
|
|
7356
|
+
pathBase = "/forms",
|
|
7357
|
+
title = "Opening Studio..."
|
|
7358
|
+
}) {
|
|
7359
|
+
const adminBasePath = useAdminBasePath();
|
|
7360
|
+
const documentInfo = useDocumentInfo3();
|
|
7361
|
+
const id = documentInfo?.id;
|
|
7362
|
+
const fallbackHref = resolveAdminPath(adminBasePath, emptyHref || pathBase);
|
|
7363
|
+
useEffect23(() => {
|
|
7364
|
+
if (!id) {
|
|
7365
|
+
return;
|
|
7366
|
+
}
|
|
7367
|
+
const targetHref = resolveAdminPath(adminBasePath, `${pathBase}/${encodeURIComponent(String(id))}`);
|
|
7368
|
+
window.location.replace(targetHref);
|
|
7369
|
+
}, [adminBasePath, id, pathBase]);
|
|
7370
|
+
return /* @__PURE__ */ jsxs32(
|
|
7371
|
+
"div",
|
|
7372
|
+
{
|
|
7373
|
+
style: {
|
|
7374
|
+
alignItems: "center",
|
|
7375
|
+
display: "flex",
|
|
7376
|
+
flexDirection: "column",
|
|
7377
|
+
gap: "0.75rem",
|
|
7378
|
+
justifyContent: "center",
|
|
7379
|
+
minHeight: "50vh",
|
|
7380
|
+
textAlign: "center"
|
|
7381
|
+
},
|
|
7382
|
+
children: [
|
|
7383
|
+
/* @__PURE__ */ jsx36("h2", { style: { margin: 0 }, children: title }),
|
|
7384
|
+
/* @__PURE__ */ jsx36("p", { style: { color: "var(--theme-elevation-600)", margin: 0 }, children: description }),
|
|
7385
|
+
/* @__PURE__ */ jsx36("a", { href: fallbackHref, children: emptyLabel })
|
|
5929
7386
|
]
|
|
5930
7387
|
}
|
|
5931
7388
|
);
|
|
5932
7389
|
}
|
|
5933
7390
|
|
|
5934
7391
|
// src/admin/components/studio/StudioBackBreadcrumb.tsx
|
|
5935
|
-
import { useEffect as
|
|
7392
|
+
import { useEffect as useEffect24, useState as useState23 } from "react";
|
|
5936
7393
|
import { SetStepNav as SetStepNav5 } from "@payloadcms/ui";
|
|
5937
|
-
import { jsx as
|
|
7394
|
+
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
5938
7395
|
var toTitle = (slug) => slug.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
5939
7396
|
var buildNav = (pathname, adminBasePath) => {
|
|
5940
7397
|
if (pathname.includes("/globals/")) {
|
|
@@ -5979,8 +7436,8 @@ var buildNav = (pathname, adminBasePath) => {
|
|
|
5979
7436
|
};
|
|
5980
7437
|
function StudioBackBreadcrumb() {
|
|
5981
7438
|
const adminBasePath = useAdminBasePath();
|
|
5982
|
-
const [pathname, setPathname] =
|
|
5983
|
-
|
|
7439
|
+
const [pathname, setPathname] = useState23("");
|
|
7440
|
+
useEffect24(() => {
|
|
5984
7441
|
const update = () => setPathname(window.location.pathname);
|
|
5985
7442
|
update();
|
|
5986
7443
|
window.addEventListener("popstate", update);
|
|
@@ -5988,13 +7445,13 @@ function StudioBackBreadcrumb() {
|
|
|
5988
7445
|
}, []);
|
|
5989
7446
|
const nav = buildNav(pathname, adminBasePath);
|
|
5990
7447
|
if (!nav) return null;
|
|
5991
|
-
return /* @__PURE__ */
|
|
7448
|
+
return /* @__PURE__ */ jsx37(SetStepNav5, { nav });
|
|
5992
7449
|
}
|
|
5993
7450
|
|
|
5994
7451
|
// src/admin/components/studio/StudioContactFormRedirect.tsx
|
|
5995
|
-
import { useEffect as
|
|
5996
|
-
import { jsx as
|
|
5997
|
-
var
|
|
7452
|
+
import { useEffect as useEffect25 } from "react";
|
|
7453
|
+
import { jsx as jsx38, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
7454
|
+
var getPropString15 = (props, key, fallback) => {
|
|
5998
7455
|
if (!props || typeof props !== "object") return fallback;
|
|
5999
7456
|
const direct = props[key];
|
|
6000
7457
|
if (typeof direct === "string" && direct.length > 0) return direct;
|
|
@@ -6007,13 +7464,13 @@ var getPropString14 = (props, key, fallback) => {
|
|
|
6007
7464
|
};
|
|
6008
7465
|
function StudioContactFormRedirect(props) {
|
|
6009
7466
|
const adminBasePath = useAdminBasePath();
|
|
6010
|
-
const studioContactFormPath =
|
|
7467
|
+
const studioContactFormPath = getPropString15(props, "studioContactFormPath", "/contact-form");
|
|
6011
7468
|
const targetPath = resolveAdminPath(adminBasePath, studioContactFormPath);
|
|
6012
|
-
|
|
7469
|
+
useEffect25(() => {
|
|
6013
7470
|
if (window.location.pathname === targetPath) return;
|
|
6014
7471
|
window.location.replace(targetPath);
|
|
6015
7472
|
}, [targetPath]);
|
|
6016
|
-
return /* @__PURE__ */
|
|
7473
|
+
return /* @__PURE__ */ jsxs33(
|
|
6017
7474
|
"div",
|
|
6018
7475
|
{
|
|
6019
7476
|
style: {
|
|
@@ -6026,8 +7483,8 @@ function StudioContactFormRedirect(props) {
|
|
|
6026
7483
|
minHeight: "40vh"
|
|
6027
7484
|
},
|
|
6028
7485
|
children: [
|
|
6029
|
-
/* @__PURE__ */
|
|
6030
|
-
/* @__PURE__ */
|
|
7486
|
+
/* @__PURE__ */ jsx38("h2", { style: { margin: 0 }, children: "Opening Contact Form Editor..." }),
|
|
7487
|
+
/* @__PURE__ */ jsx38("a", { href: targetPath, children: "Continue" })
|
|
6031
7488
|
]
|
|
6032
7489
|
}
|
|
6033
7490
|
);
|
|
@@ -6038,6 +7495,9 @@ export {
|
|
|
6038
7495
|
AdminStudioContactFormView,
|
|
6039
7496
|
AdminStudioDashboard,
|
|
6040
7497
|
AdminStudioFooterGlobalView,
|
|
7498
|
+
AdminStudioFormDetailView,
|
|
7499
|
+
AdminStudioFormSubmissionView,
|
|
7500
|
+
AdminStudioFormUploadView,
|
|
6041
7501
|
AdminStudioFormsView,
|
|
6042
7502
|
AdminStudioGlobalsView,
|
|
6043
7503
|
AdminStudioHeaderGlobalView,
|
|
@@ -6063,6 +7523,7 @@ export {
|
|
|
6063
7523
|
StatusBadge,
|
|
6064
7524
|
StudioBackBreadcrumb,
|
|
6065
7525
|
StudioContactFormRedirect,
|
|
7526
|
+
StudioDocumentRedirect,
|
|
6066
7527
|
StudioSectionLayout,
|
|
6067
7528
|
ThemeProvider,
|
|
6068
7529
|
ThemeSwitcher,
|