@fonderie/react-admin-screens 1.5.0 → 1.6.1
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 +567 -472
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -16
- package/dist/index.d.ts +31 -16
- package/dist/index.js +595 -469
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
// src/screens/AdminShell.tsx
|
|
2
|
+
import {
|
|
3
|
+
createAdminT as createAdminT16
|
|
4
|
+
} from "@fonderie/client";
|
|
2
5
|
import { ConfigEditorScreen, ConfigListScreen } from "@fonderie/react-config-admin-screens";
|
|
3
6
|
import {
|
|
4
7
|
TemplateCreateScreen,
|
|
@@ -556,11 +559,12 @@ function Empty({
|
|
|
556
559
|
function RefreshButton({
|
|
557
560
|
onClick,
|
|
558
561
|
busy,
|
|
559
|
-
label = "Refresh"
|
|
562
|
+
label = "Refresh",
|
|
563
|
+
busyLabel = "Working\u2026"
|
|
560
564
|
}) {
|
|
561
565
|
return /* @__PURE__ */ jsxs("button", { type: "button", style: styles.button, onClick, disabled: busy, children: [
|
|
562
566
|
/* @__PURE__ */ jsx(Icon, { name: "refresh", size: 14 }),
|
|
563
|
-
busy ?
|
|
567
|
+
busy ? busyLabel : label
|
|
564
568
|
] });
|
|
565
569
|
}
|
|
566
570
|
function MethodChip({ method }) {
|
|
@@ -587,9 +591,14 @@ function MethodChip({ method }) {
|
|
|
587
591
|
}
|
|
588
592
|
|
|
589
593
|
// src/screens/AdminLogScreen.tsx
|
|
594
|
+
import {
|
|
595
|
+
createAdminT,
|
|
596
|
+
formatAdminDate
|
|
597
|
+
} from "@fonderie/client";
|
|
590
598
|
import { useAdminLog } from "@fonderie/react-admin";
|
|
591
599
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
592
|
-
function AdminLogScreen({ client, pageSize = 50 }) {
|
|
600
|
+
function AdminLogScreen({ client, pageSize = 50, locale }) {
|
|
601
|
+
const t2 = createAdminT(locale);
|
|
593
602
|
const { entries, hasMore, isLoading, error, refresh, loadMore } = useAdminLog(client, {
|
|
594
603
|
limit: pageSize
|
|
595
604
|
});
|
|
@@ -597,22 +606,30 @@ function AdminLogScreen({ client, pageSize = 50 }) {
|
|
|
597
606
|
/* @__PURE__ */ jsx2(
|
|
598
607
|
PageHeader,
|
|
599
608
|
{
|
|
600
|
-
title: "
|
|
601
|
-
lead: "
|
|
602
|
-
actions: /* @__PURE__ */ jsx2(
|
|
609
|
+
title: t2("log.title"),
|
|
610
|
+
lead: t2("log.lead"),
|
|
611
|
+
actions: /* @__PURE__ */ jsx2(
|
|
612
|
+
RefreshButton,
|
|
613
|
+
{
|
|
614
|
+
onClick: () => void refresh(),
|
|
615
|
+
busy: isLoading,
|
|
616
|
+
label: t2("common.refresh"),
|
|
617
|
+
busyLabel: t2("common.working")
|
|
618
|
+
}
|
|
619
|
+
)
|
|
603
620
|
}
|
|
604
621
|
),
|
|
605
|
-
error ? /* @__PURE__ */ jsx2("p", { style: styles.error, role: "alert", children: error.status === 404 ? "
|
|
622
|
+
error ? /* @__PURE__ */ jsx2("p", { style: styles.error, role: "alert", children: error.status === 404 ? t2("log.off") : error.explanation }) : entries.length === 0 && !isLoading ? /* @__PURE__ */ jsx2(Empty, { icon: "log", title: t2("log.empty") }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
606
623
|
/* @__PURE__ */ jsxs2("table", { style: styles.table, children: [
|
|
607
624
|
/* @__PURE__ */ jsx2("thead", { children: /* @__PURE__ */ jsxs2("tr", { children: [
|
|
608
|
-
/* @__PURE__ */ jsx2("th", { style: styles.th, children: "
|
|
609
|
-
/* @__PURE__ */ jsx2("th", { style: styles.th, children: "
|
|
610
|
-
/* @__PURE__ */ jsx2("th", { style: styles.th, children: "
|
|
611
|
-
/* @__PURE__ */ jsx2("th", { style: styles.th, children: "
|
|
612
|
-
/* @__PURE__ */ jsx2("th", { style: styles.th, children: "
|
|
625
|
+
/* @__PURE__ */ jsx2("th", { style: styles.th, children: t2("log.colWhen") }),
|
|
626
|
+
/* @__PURE__ */ jsx2("th", { style: styles.th, children: t2("log.colActor") }),
|
|
627
|
+
/* @__PURE__ */ jsx2("th", { style: styles.th, children: t2("log.colRequest") }),
|
|
628
|
+
/* @__PURE__ */ jsx2("th", { style: styles.th, children: t2("log.colStatus") }),
|
|
629
|
+
/* @__PURE__ */ jsx2("th", { style: styles.th, children: t2("log.colModule") })
|
|
613
630
|
] }) }),
|
|
614
631
|
/* @__PURE__ */ jsx2("tbody", { children: entries.map((e) => /* @__PURE__ */ jsxs2("tr", { children: [
|
|
615
|
-
/* @__PURE__ */ jsx2("td", { style: { ...styles.td, ...styles.muted, whiteSpace: "nowrap" }, children:
|
|
632
|
+
/* @__PURE__ */ jsx2("td", { style: { ...styles.td, ...styles.muted, whiteSpace: "nowrap" }, children: formatAdminDate(e.at, locale, "datetime") }),
|
|
616
633
|
/* @__PURE__ */ jsx2("td", { style: styles.td, children: e.actor }),
|
|
617
634
|
/* @__PURE__ */ jsxs2("td", { style: styles.td, children: [
|
|
618
635
|
/* @__PURE__ */ jsx2(MethodChip, { method: e.method }),
|
|
@@ -630,14 +647,14 @@ function AdminLogScreen({ client, pageSize = 50 }) {
|
|
|
630
647
|
/* @__PURE__ */ jsx2("td", { style: { ...styles.td, ...styles.muted }, children: e.module })
|
|
631
648
|
] }, e.id)) })
|
|
632
649
|
] }),
|
|
633
|
-
isLoading ? /* @__PURE__ */ jsx2("p", { style: styles.status, children: "
|
|
650
|
+
isLoading ? /* @__PURE__ */ jsx2("p", { style: styles.status, children: t2("common.loading") }) : null,
|
|
634
651
|
hasMore && !isLoading ? /* @__PURE__ */ jsx2(
|
|
635
652
|
"button",
|
|
636
653
|
{
|
|
637
654
|
type: "button",
|
|
638
655
|
style: { ...styles.button, marginTop: 12 },
|
|
639
656
|
onClick: () => void loadMore(),
|
|
640
|
-
children: "
|
|
657
|
+
children: t2("common.loadMore")
|
|
641
658
|
}
|
|
642
659
|
) : null
|
|
643
660
|
] })
|
|
@@ -645,9 +662,14 @@ function AdminLogScreen({ client, pageSize = 50 }) {
|
|
|
645
662
|
}
|
|
646
663
|
|
|
647
664
|
// src/screens/AttentionScreen.tsx
|
|
665
|
+
import {
|
|
666
|
+
createAdminT as createAdminT2,
|
|
667
|
+
formatAdminDate as formatAdminDate2
|
|
668
|
+
} from "@fonderie/client";
|
|
648
669
|
import { useAttention, useManifest } from "@fonderie/react-admin";
|
|
649
670
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
650
|
-
function AttentionScreen({ client }) {
|
|
671
|
+
function AttentionScreen({ client, locale }) {
|
|
672
|
+
const t2 = createAdminT2(locale);
|
|
651
673
|
const { attention, isLoading, error, refresh } = useAttention(client);
|
|
652
674
|
const { manifest } = useManifest(client);
|
|
653
675
|
const errors = attention?.items.filter((i) => i.severity === "error") ?? [];
|
|
@@ -658,9 +680,19 @@ function AttentionScreen({ client }) {
|
|
|
658
680
|
/* @__PURE__ */ jsx3(
|
|
659
681
|
PageHeader,
|
|
660
682
|
{
|
|
661
|
-
title: "
|
|
662
|
-
lead: attention ?
|
|
663
|
-
|
|
683
|
+
title: t2("attention.title"),
|
|
684
|
+
lead: attention ? t2("attention.leadChecked", {
|
|
685
|
+
time: formatAdminDate2(attention.generatedAt, locale, "time")
|
|
686
|
+
}) : t2("attention.lead"),
|
|
687
|
+
actions: /* @__PURE__ */ jsx3(
|
|
688
|
+
RefreshButton,
|
|
689
|
+
{
|
|
690
|
+
onClick: () => void refresh(),
|
|
691
|
+
busy: isLoading,
|
|
692
|
+
label: t2("common.refresh"),
|
|
693
|
+
busyLabel: t2("common.working")
|
|
694
|
+
}
|
|
695
|
+
)
|
|
664
696
|
}
|
|
665
697
|
),
|
|
666
698
|
error ? /* @__PURE__ */ jsx3("p", { style: styles.error, role: "alert", children: error.explanation }) : null,
|
|
@@ -668,44 +700,42 @@ function AttentionScreen({ client }) {
|
|
|
668
700
|
/* @__PURE__ */ jsx3(
|
|
669
701
|
Stat,
|
|
670
702
|
{
|
|
671
|
-
label: "
|
|
703
|
+
label: t2("attention.needsAction"),
|
|
672
704
|
value: attention ? errors.length : "\u2014",
|
|
673
705
|
tone: errors.length ? "bad" : attention ? "ok" : void 0,
|
|
674
|
-
hint: "
|
|
706
|
+
hint: t2("attention.needsActionHint")
|
|
675
707
|
}
|
|
676
708
|
),
|
|
677
709
|
/* @__PURE__ */ jsx3(
|
|
678
710
|
Stat,
|
|
679
711
|
{
|
|
680
|
-
label: "
|
|
712
|
+
label: t2("attention.advice"),
|
|
681
713
|
value: attention ? advice.length : "\u2014",
|
|
682
714
|
tone: advice.length ? "warn" : void 0,
|
|
683
|
-
hint: "
|
|
715
|
+
hint: t2("attention.adviceHint")
|
|
684
716
|
}
|
|
685
717
|
),
|
|
686
718
|
/* @__PURE__ */ jsx3(
|
|
687
719
|
Stat,
|
|
688
720
|
{
|
|
689
|
-
label: "
|
|
721
|
+
label: t2("attention.modulesReady"),
|
|
690
722
|
value: manifest ? `${ready}/${total}` : "\u2014",
|
|
691
723
|
tone: manifest && ready < total ? "warn" : manifest ? "ok" : void 0,
|
|
692
|
-
hint: manifest ?
|
|
724
|
+
hint: manifest ? t2("attention.modulesReadyHint", { version: manifest.admin.version }) : void 0
|
|
693
725
|
}
|
|
694
726
|
),
|
|
695
727
|
/* @__PURE__ */ jsx3(
|
|
696
728
|
Stat,
|
|
697
729
|
{
|
|
698
|
-
label: "
|
|
730
|
+
label: t2("attention.routes"),
|
|
699
731
|
value: manifest ? manifest.routes.length : "\u2014",
|
|
700
732
|
hint: manifest ? manifest.env : void 0
|
|
701
733
|
}
|
|
702
734
|
)
|
|
703
735
|
] }),
|
|
704
|
-
isLoading && !attention ? /* @__PURE__ */ jsx3("p", { style: styles.status, children: "
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
"."
|
|
708
|
-
] }) : /* @__PURE__ */ jsx3("ul", { style: styles.list, children: [...errors, ...advice].map((item) => /* @__PURE__ */ jsxs3(
|
|
736
|
+
isLoading && !attention ? /* @__PURE__ */ jsx3("p", { style: styles.status, children: t2("attention.running") }) : attention && attention.items.length === 0 ? /* @__PURE__ */ jsx3(Empty, { title: t2("attention.emptyTitle"), children: t2("attention.emptyBody", {
|
|
737
|
+
time: formatAdminDate2(attention.generatedAt, locale, "datetime")
|
|
738
|
+
}) }) : /* @__PURE__ */ jsx3("ul", { style: styles.list, children: [...errors, ...advice].map((item) => /* @__PURE__ */ jsxs3(
|
|
709
739
|
"li",
|
|
710
740
|
{
|
|
711
741
|
style: { ...styles.row, display: "flex", gap: 12, alignItems: "flex-start" },
|
|
@@ -733,7 +763,7 @@ function AttentionScreen({ client }) {
|
|
|
733
763
|
marginBottom: 2
|
|
734
764
|
},
|
|
735
765
|
children: [
|
|
736
|
-
/* @__PURE__ */ jsx3(Pill, { tone: item.severity === "error" ? "bad" : "warn", children: item.severity === "error" ? "error" : "advice" }),
|
|
766
|
+
/* @__PURE__ */ jsx3(Pill, { tone: item.severity === "error" ? "bad" : "warn", children: item.severity === "error" ? t2("common.status.error") : t2("common.status.advice") }),
|
|
737
767
|
/* @__PURE__ */ jsx3("span", { style: styles.mono, children: item.source })
|
|
738
768
|
]
|
|
739
769
|
}
|
|
@@ -748,23 +778,25 @@ function AttentionScreen({ client }) {
|
|
|
748
778
|
}
|
|
749
779
|
|
|
750
780
|
// src/screens/EnvironmentScreen.tsx
|
|
781
|
+
import { createAdminT as createAdminT3 } from "@fonderie/client";
|
|
751
782
|
import { useAdminEnvironment } from "@fonderie/react-admin";
|
|
752
783
|
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
753
|
-
function EnvironmentScreen({ client }) {
|
|
784
|
+
function EnvironmentScreen({ client, locale }) {
|
|
785
|
+
const t2 = createAdminT3(locale);
|
|
754
786
|
const { report, isLoading, error } = useAdminEnvironment(client);
|
|
755
787
|
const missing = report?.env.filter((e) => !e.set).length ?? 0;
|
|
756
788
|
return /* @__PURE__ */ jsxs4("div", { style: styles.container, children: [
|
|
757
789
|
/* @__PURE__ */ jsx4(
|
|
758
790
|
PageHeader,
|
|
759
791
|
{
|
|
760
|
-
title: "
|
|
761
|
-
lead: "
|
|
762
|
-
actions: report && report.env.length > 0 ? /* @__PURE__ */ jsx4(Pill, { tone: missing ? "bad" : "ok", children: missing ?
|
|
792
|
+
title: t2("environment.title"),
|
|
793
|
+
lead: t2("environment.lead"),
|
|
794
|
+
actions: report && report.env.length > 0 ? /* @__PURE__ */ jsx4(Pill, { tone: missing ? "bad" : "ok", children: missing ? t2("environment.missingCount", { n: missing }) : t2("environment.allSet") }) : null
|
|
763
795
|
}
|
|
764
796
|
),
|
|
765
|
-
isLoading ? /* @__PURE__ */ jsx4("p", { style: styles.status, children: "
|
|
766
|
-
/* @__PURE__ */ jsx4("h2", { style: { ...styles.subtitle, marginTop: 0 }, children: "
|
|
767
|
-
report.env.length === 0 ? /* @__PURE__ */ jsx4("p", { style: styles.muted, children: "
|
|
797
|
+
isLoading ? /* @__PURE__ */ jsx4("p", { style: styles.status, children: t2("common.loading") }) : error ? /* @__PURE__ */ jsx4("p", { style: styles.error, role: "alert", children: error.explanation }) : report ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
798
|
+
/* @__PURE__ */ jsx4("h2", { style: { ...styles.subtitle, marginTop: 0 }, children: t2("environment.variables") }),
|
|
799
|
+
report.env.length === 0 ? /* @__PURE__ */ jsx4("p", { style: styles.muted, children: t2("environment.noVariables") }) : /* @__PURE__ */ jsx4(
|
|
768
800
|
"div",
|
|
769
801
|
{
|
|
770
802
|
style: {
|
|
@@ -785,14 +817,14 @@ function EnvironmentScreen({ client }) {
|
|
|
785
817
|
},
|
|
786
818
|
children: [
|
|
787
819
|
/* @__PURE__ */ jsx4("span", { style: { ...styles.mono, wordBreak: "break-all" }, children: e.name }),
|
|
788
|
-
/* @__PURE__ */ jsx4(Pill, { tone: e.set ? "ok" : "bad", children: e.set ? "set" : "missing" })
|
|
820
|
+
/* @__PURE__ */ jsx4(Pill, { tone: e.set ? "ok" : "bad", children: e.set ? t2("common.status.set") : t2("common.status.missing") })
|
|
789
821
|
]
|
|
790
822
|
},
|
|
791
823
|
e.name
|
|
792
824
|
))
|
|
793
825
|
}
|
|
794
826
|
),
|
|
795
|
-
/* @__PURE__ */ jsx4("h2", { style: styles.subtitle, children: "
|
|
827
|
+
/* @__PURE__ */ jsx4("h2", { style: styles.subtitle, children: t2("environment.moduleReadiness") }),
|
|
796
828
|
/* @__PURE__ */ jsx4("ul", { style: styles.list, children: report.modules.map((m) => /* @__PURE__ */ jsxs4("li", { style: styles.row, children: [
|
|
797
829
|
/* @__PURE__ */ jsxs4(
|
|
798
830
|
"div",
|
|
@@ -809,7 +841,7 @@ function EnvironmentScreen({ client }) {
|
|
|
809
841
|
Pill,
|
|
810
842
|
{
|
|
811
843
|
tone: m.problems.length === 0 ? "ok" : m.problems.some((p) => p.severity === "error") ? "bad" : "warn",
|
|
812
|
-
children: m.problems.length === 0 ? "ready" :
|
|
844
|
+
children: m.problems.length === 0 ? t2("common.status.ready") : m.problems.length === 1 ? t2("environment.problemOne") : t2("environment.problemMany", { n: m.problems.length })
|
|
813
845
|
}
|
|
814
846
|
)
|
|
815
847
|
]
|
|
@@ -833,34 +865,44 @@ function EnvironmentScreen({ client }) {
|
|
|
833
865
|
}
|
|
834
866
|
|
|
835
867
|
// src/screens/DoctorScreen.tsx
|
|
868
|
+
import { createAdminT as createAdminT4 } from "@fonderie/client";
|
|
836
869
|
import { useDoctor } from "@fonderie/react-admin";
|
|
837
870
|
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
838
|
-
function DoctorScreen({ client }) {
|
|
871
|
+
function DoctorScreen({ client, locale }) {
|
|
872
|
+
const t2 = createAdminT4(locale);
|
|
839
873
|
const { report, isLoading, error, refresh } = useDoctor(client);
|
|
840
874
|
return /* @__PURE__ */ jsxs5("div", { style: styles.container, children: [
|
|
841
875
|
/* @__PURE__ */ jsx5(
|
|
842
876
|
PageHeader,
|
|
843
877
|
{
|
|
844
|
-
title: "
|
|
845
|
-
lead: "
|
|
878
|
+
title: t2("doctor.title"),
|
|
879
|
+
lead: t2("doctor.lead"),
|
|
846
880
|
actions: /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
847
|
-
report && !isLoading ? /* @__PURE__ */ jsx5(Pill, { tone: report.ok ? "ok" : "bad", children: report.ok ? "
|
|
848
|
-
/* @__PURE__ */ jsx5(
|
|
881
|
+
report && !isLoading ? /* @__PURE__ */ jsx5(Pill, { tone: report.ok ? "ok" : "bad", children: report.ok ? t2("doctor.allPass") : t2("doctor.oneFailed") }) : null,
|
|
882
|
+
/* @__PURE__ */ jsx5(
|
|
883
|
+
RefreshButton,
|
|
884
|
+
{
|
|
885
|
+
onClick: () => void refresh(),
|
|
886
|
+
busy: isLoading,
|
|
887
|
+
label: t2("doctor.runAgain"),
|
|
888
|
+
busyLabel: t2("common.working")
|
|
889
|
+
}
|
|
890
|
+
)
|
|
849
891
|
] })
|
|
850
892
|
}
|
|
851
893
|
),
|
|
852
|
-
isLoading && !report ? /* @__PURE__ */ jsx5("p", { style: styles.status, children: "
|
|
894
|
+
isLoading && !report ? /* @__PURE__ */ jsx5("p", { style: styles.status, children: t2("doctor.running") }) : error ? /* @__PURE__ */ jsx5("p", { style: styles.error, role: "alert", children: error.explanation }) : /* @__PURE__ */ jsxs5("table", { style: styles.table, children: [
|
|
853
895
|
/* @__PURE__ */ jsx5("thead", { children: /* @__PURE__ */ jsxs5("tr", { children: [
|
|
854
|
-
/* @__PURE__ */ jsx5("th", { style: { ...styles.th, width: 110 }, children: "
|
|
855
|
-
/* @__PURE__ */ jsx5("th", { style: styles.th, children: "
|
|
856
|
-
/* @__PURE__ */ jsx5("th", { style: { ...styles.th, textAlign: "right", width: 90 }, children: "
|
|
896
|
+
/* @__PURE__ */ jsx5("th", { style: { ...styles.th, width: 110 }, children: t2("doctor.colResult") }),
|
|
897
|
+
/* @__PURE__ */ jsx5("th", { style: styles.th, children: t2("doctor.colCheck") }),
|
|
898
|
+
/* @__PURE__ */ jsx5("th", { style: { ...styles.th, textAlign: "right", width: 90 }, children: t2("doctor.colTime") })
|
|
857
899
|
] }) }),
|
|
858
900
|
/* @__PURE__ */ jsx5("tbody", { children: report?.checks.map((c) => /* @__PURE__ */ jsxs5("tr", { children: [
|
|
859
901
|
/* @__PURE__ */ jsx5("td", { style: styles.td, children: /* @__PURE__ */ jsx5(
|
|
860
902
|
Pill,
|
|
861
903
|
{
|
|
862
904
|
tone: c.skipped ? "neutral" : c.ok ? c.findings.length ? "warn" : "ok" : "bad",
|
|
863
|
-
children: c.skipped ? "skipped" : c.ok ? c.findings.length ? "advice" : "ok" : "failed"
|
|
905
|
+
children: c.skipped ? t2("common.status.skipped") : c.ok ? c.findings.length ? t2("common.status.advice") : t2("common.status.ok") : t2("common.status.failed")
|
|
864
906
|
}
|
|
865
907
|
) }),
|
|
866
908
|
/* @__PURE__ */ jsxs5("td", { style: styles.td, children: [
|
|
@@ -905,30 +947,37 @@ function DoctorScreen({ client }) {
|
|
|
905
947
|
}
|
|
906
948
|
|
|
907
949
|
// src/screens/ModulesScreen.tsx
|
|
950
|
+
import { createAdminT as createAdminT5 } from "@fonderie/client";
|
|
908
951
|
import { useManifest as useManifest2 } from "@fonderie/react-admin";
|
|
909
952
|
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
910
|
-
function ModulesScreen({ client }) {
|
|
953
|
+
function ModulesScreen({ client, locale }) {
|
|
954
|
+
const t2 = createAdminT5(locale);
|
|
911
955
|
const { manifest, isLoading, error } = useManifest2(client);
|
|
912
956
|
return /* @__PURE__ */ jsxs6("div", { style: styles.container, children: [
|
|
913
957
|
/* @__PURE__ */ jsx6(
|
|
914
958
|
PageHeader,
|
|
915
959
|
{
|
|
916
|
-
title: "
|
|
917
|
-
lead: manifest ?
|
|
960
|
+
title: t2("modules.title"),
|
|
961
|
+
lead: manifest ? t2("modules.leadSummary", {
|
|
962
|
+
env: manifest.env,
|
|
963
|
+
version: manifest.admin.version,
|
|
964
|
+
log: manifest.admin.log ? t2("modules.logOn") : t2("modules.logOff"),
|
|
965
|
+
routes: manifest.routes.length
|
|
966
|
+
}) : t2("modules.lead")
|
|
918
967
|
}
|
|
919
968
|
),
|
|
920
|
-
isLoading ? /* @__PURE__ */ jsx6("p", { style: styles.status, children: "
|
|
969
|
+
isLoading ? /* @__PURE__ */ jsx6("p", { style: styles.status, children: t2("common.loading") }) : error ? /* @__PURE__ */ jsx6("p", { style: styles.error, role: "alert", children: error.explanation }) : manifest ? /* @__PURE__ */ jsxs6("table", { style: styles.table, children: [
|
|
921
970
|
/* @__PURE__ */ jsx6("thead", { children: /* @__PURE__ */ jsxs6("tr", { children: [
|
|
922
|
-
/* @__PURE__ */ jsx6("th", { style: styles.th, children: "
|
|
923
|
-
/* @__PURE__ */ jsx6("th", { style: styles.th, children: "
|
|
924
|
-
/* @__PURE__ */ jsx6("th", { style: styles.th, children: "
|
|
925
|
-
/* @__PURE__ */ jsx6("th", { style: styles.th, children: "
|
|
971
|
+
/* @__PURE__ */ jsx6("th", { style: styles.th, children: t2("modules.colModule") }),
|
|
972
|
+
/* @__PURE__ */ jsx6("th", { style: styles.th, children: t2("modules.colVersion") }),
|
|
973
|
+
/* @__PURE__ */ jsx6("th", { style: styles.th, children: t2("modules.colReadiness") }),
|
|
974
|
+
/* @__PURE__ */ jsx6("th", { style: styles.th, children: t2("modules.colAdmin") })
|
|
926
975
|
] }) }),
|
|
927
976
|
/* @__PURE__ */ jsx6("tbody", { children: manifest.modules.map((m) => /* @__PURE__ */ jsxs6("tr", { children: [
|
|
928
977
|
/* @__PURE__ */ jsx6("td", { style: { ...styles.td, ...styles.mono, fontWeight: 600 }, children: m.name }),
|
|
929
|
-
/* @__PURE__ */ jsx6("td", { style: { ...styles.td, ...styles.mono }, children: m.version ?? /* @__PURE__ */ jsx6("span", { style: styles.muted, children: "
|
|
978
|
+
/* @__PURE__ */ jsx6("td", { style: { ...styles.td, ...styles.mono }, children: m.version ?? /* @__PURE__ */ jsx6("span", { style: styles.muted, children: t2("modules.notReported") }) }),
|
|
930
979
|
/* @__PURE__ */ jsxs6("td", { style: styles.td, children: [
|
|
931
|
-
/* @__PURE__ */ jsx6(Pill, { tone: m.readiness.ok ? "ok" : "bad", children: m.readiness.ok ? "ready" : "error" }),
|
|
980
|
+
/* @__PURE__ */ jsx6(Pill, { tone: m.readiness.ok ? "ok" : "bad", children: m.readiness.ok ? t2("common.status.ready") : t2("common.status.error") }),
|
|
932
981
|
m.readiness.problems.map((p) => /* @__PURE__ */ jsx6(
|
|
933
982
|
"div",
|
|
934
983
|
{
|
|
@@ -942,17 +991,19 @@ function ModulesScreen({ client }) {
|
|
|
942
991
|
p.message
|
|
943
992
|
))
|
|
944
993
|
] }),
|
|
945
|
-
/* @__PURE__ */ jsx6("td", { style: styles.td, children: m.describesAdmin ? /* @__PURE__ */ jsx6("span", { style: styles.badge, children: "
|
|
994
|
+
/* @__PURE__ */ jsx6("td", { style: styles.td, children: m.describesAdmin ? /* @__PURE__ */ jsx6("span", { style: styles.badge, children: t2("modules.describesAdmin") }) : /* @__PURE__ */ jsx6("span", { style: styles.muted, children: "\u2014" }) })
|
|
946
995
|
] }, m.name)) })
|
|
947
996
|
] }) : null
|
|
948
997
|
] });
|
|
949
998
|
}
|
|
950
999
|
|
|
951
1000
|
// src/screens/RoutesScreen.tsx
|
|
1001
|
+
import { createAdminT as createAdminT6 } from "@fonderie/client";
|
|
952
1002
|
import { useAdminRoutes } from "@fonderie/react-admin";
|
|
953
1003
|
import { useState } from "react";
|
|
954
1004
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
955
|
-
function RoutesScreen({ client }) {
|
|
1005
|
+
function RoutesScreen({ client, locale }) {
|
|
1006
|
+
const t2 = createAdminT6(locale);
|
|
956
1007
|
const { report, isLoading, error } = useAdminRoutes(client);
|
|
957
1008
|
const [q, setQ] = useState("");
|
|
958
1009
|
const needle = q.trim().toLowerCase();
|
|
@@ -963,27 +1014,27 @@ function RoutesScreen({ client }) {
|
|
|
963
1014
|
/* @__PURE__ */ jsx7(
|
|
964
1015
|
PageHeader,
|
|
965
1016
|
{
|
|
966
|
-
title: "
|
|
967
|
-
lead: report ?
|
|
1017
|
+
title: t2("routes.title"),
|
|
1018
|
+
lead: report ? t2("routes.leadCount", { n: report.routes.length }) : t2("routes.lead"),
|
|
968
1019
|
actions: /* @__PURE__ */ jsx7(
|
|
969
1020
|
"input",
|
|
970
1021
|
{
|
|
971
1022
|
type: "search",
|
|
972
1023
|
value: q,
|
|
973
1024
|
onChange: (e) => setQ(e.target.value),
|
|
974
|
-
placeholder: "
|
|
1025
|
+
placeholder: t2("routes.filterPlaceholder"),
|
|
975
1026
|
style: { ...styles.input, width: 280 },
|
|
976
|
-
"aria-label": "
|
|
1027
|
+
"aria-label": t2("routes.filterLabel")
|
|
977
1028
|
}
|
|
978
1029
|
)
|
|
979
1030
|
}
|
|
980
1031
|
),
|
|
981
|
-
isLoading ? /* @__PURE__ */ jsx7("p", { style: styles.status, children: "
|
|
1032
|
+
isLoading ? /* @__PURE__ */ jsx7("p", { style: styles.status, children: t2("common.loading") }) : error ? /* @__PURE__ */ jsx7("p", { style: styles.error, role: "alert", children: error.explanation }) : /* @__PURE__ */ jsxs7("table", { style: styles.table, children: [
|
|
982
1033
|
/* @__PURE__ */ jsx7("thead", { children: /* @__PURE__ */ jsxs7("tr", { children: [
|
|
983
|
-
/* @__PURE__ */ jsx7("th", { style: { ...styles.th, width: 80 }, children: "
|
|
984
|
-
/* @__PURE__ */ jsx7("th", { style: styles.th, children: "
|
|
985
|
-
/* @__PURE__ */ jsx7("th", { style: styles.th, children: "
|
|
986
|
-
/* @__PURE__ */ jsx7("th", { style: styles.th, children: "
|
|
1034
|
+
/* @__PURE__ */ jsx7("th", { style: { ...styles.th, width: 80 }, children: t2("routes.colMethod") }),
|
|
1035
|
+
/* @__PURE__ */ jsx7("th", { style: styles.th, children: t2("routes.colPath") }),
|
|
1036
|
+
/* @__PURE__ */ jsx7("th", { style: styles.th, children: t2("routes.colGuard") }),
|
|
1037
|
+
/* @__PURE__ */ jsx7("th", { style: styles.th, children: t2("routes.colModule") })
|
|
987
1038
|
] }) }),
|
|
988
1039
|
/* @__PURE__ */ jsxs7("tbody", { children: [
|
|
989
1040
|
routes.map((r) => /* @__PURE__ */ jsxs7("tr", { children: [
|
|
@@ -997,61 +1048,66 @@ function RoutesScreen({ client }) {
|
|
|
997
1048
|
children: r.guard
|
|
998
1049
|
}
|
|
999
1050
|
) }),
|
|
1000
|
-
/* @__PURE__ */ jsx7("td", { style: { ...styles.td, ...styles.muted }, children: r.module ?? "application" })
|
|
1051
|
+
/* @__PURE__ */ jsx7("td", { style: { ...styles.td, ...styles.muted }, children: r.module ?? t2("routes.application") })
|
|
1001
1052
|
] }, `${r.method} ${r.path}`)),
|
|
1002
|
-
routes.length === 0 ? /* @__PURE__ */ jsx7("tr", { children: /* @__PURE__ */
|
|
1003
|
-
"No route matches \u201C",
|
|
1004
|
-
q,
|
|
1005
|
-
"\u201D."
|
|
1006
|
-
] }) }) : null
|
|
1053
|
+
routes.length === 0 ? /* @__PURE__ */ jsx7("tr", { children: /* @__PURE__ */ jsx7("td", { style: { ...styles.td, ...styles.muted }, colSpan: 4, children: t2("routes.noMatch", { q }) }) }) : null
|
|
1007
1054
|
] })
|
|
1008
1055
|
] })
|
|
1009
1056
|
] });
|
|
1010
1057
|
}
|
|
1011
1058
|
|
|
1012
1059
|
// src/screens/MigrationsScreen.tsx
|
|
1060
|
+
import {
|
|
1061
|
+
createAdminT as createAdminT7
|
|
1062
|
+
} from "@fonderie/client";
|
|
1013
1063
|
import { useAdminMigrations } from "@fonderie/react-admin";
|
|
1014
1064
|
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1015
|
-
function why(m, everApplied) {
|
|
1065
|
+
function why(m, everApplied, t2) {
|
|
1016
1066
|
if (m.pending.length === 0) return null;
|
|
1017
|
-
if (m.blockedBy) return
|
|
1067
|
+
if (m.blockedBy) return t2("migrations.blockedBy", { module: m.blockedBy });
|
|
1018
1068
|
if (everApplied && m.pending.some((p) => p.impact === "destructive"))
|
|
1019
|
-
return "
|
|
1069
|
+
return t2("migrations.destructiveBlocked");
|
|
1020
1070
|
return null;
|
|
1021
1071
|
}
|
|
1022
|
-
function MigrationsScreen({ client }) {
|
|
1072
|
+
function MigrationsScreen({ client, locale }) {
|
|
1073
|
+
const t2 = createAdminT7(locale);
|
|
1023
1074
|
const { report, isLoading, error, refresh, apply } = useAdminMigrations(client);
|
|
1024
1075
|
const behind = report?.modules.filter((m) => m.pending.length > 0) ?? [];
|
|
1025
1076
|
return /* @__PURE__ */ jsxs8("div", { style: styles.container, children: [
|
|
1026
1077
|
/* @__PURE__ */ jsx8(
|
|
1027
1078
|
PageHeader,
|
|
1028
1079
|
{
|
|
1029
|
-
title: "
|
|
1030
|
-
lead: "
|
|
1031
|
-
actions: /* @__PURE__ */ jsx8(
|
|
1080
|
+
title: t2("migrations.title"),
|
|
1081
|
+
lead: t2("migrations.lead"),
|
|
1082
|
+
actions: /* @__PURE__ */ jsx8(
|
|
1083
|
+
RefreshButton,
|
|
1084
|
+
{
|
|
1085
|
+
onClick: () => void refresh(),
|
|
1086
|
+
busy: isLoading,
|
|
1087
|
+
label: t2("common.refresh"),
|
|
1088
|
+
busyLabel: t2("common.working")
|
|
1089
|
+
}
|
|
1090
|
+
)
|
|
1032
1091
|
}
|
|
1033
1092
|
),
|
|
1034
|
-
error ? /* @__PURE__ */ jsx8("p", { style: styles.error, role: "alert", children: error.status === 403 ? "
|
|
1035
|
-
report && !report.everApplied ? /* @__PURE__ */ jsx8("p", { style: styles.notice, children: "
|
|
1036
|
-
report && behind.length === 0 ? /* @__PURE__ */ jsx8(Empty, { icon: "migrations", title: "
|
|
1093
|
+
error ? /* @__PURE__ */ jsx8("p", { style: styles.error, role: "alert", children: error.status === 403 ? t2("migrations.needsWrite") : error.explanation }) : null,
|
|
1094
|
+
report && !report.everApplied ? /* @__PURE__ */ jsx8("p", { style: styles.notice, children: t2("migrations.firstInstall") }) : null,
|
|
1095
|
+
report && behind.length === 0 ? /* @__PURE__ */ jsx8(Empty, { icon: "migrations", title: t2("migrations.upToDate"), children: t2("migrations.noPending") }) : null,
|
|
1037
1096
|
behind.map((m) => {
|
|
1038
|
-
const blocked = why(m, report?.everApplied ?? false);
|
|
1097
|
+
const blocked = why(m, report?.everApplied ?? false, t2);
|
|
1039
1098
|
const files = m.pending.map((p) => p.file);
|
|
1040
1099
|
return /* @__PURE__ */ jsxs8("section", { style: { ...styles.card, marginBottom: 16 }, children: [
|
|
1041
1100
|
/* @__PURE__ */ jsxs8("h2", { style: { ...styles.subtitle, marginTop: 0 }, children: [
|
|
1042
1101
|
/* @__PURE__ */ jsx8("span", { style: styles.mono, children: m.name }),
|
|
1043
|
-
/* @__PURE__ */
|
|
1044
|
-
m.pending.length,
|
|
1045
|
-
" pending"
|
|
1046
|
-
] })
|
|
1102
|
+
/* @__PURE__ */ jsx8(Pill, { tone: "warn", children: t2("migrations.pendingCount", { n: m.pending.length }) })
|
|
1047
1103
|
] }),
|
|
1048
1104
|
/* @__PURE__ */ jsx8("ul", { style: { margin: "0 0 12px", paddingLeft: 18, lineHeight: 1.9 }, children: m.pending.map((p) => /* @__PURE__ */ jsxs8("li", { children: [
|
|
1049
1105
|
/* @__PURE__ */ jsx8("code", { style: styles.code, children: p.file }),
|
|
1050
1106
|
" ",
|
|
1051
|
-
p.impact === "destructive" ? /* @__PURE__ */ jsx8(Pill, { tone: "bad", children: "destructive" }) : /* @__PURE__ */ jsx8(Pill, { tone: "neutral", children: "additive" }),
|
|
1107
|
+
p.impact === "destructive" ? /* @__PURE__ */ jsx8(Pill, { tone: "bad", children: t2("migrations.destructive") }) : /* @__PURE__ */ jsx8(Pill, { tone: "neutral", children: t2("migrations.additive") }),
|
|
1052
1108
|
p.destructive.length > 0 ? /* @__PURE__ */ jsx8("ul", { children: p.destructive.map((s) => /* @__PURE__ */ jsx8("li", { children: /* @__PURE__ */ jsx8("code", { children: s.slice(0, 120) }) }, s)) }) : null
|
|
1053
1109
|
] }, p.file)) }),
|
|
1054
|
-
blocked ? /* @__PURE__ */ jsx8("p", { style: { ...styles.notice, marginBottom: 0 }, children: blocked }) : /* @__PURE__ */
|
|
1110
|
+
blocked ? /* @__PURE__ */ jsx8("p", { style: { ...styles.notice, marginBottom: 0 }, children: blocked }) : /* @__PURE__ */ jsx8(
|
|
1055
1111
|
"button",
|
|
1056
1112
|
{
|
|
1057
1113
|
type: "button",
|
|
@@ -1059,17 +1115,12 @@ function MigrationsScreen({ client }) {
|
|
|
1059
1115
|
disabled: isLoading || !m.appliable,
|
|
1060
1116
|
onClick: () => {
|
|
1061
1117
|
if (window.confirm(
|
|
1062
|
-
|
|
1118
|
+
t2("migrations.confirmApply", { n: m.pending.length, module: m.name })
|
|
1063
1119
|
))
|
|
1064
1120
|
void apply(m.name, files).catch(() => {
|
|
1065
1121
|
});
|
|
1066
1122
|
},
|
|
1067
|
-
children:
|
|
1068
|
-
"Apply ",
|
|
1069
|
-
m.pending.length,
|
|
1070
|
-
" migration",
|
|
1071
|
-
m.pending.length === 1 ? "" : "s"
|
|
1072
|
-
]
|
|
1123
|
+
children: m.pending.length === 1 ? t2("migrations.applyOne") : t2("migrations.applyMany", { n: m.pending.length })
|
|
1073
1124
|
}
|
|
1074
1125
|
)
|
|
1075
1126
|
] }, m.name);
|
|
@@ -1078,20 +1129,25 @@ function MigrationsScreen({ client }) {
|
|
|
1078
1129
|
}
|
|
1079
1130
|
|
|
1080
1131
|
// src/screens/OperatorsScreen.tsx
|
|
1132
|
+
import {
|
|
1133
|
+
createAdminT as createAdminT8,
|
|
1134
|
+
formatAdminDate as formatAdminDate3
|
|
1135
|
+
} from "@fonderie/client";
|
|
1081
1136
|
import { useAdminOperators } from "@fonderie/react-admin";
|
|
1082
1137
|
import { useState as useState2 } from "react";
|
|
1083
1138
|
import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1084
1139
|
var LEVELS = [
|
|
1085
|
-
{
|
|
1086
|
-
{
|
|
1087
|
-
{
|
|
1088
|
-
label: "Owner",
|
|
1089
|
-
scopes: ["read", "write", "secrets"],
|
|
1090
|
-
hint: "secrets, tokens and operators too"
|
|
1091
|
-
}
|
|
1140
|
+
{ id: "read", scopes: ["read"] },
|
|
1141
|
+
{ id: "editor", scopes: ["read", "write"] },
|
|
1142
|
+
{ id: "owner", scopes: ["read", "write", "secrets"] }
|
|
1092
1143
|
];
|
|
1093
|
-
var levelOf = (scopes) => scopes.includes("secrets") ? "
|
|
1094
|
-
function Minted({
|
|
1144
|
+
var levelOf = (scopes) => scopes.includes("secrets") ? "owner" : scopes.includes("write") ? "editor" : "read";
|
|
1145
|
+
function Minted({
|
|
1146
|
+
link,
|
|
1147
|
+
onClose,
|
|
1148
|
+
t: t2,
|
|
1149
|
+
locale
|
|
1150
|
+
}) {
|
|
1095
1151
|
const [copied, setCopied] = useState2(false);
|
|
1096
1152
|
const url = `${window.location.origin}${link.url}`;
|
|
1097
1153
|
return /* @__PURE__ */ jsxs9(
|
|
@@ -1103,15 +1159,9 @@ function Minted({ link, onClose }) {
|
|
|
1103
1159
|
borderColor: "color-mix(in srgb, var(--fonderie-accent,#00d294) 35%, transparent)"
|
|
1104
1160
|
},
|
|
1105
1161
|
children: [
|
|
1106
|
-
/* @__PURE__ */
|
|
1107
|
-
"Send this link to ",
|
|
1108
|
-
link.email,
|
|
1109
|
-
". It is shown once."
|
|
1110
|
-
] }),
|
|
1111
|
-
" It works once and expires",
|
|
1162
|
+
/* @__PURE__ */ jsx9("strong", { children: t2("operators.mintedTitle", { email: link.email }) }),
|
|
1112
1163
|
" ",
|
|
1113
|
-
|
|
1114
|
-
".",
|
|
1164
|
+
t2("operators.mintedBody", { date: formatAdminDate3(link.expiresAt, locale) }),
|
|
1115
1165
|
/* @__PURE__ */ jsxs9("div", { style: { display: "flex", gap: 8, marginTop: 8, alignItems: "center" }, children: [
|
|
1116
1166
|
/* @__PURE__ */ jsx9("code", { style: { ...styles.code, flex: 1, padding: "7px 10px", wordBreak: "break-all" }, children: url }),
|
|
1117
1167
|
/* @__PURE__ */ jsx9(
|
|
@@ -1123,32 +1173,36 @@ function Minted({ link, onClose }) {
|
|
|
1123
1173
|
void navigator.clipboard?.writeText(url);
|
|
1124
1174
|
setCopied(true);
|
|
1125
1175
|
},
|
|
1126
|
-
children: copied ? "
|
|
1176
|
+
children: copied ? t2("common.copied") : t2("common.copy")
|
|
1127
1177
|
}
|
|
1128
1178
|
),
|
|
1129
|
-
/* @__PURE__ */ jsx9(
|
|
1179
|
+
/* @__PURE__ */ jsx9(
|
|
1180
|
+
"button",
|
|
1181
|
+
{
|
|
1182
|
+
type: "button",
|
|
1183
|
+
style: styles.buttonGhost,
|
|
1184
|
+
onClick: onClose,
|
|
1185
|
+
"aria-label": t2("common.dismiss"),
|
|
1186
|
+
children: /* @__PURE__ */ jsx9(Icon, { name: "close", size: 14 })
|
|
1187
|
+
}
|
|
1188
|
+
)
|
|
1130
1189
|
] })
|
|
1131
1190
|
]
|
|
1132
1191
|
}
|
|
1133
1192
|
);
|
|
1134
1193
|
}
|
|
1135
|
-
function OperatorsScreen({ client, me }) {
|
|
1194
|
+
function OperatorsScreen({ client, me, locale }) {
|
|
1195
|
+
const t2 = createAdminT8(locale);
|
|
1136
1196
|
const { report, isLoading, error, invite, recover, update, revokeLink } = useAdminOperators(client);
|
|
1137
1197
|
const [email, setEmail] = useState2("");
|
|
1138
|
-
const [level, setLevel] = useState2("
|
|
1198
|
+
const [level, setLevel] = useState2("editor");
|
|
1139
1199
|
const [minted, setMinted] = useState2(null);
|
|
1140
|
-
const scopesFor = (
|
|
1141
|
-
const status = (o) => o.disabledAt ? /* @__PURE__ */ jsx9(Pill, { tone: "neutral", children: "disabled" }) : o.locked ? /* @__PURE__ */ jsx9(Pill, { tone: "warn", children: "locked" }) : !o.enrolled ? /* @__PURE__ */ jsx9(Pill, { tone: "warn", children: "
|
|
1200
|
+
const scopesFor = (id) => LEVELS.find((l) => l.id === id)?.scopes ?? ["read"];
|
|
1201
|
+
const status = (o) => o.disabledAt ? /* @__PURE__ */ jsx9(Pill, { tone: "neutral", children: t2("common.status.disabled") }) : o.locked ? /* @__PURE__ */ jsx9(Pill, { tone: "warn", children: t2("common.status.locked") }) : !o.enrolled ? /* @__PURE__ */ jsx9(Pill, { tone: "warn", children: t2("operators.settingUp") }) : /* @__PURE__ */ jsx9(Pill, { tone: "ok", children: t2("common.status.active") });
|
|
1142
1202
|
return /* @__PURE__ */ jsxs9("div", { style: styles.container, children: [
|
|
1143
|
-
/* @__PURE__ */ jsx9(
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
title: "Operators",
|
|
1147
|
-
lead: "The people who can sign in to this console. Each one uses a password and an authenticator app; there is no sign-up."
|
|
1148
|
-
}
|
|
1149
|
-
),
|
|
1150
|
-
error ? /* @__PURE__ */ jsx9("p", { style: styles.error, role: "alert", children: error.status === 403 && error.reason === "FORBIDDEN" ? "Managing operators needs the Owner level." : error.explanation }) : null,
|
|
1151
|
-
minted ? /* @__PURE__ */ jsx9(Minted, { link: minted, onClose: () => setMinted(null) }) : null,
|
|
1203
|
+
/* @__PURE__ */ jsx9(PageHeader, { title: t2("operators.title"), lead: t2("operators.lead") }),
|
|
1204
|
+
error ? /* @__PURE__ */ jsx9("p", { style: styles.error, role: "alert", children: error.status === 403 && error.reason === "FORBIDDEN" ? t2("operators.needsOwner") : error.explanation }) : null,
|
|
1205
|
+
minted ? /* @__PURE__ */ jsx9(Minted, { link: minted, onClose: () => setMinted(null), t: t2, locale }) : null,
|
|
1152
1206
|
/* @__PURE__ */ jsxs9(
|
|
1153
1207
|
"form",
|
|
1154
1208
|
{
|
|
@@ -1170,7 +1224,7 @@ function OperatorsScreen({ client, me }) {
|
|
|
1170
1224
|
},
|
|
1171
1225
|
children: [
|
|
1172
1226
|
/* @__PURE__ */ jsx9(Icon, { name: "users", size: 16 }),
|
|
1173
|
-
/* @__PURE__ */ jsx9("strong", { style: { fontSize: 13.5, marginRight: 4 }, children: "
|
|
1227
|
+
/* @__PURE__ */ jsx9("strong", { style: { fontSize: 13.5, marginRight: 4 }, children: t2("operators.invite") }),
|
|
1174
1228
|
/* @__PURE__ */ jsx9(
|
|
1175
1229
|
"input",
|
|
1176
1230
|
{
|
|
@@ -1178,9 +1232,9 @@ function OperatorsScreen({ client, me }) {
|
|
|
1178
1232
|
required: true,
|
|
1179
1233
|
value: email,
|
|
1180
1234
|
onChange: (e) => setEmail(e.target.value),
|
|
1181
|
-
placeholder: "
|
|
1235
|
+
placeholder: t2("operators.invitePlaceholder"),
|
|
1182
1236
|
style: { ...styles.input, flex: 1, minWidth: 220 },
|
|
1183
|
-
"aria-label": "
|
|
1237
|
+
"aria-label": t2("operators.inviteLabel")
|
|
1184
1238
|
}
|
|
1185
1239
|
),
|
|
1186
1240
|
/* @__PURE__ */ jsx9(
|
|
@@ -1189,27 +1243,27 @@ function OperatorsScreen({ client, me }) {
|
|
|
1189
1243
|
value: level,
|
|
1190
1244
|
onChange: (e) => setLevel(e.target.value),
|
|
1191
1245
|
style: styles.input,
|
|
1192
|
-
"aria-label": "
|
|
1193
|
-
children: LEVELS.map((l) => /* @__PURE__ */ jsxs9("option", { value: l.
|
|
1194
|
-
l.
|
|
1246
|
+
"aria-label": t2("operators.accessLevelLabel"),
|
|
1247
|
+
children: LEVELS.map((l) => /* @__PURE__ */ jsxs9("option", { value: l.id, children: [
|
|
1248
|
+
t2(`operators.level.${l.id}`),
|
|
1195
1249
|
" \u2014 ",
|
|
1196
|
-
l.
|
|
1197
|
-
] }, l.
|
|
1250
|
+
t2(`operators.levelHint.${l.id}`)
|
|
1251
|
+
] }, l.id))
|
|
1198
1252
|
}
|
|
1199
1253
|
),
|
|
1200
1254
|
/* @__PURE__ */ jsxs9("button", { type: "submit", style: styles.buttonPrimary, disabled: !email.trim(), children: [
|
|
1201
1255
|
/* @__PURE__ */ jsx9(Icon, { name: "plus", size: 14 }),
|
|
1202
|
-
"
|
|
1256
|
+
t2("operators.createInvite")
|
|
1203
1257
|
] })
|
|
1204
1258
|
]
|
|
1205
1259
|
}
|
|
1206
1260
|
),
|
|
1207
|
-
isLoading && !report ? /* @__PURE__ */ jsx9("p", { style: styles.status, children: "
|
|
1261
|
+
isLoading && !report ? /* @__PURE__ */ jsx9("p", { style: styles.status, children: t2("common.loading") }) : report && report.operators.length === 0 ? /* @__PURE__ */ jsx9(Empty, { icon: "users", title: t2("operators.emptyTitle") }) : report ? /* @__PURE__ */ jsxs9("table", { style: styles.table, children: [
|
|
1208
1262
|
/* @__PURE__ */ jsx9("thead", { children: /* @__PURE__ */ jsxs9("tr", { children: [
|
|
1209
|
-
/* @__PURE__ */ jsx9("th", { style: styles.th, children: "
|
|
1210
|
-
/* @__PURE__ */ jsx9("th", { style: styles.th, children: "
|
|
1211
|
-
/* @__PURE__ */ jsx9("th", { style: styles.th, children: "
|
|
1212
|
-
/* @__PURE__ */ jsx9("th", { style: styles.th, children: "
|
|
1263
|
+
/* @__PURE__ */ jsx9("th", { style: styles.th, children: t2("operators.col.operator") }),
|
|
1264
|
+
/* @__PURE__ */ jsx9("th", { style: styles.th, children: t2("operators.col.access") }),
|
|
1265
|
+
/* @__PURE__ */ jsx9("th", { style: styles.th, children: t2("operators.col.status") }),
|
|
1266
|
+
/* @__PURE__ */ jsx9("th", { style: styles.th, children: t2("operators.col.lastSignIn") }),
|
|
1213
1267
|
/* @__PURE__ */ jsx9("th", { style: styles.th })
|
|
1214
1268
|
] }) }),
|
|
1215
1269
|
/* @__PURE__ */ jsx9("tbody", { children: report.operators.map((o) => /* @__PURE__ */ jsxs9("tr", { children: [
|
|
@@ -1225,32 +1279,30 @@ function OperatorsScreen({ client, me }) {
|
|
|
1225
1279
|
}),
|
|
1226
1280
|
style: { ...styles.input, height: 28, fontSize: 12.5 },
|
|
1227
1281
|
disabled: o.email === me,
|
|
1228
|
-
"aria-label":
|
|
1229
|
-
children: LEVELS.map((l) => /* @__PURE__ */ jsx9("option", { value: l.
|
|
1282
|
+
"aria-label": t2("operators.accessLevelFor", { email: o.email }),
|
|
1283
|
+
children: LEVELS.map((l) => /* @__PURE__ */ jsx9("option", { value: l.id, children: t2(`operators.level.${l.id}`) }, l.id))
|
|
1230
1284
|
}
|
|
1231
1285
|
) }),
|
|
1232
1286
|
/* @__PURE__ */ jsxs9("td", { style: styles.td, children: [
|
|
1233
1287
|
status(o),
|
|
1234
|
-
o.enrolled && o.backupCodesLeft <= 2 && !o.disabledAt ? /* @__PURE__ */
|
|
1235
|
-
o.backupCodesLeft,
|
|
1236
|
-
|
|
1237
|
-
|
|
1288
|
+
o.enrolled && o.backupCodesLeft <= 2 && !o.disabledAt ? /* @__PURE__ */ jsx9("div", { style: { ...styles.muted, marginTop: 4 }, children: t2(
|
|
1289
|
+
o.backupCodesLeft === 1 ? "operators.backupCodesLeftOne" : "operators.backupCodesLeftMany",
|
|
1290
|
+
{ n: o.backupCodesLeft }
|
|
1291
|
+
) }) : null
|
|
1238
1292
|
] }),
|
|
1239
|
-
/* @__PURE__ */ jsx9("td", { style: { ...styles.td, ...styles.muted, whiteSpace: "nowrap" }, children: o.lastLoginAt ?
|
|
1240
|
-
/* @__PURE__ */ jsx9("td", { style: { ...styles.td, textAlign: "right", whiteSpace: "nowrap" }, children: o.email === me ? /* @__PURE__ */ jsx9("span", { style: styles.muted, children: "you" }) : /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
1293
|
+
/* @__PURE__ */ jsx9("td", { style: { ...styles.td, ...styles.muted, whiteSpace: "nowrap" }, children: o.lastLoginAt ? formatAdminDate3(o.lastLoginAt, locale) : t2("common.never") }),
|
|
1294
|
+
/* @__PURE__ */ jsx9("td", { style: { ...styles.td, textAlign: "right", whiteSpace: "nowrap" }, children: o.email === me ? /* @__PURE__ */ jsx9("span", { style: styles.muted, children: t2("common.you") }) : /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
1241
1295
|
/* @__PURE__ */ jsx9(
|
|
1242
1296
|
"button",
|
|
1243
1297
|
{
|
|
1244
1298
|
type: "button",
|
|
1245
1299
|
style: { ...styles.button, height: 28, marginRight: 6 },
|
|
1246
1300
|
onClick: () => {
|
|
1247
|
-
if (window.confirm(
|
|
1248
|
-
`Create a recovery link for ${o.email}? It signs them out everywhere; the link sets a new password and a new authenticator.`
|
|
1249
|
-
))
|
|
1301
|
+
if (window.confirm(t2("operators.recoveryConfirm", { email: o.email })))
|
|
1250
1302
|
void recover(o.id).then(setMinted).catch(() => {
|
|
1251
1303
|
});
|
|
1252
1304
|
},
|
|
1253
|
-
children: "
|
|
1305
|
+
children: t2("operators.recoveryLink")
|
|
1254
1306
|
}
|
|
1255
1307
|
),
|
|
1256
1308
|
/* @__PURE__ */ jsx9(
|
|
@@ -1262,35 +1314,32 @@ function OperatorsScreen({ client, me }) {
|
|
|
1262
1314
|
height: 28
|
|
1263
1315
|
},
|
|
1264
1316
|
onClick: () => {
|
|
1265
|
-
if (o.disabledAt || window.confirm(
|
|
1317
|
+
if (o.disabledAt || window.confirm(t2("operators.disableConfirm", { email: o.email })))
|
|
1266
1318
|
void update(o.id, { disabled: !o.disabledAt }).catch(() => {
|
|
1267
1319
|
});
|
|
1268
1320
|
},
|
|
1269
|
-
children: o.disabledAt ? "
|
|
1321
|
+
children: o.disabledAt ? t2("operators.enable") : t2("operators.disable")
|
|
1270
1322
|
}
|
|
1271
1323
|
)
|
|
1272
1324
|
] }) })
|
|
1273
1325
|
] }, o.id)) })
|
|
1274
1326
|
] }) : null,
|
|
1275
1327
|
report && report.links.length > 0 ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
1276
|
-
/* @__PURE__ */ jsx9("h2", { style: styles.subtitle, children: "
|
|
1328
|
+
/* @__PURE__ */ jsx9("h2", { style: styles.subtitle, children: t2("operators.pendingLinks") }),
|
|
1277
1329
|
/* @__PURE__ */ jsx9("ul", { style: styles.list, children: report.links.map((l) => /* @__PURE__ */ jsxs9(
|
|
1278
1330
|
"li",
|
|
1279
1331
|
{
|
|
1280
1332
|
style: { ...styles.row, display: "flex", gap: 12, alignItems: "center" },
|
|
1281
1333
|
children: [
|
|
1282
|
-
/* @__PURE__ */ jsx9(Pill, { tone: l.kind === "invite" ? "info" : "warn", dot: false, children: l.kind }),
|
|
1334
|
+
/* @__PURE__ */ jsx9(Pill, { tone: l.kind === "invite" ? "info" : "warn", dot: false, children: l.kind === "invite" ? t2("operators.linkKind.invite") : t2("operators.linkKind.recovery") }),
|
|
1283
1335
|
/* @__PURE__ */ jsxs9("span", { style: { flex: 1 }, children: [
|
|
1284
1336
|
l.email,
|
|
1285
1337
|
l.kind === "invite" ? /* @__PURE__ */ jsxs9("span", { style: styles.muted, children: [
|
|
1286
1338
|
" \xB7 ",
|
|
1287
|
-
levelOf(l.scopes)
|
|
1339
|
+
t2(`operators.level.${levelOf(l.scopes)}`)
|
|
1288
1340
|
] }) : null
|
|
1289
1341
|
] }),
|
|
1290
|
-
/* @__PURE__ */
|
|
1291
|
-
"expires ",
|
|
1292
|
-
new Date(l.expiresAt).toLocaleString()
|
|
1293
|
-
] }),
|
|
1342
|
+
/* @__PURE__ */ jsx9("span", { style: styles.muted, children: t2("operators.expiresOn", { date: formatAdminDate3(l.expiresAt, locale) }) }),
|
|
1294
1343
|
/* @__PURE__ */ jsx9(
|
|
1295
1344
|
"button",
|
|
1296
1345
|
{
|
|
@@ -1298,7 +1347,7 @@ function OperatorsScreen({ client, me }) {
|
|
|
1298
1347
|
style: { ...styles.buttonDanger, height: 28 },
|
|
1299
1348
|
onClick: () => void revokeLink(l.id).catch(() => {
|
|
1300
1349
|
}),
|
|
1301
|
-
children: "
|
|
1350
|
+
children: t2("operators.revoke")
|
|
1302
1351
|
}
|
|
1303
1352
|
)
|
|
1304
1353
|
]
|
|
@@ -1310,11 +1359,16 @@ function OperatorsScreen({ client, me }) {
|
|
|
1310
1359
|
}
|
|
1311
1360
|
|
|
1312
1361
|
// src/screens/TokensScreen.tsx
|
|
1362
|
+
import {
|
|
1363
|
+
createAdminT as createAdminT9,
|
|
1364
|
+
formatAdminDate as formatAdminDate4
|
|
1365
|
+
} from "@fonderie/client";
|
|
1313
1366
|
import { useAdminTokens } from "@fonderie/react-admin";
|
|
1314
1367
|
import { useState as useState3 } from "react";
|
|
1315
1368
|
import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1316
1369
|
var ALL = ["read", "write", "secrets"];
|
|
1317
|
-
function TokensScreen({ client }) {
|
|
1370
|
+
function TokensScreen({ client, locale }) {
|
|
1371
|
+
const t2 = createAdminT9(locale);
|
|
1318
1372
|
const { report, isLoading, error, issue, revoke } = useAdminTokens(client);
|
|
1319
1373
|
const [name, setName] = useState3("");
|
|
1320
1374
|
const [scopes, setScopes] = useState3(["read"]);
|
|
@@ -1322,19 +1376,13 @@ function TokensScreen({ client }) {
|
|
|
1322
1376
|
const [minted, setMinted] = useState3(null);
|
|
1323
1377
|
const toggle = (s) => setScopes((prev) => prev.includes(s) ? prev.filter((x) => x !== s) : [...prev, s]);
|
|
1324
1378
|
return /* @__PURE__ */ jsxs10("div", { style: styles.container, children: [
|
|
1325
|
-
/* @__PURE__ */ jsx10(
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
title: "Tokens",
|
|
1329
|
-
lead: "Credentials for machines: the root token's strength, scoped tokens for the CLI and CI, and any legacy per-module tokens. People sign in as operators."
|
|
1330
|
-
}
|
|
1331
|
-
),
|
|
1332
|
-
error ? /* @__PURE__ */ jsx10("p", { style: styles.error, role: "alert", children: error.status === 401 ? "Issuing and revoking need the root token (the one in your deployment config)." : error.explanation }) : null,
|
|
1333
|
-
/* @__PURE__ */ jsx10("h2", { style: { ...styles.subtitle, marginTop: 0 }, children: "Root token" }),
|
|
1379
|
+
/* @__PURE__ */ jsx10(PageHeader, { title: t2("tokens.title"), lead: t2("tokens.lead") }),
|
|
1380
|
+
error ? /* @__PURE__ */ jsx10("p", { style: styles.error, role: "alert", children: error.status === 401 ? t2("tokens.needsRoot") : error.explanation }) : null,
|
|
1381
|
+
/* @__PURE__ */ jsx10("h2", { style: { ...styles.subtitle, marginTop: 0 }, children: t2("tokens.rootToken") }),
|
|
1334
1382
|
report ? /* @__PURE__ */ jsxs10("div", { style: { ...styles.card, display: "flex", gap: 12, alignItems: "flex-start" }, children: [
|
|
1335
1383
|
/* @__PURE__ */ jsx10(Icon, { name: "lock", size: 18, style: { marginTop: 2 } }),
|
|
1336
1384
|
/* @__PURE__ */ jsxs10("div", { children: [
|
|
1337
|
-
/* @__PURE__ */ jsx10(Pill, { tone: report.admin.ok ? "ok" : "bad", children: report.admin.ok ? "strong" : "weak" }),
|
|
1385
|
+
/* @__PURE__ */ jsx10(Pill, { tone: report.admin.ok ? "ok" : "bad", children: report.admin.ok ? t2("tokens.strong") : t2("tokens.weak") }),
|
|
1338
1386
|
report.admin.problems.map((p) => /* @__PURE__ */ jsx10(
|
|
1339
1387
|
"div",
|
|
1340
1388
|
{
|
|
@@ -1345,8 +1393,8 @@ function TokensScreen({ client }) {
|
|
|
1345
1393
|
))
|
|
1346
1394
|
] })
|
|
1347
1395
|
] }) : null,
|
|
1348
|
-
/* @__PURE__ */ jsx10("h2", { style: styles.subtitle, children: "
|
|
1349
|
-
report?.issued === null ? /* @__PURE__ */ jsx10("p", { style: styles.muted, children: "
|
|
1396
|
+
/* @__PURE__ */ jsx10("h2", { style: styles.subtitle, children: t2("tokens.issuedTokens") }),
|
|
1397
|
+
report?.issued === null ? /* @__PURE__ */ jsx10("p", { style: styles.muted, children: t2("tokens.issuingOff") }) : /* @__PURE__ */ jsxs10(Fragment5, { children: [
|
|
1350
1398
|
minted ? /* @__PURE__ */ jsxs10(
|
|
1351
1399
|
"div",
|
|
1352
1400
|
{
|
|
@@ -1356,7 +1404,7 @@ function TokensScreen({ client }) {
|
|
|
1356
1404
|
borderColor: "color-mix(in srgb, var(--fonderie-accent,#00d294) 35%, transparent)"
|
|
1357
1405
|
},
|
|
1358
1406
|
children: [
|
|
1359
|
-
/* @__PURE__ */ jsx10("strong", { children: "
|
|
1407
|
+
/* @__PURE__ */ jsx10("strong", { children: t2("tokens.copyNow") }),
|
|
1360
1408
|
" (",
|
|
1361
1409
|
minted.name,
|
|
1362
1410
|
")",
|
|
@@ -1387,8 +1435,8 @@ function TokensScreen({ client }) {
|
|
|
1387
1435
|
name: name.trim(),
|
|
1388
1436
|
scopes,
|
|
1389
1437
|
...days && Number.isInteger(d) && d > 0 ? { expiresInDays: d } : {}
|
|
1390
|
-
}).then((
|
|
1391
|
-
setMinted({ name:
|
|
1438
|
+
}).then((t3) => {
|
|
1439
|
+
setMinted({ name: t3.name, token: t3.token });
|
|
1392
1440
|
setName("");
|
|
1393
1441
|
setDays("");
|
|
1394
1442
|
}).catch(() => {
|
|
@@ -1400,9 +1448,9 @@ function TokensScreen({ client }) {
|
|
|
1400
1448
|
{
|
|
1401
1449
|
value: name,
|
|
1402
1450
|
onChange: (e) => setName(e.target.value),
|
|
1403
|
-
placeholder: "
|
|
1451
|
+
placeholder: t2("tokens.namePlaceholder"),
|
|
1404
1452
|
style: styles.input,
|
|
1405
|
-
"aria-label": "
|
|
1453
|
+
"aria-label": t2("tokens.nameLabel")
|
|
1406
1454
|
}
|
|
1407
1455
|
),
|
|
1408
1456
|
ALL.map((s) => /* @__PURE__ */ jsxs10(
|
|
@@ -1419,7 +1467,7 @@ function TokensScreen({ client }) {
|
|
|
1419
1467
|
children: [
|
|
1420
1468
|
/* @__PURE__ */ jsx10("input", { type: "checkbox", checked: scopes.includes(s), onChange: () => toggle(s) }),
|
|
1421
1469
|
" ",
|
|
1422
|
-
s
|
|
1470
|
+
t2(`tokens.scope.${s}`)
|
|
1423
1471
|
]
|
|
1424
1472
|
},
|
|
1425
1473
|
s
|
|
@@ -1429,9 +1477,9 @@ function TokensScreen({ client }) {
|
|
|
1429
1477
|
{
|
|
1430
1478
|
value: days,
|
|
1431
1479
|
onChange: (e) => setDays(e.target.value),
|
|
1432
|
-
placeholder: "
|
|
1480
|
+
placeholder: t2("tokens.daysPlaceholder"),
|
|
1433
1481
|
style: { ...styles.input, width: 140 },
|
|
1434
|
-
"aria-label": "
|
|
1482
|
+
"aria-label": t2("tokens.daysLabel")
|
|
1435
1483
|
}
|
|
1436
1484
|
),
|
|
1437
1485
|
/* @__PURE__ */ jsxs10(
|
|
@@ -1442,7 +1490,7 @@ function TokensScreen({ client }) {
|
|
|
1442
1490
|
disabled: !name.trim() || scopes.length === 0 || isLoading,
|
|
1443
1491
|
children: [
|
|
1444
1492
|
/* @__PURE__ */ jsx10(Icon, { name: "plus", size: 14 }),
|
|
1445
|
-
"
|
|
1493
|
+
t2("tokens.issue")
|
|
1446
1494
|
]
|
|
1447
1495
|
}
|
|
1448
1496
|
)
|
|
@@ -1451,58 +1499,60 @@ function TokensScreen({ client }) {
|
|
|
1451
1499
|
),
|
|
1452
1500
|
report?.issued && report.issued.length > 0 ? /* @__PURE__ */ jsxs10("table", { style: styles.table, children: [
|
|
1453
1501
|
/* @__PURE__ */ jsx10("thead", { children: /* @__PURE__ */ jsxs10("tr", { children: [
|
|
1454
|
-
/* @__PURE__ */ jsx10("th", { style: styles.th, children: "
|
|
1455
|
-
/* @__PURE__ */ jsx10("th", { style: styles.th, children: "
|
|
1456
|
-
/* @__PURE__ */ jsx10("th", { style: styles.th, children: "
|
|
1457
|
-
/* @__PURE__ */ jsx10("th", { style: styles.th, children: "
|
|
1458
|
-
/* @__PURE__ */ jsx10("th", { style: styles.th, children: "
|
|
1502
|
+
/* @__PURE__ */ jsx10("th", { style: styles.th, children: t2("tokens.col.name") }),
|
|
1503
|
+
/* @__PURE__ */ jsx10("th", { style: styles.th, children: t2("tokens.col.scopes") }),
|
|
1504
|
+
/* @__PURE__ */ jsx10("th", { style: styles.th, children: t2("tokens.col.created") }),
|
|
1505
|
+
/* @__PURE__ */ jsx10("th", { style: styles.th, children: t2("tokens.col.expires") }),
|
|
1506
|
+
/* @__PURE__ */ jsx10("th", { style: styles.th, children: t2("tokens.col.lastUsed") }),
|
|
1459
1507
|
/* @__PURE__ */ jsx10("th", { style: styles.th })
|
|
1460
1508
|
] }) }),
|
|
1461
|
-
/* @__PURE__ */ jsx10("tbody", { children: report.issued.map((
|
|
1509
|
+
/* @__PURE__ */ jsx10("tbody", { children: report.issued.map((tk) => /* @__PURE__ */ jsxs10("tr", { children: [
|
|
1462
1510
|
/* @__PURE__ */ jsxs10("td", { style: styles.td, children: [
|
|
1463
|
-
|
|
1464
|
-
|
|
1511
|
+
tk.name,
|
|
1512
|
+
tk.revokedAt ? /* @__PURE__ */ jsxs10(Fragment5, { children: [
|
|
1465
1513
|
" ",
|
|
1466
|
-
/* @__PURE__ */ jsx10(Pill, { tone: "neutral", children: "revoked" })
|
|
1514
|
+
/* @__PURE__ */ jsx10(Pill, { tone: "neutral", children: t2("tokens.revoked") })
|
|
1467
1515
|
] }) : null
|
|
1468
1516
|
] }),
|
|
1469
|
-
/* @__PURE__ */ jsx10("td", { style: { ...styles.td, ...styles.mono }, children:
|
|
1517
|
+
/* @__PURE__ */ jsx10("td", { style: { ...styles.td, ...styles.mono }, children: tk.scopes.map((s) => t2(`tokens.scope.${s}`)).join(", ") }),
|
|
1470
1518
|
/* @__PURE__ */ jsxs10("td", { style: { ...styles.td, ...styles.muted }, children: [
|
|
1471
|
-
|
|
1519
|
+
formatAdminDate4(tk.createdAt, locale, "date"),
|
|
1472
1520
|
" \xB7 ",
|
|
1473
|
-
|
|
1521
|
+
tk.createdBy
|
|
1474
1522
|
] }),
|
|
1475
|
-
/* @__PURE__ */ jsx10("td", { style: { ...styles.td, ...styles.muted }, children:
|
|
1476
|
-
/* @__PURE__ */ jsx10("td", { style: { ...styles.td, ...styles.muted }, children:
|
|
1477
|
-
/* @__PURE__ */ jsx10("td", { style: styles.td, children:
|
|
1523
|
+
/* @__PURE__ */ jsx10("td", { style: { ...styles.td, ...styles.muted }, children: tk.expiresAt ? formatAdminDate4(tk.expiresAt, locale, "date") : t2("common.never") }),
|
|
1524
|
+
/* @__PURE__ */ jsx10("td", { style: { ...styles.td, ...styles.muted }, children: tk.lastUsedAt ? formatAdminDate4(tk.lastUsedAt, locale) : t2("common.never") }),
|
|
1525
|
+
/* @__PURE__ */ jsx10("td", { style: styles.td, children: tk.revokedAt ? null : /* @__PURE__ */ jsx10(
|
|
1478
1526
|
"button",
|
|
1479
1527
|
{
|
|
1480
1528
|
type: "button",
|
|
1481
1529
|
style: styles.buttonDanger,
|
|
1482
1530
|
onClick: () => {
|
|
1483
|
-
if (window.confirm(
|
|
1484
|
-
|
|
1485
|
-
))
|
|
1486
|
-
void revoke(t2.id).catch(() => {
|
|
1531
|
+
if (window.confirm(t2("tokens.revokeConfirm", { name: tk.name })))
|
|
1532
|
+
void revoke(tk.id).catch(() => {
|
|
1487
1533
|
});
|
|
1488
1534
|
},
|
|
1489
|
-
children: "
|
|
1535
|
+
children: t2("tokens.revoke")
|
|
1490
1536
|
}
|
|
1491
1537
|
) })
|
|
1492
|
-
] },
|
|
1493
|
-
] }) : /* @__PURE__ */ jsx10(Empty, { icon: "tokens", title: "
|
|
1538
|
+
] }, tk.id)) })
|
|
1539
|
+
] }) : /* @__PURE__ */ jsx10(Empty, { icon: "tokens", title: t2("tokens.emptyTitle"), children: t2("tokens.emptyBody") })
|
|
1494
1540
|
] }),
|
|
1495
|
-
/* @__PURE__ */ jsx10("h2", { style: styles.subtitle, children: "
|
|
1496
|
-
report && report.legacy.length === 0 ? /* @__PURE__ */ jsx10("p", { style: styles.muted, children: "
|
|
1541
|
+
/* @__PURE__ */ jsx10("h2", { style: styles.subtitle, children: t2("tokens.legacyTitle") }),
|
|
1542
|
+
report && report.legacy.length === 0 ? /* @__PURE__ */ jsx10("p", { style: styles.muted, children: t2("tokens.legacyNone") }) : /* @__PURE__ */ jsx10("ul", { style: styles.list, children: report?.legacy.map((l) => /* @__PURE__ */ jsxs10("li", { style: styles.row, children: [
|
|
1497
1543
|
/* @__PURE__ */ jsx10("span", { style: styles.mono, children: l.module }),
|
|
1498
1544
|
" ",
|
|
1499
|
-
/* @__PURE__ */ jsx10("span", { style: styles.muted, children: "
|
|
1545
|
+
/* @__PURE__ */ jsx10("span", { style: styles.muted, children: t2("tokens.legacyRow") })
|
|
1500
1546
|
] }, l.module)) })
|
|
1501
1547
|
] });
|
|
1502
1548
|
}
|
|
1503
1549
|
|
|
1504
1550
|
// src/screens/UsersScreen.tsx
|
|
1505
|
-
import {
|
|
1551
|
+
import {
|
|
1552
|
+
createAdminT as createAdminT12,
|
|
1553
|
+
describeLocation,
|
|
1554
|
+
formatAdminDate as formatAdminDate7
|
|
1555
|
+
} from "@fonderie/client";
|
|
1506
1556
|
import {
|
|
1507
1557
|
useAdminLoginHistory,
|
|
1508
1558
|
useAdminUser,
|
|
@@ -1512,14 +1562,38 @@ import {
|
|
|
1512
1562
|
import { useState as useState6 } from "react";
|
|
1513
1563
|
|
|
1514
1564
|
// src/billing.ts
|
|
1565
|
+
import {
|
|
1566
|
+
createAdminT as createAdminT10,
|
|
1567
|
+
formatAdminDate as formatAdminDate5
|
|
1568
|
+
} from "@fonderie/client";
|
|
1515
1569
|
import { useEffect, useState as useState4 } from "react";
|
|
1516
|
-
function periodEnd(s) {
|
|
1570
|
+
function periodEnd(s, locale) {
|
|
1517
1571
|
if (!s.currentPeriodEnd) return null;
|
|
1518
|
-
const
|
|
1572
|
+
const t2 = createAdminT10(locale);
|
|
1573
|
+
const date = formatAdminDate5(s.currentPeriodEnd, locale, "date");
|
|
1519
1574
|
if (s.status === "canceled")
|
|
1520
|
-
return {
|
|
1521
|
-
|
|
1522
|
-
|
|
1575
|
+
return {
|
|
1576
|
+
label: new Date(s.currentPeriodEnd) < /* @__PURE__ */ new Date() ? t2("billing.ended") : t2("billing.ends"),
|
|
1577
|
+
date
|
|
1578
|
+
};
|
|
1579
|
+
if (s.cancelAtPeriodEnd) return { label: t2("billing.ends"), date };
|
|
1580
|
+
return { label: t2("billing.renews"), date };
|
|
1581
|
+
}
|
|
1582
|
+
var STATUS_KEYS = [
|
|
1583
|
+
"active",
|
|
1584
|
+
"trialing",
|
|
1585
|
+
"past_due",
|
|
1586
|
+
"unpaid",
|
|
1587
|
+
"canceled",
|
|
1588
|
+
"incomplete",
|
|
1589
|
+
"incomplete_expired",
|
|
1590
|
+
"paused"
|
|
1591
|
+
];
|
|
1592
|
+
function statusLabel(t2, status) {
|
|
1593
|
+
return STATUS_KEYS.includes(status) ? t2(`billing.statusLabel.${status}`) : status;
|
|
1594
|
+
}
|
|
1595
|
+
function intervalLabel(t2, interval) {
|
|
1596
|
+
return interval === "month" || interval === "year" ? t2(`billing.intervalLabel.${interval}`) : interval;
|
|
1523
1597
|
}
|
|
1524
1598
|
var statusTone = (status) => status === "active" ? "ok" : status === "trialing" ? "info" : status === "past_due" || status === "unpaid" ? "warn" : "neutral";
|
|
1525
1599
|
function useSubscriptionIndex(client) {
|
|
@@ -1554,23 +1628,31 @@ function useSubscriptionIndex(client) {
|
|
|
1554
1628
|
}
|
|
1555
1629
|
|
|
1556
1630
|
// src/screens/SubscriberBilling.tsx
|
|
1631
|
+
import {
|
|
1632
|
+
createAdminT as createAdminT11,
|
|
1633
|
+
formatAdminDate as formatAdminDate6
|
|
1634
|
+
} from "@fonderie/client";
|
|
1557
1635
|
import { useAdminSubscriber } from "@fonderie/react-admin";
|
|
1558
1636
|
import { useState as useState5 } from "react";
|
|
1559
1637
|
import { Fragment as Fragment6, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1560
|
-
function SubscriberBilling({ client, subscriber }) {
|
|
1638
|
+
function SubscriberBilling({ client, subscriber, locale }) {
|
|
1639
|
+
const t2 = createAdminT11(locale);
|
|
1640
|
+
const LEDGER_KINDS = ["purchase", "grant", "usage", "refund", "adjustment", "expiry"];
|
|
1641
|
+
const ledgerKind = (kind) => LEDGER_KINDS.includes(kind) ? t2(`billing.ledgerKind.${kind}`) : kind;
|
|
1561
1642
|
const [currency, setCurrency] = useState5("");
|
|
1562
1643
|
const [currencyDraft, setCurrencyDraft] = useState5("");
|
|
1563
1644
|
const { subscription, wallet, ledger, hasMoreLedger, isLoading, error, loadMoreLedger, grant } = useAdminSubscriber(client, subscriber, { limit: 20, ...currency ? { currency } : {} });
|
|
1564
1645
|
const [amount, setAmount] = useState5("");
|
|
1565
1646
|
const [note, setNote] = useState5("");
|
|
1566
1647
|
const [granted, setGranted] = useState5(null);
|
|
1567
|
-
if (isLoading && !wallet && !subscription)
|
|
1568
|
-
|
|
1648
|
+
if (isLoading && !wallet && !subscription)
|
|
1649
|
+
return /* @__PURE__ */ jsx11("p", { style: styles.status, children: t2("billing.loading") });
|
|
1650
|
+
const end = subscription ? periodEnd(subscription, locale) : null;
|
|
1569
1651
|
return /* @__PURE__ */ jsxs11(Fragment6, { children: [
|
|
1570
1652
|
error ? /* @__PURE__ */ jsx11("p", { style: styles.error, role: "alert", children: error.explanation }) : null,
|
|
1571
1653
|
/* @__PURE__ */ jsxs11("div", { style: { ...styles.grid, marginBottom: 16 }, children: [
|
|
1572
1654
|
/* @__PURE__ */ jsxs11("div", { style: styles.card, children: [
|
|
1573
|
-
/* @__PURE__ */ jsx11("div", { style: styles.statLabel, children: "
|
|
1655
|
+
/* @__PURE__ */ jsx11("div", { style: styles.statLabel, children: t2("billing.plan") }),
|
|
1574
1656
|
/* @__PURE__ */ jsxs11(
|
|
1575
1657
|
"div",
|
|
1576
1658
|
{
|
|
@@ -1582,14 +1664,14 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1582
1664
|
flexWrap: "wrap"
|
|
1583
1665
|
},
|
|
1584
1666
|
children: [
|
|
1585
|
-
/* @__PURE__ */ jsx11("strong", { style: { fontSize: 18 }, children: subscription ? subscription.plan : "
|
|
1667
|
+
/* @__PURE__ */ jsx11("strong", { style: { fontSize: 18 }, children: subscription ? subscription.plan : t2("billing.free") }),
|
|
1586
1668
|
subscription ? /* @__PURE__ */ jsxs11(Fragment6, { children: [
|
|
1587
1669
|
/* @__PURE__ */ jsxs11("span", { style: styles.muted, children: [
|
|
1588
1670
|
"\xB7 ",
|
|
1589
|
-
subscription.interval
|
|
1671
|
+
intervalLabel(t2, subscription.interval)
|
|
1590
1672
|
] }),
|
|
1591
|
-
/* @__PURE__ */ jsx11(Pill, { tone: statusTone(subscription.status), children: subscription.status })
|
|
1592
|
-
] }) : /* @__PURE__ */ jsx11("span", { style: styles.muted, children: "
|
|
1673
|
+
/* @__PURE__ */ jsx11(Pill, { tone: statusTone(subscription.status), children: statusLabel(t2, subscription.status) })
|
|
1674
|
+
] }) : /* @__PURE__ */ jsx11("span", { style: styles.muted, children: t2("billing.noSubscription") })
|
|
1593
1675
|
]
|
|
1594
1676
|
}
|
|
1595
1677
|
),
|
|
@@ -1611,7 +1693,7 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1611
1693
|
gap: 8
|
|
1612
1694
|
},
|
|
1613
1695
|
children: [
|
|
1614
|
-
/* @__PURE__ */ jsx11("div", { style: styles.statLabel, children: "
|
|
1696
|
+
/* @__PURE__ */ jsx11("div", { style: styles.statLabel, children: t2("billing.credits") }),
|
|
1615
1697
|
/* @__PURE__ */ jsx11(
|
|
1616
1698
|
"form",
|
|
1617
1699
|
{
|
|
@@ -1625,11 +1707,11 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1625
1707
|
{
|
|
1626
1708
|
value: currencyDraft,
|
|
1627
1709
|
onChange: (e) => setCurrencyDraft(e.target.value),
|
|
1628
|
-
placeholder: wallet?.currency ?? "
|
|
1710
|
+
placeholder: wallet?.currency ?? t2("billing.currencyPlaceholder"),
|
|
1629
1711
|
maxLength: 8,
|
|
1630
1712
|
style: { ...styles.input, height: 26, width: 84, fontSize: 12 },
|
|
1631
|
-
"aria-label": "
|
|
1632
|
-
title: "
|
|
1713
|
+
"aria-label": t2("billing.currencyLabel"),
|
|
1714
|
+
title: t2("billing.currencyTitle")
|
|
1633
1715
|
}
|
|
1634
1716
|
)
|
|
1635
1717
|
}
|
|
@@ -1644,13 +1726,15 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1644
1726
|
/* @__PURE__ */ jsx11("span", { style: { fontSize: 14, fontWeight: 500 }, children: wallet.currency })
|
|
1645
1727
|
] }),
|
|
1646
1728
|
/* @__PURE__ */ jsxs11("div", { style: styles.statHint, children: [
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
wallet.grantedExpiresAt ?
|
|
1729
|
+
t2("billing.breakdown", {
|
|
1730
|
+
permanent: wallet.purchased ?? "0",
|
|
1731
|
+
allowance: wallet.granted ?? "0"
|
|
1732
|
+
}),
|
|
1733
|
+
wallet.grantedExpiresAt ? t2("billing.expires", {
|
|
1734
|
+
date: formatAdminDate6(wallet.grantedExpiresAt, locale, "date")
|
|
1735
|
+
}) : ""
|
|
1652
1736
|
] })
|
|
1653
|
-
] }) : /* @__PURE__ */ jsx11("div", { style: styles.statHint, children: "
|
|
1737
|
+
] }) : /* @__PURE__ */ jsx11("div", { style: styles.statHint, children: t2("billing.noWallet") })
|
|
1654
1738
|
] })
|
|
1655
1739
|
] }),
|
|
1656
1740
|
wallet ? /* @__PURE__ */ jsxs11(
|
|
@@ -1672,23 +1756,25 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1672
1756
|
...note ? { description: note } : {},
|
|
1673
1757
|
idempotencyKey: key
|
|
1674
1758
|
}).then(() => {
|
|
1675
|
-
setGranted(
|
|
1759
|
+
setGranted(
|
|
1760
|
+
t2("billing.granted", { amount: amount.trim(), currency: wallet.currency })
|
|
1761
|
+
);
|
|
1676
1762
|
setAmount("");
|
|
1677
1763
|
setNote("");
|
|
1678
1764
|
}).catch(() => {
|
|
1679
1765
|
});
|
|
1680
1766
|
},
|
|
1681
1767
|
children: [
|
|
1682
|
-
/* @__PURE__ */ jsx11("strong", { style: { fontSize: 13.5, marginRight: 4 }, children: "
|
|
1768
|
+
/* @__PURE__ */ jsx11("strong", { style: { fontSize: 13.5, marginRight: 4 }, children: t2("billing.grantCredits") }),
|
|
1683
1769
|
/* @__PURE__ */ jsx11(
|
|
1684
1770
|
"input",
|
|
1685
1771
|
{
|
|
1686
1772
|
value: amount,
|
|
1687
1773
|
onChange: (e) => setAmount(e.target.value),
|
|
1688
|
-
placeholder:
|
|
1774
|
+
placeholder: t2("billing.amountPlaceholder", { currency: wallet.currency }),
|
|
1689
1775
|
inputMode: "numeric",
|
|
1690
1776
|
style: { ...styles.input, width: 150 },
|
|
1691
|
-
"aria-label": "
|
|
1777
|
+
"aria-label": t2("billing.amountLabel")
|
|
1692
1778
|
}
|
|
1693
1779
|
),
|
|
1694
1780
|
/* @__PURE__ */ jsx11(
|
|
@@ -1696,9 +1782,9 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1696
1782
|
{
|
|
1697
1783
|
value: note,
|
|
1698
1784
|
onChange: (e) => setNote(e.target.value),
|
|
1699
|
-
placeholder: "
|
|
1785
|
+
placeholder: t2("billing.reasonPlaceholder"),
|
|
1700
1786
|
style: { ...styles.input, flex: 1, minWidth: 180 },
|
|
1701
|
-
"aria-label": "
|
|
1787
|
+
"aria-label": t2("billing.reasonLabel")
|
|
1702
1788
|
}
|
|
1703
1789
|
),
|
|
1704
1790
|
/* @__PURE__ */ jsxs11(
|
|
@@ -1709,7 +1795,7 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1709
1795
|
disabled: !/^\d+$/.test(amount.trim()),
|
|
1710
1796
|
children: [
|
|
1711
1797
|
/* @__PURE__ */ jsx11(Icon, { name: "plus", size: 14 }),
|
|
1712
|
-
"
|
|
1798
|
+
t2("billing.grant")
|
|
1713
1799
|
]
|
|
1714
1800
|
}
|
|
1715
1801
|
),
|
|
@@ -1717,20 +1803,20 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1717
1803
|
]
|
|
1718
1804
|
}
|
|
1719
1805
|
) : null,
|
|
1720
|
-
wallet ? ledger.length === 0 ? /* @__PURE__ */ jsx11(Empty, { icon: "subscriber", title: "
|
|
1806
|
+
wallet ? ledger.length === 0 ? /* @__PURE__ */ jsx11(Empty, { icon: "subscriber", title: t2("billing.noMovements") }) : /* @__PURE__ */ jsxs11(Fragment6, { children: [
|
|
1721
1807
|
/* @__PURE__ */ jsxs11("table", { style: styles.table, children: [
|
|
1722
1808
|
/* @__PURE__ */ jsx11("thead", { children: /* @__PURE__ */ jsxs11("tr", { children: [
|
|
1723
|
-
/* @__PURE__ */ jsx11("th", { style: styles.th, children: "
|
|
1724
|
-
/* @__PURE__ */ jsx11("th", { style: styles.th, children: "
|
|
1725
|
-
/* @__PURE__ */ jsx11("th", { style: styles.th, children: "
|
|
1726
|
-
/* @__PURE__ */ jsx11("th", { style: styles.th, children: "
|
|
1809
|
+
/* @__PURE__ */ jsx11("th", { style: styles.th, children: t2("billing.col.when") }),
|
|
1810
|
+
/* @__PURE__ */ jsx11("th", { style: styles.th, children: t2("billing.col.kind") }),
|
|
1811
|
+
/* @__PURE__ */ jsx11("th", { style: styles.th, children: t2("billing.col.amount") }),
|
|
1812
|
+
/* @__PURE__ */ jsx11("th", { style: styles.th, children: t2("billing.col.note") })
|
|
1727
1813
|
] }) }),
|
|
1728
|
-
/* @__PURE__ */ jsx11("tbody", { children: ledger.map((
|
|
1729
|
-
/* @__PURE__ */ jsx11("td", { style: { ...styles.td, ...styles.muted, whiteSpace: "nowrap" }, children:
|
|
1730
|
-
/* @__PURE__ */ jsx11("td", { style: styles.td, children:
|
|
1731
|
-
/* @__PURE__ */ jsx11("td", { style: { ...styles.td, ...styles.mono }, children:
|
|
1732
|
-
/* @__PURE__ */ jsx11("td", { style: { ...styles.td, ...styles.muted }, children:
|
|
1733
|
-
] },
|
|
1814
|
+
/* @__PURE__ */ jsx11("tbody", { children: ledger.map((tx) => /* @__PURE__ */ jsxs11("tr", { children: [
|
|
1815
|
+
/* @__PURE__ */ jsx11("td", { style: { ...styles.td, ...styles.muted, whiteSpace: "nowrap" }, children: formatAdminDate6(tx.createdAt, locale) }),
|
|
1816
|
+
/* @__PURE__ */ jsx11("td", { style: styles.td, children: ledgerKind(tx.type) }),
|
|
1817
|
+
/* @__PURE__ */ jsx11("td", { style: { ...styles.td, ...styles.mono }, children: tx.amount }),
|
|
1818
|
+
/* @__PURE__ */ jsx11("td", { style: { ...styles.td, ...styles.muted }, children: tx.description ?? "" })
|
|
1819
|
+
] }, tx.id)) })
|
|
1734
1820
|
] }),
|
|
1735
1821
|
hasMoreLedger ? /* @__PURE__ */ jsx11(
|
|
1736
1822
|
"button",
|
|
@@ -1738,7 +1824,7 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1738
1824
|
type: "button",
|
|
1739
1825
|
style: { ...styles.button, marginTop: 8 },
|
|
1740
1826
|
onClick: () => void loadMoreLedger(),
|
|
1741
|
-
children: "
|
|
1827
|
+
children: t2("common.loadMore")
|
|
1742
1828
|
}
|
|
1743
1829
|
) : null
|
|
1744
1830
|
] }) : null
|
|
@@ -1751,8 +1837,10 @@ function UsersScreen({
|
|
|
1751
1837
|
client,
|
|
1752
1838
|
pageSize = 50,
|
|
1753
1839
|
billingClient,
|
|
1754
|
-
openUserId
|
|
1840
|
+
openUserId,
|
|
1841
|
+
locale
|
|
1755
1842
|
}) {
|
|
1843
|
+
const t2 = createAdminT12(locale);
|
|
1756
1844
|
const [input, setInput] = useState6("");
|
|
1757
1845
|
const [selected, setSelected] = useState6(
|
|
1758
1846
|
openUserId ? { id: openUserId } : null
|
|
@@ -1770,19 +1858,13 @@ function UsersScreen({
|
|
|
1770
1858
|
const userId = user?.id ?? null;
|
|
1771
1859
|
const sessions = useAdminUserSessions(client, userId);
|
|
1772
1860
|
const history = useAdminLoginHistory(client, userId, { limit: 20 });
|
|
1773
|
-
const yesNo = (v) => v ? /* @__PURE__ */ jsx12(Pill, { tone: "ok", children: "yes" }) : /* @__PURE__ */ jsx12(Pill, { tone: "neutral", children: "no" });
|
|
1861
|
+
const yesNo = (v) => v ? /* @__PURE__ */ jsx12(Pill, { tone: "ok", children: t2("common.yes") }) : /* @__PURE__ */ jsx12(Pill, { tone: "neutral", children: t2("common.no") });
|
|
1774
1862
|
const clear = () => {
|
|
1775
1863
|
setSelected(null);
|
|
1776
1864
|
setInput("");
|
|
1777
1865
|
};
|
|
1778
1866
|
return /* @__PURE__ */ jsxs12("div", { style: styles.container, children: [
|
|
1779
|
-
/* @__PURE__ */ jsx12(
|
|
1780
|
-
PageHeader,
|
|
1781
|
-
{
|
|
1782
|
-
title: "Users",
|
|
1783
|
-
lead: "Everyone signed up. Open an account for its sessions, sign-ins and the suspend and sign-out controls."
|
|
1784
|
-
}
|
|
1785
|
-
),
|
|
1867
|
+
/* @__PURE__ */ jsx12(PageHeader, { title: t2("users.title"), lead: t2("users.lead") }),
|
|
1786
1868
|
/* @__PURE__ */ jsxs12(
|
|
1787
1869
|
"form",
|
|
1788
1870
|
{
|
|
@@ -1799,18 +1881,18 @@ function UsersScreen({
|
|
|
1799
1881
|
type: "email",
|
|
1800
1882
|
value: input,
|
|
1801
1883
|
onChange: (e) => setInput(e.target.value),
|
|
1802
|
-
placeholder: "
|
|
1884
|
+
placeholder: t2("users.emailPlaceholder"),
|
|
1803
1885
|
style: { ...styles.input, minWidth: 280 },
|
|
1804
|
-
"aria-label": "
|
|
1886
|
+
"aria-label": t2("users.emailLabel")
|
|
1805
1887
|
}
|
|
1806
1888
|
),
|
|
1807
1889
|
/* @__PURE__ */ jsxs12("button", { type: "submit", style: styles.buttonPrimary, disabled: isLoading, children: [
|
|
1808
1890
|
/* @__PURE__ */ jsx12(Icon, { name: "search", size: 14 }),
|
|
1809
|
-
"
|
|
1891
|
+
t2("common.lookUp")
|
|
1810
1892
|
] }),
|
|
1811
1893
|
selected ? /* @__PURE__ */ jsxs12("button", { type: "button", style: styles.buttonGhost, onClick: clear, children: [
|
|
1812
1894
|
/* @__PURE__ */ jsx12(Icon, { name: "back", size: 14 }),
|
|
1813
|
-
"
|
|
1895
|
+
t2("users.allUsers")
|
|
1814
1896
|
] }) : /* @__PURE__ */ jsx12(
|
|
1815
1897
|
"button",
|
|
1816
1898
|
{
|
|
@@ -1818,7 +1900,7 @@ function UsersScreen({
|
|
|
1818
1900
|
style: styles.button,
|
|
1819
1901
|
onClick: () => void list.refresh(),
|
|
1820
1902
|
disabled: list.isLoading,
|
|
1821
|
-
children: "
|
|
1903
|
+
children: t2("common.refresh")
|
|
1822
1904
|
}
|
|
1823
1905
|
),
|
|
1824
1906
|
!selected ? /* @__PURE__ */ jsx12(
|
|
@@ -1832,7 +1914,7 @@ function UsersScreen({
|
|
|
1832
1914
|
padding: 0,
|
|
1833
1915
|
minWidth: 0
|
|
1834
1916
|
},
|
|
1835
|
-
"aria-label": "
|
|
1917
|
+
"aria-label": t2("users.whichAccounts"),
|
|
1836
1918
|
children: [false, true].map((d) => /* @__PURE__ */ jsx12(
|
|
1837
1919
|
"button",
|
|
1838
1920
|
{
|
|
@@ -1843,7 +1925,7 @@ function UsersScreen({
|
|
|
1843
1925
|
...showDeleted === d ? styles.buttonPrimary : styles.button,
|
|
1844
1926
|
height: 28
|
|
1845
1927
|
},
|
|
1846
|
-
children: d ? "
|
|
1928
|
+
children: d ? t2("users.deletedAccounts") : t2("users.activeAccounts")
|
|
1847
1929
|
},
|
|
1848
1930
|
String(d)
|
|
1849
1931
|
))
|
|
@@ -1852,34 +1934,39 @@ function UsersScreen({
|
|
|
1852
1934
|
]
|
|
1853
1935
|
}
|
|
1854
1936
|
),
|
|
1855
|
-
error && !(error.status === 404 && selected?.id) ? /* @__PURE__ */ jsx12("p", { style: styles.error, role: "alert", children: error.status === 404 ? "
|
|
1937
|
+
error && !(error.status === 404 && selected?.id) ? /* @__PURE__ */ jsx12("p", { style: styles.error, role: "alert", children: error.status === 404 ? t2("users.noUserWithEmail") : error.explanation }) : null,
|
|
1856
1938
|
error?.status === 404 && selected?.id ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
1857
1939
|
/* @__PURE__ */ jsxs12("div", { style: styles.notice, role: "status", children: [
|
|
1858
|
-
/* @__PURE__ */
|
|
1940
|
+
/* @__PURE__ */ jsxs12("strong", { children: [
|
|
1941
|
+
t2("users.missingIdPrefix"),
|
|
1942
|
+
" "
|
|
1943
|
+
] }),
|
|
1859
1944
|
/* @__PURE__ */ jsx12("code", { style: styles.code, children: selected.id }),
|
|
1860
1945
|
/* @__PURE__ */ jsx12("strong", { children: "." }),
|
|
1861
|
-
"
|
|
1946
|
+
" ",
|
|
1947
|
+
t2("users.missingIdBody")
|
|
1862
1948
|
] }),
|
|
1863
1949
|
billingClient ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
1864
|
-
/* @__PURE__ */ jsx12("h2", { style: styles.subtitle, children: "
|
|
1950
|
+
/* @__PURE__ */ jsx12("h2", { style: styles.subtitle, children: t2("users.planCredits") }),
|
|
1865
1951
|
/* @__PURE__ */ jsx12(
|
|
1866
1952
|
SubscriberBilling,
|
|
1867
1953
|
{
|
|
1868
1954
|
client: billingClient,
|
|
1869
|
-
subscriber: { type: "user", id: selected.id }
|
|
1955
|
+
subscriber: { type: "user", id: selected.id },
|
|
1956
|
+
locale
|
|
1870
1957
|
}
|
|
1871
1958
|
)
|
|
1872
1959
|
] }) : null
|
|
1873
1960
|
] }) : null,
|
|
1874
1961
|
!selected ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
1875
1962
|
list.error ? /* @__PURE__ */ jsx12("p", { style: styles.error, role: "alert", children: list.error.explanation }) : null,
|
|
1876
|
-
list.users.length === 0 && !list.isLoading ? /* @__PURE__ */ jsx12(Empty, { icon: "users", title: "
|
|
1963
|
+
list.users.length === 0 && !list.isLoading ? /* @__PURE__ */ jsx12(Empty, { icon: "users", title: t2("users.emptyTitle"), children: t2("users.emptyBody") }) : /* @__PURE__ */ jsxs12("table", { style: styles.table, children: [
|
|
1877
1964
|
/* @__PURE__ */ jsx12("thead", { children: /* @__PURE__ */ jsxs12("tr", { children: [
|
|
1878
|
-
/* @__PURE__ */ jsx12("th", { style: styles.th, children: "
|
|
1879
|
-
/* @__PURE__ */ jsx12("th", { style: styles.th, children: "
|
|
1880
|
-
billingClient ? /* @__PURE__ */ jsx12("th", { style: styles.th, children: "
|
|
1881
|
-
/* @__PURE__ */ jsx12("th", { style: styles.th, children: "
|
|
1882
|
-
/* @__PURE__ */ jsx12("th", { style: styles.th, children: "
|
|
1965
|
+
/* @__PURE__ */ jsx12("th", { style: styles.th, children: t2("users.col.email") }),
|
|
1966
|
+
/* @__PURE__ */ jsx12("th", { style: styles.th, children: t2("users.col.name") }),
|
|
1967
|
+
billingClient ? /* @__PURE__ */ jsx12("th", { style: styles.th, children: t2("users.col.plan") }) : null,
|
|
1968
|
+
/* @__PURE__ */ jsx12("th", { style: styles.th, children: t2("users.col.created") }),
|
|
1969
|
+
/* @__PURE__ */ jsx12("th", { style: styles.th, children: t2("users.col.status") })
|
|
1883
1970
|
] }) }),
|
|
1884
1971
|
/* @__PURE__ */ jsx12("tbody", { children: list.users.map((u) => /* @__PURE__ */ jsxs12("tr", { children: [
|
|
1885
1972
|
/* @__PURE__ */ jsx12("td", { style: styles.td, children: /* @__PURE__ */ jsx12(
|
|
@@ -1896,29 +1983,29 @@ function UsersScreen({
|
|
|
1896
1983
|
const sub = plans?.get(`user/${u.id}`);
|
|
1897
1984
|
if (!plans) return /* @__PURE__ */ jsx12("span", { style: styles.muted, children: "\u2026" });
|
|
1898
1985
|
if (!sub || sub.status === "canceled")
|
|
1899
|
-
return /* @__PURE__ */ jsx12("span", { style: styles.muted, children: "free" });
|
|
1986
|
+
return /* @__PURE__ */ jsx12("span", { style: styles.muted, children: t2("common.status.free") });
|
|
1900
1987
|
return /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
1901
1988
|
/* @__PURE__ */ jsx12("strong", { children: sub.plan }),
|
|
1902
1989
|
" ",
|
|
1903
|
-
sub.status !== "active" ? /* @__PURE__ */ jsx12(Pill, { tone: statusTone(sub.status), children: sub.status }) : null
|
|
1990
|
+
sub.status !== "active" ? /* @__PURE__ */ jsx12(Pill, { tone: statusTone(sub.status), children: statusLabel(t2, sub.status) }) : null
|
|
1904
1991
|
] });
|
|
1905
1992
|
})() }) : null,
|
|
1906
|
-
/* @__PURE__ */ jsx12("td", { style: styles.td, children:
|
|
1993
|
+
/* @__PURE__ */ jsx12("td", { style: styles.td, children: formatAdminDate7(u.createdAt, locale, "date") }),
|
|
1907
1994
|
/* @__PURE__ */ jsxs12("td", { style: styles.td, children: [
|
|
1908
|
-
u.suspended ? /* @__PURE__ */ jsx12(Pill, { tone: "warn", children: "suspended" }) : null,
|
|
1909
|
-
u.deletedAt ? /* @__PURE__ */ jsx12(Pill, { tone: "neutral", children: "deleted" }) : null,
|
|
1910
|
-
!u.suspended && !u.deletedAt ? /* @__PURE__ */ jsx12(Pill, { tone: "ok", children: "active" }) : null
|
|
1995
|
+
u.suspended ? /* @__PURE__ */ jsx12(Pill, { tone: "warn", children: t2("common.status.suspended") }) : null,
|
|
1996
|
+
u.deletedAt ? /* @__PURE__ */ jsx12(Pill, { tone: "neutral", children: t2("common.status.deleted") }) : null,
|
|
1997
|
+
!u.suspended && !u.deletedAt ? /* @__PURE__ */ jsx12(Pill, { tone: "ok", children: t2("common.status.active") }) : null
|
|
1911
1998
|
] })
|
|
1912
1999
|
] }, u.id)) })
|
|
1913
2000
|
] }),
|
|
1914
|
-
list.isLoading ? /* @__PURE__ */ jsx12("p", { style: styles.status, children: "
|
|
2001
|
+
list.isLoading ? /* @__PURE__ */ jsx12("p", { style: styles.status, children: t2("common.loading") }) : null,
|
|
1915
2002
|
list.hasMore && !list.isLoading ? /* @__PURE__ */ jsx12(
|
|
1916
2003
|
"button",
|
|
1917
2004
|
{
|
|
1918
2005
|
type: "button",
|
|
1919
2006
|
style: { ...styles.button, marginTop: 8 },
|
|
1920
2007
|
onClick: () => void list.loadMore(),
|
|
1921
|
-
children: "
|
|
2008
|
+
children: t2("common.loadMore")
|
|
1922
2009
|
}
|
|
1923
2010
|
) : null
|
|
1924
2011
|
] }) : null,
|
|
@@ -1926,49 +2013,48 @@ function UsersScreen({
|
|
|
1926
2013
|
/* @__PURE__ */ jsxs12("h2", { style: styles.subtitle, children: [
|
|
1927
2014
|
user.firstName || user.lastName ? `${user.firstName} ${user.lastName}`.trim() : user.email,
|
|
1928
2015
|
" ",
|
|
1929
|
-
user.suspended ? /* @__PURE__ */ jsx12(Pill, { tone: "warn", children: "suspended" }) : null,
|
|
1930
|
-
user.deletedAt ? /* @__PURE__ */ jsx12(Pill, { tone: "neutral", children: "deleted" }) : null
|
|
2016
|
+
user.suspended ? /* @__PURE__ */ jsx12(Pill, { tone: "warn", children: t2("common.status.suspended") }) : null,
|
|
2017
|
+
user.deletedAt ? /* @__PURE__ */ jsx12(Pill, { tone: "neutral", children: t2("common.status.deleted") }) : null
|
|
1931
2018
|
] }),
|
|
1932
2019
|
/* @__PURE__ */ jsx12("table", { style: styles.table, children: /* @__PURE__ */ jsxs12("tbody", { children: [
|
|
1933
2020
|
/* @__PURE__ */ jsxs12("tr", { children: [
|
|
1934
|
-
/* @__PURE__ */ jsx12("td", { style: styles.td, children: "id" }),
|
|
2021
|
+
/* @__PURE__ */ jsx12("td", { style: styles.td, children: t2("users.field.id") }),
|
|
1935
2022
|
/* @__PURE__ */ jsx12("td", { style: { ...styles.td, ...styles.mono }, children: user.id })
|
|
1936
2023
|
] }),
|
|
1937
2024
|
/* @__PURE__ */ jsxs12("tr", { children: [
|
|
1938
|
-
/* @__PURE__ */ jsx12("td", { style: styles.td, children: "email" }),
|
|
2025
|
+
/* @__PURE__ */ jsx12("td", { style: styles.td, children: t2("users.field.email") }),
|
|
1939
2026
|
/* @__PURE__ */ jsxs12("td", { style: styles.td, children: [
|
|
1940
2027
|
user.email,
|
|
1941
|
-
" \xB7
|
|
2028
|
+
" \xB7 ",
|
|
2029
|
+
t2("users.field.verified"),
|
|
2030
|
+
" ",
|
|
1942
2031
|
yesNo(user.isEmailVerified)
|
|
1943
2032
|
] })
|
|
1944
2033
|
] }),
|
|
1945
2034
|
/* @__PURE__ */ jsxs12("tr", { children: [
|
|
1946
|
-
/* @__PURE__ */ jsx12("td", { style: styles.td, children: "
|
|
2035
|
+
/* @__PURE__ */ jsx12("td", { style: styles.td, children: t2("users.field.mfa") }),
|
|
1947
2036
|
/* @__PURE__ */ jsx12("td", { style: styles.td, children: yesNo(user.mfaEnabled) })
|
|
1948
2037
|
] }),
|
|
1949
2038
|
/* @__PURE__ */ jsxs12("tr", { children: [
|
|
1950
|
-
/* @__PURE__ */ jsx12("td", { style: styles.td, children: "provider" }),
|
|
2039
|
+
/* @__PURE__ */ jsx12("td", { style: styles.td, children: t2("users.field.provider") }),
|
|
1951
2040
|
/* @__PURE__ */ jsxs12("td", { style: styles.td, children: [
|
|
1952
|
-
user.provider || "
|
|
1953
|
-
user.hasPassword ? "" :
|
|
2041
|
+
user.provider || t2("users.passwordProvider"),
|
|
2042
|
+
user.hasPassword ? "" : ` \xB7 ${t2("users.noPasswordSet")}`
|
|
1954
2043
|
] })
|
|
1955
2044
|
] }),
|
|
1956
2045
|
/* @__PURE__ */ jsxs12("tr", { children: [
|
|
1957
|
-
/* @__PURE__ */ jsx12("td", { style: styles.td, children: "
|
|
1958
|
-
/* @__PURE__ */ jsx12("td", { style: styles.td, children: user.lastLogin ?
|
|
2046
|
+
/* @__PURE__ */ jsx12("td", { style: styles.td, children: t2("users.field.lastLogin") }),
|
|
2047
|
+
/* @__PURE__ */ jsx12("td", { style: styles.td, children: user.lastLogin ? formatAdminDate7(user.lastLogin, locale) : /* @__PURE__ */ jsx12("span", { style: styles.muted, children: t2("common.never") }) })
|
|
1959
2048
|
] }),
|
|
1960
2049
|
/* @__PURE__ */ jsxs12("tr", { children: [
|
|
1961
|
-
/* @__PURE__ */ jsx12("td", { style: styles.td, children: "created" }),
|
|
1962
|
-
/* @__PURE__ */ jsx12("td", { style: styles.td, children:
|
|
2050
|
+
/* @__PURE__ */ jsx12("td", { style: styles.td, children: t2("users.field.created") }),
|
|
2051
|
+
/* @__PURE__ */ jsx12("td", { style: styles.td, children: formatAdminDate7(user.createdAt, locale) })
|
|
1963
2052
|
] })
|
|
1964
2053
|
] }) }),
|
|
1965
2054
|
user.deletedAt ? /* @__PURE__ */ jsxs12("div", { style: { ...styles.notice, marginTop: 12 }, role: "status", children: [
|
|
1966
|
-
/* @__PURE__ */
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
"."
|
|
1970
|
-
] }),
|
|
1971
|
-
" The account cannot sign in, and it is erased when the retention purge runs. Its billing records stay."
|
|
2055
|
+
/* @__PURE__ */ jsx12("strong", { children: t2("users.deletedOn", { date: formatAdminDate7(user.deletedAt, locale) }) }),
|
|
2056
|
+
" ",
|
|
2057
|
+
t2("users.deletedBody")
|
|
1972
2058
|
] }) : /* @__PURE__ */ jsxs12("div", { style: { ...styles.toolbar, marginTop: 12 }, children: [
|
|
1973
2059
|
user.suspended ? /* @__PURE__ */ jsx12(
|
|
1974
2060
|
"button",
|
|
@@ -1977,7 +2063,7 @@ function UsersScreen({
|
|
|
1977
2063
|
style: styles.button,
|
|
1978
2064
|
onClick: () => void unsuspend(),
|
|
1979
2065
|
disabled: isLoading,
|
|
1980
|
-
children: "
|
|
2066
|
+
children: t2("users.unsuspend")
|
|
1981
2067
|
}
|
|
1982
2068
|
) : /* @__PURE__ */ jsx12(
|
|
1983
2069
|
"button",
|
|
@@ -1986,7 +2072,7 @@ function UsersScreen({
|
|
|
1986
2072
|
style: styles.buttonDanger,
|
|
1987
2073
|
onClick: () => void suspend(),
|
|
1988
2074
|
disabled: isLoading,
|
|
1989
|
-
children: "
|
|
2075
|
+
children: t2("users.suspend")
|
|
1990
2076
|
}
|
|
1991
2077
|
),
|
|
1992
2078
|
/* @__PURE__ */ jsx12(
|
|
@@ -1996,23 +2082,24 @@ function UsersScreen({
|
|
|
1996
2082
|
style: styles.button,
|
|
1997
2083
|
onClick: () => void revokeSessions().then(() => sessions.refresh()),
|
|
1998
2084
|
disabled: isLoading,
|
|
1999
|
-
children: "
|
|
2085
|
+
children: t2("users.signOutEverywhere")
|
|
2000
2086
|
}
|
|
2001
2087
|
)
|
|
2002
2088
|
] }),
|
|
2003
2089
|
billingClient ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
2004
|
-
/* @__PURE__ */ jsx12("h2", { style: styles.subtitle, children: "
|
|
2090
|
+
/* @__PURE__ */ jsx12("h2", { style: styles.subtitle, children: t2("users.planCredits") }),
|
|
2005
2091
|
/* @__PURE__ */ jsx12(
|
|
2006
2092
|
SubscriberBilling,
|
|
2007
2093
|
{
|
|
2008
2094
|
client: billingClient,
|
|
2009
|
-
subscriber: { type: "user", id: user.id }
|
|
2095
|
+
subscriber: { type: "user", id: user.id },
|
|
2096
|
+
locale
|
|
2010
2097
|
}
|
|
2011
2098
|
)
|
|
2012
2099
|
] }) : null,
|
|
2013
2100
|
!user.deletedAt ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
2014
|
-
/* @__PURE__ */ jsx12("h2", { style: styles.subtitle, children: "
|
|
2015
|
-
sessions.sessions.length === 0 ? /* @__PURE__ */ jsx12("p", { style: styles.muted, children: "
|
|
2101
|
+
/* @__PURE__ */ jsx12("h2", { style: styles.subtitle, children: t2("users.liveSessions") }),
|
|
2102
|
+
sessions.sessions.length === 0 ? /* @__PURE__ */ jsx12("p", { style: styles.muted, children: t2("common.none") }) : /* @__PURE__ */ jsx12("ul", { style: styles.list, children: sessions.sessions.map((s) => /* @__PURE__ */ jsxs12("li", { style: styles.row, children: [
|
|
2016
2103
|
/* @__PURE__ */ jsx12("span", { style: styles.mono, children: s.ipAddress ?? "\u2014" }),
|
|
2017
2104
|
" ",
|
|
2018
2105
|
describeLocation(s.location) ? /* @__PURE__ */ jsxs12("span", { style: styles.muted, children: [
|
|
@@ -2021,14 +2108,11 @@ function UsersScreen({
|
|
|
2021
2108
|
] }) : null,
|
|
2022
2109
|
/* @__PURE__ */ jsx12("span", { style: styles.muted, children: s.userAgent ?? "" }),
|
|
2023
2110
|
" ",
|
|
2024
|
-
/* @__PURE__ */
|
|
2025
|
-
"since ",
|
|
2026
|
-
new Date(s.createdAt).toLocaleString()
|
|
2027
|
-
] })
|
|
2111
|
+
/* @__PURE__ */ jsx12("span", { style: styles.muted, children: t2("users.since", { date: formatAdminDate7(s.createdAt, locale) }) })
|
|
2028
2112
|
] }, s.id)) }),
|
|
2029
|
-
/* @__PURE__ */ jsx12("h2", { style: styles.subtitle, children: "
|
|
2030
|
-
history.events.length === 0 && !history.isLoading ? /* @__PURE__ */ jsx12("p", { style: styles.muted, children: "
|
|
2031
|
-
/* @__PURE__ */ jsx12(Pill, { tone: e.outcome === "success" ? "ok" : "bad", children: e.outcome }),
|
|
2113
|
+
/* @__PURE__ */ jsx12("h2", { style: styles.subtitle, children: t2("users.recentSignIns") }),
|
|
2114
|
+
history.events.length === 0 && !history.isLoading ? /* @__PURE__ */ jsx12("p", { style: styles.muted, children: t2("users.noneRecorded") }) : /* @__PURE__ */ jsx12("ul", { style: styles.list, children: history.events.map((e) => /* @__PURE__ */ jsxs12("li", { style: styles.row, children: [
|
|
2115
|
+
/* @__PURE__ */ jsx12(Pill, { tone: e.outcome === "success" ? "ok" : "bad", children: e.outcome === "success" ? t2("users.outcome.success") : e.outcome === "failure" ? t2("users.outcome.failure") : e.outcome }),
|
|
2032
2116
|
" ",
|
|
2033
2117
|
/* @__PURE__ */ jsx12("span", { style: styles.muted, children: e.method }),
|
|
2034
2118
|
" ",
|
|
@@ -2037,10 +2121,10 @@ function UsersScreen({
|
|
|
2037
2121
|
describeLocation(e.location) ? /* @__PURE__ */ jsx12("span", { style: styles.muted, children: describeLocation(e.location) }) : null,
|
|
2038
2122
|
e.location?.proxy || e.location?.hosting ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
2039
2123
|
" ",
|
|
2040
|
-
/* @__PURE__ */ jsx12(Pill, { tone: "warn", children: e.location.proxy ? "
|
|
2124
|
+
/* @__PURE__ */ jsx12(Pill, { tone: "warn", children: e.location.proxy ? t2("users.proxyVpn") : t2("users.hosting") })
|
|
2041
2125
|
] }) : null,
|
|
2042
2126
|
" ",
|
|
2043
|
-
/* @__PURE__ */ jsx12("span", { style: styles.muted, children:
|
|
2127
|
+
/* @__PURE__ */ jsx12("span", { style: styles.muted, children: formatAdminDate7(e.createdAt, locale) })
|
|
2044
2128
|
] }, e.id)) }),
|
|
2045
2129
|
history.hasMore && !history.isLoading ? /* @__PURE__ */ jsx12(
|
|
2046
2130
|
"button",
|
|
@@ -2048,7 +2132,7 @@ function UsersScreen({
|
|
|
2048
2132
|
type: "button",
|
|
2049
2133
|
style: { ...styles.button, marginTop: 8 },
|
|
2050
2134
|
onClick: () => void history.loadMore(),
|
|
2051
|
-
children: "
|
|
2135
|
+
children: t2("common.loadMore")
|
|
2052
2136
|
}
|
|
2053
2137
|
) : null
|
|
2054
2138
|
] }) : null
|
|
@@ -2057,24 +2141,33 @@ function UsersScreen({
|
|
|
2057
2141
|
}
|
|
2058
2142
|
|
|
2059
2143
|
// src/screens/CatalogScreen.tsx
|
|
2144
|
+
import { createAdminT as createAdminT13 } from "@fonderie/client";
|
|
2060
2145
|
import { useAdminCatalog } from "@fonderie/react-admin";
|
|
2061
2146
|
import { Fragment as Fragment8, jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2062
|
-
function CatalogScreen({ client }) {
|
|
2147
|
+
function CatalogScreen({ client, locale }) {
|
|
2148
|
+
const t2 = createAdminT13(locale);
|
|
2063
2149
|
const { catalog, isLoading, error, refresh, deletePlan } = useAdminCatalog(client);
|
|
2064
2150
|
const money = (v) => v == null ? "\u2014" : (v / 100).toFixed(2);
|
|
2065
2151
|
return /* @__PURE__ */ jsxs13("div", { style: styles.container, children: [
|
|
2066
2152
|
/* @__PURE__ */ jsx13(
|
|
2067
2153
|
PageHeader,
|
|
2068
2154
|
{
|
|
2069
|
-
title: "
|
|
2070
|
-
lead: "
|
|
2071
|
-
actions: /* @__PURE__ */ jsx13(
|
|
2155
|
+
title: t2("catalog.title"),
|
|
2156
|
+
lead: t2("catalog.lead"),
|
|
2157
|
+
actions: /* @__PURE__ */ jsx13(
|
|
2158
|
+
RefreshButton,
|
|
2159
|
+
{
|
|
2160
|
+
onClick: () => void refresh(),
|
|
2161
|
+
busy: isLoading,
|
|
2162
|
+
label: t2("common.refresh")
|
|
2163
|
+
}
|
|
2164
|
+
)
|
|
2072
2165
|
}
|
|
2073
2166
|
),
|
|
2074
2167
|
error ? /* @__PURE__ */ jsx13("p", { style: styles.error, role: "alert", children: error.explanation }) : null,
|
|
2075
|
-
isLoading && !catalog ? /* @__PURE__ */ jsx13("p", { style: styles.status, children: "
|
|
2168
|
+
isLoading && !catalog ? /* @__PURE__ */ jsx13("p", { style: styles.status, children: t2("common.loading") }) : null,
|
|
2076
2169
|
catalog ? /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
2077
|
-
/* @__PURE__ */ jsx13("h2", { style: { ...styles.subtitle, marginTop: 0 }, children: "
|
|
2170
|
+
/* @__PURE__ */ jsx13("h2", { style: { ...styles.subtitle, marginTop: 0 }, children: t2("catalog.configured") }),
|
|
2078
2171
|
/* @__PURE__ */ jsx13(
|
|
2079
2172
|
"pre",
|
|
2080
2173
|
{
|
|
@@ -2089,15 +2182,15 @@ function CatalogScreen({ client }) {
|
|
|
2089
2182
|
children: JSON.stringify(catalog.configured, null, 2)
|
|
2090
2183
|
}
|
|
2091
2184
|
),
|
|
2092
|
-
/* @__PURE__ */ jsx13("h2", { style: styles.subtitle, children: "
|
|
2093
|
-
catalog.stored.length === 0 ? /* @__PURE__ */ jsx13(Empty, { icon: "catalog", title: "
|
|
2185
|
+
/* @__PURE__ */ jsx13("h2", { style: styles.subtitle, children: t2("catalog.stored") }),
|
|
2186
|
+
catalog.stored.length === 0 ? /* @__PURE__ */ jsx13(Empty, { icon: "catalog", title: t2("catalog.emptyTitle"), children: t2("catalog.emptyBody") }) : /* @__PURE__ */ jsxs13("table", { style: styles.table, children: [
|
|
2094
2187
|
/* @__PURE__ */ jsx13("thead", { children: /* @__PURE__ */ jsxs13("tr", { children: [
|
|
2095
|
-
/* @__PURE__ */ jsx13("th", { style: styles.th, children: "
|
|
2096
|
-
/* @__PURE__ */ jsx13("th", { style: styles.th, children: "
|
|
2097
|
-
/* @__PURE__ */ jsx13("th", { style: styles.th, children: "
|
|
2098
|
-
/* @__PURE__ */ jsx13("th", { style: styles.th, children: "
|
|
2099
|
-
/* @__PURE__ */ jsx13("th", { style: styles.th, children: "
|
|
2100
|
-
/* @__PURE__ */ jsx13("th", { style: styles.th, children: "
|
|
2188
|
+
/* @__PURE__ */ jsx13("th", { style: styles.th, children: t2("catalog.col.plan") }),
|
|
2189
|
+
/* @__PURE__ */ jsx13("th", { style: styles.th, children: t2("catalog.col.tier") }),
|
|
2190
|
+
/* @__PURE__ */ jsx13("th", { style: styles.th, children: t2("catalog.col.seats") }),
|
|
2191
|
+
/* @__PURE__ */ jsx13("th", { style: styles.th, children: t2("catalog.col.monthly") }),
|
|
2192
|
+
/* @__PURE__ */ jsx13("th", { style: styles.th, children: t2("catalog.col.yearly") }),
|
|
2193
|
+
/* @__PURE__ */ jsx13("th", { style: styles.th, children: t2("catalog.col.trial") }),
|
|
2101
2194
|
/* @__PURE__ */ jsx13("th", { style: styles.th })
|
|
2102
2195
|
] }) }),
|
|
2103
2196
|
/* @__PURE__ */ jsx13("tbody", { children: catalog.stored.map((p) => /* @__PURE__ */ jsxs13("tr", { children: [
|
|
@@ -2113,18 +2206,18 @@ function CatalogScreen({ client }) {
|
|
|
2113
2206
|
p.pricing?.currency ?? ""
|
|
2114
2207
|
] }),
|
|
2115
2208
|
/* @__PURE__ */ jsx13("td", { style: styles.td, children: money(p.pricing?.yearly) }),
|
|
2116
|
-
/* @__PURE__ */ jsx13("td", { style: styles.td, children: p.trialDays ?
|
|
2209
|
+
/* @__PURE__ */ jsx13("td", { style: styles.td, children: p.trialDays ? t2("catalog.trialDays", { n: p.trialDays }) : "\u2014" }),
|
|
2117
2210
|
/* @__PURE__ */ jsx13("td", { style: styles.td, children: /* @__PURE__ */ jsx13(
|
|
2118
2211
|
"button",
|
|
2119
2212
|
{
|
|
2120
2213
|
type: "button",
|
|
2121
2214
|
style: styles.buttonDanger,
|
|
2122
2215
|
onClick: () => {
|
|
2123
|
-
if (window.confirm(
|
|
2216
|
+
if (window.confirm(t2("catalog.deleteConfirm", { name: p.name })))
|
|
2124
2217
|
void deletePlan(p.id).catch(() => {
|
|
2125
2218
|
});
|
|
2126
2219
|
},
|
|
2127
|
-
children: "
|
|
2220
|
+
children: t2("common.delete")
|
|
2128
2221
|
}
|
|
2129
2222
|
) })
|
|
2130
2223
|
] }, p.id)) })
|
|
@@ -2134,19 +2227,28 @@ function CatalogScreen({ client }) {
|
|
|
2134
2227
|
}
|
|
2135
2228
|
|
|
2136
2229
|
// src/screens/SubscriberScreen.tsx
|
|
2230
|
+
import {
|
|
2231
|
+
createAdminT as createAdminT14
|
|
2232
|
+
} from "@fonderie/client";
|
|
2137
2233
|
import { useAdminSubscribers } from "@fonderie/react-admin";
|
|
2138
2234
|
import { useState as useState7 } from "react";
|
|
2139
2235
|
import { Fragment as Fragment9, jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2140
2236
|
var FILTERS = [
|
|
2141
|
-
{
|
|
2142
|
-
{
|
|
2143
|
-
{
|
|
2144
|
-
{
|
|
2145
|
-
{
|
|
2237
|
+
{ id: "all", match: () => true },
|
|
2238
|
+
{ id: "active", match: (s) => s === "active" },
|
|
2239
|
+
{ id: "trialing", match: (s) => s === "trialing" },
|
|
2240
|
+
{ id: "pastDue", match: (s) => s === "past_due" || s === "unpaid" },
|
|
2241
|
+
{ id: "canceled", match: (s) => s === "canceled" }
|
|
2146
2242
|
];
|
|
2147
|
-
function SubscriberScreen({
|
|
2243
|
+
function SubscriberScreen({
|
|
2244
|
+
client,
|
|
2245
|
+
pageSize = 50,
|
|
2246
|
+
onOpenUser,
|
|
2247
|
+
locale
|
|
2248
|
+
}) {
|
|
2249
|
+
const t2 = createAdminT14(locale);
|
|
2148
2250
|
const list = useAdminSubscribers(client, { limit: pageSize });
|
|
2149
|
-
const [filter, setFilter] = useState7("
|
|
2251
|
+
const [filter, setFilter] = useState7("all");
|
|
2150
2252
|
const [open, setOpen] = useState7(null);
|
|
2151
2253
|
const [type, setType] = useState7("workspace");
|
|
2152
2254
|
const [idInput, setIdInput] = useState7("");
|
|
@@ -2156,26 +2258,33 @@ function SubscriberScreen({ client, pageSize = 50, onOpenUser }) {
|
|
|
2156
2258
|
PageHeader,
|
|
2157
2259
|
{
|
|
2158
2260
|
title: `${open.type}/${open.id}`,
|
|
2159
|
-
lead: "
|
|
2261
|
+
lead: t2("billing.subscriptions.detailLead"),
|
|
2160
2262
|
actions: /* @__PURE__ */ jsxs14("button", { type: "button", style: styles.buttonGhost, onClick: () => setOpen(null), children: [
|
|
2161
2263
|
/* @__PURE__ */ jsx14(Icon, { name: "back", size: 14 }),
|
|
2162
|
-
"
|
|
2264
|
+
t2("billing.subscriptions.back")
|
|
2163
2265
|
] })
|
|
2164
2266
|
}
|
|
2165
2267
|
),
|
|
2166
|
-
/* @__PURE__ */ jsx14(SubscriberBilling, { client, subscriber: open })
|
|
2268
|
+
/* @__PURE__ */ jsx14(SubscriberBilling, { client, subscriber: open, locale })
|
|
2167
2269
|
] });
|
|
2168
2270
|
}
|
|
2169
|
-
const match = FILTERS.find((f) => f.
|
|
2271
|
+
const match = FILTERS.find((f) => f.id === filter)?.match ?? (() => true);
|
|
2170
2272
|
const rows = list.subscriptions.filter((s) => match(s.status));
|
|
2171
|
-
const openRow = (
|
|
2273
|
+
const openRow = (t3, id) => t3 === "user" && onOpenUser ? onOpenUser(id) : setOpen({ type: t3, id });
|
|
2172
2274
|
return /* @__PURE__ */ jsxs14("div", { style: styles.container, children: [
|
|
2173
2275
|
/* @__PURE__ */ jsx14(
|
|
2174
2276
|
PageHeader,
|
|
2175
2277
|
{
|
|
2176
|
-
title: "
|
|
2177
|
-
lead: "
|
|
2178
|
-
actions: /* @__PURE__ */ jsx14(
|
|
2278
|
+
title: t2("billing.subscriptions.title"),
|
|
2279
|
+
lead: t2("billing.subscriptions.lead"),
|
|
2280
|
+
actions: /* @__PURE__ */ jsx14(
|
|
2281
|
+
RefreshButton,
|
|
2282
|
+
{
|
|
2283
|
+
onClick: () => void list.refresh(),
|
|
2284
|
+
busy: list.isLoading,
|
|
2285
|
+
label: t2("common.refresh")
|
|
2286
|
+
}
|
|
2287
|
+
)
|
|
2179
2288
|
}
|
|
2180
2289
|
),
|
|
2181
2290
|
/* @__PURE__ */ jsxs14("div", { style: { ...styles.toolbar, justifyContent: "space-between" }, children: [
|
|
@@ -2191,23 +2300,23 @@ function SubscriberScreen({ client, pageSize = 50, onOpenUser }) {
|
|
|
2191
2300
|
padding: 0,
|
|
2192
2301
|
minWidth: 0
|
|
2193
2302
|
},
|
|
2194
|
-
"aria-label": "
|
|
2303
|
+
"aria-label": t2("billing.subscriptions.filterLabel"),
|
|
2195
2304
|
children: FILTERS.map((f) => {
|
|
2196
2305
|
const n = list.subscriptions.filter((s) => f.match(s.status)).length;
|
|
2197
|
-
const on = filter === f.
|
|
2306
|
+
const on = filter === f.id;
|
|
2198
2307
|
return /* @__PURE__ */ jsxs14(
|
|
2199
2308
|
"button",
|
|
2200
2309
|
{
|
|
2201
2310
|
type: "button",
|
|
2202
2311
|
"aria-pressed": on,
|
|
2203
|
-
onClick: () => setFilter(f.
|
|
2312
|
+
onClick: () => setFilter(f.id),
|
|
2204
2313
|
style: { ...on ? styles.buttonPrimary : styles.button, height: 28 },
|
|
2205
2314
|
children: [
|
|
2206
|
-
f.
|
|
2315
|
+
t2(`billing.subscriptions.filter.${f.id}`),
|
|
2207
2316
|
/* @__PURE__ */ jsx14("span", { style: { opacity: 0.7 }, children: n })
|
|
2208
2317
|
]
|
|
2209
2318
|
},
|
|
2210
|
-
f.
|
|
2319
|
+
f.id
|
|
2211
2320
|
);
|
|
2212
2321
|
})
|
|
2213
2322
|
}
|
|
@@ -2227,10 +2336,10 @@ function SubscriberScreen({ client, pageSize = 50, onOpenUser }) {
|
|
|
2227
2336
|
value: type,
|
|
2228
2337
|
onChange: (e) => setType(e.target.value),
|
|
2229
2338
|
style: styles.input,
|
|
2230
|
-
"aria-label": "
|
|
2339
|
+
"aria-label": t2("billing.subscriptions.typeLabel"),
|
|
2231
2340
|
children: [
|
|
2232
|
-
/* @__PURE__ */ jsx14("option", { value: "workspace", children: "
|
|
2233
|
-
/* @__PURE__ */ jsx14("option", { value: "user", children: "
|
|
2341
|
+
/* @__PURE__ */ jsx14("option", { value: "workspace", children: t2("billing.subscriptions.typeWorkspace") }),
|
|
2342
|
+
/* @__PURE__ */ jsx14("option", { value: "user", children: t2("billing.subscriptions.typeUser") })
|
|
2234
2343
|
]
|
|
2235
2344
|
}
|
|
2236
2345
|
),
|
|
@@ -2239,36 +2348,29 @@ function SubscriberScreen({ client, pageSize = 50, onOpenUser }) {
|
|
|
2239
2348
|
{
|
|
2240
2349
|
value: idInput,
|
|
2241
2350
|
onChange: (e) => setIdInput(e.target.value),
|
|
2242
|
-
placeholder: "
|
|
2351
|
+
placeholder: t2("billing.subscriptions.idPlaceholder"),
|
|
2243
2352
|
style: { ...styles.input, width: 220 },
|
|
2244
|
-
"aria-label": "
|
|
2353
|
+
"aria-label": t2("billing.subscriptions.idLabel")
|
|
2245
2354
|
}
|
|
2246
2355
|
),
|
|
2247
2356
|
/* @__PURE__ */ jsxs14("button", { type: "submit", style: styles.button, disabled: !idInput.trim(), children: [
|
|
2248
2357
|
/* @__PURE__ */ jsx14(Icon, { name: "search", size: 14 }),
|
|
2249
|
-
"
|
|
2358
|
+
t2("common.open")
|
|
2250
2359
|
] })
|
|
2251
2360
|
]
|
|
2252
2361
|
}
|
|
2253
2362
|
)
|
|
2254
2363
|
] }),
|
|
2255
2364
|
list.error ? /* @__PURE__ */ jsx14("p", { style: styles.error, role: "alert", children: list.error.explanation }) : null,
|
|
2256
|
-
rows.length === 0 && !list.isLoading ? /* @__PURE__ */ jsx14(
|
|
2257
|
-
Empty,
|
|
2258
|
-
{
|
|
2259
|
-
icon: "subscriber",
|
|
2260
|
-
title: filter === "All" ? "No subscriptions yet" : `No ${filter.toLowerCase()} subscriptions`,
|
|
2261
|
-
children: "Subscriptions appear here once someone checks out."
|
|
2262
|
-
}
|
|
2263
|
-
) : /* @__PURE__ */ jsxs14("table", { style: styles.table, children: [
|
|
2365
|
+
rows.length === 0 && !list.isLoading ? /* @__PURE__ */ jsx14(Empty, { icon: "subscriber", title: t2(`billing.subscriptions.empty.${filter}`), children: t2("billing.subscriptions.emptyHint") }) : /* @__PURE__ */ jsxs14("table", { style: styles.table, children: [
|
|
2264
2366
|
/* @__PURE__ */ jsx14("thead", { children: /* @__PURE__ */ jsxs14("tr", { children: [
|
|
2265
|
-
/* @__PURE__ */ jsx14("th", { style: styles.th, children: "
|
|
2266
|
-
/* @__PURE__ */ jsx14("th", { style: styles.th, children: "
|
|
2267
|
-
/* @__PURE__ */ jsx14("th", { style: styles.th, children: "
|
|
2268
|
-
/* @__PURE__ */ jsx14("th", { style: styles.th, children: "
|
|
2367
|
+
/* @__PURE__ */ jsx14("th", { style: styles.th, children: t2("billing.subscriptions.col.subscriber") }),
|
|
2368
|
+
/* @__PURE__ */ jsx14("th", { style: styles.th, children: t2("billing.subscriptions.col.plan") }),
|
|
2369
|
+
/* @__PURE__ */ jsx14("th", { style: styles.th, children: t2("billing.subscriptions.col.status") }),
|
|
2370
|
+
/* @__PURE__ */ jsx14("th", { style: styles.th, children: t2("billing.subscriptions.col.renewsEnds") })
|
|
2269
2371
|
] }) }),
|
|
2270
2372
|
/* @__PURE__ */ jsx14("tbody", { children: rows.map((s) => {
|
|
2271
|
-
const end = periodEnd(s);
|
|
2373
|
+
const end = periodEnd(s, locale);
|
|
2272
2374
|
return /* @__PURE__ */ jsxs14("tr", { children: [
|
|
2273
2375
|
/* @__PURE__ */ jsx14("td", { style: styles.td, children: /* @__PURE__ */ jsxs14(
|
|
2274
2376
|
"button",
|
|
@@ -2288,14 +2390,14 @@ function SubscriberScreen({ client, pageSize = 50, onOpenUser }) {
|
|
|
2288
2390
|
" ",
|
|
2289
2391
|
/* @__PURE__ */ jsxs14("span", { style: styles.muted, children: [
|
|
2290
2392
|
"\xB7 ",
|
|
2291
|
-
s.interval
|
|
2393
|
+
intervalLabel(t2, s.interval)
|
|
2292
2394
|
] })
|
|
2293
2395
|
] }),
|
|
2294
2396
|
/* @__PURE__ */ jsxs14("td", { style: styles.td, children: [
|
|
2295
|
-
/* @__PURE__ */ jsx14(Pill, { tone: statusTone(s.status), children: s.status }),
|
|
2397
|
+
/* @__PURE__ */ jsx14(Pill, { tone: statusTone(s.status), children: statusLabel(t2, s.status) }),
|
|
2296
2398
|
s.cancelAtPeriodEnd && s.status !== "canceled" ? /* @__PURE__ */ jsxs14(Fragment9, { children: [
|
|
2297
2399
|
" ",
|
|
2298
|
-
/* @__PURE__ */ jsx14(Pill, { tone: "warn", dot: false, children: "cancels" })
|
|
2400
|
+
/* @__PURE__ */ jsx14(Pill, { tone: "warn", dot: false, children: t2("billing.subscriptions.cancels") })
|
|
2299
2401
|
] }) : null
|
|
2300
2402
|
] }),
|
|
2301
2403
|
/* @__PURE__ */ jsx14("td", { style: { ...styles.td, whiteSpace: "nowrap" }, children: end ? /* @__PURE__ */ jsxs14(Fragment9, { children: [
|
|
@@ -2306,24 +2408,29 @@ function SubscriberScreen({ client, pageSize = 50, onOpenUser }) {
|
|
|
2306
2408
|
] }, s.id);
|
|
2307
2409
|
}) })
|
|
2308
2410
|
] }),
|
|
2309
|
-
list.isLoading ? /* @__PURE__ */ jsx14("p", { style: styles.status, children: "
|
|
2411
|
+
list.isLoading ? /* @__PURE__ */ jsx14("p", { style: styles.status, children: t2("common.loading") }) : null,
|
|
2310
2412
|
list.hasMore && !list.isLoading ? /* @__PURE__ */ jsx14(
|
|
2311
2413
|
"button",
|
|
2312
2414
|
{
|
|
2313
2415
|
type: "button",
|
|
2314
2416
|
style: { ...styles.button, marginTop: 8 },
|
|
2315
2417
|
onClick: () => void list.loadMore(),
|
|
2316
|
-
children: "
|
|
2418
|
+
children: t2("common.loadMore")
|
|
2317
2419
|
}
|
|
2318
2420
|
) : null
|
|
2319
2421
|
] });
|
|
2320
2422
|
}
|
|
2321
2423
|
|
|
2322
2424
|
// src/screens/AuditScreen.tsx
|
|
2425
|
+
import {
|
|
2426
|
+
createAdminT as createAdminT15,
|
|
2427
|
+
formatAdminDate as formatAdminDate8
|
|
2428
|
+
} from "@fonderie/client";
|
|
2323
2429
|
import { useAdminAudit } from "@fonderie/react-admin";
|
|
2324
2430
|
import { useState as useState8 } from "react";
|
|
2325
2431
|
import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2326
|
-
function AuditScreen({ client, pageSize = 50 }) {
|
|
2432
|
+
function AuditScreen({ client, pageSize = 50, locale }) {
|
|
2433
|
+
const t2 = createAdminT15(locale);
|
|
2327
2434
|
const [draft, setDraft] = useState8({ workspaceId: "", type: "", actorId: "", from: "", to: "" });
|
|
2328
2435
|
const [filter, setFilter] = useState8({});
|
|
2329
2436
|
const { events, hasMore, isLoading, error, refresh, loadMore } = useAdminAudit(client, {
|
|
@@ -2341,13 +2448,7 @@ function AuditScreen({ client, pageSize = 50 }) {
|
|
|
2341
2448
|
}
|
|
2342
2449
|
);
|
|
2343
2450
|
return /* @__PURE__ */ jsxs15("div", { style: styles.container, children: [
|
|
2344
|
-
/* @__PURE__ */ jsx15(
|
|
2345
|
-
PageHeader,
|
|
2346
|
-
{
|
|
2347
|
-
title: "Audit",
|
|
2348
|
-
lead: "What happened, across every workspace unless you name one. The chain's integrity verdict is on the Doctor page."
|
|
2349
|
-
}
|
|
2350
|
-
),
|
|
2451
|
+
/* @__PURE__ */ jsx15(PageHeader, { title: t2("audit.title"), lead: t2("audit.lead") }),
|
|
2351
2452
|
/* @__PURE__ */ jsxs15(
|
|
2352
2453
|
"form",
|
|
2353
2454
|
{
|
|
@@ -2364,9 +2465,9 @@ function AuditScreen({ client, pageSize = 50 }) {
|
|
|
2364
2465
|
});
|
|
2365
2466
|
},
|
|
2366
2467
|
children: [
|
|
2367
|
-
field("workspaceId",
|
|
2368
|
-
field("type", "
|
|
2369
|
-
field("actorId", "
|
|
2468
|
+
field("workspaceId", t2("audit.workspacePlaceholder")),
|
|
2469
|
+
field("type", t2("audit.typePlaceholder")),
|
|
2470
|
+
field("actorId", t2("audit.actorPlaceholder")),
|
|
2370
2471
|
/* @__PURE__ */ jsx15(
|
|
2371
2472
|
"input",
|
|
2372
2473
|
{
|
|
@@ -2374,8 +2475,8 @@ function AuditScreen({ client, pageSize = 50 }) {
|
|
|
2374
2475
|
value: draft.from,
|
|
2375
2476
|
onChange: (e) => setDraft({ ...draft, from: e.target.value }),
|
|
2376
2477
|
style: styles.input,
|
|
2377
|
-
"aria-label": "
|
|
2378
|
-
title: "
|
|
2478
|
+
"aria-label": t2("audit.fromLabel"),
|
|
2479
|
+
title: t2("audit.fromTitle")
|
|
2379
2480
|
}
|
|
2380
2481
|
),
|
|
2381
2482
|
/* @__PURE__ */ jsx15(
|
|
@@ -2385,13 +2486,13 @@ function AuditScreen({ client, pageSize = 50 }) {
|
|
|
2385
2486
|
value: draft.to,
|
|
2386
2487
|
onChange: (e) => setDraft({ ...draft, to: e.target.value }),
|
|
2387
2488
|
style: styles.input,
|
|
2388
|
-
"aria-label": "
|
|
2389
|
-
title: "
|
|
2489
|
+
"aria-label": t2("audit.toLabel"),
|
|
2490
|
+
title: t2("audit.toTitle")
|
|
2390
2491
|
}
|
|
2391
2492
|
),
|
|
2392
2493
|
/* @__PURE__ */ jsxs15("button", { type: "submit", style: styles.buttonPrimary, disabled: isLoading, children: [
|
|
2393
2494
|
/* @__PURE__ */ jsx15(Icon, { name: "search", size: 14 }),
|
|
2394
|
-
"
|
|
2495
|
+
t2("common.filter")
|
|
2395
2496
|
] }),
|
|
2396
2497
|
/* @__PURE__ */ jsx15(
|
|
2397
2498
|
"button",
|
|
@@ -2400,37 +2501,37 @@ function AuditScreen({ client, pageSize = 50 }) {
|
|
|
2400
2501
|
style: styles.button,
|
|
2401
2502
|
onClick: () => void refresh(),
|
|
2402
2503
|
disabled: isLoading,
|
|
2403
|
-
children: "
|
|
2504
|
+
children: t2("common.refresh")
|
|
2404
2505
|
}
|
|
2405
2506
|
)
|
|
2406
2507
|
]
|
|
2407
2508
|
}
|
|
2408
2509
|
),
|
|
2409
2510
|
error ? /* @__PURE__ */ jsx15("p", { style: styles.error, role: "alert", children: error.explanation }) : null,
|
|
2410
|
-
events.length === 0 && !isLoading ? /* @__PURE__ */ jsx15(Empty, { icon: "audit", title: "
|
|
2511
|
+
events.length === 0 && !isLoading ? /* @__PURE__ */ jsx15(Empty, { icon: "audit", title: t2("audit.empty") }) : /* @__PURE__ */ jsxs15("table", { style: styles.table, children: [
|
|
2411
2512
|
/* @__PURE__ */ jsx15("thead", { children: /* @__PURE__ */ jsxs15("tr", { children: [
|
|
2412
|
-
/* @__PURE__ */ jsx15("th", { style: styles.th, children: "
|
|
2413
|
-
/* @__PURE__ */ jsx15("th", { style: styles.th, children: "
|
|
2414
|
-
/* @__PURE__ */ jsx15("th", { style: styles.th, children: "
|
|
2415
|
-
/* @__PURE__ */ jsx15("th", { style: styles.th, children: "
|
|
2416
|
-
/* @__PURE__ */ jsx15("th", { style: styles.th, children: "
|
|
2513
|
+
/* @__PURE__ */ jsx15("th", { style: styles.th, children: t2("audit.col.when") }),
|
|
2514
|
+
/* @__PURE__ */ jsx15("th", { style: styles.th, children: t2("audit.col.type") }),
|
|
2515
|
+
/* @__PURE__ */ jsx15("th", { style: styles.th, children: t2("audit.col.workspace") }),
|
|
2516
|
+
/* @__PURE__ */ jsx15("th", { style: styles.th, children: t2("audit.col.actor") }),
|
|
2517
|
+
/* @__PURE__ */ jsx15("th", { style: styles.th, children: t2("audit.col.request") })
|
|
2417
2518
|
] }) }),
|
|
2418
2519
|
/* @__PURE__ */ jsx15("tbody", { children: events.map((e) => /* @__PURE__ */ jsxs15("tr", { children: [
|
|
2419
|
-
/* @__PURE__ */ jsx15("td", { style: { ...styles.td, ...styles.muted }, children:
|
|
2520
|
+
/* @__PURE__ */ jsx15("td", { style: { ...styles.td, ...styles.muted }, children: formatAdminDate8(e.createdAt, locale) }),
|
|
2420
2521
|
/* @__PURE__ */ jsx15("td", { style: { ...styles.td, ...styles.mono }, children: e.type }),
|
|
2421
2522
|
/* @__PURE__ */ jsx15("td", { style: { ...styles.td, ...styles.mono }, children: String(e.payload["workspaceId"] ?? "\u2014") }),
|
|
2422
2523
|
/* @__PURE__ */ jsx15("td", { style: { ...styles.td, ...styles.mono }, children: e.actorId ?? "\u2014" }),
|
|
2423
2524
|
/* @__PURE__ */ jsx15("td", { style: { ...styles.td, ...styles.muted }, children: e.requestId ?? "" })
|
|
2424
2525
|
] }, e.id)) })
|
|
2425
2526
|
] }),
|
|
2426
|
-
isLoading ? /* @__PURE__ */ jsx15("p", { style: styles.status, children: "
|
|
2527
|
+
isLoading ? /* @__PURE__ */ jsx15("p", { style: styles.status, children: t2("common.loading") }) : null,
|
|
2427
2528
|
hasMore && !isLoading ? /* @__PURE__ */ jsx15(
|
|
2428
2529
|
"button",
|
|
2429
2530
|
{
|
|
2430
2531
|
type: "button",
|
|
2431
2532
|
style: { ...styles.button, marginTop: 8 },
|
|
2432
2533
|
onClick: () => void loadMore(),
|
|
2433
|
-
children: "
|
|
2534
|
+
children: t2("common.loadMore")
|
|
2434
2535
|
}
|
|
2435
2536
|
) : null
|
|
2436
2537
|
] });
|
|
@@ -2468,34 +2569,43 @@ function useNarrow() {
|
|
|
2468
2569
|
return narrow;
|
|
2469
2570
|
}
|
|
2470
2571
|
var NAV = [
|
|
2471
|
-
{ group: "
|
|
2572
|
+
{ group: "nav.groups.today", items: [{ page: "attention", label: "nav.items.attention" }] },
|
|
2472
2573
|
{
|
|
2473
|
-
group: "
|
|
2574
|
+
group: "nav.groups.system",
|
|
2474
2575
|
items: [
|
|
2475
|
-
{ page: "modules", label: "
|
|
2476
|
-
{ page: "environment", label: "
|
|
2477
|
-
{ page: "doctor", label: "
|
|
2478
|
-
{ page: "routes", label: "
|
|
2576
|
+
{ page: "modules", label: "nav.items.modules" },
|
|
2577
|
+
{ page: "environment", label: "nav.items.environment" },
|
|
2578
|
+
{ page: "doctor", label: "nav.items.doctor" },
|
|
2579
|
+
{ page: "routes", label: "nav.items.routes" }
|
|
2479
2580
|
]
|
|
2480
2581
|
},
|
|
2481
|
-
{ group: "People", items: [{ page: "users", label: "Users", needs: "auth" }] },
|
|
2482
2582
|
{
|
|
2483
|
-
group: "
|
|
2583
|
+
group: "nav.groups.people",
|
|
2584
|
+
items: [{ page: "users", label: "nav.items.users", needs: "auth" }]
|
|
2585
|
+
},
|
|
2586
|
+
{
|
|
2587
|
+
group: "nav.groups.money",
|
|
2484
2588
|
items: [
|
|
2485
|
-
{ page: "catalog", label: "
|
|
2486
|
-
{ page: "subscriber", label: "
|
|
2589
|
+
{ page: "catalog", label: "nav.items.catalog", needs: "billing" },
|
|
2590
|
+
{ page: "subscriber", label: "nav.items.subscriptions", needs: "billing" }
|
|
2487
2591
|
]
|
|
2488
2592
|
},
|
|
2489
|
-
{ group: "Settings", items: [{ page: "settings", label: "Config & secrets", needs: "config" }] },
|
|
2490
|
-
{ group: "Messaging", items: [{ page: "templates", label: "Templates", needs: "courier" }] },
|
|
2491
2593
|
{
|
|
2492
|
-
group: "
|
|
2594
|
+
group: "nav.groups.settings",
|
|
2595
|
+
items: [{ page: "settings", label: "nav.items.settings", needs: "config" }]
|
|
2596
|
+
},
|
|
2597
|
+
{
|
|
2598
|
+
group: "nav.groups.messaging",
|
|
2599
|
+
items: [{ page: "templates", label: "nav.items.templates", needs: "courier" }]
|
|
2600
|
+
},
|
|
2601
|
+
{
|
|
2602
|
+
group: "nav.groups.activity",
|
|
2493
2603
|
items: [
|
|
2494
|
-
{ page: "audit", label: "
|
|
2495
|
-
{ page: "log", label: "
|
|
2496
|
-
{ page: "operators", label: "
|
|
2497
|
-
{ page: "tokens", label: "
|
|
2498
|
-
{ page: "migrations", label: "
|
|
2604
|
+
{ page: "audit", label: "nav.items.audit", needs: "audit" },
|
|
2605
|
+
{ page: "log", label: "nav.items.log" },
|
|
2606
|
+
{ page: "operators", label: "nav.items.operators", needs: "operators" },
|
|
2607
|
+
{ page: "tokens", label: "nav.items.tokens" },
|
|
2608
|
+
{ page: "migrations", label: "nav.items.migrations" }
|
|
2499
2609
|
]
|
|
2500
2610
|
}
|
|
2501
2611
|
];
|
|
@@ -2514,8 +2624,10 @@ function AdminShell({
|
|
|
2514
2624
|
footer,
|
|
2515
2625
|
operators = false,
|
|
2516
2626
|
currentOperator,
|
|
2517
|
-
publicConfigUrl
|
|
2627
|
+
publicConfigUrl,
|
|
2628
|
+
locale
|
|
2518
2629
|
}) {
|
|
2630
|
+
const t2 = createAdminT16(locale);
|
|
2519
2631
|
const narrow = useNarrow();
|
|
2520
2632
|
const [drawer, setDrawer] = useState9(false);
|
|
2521
2633
|
const [own, setOwn] = useState9("attention");
|
|
@@ -2538,40 +2650,41 @@ function AdminShell({
|
|
|
2538
2650
|
let body;
|
|
2539
2651
|
switch (current) {
|
|
2540
2652
|
case "attention":
|
|
2541
|
-
body = /* @__PURE__ */ jsx16(AttentionScreen, { client });
|
|
2653
|
+
body = /* @__PURE__ */ jsx16(AttentionScreen, { client, locale });
|
|
2542
2654
|
break;
|
|
2543
2655
|
case "modules":
|
|
2544
|
-
body = /* @__PURE__ */ jsx16(ModulesScreen, { client });
|
|
2656
|
+
body = /* @__PURE__ */ jsx16(ModulesScreen, { client, locale });
|
|
2545
2657
|
break;
|
|
2546
2658
|
case "doctor":
|
|
2547
|
-
body = /* @__PURE__ */ jsx16(DoctorScreen, { client });
|
|
2659
|
+
body = /* @__PURE__ */ jsx16(DoctorScreen, { client, locale });
|
|
2548
2660
|
break;
|
|
2549
2661
|
case "environment":
|
|
2550
|
-
body = /* @__PURE__ */ jsx16(EnvironmentScreen, { client });
|
|
2662
|
+
body = /* @__PURE__ */ jsx16(EnvironmentScreen, { client, locale });
|
|
2551
2663
|
break;
|
|
2552
2664
|
case "routes":
|
|
2553
|
-
body = /* @__PURE__ */ jsx16(RoutesScreen, { client });
|
|
2665
|
+
body = /* @__PURE__ */ jsx16(RoutesScreen, { client, locale });
|
|
2554
2666
|
break;
|
|
2555
2667
|
case "tokens":
|
|
2556
|
-
body = /* @__PURE__ */ jsx16(TokensScreen, { client });
|
|
2668
|
+
body = /* @__PURE__ */ jsx16(TokensScreen, { client, locale });
|
|
2557
2669
|
break;
|
|
2558
2670
|
case "operators":
|
|
2559
|
-
body = /* @__PURE__ */ jsx16(OperatorsScreen, { client, me: currentOperator });
|
|
2671
|
+
body = /* @__PURE__ */ jsx16(OperatorsScreen, { client, me: currentOperator, locale });
|
|
2560
2672
|
break;
|
|
2561
2673
|
case "migrations":
|
|
2562
|
-
body = /* @__PURE__ */ jsx16(MigrationsScreen, { client });
|
|
2674
|
+
body = /* @__PURE__ */ jsx16(MigrationsScreen, { client, locale });
|
|
2563
2675
|
break;
|
|
2564
2676
|
case "log":
|
|
2565
|
-
body = /* @__PURE__ */ jsx16(AdminLogScreen, { client });
|
|
2677
|
+
body = /* @__PURE__ */ jsx16(AdminLogScreen, { client, locale });
|
|
2566
2678
|
break;
|
|
2567
2679
|
case "catalog":
|
|
2568
|
-
body = billingClient ? /* @__PURE__ */ jsx16(CatalogScreen, { client: billingClient }) : /* @__PURE__ */ jsx16("p", { style: { ...styles.status, padding: "32px 40px" }, children: "
|
|
2680
|
+
body = billingClient ? /* @__PURE__ */ jsx16(CatalogScreen, { client: billingClient, locale }) : /* @__PURE__ */ jsx16("p", { style: { ...styles.status, padding: "32px 40px" }, children: t2("shell.missingClient", { client: "BillingAdminClient" }) });
|
|
2569
2681
|
break;
|
|
2570
2682
|
case "subscriber":
|
|
2571
2683
|
body = billingClient ? /* @__PURE__ */ jsx16(
|
|
2572
2684
|
SubscriberScreen,
|
|
2573
2685
|
{
|
|
2574
2686
|
client: billingClient,
|
|
2687
|
+
locale,
|
|
2575
2688
|
...authClient ? {
|
|
2576
2689
|
onOpenUser: (id) => {
|
|
2577
2690
|
setOpenUser(id);
|
|
@@ -2579,10 +2692,10 @@ function AdminShell({
|
|
|
2579
2692
|
}
|
|
2580
2693
|
} : {}
|
|
2581
2694
|
}
|
|
2582
|
-
) : /* @__PURE__ */ jsx16("p", { style: { ...styles.status, padding: "32px 40px" }, children: "
|
|
2695
|
+
) : /* @__PURE__ */ jsx16("p", { style: { ...styles.status, padding: "32px 40px" }, children: t2("shell.missingClient", { client: "BillingAdminClient" }) });
|
|
2583
2696
|
break;
|
|
2584
2697
|
case "audit":
|
|
2585
|
-
body = auditClient ? /* @__PURE__ */ jsx16(AuditScreen, { client: auditClient }) : /* @__PURE__ */ jsx16("p", { style: { ...styles.status, padding: "32px 40px" }, children: "
|
|
2698
|
+
body = auditClient ? /* @__PURE__ */ jsx16(AuditScreen, { client: auditClient, locale }) : /* @__PURE__ */ jsx16("p", { style: { ...styles.status, padding: "32px 40px" }, children: t2("shell.missingClient", { client: "AuditAdminClient" }) });
|
|
2586
2699
|
break;
|
|
2587
2700
|
case "users":
|
|
2588
2701
|
body = authClient ? /* @__PURE__ */ jsx16(
|
|
@@ -2590,16 +2703,17 @@ function AdminShell({
|
|
|
2590
2703
|
{
|
|
2591
2704
|
client: authClient,
|
|
2592
2705
|
billingClient,
|
|
2593
|
-
openUserId: openUser
|
|
2706
|
+
openUserId: openUser,
|
|
2707
|
+
locale
|
|
2594
2708
|
},
|
|
2595
2709
|
openUser ?? "list"
|
|
2596
|
-
) : /* @__PURE__ */ jsx16("p", { style: { ...styles.status, padding: "32px 40px" }, children: "
|
|
2710
|
+
) : /* @__PURE__ */ jsx16("p", { style: { ...styles.status, padding: "32px 40px" }, children: t2("shell.missingClient", { client: "AuthAdminClient" }) });
|
|
2597
2711
|
break;
|
|
2598
2712
|
case "settings":
|
|
2599
|
-
body = !configClient ? /* @__PURE__ */ jsx16("p", { style: { ...styles.status, padding: "32px 40px" }, children: "
|
|
2713
|
+
body = !configClient ? /* @__PURE__ */ jsx16("p", { style: { ...styles.status, padding: "32px 40px" }, children: t2("shell.missingClient", { client: "ConfigAdminClient" }) }) : editing && (editing.kind === "config" || editing.kind === "secret") ? /* @__PURE__ */ jsxs16(Fragment10, { children: [
|
|
2600
2714
|
/* @__PURE__ */ jsx16("div", { style: { padding: "24px 40px 0" }, children: /* @__PURE__ */ jsxs16("button", { type: "button", style: styles.buttonGhost, onClick: () => setEditing(null), children: [
|
|
2601
2715
|
/* @__PURE__ */ jsx16(Icon, { name: "back", size: 14 }),
|
|
2602
|
-
"
|
|
2716
|
+
t2("nav.items.settings")
|
|
2603
2717
|
] }) }),
|
|
2604
2718
|
/* @__PURE__ */ jsx16(
|
|
2605
2719
|
ConfigEditorScreen,
|
|
@@ -2610,7 +2724,8 @@ function AdminShell({
|
|
|
2610
2724
|
...editing.environment !== void 0 ? { environment: editing.environment } : environment !== void 0 ? { environment } : {},
|
|
2611
2725
|
...editing.environments ? { environments: editing.environments } : {},
|
|
2612
2726
|
onSaved: () => setEditing(null),
|
|
2613
|
-
onDeleted: () => setEditing(null)
|
|
2727
|
+
onDeleted: () => setEditing(null),
|
|
2728
|
+
locale
|
|
2614
2729
|
},
|
|
2615
2730
|
`${editing.kind}:${editing.key}:${editing.environment ?? ""}`
|
|
2616
2731
|
)
|
|
@@ -2618,6 +2733,7 @@ function AdminShell({
|
|
|
2618
2733
|
ConfigListScreen,
|
|
2619
2734
|
{
|
|
2620
2735
|
client: configClient,
|
|
2736
|
+
locale,
|
|
2621
2737
|
...environment !== void 0 ? { environment } : {},
|
|
2622
2738
|
...publicConfigUrl ? { publicConfigUrl } : {},
|
|
2623
2739
|
onSelectConfig: (key, env) => setEditing({ kind: "config", key, environment: env }),
|
|
@@ -2638,15 +2754,16 @@ function AdminShell({
|
|
|
2638
2754
|
);
|
|
2639
2755
|
break;
|
|
2640
2756
|
case "templates":
|
|
2641
|
-
body = !courierClient ? /* @__PURE__ */ jsx16("p", { style: { ...styles.status, padding: "32px 40px" }, children: "
|
|
2757
|
+
body = !courierClient ? /* @__PURE__ */ jsx16("p", { style: { ...styles.status, padding: "32px 40px" }, children: t2("shell.missingClient", { client: "CourierAdminClient" }) }) : editing?.kind === "template-new" ? /* @__PURE__ */ jsxs16(Fragment10, { children: [
|
|
2642
2758
|
/* @__PURE__ */ jsx16("div", { style: { padding: "24px 40px 0" }, children: /* @__PURE__ */ jsxs16("button", { type: "button", style: styles.buttonGhost, onClick: () => setEditing(null), children: [
|
|
2643
2759
|
/* @__PURE__ */ jsx16(Icon, { name: "back", size: 14 }),
|
|
2644
|
-
"
|
|
2760
|
+
t2("nav.items.templates")
|
|
2645
2761
|
] }) }),
|
|
2646
2762
|
/* @__PURE__ */ jsx16(
|
|
2647
2763
|
TemplateCreateScreen,
|
|
2648
2764
|
{
|
|
2649
2765
|
client: courierClient,
|
|
2766
|
+
locale,
|
|
2650
2767
|
...editing.type ? { type: editing.type } : {},
|
|
2651
2768
|
...editing.locales ? { locales: editing.locales } : {},
|
|
2652
2769
|
onCreated: (c) => setEditing({ kind: "template", type: c.type, locale: c.locale, system: false })
|
|
@@ -2655,7 +2772,7 @@ function AdminShell({
|
|
|
2655
2772
|
] }) : editing?.kind === "template" ? /* @__PURE__ */ jsxs16(Fragment10, { children: [
|
|
2656
2773
|
/* @__PURE__ */ jsx16("div", { style: { padding: "24px 40px 0" }, children: /* @__PURE__ */ jsxs16("button", { type: "button", style: styles.buttonGhost, onClick: () => setEditing(null), children: [
|
|
2657
2774
|
/* @__PURE__ */ jsx16(Icon, { name: "back", size: 14 }),
|
|
2658
|
-
"
|
|
2775
|
+
t2("nav.items.templates")
|
|
2659
2776
|
] }) }),
|
|
2660
2777
|
/* @__PURE__ */ jsx16(
|
|
2661
2778
|
TemplateEditorScreen,
|
|
@@ -2666,7 +2783,14 @@ function AdminShell({
|
|
|
2666
2783
|
system: editing.system,
|
|
2667
2784
|
onSaved: () => setEditing(null),
|
|
2668
2785
|
onDeleted: () => setEditing(null),
|
|
2669
|
-
onAddLocale: (type) => setEditing({ kind: "template-new", type })
|
|
2786
|
+
onAddLocale: (type, c) => setEditing({ kind: "template-new", type, locales: c.locales }),
|
|
2787
|
+
onSelectLocale: (tpl) => setEditing({
|
|
2788
|
+
kind: "template",
|
|
2789
|
+
type: tpl.type,
|
|
2790
|
+
locale: tpl.locale,
|
|
2791
|
+
system: tpl.system === true
|
|
2792
|
+
}),
|
|
2793
|
+
uiLocale: locale
|
|
2670
2794
|
},
|
|
2671
2795
|
`${editing.type}:${editing.locale ?? ""}`
|
|
2672
2796
|
)
|
|
@@ -2674,11 +2798,12 @@ function AdminShell({
|
|
|
2674
2798
|
TemplateListScreen,
|
|
2675
2799
|
{
|
|
2676
2800
|
client: courierClient,
|
|
2677
|
-
|
|
2801
|
+
locale,
|
|
2802
|
+
onSelectTemplate: (tpl) => setEditing({
|
|
2678
2803
|
kind: "template",
|
|
2679
|
-
type:
|
|
2680
|
-
locale:
|
|
2681
|
-
system:
|
|
2804
|
+
type: tpl.type,
|
|
2805
|
+
locale: tpl.locale ?? null,
|
|
2806
|
+
system: tpl.system === true
|
|
2682
2807
|
}),
|
|
2683
2808
|
onCreateTemplate: (c) => setEditing({ kind: "template-new", locales: c.locales })
|
|
2684
2809
|
}
|
|
@@ -2712,7 +2837,7 @@ function AdminShell({
|
|
|
2712
2837
|
{
|
|
2713
2838
|
type: "button",
|
|
2714
2839
|
style: styles.buttonGhost,
|
|
2715
|
-
"aria-label": "
|
|
2840
|
+
"aria-label": t2("shell.closeMenu"),
|
|
2716
2841
|
onClick: () => setDrawer(false),
|
|
2717
2842
|
children: /* @__PURE__ */ jsx16(Icon, { name: "close" })
|
|
2718
2843
|
}
|
|
@@ -2725,14 +2850,14 @@ function AdminShell({
|
|
|
2725
2850
|
...styles.nav,
|
|
2726
2851
|
...narrow ? { width: 280, maxWidth: "85vw", boxShadow: "0 10px 40px rgba(0,0,0,.25)" } : {}
|
|
2727
2852
|
},
|
|
2728
|
-
"aria-label": "
|
|
2853
|
+
"aria-label": t2("shell.navLabel"),
|
|
2729
2854
|
children: [
|
|
2730
2855
|
brand,
|
|
2731
2856
|
/* @__PURE__ */ jsx16("div", { style: styles.navScroll, children: NAV.map((g) => {
|
|
2732
2857
|
const items = g.items.filter((i) => !i.needs || has[i.needs]);
|
|
2733
2858
|
if (items.length === 0) return null;
|
|
2734
2859
|
return /* @__PURE__ */ jsxs16("div", { children: [
|
|
2735
|
-
/* @__PURE__ */ jsx16("div", { style: styles.navGroup, children: g.group }),
|
|
2860
|
+
/* @__PURE__ */ jsx16("div", { style: styles.navGroup, children: t2(g.group) }),
|
|
2736
2861
|
items.map((i) => {
|
|
2737
2862
|
const active = current === i.page;
|
|
2738
2863
|
return /* @__PURE__ */ jsxs16(
|
|
@@ -2749,7 +2874,7 @@ function AdminShell({
|
|
|
2749
2874
|
},
|
|
2750
2875
|
children: [
|
|
2751
2876
|
/* @__PURE__ */ jsx16(Icon, { name: ICON[i.page], style: active ? styles.navIconActive : void 0 }),
|
|
2752
|
-
i.label
|
|
2877
|
+
t2(i.label)
|
|
2753
2878
|
]
|
|
2754
2879
|
},
|
|
2755
2880
|
i.page
|
|
@@ -2761,7 +2886,8 @@ function AdminShell({
|
|
|
2761
2886
|
]
|
|
2762
2887
|
}
|
|
2763
2888
|
);
|
|
2764
|
-
const
|
|
2889
|
+
const titleKey = NAV.flatMap((g) => g.items).find((i) => i.page === current)?.label;
|
|
2890
|
+
const title = titleKey ? t2(titleKey) : "";
|
|
2765
2891
|
return /* @__PURE__ */ jsxs16("div", { style: { ...styles.shell, ...narrow ? { flexDirection: "column" } : {} }, children: [
|
|
2766
2892
|
narrow ? /* @__PURE__ */ jsxs16(Fragment10, { children: [
|
|
2767
2893
|
/* @__PURE__ */ jsxs16("div", { style: styles.topbar, children: [
|
|
@@ -2770,7 +2896,7 @@ function AdminShell({
|
|
|
2770
2896
|
{
|
|
2771
2897
|
type: "button",
|
|
2772
2898
|
style: styles.buttonGhost,
|
|
2773
|
-
"aria-label": "
|
|
2899
|
+
"aria-label": t2("shell.openMenu"),
|
|
2774
2900
|
"aria-expanded": drawer,
|
|
2775
2901
|
onClick: () => setDrawer(true),
|
|
2776
2902
|
children: /* @__PURE__ */ jsx16(Icon, { name: "menu" })
|