@orion-studios/payload-studio 0.6.0-beta.17 → 0.6.0-beta.18
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 +1434 -122
- package/dist/admin/client.mjs +1429 -121
- package/dist/admin/index.js +100 -3
- package/dist/admin/index.mjs +1 -1
- package/dist/{chunk-XZQILJK3.mjs → chunk-3AHBR7RI.mjs} +100 -3
- package/dist/index.js +100 -3
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
package/dist/admin/client.mjs
CHANGED
|
@@ -5397,14 +5397,10 @@ function AdminStudioFormsView(props) {
|
|
|
5397
5397
|
"formSubmissionsCollectionSlug",
|
|
5398
5398
|
"form-submissions"
|
|
5399
5399
|
);
|
|
5400
|
-
const formUploadsCollectionSlug = getPropString13(props, "formUploadsCollectionSlug", "form-uploads");
|
|
5401
5400
|
const adminBasePath = useAdminBasePath();
|
|
5402
|
-
const
|
|
5403
|
-
const
|
|
5404
|
-
|
|
5405
|
-
`/collections/${formSubmissionsCollectionSlug}`
|
|
5406
|
-
);
|
|
5407
|
-
const rawUploadsPath = resolveAdminPath(adminBasePath, `/collections/${formUploadsCollectionSlug}`);
|
|
5401
|
+
const studioFormsPath = resolveAdminPath(adminBasePath, "/forms");
|
|
5402
|
+
const studioSubmissionsPath = resolveAdminPath(adminBasePath, "/forms/submissions");
|
|
5403
|
+
const studioUploadsPath = resolveAdminPath(adminBasePath, "/forms/uploads");
|
|
5408
5404
|
const [forms, setForms] = useState18([]);
|
|
5409
5405
|
const [submissions, setSubmissions] = useState18([]);
|
|
5410
5406
|
const [loading, setLoading] = useState18(true);
|
|
@@ -5564,7 +5560,7 @@ function AdminStudioFormsView(props) {
|
|
|
5564
5560
|
Link3,
|
|
5565
5561
|
{
|
|
5566
5562
|
className: "orion-admin-action-button orion-admin-action-button--soft",
|
|
5567
|
-
href: `${
|
|
5563
|
+
href: `${studioFormsPath}/${id}`,
|
|
5568
5564
|
children: "Open Form"
|
|
5569
5565
|
}
|
|
5570
5566
|
)
|
|
@@ -5666,7 +5662,7 @@ function AdminStudioFormsView(props) {
|
|
|
5666
5662
|
Link3,
|
|
5667
5663
|
{
|
|
5668
5664
|
className: "orion-admin-upload-chip",
|
|
5669
|
-
href: `${
|
|
5665
|
+
href: `${studioUploadsPath}/${uploadID}`,
|
|
5670
5666
|
children: uploadLabel
|
|
5671
5667
|
},
|
|
5672
5668
|
uploadID
|
|
@@ -5683,7 +5679,7 @@ function AdminStudioFormsView(props) {
|
|
|
5683
5679
|
Link3,
|
|
5684
5680
|
{
|
|
5685
5681
|
className: "orion-admin-action-button orion-admin-action-button--ghost",
|
|
5686
|
-
href: `${
|
|
5682
|
+
href: `${studioSubmissionsPath}/${submissionID}`,
|
|
5687
5683
|
children: "Open"
|
|
5688
5684
|
}
|
|
5689
5685
|
)
|
|
@@ -5703,92 +5699,1357 @@ function AdminStudioFormsView(props) {
|
|
|
5703
5699
|
) });
|
|
5704
5700
|
}
|
|
5705
5701
|
|
|
5706
|
-
// src/admin/components/studio/
|
|
5707
|
-
import
|
|
5708
|
-
import {
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
var
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5702
|
+
// src/admin/components/studio/AdminStudioFormDetailView.tsx
|
|
5703
|
+
import Link4 from "next/link";
|
|
5704
|
+
import { useEffect as useEffect18, useMemo as useMemo14, useState as useState19 } from "react";
|
|
5705
|
+
|
|
5706
|
+
// src/admin/components/studio/formsStudioShared.ts
|
|
5707
|
+
var FORM_TONES2 = [
|
|
5708
|
+
{
|
|
5709
|
+
accent: "var(--orion-cms-tone-1, var(--orion-cms-accent, var(--orion-admin-accent)))",
|
|
5710
|
+
accentBorder: "color-mix(in srgb, var(--orion-cms-tone-1, var(--orion-cms-accent, var(--orion-admin-accent))) 24%, transparent)",
|
|
5711
|
+
accentMist: "color-mix(in srgb, var(--orion-cms-tone-1, var(--orion-cms-accent, var(--orion-admin-accent))) 12%, transparent)",
|
|
5712
|
+
accentSoft: "color-mix(in srgb, var(--orion-cms-tone-1, var(--orion-cms-accent, var(--orion-admin-accent))) 7%, transparent)"
|
|
5713
|
+
},
|
|
5714
|
+
{
|
|
5715
|
+
accent: "var(--orion-cms-tone-2, var(--brand-secondary, var(--orion-admin-accent)))",
|
|
5716
|
+
accentBorder: "color-mix(in srgb, var(--orion-cms-tone-2, var(--brand-secondary, var(--orion-admin-accent))) 24%, transparent)",
|
|
5717
|
+
accentMist: "color-mix(in srgb, var(--orion-cms-tone-2, var(--brand-secondary, var(--orion-admin-accent))) 13%, transparent)",
|
|
5718
|
+
accentSoft: "color-mix(in srgb, var(--orion-cms-tone-2, var(--brand-secondary, var(--orion-admin-accent))) 8%, transparent)"
|
|
5719
|
+
},
|
|
5720
|
+
{
|
|
5721
|
+
accent: "var(--orion-cms-tone-3, color-mix(in srgb, var(--orion-cms-accent, var(--orion-admin-accent)) 72%, #5f816b))",
|
|
5722
|
+
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)",
|
|
5723
|
+
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)",
|
|
5724
|
+
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)"
|
|
5725
|
+
},
|
|
5726
|
+
{
|
|
5727
|
+
accent: "var(--orion-cms-tone-4, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 72%, #7a652e))",
|
|
5728
|
+
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)",
|
|
5729
|
+
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)",
|
|
5730
|
+
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)"
|
|
5731
|
+
},
|
|
5732
|
+
{
|
|
5733
|
+
accent: "var(--orion-cms-tone-5, color-mix(in srgb, var(--brand-secondary, var(--orion-admin-accent)) 68%, #8d4a40))",
|
|
5734
|
+
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)",
|
|
5735
|
+
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)",
|
|
5736
|
+
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)"
|
|
5737
|
+
}
|
|
5738
|
+
];
|
|
5739
|
+
var FORM_TONE_OVERRIDES2 = {
|
|
5740
|
+
"basket-request": FORM_TONES2[1],
|
|
5741
|
+
contact: FORM_TONES2[2],
|
|
5742
|
+
"vendor-inquiry": FORM_TONES2[0]
|
|
5715
5743
|
};
|
|
5716
|
-
var
|
|
5717
|
-
|
|
5718
|
-
|
|
5744
|
+
var IDENTITY_KEYS2 = /* @__PURE__ */ new Set(["contactEmail", "email", "firstName", "lastName", "name"]);
|
|
5745
|
+
var RESPONSE_FIELD_PREVIEW_LIMIT2 = 3;
|
|
5746
|
+
var getPropString14 = (props, key, fallback) => {
|
|
5747
|
+
if (!props || typeof props !== "object") return fallback;
|
|
5748
|
+
const direct = props[key];
|
|
5749
|
+
if (typeof direct === "string" && direct.length > 0) return direct;
|
|
5750
|
+
const clientProps = props.clientProps;
|
|
5751
|
+
if (clientProps && typeof clientProps === "object") {
|
|
5752
|
+
const nested = clientProps[key];
|
|
5753
|
+
if (typeof nested === "string" && nested.length > 0) return nested;
|
|
5754
|
+
}
|
|
5755
|
+
return fallback;
|
|
5756
|
+
};
|
|
5757
|
+
var getParam3 = (params, key) => {
|
|
5758
|
+
if (!params || typeof params !== "object") return null;
|
|
5759
|
+
const value = params[key];
|
|
5760
|
+
if (typeof value === "string") return value;
|
|
5761
|
+
if (Array.isArray(value) && typeof value[0] === "string") return value[0];
|
|
5762
|
+
return null;
|
|
5763
|
+
};
|
|
5764
|
+
var getIDFromPathname = (pathname, marker) => {
|
|
5765
|
+
const markerIndex = pathname.indexOf(marker);
|
|
5766
|
+
if (markerIndex < 0) return null;
|
|
5767
|
+
const id = pathname.slice(markerIndex + marker.length).split("/")[0];
|
|
5768
|
+
return id ? decodeURIComponent(id) : null;
|
|
5769
|
+
};
|
|
5770
|
+
var formatDate2 = (value) => {
|
|
5771
|
+
if (typeof value !== "string" || value.length === 0) return "Unknown date";
|
|
5772
|
+
const date = new Date(value);
|
|
5773
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
5774
|
+
return date.toLocaleString();
|
|
5775
|
+
};
|
|
5776
|
+
var formatFileSize2 = (value) => {
|
|
5777
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return null;
|
|
5778
|
+
if (value < 1024) return `${value} B`;
|
|
5779
|
+
if (value < 1024 * 1024) return `${(value / 1024).toFixed(1)} KB`;
|
|
5780
|
+
return `${(value / (1024 * 1024)).toFixed(1)} MB`;
|
|
5781
|
+
};
|
|
5782
|
+
var getFieldCount2 = (form) => Array.isArray(form.steps) ? form.steps.reduce((count, step) => {
|
|
5783
|
+
if (!step || typeof step !== "object") return count;
|
|
5784
|
+
const fields = step.fields;
|
|
5785
|
+
return count + (Array.isArray(fields) ? fields.length : 0);
|
|
5786
|
+
}, 0) : 0;
|
|
5787
|
+
var getFormID3 = (value) => {
|
|
5788
|
+
if (typeof value === "string" || typeof value === "number") return String(value);
|
|
5789
|
+
if (value && typeof value === "object") {
|
|
5790
|
+
const id = value.id;
|
|
5791
|
+
if (typeof id === "string" || typeof id === "number") return String(id);
|
|
5792
|
+
}
|
|
5793
|
+
return "";
|
|
5794
|
+
};
|
|
5795
|
+
var getUploads2 = (value) => Array.isArray(value) ? value.map((entry) => {
|
|
5796
|
+
if (typeof entry === "string" || typeof entry === "number") {
|
|
5797
|
+
return { id: entry };
|
|
5798
|
+
}
|
|
5799
|
+
return entry && typeof entry === "object" ? entry : null;
|
|
5800
|
+
}).filter((entry) => Boolean(entry)) : [];
|
|
5801
|
+
var getNameAndEmail2 = (data) => {
|
|
5802
|
+
if (!data || typeof data !== "object") return {};
|
|
5803
|
+
const record = data;
|
|
5804
|
+
const email = typeof record.email === "string" ? record.email : typeof record.contactEmail === "string" ? record.contactEmail : void 0;
|
|
5805
|
+
const firstName = typeof record.firstName === "string" ? record.firstName : void 0;
|
|
5806
|
+
const lastName = typeof record.lastName === "string" ? record.lastName : void 0;
|
|
5807
|
+
const fallbackName = typeof record.name === "string" ? record.name : void 0;
|
|
5808
|
+
const joinedName = [firstName, lastName].filter(Boolean).join(" ").trim();
|
|
5809
|
+
return {
|
|
5810
|
+
...email ? { email } : {},
|
|
5811
|
+
...joinedName ? { name: joinedName } : fallbackName ? { name: fallbackName } : {}
|
|
5812
|
+
};
|
|
5813
|
+
};
|
|
5814
|
+
var humanizeKey2 = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").replace(/\s+/g, " ").trim().replace(/^./, (char) => char.toUpperCase());
|
|
5815
|
+
var buildFieldLabelMap2 = (form) => {
|
|
5816
|
+
const labels = /* @__PURE__ */ new Map();
|
|
5817
|
+
for (const step of Array.isArray(form.steps) ? form.steps : []) {
|
|
5818
|
+
const fields = step && typeof step === "object" ? step.fields : null;
|
|
5819
|
+
for (const field of Array.isArray(fields) ? fields : []) {
|
|
5820
|
+
const name = field && typeof field === "object" && typeof field.name === "string" ? field.name.trim() : "";
|
|
5821
|
+
const label = field && typeof field === "object" && typeof field.label === "string" ? field.label.trim() : "";
|
|
5822
|
+
if (name) {
|
|
5823
|
+
labels.set(name, label || humanizeKey2(name));
|
|
5824
|
+
}
|
|
5825
|
+
}
|
|
5826
|
+
}
|
|
5827
|
+
return labels;
|
|
5828
|
+
};
|
|
5829
|
+
var truncateText2 = (value, maxLength = 64) => {
|
|
5830
|
+
const normalized = value.replace(/\s+/g, " ").trim();
|
|
5831
|
+
if (normalized.length <= maxLength) return normalized;
|
|
5832
|
+
return `${normalized.slice(0, maxLength - 1).trimEnd()}...`;
|
|
5833
|
+
};
|
|
5834
|
+
var formatPreviewValue2 = (value) => {
|
|
5835
|
+
if (value === null || value === void 0) return null;
|
|
5836
|
+
if (typeof value === "boolean") return value ? "Yes" : "No";
|
|
5837
|
+
if (typeof value === "number") return String(value);
|
|
5838
|
+
if (typeof value === "string") {
|
|
5839
|
+
const trimmed = value.trim();
|
|
5840
|
+
return trimmed ? truncateText2(trimmed, 72) : null;
|
|
5841
|
+
}
|
|
5842
|
+
if (Array.isArray(value)) {
|
|
5843
|
+
const joined = value.map((entry) => String(entry).trim()).filter(Boolean).join(", ");
|
|
5844
|
+
return joined ? truncateText2(joined, 72) : null;
|
|
5845
|
+
}
|
|
5846
|
+
if (typeof value === "object") {
|
|
5847
|
+
return truncateText2(JSON.stringify(value), 72);
|
|
5848
|
+
}
|
|
5849
|
+
return truncateText2(String(value), 72);
|
|
5850
|
+
};
|
|
5851
|
+
var getPreviewFields2 = (data, fieldLabels) => {
|
|
5852
|
+
if (!data || typeof data !== "object") return [];
|
|
5853
|
+
return Object.entries(data).filter(([key]) => !IDENTITY_KEYS2.has(key)).map(([key, value]) => {
|
|
5854
|
+
const formatted = formatPreviewValue2(value);
|
|
5855
|
+
if (!formatted) return null;
|
|
5856
|
+
return {
|
|
5857
|
+
label: fieldLabels.get(key) || humanizeKey2(key),
|
|
5858
|
+
value: formatted
|
|
5859
|
+
};
|
|
5860
|
+
}).filter((entry) => Boolean(entry)).slice(0, RESPONSE_FIELD_PREVIEW_LIMIT2);
|
|
5861
|
+
};
|
|
5862
|
+
var getInitials2 = (...values) => {
|
|
5863
|
+
const source = values.find((value) => typeof value === "string" && value.trim().length > 0);
|
|
5864
|
+
if (!source) return "FM";
|
|
5865
|
+
const cleaned = source.replace(/[^a-z0-9]+/gi, " ").trim();
|
|
5866
|
+
if (!cleaned) return "FM";
|
|
5867
|
+
const parts = cleaned.split(/\s+/).filter(Boolean);
|
|
5868
|
+
if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
|
|
5869
|
+
return `${parts[0][0] || ""}${parts[1][0] || ""}`.toUpperCase();
|
|
5870
|
+
};
|
|
5871
|
+
var getHash2 = (value) => {
|
|
5872
|
+
let hash = 0;
|
|
5873
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
5874
|
+
hash = hash * 31 + value.charCodeAt(index) >>> 0;
|
|
5875
|
+
}
|
|
5876
|
+
return hash;
|
|
5877
|
+
};
|
|
5878
|
+
var normalizeToneKey2 = (value) => value?.trim().toLowerCase() || "";
|
|
5879
|
+
var getFormTone2 = (slug, fallbackSeed) => {
|
|
5880
|
+
const normalizedSlug = normalizeToneKey2(slug);
|
|
5881
|
+
if (normalizedSlug && FORM_TONE_OVERRIDES2[normalizedSlug]) {
|
|
5882
|
+
return FORM_TONE_OVERRIDES2[normalizedSlug];
|
|
5883
|
+
}
|
|
5884
|
+
const normalizedSeed = normalizeToneKey2(fallbackSeed);
|
|
5885
|
+
if (normalizedSeed && FORM_TONE_OVERRIDES2[normalizedSeed]) {
|
|
5886
|
+
return FORM_TONE_OVERRIDES2[normalizedSeed];
|
|
5887
|
+
}
|
|
5888
|
+
return FORM_TONES2[getHash2(slug || fallbackSeed) % FORM_TONES2.length];
|
|
5889
|
+
};
|
|
5890
|
+
var getFormToneStyle2 = (slug, fallbackSeed) => {
|
|
5891
|
+
const tone = getFormTone2(slug, fallbackSeed);
|
|
5892
|
+
return {
|
|
5893
|
+
["--form-accent"]: tone.accent,
|
|
5894
|
+
["--form-accent-border"]: tone.accentBorder,
|
|
5895
|
+
["--form-accent-mist"]: tone.accentMist,
|
|
5896
|
+
["--form-accent-soft"]: tone.accentSoft
|
|
5897
|
+
};
|
|
5898
|
+
};
|
|
5899
|
+
var getFormTitle2 = (value) => {
|
|
5900
|
+
if (value && typeof value === "object" && typeof value.title === "string") {
|
|
5901
|
+
const title = value.title.trim();
|
|
5902
|
+
if (title.length > 0) return title;
|
|
5903
|
+
}
|
|
5904
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
5905
|
+
return value;
|
|
5906
|
+
}
|
|
5907
|
+
return "Untitled Form";
|
|
5908
|
+
};
|
|
5909
|
+
|
|
5910
|
+
// src/admin/components/studio/AdminStudioFormDetailView.tsx
|
|
5911
|
+
import { Fragment as Fragment5, jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
5912
|
+
var getNonEmptyText = (value, fallback = "") => typeof value === "string" && value.trim().length > 0 ? value : fallback;
|
|
5913
|
+
var formatStepsText = (value) => {
|
|
5914
|
+
if (!Array.isArray(value)) {
|
|
5915
|
+
return "[]";
|
|
5916
|
+
}
|
|
5917
|
+
try {
|
|
5918
|
+
return JSON.stringify(value, null, 2);
|
|
5919
|
+
} catch {
|
|
5920
|
+
return "[]";
|
|
5921
|
+
}
|
|
5922
|
+
};
|
|
5923
|
+
var toEditorState = (doc) => {
|
|
5924
|
+
const emails = doc.emails && typeof doc.emails === "object" ? doc.emails : null;
|
|
5925
|
+
const adminRecipients = Array.isArray(emails?.adminRecipients) ? emails?.adminRecipients.map(
|
|
5926
|
+
(entry) => entry && typeof entry === "object" && typeof entry.email === "string" ? entry.email.trim() : ""
|
|
5927
|
+
).filter(Boolean) : [];
|
|
5928
|
+
return {
|
|
5929
|
+
adminRecipientsText: adminRecipients.join("\n"),
|
|
5930
|
+
adminSubject: getNonEmptyText(emails?.adminSubject),
|
|
5931
|
+
confirmationHeading: getNonEmptyText(emails?.confirmationHeading),
|
|
5932
|
+
confirmationMessage: getNonEmptyText(emails?.confirmationMessage),
|
|
5933
|
+
confirmationSubject: getNonEmptyText(emails?.confirmationSubject),
|
|
5934
|
+
sendAdmin: emails?.sendAdmin !== false,
|
|
5935
|
+
sendConfirmation: emails?.sendConfirmation !== false,
|
|
5936
|
+
slug: getNonEmptyText(doc.slug),
|
|
5937
|
+
stepsText: formatStepsText(doc.steps),
|
|
5938
|
+
submitLabel: getNonEmptyText(doc.submitLabel, "Submit"),
|
|
5939
|
+
successMessage: getNonEmptyText(doc.successMessage),
|
|
5940
|
+
title: getNonEmptyText(doc.title, "Untitled Form")
|
|
5941
|
+
};
|
|
5942
|
+
};
|
|
5943
|
+
var checkboxLabelStyle = {
|
|
5944
|
+
alignItems: "center",
|
|
5945
|
+
display: "flex",
|
|
5946
|
+
gap: "0.6rem"
|
|
5947
|
+
};
|
|
5948
|
+
var codeStyle = {
|
|
5949
|
+
background: "color-mix(in srgb, var(--orion-admin-card-bg) 82%, black)",
|
|
5950
|
+
border: "1px solid var(--orion-admin-card-border)",
|
|
5951
|
+
borderRadius: "var(--orion-admin-radius-sm)",
|
|
5952
|
+
color: "var(--orion-admin-text)",
|
|
5953
|
+
fontFamily: "ui-monospace, SFMono-Regular, SFMono-Regular, Menlo, monospace",
|
|
5954
|
+
fontSize: "0.86rem",
|
|
5955
|
+
lineHeight: 1.55,
|
|
5956
|
+
margin: 0,
|
|
5957
|
+
maxHeight: "28rem",
|
|
5958
|
+
overflow: "auto",
|
|
5959
|
+
padding: "0.9rem",
|
|
5960
|
+
whiteSpace: "pre-wrap"
|
|
5961
|
+
};
|
|
5962
|
+
var sectionGridStyle = {
|
|
5963
|
+
display: "grid",
|
|
5964
|
+
gap: "1rem",
|
|
5965
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))"
|
|
5966
|
+
};
|
|
5967
|
+
function getFormIDFromPathname(pathname) {
|
|
5968
|
+
const marker = "/forms/";
|
|
5969
|
+
const raw = getIDFromPathname(pathname, marker);
|
|
5970
|
+
if (!raw || raw === "submissions" || raw === "uploads") {
|
|
5971
|
+
return null;
|
|
5972
|
+
}
|
|
5973
|
+
return raw;
|
|
5974
|
+
}
|
|
5975
|
+
function AdminStudioFormDetailView(props) {
|
|
5976
|
+
const formsCollectionSlug = getPropString14(props, "formsCollectionSlug", "forms");
|
|
5977
|
+
const formSubmissionsCollectionSlug = getPropString14(
|
|
5978
|
+
props,
|
|
5979
|
+
"formSubmissionsCollectionSlug",
|
|
5980
|
+
"form-submissions"
|
|
5981
|
+
);
|
|
5719
5982
|
const adminBasePath = useAdminBasePath();
|
|
5720
|
-
const
|
|
5983
|
+
const formsPath = resolveAdminPath(adminBasePath, "/forms");
|
|
5984
|
+
const formIDFromParams = useMemo14(() => getParam3(props.params, "id"), [props.params]);
|
|
5985
|
+
const [formID, setFormID] = useState19(formIDFromParams);
|
|
5986
|
+
const [didResolvePathFallback, setDidResolvePathFallback] = useState19(false);
|
|
5987
|
+
const [doc, setDoc] = useState19(null);
|
|
5988
|
+
const [submissions, setSubmissions] = useState19([]);
|
|
5989
|
+
const [editorState, setEditorState] = useState19(null);
|
|
5721
5990
|
const [loading, setLoading] = useState19(true);
|
|
5722
5991
|
const [error, setError] = useState19(null);
|
|
5992
|
+
const [saving, setSaving] = useState19(false);
|
|
5723
5993
|
const [savedMessage, setSavedMessage] = useState19(null);
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
children: /* @__PURE__ */ jsxs27("div", { className: "orion-admin-card", children: [
|
|
5737
|
-
/* @__PURE__ */ jsx30("strong", { children: "Access denied" }),
|
|
5738
|
-
/* @__PURE__ */ jsx30("span", { children: "This section is restricted to administrator and developer accounts." })
|
|
5739
|
-
] })
|
|
5740
|
-
}
|
|
5741
|
-
) });
|
|
5742
|
-
}
|
|
5743
|
-
const loadUsers = async () => {
|
|
5994
|
+
useEffect18(() => {
|
|
5995
|
+
if (formIDFromParams) {
|
|
5996
|
+
setFormID(formIDFromParams);
|
|
5997
|
+
setDidResolvePathFallback(true);
|
|
5998
|
+
return;
|
|
5999
|
+
}
|
|
6000
|
+
if (typeof window !== "undefined") {
|
|
6001
|
+
setFormID(getFormIDFromPathname(window.location.pathname));
|
|
6002
|
+
}
|
|
6003
|
+
setDidResolvePathFallback(true);
|
|
6004
|
+
}, [formIDFromParams]);
|
|
6005
|
+
const loadDoc = async (id) => {
|
|
5744
6006
|
setLoading(true);
|
|
5745
6007
|
setError(null);
|
|
5746
6008
|
try {
|
|
5747
|
-
const
|
|
5748
|
-
depth: "
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
sort: "email"
|
|
5752
|
-
});
|
|
5753
|
-
const response = await fetch(`/api/users?${params.toString()}`, {
|
|
5754
|
-
credentials: "include"
|
|
6009
|
+
const submissionsParams = new URLSearchParams({
|
|
6010
|
+
depth: "1",
|
|
6011
|
+
limit: "25",
|
|
6012
|
+
sort: "-submittedAt"
|
|
5755
6013
|
});
|
|
5756
|
-
|
|
5757
|
-
|
|
6014
|
+
submissionsParams.set("where[form][equals]", id);
|
|
6015
|
+
const [formResponse, submissionsResponse] = await Promise.all([
|
|
6016
|
+
fetch(`/api/${formsCollectionSlug}/${encodeURIComponent(id)}?depth=0&draft=true`, {
|
|
6017
|
+
credentials: "include"
|
|
6018
|
+
}),
|
|
6019
|
+
fetch(`/api/${formSubmissionsCollectionSlug}?${submissionsParams.toString()}`, {
|
|
6020
|
+
credentials: "include"
|
|
6021
|
+
})
|
|
6022
|
+
]);
|
|
6023
|
+
if (!formResponse.ok) {
|
|
6024
|
+
throw new Error(`Failed to load form (${formResponse.status}).`);
|
|
5758
6025
|
}
|
|
5759
|
-
|
|
5760
|
-
|
|
6026
|
+
if (!submissionsResponse.ok) {
|
|
6027
|
+
throw new Error(`Failed to load submissions (${submissionsResponse.status}).`);
|
|
6028
|
+
}
|
|
6029
|
+
const nextDoc = await formResponse.json();
|
|
6030
|
+
const submissionsPayload = await submissionsResponse.json();
|
|
6031
|
+
const nextSubmissions = Array.isArray(submissionsPayload.docs) ? submissionsPayload.docs : [];
|
|
6032
|
+
setDoc(nextDoc);
|
|
6033
|
+
setEditorState(toEditorState(nextDoc));
|
|
6034
|
+
setSubmissions(nextSubmissions);
|
|
5761
6035
|
} catch (loadError) {
|
|
5762
|
-
setError(loadError instanceof Error ? loadError.message : "Failed to load
|
|
6036
|
+
setError(loadError instanceof Error ? loadError.message : "Failed to load form.");
|
|
6037
|
+
setDoc(null);
|
|
6038
|
+
setEditorState(null);
|
|
6039
|
+
setSubmissions([]);
|
|
5763
6040
|
} finally {
|
|
5764
6041
|
setLoading(false);
|
|
5765
6042
|
}
|
|
5766
6043
|
};
|
|
5767
6044
|
useEffect18(() => {
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
6045
|
+
if (!formID) {
|
|
6046
|
+
return;
|
|
6047
|
+
}
|
|
6048
|
+
void loadDoc(formID);
|
|
6049
|
+
}, [formID, formsCollectionSlug, formSubmissionsCollectionSlug]);
|
|
6050
|
+
const save = async (event) => {
|
|
5771
6051
|
event.preventDefault();
|
|
5772
|
-
|
|
5773
|
-
|
|
6052
|
+
if (!formID || !editorState) {
|
|
6053
|
+
return;
|
|
6054
|
+
}
|
|
6055
|
+
setSaving(true);
|
|
5774
6056
|
setError(null);
|
|
5775
6057
|
setSavedMessage(null);
|
|
5776
6058
|
try {
|
|
5777
|
-
const
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
const fullName = String(formData.get("fullName") || "").trim();
|
|
5781
|
-
const role = normalizeRole(String(formData.get("role") || "editor").trim());
|
|
5782
|
-
if (!email || !password) {
|
|
5783
|
-
throw new Error("Email and password are required.");
|
|
6059
|
+
const parsedSteps = JSON.parse(editorState.stepsText);
|
|
6060
|
+
if (!Array.isArray(parsedSteps)) {
|
|
6061
|
+
throw new Error("Structure JSON must be an array of steps.");
|
|
5784
6062
|
}
|
|
5785
|
-
const
|
|
5786
|
-
|
|
5787
|
-
email,
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
6063
|
+
const payload = {
|
|
6064
|
+
emails: {
|
|
6065
|
+
adminRecipients: editorState.adminRecipientsText.split("\n").map((value) => value.trim()).filter(Boolean).map((email) => ({ email })),
|
|
6066
|
+
adminSubject: editorState.adminSubject.trim(),
|
|
6067
|
+
confirmationHeading: editorState.confirmationHeading.trim(),
|
|
6068
|
+
confirmationMessage: editorState.confirmationMessage,
|
|
6069
|
+
confirmationSubject: editorState.confirmationSubject.trim(),
|
|
6070
|
+
sendAdmin: editorState.sendAdmin,
|
|
6071
|
+
sendConfirmation: editorState.sendConfirmation
|
|
6072
|
+
},
|
|
6073
|
+
slug: editorState.slug.trim(),
|
|
6074
|
+
steps: parsedSteps,
|
|
6075
|
+
submitLabel: editorState.submitLabel.trim(),
|
|
6076
|
+
successMessage: editorState.successMessage,
|
|
6077
|
+
title: editorState.title.trim()
|
|
6078
|
+
};
|
|
6079
|
+
const response = await fetch(`/api/${formsCollectionSlug}/${encodeURIComponent(formID)}`, {
|
|
6080
|
+
body: JSON.stringify(payload),
|
|
6081
|
+
credentials: "include",
|
|
6082
|
+
headers: {
|
|
6083
|
+
"Content-Type": "application/json"
|
|
6084
|
+
},
|
|
6085
|
+
method: "PATCH"
|
|
6086
|
+
});
|
|
6087
|
+
if (!response.ok) {
|
|
6088
|
+
throw new Error(`Failed to save form (${response.status}).`);
|
|
6089
|
+
}
|
|
6090
|
+
const nextDoc = await response.json();
|
|
6091
|
+
setDoc(nextDoc);
|
|
6092
|
+
setEditorState(toEditorState(nextDoc));
|
|
6093
|
+
setSavedMessage("Saved.");
|
|
6094
|
+
} catch (saveError) {
|
|
6095
|
+
setError(saveError instanceof Error ? saveError.message : "Failed to save form.");
|
|
6096
|
+
} finally {
|
|
6097
|
+
setSaving(false);
|
|
6098
|
+
}
|
|
6099
|
+
};
|
|
6100
|
+
if (!formID && !didResolvePathFallback) {
|
|
6101
|
+
return /* @__PURE__ */ jsx30(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsx30(
|
|
6102
|
+
AdminPage,
|
|
6103
|
+
{
|
|
6104
|
+
breadcrumbs: [
|
|
6105
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
6106
|
+
{ label: "Forms", href: formsPath },
|
|
6107
|
+
{ label: "Form" }
|
|
6108
|
+
],
|
|
6109
|
+
description: "Loading form workspace...",
|
|
6110
|
+
title: "Form",
|
|
6111
|
+
children: /* @__PURE__ */ jsx30(Fragment5, {})
|
|
6112
|
+
}
|
|
6113
|
+
) });
|
|
6114
|
+
}
|
|
6115
|
+
const title = doc && typeof doc.title === "string" && doc.title.trim().length > 0 ? doc.title : "Form";
|
|
6116
|
+
const slug = doc && typeof doc.slug === "string" ? doc.slug : "";
|
|
6117
|
+
const toneStyle = getFormToneStyle2(slug, title || formID || "form");
|
|
6118
|
+
const fieldLabels = doc ? buildFieldLabelMap2(doc) : /* @__PURE__ */ new Map();
|
|
6119
|
+
const latestSubmission = submissions[0];
|
|
6120
|
+
const stepCount = doc && Array.isArray(doc.steps) ? doc.steps.length : 0;
|
|
6121
|
+
const fieldCount = doc ? getFieldCount2(doc) : 0;
|
|
6122
|
+
return /* @__PURE__ */ jsx30(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsxs27(
|
|
6123
|
+
AdminPage,
|
|
6124
|
+
{
|
|
6125
|
+
breadcrumbs: [
|
|
6126
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
6127
|
+
{ label: "Forms", href: formsPath },
|
|
6128
|
+
{ label: title }
|
|
6129
|
+
],
|
|
6130
|
+
description: "Manage form content and review recent responses without leaving Studio.",
|
|
6131
|
+
title: "Form",
|
|
6132
|
+
children: [
|
|
6133
|
+
loading ? /* @__PURE__ */ jsx30("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
|
|
6134
|
+
error ? /* @__PURE__ */ jsx30("div", { className: "orion-admin-error", children: error }) : null,
|
|
6135
|
+
savedMessage ? /* @__PURE__ */ jsx30("div", { className: "orion-admin-success", children: savedMessage }) : null,
|
|
6136
|
+
!loading && !error && doc && editorState && formID ? /* @__PURE__ */ jsxs27("div", { style: { display: "grid", gap: "1rem" }, children: [
|
|
6137
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-forms-summary-grid", children: [
|
|
6138
|
+
/* @__PURE__ */ jsxs27("article", { className: "orion-admin-overview-stat", children: [
|
|
6139
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-overview-stat-label", children: "Workflow steps" }),
|
|
6140
|
+
/* @__PURE__ */ jsx30("strong", { children: stepCount }),
|
|
6141
|
+
/* @__PURE__ */ jsx30("p", { children: "Configured stages in the public form flow." })
|
|
6142
|
+
] }),
|
|
6143
|
+
/* @__PURE__ */ jsxs27("article", { className: "orion-admin-overview-stat", children: [
|
|
6144
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-overview-stat-label", children: "Fields" }),
|
|
6145
|
+
/* @__PURE__ */ jsx30("strong", { children: fieldCount }),
|
|
6146
|
+
/* @__PURE__ */ jsx30("p", { children: "Total visible and conditional fields across every step." })
|
|
6147
|
+
] }),
|
|
6148
|
+
/* @__PURE__ */ jsxs27("article", { className: "orion-admin-overview-stat", children: [
|
|
6149
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-overview-stat-label", children: "Recent submissions" }),
|
|
6150
|
+
/* @__PURE__ */ jsx30("strong", { children: submissions.length }),
|
|
6151
|
+
/* @__PURE__ */ jsx30("p", { children: latestSubmission ? `Latest response ${formatDate2(latestSubmission.submittedAt)}` : "No responses have been recorded yet." })
|
|
6152
|
+
] })
|
|
6153
|
+
] }),
|
|
6154
|
+
/* @__PURE__ */ jsxs27("section", { className: "orion-admin-form-board", style: toneStyle, children: [
|
|
6155
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-form-board-header", children: [
|
|
6156
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-form-board-heading", children: [
|
|
6157
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-form-board-kicker-row", children: [
|
|
6158
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-form-board-kicker", children: slug || "No slug set" }),
|
|
6159
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-form-board-meta", children: doc.updatedAt ? `Updated ${formatDate2(doc.updatedAt)}` : "Update time unavailable" })
|
|
6160
|
+
] }),
|
|
6161
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-form-board-title-row", children: [
|
|
6162
|
+
/* @__PURE__ */ jsx30("div", { className: "orion-admin-form-board-mark", children: getInitials2(title, slug) }),
|
|
6163
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-form-board-copy", children: [
|
|
6164
|
+
/* @__PURE__ */ jsx30("h2", { className: "orion-admin-form-board-title", children: title }),
|
|
6165
|
+
/* @__PURE__ */ jsx30("p", { className: "orion-admin-form-board-subtitle", children: editorState.successMessage.trim().length > 0 ? editorState.successMessage : "No success message set." })
|
|
6166
|
+
] })
|
|
6167
|
+
] })
|
|
6168
|
+
] }),
|
|
6169
|
+
/* @__PURE__ */ jsx30("div", { className: "orion-admin-form-board-actions", children: /* @__PURE__ */ jsxs27("div", { className: "orion-admin-form-board-count", children: [
|
|
6170
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-form-board-count-value", children: submissions.length }),
|
|
6171
|
+
/* @__PURE__ */ jsxs27("span", { className: "orion-admin-form-board-count-label", children: [
|
|
6172
|
+
"response",
|
|
6173
|
+
submissions.length === 1 ? "" : "s"
|
|
6174
|
+
] })
|
|
6175
|
+
] }) })
|
|
6176
|
+
] }),
|
|
6177
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-form-board-metrics", children: [
|
|
6178
|
+
/* @__PURE__ */ jsxs27("article", { className: "orion-admin-form-metric", children: [
|
|
6179
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-form-metric-label", children: "Submit button" }),
|
|
6180
|
+
/* @__PURE__ */ jsx30("strong", { className: "orion-admin-form-metric-value is-copy", children: editorState.submitLabel || "Submit" })
|
|
6181
|
+
] }),
|
|
6182
|
+
/* @__PURE__ */ jsxs27("article", { className: "orion-admin-form-metric", children: [
|
|
6183
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-form-metric-label", children: "Admin notifications" }),
|
|
6184
|
+
/* @__PURE__ */ jsx30("strong", { className: "orion-admin-form-metric-value", children: editorState.sendAdmin ? "On" : "Off" })
|
|
6185
|
+
] }),
|
|
6186
|
+
/* @__PURE__ */ jsxs27("article", { className: "orion-admin-form-metric", children: [
|
|
6187
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-form-metric-label", children: "Confirmation email" }),
|
|
6188
|
+
/* @__PURE__ */ jsx30("strong", { className: "orion-admin-form-metric-value", children: editorState.sendConfirmation ? "On" : "Off" })
|
|
6189
|
+
] }),
|
|
6190
|
+
/* @__PURE__ */ jsxs27("article", { className: "orion-admin-form-metric", children: [
|
|
6191
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-form-metric-label", children: "Latest response" }),
|
|
6192
|
+
/* @__PURE__ */ jsx30("strong", { className: "orion-admin-form-metric-value is-copy", children: latestSubmission ? formatDate2(latestSubmission.submittedAt) : "No activity yet" })
|
|
6193
|
+
] })
|
|
6194
|
+
] })
|
|
6195
|
+
] }),
|
|
6196
|
+
/* @__PURE__ */ jsxs27("div", { style: sectionGridStyle, children: [
|
|
6197
|
+
/* @__PURE__ */ jsxs27("div", { style: { display: "grid", gap: "1rem" }, children: [
|
|
6198
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-card", children: [
|
|
6199
|
+
/* @__PURE__ */ jsx30("strong", { children: "Step preview" }),
|
|
6200
|
+
/* @__PURE__ */ jsx30("span", { children: "Review the configured workflow structure before editing the JSON source." }),
|
|
6201
|
+
/* @__PURE__ */ jsx30("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: Array.isArray(doc.steps) && doc.steps.length > 0 ? doc.steps.map((step, stepIndex) => {
|
|
6202
|
+
const record = step && typeof step === "object" && !Array.isArray(step) ? step : null;
|
|
6203
|
+
const fields = Array.isArray(record?.fields) ? record.fields : [];
|
|
6204
|
+
return /* @__PURE__ */ jsxs27("div", { className: "orion-admin-form", children: [
|
|
6205
|
+
/* @__PURE__ */ jsxs27("div", { children: [
|
|
6206
|
+
/* @__PURE__ */ jsxs27("strong", { children: [
|
|
6207
|
+
"Step ",
|
|
6208
|
+
stepIndex + 1,
|
|
6209
|
+
": ",
|
|
6210
|
+
getNonEmptyText(record?.title, "Untitled Step")
|
|
6211
|
+
] }),
|
|
6212
|
+
getNonEmptyText(record?.subtitle) ? /* @__PURE__ */ jsx30("div", { className: "orion-admin-list-meta", style: { marginTop: "0.25rem" }, children: getNonEmptyText(record?.subtitle) }) : null
|
|
6213
|
+
] }),
|
|
6214
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-inline-actions", children: [
|
|
6215
|
+
/* @__PURE__ */ jsxs27("span", { className: "orion-admin-pill", children: [
|
|
6216
|
+
fields.length,
|
|
6217
|
+
" field",
|
|
6218
|
+
fields.length === 1 ? "" : "s"
|
|
6219
|
+
] }),
|
|
6220
|
+
record?.allowSkip === true ? /* @__PURE__ */ jsx30("span", { className: "orion-admin-pill", children: "Can skip" }) : null,
|
|
6221
|
+
getNonEmptyText(record?.nextLabel) ? /* @__PURE__ */ jsxs27("span", { className: "orion-admin-pill", children: [
|
|
6222
|
+
"Next: ",
|
|
6223
|
+
getNonEmptyText(record?.nextLabel)
|
|
6224
|
+
] }) : null
|
|
6225
|
+
] }),
|
|
6226
|
+
fields.length > 0 ? /* @__PURE__ */ jsx30("div", { className: "orion-admin-list", children: fields.map((field, fieldIndex) => {
|
|
6227
|
+
const fieldRecord = field && typeof field === "object" && !Array.isArray(field) ? field : null;
|
|
6228
|
+
const type = getNonEmptyText(fieldRecord?.type, "text");
|
|
6229
|
+
const label = getNonEmptyText(
|
|
6230
|
+
fieldRecord?.label,
|
|
6231
|
+
getNonEmptyText(fieldRecord?.name, `Field ${fieldIndex + 1}`)
|
|
6232
|
+
);
|
|
6233
|
+
const helpText = getNonEmptyText(fieldRecord?.helpText);
|
|
6234
|
+
const condition = fieldRecord?.condition && typeof fieldRecord.condition === "object" && !Array.isArray(fieldRecord.condition) ? fieldRecord.condition : null;
|
|
6235
|
+
return /* @__PURE__ */ jsx30("div", { className: "orion-admin-list-item", children: /* @__PURE__ */ jsxs27("div", { children: [
|
|
6236
|
+
/* @__PURE__ */ jsx30("strong", { children: label }),
|
|
6237
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-list-meta", children: [
|
|
6238
|
+
type,
|
|
6239
|
+
fieldRecord?.required === true ? " \xB7 required" : "",
|
|
6240
|
+
condition?.field && condition?.equals ? ` \xB7 when ${String(condition.field)} = ${String(condition.equals)}` : ""
|
|
6241
|
+
] }),
|
|
6242
|
+
helpText ? /* @__PURE__ */ jsx30(
|
|
6243
|
+
"div",
|
|
6244
|
+
{
|
|
6245
|
+
className: "orion-admin-list-meta",
|
|
6246
|
+
style: { marginTop: "0.25rem" },
|
|
6247
|
+
children: helpText
|
|
6248
|
+
}
|
|
6249
|
+
) : null
|
|
6250
|
+
] }) }, `field-${fieldIndex}`);
|
|
6251
|
+
}) }) : /* @__PURE__ */ jsx30("div", { className: "orion-admin-list-meta", children: "This step has no fields." })
|
|
6252
|
+
] }, `step-${stepIndex}`);
|
|
6253
|
+
}) : /* @__PURE__ */ jsxs27("div", { className: "orion-admin-empty-state", children: [
|
|
6254
|
+
/* @__PURE__ */ jsx30("strong", { children: "No steps configured" }),
|
|
6255
|
+
/* @__PURE__ */ jsx30("span", { children: "Add at least one step in the JSON editor to publish this form." })
|
|
6256
|
+
] }) })
|
|
6257
|
+
] }),
|
|
6258
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-card", children: [
|
|
6259
|
+
/* @__PURE__ */ jsx30("strong", { children: "Recent submissions" }),
|
|
6260
|
+
/* @__PURE__ */ jsx30("span", { children: "Jump from the form definition into the latest responses." }),
|
|
6261
|
+
/* @__PURE__ */ jsx30("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: submissions.length > 0 ? submissions.map((submission) => {
|
|
6262
|
+
const submissionID = typeof submission.id === "string" || typeof submission.id === "number" ? String(submission.id) : "";
|
|
6263
|
+
if (!submissionID) return null;
|
|
6264
|
+
const identity = getNameAndEmail2(submission.data);
|
|
6265
|
+
const previewFields = getPreviewFields2(submission.data, fieldLabels);
|
|
6266
|
+
const formSubmissionPath = resolveAdminPath(
|
|
6267
|
+
adminBasePath,
|
|
6268
|
+
`/forms/submissions/${submissionID}`
|
|
6269
|
+
);
|
|
6270
|
+
return /* @__PURE__ */ jsxs27(Link4, { className: "orion-admin-list-item", href: formSubmissionPath, children: [
|
|
6271
|
+
/* @__PURE__ */ jsxs27("div", { children: [
|
|
6272
|
+
/* @__PURE__ */ jsx30("strong", { children: identity.name || identity.email || "Submission" }),
|
|
6273
|
+
/* @__PURE__ */ jsx30("div", { className: "orion-admin-list-meta", children: formatDate2(submission.submittedAt) }),
|
|
6274
|
+
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
|
|
6275
|
+
] }),
|
|
6276
|
+
/* @__PURE__ */ jsx30("span", { className: "orion-admin-action-button orion-admin-action-button--ghost", children: "Open" })
|
|
6277
|
+
] }, submissionID);
|
|
6278
|
+
}) : /* @__PURE__ */ jsxs27("div", { className: "orion-admin-empty-state", children: [
|
|
6279
|
+
/* @__PURE__ */ jsx30("strong", { children: "No responses yet" }),
|
|
6280
|
+
/* @__PURE__ */ jsx30("span", { children: "This view will populate as soon as the form starts receiving traffic." })
|
|
6281
|
+
] }) })
|
|
6282
|
+
] })
|
|
6283
|
+
] }),
|
|
6284
|
+
/* @__PURE__ */ jsxs27("form", { className: "orion-admin-form", onSubmit: save, children: [
|
|
6285
|
+
/* @__PURE__ */ jsx30("strong", { children: "Form settings" }),
|
|
6286
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6287
|
+
"Title",
|
|
6288
|
+
/* @__PURE__ */ jsx30(
|
|
6289
|
+
"input",
|
|
6290
|
+
{
|
|
6291
|
+
onChange: (event) => setEditorState(
|
|
6292
|
+
(current) => current ? { ...current, title: event.target.value } : current
|
|
6293
|
+
),
|
|
6294
|
+
required: true,
|
|
6295
|
+
type: "text",
|
|
6296
|
+
value: editorState.title
|
|
6297
|
+
}
|
|
6298
|
+
)
|
|
6299
|
+
] }),
|
|
6300
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6301
|
+
"Slug",
|
|
6302
|
+
/* @__PURE__ */ jsx30(
|
|
6303
|
+
"input",
|
|
6304
|
+
{
|
|
6305
|
+
onChange: (event) => setEditorState(
|
|
6306
|
+
(current) => current ? { ...current, slug: event.target.value } : current
|
|
6307
|
+
),
|
|
6308
|
+
required: true,
|
|
6309
|
+
type: "text",
|
|
6310
|
+
value: editorState.slug
|
|
6311
|
+
}
|
|
6312
|
+
)
|
|
6313
|
+
] }),
|
|
6314
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6315
|
+
"Submit button",
|
|
6316
|
+
/* @__PURE__ */ jsx30(
|
|
6317
|
+
"input",
|
|
6318
|
+
{
|
|
6319
|
+
onChange: (event) => setEditorState(
|
|
6320
|
+
(current) => current ? { ...current, submitLabel: event.target.value } : current
|
|
6321
|
+
),
|
|
6322
|
+
type: "text",
|
|
6323
|
+
value: editorState.submitLabel
|
|
6324
|
+
}
|
|
6325
|
+
)
|
|
6326
|
+
] }),
|
|
6327
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6328
|
+
"Success message",
|
|
6329
|
+
/* @__PURE__ */ jsx30(
|
|
6330
|
+
"textarea",
|
|
6331
|
+
{
|
|
6332
|
+
onChange: (event) => setEditorState(
|
|
6333
|
+
(current) => current ? { ...current, successMessage: event.target.value } : current
|
|
6334
|
+
),
|
|
6335
|
+
rows: 4,
|
|
6336
|
+
value: editorState.successMessage
|
|
6337
|
+
}
|
|
6338
|
+
)
|
|
6339
|
+
] }),
|
|
6340
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-card", children: [
|
|
6341
|
+
/* @__PURE__ */ jsx30("strong", { children: "Email behavior" }),
|
|
6342
|
+
/* @__PURE__ */ jsxs27("div", { style: { display: "grid", gap: "0.85rem", marginTop: "0.9rem" }, children: [
|
|
6343
|
+
/* @__PURE__ */ jsxs27("label", { style: checkboxLabelStyle, children: [
|
|
6344
|
+
/* @__PURE__ */ jsx30(
|
|
6345
|
+
"input",
|
|
6346
|
+
{
|
|
6347
|
+
checked: editorState.sendAdmin,
|
|
6348
|
+
onChange: (event) => setEditorState(
|
|
6349
|
+
(current) => current ? { ...current, sendAdmin: event.target.checked } : current
|
|
6350
|
+
),
|
|
6351
|
+
type: "checkbox"
|
|
6352
|
+
}
|
|
6353
|
+
),
|
|
6354
|
+
"Send admin notifications"
|
|
6355
|
+
] }),
|
|
6356
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6357
|
+
"Admin recipients",
|
|
6358
|
+
/* @__PURE__ */ jsx30(
|
|
6359
|
+
"textarea",
|
|
6360
|
+
{
|
|
6361
|
+
onChange: (event) => setEditorState(
|
|
6362
|
+
(current) => current ? { ...current, adminRecipientsText: event.target.value } : current
|
|
6363
|
+
),
|
|
6364
|
+
placeholder: "one@email.com\ntwo@email.com",
|
|
6365
|
+
rows: 4,
|
|
6366
|
+
value: editorState.adminRecipientsText
|
|
6367
|
+
}
|
|
6368
|
+
)
|
|
6369
|
+
] }),
|
|
6370
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6371
|
+
"Admin subject",
|
|
6372
|
+
/* @__PURE__ */ jsx30(
|
|
6373
|
+
"input",
|
|
6374
|
+
{
|
|
6375
|
+
onChange: (event) => setEditorState(
|
|
6376
|
+
(current) => current ? { ...current, adminSubject: event.target.value } : current
|
|
6377
|
+
),
|
|
6378
|
+
type: "text",
|
|
6379
|
+
value: editorState.adminSubject
|
|
6380
|
+
}
|
|
6381
|
+
)
|
|
6382
|
+
] }),
|
|
6383
|
+
/* @__PURE__ */ jsxs27("label", { style: checkboxLabelStyle, children: [
|
|
6384
|
+
/* @__PURE__ */ jsx30(
|
|
6385
|
+
"input",
|
|
6386
|
+
{
|
|
6387
|
+
checked: editorState.sendConfirmation,
|
|
6388
|
+
onChange: (event) => setEditorState(
|
|
6389
|
+
(current) => current ? { ...current, sendConfirmation: event.target.checked } : current
|
|
6390
|
+
),
|
|
6391
|
+
type: "checkbox"
|
|
6392
|
+
}
|
|
6393
|
+
),
|
|
6394
|
+
"Send confirmation email"
|
|
6395
|
+
] }),
|
|
6396
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6397
|
+
"Confirmation subject",
|
|
6398
|
+
/* @__PURE__ */ jsx30(
|
|
6399
|
+
"input",
|
|
6400
|
+
{
|
|
6401
|
+
onChange: (event) => setEditorState(
|
|
6402
|
+
(current) => current ? { ...current, confirmationSubject: event.target.value } : current
|
|
6403
|
+
),
|
|
6404
|
+
type: "text",
|
|
6405
|
+
value: editorState.confirmationSubject
|
|
6406
|
+
}
|
|
6407
|
+
)
|
|
6408
|
+
] }),
|
|
6409
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6410
|
+
"Confirmation heading",
|
|
6411
|
+
/* @__PURE__ */ jsx30(
|
|
6412
|
+
"input",
|
|
6413
|
+
{
|
|
6414
|
+
onChange: (event) => setEditorState(
|
|
6415
|
+
(current) => current ? { ...current, confirmationHeading: event.target.value } : current
|
|
6416
|
+
),
|
|
6417
|
+
type: "text",
|
|
6418
|
+
value: editorState.confirmationHeading
|
|
6419
|
+
}
|
|
6420
|
+
)
|
|
6421
|
+
] }),
|
|
6422
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6423
|
+
"Confirmation message",
|
|
6424
|
+
/* @__PURE__ */ jsx30(
|
|
6425
|
+
"textarea",
|
|
6426
|
+
{
|
|
6427
|
+
onChange: (event) => setEditorState(
|
|
6428
|
+
(current) => current ? { ...current, confirmationMessage: event.target.value } : current
|
|
6429
|
+
),
|
|
6430
|
+
rows: 4,
|
|
6431
|
+
value: editorState.confirmationMessage
|
|
6432
|
+
}
|
|
6433
|
+
)
|
|
6434
|
+
] })
|
|
6435
|
+
] })
|
|
6436
|
+
] }),
|
|
6437
|
+
/* @__PURE__ */ jsxs27("label", { children: [
|
|
6438
|
+
"Structure JSON",
|
|
6439
|
+
/* @__PURE__ */ jsx30(
|
|
6440
|
+
"textarea",
|
|
6441
|
+
{
|
|
6442
|
+
onChange: (event) => setEditorState(
|
|
6443
|
+
(current) => current ? { ...current, stepsText: event.target.value } : current
|
|
6444
|
+
),
|
|
6445
|
+
rows: 18,
|
|
6446
|
+
spellCheck: false,
|
|
6447
|
+
style: {
|
|
6448
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
6449
|
+
minHeight: "24rem"
|
|
6450
|
+
},
|
|
6451
|
+
value: editorState.stepsText
|
|
6452
|
+
}
|
|
6453
|
+
)
|
|
6454
|
+
] }),
|
|
6455
|
+
/* @__PURE__ */ jsx30("div", { className: "orion-admin-list-meta", children: "Edit the public workflow as JSON. The saved payload must remain an array of step objects compatible with the form collection schema." }),
|
|
6456
|
+
/* @__PURE__ */ jsx30("button", { disabled: saving, type: "submit", children: saving ? "Saving..." : "Save Form" })
|
|
6457
|
+
] })
|
|
6458
|
+
] }),
|
|
6459
|
+
/* @__PURE__ */ jsxs27("div", { className: "orion-admin-card", children: [
|
|
6460
|
+
/* @__PURE__ */ jsx30("strong", { children: "Current structure payload" }),
|
|
6461
|
+
/* @__PURE__ */ jsx30("span", { children: "Reference snapshot of the form steps that will be written back on save." }),
|
|
6462
|
+
/* @__PURE__ */ jsx30("pre", { style: { ...codeStyle, marginTop: "1rem" }, children: editorState.stepsText })
|
|
6463
|
+
] })
|
|
6464
|
+
] }) : null
|
|
6465
|
+
]
|
|
6466
|
+
}
|
|
6467
|
+
) });
|
|
6468
|
+
}
|
|
6469
|
+
|
|
6470
|
+
// src/admin/components/studio/AdminStudioFormSubmissionView.tsx
|
|
6471
|
+
import Link5 from "next/link";
|
|
6472
|
+
import { useEffect as useEffect19, useMemo as useMemo15, useState as useState20 } from "react";
|
|
6473
|
+
import { Fragment as Fragment6, jsx as jsx31, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
6474
|
+
var codeStyle2 = {
|
|
6475
|
+
background: "color-mix(in srgb, var(--orion-admin-card-bg) 82%, black)",
|
|
6476
|
+
border: "1px solid var(--orion-admin-card-border)",
|
|
6477
|
+
borderRadius: "var(--orion-admin-radius-sm)",
|
|
6478
|
+
color: "var(--orion-admin-text)",
|
|
6479
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
6480
|
+
fontSize: "0.86rem",
|
|
6481
|
+
lineHeight: 1.55,
|
|
6482
|
+
margin: 0,
|
|
6483
|
+
maxHeight: "28rem",
|
|
6484
|
+
overflow: "auto",
|
|
6485
|
+
padding: "0.9rem",
|
|
6486
|
+
whiteSpace: "pre-wrap"
|
|
6487
|
+
};
|
|
6488
|
+
var sectionGridStyle2 = {
|
|
6489
|
+
display: "grid",
|
|
6490
|
+
gap: "1rem",
|
|
6491
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))"
|
|
6492
|
+
};
|
|
6493
|
+
var renderFieldValue = (value) => {
|
|
6494
|
+
if (value === null || value === void 0) {
|
|
6495
|
+
return /* @__PURE__ */ jsx31("span", { className: "orion-admin-list-meta", children: "No value" });
|
|
6496
|
+
}
|
|
6497
|
+
if (typeof value === "boolean") {
|
|
6498
|
+
return value ? "Yes" : "No";
|
|
6499
|
+
}
|
|
6500
|
+
if (typeof value === "number") {
|
|
6501
|
+
return String(value);
|
|
6502
|
+
}
|
|
6503
|
+
if (typeof value === "string") {
|
|
6504
|
+
return value.trim().length > 0 ? value : /* @__PURE__ */ jsx31("span", { className: "orion-admin-list-meta", children: "No value" });
|
|
6505
|
+
}
|
|
6506
|
+
return /* @__PURE__ */ jsx31("pre", { style: codeStyle2, children: JSON.stringify(value, null, 2) });
|
|
6507
|
+
};
|
|
6508
|
+
function getSubmissionIDFromPathname(pathname) {
|
|
6509
|
+
return getIDFromPathname(pathname, "/forms/submissions/");
|
|
6510
|
+
}
|
|
6511
|
+
function AdminStudioFormSubmissionView(props) {
|
|
6512
|
+
const formsCollectionSlug = getPropString14(props, "formsCollectionSlug", "forms");
|
|
6513
|
+
const formSubmissionsCollectionSlug = getPropString14(
|
|
6514
|
+
props,
|
|
6515
|
+
"formSubmissionsCollectionSlug",
|
|
6516
|
+
"form-submissions"
|
|
6517
|
+
);
|
|
6518
|
+
const adminBasePath = useAdminBasePath();
|
|
6519
|
+
const formsPath = resolveAdminPath(adminBasePath, "/forms");
|
|
6520
|
+
const submissionIDFromParams = useMemo15(() => getParam3(props.params, "id"), [props.params]);
|
|
6521
|
+
const [submissionID, setSubmissionID] = useState20(submissionIDFromParams);
|
|
6522
|
+
const [didResolvePathFallback, setDidResolvePathFallback] = useState20(false);
|
|
6523
|
+
const [doc, setDoc] = useState20(null);
|
|
6524
|
+
const [formDoc, setFormDoc] = useState20(null);
|
|
6525
|
+
const [loading, setLoading] = useState20(true);
|
|
6526
|
+
const [error, setError] = useState20(null);
|
|
6527
|
+
const [confirmDelete, setConfirmDelete] = useState20(false);
|
|
6528
|
+
const [deleting, setDeleting] = useState20(false);
|
|
6529
|
+
useEffect19(() => {
|
|
6530
|
+
if (submissionIDFromParams) {
|
|
6531
|
+
setSubmissionID(submissionIDFromParams);
|
|
6532
|
+
setDidResolvePathFallback(true);
|
|
6533
|
+
return;
|
|
6534
|
+
}
|
|
6535
|
+
if (typeof window !== "undefined") {
|
|
6536
|
+
setSubmissionID(getSubmissionIDFromPathname(window.location.pathname));
|
|
6537
|
+
}
|
|
6538
|
+
setDidResolvePathFallback(true);
|
|
6539
|
+
}, [submissionIDFromParams]);
|
|
6540
|
+
const loadDoc = async (id) => {
|
|
6541
|
+
setLoading(true);
|
|
6542
|
+
setError(null);
|
|
6543
|
+
try {
|
|
6544
|
+
const response = await fetch(
|
|
6545
|
+
`/api/${formSubmissionsCollectionSlug}/${encodeURIComponent(id)}?depth=2&draft=true`,
|
|
6546
|
+
{
|
|
6547
|
+
credentials: "include"
|
|
6548
|
+
}
|
|
6549
|
+
);
|
|
6550
|
+
if (!response.ok) {
|
|
6551
|
+
throw new Error(`Failed to load submission (${response.status}).`);
|
|
6552
|
+
}
|
|
6553
|
+
const nextDoc = await response.json();
|
|
6554
|
+
const relatedForm = nextDoc.form && typeof nextDoc.form === "object" && !Array.isArray(nextDoc.form) ? nextDoc.form : null;
|
|
6555
|
+
let nextFormDoc = relatedForm;
|
|
6556
|
+
const relatedFormID2 = getFormID3(nextDoc.form);
|
|
6557
|
+
if (!nextFormDoc && relatedFormID2) {
|
|
6558
|
+
const formResponse = await fetch(
|
|
6559
|
+
`/api/${formsCollectionSlug}/${encodeURIComponent(relatedFormID2)}?depth=0&draft=true`,
|
|
6560
|
+
{
|
|
6561
|
+
credentials: "include"
|
|
6562
|
+
}
|
|
6563
|
+
);
|
|
6564
|
+
if (formResponse.ok) {
|
|
6565
|
+
nextFormDoc = await formResponse.json();
|
|
6566
|
+
}
|
|
6567
|
+
}
|
|
6568
|
+
setDoc(nextDoc);
|
|
6569
|
+
setFormDoc(nextFormDoc);
|
|
6570
|
+
} catch (loadError) {
|
|
6571
|
+
setError(loadError instanceof Error ? loadError.message : "Failed to load submission.");
|
|
6572
|
+
setDoc(null);
|
|
6573
|
+
setFormDoc(null);
|
|
6574
|
+
} finally {
|
|
6575
|
+
setLoading(false);
|
|
6576
|
+
}
|
|
6577
|
+
};
|
|
6578
|
+
useEffect19(() => {
|
|
6579
|
+
if (!submissionID) {
|
|
6580
|
+
return;
|
|
6581
|
+
}
|
|
6582
|
+
void loadDoc(submissionID);
|
|
6583
|
+
}, [formsCollectionSlug, formSubmissionsCollectionSlug, submissionID]);
|
|
6584
|
+
const deleteSubmission = async () => {
|
|
6585
|
+
if (!submissionID) {
|
|
6586
|
+
return;
|
|
6587
|
+
}
|
|
6588
|
+
setDeleting(true);
|
|
6589
|
+
setError(null);
|
|
6590
|
+
try {
|
|
6591
|
+
const response = await fetch(`/api/${formSubmissionsCollectionSlug}/${encodeURIComponent(submissionID)}`, {
|
|
6592
|
+
credentials: "include",
|
|
6593
|
+
method: "DELETE"
|
|
6594
|
+
});
|
|
6595
|
+
if (!response.ok) {
|
|
6596
|
+
throw new Error(`Failed to delete submission (${response.status}).`);
|
|
6597
|
+
}
|
|
6598
|
+
const relatedFormID2 = doc ? getFormID3(doc.form) : "";
|
|
6599
|
+
const targetHref = relatedFormID2 ? resolveAdminPath(adminBasePath, `/forms/${relatedFormID2}`) : formsPath;
|
|
6600
|
+
window.location.assign(targetHref);
|
|
6601
|
+
} catch (deleteError) {
|
|
6602
|
+
setError(deleteError instanceof Error ? deleteError.message : "Failed to delete submission.");
|
|
6603
|
+
setDeleting(false);
|
|
6604
|
+
}
|
|
6605
|
+
};
|
|
6606
|
+
if (!submissionID && !didResolvePathFallback) {
|
|
6607
|
+
return /* @__PURE__ */ jsx31(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsx31(
|
|
6608
|
+
AdminPage,
|
|
6609
|
+
{
|
|
6610
|
+
breadcrumbs: [
|
|
6611
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
6612
|
+
{ label: "Forms", href: formsPath },
|
|
6613
|
+
{ label: "Submission" }
|
|
6614
|
+
],
|
|
6615
|
+
description: "Loading submission workspace...",
|
|
6616
|
+
title: "Submission",
|
|
6617
|
+
children: /* @__PURE__ */ jsx31(Fragment6, {})
|
|
6618
|
+
}
|
|
6619
|
+
) });
|
|
6620
|
+
}
|
|
6621
|
+
const relatedFormID = doc ? getFormID3(doc.form) : "";
|
|
6622
|
+
const formPath = relatedFormID ? resolveAdminPath(adminBasePath, `/forms/${relatedFormID}`) : formsPath;
|
|
6623
|
+
const formTitle = formDoc ? getFormTitle2(formDoc) : getFormTitle2(doc?.formSlug);
|
|
6624
|
+
const uploads = doc ? getUploads2(doc.files) : [];
|
|
6625
|
+
const identity = doc ? getNameAndEmail2(doc.data) : {};
|
|
6626
|
+
const fieldLabels = formDoc ? buildFieldLabelMap2(formDoc) : /* @__PURE__ */ new Map();
|
|
6627
|
+
const previewFields = doc ? getPreviewFields2(doc.data, fieldLabels) : [];
|
|
6628
|
+
const answerEntries = doc && doc.data && typeof doc.data === "object" ? Object.entries(doc.data) : [];
|
|
6629
|
+
return /* @__PURE__ */ jsx31(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsxs28(
|
|
6630
|
+
AdminPage,
|
|
6631
|
+
{
|
|
6632
|
+
breadcrumbs: [
|
|
6633
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
6634
|
+
{ label: "Forms", href: formsPath },
|
|
6635
|
+
...relatedFormID ? [{ label: formTitle, href: formPath }] : [{ label: formTitle }],
|
|
6636
|
+
{ label: "Submission" }
|
|
6637
|
+
],
|
|
6638
|
+
description: "Review the submitted answers, related files, and linked form details.",
|
|
6639
|
+
title: "Submission",
|
|
6640
|
+
children: [
|
|
6641
|
+
loading ? /* @__PURE__ */ jsx31("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
|
|
6642
|
+
error ? /* @__PURE__ */ jsx31("div", { className: "orion-admin-error", children: error }) : null,
|
|
6643
|
+
!loading && !error && doc && submissionID ? /* @__PURE__ */ jsxs28("div", { style: { display: "grid", gap: "1rem" }, children: [
|
|
6644
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-forms-summary-grid", children: [
|
|
6645
|
+
/* @__PURE__ */ jsxs28("article", { className: "orion-admin-overview-stat", children: [
|
|
6646
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-overview-stat-label", children: "Submitted" }),
|
|
6647
|
+
/* @__PURE__ */ jsx31("strong", { children: formatDate2(doc.submittedAt) }),
|
|
6648
|
+
/* @__PURE__ */ jsx31("p", { children: "Captured timestamp for this response." })
|
|
6649
|
+
] }),
|
|
6650
|
+
/* @__PURE__ */ jsxs28("article", { className: "orion-admin-overview-stat", children: [
|
|
6651
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-overview-stat-label", children: "Uploads" }),
|
|
6652
|
+
/* @__PURE__ */ jsx31("strong", { children: uploads.length }),
|
|
6653
|
+
/* @__PURE__ */ jsx31("p", { children: "Files attached by the submitter." })
|
|
6654
|
+
] }),
|
|
6655
|
+
/* @__PURE__ */ jsxs28("article", { className: "orion-admin-overview-stat", children: [
|
|
6656
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-overview-stat-label", children: "Highlighted answers" }),
|
|
6657
|
+
/* @__PURE__ */ jsx31("strong", { children: previewFields.length }),
|
|
6658
|
+
/* @__PURE__ */ jsx31("p", { children: "Readable answer previews surfaced from the structured payload." })
|
|
6659
|
+
] })
|
|
6660
|
+
] }),
|
|
6661
|
+
/* @__PURE__ */ jsxs28("div", { style: sectionGridStyle2, children: [
|
|
6662
|
+
/* @__PURE__ */ jsxs28("div", { style: { display: "grid", gap: "1rem" }, children: [
|
|
6663
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-card", children: [
|
|
6664
|
+
/* @__PURE__ */ jsx31("strong", { children: "Response details" }),
|
|
6665
|
+
/* @__PURE__ */ jsx31("span", { children: "Formatted answers using the current form field labels when available." }),
|
|
6666
|
+
/* @__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: [
|
|
6667
|
+
/* @__PURE__ */ jsxs28("div", { children: [
|
|
6668
|
+
/* @__PURE__ */ jsx31("strong", { children: fieldLabels.get(key) || humanizeKey2(key) }),
|
|
6669
|
+
/* @__PURE__ */ jsx31("div", { className: "orion-admin-list-meta", children: key })
|
|
6670
|
+
] }),
|
|
6671
|
+
/* @__PURE__ */ jsx31("div", { children: renderFieldValue(value) })
|
|
6672
|
+
] }, key)) : /* @__PURE__ */ jsxs28("div", { className: "orion-admin-empty-state", children: [
|
|
6673
|
+
/* @__PURE__ */ jsx31("strong", { children: "No response payload" }),
|
|
6674
|
+
/* @__PURE__ */ jsx31("span", { children: "This submission does not contain a structured data object." })
|
|
6675
|
+
] }) })
|
|
6676
|
+
] }),
|
|
6677
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-card", children: [
|
|
6678
|
+
/* @__PURE__ */ jsx31("strong", { children: "Raw payload" }),
|
|
6679
|
+
/* @__PURE__ */ jsx31("span", { children: "Verbatim submission data for troubleshooting or export checks." }),
|
|
6680
|
+
/* @__PURE__ */ jsx31("pre", { style: { ...codeStyle2, marginTop: "1rem" }, children: JSON.stringify(doc.data ?? {}, null, 2) })
|
|
6681
|
+
] })
|
|
6682
|
+
] }),
|
|
6683
|
+
/* @__PURE__ */ jsxs28("div", { style: { display: "grid", gap: "1rem" }, children: [
|
|
6684
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-card orion-admin-meta-table", children: [
|
|
6685
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-meta-row", children: [
|
|
6686
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-label", children: "Form" }),
|
|
6687
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-value", children: relatedFormID ? /* @__PURE__ */ jsx31(Link5, { href: formPath, children: formTitle }) : formTitle })
|
|
6688
|
+
] }),
|
|
6689
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-meta-row", children: [
|
|
6690
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-label", children: "Primary contact" }),
|
|
6691
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-value", children: identity.name || identity.email || "Unknown" })
|
|
6692
|
+
] }),
|
|
6693
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-meta-row", children: [
|
|
6694
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-label", children: "Email" }),
|
|
6695
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-value", children: identity.email || "Not provided" })
|
|
6696
|
+
] }),
|
|
6697
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-meta-row", children: [
|
|
6698
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-label", children: "Submission ID" }),
|
|
6699
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-value", children: submissionID })
|
|
6700
|
+
] }),
|
|
6701
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-meta-row", children: [
|
|
6702
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-label", children: "Form slug" }),
|
|
6703
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-value", children: typeof doc.formSlug === "string" && doc.formSlug.trim().length > 0 ? doc.formSlug : "Unavailable" })
|
|
6704
|
+
] })
|
|
6705
|
+
] }),
|
|
6706
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-card", children: [
|
|
6707
|
+
/* @__PURE__ */ jsx31("strong", { children: "Attached uploads" }),
|
|
6708
|
+
/* @__PURE__ */ jsx31("span", { children: "Files linked to this response remain inside the Studio workspace." }),
|
|
6709
|
+
/* @__PURE__ */ jsx31("div", { style: { display: "grid", gap: "0.75rem", marginTop: "1rem" }, children: uploads.length > 0 ? uploads.map((upload) => {
|
|
6710
|
+
const uploadID = typeof upload.id === "string" || typeof upload.id === "number" ? String(upload.id) : "";
|
|
6711
|
+
if (!uploadID) return null;
|
|
6712
|
+
const uploadPath = resolveAdminPath(adminBasePath, `/forms/uploads/${uploadID}`);
|
|
6713
|
+
const meta = [formatFileSize2(upload.filesize), typeof upload.mimeType === "string" ? upload.mimeType : null].filter(Boolean).join(" \xB7 ");
|
|
6714
|
+
return /* @__PURE__ */ jsxs28(Link5, { className: "orion-admin-list-item", href: uploadPath, children: [
|
|
6715
|
+
/* @__PURE__ */ jsxs28("div", { children: [
|
|
6716
|
+
/* @__PURE__ */ jsx31("strong", { children: typeof upload.filename === "string" && upload.filename.trim().length > 0 ? upload.filename : `Upload ${uploadID}` }),
|
|
6717
|
+
/* @__PURE__ */ jsx31("div", { className: "orion-admin-list-meta", children: meta || "Open file details" })
|
|
6718
|
+
] }),
|
|
6719
|
+
/* @__PURE__ */ jsx31("span", { className: "orion-admin-action-button orion-admin-action-button--ghost", children: "Open" })
|
|
6720
|
+
] }, uploadID);
|
|
6721
|
+
}) : /* @__PURE__ */ jsxs28("div", { className: "orion-admin-empty-state", children: [
|
|
6722
|
+
/* @__PURE__ */ jsx31("strong", { children: "No files attached" }),
|
|
6723
|
+
/* @__PURE__ */ jsx31("span", { children: "This response did not include any uploads." })
|
|
6724
|
+
] }) })
|
|
6725
|
+
] }),
|
|
6726
|
+
confirmDelete ? /* @__PURE__ */ jsxs28("div", { className: "orion-admin-form", style: { borderColor: "#b42318" }, children: [
|
|
6727
|
+
/* @__PURE__ */ jsx31("p", { style: { fontWeight: 700, margin: 0 }, children: "Delete this submission?" }),
|
|
6728
|
+
/* @__PURE__ */ jsx31("p", { className: "orion-admin-list-meta", style: { margin: 0 }, children: "This action cannot be undone and will remove the stored response." }),
|
|
6729
|
+
/* @__PURE__ */ jsxs28("div", { className: "orion-admin-inline-actions", children: [
|
|
6730
|
+
/* @__PURE__ */ jsx31("button", { disabled: deleting, onClick: deleteSubmission, type: "button", children: deleting ? "Deleting..." : "Yes, Delete" }),
|
|
6731
|
+
/* @__PURE__ */ jsx31("button", { onClick: () => setConfirmDelete(false), type: "button", children: "Cancel" })
|
|
6732
|
+
] })
|
|
6733
|
+
] }) : /* @__PURE__ */ jsx31(
|
|
6734
|
+
"button",
|
|
6735
|
+
{
|
|
6736
|
+
className: "orion-admin-action-button",
|
|
6737
|
+
onClick: () => setConfirmDelete(true),
|
|
6738
|
+
style: { background: "#b42318" },
|
|
6739
|
+
type: "button",
|
|
6740
|
+
children: "Delete Submission"
|
|
6741
|
+
}
|
|
6742
|
+
)
|
|
6743
|
+
] })
|
|
6744
|
+
] })
|
|
6745
|
+
] }) : null
|
|
6746
|
+
]
|
|
6747
|
+
}
|
|
6748
|
+
) });
|
|
6749
|
+
}
|
|
6750
|
+
|
|
6751
|
+
// src/admin/components/studio/AdminStudioFormUploadView.tsx
|
|
6752
|
+
import { useEffect as useEffect20, useMemo as useMemo16, useState as useState21 } from "react";
|
|
6753
|
+
import { Fragment as Fragment7, jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
6754
|
+
var previewStyle = {
|
|
6755
|
+
borderRadius: 14,
|
|
6756
|
+
display: "block",
|
|
6757
|
+
maxHeight: "28rem",
|
|
6758
|
+
objectFit: "contain",
|
|
6759
|
+
width: "100%"
|
|
6760
|
+
};
|
|
6761
|
+
function getUploadIDFromPathname(pathname) {
|
|
6762
|
+
return getIDFromPathname(pathname, "/forms/uploads/");
|
|
6763
|
+
}
|
|
6764
|
+
function AdminStudioFormUploadView(props) {
|
|
6765
|
+
const formUploadsCollectionSlug = getPropString14(props, "formUploadsCollectionSlug", "form-uploads");
|
|
6766
|
+
const adminBasePath = useAdminBasePath();
|
|
6767
|
+
const formsPath = resolveAdminPath(adminBasePath, "/forms");
|
|
6768
|
+
const uploadIDFromParams = useMemo16(() => getParam3(props.params, "id"), [props.params]);
|
|
6769
|
+
const [uploadID, setUploadID] = useState21(uploadIDFromParams);
|
|
6770
|
+
const [didResolvePathFallback, setDidResolvePathFallback] = useState21(false);
|
|
6771
|
+
const [doc, setDoc] = useState21(null);
|
|
6772
|
+
const [loading, setLoading] = useState21(true);
|
|
6773
|
+
const [error, setError] = useState21(null);
|
|
6774
|
+
const [savedMessage, setSavedMessage] = useState21(null);
|
|
6775
|
+
const [saving, setSaving] = useState21(false);
|
|
6776
|
+
const [confirmDelete, setConfirmDelete] = useState21(false);
|
|
6777
|
+
const [deleting, setDeleting] = useState21(false);
|
|
6778
|
+
useEffect20(() => {
|
|
6779
|
+
if (uploadIDFromParams) {
|
|
6780
|
+
setUploadID(uploadIDFromParams);
|
|
6781
|
+
setDidResolvePathFallback(true);
|
|
6782
|
+
return;
|
|
6783
|
+
}
|
|
6784
|
+
if (typeof window !== "undefined") {
|
|
6785
|
+
setUploadID(getUploadIDFromPathname(window.location.pathname));
|
|
6786
|
+
}
|
|
6787
|
+
setDidResolvePathFallback(true);
|
|
6788
|
+
}, [uploadIDFromParams]);
|
|
6789
|
+
const loadDoc = async (id) => {
|
|
6790
|
+
setLoading(true);
|
|
6791
|
+
setError(null);
|
|
6792
|
+
try {
|
|
6793
|
+
const response = await fetch(`/api/${formUploadsCollectionSlug}/${encodeURIComponent(id)}?depth=0&draft=true`, {
|
|
6794
|
+
credentials: "include"
|
|
6795
|
+
});
|
|
6796
|
+
if (!response.ok) {
|
|
6797
|
+
throw new Error(`Failed to load upload (${response.status}).`);
|
|
6798
|
+
}
|
|
6799
|
+
const nextDoc = await response.json();
|
|
6800
|
+
setDoc(nextDoc);
|
|
6801
|
+
} catch (loadError) {
|
|
6802
|
+
setError(loadError instanceof Error ? loadError.message : "Failed to load upload.");
|
|
6803
|
+
setDoc(null);
|
|
6804
|
+
} finally {
|
|
6805
|
+
setLoading(false);
|
|
6806
|
+
}
|
|
6807
|
+
};
|
|
6808
|
+
useEffect20(() => {
|
|
6809
|
+
if (!uploadID) {
|
|
6810
|
+
return;
|
|
6811
|
+
}
|
|
6812
|
+
void loadDoc(uploadID);
|
|
6813
|
+
}, [formUploadsCollectionSlug, uploadID]);
|
|
6814
|
+
const save = async (event) => {
|
|
6815
|
+
event.preventDefault();
|
|
6816
|
+
if (!uploadID) {
|
|
6817
|
+
return;
|
|
6818
|
+
}
|
|
6819
|
+
setSaving(true);
|
|
6820
|
+
setError(null);
|
|
6821
|
+
setSavedMessage(null);
|
|
6822
|
+
try {
|
|
6823
|
+
const formData = new FormData(event.currentTarget);
|
|
6824
|
+
const alt = String(formData.get("alt") || "").trim();
|
|
6825
|
+
const response = await fetch(`/api/${formUploadsCollectionSlug}/${encodeURIComponent(uploadID)}`, {
|
|
6826
|
+
body: JSON.stringify({ alt }),
|
|
6827
|
+
credentials: "include",
|
|
6828
|
+
headers: {
|
|
6829
|
+
"Content-Type": "application/json"
|
|
6830
|
+
},
|
|
6831
|
+
method: "PATCH"
|
|
6832
|
+
});
|
|
6833
|
+
if (!response.ok) {
|
|
6834
|
+
throw new Error(`Failed to save upload (${response.status}).`);
|
|
6835
|
+
}
|
|
6836
|
+
const nextDoc = await response.json();
|
|
6837
|
+
setDoc(nextDoc);
|
|
6838
|
+
setSavedMessage("Saved.");
|
|
6839
|
+
} catch (saveError) {
|
|
6840
|
+
setError(saveError instanceof Error ? saveError.message : "Failed to save upload.");
|
|
6841
|
+
} finally {
|
|
6842
|
+
setSaving(false);
|
|
6843
|
+
}
|
|
6844
|
+
};
|
|
6845
|
+
const deleteUpload = async () => {
|
|
6846
|
+
if (!uploadID) {
|
|
6847
|
+
return;
|
|
6848
|
+
}
|
|
6849
|
+
setDeleting(true);
|
|
6850
|
+
setError(null);
|
|
6851
|
+
try {
|
|
6852
|
+
const response = await fetch(`/api/${formUploadsCollectionSlug}/${encodeURIComponent(uploadID)}`, {
|
|
6853
|
+
credentials: "include",
|
|
6854
|
+
method: "DELETE"
|
|
6855
|
+
});
|
|
6856
|
+
if (!response.ok) {
|
|
6857
|
+
throw new Error(`Failed to delete upload (${response.status}).`);
|
|
6858
|
+
}
|
|
6859
|
+
window.location.assign(formsPath);
|
|
6860
|
+
} catch (deleteError) {
|
|
6861
|
+
setError(deleteError instanceof Error ? deleteError.message : "Failed to delete upload.");
|
|
6862
|
+
setDeleting(false);
|
|
6863
|
+
}
|
|
6864
|
+
};
|
|
6865
|
+
if (!uploadID && !didResolvePathFallback) {
|
|
6866
|
+
return /* @__PURE__ */ jsx32(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsx32(
|
|
6867
|
+
AdminPage,
|
|
6868
|
+
{
|
|
6869
|
+
breadcrumbs: [
|
|
6870
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
6871
|
+
{ label: "Forms", href: formsPath },
|
|
6872
|
+
{ label: "Upload" }
|
|
6873
|
+
],
|
|
6874
|
+
description: "Loading upload workspace...",
|
|
6875
|
+
title: "Upload",
|
|
6876
|
+
children: /* @__PURE__ */ jsx32(Fragment7, {})
|
|
6877
|
+
}
|
|
6878
|
+
) });
|
|
6879
|
+
}
|
|
6880
|
+
const filename = doc && typeof doc.filename === "string" && doc.filename.trim().length > 0 ? doc.filename : uploadID ? `Upload ${uploadID}` : "Upload";
|
|
6881
|
+
const mimeType = doc && typeof doc.mimeType === "string" ? doc.mimeType : "";
|
|
6882
|
+
const sourceURL = doc && typeof doc.url === "string" && doc.url.trim().length > 0 ? doc.url : null;
|
|
6883
|
+
const canPreview = Boolean(sourceURL && mimeType.startsWith("image/"));
|
|
6884
|
+
const createdAt = doc?.createdAt ?? doc?.updatedAt;
|
|
6885
|
+
return /* @__PURE__ */ jsx32(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsxs29(
|
|
6886
|
+
AdminPage,
|
|
6887
|
+
{
|
|
6888
|
+
breadcrumbs: [
|
|
6889
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
6890
|
+
{ label: "Forms", href: formsPath },
|
|
6891
|
+
{ label: filename }
|
|
6892
|
+
],
|
|
6893
|
+
description: "Review file metadata, update alt text, and remove private uploads from Studio.",
|
|
6894
|
+
title: "Upload",
|
|
6895
|
+
children: [
|
|
6896
|
+
loading ? /* @__PURE__ */ jsx32("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
|
|
6897
|
+
error ? /* @__PURE__ */ jsx32("div", { className: "orion-admin-error", children: error }) : null,
|
|
6898
|
+
savedMessage ? /* @__PURE__ */ jsx32("div", { className: "orion-admin-success", children: savedMessage }) : null,
|
|
6899
|
+
!loading && !error && doc && uploadID ? /* @__PURE__ */ jsxs29("div", { className: "orion-admin-grid", style: { alignItems: "start" }, children: [
|
|
6900
|
+
/* @__PURE__ */ jsxs29("div", { style: { display: "grid", gap: "0.8rem" }, children: [
|
|
6901
|
+
/* @__PURE__ */ jsx32("div", { className: "orion-admin-card", children: canPreview && sourceURL ? /* @__PURE__ */ jsx32("img", { alt: filename, src: sourceURL, style: previewStyle }) : /* @__PURE__ */ jsxs29(Fragment7, { children: [
|
|
6902
|
+
/* @__PURE__ */ jsx32("strong", { children: "No inline preview" }),
|
|
6903
|
+
/* @__PURE__ */ jsx32("span", { children: mimeType ? `Preview unavailable for ${mimeType}.` : "Preview unavailable for this file." })
|
|
6904
|
+
] }) }),
|
|
6905
|
+
sourceURL ? /* @__PURE__ */ jsx32("a", { className: "orion-admin-action-button", href: sourceURL, rel: "noreferrer", target: "_blank", children: "Open File" }) : null
|
|
6906
|
+
] }),
|
|
6907
|
+
/* @__PURE__ */ jsxs29("div", { style: { display: "grid", gap: "0.8rem" }, children: [
|
|
6908
|
+
/* @__PURE__ */ jsxs29("div", { className: "orion-admin-card orion-admin-meta-table", children: [
|
|
6909
|
+
/* @__PURE__ */ jsxs29("div", { className: "orion-admin-meta-row", children: [
|
|
6910
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-label", children: "Filename" }),
|
|
6911
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-value", children: filename })
|
|
6912
|
+
] }),
|
|
6913
|
+
/* @__PURE__ */ jsxs29("div", { className: "orion-admin-meta-row", children: [
|
|
6914
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-label", children: "File size" }),
|
|
6915
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-value", children: formatFileSize2(doc.filesize) || "Unavailable" })
|
|
6916
|
+
] }),
|
|
6917
|
+
/* @__PURE__ */ jsxs29("div", { className: "orion-admin-meta-row", children: [
|
|
6918
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-label", children: "Type" }),
|
|
6919
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-value", children: mimeType || "Unavailable" })
|
|
6920
|
+
] }),
|
|
6921
|
+
typeof doc.width === "number" && typeof doc.height === "number" ? /* @__PURE__ */ jsxs29("div", { className: "orion-admin-meta-row", children: [
|
|
6922
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-label", children: "Dimensions" }),
|
|
6923
|
+
/* @__PURE__ */ jsxs29("span", { className: "orion-admin-meta-value", children: [
|
|
6924
|
+
doc.width,
|
|
6925
|
+
" x ",
|
|
6926
|
+
doc.height,
|
|
6927
|
+
"px"
|
|
6928
|
+
] })
|
|
6929
|
+
] }) : null,
|
|
6930
|
+
/* @__PURE__ */ jsxs29("div", { className: "orion-admin-meta-row", children: [
|
|
6931
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-label", children: "Uploaded" }),
|
|
6932
|
+
/* @__PURE__ */ jsx32("span", { className: "orion-admin-meta-value", children: formatDate2(createdAt) })
|
|
6933
|
+
] })
|
|
6934
|
+
] }),
|
|
6935
|
+
/* @__PURE__ */ jsxs29("form", { className: "orion-admin-form", onSubmit: save, children: [
|
|
6936
|
+
/* @__PURE__ */ jsx32("strong", { children: "Asset details" }),
|
|
6937
|
+
/* @__PURE__ */ jsxs29("label", { children: [
|
|
6938
|
+
"Alt text",
|
|
6939
|
+
/* @__PURE__ */ jsx32("input", { defaultValue: typeof doc.alt === "string" ? doc.alt : "", name: "alt", type: "text" })
|
|
6940
|
+
] }),
|
|
6941
|
+
/* @__PURE__ */ jsx32("button", { disabled: saving, type: "submit", children: saving ? "Saving..." : "Save Upload" })
|
|
6942
|
+
] }),
|
|
6943
|
+
confirmDelete ? /* @__PURE__ */ jsxs29("div", { className: "orion-admin-form", style: { borderColor: "#b42318" }, children: [
|
|
6944
|
+
/* @__PURE__ */ jsx32("p", { style: { fontWeight: 700, margin: 0 }, children: "Delete this upload?" }),
|
|
6945
|
+
/* @__PURE__ */ jsx32("p", { className: "orion-admin-list-meta", style: { margin: 0 }, children: "This removes the stored file and any linked submission attachment references." }),
|
|
6946
|
+
/* @__PURE__ */ jsxs29("div", { className: "orion-admin-inline-actions", children: [
|
|
6947
|
+
/* @__PURE__ */ jsx32("button", { disabled: deleting, onClick: deleteUpload, type: "button", children: deleting ? "Deleting..." : "Yes, Delete" }),
|
|
6948
|
+
/* @__PURE__ */ jsx32("button", { onClick: () => setConfirmDelete(false), type: "button", children: "Cancel" })
|
|
6949
|
+
] })
|
|
6950
|
+
] }) : /* @__PURE__ */ jsx32(
|
|
6951
|
+
"button",
|
|
6952
|
+
{
|
|
6953
|
+
className: "orion-admin-action-button",
|
|
6954
|
+
onClick: () => setConfirmDelete(true),
|
|
6955
|
+
style: { background: "#b42318" },
|
|
6956
|
+
type: "button",
|
|
6957
|
+
children: "Delete Upload"
|
|
6958
|
+
}
|
|
6959
|
+
)
|
|
6960
|
+
] })
|
|
6961
|
+
] }) : null
|
|
6962
|
+
]
|
|
6963
|
+
}
|
|
6964
|
+
) });
|
|
6965
|
+
}
|
|
6966
|
+
|
|
6967
|
+
// src/admin/components/studio/AdminStudioToolsView.tsx
|
|
6968
|
+
import { useEffect as useEffect21, useState as useState22 } from "react";
|
|
6969
|
+
import { useAuth as useAuth7 } from "@payloadcms/ui";
|
|
6970
|
+
import { jsx as jsx33, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
6971
|
+
var userRoles = ["admin", "developer", "editor", "client"];
|
|
6972
|
+
var hasAdminAccess4 = (user) => {
|
|
6973
|
+
if (!user || typeof user !== "object") return false;
|
|
6974
|
+
const role = user.role;
|
|
6975
|
+
return typeof role === "string" && (role === "admin" || role === "developer");
|
|
6976
|
+
};
|
|
6977
|
+
var normalizeRole = (value) => userRoles.includes(value) ? value : "editor";
|
|
6978
|
+
function AdminStudioToolsView(props) {
|
|
6979
|
+
const { user } = useAuth7();
|
|
6980
|
+
const adminBasePath = useAdminBasePath();
|
|
6981
|
+
const [docs, setDocs] = useState22([]);
|
|
6982
|
+
const [loading, setLoading] = useState22(true);
|
|
6983
|
+
const [error, setError] = useState22(null);
|
|
6984
|
+
const [savedMessage, setSavedMessage] = useState22(null);
|
|
6985
|
+
const [createSubmitting, setCreateSubmitting] = useState22(false);
|
|
6986
|
+
const [updatingUserID, setUpdatingUserID] = useState22(null);
|
|
6987
|
+
if (!hasAdminAccess4(user)) {
|
|
6988
|
+
return /* @__PURE__ */ jsx33(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsx33(
|
|
6989
|
+
AdminPage,
|
|
6990
|
+
{
|
|
6991
|
+
breadcrumbs: [
|
|
6992
|
+
{ label: "Dashboard", href: adminBasePath },
|
|
6993
|
+
{ label: "Admin Tools" }
|
|
6994
|
+
],
|
|
6995
|
+
description: "You do not have access to this section.",
|
|
6996
|
+
title: "Admin Tools",
|
|
6997
|
+
children: /* @__PURE__ */ jsxs30("div", { className: "orion-admin-card", children: [
|
|
6998
|
+
/* @__PURE__ */ jsx33("strong", { children: "Access denied" }),
|
|
6999
|
+
/* @__PURE__ */ jsx33("span", { children: "This section is restricted to administrator and developer accounts." })
|
|
7000
|
+
] })
|
|
7001
|
+
}
|
|
7002
|
+
) });
|
|
7003
|
+
}
|
|
7004
|
+
const loadUsers = async () => {
|
|
7005
|
+
setLoading(true);
|
|
7006
|
+
setError(null);
|
|
7007
|
+
try {
|
|
7008
|
+
const params = new URLSearchParams({
|
|
7009
|
+
depth: "0",
|
|
7010
|
+
draft: "true",
|
|
7011
|
+
limit: "200",
|
|
7012
|
+
sort: "email"
|
|
7013
|
+
});
|
|
7014
|
+
const response = await fetch(`/api/users?${params.toString()}`, {
|
|
7015
|
+
credentials: "include"
|
|
7016
|
+
});
|
|
7017
|
+
if (!response.ok) {
|
|
7018
|
+
throw new Error(`Failed to load users (${response.status}).`);
|
|
7019
|
+
}
|
|
7020
|
+
const payload = await response.json();
|
|
7021
|
+
setDocs(Array.isArray(payload.docs) ? payload.docs : []);
|
|
7022
|
+
} catch (loadError) {
|
|
7023
|
+
setError(loadError instanceof Error ? loadError.message : "Failed to load users.");
|
|
7024
|
+
} finally {
|
|
7025
|
+
setLoading(false);
|
|
7026
|
+
}
|
|
7027
|
+
};
|
|
7028
|
+
useEffect21(() => {
|
|
7029
|
+
void loadUsers();
|
|
7030
|
+
}, []);
|
|
7031
|
+
const createUser = async (event) => {
|
|
7032
|
+
event.preventDefault();
|
|
7033
|
+
const form = event.currentTarget;
|
|
7034
|
+
setCreateSubmitting(true);
|
|
7035
|
+
setError(null);
|
|
7036
|
+
setSavedMessage(null);
|
|
7037
|
+
try {
|
|
7038
|
+
const formData = new FormData(form);
|
|
7039
|
+
const email = String(formData.get("email") || "").trim();
|
|
7040
|
+
const password = String(formData.get("password") || "");
|
|
7041
|
+
const fullName = String(formData.get("fullName") || "").trim();
|
|
7042
|
+
const role = normalizeRole(String(formData.get("role") || "editor").trim());
|
|
7043
|
+
if (!email || !password) {
|
|
7044
|
+
throw new Error("Email and password are required.");
|
|
7045
|
+
}
|
|
7046
|
+
const response = await fetch("/api/users", {
|
|
7047
|
+
body: JSON.stringify({
|
|
7048
|
+
email,
|
|
7049
|
+
fullName,
|
|
7050
|
+
password,
|
|
7051
|
+
role
|
|
7052
|
+
}),
|
|
5792
7053
|
credentials: "include",
|
|
5793
7054
|
headers: {
|
|
5794
7055
|
"Content-Type": "application/json"
|
|
@@ -5836,7 +7097,7 @@ function AdminStudioToolsView(props) {
|
|
|
5836
7097
|
setUpdatingUserID(null);
|
|
5837
7098
|
}
|
|
5838
7099
|
};
|
|
5839
|
-
return /* @__PURE__ */
|
|
7100
|
+
return /* @__PURE__ */ jsx33(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsxs30(
|
|
5840
7101
|
AdminPage,
|
|
5841
7102
|
{
|
|
5842
7103
|
breadcrumbs: [
|
|
@@ -5846,44 +7107,44 @@ function AdminStudioToolsView(props) {
|
|
|
5846
7107
|
description: "Manage users and fallback links to Payload native admin.",
|
|
5847
7108
|
title: "Admin Tools",
|
|
5848
7109
|
children: [
|
|
5849
|
-
error ? /* @__PURE__ */
|
|
5850
|
-
savedMessage ? /* @__PURE__ */
|
|
5851
|
-
/* @__PURE__ */
|
|
5852
|
-
/* @__PURE__ */
|
|
5853
|
-
/* @__PURE__ */
|
|
7110
|
+
error ? /* @__PURE__ */ jsx33("div", { className: "orion-admin-error", style: { marginBottom: "1rem" }, children: error }) : null,
|
|
7111
|
+
savedMessage ? /* @__PURE__ */ jsx33("div", { className: "orion-admin-success", style: { marginBottom: "1rem" }, children: savedMessage }) : null,
|
|
7112
|
+
/* @__PURE__ */ jsxs30("form", { className: "orion-admin-form", onSubmit: createUser, style: { marginBottom: "1rem" }, children: [
|
|
7113
|
+
/* @__PURE__ */ jsx33("strong", { children: "Create User" }),
|
|
7114
|
+
/* @__PURE__ */ jsxs30("label", { children: [
|
|
5854
7115
|
"Email",
|
|
5855
|
-
/* @__PURE__ */
|
|
7116
|
+
/* @__PURE__ */ jsx33("input", { name: "email", required: true, type: "email" })
|
|
5856
7117
|
] }),
|
|
5857
|
-
/* @__PURE__ */
|
|
7118
|
+
/* @__PURE__ */ jsxs30("label", { children: [
|
|
5858
7119
|
"Full Name",
|
|
5859
|
-
/* @__PURE__ */
|
|
7120
|
+
/* @__PURE__ */ jsx33("input", { name: "fullName", type: "text" })
|
|
5860
7121
|
] }),
|
|
5861
|
-
/* @__PURE__ */
|
|
7122
|
+
/* @__PURE__ */ jsxs30("label", { children: [
|
|
5862
7123
|
"Password",
|
|
5863
|
-
/* @__PURE__ */
|
|
7124
|
+
/* @__PURE__ */ jsx33("input", { name: "password", required: true, type: "password" })
|
|
5864
7125
|
] }),
|
|
5865
|
-
/* @__PURE__ */
|
|
7126
|
+
/* @__PURE__ */ jsxs30("label", { children: [
|
|
5866
7127
|
"Role",
|
|
5867
|
-
/* @__PURE__ */
|
|
7128
|
+
/* @__PURE__ */ jsx33("select", { defaultValue: "editor", name: "role", children: userRoles.map((role) => /* @__PURE__ */ jsx33("option", { value: role, children: role }, role)) })
|
|
5868
7129
|
] }),
|
|
5869
|
-
/* @__PURE__ */
|
|
7130
|
+
/* @__PURE__ */ jsx33("button", { disabled: createSubmitting, type: "submit", children: createSubmitting ? "Creating..." : "Create User" })
|
|
5870
7131
|
] }),
|
|
5871
|
-
loading ? /* @__PURE__ */
|
|
5872
|
-
/* @__PURE__ */
|
|
7132
|
+
loading ? /* @__PURE__ */ jsx33("div", { className: "orion-admin-list-meta", children: "Loading..." }) : null,
|
|
7133
|
+
/* @__PURE__ */ jsx33("div", { className: "orion-admin-list", children: docs.map((doc) => {
|
|
5873
7134
|
const id = typeof doc.id === "string" || typeof doc.id === "number" ? String(doc.id) : "";
|
|
5874
7135
|
if (!id) return null;
|
|
5875
7136
|
const email = typeof doc.email === "string" ? doc.email : `user-${id}`;
|
|
5876
7137
|
const fullName = typeof doc.fullName === "string" ? doc.fullName : "";
|
|
5877
7138
|
const currentRole = typeof doc.role === "string" ? normalizeRole(doc.role) : "editor";
|
|
5878
|
-
return /* @__PURE__ */
|
|
5879
|
-
/* @__PURE__ */
|
|
5880
|
-
/* @__PURE__ */
|
|
5881
|
-
/* @__PURE__ */
|
|
7139
|
+
return /* @__PURE__ */ jsxs30("div", { className: "orion-admin-list-item", children: [
|
|
7140
|
+
/* @__PURE__ */ jsxs30("div", { children: [
|
|
7141
|
+
/* @__PURE__ */ jsx33("strong", { children: email }),
|
|
7142
|
+
/* @__PURE__ */ jsx33("div", { className: "orion-admin-list-meta", children: fullName || "No full name set" })
|
|
5882
7143
|
] }),
|
|
5883
|
-
/* @__PURE__ */
|
|
5884
|
-
/* @__PURE__ */
|
|
5885
|
-
/* @__PURE__ */
|
|
5886
|
-
/* @__PURE__ */
|
|
7144
|
+
/* @__PURE__ */ jsxs30("form", { className: "orion-admin-inline-actions", onSubmit: updateUserRole, children: [
|
|
7145
|
+
/* @__PURE__ */ jsx33("input", { name: "id", type: "hidden", value: id }),
|
|
7146
|
+
/* @__PURE__ */ jsx33("select", { defaultValue: currentRole, name: "role", children: userRoles.map((role) => /* @__PURE__ */ jsx33("option", { value: role, children: role }, role)) }),
|
|
7147
|
+
/* @__PURE__ */ jsx33("button", { disabled: updatingUserID === id, type: "submit", children: updatingUserID === id ? "Updating..." : "Update" })
|
|
5887
7148
|
] })
|
|
5888
7149
|
] }, id);
|
|
5889
7150
|
}) })
|
|
@@ -5894,14 +7155,14 @@ function AdminStudioToolsView(props) {
|
|
|
5894
7155
|
|
|
5895
7156
|
// src/admin/components/studio/OpenInStudioMenuItem.tsx
|
|
5896
7157
|
import { useDocumentInfo } from "@payloadcms/ui";
|
|
5897
|
-
import { jsx as
|
|
7158
|
+
import { jsx as jsx34 } from "react/jsx-runtime";
|
|
5898
7159
|
function OpenInStudioMenuItem({ pagesPathBase = "/pages" }) {
|
|
5899
7160
|
const documentInfo = useDocumentInfo();
|
|
5900
7161
|
const id = documentInfo?.id;
|
|
5901
7162
|
if (!id) {
|
|
5902
7163
|
return null;
|
|
5903
7164
|
}
|
|
5904
|
-
return /* @__PURE__ */
|
|
7165
|
+
return /* @__PURE__ */ jsx34(
|
|
5905
7166
|
"a",
|
|
5906
7167
|
{
|
|
5907
7168
|
href: `${pagesPathBase}/${id}`,
|
|
@@ -5920,19 +7181,19 @@ function OpenInStudioMenuItem({ pagesPathBase = "/pages" }) {
|
|
|
5920
7181
|
}
|
|
5921
7182
|
|
|
5922
7183
|
// src/admin/components/studio/PageEditRedirectToStudio.tsx
|
|
5923
|
-
import { useEffect as
|
|
7184
|
+
import { useEffect as useEffect22 } from "react";
|
|
5924
7185
|
import { useDocumentInfo as useDocumentInfo2 } from "@payloadcms/ui";
|
|
5925
|
-
import { jsx as
|
|
7186
|
+
import { jsx as jsx35, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
5926
7187
|
function PageEditRedirectToStudio({ pagesPathBase = "/pages" }) {
|
|
5927
7188
|
const documentInfo = useDocumentInfo2();
|
|
5928
7189
|
const id = documentInfo?.id;
|
|
5929
|
-
|
|
7190
|
+
useEffect22(() => {
|
|
5930
7191
|
if (!id) {
|
|
5931
7192
|
return;
|
|
5932
7193
|
}
|
|
5933
7194
|
window.location.replace(`${pagesPathBase}/${id}`);
|
|
5934
7195
|
}, [id, pagesPathBase]);
|
|
5935
|
-
return /* @__PURE__ */
|
|
7196
|
+
return /* @__PURE__ */ jsxs31(
|
|
5936
7197
|
"div",
|
|
5937
7198
|
{
|
|
5938
7199
|
style: {
|
|
@@ -5944,18 +7205,61 @@ function PageEditRedirectToStudio({ pagesPathBase = "/pages" }) {
|
|
|
5944
7205
|
minHeight: "50vh"
|
|
5945
7206
|
},
|
|
5946
7207
|
children: [
|
|
5947
|
-
/* @__PURE__ */
|
|
5948
|
-
/* @__PURE__ */
|
|
5949
|
-
id ? /* @__PURE__ */
|
|
7208
|
+
/* @__PURE__ */ jsx35("h2", { style: { margin: 0 }, children: "Opening Editor..." }),
|
|
7209
|
+
/* @__PURE__ */ jsx35("p", { style: { color: "var(--theme-elevation-600)", margin: 0 }, children: "Redirecting to the custom page editor." }),
|
|
7210
|
+
id ? /* @__PURE__ */ jsx35("a", { href: `${pagesPathBase}/${id}`, children: "Continue to Editor" }) : /* @__PURE__ */ jsx35("a", { href: pagesPathBase, children: "Open Pages" })
|
|
7211
|
+
]
|
|
7212
|
+
}
|
|
7213
|
+
);
|
|
7214
|
+
}
|
|
7215
|
+
|
|
7216
|
+
// src/admin/components/studio/StudioDocumentRedirect.tsx
|
|
7217
|
+
import { useEffect as useEffect23 } from "react";
|
|
7218
|
+
import { useDocumentInfo as useDocumentInfo3 } from "@payloadcms/ui";
|
|
7219
|
+
import { jsx as jsx36, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
7220
|
+
function StudioDocumentRedirect({
|
|
7221
|
+
description = "Redirecting to the Studio view.",
|
|
7222
|
+
emptyHref,
|
|
7223
|
+
emptyLabel = "Open Studio",
|
|
7224
|
+
pathBase = "/forms",
|
|
7225
|
+
title = "Opening Studio..."
|
|
7226
|
+
}) {
|
|
7227
|
+
const adminBasePath = useAdminBasePath();
|
|
7228
|
+
const documentInfo = useDocumentInfo3();
|
|
7229
|
+
const id = documentInfo?.id;
|
|
7230
|
+
const fallbackHref = resolveAdminPath(adminBasePath, emptyHref || pathBase);
|
|
7231
|
+
useEffect23(() => {
|
|
7232
|
+
if (!id) {
|
|
7233
|
+
return;
|
|
7234
|
+
}
|
|
7235
|
+
const targetHref = resolveAdminPath(adminBasePath, `${pathBase}/${encodeURIComponent(String(id))}`);
|
|
7236
|
+
window.location.replace(targetHref);
|
|
7237
|
+
}, [adminBasePath, id, pathBase]);
|
|
7238
|
+
return /* @__PURE__ */ jsxs32(
|
|
7239
|
+
"div",
|
|
7240
|
+
{
|
|
7241
|
+
style: {
|
|
7242
|
+
alignItems: "center",
|
|
7243
|
+
display: "flex",
|
|
7244
|
+
flexDirection: "column",
|
|
7245
|
+
gap: "0.75rem",
|
|
7246
|
+
justifyContent: "center",
|
|
7247
|
+
minHeight: "50vh",
|
|
7248
|
+
textAlign: "center"
|
|
7249
|
+
},
|
|
7250
|
+
children: [
|
|
7251
|
+
/* @__PURE__ */ jsx36("h2", { style: { margin: 0 }, children: title }),
|
|
7252
|
+
/* @__PURE__ */ jsx36("p", { style: { color: "var(--theme-elevation-600)", margin: 0 }, children: description }),
|
|
7253
|
+
/* @__PURE__ */ jsx36("a", { href: fallbackHref, children: emptyLabel })
|
|
5950
7254
|
]
|
|
5951
7255
|
}
|
|
5952
7256
|
);
|
|
5953
7257
|
}
|
|
5954
7258
|
|
|
5955
7259
|
// src/admin/components/studio/StudioBackBreadcrumb.tsx
|
|
5956
|
-
import { useEffect as
|
|
7260
|
+
import { useEffect as useEffect24, useState as useState23 } from "react";
|
|
5957
7261
|
import { SetStepNav as SetStepNav5 } from "@payloadcms/ui";
|
|
5958
|
-
import { jsx as
|
|
7262
|
+
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
5959
7263
|
var toTitle = (slug) => slug.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
5960
7264
|
var buildNav = (pathname, adminBasePath) => {
|
|
5961
7265
|
if (pathname.includes("/globals/")) {
|
|
@@ -6000,8 +7304,8 @@ var buildNav = (pathname, adminBasePath) => {
|
|
|
6000
7304
|
};
|
|
6001
7305
|
function StudioBackBreadcrumb() {
|
|
6002
7306
|
const adminBasePath = useAdminBasePath();
|
|
6003
|
-
const [pathname, setPathname] =
|
|
6004
|
-
|
|
7307
|
+
const [pathname, setPathname] = useState23("");
|
|
7308
|
+
useEffect24(() => {
|
|
6005
7309
|
const update = () => setPathname(window.location.pathname);
|
|
6006
7310
|
update();
|
|
6007
7311
|
window.addEventListener("popstate", update);
|
|
@@ -6009,13 +7313,13 @@ function StudioBackBreadcrumb() {
|
|
|
6009
7313
|
}, []);
|
|
6010
7314
|
const nav = buildNav(pathname, adminBasePath);
|
|
6011
7315
|
if (!nav) return null;
|
|
6012
|
-
return /* @__PURE__ */
|
|
7316
|
+
return /* @__PURE__ */ jsx37(SetStepNav5, { nav });
|
|
6013
7317
|
}
|
|
6014
7318
|
|
|
6015
7319
|
// src/admin/components/studio/StudioContactFormRedirect.tsx
|
|
6016
|
-
import { useEffect as
|
|
6017
|
-
import { jsx as
|
|
6018
|
-
var
|
|
7320
|
+
import { useEffect as useEffect25 } from "react";
|
|
7321
|
+
import { jsx as jsx38, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
7322
|
+
var getPropString15 = (props, key, fallback) => {
|
|
6019
7323
|
if (!props || typeof props !== "object") return fallback;
|
|
6020
7324
|
const direct = props[key];
|
|
6021
7325
|
if (typeof direct === "string" && direct.length > 0) return direct;
|
|
@@ -6028,13 +7332,13 @@ var getPropString14 = (props, key, fallback) => {
|
|
|
6028
7332
|
};
|
|
6029
7333
|
function StudioContactFormRedirect(props) {
|
|
6030
7334
|
const adminBasePath = useAdminBasePath();
|
|
6031
|
-
const studioContactFormPath =
|
|
7335
|
+
const studioContactFormPath = getPropString15(props, "studioContactFormPath", "/contact-form");
|
|
6032
7336
|
const targetPath = resolveAdminPath(adminBasePath, studioContactFormPath);
|
|
6033
|
-
|
|
7337
|
+
useEffect25(() => {
|
|
6034
7338
|
if (window.location.pathname === targetPath) return;
|
|
6035
7339
|
window.location.replace(targetPath);
|
|
6036
7340
|
}, [targetPath]);
|
|
6037
|
-
return /* @__PURE__ */
|
|
7341
|
+
return /* @__PURE__ */ jsxs33(
|
|
6038
7342
|
"div",
|
|
6039
7343
|
{
|
|
6040
7344
|
style: {
|
|
@@ -6047,8 +7351,8 @@ function StudioContactFormRedirect(props) {
|
|
|
6047
7351
|
minHeight: "40vh"
|
|
6048
7352
|
},
|
|
6049
7353
|
children: [
|
|
6050
|
-
/* @__PURE__ */
|
|
6051
|
-
/* @__PURE__ */
|
|
7354
|
+
/* @__PURE__ */ jsx38("h2", { style: { margin: 0 }, children: "Opening Contact Form Editor..." }),
|
|
7355
|
+
/* @__PURE__ */ jsx38("a", { href: targetPath, children: "Continue" })
|
|
6052
7356
|
]
|
|
6053
7357
|
}
|
|
6054
7358
|
);
|
|
@@ -6059,6 +7363,9 @@ export {
|
|
|
6059
7363
|
AdminStudioContactFormView,
|
|
6060
7364
|
AdminStudioDashboard,
|
|
6061
7365
|
AdminStudioFooterGlobalView,
|
|
7366
|
+
AdminStudioFormDetailView,
|
|
7367
|
+
AdminStudioFormSubmissionView,
|
|
7368
|
+
AdminStudioFormUploadView,
|
|
6062
7369
|
AdminStudioFormsView,
|
|
6063
7370
|
AdminStudioGlobalsView,
|
|
6064
7371
|
AdminStudioHeaderGlobalView,
|
|
@@ -6084,6 +7391,7 @@ export {
|
|
|
6084
7391
|
StatusBadge,
|
|
6085
7392
|
StudioBackBreadcrumb,
|
|
6086
7393
|
StudioContactFormRedirect,
|
|
7394
|
+
StudioDocumentRedirect,
|
|
6087
7395
|
StudioSectionLayout,
|
|
6088
7396
|
ThemeProvider,
|
|
6089
7397
|
ThemeSwitcher,
|