@fonderie/vue-courier-admin-screens 0.10.0 → 0.11.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/dist/index.cjs +246 -107
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +76 -56
- package/dist/index.d.ts +76 -56
- package/dist/index.js +253 -111
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -292,6 +292,8 @@ var TemplateCreateScreen = (0, import_vue.defineComponent)({
|
|
|
292
292
|
type: { type: String, default: void 0 },
|
|
293
293
|
/** Locales already in use, offered as suggestions. */
|
|
294
294
|
locales: { type: Array, default: () => [] },
|
|
295
|
+
/** The system locale: the default version already is it, so adding it is refused. */
|
|
296
|
+
defaultLocale: { type: String, default: void 0 },
|
|
295
297
|
/** The console language; defaults to English. */
|
|
296
298
|
locale: { type: String, default: void 0 }
|
|
297
299
|
},
|
|
@@ -319,7 +321,7 @@ var TemplateCreateScreen = (0, import_vue.defineComponent)({
|
|
|
319
321
|
const tr = (key, params) => (0, import_client.createAdminT)(props.locale)(key, params);
|
|
320
322
|
(0, import_vue.onMounted)(() => {
|
|
321
323
|
if (!props.type) return;
|
|
322
|
-
props.client.getTemplate(props.type, null).then(({ result }) => {
|
|
324
|
+
props.client.getTemplate(props.type, null).catch(() => props.client.getBuiltInTemplate(props.type, null)).then(({ result }) => {
|
|
323
325
|
subject.value = result.subject ?? "";
|
|
324
326
|
html.value = result.html ?? "";
|
|
325
327
|
text.value = result.text;
|
|
@@ -384,6 +386,10 @@ var TemplateCreateScreen = (0, import_vue.defineComponent)({
|
|
|
384
386
|
error.value = tr("templates.create.errorLocale");
|
|
385
387
|
return;
|
|
386
388
|
}
|
|
389
|
+
if (l && props.defaultLocale && l.toLowerCase() === props.defaultLocale.toLowerCase()) {
|
|
390
|
+
error.value = tr("templates.create.errorDefaultLocale", { locale: props.defaultLocale });
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
387
393
|
if (!text.value.trim()) {
|
|
388
394
|
error.value = tr("templates.create.errorText");
|
|
389
395
|
return;
|
|
@@ -527,7 +533,8 @@ var tabSelected = {
|
|
|
527
533
|
borderBottomColor: "var(--fonderie-text,#171717)",
|
|
528
534
|
cursor: "default"
|
|
529
535
|
};
|
|
530
|
-
var tabInactive = {
|
|
536
|
+
var tabInactive = { opacity: 0.55, textDecoration: "line-through" };
|
|
537
|
+
var tabBuiltIn = { fontStyle: "italic" };
|
|
531
538
|
var tabBar = {
|
|
532
539
|
display: "flex",
|
|
533
540
|
alignItems: "flex-end",
|
|
@@ -577,10 +584,27 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
577
584
|
props.type,
|
|
578
585
|
props.locale
|
|
579
586
|
);
|
|
580
|
-
const {
|
|
581
|
-
const
|
|
582
|
-
|
|
587
|
+
const { saveTemplate, removeTemplate } = (0, import_vue_courier_admin2.useTemplates)(props.client);
|
|
588
|
+
const notSaved = (0, import_vue2.computed)(() => error.value?.status === 404);
|
|
589
|
+
const { builtIn: builtIn2, isLoading: builtInLoading } = (0, import_vue_courier_admin2.useBuiltInTemplate)(
|
|
590
|
+
props.client,
|
|
591
|
+
props.type,
|
|
592
|
+
props.locale
|
|
593
|
+
);
|
|
594
|
+
const { catalog, refresh: refreshCatalog } = (0, import_vue_courier_admin2.useTemplateCatalog)(props.client);
|
|
595
|
+
const defaultLocale = (0, import_vue2.computed)(() => catalog.value?.defaultLocale ?? "en-US");
|
|
596
|
+
const email = (0, import_vue2.computed)(() => catalog.value?.emails.find((e) => e.type === props.type));
|
|
597
|
+
const languages = (0, import_vue2.computed)(
|
|
598
|
+
() => email.value ? (0, import_client2.templateLanguages)(email.value, defaultLocale.value) : []
|
|
583
599
|
);
|
|
600
|
+
const source = (0, import_vue2.computed)(() => template.value ?? (notSaved.value ? builtIn2.value : null));
|
|
601
|
+
const protectedRow = (0, import_vue2.computed)(() => !props.locale && (email.value?.system ?? props.system));
|
|
602
|
+
const shipsHere = (0, import_vue2.computed)(
|
|
603
|
+
() => props.locale ? languages.value.some((l) => l.locale === props.locale && l.builtIn) : !!email.value?.builtIn.default
|
|
604
|
+
);
|
|
605
|
+
const { resolution, resolve } = (0, import_vue_courier_admin2.useTemplateResolution)(props.client);
|
|
606
|
+
const probe = (0, import_vue2.ref)("");
|
|
607
|
+
(0, import_vue2.watch)(defaultLocale, (dl) => void resolve(props.type, props.locale ?? dl), { immediate: true });
|
|
584
608
|
const isDeleting = (0, import_vue2.ref)(false);
|
|
585
609
|
const { revisions, rollback } = (0, import_vue_courier_admin2.useTemplateRevisions)(props.client, props.type, props.locale);
|
|
586
610
|
const isSaving = (0, import_vue2.ref)(false);
|
|
@@ -589,12 +613,12 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
589
613
|
const html = (0, import_vue2.ref)("");
|
|
590
614
|
const text = (0, import_vue2.ref)("");
|
|
591
615
|
const active = (0, import_vue2.ref)(true);
|
|
592
|
-
(0, import_vue2.watch)(
|
|
593
|
-
if (!
|
|
594
|
-
subject.value =
|
|
595
|
-
html.value =
|
|
596
|
-
text.value =
|
|
597
|
-
active.value =
|
|
616
|
+
(0, import_vue2.watch)(source, (src) => {
|
|
617
|
+
if (!src) return;
|
|
618
|
+
subject.value = src.subject ?? "";
|
|
619
|
+
html.value = src.html ?? "";
|
|
620
|
+
text.value = src.text;
|
|
621
|
+
active.value = template.value ? template.value.active : true;
|
|
598
622
|
});
|
|
599
623
|
const {
|
|
600
624
|
preview,
|
|
@@ -639,13 +663,13 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
639
663
|
}
|
|
640
664
|
let previewTimer;
|
|
641
665
|
(0, import_vue2.watch)([template, subject, html, text, sampleJson], () => {
|
|
642
|
-
if (!
|
|
666
|
+
if (!source.value) return;
|
|
643
667
|
clearTimeout(previewTimer);
|
|
644
668
|
previewTimer = setTimeout(() => void run(), PREVIEW_DEBOUNCE_MS2);
|
|
645
669
|
});
|
|
646
670
|
const dirty = (0, import_vue2.computed)(() => {
|
|
647
671
|
const tpl = template.value;
|
|
648
|
-
return !!tpl && (subject.value !== (tpl.subject ?? "") || html.value !== (tpl.html ?? "") || text.value !== tpl.text || active.value !== tpl.active);
|
|
672
|
+
return notSaved.value && !!builtIn2.value || !!tpl && (subject.value !== (tpl.subject ?? "") || html.value !== (tpl.html ?? "") || text.value !== tpl.text || active.value !== tpl.active);
|
|
649
673
|
});
|
|
650
674
|
async function handleSubmit(event) {
|
|
651
675
|
event.preventDefault();
|
|
@@ -657,7 +681,7 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
657
681
|
if (html.value) input.html = html.value;
|
|
658
682
|
if (template.value?.version !== void 0) input.ifVersion = template.value.version;
|
|
659
683
|
await saveTemplate(props.type, input, props.locale);
|
|
660
|
-
await refresh();
|
|
684
|
+
await Promise.all([refresh(), refreshCatalog()]);
|
|
661
685
|
emit("saved");
|
|
662
686
|
} catch (err) {
|
|
663
687
|
saveError.value = err;
|
|
@@ -665,7 +689,32 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
665
689
|
isSaving.value = false;
|
|
666
690
|
}
|
|
667
691
|
}
|
|
668
|
-
const leave = () => !dirty.value || window.confirm(t("templates.editor.discardChanges"));
|
|
692
|
+
const leave = () => !dirty.value || notSaved.value && !!builtIn2.value || window.confirm(t("templates.editor.discardChanges"));
|
|
693
|
+
async function handleReset() {
|
|
694
|
+
const copy = builtIn2.value;
|
|
695
|
+
if (!copy || !window.confirm(
|
|
696
|
+
t("templates.editor.confirmReset", { locale: props.locale ?? defaultLocale.value })
|
|
697
|
+
))
|
|
698
|
+
return;
|
|
699
|
+
isDeleting.value = true;
|
|
700
|
+
saveError.value = null;
|
|
701
|
+
try {
|
|
702
|
+
if (props.locale) {
|
|
703
|
+
await removeTemplate(props.type, props.locale);
|
|
704
|
+
} else {
|
|
705
|
+
const input = { text: copy.text, active: active.value };
|
|
706
|
+
if (copy.subject) input.subject = copy.subject;
|
|
707
|
+
if (copy.html) input.html = copy.html;
|
|
708
|
+
if (template.value?.version !== void 0) input.ifVersion = template.value.version;
|
|
709
|
+
await saveTemplate(props.type, input, null);
|
|
710
|
+
}
|
|
711
|
+
await Promise.all([refresh(), refreshCatalog()]);
|
|
712
|
+
} catch (err) {
|
|
713
|
+
saveError.value = err;
|
|
714
|
+
} finally {
|
|
715
|
+
isDeleting.value = false;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
669
718
|
function renderTabBar() {
|
|
670
719
|
if (!props.localeTabs && !props.allowAddLocale) return null;
|
|
671
720
|
return (0, import_vue2.h)("div", { style: tabBar }, [
|
|
@@ -675,21 +724,30 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
675
724
|
(0, import_vue2.h)(
|
|
676
725
|
"nav",
|
|
677
726
|
{ "aria-label": t("templates.editor.locales"), style: tabs },
|
|
678
|
-
|
|
679
|
-
const selected =
|
|
727
|
+
languages.value.map((l) => {
|
|
728
|
+
const selected = l.locale === (props.locale ?? null);
|
|
680
729
|
return (0, import_vue2.h)(
|
|
681
730
|
"button",
|
|
682
731
|
{
|
|
683
|
-
key:
|
|
732
|
+
key: l.label,
|
|
684
733
|
type: "button",
|
|
685
734
|
"aria-current": selected ? "true" : void 0,
|
|
686
|
-
style:
|
|
687
|
-
|
|
735
|
+
style: {
|
|
736
|
+
...selected ? tabSelected : tab,
|
|
737
|
+
...l.saved ? {} : tabBuiltIn,
|
|
738
|
+
...l.active ? {} : tabInactive
|
|
739
|
+
},
|
|
740
|
+
title: l.active ? void 0 : t("common.status.inactive"),
|
|
688
741
|
onClick: () => {
|
|
689
|
-
if (!selected && leave())
|
|
742
|
+
if (!selected && leave())
|
|
743
|
+
emit("select-locale", {
|
|
744
|
+
type: props.type,
|
|
745
|
+
locale: l.locale,
|
|
746
|
+
system: !!email.value?.system
|
|
747
|
+
});
|
|
690
748
|
}
|
|
691
749
|
},
|
|
692
|
-
|
|
750
|
+
l.label
|
|
693
751
|
);
|
|
694
752
|
})
|
|
695
753
|
)
|
|
@@ -702,7 +760,8 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
702
760
|
onClick: () => {
|
|
703
761
|
if (leave())
|
|
704
762
|
emit("add-locale", props.type, {
|
|
705
|
-
locales: (0, import_client2.
|
|
763
|
+
locales: catalog.value ? (0, import_client2.suggestTemplateLocales)(catalog.value, props.type) : [],
|
|
764
|
+
defaultLocale: defaultLocale.value
|
|
706
765
|
});
|
|
707
766
|
}
|
|
708
767
|
},
|
|
@@ -738,16 +797,19 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
738
797
|
]);
|
|
739
798
|
}
|
|
740
799
|
return () => {
|
|
741
|
-
if (isLoading.value
|
|
742
|
-
|
|
800
|
+
if (isLoading.value || notSaved.value && builtInLoading.value)
|
|
801
|
+
return (0, import_vue2.h)("p", { style: styles.status }, t("templates.editor.loading"));
|
|
802
|
+
if (error.value && !(notSaved.value && builtIn2.value))
|
|
743
803
|
return (0, import_vue2.h)("p", { style: styles.error, role: "alert" }, error.value.explanation);
|
|
744
804
|
return (0, import_vue2.h)("div", { style: styles.container }, [
|
|
745
805
|
(0, import_vue2.h)("h1", { style: styles.title }, props.type),
|
|
746
806
|
renderTabBar(),
|
|
747
807
|
(0, import_vue2.h)("p", { style: styles.meta }, [
|
|
748
|
-
(0, import_vue2.h)("strong", props.locale ??
|
|
749
|
-
` \xB7 v${template.value
|
|
750
|
-
|
|
808
|
+
(0, import_vue2.h)("strong", props.locale ?? defaultLocale.value),
|
|
809
|
+
template.value ? ` \xB7 v${template.value.version}` : "",
|
|
810
|
+
template.value && protectedRow.value ? ` \xB7 ${t("templates.editor.builtInNote")}` : "",
|
|
811
|
+
!template.value && builtIn2.value ? ` \xB7 ${t("templates.editor.builtInCopy")}` : "",
|
|
812
|
+
resolution.value && resolution.value.chain.length > 1 && resolution.value.requested === (props.locale ?? defaultLocale.value) ? ` \xB7 ${t("templates.editor.chain", { chain: [...resolution.value.chain, defaultLocale.value].join(" \u2192 ") })}` : ""
|
|
751
813
|
]),
|
|
752
814
|
(0, import_vue2.h)("div", { style: styles.split }, [
|
|
753
815
|
(0, import_vue2.h)("div", { style: styles.column }, [
|
|
@@ -818,7 +880,16 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
818
880
|
isSaving.value ? t("common.saving") : t("common.save")
|
|
819
881
|
),
|
|
820
882
|
!dirty.value && !isSaving.value ? (0, import_vue2.h)("span", { style: styles.meta }, t("templates.editor.noChanges")) : null,
|
|
821
|
-
|
|
883
|
+
template.value && shipsHere.value && builtIn2.value ? (0, import_vue2.h)(
|
|
884
|
+
"button",
|
|
885
|
+
{
|
|
886
|
+
type: "button",
|
|
887
|
+
disabled: isDeleting.value,
|
|
888
|
+
onClick: () => void handleReset(),
|
|
889
|
+
style: { ...styles.rollbackButton, height: "36px", marginLeft: "auto" }
|
|
890
|
+
},
|
|
891
|
+
t("templates.editor.resetToBuiltIn")
|
|
892
|
+
) : template.value && !protectedRow.value ? (0, import_vue2.h)(
|
|
822
893
|
"button",
|
|
823
894
|
{
|
|
824
895
|
type: "button",
|
|
@@ -877,6 +948,46 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
877
948
|
) : preview.value ? (0, import_vue2.h)("pre", { style: styles.previewText }, preview.value.text) : (0, import_vue2.h)("p", { style: styles.meta }, t("templates.editor.nothingRendered"))
|
|
878
949
|
])
|
|
879
950
|
]),
|
|
951
|
+
// Who receives what: any locale, answered by the same decision a send makes.
|
|
952
|
+
(0, import_vue2.h)("div", { style: styles.revisions }, [
|
|
953
|
+
(0, import_vue2.h)("h2", { style: styles.subtitle }, t("templates.editor.whoReceives")),
|
|
954
|
+
(0, import_vue2.h)(
|
|
955
|
+
"form",
|
|
956
|
+
{
|
|
957
|
+
style: { display: "flex", gap: "8px", alignItems: "center", flexWrap: "wrap" },
|
|
958
|
+
onSubmit: (event) => {
|
|
959
|
+
event.preventDefault();
|
|
960
|
+
if (probe.value.trim()) void resolve(props.type, probe.value.trim());
|
|
961
|
+
}
|
|
962
|
+
},
|
|
963
|
+
[
|
|
964
|
+
(0, import_vue2.h)("input", {
|
|
965
|
+
"aria-label": t("templates.editor.whoReceives"),
|
|
966
|
+
style: { ...styles.input, width: "200px" },
|
|
967
|
+
value: probe.value,
|
|
968
|
+
placeholder: t("templates.editor.whoPlaceholder"),
|
|
969
|
+
spellcheck: false,
|
|
970
|
+
onInput: (e) => {
|
|
971
|
+
probe.value = e.target.value;
|
|
972
|
+
}
|
|
973
|
+
}),
|
|
974
|
+
(0, import_vue2.h)(
|
|
975
|
+
"button",
|
|
976
|
+
{ type: "submit", style: { ...styles.rollbackButton, height: "36px" } },
|
|
977
|
+
t("templates.editor.check")
|
|
978
|
+
),
|
|
979
|
+
resolution.value && probe.value.trim() ? (0, import_vue2.h)("span", { style: { ...styles.meta, marginBottom: "0" }, role: "status" }, [
|
|
980
|
+
t("templates.editor.receives", {
|
|
981
|
+
requested: resolution.value.requested,
|
|
982
|
+
sent: resolution.value.sent
|
|
983
|
+
}),
|
|
984
|
+
" ",
|
|
985
|
+
resolution.value.source === "saved" ? t("templates.editor.sourceSaved") : t("templates.editor.sourceBuiltIn"),
|
|
986
|
+
resolution.value.chain.length > 0 ? ` (${[...resolution.value.chain, resolution.value.defaultLocale].join(" \u2192 ")})` : ""
|
|
987
|
+
]) : null
|
|
988
|
+
]
|
|
989
|
+
)
|
|
990
|
+
]),
|
|
880
991
|
revisions.value.length > 0 ? (0, import_vue2.h)("div", { style: styles.revisions }, [
|
|
881
992
|
(0, import_vue2.h)("h2", { style: styles.subtitle }, t("templates.editor.history")),
|
|
882
993
|
(0, import_vue2.h)("ul", { style: styles.list }, revisions.value.map(renderRevision))
|
|
@@ -890,13 +1001,15 @@ var TemplateEditorScreen = (0, import_vue2.defineComponent)({
|
|
|
890
1001
|
var import_client3 = require("@fonderie/client");
|
|
891
1002
|
var import_vue_courier_admin3 = require("@fonderie/vue-courier-admin");
|
|
892
1003
|
var import_vue3 = require("vue");
|
|
1004
|
+
var MONO = 'var(--fonderie-mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace)';
|
|
893
1005
|
var builtIn = {
|
|
894
1006
|
fontSize: "11px",
|
|
895
1007
|
fontWeight: 500,
|
|
896
1008
|
padding: "1px 7px",
|
|
897
1009
|
borderRadius: "999px",
|
|
898
1010
|
border: "1px solid var(--fonderie-border,#e0e0e0)",
|
|
899
|
-
color: "var(--fonderie-text-muted,#5c5c5c)"
|
|
1011
|
+
color: "var(--fonderie-text-muted,#5c5c5c)",
|
|
1012
|
+
flexShrink: 0
|
|
900
1013
|
};
|
|
901
1014
|
var chip = {
|
|
902
1015
|
height: "24px",
|
|
@@ -907,23 +1020,42 @@ var chip = {
|
|
|
907
1020
|
background: "var(--fonderie-surface,#fff)",
|
|
908
1021
|
color: "var(--fonderie-text,#171717)",
|
|
909
1022
|
fontSize: "12px",
|
|
910
|
-
fontFamily:
|
|
1023
|
+
fontFamily: MONO,
|
|
911
1024
|
cursor: "pointer"
|
|
912
1025
|
};
|
|
913
|
-
var
|
|
1026
|
+
var chipBuiltIn = {
|
|
1027
|
+
borderStyle: "dashed",
|
|
1028
|
+
background: "transparent",
|
|
1029
|
+
color: "var(--fonderie-text-muted,#5c5c5c)"
|
|
1030
|
+
};
|
|
1031
|
+
var chipOff = { opacity: 0.5, textDecoration: "line-through" };
|
|
914
1032
|
var row = {
|
|
915
1033
|
...styles.row,
|
|
916
|
-
display: "
|
|
1034
|
+
display: "grid",
|
|
1035
|
+
gridTemplateColumns: "minmax(0, 1fr) minmax(180px, 280px) 88px",
|
|
917
1036
|
alignItems: "center",
|
|
918
|
-
gap: "
|
|
1037
|
+
gap: "16px",
|
|
919
1038
|
paddingRight: "16px"
|
|
920
1039
|
};
|
|
921
|
-
var rowButton = {
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
justifyContent: "flex-
|
|
926
|
-
gap: "
|
|
1040
|
+
var rowButton = {
|
|
1041
|
+
...styles.rowButton,
|
|
1042
|
+
width: "auto",
|
|
1043
|
+
minWidth: "0",
|
|
1044
|
+
justifyContent: "flex-start",
|
|
1045
|
+
gap: "12px"
|
|
1046
|
+
};
|
|
1047
|
+
var typeName = {
|
|
1048
|
+
...styles.type,
|
|
1049
|
+
flex: "none",
|
|
1050
|
+
overflow: "hidden",
|
|
1051
|
+
textOverflow: "ellipsis",
|
|
1052
|
+
whiteSpace: "nowrap"
|
|
1053
|
+
};
|
|
1054
|
+
var chips = { display: "flex", flexWrap: "wrap", gap: "6px" };
|
|
1055
|
+
var legend = {
|
|
1056
|
+
fontSize: "12.5px",
|
|
1057
|
+
color: "var(--fonderie-text-muted,#5c5c5c)",
|
|
1058
|
+
margin: "10px 2px 0"
|
|
927
1059
|
};
|
|
928
1060
|
var newButton = {
|
|
929
1061
|
display: "inline-flex",
|
|
@@ -951,90 +1083,97 @@ var TemplateListScreen = (0, import_vue3.defineComponent)({
|
|
|
951
1083
|
},
|
|
952
1084
|
emits: {
|
|
953
1085
|
/**
|
|
954
|
-
*
|
|
955
|
-
*
|
|
1086
|
+
* One row per email — built-in ones included, even when nobody saved a
|
|
1087
|
+
* copy. The row opens the default version; a language chip that language.
|
|
956
1088
|
*/
|
|
957
1089
|
"select-template": (_template) => true,
|
|
958
1090
|
/** Receives the locales in use, to suggest. */
|
|
959
1091
|
"create-template": (_context) => true
|
|
960
1092
|
},
|
|
961
1093
|
setup(props, { emit }) {
|
|
962
|
-
const {
|
|
1094
|
+
const { catalog, isLoading, error } = (0, import_vue_courier_admin3.useTemplateCatalog)(props.client);
|
|
963
1095
|
const t = (key, params) => (0, import_client3.createAdminT)(props.locale)(key, params);
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
])
|
|
981
|
-
]
|
|
982
|
-
),
|
|
983
|
-
// Siblings of the row button, not inside it: a button cannot hold buttons.
|
|
1096
|
+
const defaultLocale = () => catalog.value?.defaultLocale ?? "en-US";
|
|
1097
|
+
function renderRow(email) {
|
|
1098
|
+
const languages = (0, import_client3.templateLanguages)(email, defaultLocale());
|
|
1099
|
+
const primary = languages.find((l) => l.locale === null) ?? languages[0];
|
|
1100
|
+
const open = (l) => emit("select-template", {
|
|
1101
|
+
type: email.type,
|
|
1102
|
+
locale: l?.locale ?? null,
|
|
1103
|
+
system: email.system
|
|
1104
|
+
});
|
|
1105
|
+
return (0, import_vue3.h)("li", { key: email.type, style: row }, [
|
|
1106
|
+
(0, import_vue3.h)("button", { type: "button", style: rowButton, onClick: () => open(primary) }, [
|
|
1107
|
+
(0, import_vue3.h)("span", { style: typeName }, email.type),
|
|
1108
|
+
email.system ? (0, import_vue3.h)("span", { style: builtIn }, t("templates.builtInBadge")) : null
|
|
1109
|
+
]),
|
|
1110
|
+
// Siblings of the row button: a button cannot hold buttons. Each chip
|
|
1111
|
+
// names its email and language for screen readers.
|
|
984
1112
|
(0, import_vue3.h)(
|
|
985
1113
|
"span",
|
|
986
1114
|
{ style: chips },
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
return (0, import_vue3.h)(
|
|
1115
|
+
languages.map(
|
|
1116
|
+
(l) => (0, import_vue3.h)(
|
|
990
1117
|
"button",
|
|
991
1118
|
{
|
|
992
|
-
key:
|
|
1119
|
+
key: l.label,
|
|
993
1120
|
type: "button",
|
|
994
|
-
style:
|
|
995
|
-
"aria-label": t("templates.list.openLocale", { type:
|
|
996
|
-
title:
|
|
997
|
-
onClick: () =>
|
|
1121
|
+
style: { ...chip, ...l.saved ? {} : chipBuiltIn, ...l.active ? {} : chipOff },
|
|
1122
|
+
"aria-label": t("templates.list.openLocale", { type: email.type, locale: l.label }),
|
|
1123
|
+
title: l.active ? void 0 : t("common.status.inactive"),
|
|
1124
|
+
onClick: () => open(l)
|
|
998
1125
|
},
|
|
999
|
-
|
|
1000
|
-
)
|
|
1001
|
-
|
|
1002
|
-
)
|
|
1126
|
+
l.label
|
|
1127
|
+
)
|
|
1128
|
+
)
|
|
1129
|
+
),
|
|
1130
|
+
(0, import_vue3.h)("span", { style: primary?.active === false ? styles.inactive : styles.active }, [
|
|
1131
|
+
(0, import_vue3.h)("span", { style: styles.dot }),
|
|
1132
|
+
primary?.active === false ? t("common.status.inactive") : t("common.status.active")
|
|
1133
|
+
])
|
|
1003
1134
|
]);
|
|
1004
1135
|
}
|
|
1005
|
-
return () =>
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
"
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1136
|
+
return () => {
|
|
1137
|
+
const emails = catalog.value?.emails ?? [];
|
|
1138
|
+
return (0, import_vue3.h)("div", { style: styles.listContainer }, [
|
|
1139
|
+
(0, import_vue3.h)(
|
|
1140
|
+
"div",
|
|
1141
|
+
{
|
|
1142
|
+
style: {
|
|
1143
|
+
display: "flex",
|
|
1144
|
+
alignItems: "center",
|
|
1145
|
+
justifyContent: "space-between",
|
|
1146
|
+
gap: "16px"
|
|
1147
|
+
}
|
|
1148
|
+
},
|
|
1149
|
+
[
|
|
1150
|
+
(0, import_vue3.h)("h1", { style: styles.listTitle }, t("templates.list.title")),
|
|
1151
|
+
props.allowCreate ? (0, import_vue3.h)(
|
|
1152
|
+
"button",
|
|
1153
|
+
{
|
|
1154
|
+
type: "button",
|
|
1155
|
+
style: newButton,
|
|
1156
|
+
onClick: () => emit("create-template", {
|
|
1157
|
+
locales: [
|
|
1158
|
+
...new Set(
|
|
1159
|
+
emails.flatMap(
|
|
1160
|
+
(e) => (0, import_client3.templateLanguages)(e, defaultLocale()).filter((l) => l.locale !== null).map((l) => l.label)
|
|
1161
|
+
)
|
|
1162
|
+
)
|
|
1163
|
+
].sort()
|
|
1164
|
+
})
|
|
1165
|
+
},
|
|
1166
|
+
t("templates.list.newTemplate")
|
|
1167
|
+
) : null
|
|
1168
|
+
]
|
|
1169
|
+
),
|
|
1170
|
+
(0, import_vue3.h)("p", { style: styles.hint }, t("templates.list.hint")),
|
|
1171
|
+
isLoading.value ? (0, import_vue3.h)("p", { style: styles.status }, t("templates.list.loading")) : error.value ? (0, import_vue3.h)("p", { style: styles.error, role: "alert" }, error.value.explanation) : [
|
|
1172
|
+
(0, import_vue3.h)("ul", { style: styles.list }, emails.map(renderRow)),
|
|
1173
|
+
(0, import_vue3.h)("p", { style: legend }, t("templates.list.legend"))
|
|
1033
1174
|
]
|
|
1034
|
-
)
|
|
1035
|
-
|
|
1036
|
-
isLoading.value ? (0, import_vue3.h)("p", { style: styles.status }, t("templates.list.loading")) : error.value ? (0, import_vue3.h)("p", { style: styles.error, role: "alert" }, error.value.explanation) : (0, import_vue3.h)("ul", { style: styles.list }, (0, import_client3.groupTemplatesByType)(templates.value).map(renderRow))
|
|
1037
|
-
]);
|
|
1175
|
+
]);
|
|
1176
|
+
};
|
|
1038
1177
|
}
|
|
1039
1178
|
});
|
|
1040
1179
|
// Annotate the CommonJS export names for ESM import in node:
|