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