strapi-plugin-hubspot 0.7.0 → 0.9.0
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/CHANGELOG.md +38 -0
- package/README.md +28 -0
- package/dist/_chunks/{Forms-CKA6ukB6.mjs → Forms-BsKys-Hc.mjs} +404 -42
- package/dist/_chunks/{Forms-HMZbTk_B.js → Forms-JuzNfsbL.js} +401 -39
- package/dist/_chunks/{HubspotFormInput-CKYRcNNU.mjs → HubspotFormInput-CIvHS5rp.mjs} +1 -1
- package/dist/_chunks/{HubspotFormInput-BequMb12.js → HubspotFormInput-ph9pe6xY.js} +1 -1
- package/dist/_chunks/{HubspotObjectInput-V3uhGK8k.mjs → HubspotObjectInput-BX1qYD2c.mjs} +3 -3
- package/dist/_chunks/{HubspotObjectInput-D-FGwsyS.js → HubspotObjectInput-dAd-lMdD.js} +3 -3
- package/dist/_chunks/{HubspotPropertyInput-Dn1QvOcu.js → HubspotPropertyInput-BM3ZaY8f.js} +3 -3
- package/dist/_chunks/{HubspotPropertyInput-DrBsx9jQ.mjs → HubspotPropertyInput-C2Z6472q.mjs} +3 -3
- package/dist/_chunks/{Settings-Cgp7M1Cv.js → Settings-Cdcjy9DA.js} +2 -2
- package/dist/_chunks/{Settings-BjkNbyna.mjs → Settings-DnwGetcc.mjs} +2 -2
- package/dist/_chunks/{en-Cun5LoUP.mjs → en-CcQWnXra.mjs} +50 -3
- package/dist/_chunks/{en-D5Ch9YFo.js → en-Cqfair98.js} +50 -3
- package/dist/_chunks/{fr-ClOWflse.mjs → fr-CBRZ9q8U.mjs} +50 -3
- package/dist/_chunks/{fr-CqlhHltZ.js → fr-D117-3Ta.js} +50 -3
- package/dist/_chunks/{index-D2Q34BuH.js → index-BbRtXnAL.js} +6 -6
- package/dist/_chunks/{index-FKsiOEPB.mjs → index-LTaVoyWJ.mjs} +6 -6
- package/dist/_chunks/{objectLabels-DBKevJle.mjs → objectLabels-DE2xGq7f.mjs} +1 -1
- package/dist/_chunks/{objectLabels-LAQ0M6-a.js → objectLabels-DU0Cagt_.js} +1 -1
- package/dist/_chunks/{useHubspotSchema-BC0Od-Wl.mjs → useHubspotSchema-BSKow0X3.mjs} +1 -1
- package/dist/_chunks/{useHubspotSchema-C08qBAyy.js → useHubspotSchema-DzBMAxv7.js} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/builder/types.d.ts +26 -0
- package/dist/admin/src/pages/Forms.d.ts +5 -1
- package/dist/admin/src/pages/Submissions.d.ts +8 -0
- package/dist/server/index.js +396 -21
- package/dist/server/index.mjs +396 -21
- package/dist/server/src/__tests__/importHubspot.test.d.ts +1 -0
- package/dist/server/src/__tests__/submissions.test.d.ts +1 -0
- package/dist/server/src/content-types.d.ts +3 -0
- package/dist/server/src/forms.d.ts +2 -0
- package/dist/server/src/formsAdmin.d.ts +19 -0
- package/dist/server/src/importHubspot.d.ts +85 -0
- package/dist/server/src/importLegacy.d.ts +1 -0
- package/dist/server/src/index.d.ts +32 -1
- package/dist/server/src/submissions.d.ts +28 -0
- package/dist/shared/types.d.ts +2 -0
- package/package.json +2 -2
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useParams, useSearchParams, Link, useNavigate, Routes, Route } from "react-router-dom";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { u as useIntl } from "./index-CEh8vkxY.mjs";
|
|
5
|
-
import { Typography, Flex, Box, SingleSelect, SingleSelectOption, TextInput, IconButton, Button, Field, Checkbox, Divider, Combobox, ComboboxOption, Loader, Badge, Textarea, Table, Thead, Tr, Th, Tbody, Td } from "@strapi/design-system";
|
|
6
|
-
import { Trash, Plus, ArrowClockwise, ArrowLeft, ArrowUp, ArrowDown } from "@strapi/icons";
|
|
5
|
+
import { Typography, Flex, Box, SingleSelect, SingleSelectOption, TextInput, IconButton, Button, Field, Checkbox, Divider, Combobox, ComboboxOption, Loader, Badge, Textarea, Table, Thead, Tr, Th, Tbody, Td, Modal } from "@strapi/design-system";
|
|
6
|
+
import { Trash, Plus, ArrowClockwise, ArrowLeft, ArrowUp, ArrowDown, List, Duplicate, Download } from "@strapi/icons";
|
|
7
7
|
import { useFetchClient } from "@strapi/strapi/admin";
|
|
8
|
-
import { g as getTranslation, P as PLUGIN_ID } from "./index-
|
|
9
|
-
import { o as objectLabel } from "./objectLabels-
|
|
10
|
-
import { u as useHubspotSchema } from "./useHubspotSchema-
|
|
8
|
+
import { g as getTranslation, P as PLUGIN_ID } from "./index-LTaVoyWJ.mjs";
|
|
9
|
+
import { o as objectLabel } from "./objectLabels-DE2xGq7f.mjs";
|
|
10
|
+
import { u as useHubspotSchema } from "./useHubspotSchema-BSKow0X3.mjs";
|
|
11
11
|
const OPERATORS = ["eq", "neq", "contains", "empty", "notEmpty", "gt", "lt"];
|
|
12
12
|
const NEEDS_VALUE = /* @__PURE__ */ new Set(["eq", "neq", "contains", "gt", "lt"]);
|
|
13
13
|
const ConditionEditor = ({ condition, candidates, onChange }) => {
|
|
@@ -224,6 +224,43 @@ const FieldPanel = ({ field, candidates, problem, onChange }) => {
|
|
|
224
224
|
children: t("panel.required", "Required")
|
|
225
225
|
}
|
|
226
226
|
),
|
|
227
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 4, children: [
|
|
228
|
+
/* @__PURE__ */ jsx(Box, { flex: "1", children: /* @__PURE__ */ jsxs(Field.Root, { children: [
|
|
229
|
+
/* @__PURE__ */ jsx(Field.Label, { children: t("panel.icon", "Icon") }),
|
|
230
|
+
/* @__PURE__ */ jsx(
|
|
231
|
+
TextInput,
|
|
232
|
+
{
|
|
233
|
+
value: field.icon ?? "",
|
|
234
|
+
placeholder: "i-lucide-building-2",
|
|
235
|
+
onChange: (e) => onChange({ icon: e.target.value })
|
|
236
|
+
}
|
|
237
|
+
)
|
|
238
|
+
] }) }),
|
|
239
|
+
/* @__PURE__ */ jsx(Box, { flex: "1", children: /* @__PURE__ */ jsxs(Field.Root, { children: [
|
|
240
|
+
/* @__PURE__ */ jsx(Field.Label, { children: t("panel.persist", "Answer memory") }),
|
|
241
|
+
/* @__PURE__ */ jsxs(
|
|
242
|
+
SingleSelect,
|
|
243
|
+
{
|
|
244
|
+
value: field.persist ?? "session",
|
|
245
|
+
onChange: (v) => onChange({ persist: v }),
|
|
246
|
+
children: [
|
|
247
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "session", children: t("panel.persist-session", "This visit only") }),
|
|
248
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "days30", children: t("panel.persist-days30", "30 days (non-identifying fields only)") })
|
|
249
|
+
]
|
|
250
|
+
}
|
|
251
|
+
)
|
|
252
|
+
] }) })
|
|
253
|
+
] }),
|
|
254
|
+
/* @__PURE__ */ jsxs(Field.Root, { children: [
|
|
255
|
+
/* @__PURE__ */ jsx(Field.Label, { children: t("panel.class", "CSS classes") }),
|
|
256
|
+
/* @__PURE__ */ jsx(
|
|
257
|
+
TextInput,
|
|
258
|
+
{
|
|
259
|
+
value: field.class ?? "",
|
|
260
|
+
onChange: (e) => onChange({ class: e.target.value })
|
|
261
|
+
}
|
|
262
|
+
)
|
|
263
|
+
] }),
|
|
227
264
|
isChoice && /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: [
|
|
228
265
|
/* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", children: t("panel.options", "Choices") }),
|
|
229
266
|
(field.options ?? []).map((option, index) => /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
@@ -370,6 +407,14 @@ const FormEditor = () => {
|
|
|
370
407
|
const [feedback, setFeedback] = React.useState(null);
|
|
371
408
|
const t = (id, defaultMessage, values) => formatMessage({ id: getTranslation(id), defaultMessage }, values);
|
|
372
409
|
const query = locale ? `?locale=${locale}` : "";
|
|
410
|
+
React.useEffect(() => {
|
|
411
|
+
if (!dirty) return void 0;
|
|
412
|
+
const warn = (event) => {
|
|
413
|
+
event.preventDefault();
|
|
414
|
+
};
|
|
415
|
+
window.addEventListener("beforeunload", warn);
|
|
416
|
+
return () => window.removeEventListener("beforeunload", warn);
|
|
417
|
+
}, [dirty]);
|
|
373
418
|
React.useEffect(() => {
|
|
374
419
|
get("/i18n/locales").then(({ data }) => Array.isArray(data) && setLocales(data)).catch(() => setLocales([]));
|
|
375
420
|
}, [get]);
|
|
@@ -462,6 +507,7 @@ const FormEditor = () => {
|
|
|
462
507
|
nextLabel: entry.nextLabel,
|
|
463
508
|
submitLabel: entry.submitLabel,
|
|
464
509
|
successMessage: entry.successMessage,
|
|
510
|
+
class: entry.class,
|
|
465
511
|
definition
|
|
466
512
|
}
|
|
467
513
|
);
|
|
@@ -567,6 +613,8 @@ const FormEditor = () => {
|
|
|
567
613
|
hasRadius: true,
|
|
568
614
|
shadow: "tableShadow",
|
|
569
615
|
padding: 4,
|
|
616
|
+
onClick: () => setSelection({ kind: "step", stepId: step.id }),
|
|
617
|
+
style: { cursor: "pointer" },
|
|
570
618
|
borderColor: selection.kind === "step" && selection.stepId === step.id ? "primary600" : void 0,
|
|
571
619
|
borderStyle: selection.kind === "step" && selection.stepId === step.id ? "solid" : void 0,
|
|
572
620
|
borderWidth: selection.kind === "step" && selection.stepId === step.id ? "1px" : void 0,
|
|
@@ -589,7 +637,7 @@ const FormEditor = () => {
|
|
|
589
637
|
]
|
|
590
638
|
}
|
|
591
639
|
),
|
|
592
|
-
/* @__PURE__ */ jsxs(Flex, { gap: 1, children: [
|
|
640
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 1, onClick: (e) => e.stopPropagation(), children: [
|
|
593
641
|
/* @__PURE__ */ jsx(
|
|
594
642
|
IconButton,
|
|
595
643
|
{
|
|
@@ -631,7 +679,10 @@ const FormEditor = () => {
|
|
|
631
679
|
background: isSelected ? "primary100" : "neutral100",
|
|
632
680
|
hasRadius: true,
|
|
633
681
|
padding: 3,
|
|
634
|
-
onClick: () =>
|
|
682
|
+
onClick: (e) => {
|
|
683
|
+
e.stopPropagation();
|
|
684
|
+
setSelection({ kind: "field", fieldId: field.id });
|
|
685
|
+
},
|
|
635
686
|
style: { cursor: "pointer" },
|
|
636
687
|
children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [
|
|
637
688
|
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", wrap: "wrap", children: [
|
|
@@ -689,7 +740,8 @@ const FormEditor = () => {
|
|
|
689
740
|
{
|
|
690
741
|
variant: "tertiary",
|
|
691
742
|
startIcon: /* @__PURE__ */ jsx(Plus, {}),
|
|
692
|
-
onClick: () => {
|
|
743
|
+
onClick: (e) => {
|
|
744
|
+
e.stopPropagation();
|
|
693
745
|
const field = newField(t("editor.new-field", "New field"));
|
|
694
746
|
patchStep(step.id, { fields: [...step.fields, field] });
|
|
695
747
|
setSelection({ kind: "field", fieldId: field.id });
|
|
@@ -746,6 +798,16 @@ const FormEditor = () => {
|
|
|
746
798
|
}
|
|
747
799
|
)
|
|
748
800
|
] }),
|
|
801
|
+
/* @__PURE__ */ jsxs(Field.Root, { children: [
|
|
802
|
+
/* @__PURE__ */ jsx(Field.Label, { children: t("panel.class", "CSS classes") }),
|
|
803
|
+
/* @__PURE__ */ jsx(
|
|
804
|
+
TextInput,
|
|
805
|
+
{
|
|
806
|
+
value: selectedStep.class ?? "",
|
|
807
|
+
onChange: (e) => patchStep(selectedStep.id, { class: e.target.value })
|
|
808
|
+
}
|
|
809
|
+
)
|
|
810
|
+
] }),
|
|
749
811
|
/* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", children: t("editor.step-condition", "Show this step only when…") }),
|
|
750
812
|
/* @__PURE__ */ jsx(
|
|
751
813
|
ConditionEditor,
|
|
@@ -819,6 +881,16 @@ const FormEditor = () => {
|
|
|
819
881
|
}
|
|
820
882
|
)
|
|
821
883
|
] }),
|
|
884
|
+
/* @__PURE__ */ jsxs(Field.Root, { children: [
|
|
885
|
+
/* @__PURE__ */ jsx(Field.Label, { children: t("panel.class", "CSS classes") }),
|
|
886
|
+
/* @__PURE__ */ jsx(
|
|
887
|
+
TextInput,
|
|
888
|
+
{
|
|
889
|
+
value: entry.class ?? "",
|
|
890
|
+
onChange: (e) => patchEntry({ class: e.target.value })
|
|
891
|
+
}
|
|
892
|
+
)
|
|
893
|
+
] }),
|
|
822
894
|
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: t(
|
|
823
895
|
"editor.form-hint",
|
|
824
896
|
"Select a step or a field to edit it. The public endpoint serves this form at /api/hubspot/forms/{slug}.",
|
|
@@ -838,6 +910,12 @@ const FormsList = () => {
|
|
|
838
910
|
const [error, setError] = React.useState(null);
|
|
839
911
|
const [sources, setSources] = React.useState([]);
|
|
840
912
|
const [sourceId, setSourceId] = React.useState("");
|
|
913
|
+
const [hsForms, setHsForms] = React.useState([]);
|
|
914
|
+
const [hsFormId, setHsFormId] = React.useState("");
|
|
915
|
+
const [hsError, setHsError] = React.useState(null);
|
|
916
|
+
const [report, setReport] = React.useState(
|
|
917
|
+
null
|
|
918
|
+
);
|
|
841
919
|
const t = (id, defaultMessage, values) => formatMessage({ id: getTranslation(id), defaultMessage }, values);
|
|
842
920
|
const load = React.useCallback(async () => {
|
|
843
921
|
const { data } = await get(`/${PLUGIN_ID}/builder/forms`);
|
|
@@ -848,6 +926,17 @@ const FormsList = () => {
|
|
|
848
926
|
get(
|
|
849
927
|
`/${PLUGIN_ID}/builder/import/sources`
|
|
850
928
|
).then(({ data }) => setSources(data.sources ?? [])).catch(() => setSources([]));
|
|
929
|
+
get(`/${PLUGIN_ID}/builder/import/hubspot`).then(({ data }) => setHsForms(data.configured ? data.forms ?? [] : [])).catch(
|
|
930
|
+
() => (
|
|
931
|
+
// Reachable settings but no portal list: almost always the missing scope.
|
|
932
|
+
setHsError(
|
|
933
|
+
t(
|
|
934
|
+
"forms.hubspot-list-error",
|
|
935
|
+
"Could not list the portal's forms — the token needs the `forms` read scope."
|
|
936
|
+
)
|
|
937
|
+
)
|
|
938
|
+
)
|
|
939
|
+
);
|
|
851
940
|
}, [load]);
|
|
852
941
|
const runImport = async () => {
|
|
853
942
|
if (!sourceId) return;
|
|
@@ -863,6 +952,48 @@ const FormsList = () => {
|
|
|
863
952
|
setBusy(false);
|
|
864
953
|
}
|
|
865
954
|
};
|
|
955
|
+
const runHubspotImport = async () => {
|
|
956
|
+
if (!hsFormId) return;
|
|
957
|
+
setBusy(true);
|
|
958
|
+
setError(null);
|
|
959
|
+
setReport(null);
|
|
960
|
+
try {
|
|
961
|
+
const { data } = await post(
|
|
962
|
+
`/${PLUGIN_ID}/builder/import/hubspot`,
|
|
963
|
+
{ formId: hsFormId }
|
|
964
|
+
);
|
|
965
|
+
if (data.skipped.length) {
|
|
966
|
+
setReport(data);
|
|
967
|
+
setBusy(false);
|
|
968
|
+
await load();
|
|
969
|
+
} else {
|
|
970
|
+
navigate(data.documentId);
|
|
971
|
+
}
|
|
972
|
+
} catch {
|
|
973
|
+
setError(t("forms.import-error", "Could not import the form."));
|
|
974
|
+
setBusy(false);
|
|
975
|
+
}
|
|
976
|
+
};
|
|
977
|
+
const skippedLine = (item) => {
|
|
978
|
+
const label = item.label ?? "";
|
|
979
|
+
const detail = item.detail ?? "";
|
|
980
|
+
switch (item.code) {
|
|
981
|
+
case "field-type":
|
|
982
|
+
return t("forms.skipped-field-type", '"{label}" skipped — unsupported type ({detail})', { label, detail });
|
|
983
|
+
case "hidden-field":
|
|
984
|
+
return t("forms.skipped-hidden", '"{label}" skipped — hidden fields are not supported yet', { label });
|
|
985
|
+
case "object":
|
|
986
|
+
return t("forms.skipped-object", '"{label}" skipped — unmapped object ({detail})', { label, detail });
|
|
987
|
+
case "duplicate":
|
|
988
|
+
return t("forms.skipped-duplicate", '"{label}" skipped — the name "{detail}" is already used', { label, detail });
|
|
989
|
+
case "condition":
|
|
990
|
+
return t("forms.skipped-condition", 'Condition on "{label}" dropped — no equivalent operator ({detail})', { label, detail });
|
|
991
|
+
case "rich-text":
|
|
992
|
+
return t("forms.skipped-rich-text", "A content block was skipped — the builder has no rich-text element");
|
|
993
|
+
case "legal-consent":
|
|
994
|
+
return t("forms.skipped-consent", "The GDPR consent block was skipped — rebuild it as a field if needed");
|
|
995
|
+
}
|
|
996
|
+
};
|
|
866
997
|
const create = async () => {
|
|
867
998
|
if (!name.trim()) return;
|
|
868
999
|
setBusy(true);
|
|
@@ -878,6 +1009,19 @@ const FormsList = () => {
|
|
|
878
1009
|
setBusy(false);
|
|
879
1010
|
}
|
|
880
1011
|
};
|
|
1012
|
+
const duplicate = async (row) => {
|
|
1013
|
+
setBusy(true);
|
|
1014
|
+
setError(null);
|
|
1015
|
+
try {
|
|
1016
|
+
const { data } = await post(
|
|
1017
|
+
`/${PLUGIN_ID}/builder/forms/${row.documentId}/duplicate`
|
|
1018
|
+
);
|
|
1019
|
+
navigate(data.documentId);
|
|
1020
|
+
} catch {
|
|
1021
|
+
setError(t("forms.duplicate-error", "Could not duplicate the form."));
|
|
1022
|
+
setBusy(false);
|
|
1023
|
+
}
|
|
1024
|
+
};
|
|
881
1025
|
const remove = async (row) => {
|
|
882
1026
|
if (!window.confirm(t("forms.delete-confirm", 'Delete "{name}" and all its locales?', { name: row.name }))) {
|
|
883
1027
|
return;
|
|
@@ -902,6 +1046,7 @@ const FormsList = () => {
|
|
|
902
1046
|
) })
|
|
903
1047
|
] }),
|
|
904
1048
|
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
1049
|
+
/* @__PURE__ */ jsx(Button, { variant: "tertiary", startIcon: /* @__PURE__ */ jsx(List, {}), onClick: () => navigate("submissions"), children: t("forms.submissions", "Submissions") }),
|
|
905
1050
|
/* @__PURE__ */ jsx(
|
|
906
1051
|
TextInput,
|
|
907
1052
|
{
|
|
@@ -916,40 +1061,76 @@ const FormsList = () => {
|
|
|
916
1061
|
] })
|
|
917
1062
|
] }),
|
|
918
1063
|
error && /* @__PURE__ */ jsx(Box, { paddingBottom: 4, children: /* @__PURE__ */ jsx(Typography, { textColor: "danger600", children: error }) }),
|
|
919
|
-
sources.length > 0 && /* @__PURE__ */ jsx(Box, { background: "neutral0", hasRadius: true, shadow: "tableShadow", padding: 4, marginBottom: 4, children: /* @__PURE__ */ jsxs(Flex, {
|
|
1064
|
+
(sources.length > 0 || hsForms.length > 0 || hsError) && /* @__PURE__ */ jsx(Box, { background: "neutral0", hasRadius: true, shadow: "tableShadow", padding: 4, marginBottom: 4, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 3, children: [
|
|
1065
|
+
hsForms.length > 0 && /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "flex-end", justifyContent: "space-between", children: [
|
|
1066
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
1067
|
+
/* @__PURE__ */ jsx(Typography, { variant: "delta", tag: "h2", children: t("forms.import-hubspot-title", "Import from your HubSpot portal") }),
|
|
1068
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", tag: "p", children: t(
|
|
1069
|
+
"forms.import-hubspot-hint",
|
|
1070
|
+
"Translates a form built in HubSpot into a draft here, CRM mapping included. What the builder can't express is skipped and reported. Re-importing overwrites the draft."
|
|
1071
|
+
) })
|
|
1072
|
+
] }),
|
|
1073
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
1074
|
+
/* @__PURE__ */ jsx(
|
|
1075
|
+
SingleSelect,
|
|
1076
|
+
{
|
|
1077
|
+
"aria-label": t("forms.import-hubspot-source", "HubSpot form to import"),
|
|
1078
|
+
placeholder: t("forms.import-hubspot-source", "HubSpot form to import"),
|
|
1079
|
+
value: hsFormId,
|
|
1080
|
+
onChange: (v) => setHsFormId(String(v)),
|
|
1081
|
+
children: hsForms.map((f) => /* @__PURE__ */ jsx(SingleSelectOption, { value: f.id, children: f.name }, f.id))
|
|
1082
|
+
}
|
|
1083
|
+
),
|
|
1084
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: runHubspotImport, disabled: busy || !hsFormId, children: t("forms.import", "Import") })
|
|
1085
|
+
] })
|
|
1086
|
+
] }),
|
|
1087
|
+
hsError && /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "warning700", children: hsError }),
|
|
1088
|
+
sources.length > 0 && /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "flex-end", justifyContent: "space-between", children: [
|
|
1089
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
1090
|
+
/* @__PURE__ */ jsx(Typography, { variant: "delta", tag: "h2", children: t("forms.import-title", "Import an existing form") }),
|
|
1091
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", tag: "p", children: t(
|
|
1092
|
+
"forms.import-hint",
|
|
1093
|
+
"Converts a legacy content-type form (all locales) into a draft here — same slug, source untouched. Re-importing overwrites the draft."
|
|
1094
|
+
) })
|
|
1095
|
+
] }),
|
|
1096
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
1097
|
+
/* @__PURE__ */ jsx(
|
|
1098
|
+
SingleSelect,
|
|
1099
|
+
{
|
|
1100
|
+
"aria-label": t("forms.import-source", "Form to import"),
|
|
1101
|
+
placeholder: t("forms.import-source", "Form to import"),
|
|
1102
|
+
value: sourceId,
|
|
1103
|
+
onChange: (v) => setSourceId(String(v)),
|
|
1104
|
+
children: sources.map((s) => /* @__PURE__ */ jsxs(SingleSelectOption, { value: s.documentId, children: [
|
|
1105
|
+
s.name,
|
|
1106
|
+
" ",
|
|
1107
|
+
s.slug ? `(${s.slug})` : ""
|
|
1108
|
+
] }, s.documentId))
|
|
1109
|
+
}
|
|
1110
|
+
),
|
|
1111
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: runImport, disabled: busy || !sourceId, children: t("forms.import", "Import") })
|
|
1112
|
+
] })
|
|
1113
|
+
] })
|
|
1114
|
+
] }) }),
|
|
1115
|
+
report && /* @__PURE__ */ jsx(Box, { background: "warning100", hasRadius: true, padding: 4, marginBottom: 4, children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "flex-start", gap: 4, children: [
|
|
920
1116
|
/* @__PURE__ */ jsxs(Box, { children: [
|
|
921
|
-
/* @__PURE__ */ jsx(Typography, { variant: "delta", tag: "h2", children: t("forms.
|
|
922
|
-
/* @__PURE__ */ jsx(
|
|
923
|
-
"forms.import-hint",
|
|
924
|
-
"Converts a legacy content-type form (all locales) into a draft here — same slug, source untouched. Re-importing overwrites the draft."
|
|
925
|
-
) })
|
|
1117
|
+
/* @__PURE__ */ jsx(Typography, { variant: "delta", tag: "h2", textColor: "warning700", children: t("forms.report-title", "Imported with gaps") }),
|
|
1118
|
+
/* @__PURE__ */ jsx(Box, { tag: "ul", paddingTop: 2, style: { listStyle: "disc", paddingLeft: 16 }, children: report.skipped.map((item, i) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "warning700", children: skippedLine(item) }) }, i)) })
|
|
926
1119
|
] }),
|
|
927
|
-
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
928
|
-
/* @__PURE__ */ jsx(
|
|
929
|
-
|
|
930
|
-
{
|
|
931
|
-
"aria-label": t("forms.import-source", "Form to import"),
|
|
932
|
-
placeholder: t("forms.import-source", "Form to import"),
|
|
933
|
-
value: sourceId,
|
|
934
|
-
onChange: (v) => setSourceId(String(v)),
|
|
935
|
-
children: sources.map((s) => /* @__PURE__ */ jsxs(SingleSelectOption, { value: s.documentId, children: [
|
|
936
|
-
s.name,
|
|
937
|
-
" ",
|
|
938
|
-
s.slug ? `(${s.slug})` : ""
|
|
939
|
-
] }, s.documentId))
|
|
940
|
-
}
|
|
941
|
-
),
|
|
942
|
-
/* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: runImport, disabled: busy || !sourceId, children: t("forms.import", "Import") })
|
|
1120
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, shrink: 0, children: [
|
|
1121
|
+
/* @__PURE__ */ jsx(Button, { variant: "tertiary", onClick: () => setReport(null), children: t("forms.report-dismiss", "Dismiss") }),
|
|
1122
|
+
/* @__PURE__ */ jsx(Button, { onClick: () => navigate(report.documentId), children: t("forms.report-open", "Open the form") })
|
|
943
1123
|
] })
|
|
944
1124
|
] }) }),
|
|
945
|
-
!rows ? /* @__PURE__ */ jsx(Loader, { children: t("forms.loading", "Loading…") }) : rows.length === 0 ? /* @__PURE__ */ jsx(Box, { background: "neutral0", hasRadius: true, shadow: "tableShadow", padding: 8, children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: t("forms.empty", "No form yet — name one above to open the builder.") }) }) : /* @__PURE__ */ jsxs(Table, { colCount:
|
|
1125
|
+
!rows ? /* @__PURE__ */ jsx(Loader, { children: t("forms.loading", "Loading…") }) : rows.length === 0 ? /* @__PURE__ */ jsx(Box, { background: "neutral0", hasRadius: true, shadow: "tableShadow", padding: 8, children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: t("forms.empty", "No form yet — name one above to open the builder.") }) }) : /* @__PURE__ */ jsxs(Table, { colCount: 7, rowCount: rows.length, children: [
|
|
946
1126
|
/* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
|
|
947
1127
|
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("forms.col-name", "Name") }) }),
|
|
948
1128
|
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("forms.col-slug", "Slug") }) }),
|
|
949
1129
|
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("forms.col-structure", "Structure") }) }),
|
|
950
1130
|
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("forms.col-status", "Status") }) }),
|
|
1131
|
+
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("forms.col-submissions", "Submissions") }) }),
|
|
951
1132
|
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("forms.col-updated", "Updated") }) }),
|
|
952
|
-
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("forms.col-actions", "") }) })
|
|
1133
|
+
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("forms.col-actions", "Actions") }) })
|
|
953
1134
|
] }) }),
|
|
954
1135
|
/* @__PURE__ */ jsx(Tbody, { children: rows.map((row) => /* @__PURE__ */ jsxs(
|
|
955
1136
|
Tr,
|
|
@@ -959,21 +1140,41 @@ const FormsList = () => {
|
|
|
959
1140
|
children: [
|
|
960
1141
|
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", children: row.name }) }),
|
|
961
1142
|
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: row.slug }) }),
|
|
962
|
-
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: t("forms.structure", "{steps} steps · {fields} fields", {
|
|
1143
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: t("forms.structure", "{steps, plural, one {# step} other {# steps}} · {fields, plural, one {# field} other {# fields}}", {
|
|
963
1144
|
steps: row.steps,
|
|
964
1145
|
fields: row.fields
|
|
965
1146
|
}) }) }),
|
|
966
1147
|
/* @__PURE__ */ jsx(Td, { children: row.published ? /* @__PURE__ */ jsx(Badge, { backgroundColor: "success100", textColor: "success700", children: t("forms.published", "Published") }) : /* @__PURE__ */ jsx(Badge, { backgroundColor: "secondary100", textColor: "secondary700", children: t("forms.draft", "Draft") }) }),
|
|
967
|
-
/* @__PURE__ */ jsx(Td, {
|
|
968
|
-
|
|
969
|
-
IconButton,
|
|
1148
|
+
/* @__PURE__ */ jsx(Td, { onClick: (e) => e.stopPropagation(), children: row.submissions > 0 ? /* @__PURE__ */ jsx(
|
|
1149
|
+
Button,
|
|
970
1150
|
{
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
children:
|
|
1151
|
+
variant: "ghost",
|
|
1152
|
+
startIcon: /* @__PURE__ */ jsx(List, {}),
|
|
1153
|
+
onClick: () => navigate(`submissions?form=${encodeURIComponent(row.slug)}`),
|
|
1154
|
+
children: row.submissions
|
|
975
1155
|
}
|
|
976
|
-
) })
|
|
1156
|
+
) : /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: "—" }) }),
|
|
1157
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: row.updatedAt ? new Date(row.updatedAt).toLocaleString() : "—" }) }),
|
|
1158
|
+
/* @__PURE__ */ jsx(Td, { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxs(Flex, { gap: 1, children: [
|
|
1159
|
+
/* @__PURE__ */ jsx(
|
|
1160
|
+
IconButton,
|
|
1161
|
+
{
|
|
1162
|
+
label: t("forms.duplicate", "Duplicate"),
|
|
1163
|
+
onClick: () => duplicate(row),
|
|
1164
|
+
disabled: busy,
|
|
1165
|
+
children: /* @__PURE__ */ jsx(Duplicate, {})
|
|
1166
|
+
}
|
|
1167
|
+
),
|
|
1168
|
+
/* @__PURE__ */ jsx(
|
|
1169
|
+
IconButton,
|
|
1170
|
+
{
|
|
1171
|
+
label: t("forms.delete", "Delete"),
|
|
1172
|
+
onClick: () => remove(row),
|
|
1173
|
+
disabled: busy,
|
|
1174
|
+
children: /* @__PURE__ */ jsx(Trash, {})
|
|
1175
|
+
}
|
|
1176
|
+
)
|
|
1177
|
+
] }) })
|
|
977
1178
|
]
|
|
978
1179
|
},
|
|
979
1180
|
row.documentId
|
|
@@ -981,8 +1182,169 @@ const FormsList = () => {
|
|
|
981
1182
|
] })
|
|
982
1183
|
] });
|
|
983
1184
|
};
|
|
1185
|
+
const PAGE_SIZE = 20;
|
|
1186
|
+
const preview = (values, max = 3) => {
|
|
1187
|
+
const parts = Object.entries(values ?? {}).slice(0, max).map(([k, v]) => `${k}: ${String(v)}`);
|
|
1188
|
+
const more = Object.keys(values ?? {}).length - max;
|
|
1189
|
+
return parts.join(" · ") + (more > 0 ? ` · +${more}` : "");
|
|
1190
|
+
};
|
|
1191
|
+
const Submissions = () => {
|
|
1192
|
+
const { formatMessage } = useIntl();
|
|
1193
|
+
const { get } = useFetchClient();
|
|
1194
|
+
const navigate = useNavigate();
|
|
1195
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
1196
|
+
const form = searchParams.get("form") ?? "";
|
|
1197
|
+
const [forms, setForms] = React.useState([]);
|
|
1198
|
+
const [rows, setRows] = React.useState(null);
|
|
1199
|
+
const [total, setTotal] = React.useState(0);
|
|
1200
|
+
const [page, setPage] = React.useState(1);
|
|
1201
|
+
const [selected, setSelected] = React.useState(null);
|
|
1202
|
+
const [error, setError] = React.useState(null);
|
|
1203
|
+
const [exporting, setExporting] = React.useState(false);
|
|
1204
|
+
const t = (id, defaultMessage, values) => formatMessage({ id: getTranslation(id), defaultMessage }, values);
|
|
1205
|
+
React.useEffect(() => {
|
|
1206
|
+
get(`/${PLUGIN_ID}/builder/forms`).then(({ data }) => setForms(data.forms)).catch(() => setForms([]));
|
|
1207
|
+
}, [get]);
|
|
1208
|
+
React.useEffect(() => {
|
|
1209
|
+
setRows(null);
|
|
1210
|
+
const query = new URLSearchParams({ page: String(page), pageSize: String(PAGE_SIZE) });
|
|
1211
|
+
if (form) query.set("form", form);
|
|
1212
|
+
get(
|
|
1213
|
+
`/${PLUGIN_ID}/builder/submissions?${query}`
|
|
1214
|
+
).then(({ data }) => {
|
|
1215
|
+
setRows(data.submissions);
|
|
1216
|
+
setTotal(data.total);
|
|
1217
|
+
}).catch(() => setError(t("submissions.load-error", "Could not load the submissions.")));
|
|
1218
|
+
}, [get, form, page]);
|
|
1219
|
+
const changeForm = (slug) => {
|
|
1220
|
+
setPage(1);
|
|
1221
|
+
setSearchParams(slug ? { form: slug } : {});
|
|
1222
|
+
};
|
|
1223
|
+
const exportCsv = async () => {
|
|
1224
|
+
if (!form) return;
|
|
1225
|
+
setExporting(true);
|
|
1226
|
+
setError(null);
|
|
1227
|
+
try {
|
|
1228
|
+
const { data } = await get(
|
|
1229
|
+
`/${PLUGIN_ID}/builder/submissions/export?form=${encodeURIComponent(form)}`
|
|
1230
|
+
);
|
|
1231
|
+
const url = URL.createObjectURL(new Blob([data.csv], { type: "text/csv;charset=utf-8" }));
|
|
1232
|
+
const link = document.createElement("a");
|
|
1233
|
+
link.href = url;
|
|
1234
|
+
link.download = data.filename;
|
|
1235
|
+
link.click();
|
|
1236
|
+
URL.revokeObjectURL(url);
|
|
1237
|
+
} catch {
|
|
1238
|
+
setError(t("submissions.export-error", "Could not export the submissions."));
|
|
1239
|
+
} finally {
|
|
1240
|
+
setExporting(false);
|
|
1241
|
+
}
|
|
1242
|
+
};
|
|
1243
|
+
const pages = Math.max(1, Math.ceil(total / PAGE_SIZE));
|
|
1244
|
+
return /* @__PURE__ */ jsxs(Box, { padding: 8, children: [
|
|
1245
|
+
/* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "flex-end", paddingBottom: 6, children: [
|
|
1246
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
1247
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
|
|
1248
|
+
/* @__PURE__ */ jsx(IconButton, { label: t("submissions.back", "Back to the forms"), onClick: () => navigate(".."), children: /* @__PURE__ */ jsx(ArrowLeft, {}) }),
|
|
1249
|
+
/* @__PURE__ */ jsx(Typography, { variant: "alpha", tag: "h1", children: t("submissions.title", "Submissions") })
|
|
1250
|
+
] }),
|
|
1251
|
+
/* @__PURE__ */ jsx(Typography, { variant: "epsilon", textColor: "neutral600", tag: "p", children: t(
|
|
1252
|
+
"submissions.subtitle",
|
|
1253
|
+
"Every answer received by the built forms — stored whatever the CRM's mood."
|
|
1254
|
+
) })
|
|
1255
|
+
] }),
|
|
1256
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
1257
|
+
/* @__PURE__ */ jsx(
|
|
1258
|
+
SingleSelect,
|
|
1259
|
+
{
|
|
1260
|
+
"aria-label": t("submissions.filter", "Filter by form"),
|
|
1261
|
+
placeholder: t("submissions.all-forms", "All forms"),
|
|
1262
|
+
value: form,
|
|
1263
|
+
onChange: (v) => changeForm(String(v)),
|
|
1264
|
+
onClear: () => changeForm(""),
|
|
1265
|
+
children: forms.map((f) => /* @__PURE__ */ jsx(SingleSelectOption, { value: f.slug, children: f.name }, f.slug))
|
|
1266
|
+
}
|
|
1267
|
+
),
|
|
1268
|
+
/* @__PURE__ */ jsx(
|
|
1269
|
+
Button,
|
|
1270
|
+
{
|
|
1271
|
+
variant: "secondary",
|
|
1272
|
+
startIcon: /* @__PURE__ */ jsx(Download, {}),
|
|
1273
|
+
onClick: exportCsv,
|
|
1274
|
+
disabled: !form || exporting,
|
|
1275
|
+
title: form ? void 0 : t("submissions.export-pick", "Pick a form to export"),
|
|
1276
|
+
children: t("submissions.export", "Export CSV")
|
|
1277
|
+
}
|
|
1278
|
+
)
|
|
1279
|
+
] })
|
|
1280
|
+
] }),
|
|
1281
|
+
error && /* @__PURE__ */ jsx(Box, { paddingBottom: 4, children: /* @__PURE__ */ jsx(Typography, { textColor: "danger600", children: error }) }),
|
|
1282
|
+
!rows ? /* @__PURE__ */ jsx(Loader, { children: t("submissions.loading", "Loading…") }) : rows.length === 0 ? /* @__PURE__ */ jsx(Box, { background: "neutral0", hasRadius: true, shadow: "tableShadow", padding: 8, children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: form ? t("submissions.empty-form", "No submission for this form yet.") : t("submissions.empty", "No submission yet.") }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1283
|
+
/* @__PURE__ */ jsxs(Table, { colCount: 5, rowCount: rows.length, children: [
|
|
1284
|
+
/* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
|
|
1285
|
+
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("submissions.col-date", "Date") }) }),
|
|
1286
|
+
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("submissions.col-form", "Form") }) }),
|
|
1287
|
+
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("submissions.col-email", "Email") }) }),
|
|
1288
|
+
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("submissions.col-answers", "Answers") }) }),
|
|
1289
|
+
/* @__PURE__ */ jsx(Th, { children: /* @__PURE__ */ jsx(Typography, { variant: "sigma", children: t("submissions.col-crm", "CRM") }) })
|
|
1290
|
+
] }) }),
|
|
1291
|
+
/* @__PURE__ */ jsx(Tbody, { children: rows.map((row) => /* @__PURE__ */ jsxs(
|
|
1292
|
+
Tr,
|
|
1293
|
+
{
|
|
1294
|
+
onClick: () => setSelected(row),
|
|
1295
|
+
style: { cursor: "pointer" },
|
|
1296
|
+
children: [
|
|
1297
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: row.createdAt ? new Date(row.createdAt).toLocaleString() : "—" }) }),
|
|
1298
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { children: row.formTitle || row.form }) }),
|
|
1299
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { fontWeight: "semiBold", children: row.email || "—" }) }),
|
|
1300
|
+
/* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", ellipsis: true, children: preview(row.values) }) }),
|
|
1301
|
+
/* @__PURE__ */ jsx(Td, { children: row.hubspotSynced ? /* @__PURE__ */ jsx(Badge, { backgroundColor: "success100", textColor: "success700", children: t("submissions.synced", "Synced") }) : /* @__PURE__ */ jsx(Badge, { backgroundColor: "warning100", textColor: "warning700", children: t("submissions.not-synced", "Not synced") }) })
|
|
1302
|
+
]
|
|
1303
|
+
},
|
|
1304
|
+
row.documentId
|
|
1305
|
+
)) })
|
|
1306
|
+
] }),
|
|
1307
|
+
/* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", paddingTop: 4, children: [
|
|
1308
|
+
/* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: t("submissions.count", "{total, plural, one {# submission} other {# submissions}}", {
|
|
1309
|
+
total
|
|
1310
|
+
}) }),
|
|
1311
|
+
pages > 1 && /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
1312
|
+
/* @__PURE__ */ jsx(Button, { variant: "tertiary", disabled: page <= 1, onClick: () => setPage(page - 1), children: t("submissions.prev", "Previous") }),
|
|
1313
|
+
/* @__PURE__ */ jsx(Typography, { textColor: "neutral600", children: t("submissions.page", "{page} / {pages}", { page, pages }) }),
|
|
1314
|
+
/* @__PURE__ */ jsx(
|
|
1315
|
+
Button,
|
|
1316
|
+
{
|
|
1317
|
+
variant: "tertiary",
|
|
1318
|
+
disabled: page >= pages,
|
|
1319
|
+
onClick: () => setPage(page + 1),
|
|
1320
|
+
children: t("submissions.next", "Next")
|
|
1321
|
+
}
|
|
1322
|
+
)
|
|
1323
|
+
] })
|
|
1324
|
+
] })
|
|
1325
|
+
] }),
|
|
1326
|
+
/* @__PURE__ */ jsx(Modal.Root, { open: Boolean(selected), onOpenChange: (open) => !open && setSelected(null), children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
|
|
1327
|
+
/* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsxs(Modal.Title, { children: [
|
|
1328
|
+
selected?.formTitle || selected?.form,
|
|
1329
|
+
" ",
|
|
1330
|
+
selected?.createdAt ? `— ${new Date(selected.createdAt).toLocaleString()}` : ""
|
|
1331
|
+
] }) }),
|
|
1332
|
+
/* @__PURE__ */ jsx(Modal.Body, { children: selected && /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 3, children: [
|
|
1333
|
+
Object.entries(selected.values ?? {}).map(([key, value]) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
1334
|
+
/* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", tag: "p", children: key }),
|
|
1335
|
+
/* @__PURE__ */ jsx(Typography, { tag: "p", children: String(value) })
|
|
1336
|
+
] }, key)),
|
|
1337
|
+
selected.meta?.pagePath && /* @__PURE__ */ jsxs(Box, { children: [
|
|
1338
|
+
/* @__PURE__ */ jsx(Typography, { variant: "sigma", textColor: "neutral600", tag: "p", children: t("submissions.meta-page", "Submitted from") }),
|
|
1339
|
+
/* @__PURE__ */ jsx(Typography, { tag: "p", children: selected.meta.pagePath })
|
|
1340
|
+
] })
|
|
1341
|
+
] }) })
|
|
1342
|
+
] }) })
|
|
1343
|
+
] });
|
|
1344
|
+
};
|
|
984
1345
|
const Forms = () => /* @__PURE__ */ jsxs(Routes, { children: [
|
|
985
1346
|
/* @__PURE__ */ jsx(Route, { index: true, element: /* @__PURE__ */ jsx(FormsList, {}) }),
|
|
1347
|
+
/* @__PURE__ */ jsx(Route, { path: "submissions", element: /* @__PURE__ */ jsx(Submissions, {}) }),
|
|
986
1348
|
/* @__PURE__ */ jsx(Route, { path: ":documentId", element: /* @__PURE__ */ jsx(FormEditor, {}) })
|
|
987
1349
|
] });
|
|
988
1350
|
export {
|