@fonderie/react-admin-screens 1.4.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +663 -474
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -16
- package/dist/index.d.ts +32 -16
- package/dist/index.js +696 -472
- 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,21 +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 }) {
|
|
1592
|
-
const
|
|
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;
|
|
1647
|
+
const [currency, setCurrency] = (0, import_react5.useState)("");
|
|
1648
|
+
const [currencyDraft, setCurrencyDraft] = (0, import_react5.useState)("");
|
|
1649
|
+
const { subscription, wallet, ledger, hasMoreLedger, isLoading, error, loadMoreLedger, grant } = (0, import_react_admin10.useAdminSubscriber)(client, subscriber, { limit: 20, ...currency ? { currency } : {} });
|
|
1593
1650
|
const [amount, setAmount] = (0, import_react5.useState)("");
|
|
1594
1651
|
const [note, setNote] = (0, import_react5.useState)("");
|
|
1595
1652
|
const [granted, setGranted] = (0, import_react5.useState)(null);
|
|
1596
|
-
if (isLoading && !wallet && !subscription)
|
|
1597
|
-
|
|
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;
|
|
1598
1656
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
1599
1657
|
error ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: styles.error, role: "alert", children: error.explanation }) : null,
|
|
1600
1658
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { ...styles.grid, marginBottom: 16 }, children: [
|
|
1601
1659
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.card, children: [
|
|
1602
|
-
/* @__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") }),
|
|
1603
1661
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1604
1662
|
"div",
|
|
1605
1663
|
{
|
|
@@ -1611,14 +1669,14 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1611
1669
|
flexWrap: "wrap"
|
|
1612
1670
|
},
|
|
1613
1671
|
children: [
|
|
1614
|
-
/* @__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") }),
|
|
1615
1673
|
subscription ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
1616
1674
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { style: styles.muted, children: [
|
|
1617
1675
|
"\xB7 ",
|
|
1618
|
-
subscription.interval
|
|
1676
|
+
intervalLabel(t2, subscription.interval)
|
|
1619
1677
|
] }),
|
|
1620
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Pill, { tone: statusTone(subscription.status), children: subscription.status })
|
|
1621
|
-
] }) : /* @__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") })
|
|
1622
1680
|
]
|
|
1623
1681
|
}
|
|
1624
1682
|
),
|
|
@@ -1630,7 +1688,42 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1630
1688
|
subscription?.providerSubscriptionId ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { ...styles.statHint, fontFamily: "var(--fonderie-mono,monospace)" }, children: subscription.providerSubscriptionId }) : null
|
|
1631
1689
|
] }),
|
|
1632
1690
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.card, children: [
|
|
1633
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.
|
|
1691
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
1692
|
+
"div",
|
|
1693
|
+
{
|
|
1694
|
+
style: {
|
|
1695
|
+
display: "flex",
|
|
1696
|
+
justifyContent: "space-between",
|
|
1697
|
+
alignItems: "center",
|
|
1698
|
+
gap: 8
|
|
1699
|
+
},
|
|
1700
|
+
children: [
|
|
1701
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: styles.statLabel, children: t2("billing.credits") }),
|
|
1702
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1703
|
+
"form",
|
|
1704
|
+
{
|
|
1705
|
+
style: { display: "flex", gap: 4 },
|
|
1706
|
+
onSubmit: (e) => {
|
|
1707
|
+
e.preventDefault();
|
|
1708
|
+
setCurrency(currencyDraft.trim().toUpperCase());
|
|
1709
|
+
},
|
|
1710
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1711
|
+
"input",
|
|
1712
|
+
{
|
|
1713
|
+
value: currencyDraft,
|
|
1714
|
+
onChange: (e) => setCurrencyDraft(e.target.value),
|
|
1715
|
+
placeholder: wallet?.currency ?? t2("billing.currencyPlaceholder"),
|
|
1716
|
+
maxLength: 8,
|
|
1717
|
+
style: { ...styles.input, height: 26, width: 84, fontSize: 12 },
|
|
1718
|
+
"aria-label": t2("billing.currencyLabel"),
|
|
1719
|
+
title: t2("billing.currencyTitle")
|
|
1720
|
+
}
|
|
1721
|
+
)
|
|
1722
|
+
}
|
|
1723
|
+
)
|
|
1724
|
+
]
|
|
1725
|
+
}
|
|
1726
|
+
),
|
|
1634
1727
|
wallet ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
1635
1728
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.statValue, children: [
|
|
1636
1729
|
wallet.balance,
|
|
@@ -1638,13 +1731,15 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1638
1731
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { fontSize: 14, fontWeight: 500 }, children: wallet.currency })
|
|
1639
1732
|
] }),
|
|
1640
1733
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: styles.statHint, children: [
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
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
|
+
}) : ""
|
|
1646
1741
|
] })
|
|
1647
|
-
] }) : /* @__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") })
|
|
1648
1743
|
] })
|
|
1649
1744
|
] }),
|
|
1650
1745
|
wallet ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
@@ -1666,23 +1761,25 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1666
1761
|
...note ? { description: note } : {},
|
|
1667
1762
|
idempotencyKey: key
|
|
1668
1763
|
}).then(() => {
|
|
1669
|
-
setGranted(
|
|
1764
|
+
setGranted(
|
|
1765
|
+
t2("billing.granted", { amount: amount.trim(), currency: wallet.currency })
|
|
1766
|
+
);
|
|
1670
1767
|
setAmount("");
|
|
1671
1768
|
setNote("");
|
|
1672
1769
|
}).catch(() => {
|
|
1673
1770
|
});
|
|
1674
1771
|
},
|
|
1675
1772
|
children: [
|
|
1676
|
-
/* @__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") }),
|
|
1677
1774
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1678
1775
|
"input",
|
|
1679
1776
|
{
|
|
1680
1777
|
value: amount,
|
|
1681
1778
|
onChange: (e) => setAmount(e.target.value),
|
|
1682
|
-
placeholder:
|
|
1779
|
+
placeholder: t2("billing.amountPlaceholder", { currency: wallet.currency }),
|
|
1683
1780
|
inputMode: "numeric",
|
|
1684
1781
|
style: { ...styles.input, width: 150 },
|
|
1685
|
-
"aria-label": "
|
|
1782
|
+
"aria-label": t2("billing.amountLabel")
|
|
1686
1783
|
}
|
|
1687
1784
|
),
|
|
1688
1785
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
@@ -1690,9 +1787,9 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1690
1787
|
{
|
|
1691
1788
|
value: note,
|
|
1692
1789
|
onChange: (e) => setNote(e.target.value),
|
|
1693
|
-
placeholder: "
|
|
1790
|
+
placeholder: t2("billing.reasonPlaceholder"),
|
|
1694
1791
|
style: { ...styles.input, flex: 1, minWidth: 180 },
|
|
1695
|
-
"aria-label": "
|
|
1792
|
+
"aria-label": t2("billing.reasonLabel")
|
|
1696
1793
|
}
|
|
1697
1794
|
),
|
|
1698
1795
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
@@ -1703,7 +1800,7 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1703
1800
|
disabled: !/^\d+$/.test(amount.trim()),
|
|
1704
1801
|
children: [
|
|
1705
1802
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Icon, { name: "plus", size: 14 }),
|
|
1706
|
-
"
|
|
1803
|
+
t2("billing.grant")
|
|
1707
1804
|
]
|
|
1708
1805
|
}
|
|
1709
1806
|
),
|
|
@@ -1711,20 +1808,20 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1711
1808
|
]
|
|
1712
1809
|
}
|
|
1713
1810
|
) : null,
|
|
1714
|
-
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: [
|
|
1715
1812
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("table", { style: styles.table, children: [
|
|
1716
1813
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("tr", { children: [
|
|
1717
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { style: styles.th, children: "
|
|
1718
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { style: styles.th, children: "
|
|
1719
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("th", { style: styles.th, children: "
|
|
1720
|
-
/* @__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") })
|
|
1721
1818
|
] }) }),
|
|
1722
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tbody", { children: ledger.map((
|
|
1723
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { style: { ...styles.td, ...styles.muted, whiteSpace: "nowrap" }, children:
|
|
1724
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { style: styles.td, children:
|
|
1725
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { style: { ...styles.td, ...styles.mono }, children:
|
|
1726
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("td", { style: { ...styles.td, ...styles.muted }, children:
|
|
1727
|
-
] },
|
|
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)) })
|
|
1728
1825
|
] }),
|
|
1729
1826
|
hasMoreLedger ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1730
1827
|
"button",
|
|
@@ -1732,7 +1829,7 @@ function SubscriberBilling({ client, subscriber }) {
|
|
|
1732
1829
|
type: "button",
|
|
1733
1830
|
style: { ...styles.button, marginTop: 8 },
|
|
1734
1831
|
onClick: () => void loadMoreLedger(),
|
|
1735
|
-
children: "
|
|
1832
|
+
children: t2("common.loadMore")
|
|
1736
1833
|
}
|
|
1737
1834
|
) : null
|
|
1738
1835
|
] }) : null
|
|
@@ -1745,8 +1842,10 @@ function UsersScreen({
|
|
|
1745
1842
|
client,
|
|
1746
1843
|
pageSize = 50,
|
|
1747
1844
|
billingClient,
|
|
1748
|
-
openUserId
|
|
1845
|
+
openUserId,
|
|
1846
|
+
locale
|
|
1749
1847
|
}) {
|
|
1848
|
+
const t2 = (0, import_client12.createAdminT)(locale);
|
|
1750
1849
|
const [input, setInput] = (0, import_react6.useState)("");
|
|
1751
1850
|
const [selected, setSelected] = (0, import_react6.useState)(
|
|
1752
1851
|
openUserId ? { id: openUserId } : null
|
|
@@ -1764,19 +1863,13 @@ function UsersScreen({
|
|
|
1764
1863
|
const userId = user?.id ?? null;
|
|
1765
1864
|
const sessions = (0, import_react_admin11.useAdminUserSessions)(client, userId);
|
|
1766
1865
|
const history = (0, import_react_admin11.useAdminLoginHistory)(client, userId, { limit: 20 });
|
|
1767
|
-
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") });
|
|
1768
1867
|
const clear = () => {
|
|
1769
1868
|
setSelected(null);
|
|
1770
1869
|
setInput("");
|
|
1771
1870
|
};
|
|
1772
1871
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: styles.container, children: [
|
|
1773
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1774
|
-
PageHeader,
|
|
1775
|
-
{
|
|
1776
|
-
title: "Users",
|
|
1777
|
-
lead: "Everyone signed up. Open an account for its sessions, sign-ins and the suspend and sign-out controls."
|
|
1778
|
-
}
|
|
1779
|
-
),
|
|
1872
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PageHeader, { title: t2("users.title"), lead: t2("users.lead") }),
|
|
1780
1873
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1781
1874
|
"form",
|
|
1782
1875
|
{
|
|
@@ -1793,18 +1886,18 @@ function UsersScreen({
|
|
|
1793
1886
|
type: "email",
|
|
1794
1887
|
value: input,
|
|
1795
1888
|
onChange: (e) => setInput(e.target.value),
|
|
1796
|
-
placeholder: "
|
|
1889
|
+
placeholder: t2("users.emailPlaceholder"),
|
|
1797
1890
|
style: { ...styles.input, minWidth: 280 },
|
|
1798
|
-
"aria-label": "
|
|
1891
|
+
"aria-label": t2("users.emailLabel")
|
|
1799
1892
|
}
|
|
1800
1893
|
),
|
|
1801
1894
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { type: "submit", style: styles.buttonPrimary, disabled: isLoading, children: [
|
|
1802
1895
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Icon, { name: "search", size: 14 }),
|
|
1803
|
-
"
|
|
1896
|
+
t2("common.lookUp")
|
|
1804
1897
|
] }),
|
|
1805
1898
|
selected ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("button", { type: "button", style: styles.buttonGhost, onClick: clear, children: [
|
|
1806
1899
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Icon, { name: "back", size: 14 }),
|
|
1807
|
-
"
|
|
1900
|
+
t2("users.allUsers")
|
|
1808
1901
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1809
1902
|
"button",
|
|
1810
1903
|
{
|
|
@@ -1812,7 +1905,7 @@ function UsersScreen({
|
|
|
1812
1905
|
style: styles.button,
|
|
1813
1906
|
onClick: () => void list.refresh(),
|
|
1814
1907
|
disabled: list.isLoading,
|
|
1815
|
-
children: "
|
|
1908
|
+
children: t2("common.refresh")
|
|
1816
1909
|
}
|
|
1817
1910
|
),
|
|
1818
1911
|
!selected ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
@@ -1826,7 +1919,7 @@ function UsersScreen({
|
|
|
1826
1919
|
padding: 0,
|
|
1827
1920
|
minWidth: 0
|
|
1828
1921
|
},
|
|
1829
|
-
"aria-label": "
|
|
1922
|
+
"aria-label": t2("users.whichAccounts"),
|
|
1830
1923
|
children: [false, true].map((d) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1831
1924
|
"button",
|
|
1832
1925
|
{
|
|
@@ -1837,7 +1930,7 @@ function UsersScreen({
|
|
|
1837
1930
|
...showDeleted === d ? styles.buttonPrimary : styles.button,
|
|
1838
1931
|
height: 28
|
|
1839
1932
|
},
|
|
1840
|
-
children: d ? "
|
|
1933
|
+
children: d ? t2("users.deletedAccounts") : t2("users.activeAccounts")
|
|
1841
1934
|
},
|
|
1842
1935
|
String(d)
|
|
1843
1936
|
))
|
|
@@ -1846,34 +1939,39 @@ function UsersScreen({
|
|
|
1846
1939
|
]
|
|
1847
1940
|
}
|
|
1848
1941
|
),
|
|
1849
|
-
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,
|
|
1850
1943
|
error?.status === 404 && selected?.id ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
1851
1944
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: styles.notice, role: "status", children: [
|
|
1852
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.
|
|
1945
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("strong", { children: [
|
|
1946
|
+
t2("users.missingIdPrefix"),
|
|
1947
|
+
" "
|
|
1948
|
+
] }),
|
|
1853
1949
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("code", { style: styles.code, children: selected.id }),
|
|
1854
1950
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("strong", { children: "." }),
|
|
1855
|
-
"
|
|
1951
|
+
" ",
|
|
1952
|
+
t2("users.missingIdBody")
|
|
1856
1953
|
] }),
|
|
1857
1954
|
billingClient ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
1858
|
-
/* @__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") }),
|
|
1859
1956
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1860
1957
|
SubscriberBilling,
|
|
1861
1958
|
{
|
|
1862
1959
|
client: billingClient,
|
|
1863
|
-
subscriber: { type: "user", id: selected.id }
|
|
1960
|
+
subscriber: { type: "user", id: selected.id },
|
|
1961
|
+
locale
|
|
1864
1962
|
}
|
|
1865
1963
|
)
|
|
1866
1964
|
] }) : null
|
|
1867
1965
|
] }) : null,
|
|
1868
1966
|
!selected ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
1869
1967
|
list.error ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { style: styles.error, role: "alert", children: list.error.explanation }) : null,
|
|
1870
|
-
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: [
|
|
1871
1969
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
|
|
1872
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { style: styles.th, children: "
|
|
1873
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { style: styles.th, children: "
|
|
1874
|
-
billingClient ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { style: styles.th, children: "
|
|
1875
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { style: styles.th, children: "
|
|
1876
|
-
/* @__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") })
|
|
1877
1975
|
] }) }),
|
|
1878
1976
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("tbody", { children: list.users.map((u) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
|
|
1879
1977
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { style: styles.td, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
@@ -1890,29 +1988,29 @@ function UsersScreen({
|
|
|
1890
1988
|
const sub = plans?.get(`user/${u.id}`);
|
|
1891
1989
|
if (!plans) return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: styles.muted, children: "\u2026" });
|
|
1892
1990
|
if (!sub || sub.status === "canceled")
|
|
1893
|
-
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") });
|
|
1894
1992
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
1895
1993
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("strong", { children: sub.plan }),
|
|
1896
1994
|
" ",
|
|
1897
|
-
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
|
|
1898
1996
|
] });
|
|
1899
1997
|
})() }) : null,
|
|
1900
|
-
/* @__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") }),
|
|
1901
1999
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("td", { style: styles.td, children: [
|
|
1902
|
-
u.suspended ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Pill, { tone: "warn", children: "suspended" }) : null,
|
|
1903
|
-
u.deletedAt ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Pill, { tone: "neutral", children: "deleted" }) : null,
|
|
1904
|
-
!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
|
|
1905
2003
|
] })
|
|
1906
2004
|
] }, u.id)) })
|
|
1907
2005
|
] }),
|
|
1908
|
-
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,
|
|
1909
2007
|
list.hasMore && !list.isLoading ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1910
2008
|
"button",
|
|
1911
2009
|
{
|
|
1912
2010
|
type: "button",
|
|
1913
2011
|
style: { ...styles.button, marginTop: 8 },
|
|
1914
2012
|
onClick: () => void list.loadMore(),
|
|
1915
|
-
children: "
|
|
2013
|
+
children: t2("common.loadMore")
|
|
1916
2014
|
}
|
|
1917
2015
|
) : null
|
|
1918
2016
|
] }) : null,
|
|
@@ -1920,49 +2018,48 @@ function UsersScreen({
|
|
|
1920
2018
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("h2", { style: styles.subtitle, children: [
|
|
1921
2019
|
user.firstName || user.lastName ? `${user.firstName} ${user.lastName}`.trim() : user.email,
|
|
1922
2020
|
" ",
|
|
1923
|
-
user.suspended ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Pill, { tone: "warn", children: "suspended" }) : null,
|
|
1924
|
-
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
|
|
1925
2023
|
] }),
|
|
1926
2024
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("table", { style: styles.table, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tbody", { children: [
|
|
1927
2025
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
|
|
1928
|
-
/* @__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") }),
|
|
1929
2027
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { style: { ...styles.td, ...styles.mono }, children: user.id })
|
|
1930
2028
|
] }),
|
|
1931
2029
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
|
|
1932
|
-
/* @__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") }),
|
|
1933
2031
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("td", { style: styles.td, children: [
|
|
1934
2032
|
user.email,
|
|
1935
|
-
" \xB7
|
|
2033
|
+
" \xB7 ",
|
|
2034
|
+
t2("users.field.verified"),
|
|
2035
|
+
" ",
|
|
1936
2036
|
yesNo(user.isEmailVerified)
|
|
1937
2037
|
] })
|
|
1938
2038
|
] }),
|
|
1939
2039
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
|
|
1940
|
-
/* @__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") }),
|
|
1941
2041
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { style: styles.td, children: yesNo(user.mfaEnabled) })
|
|
1942
2042
|
] }),
|
|
1943
2043
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
|
|
1944
|
-
/* @__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") }),
|
|
1945
2045
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("td", { style: styles.td, children: [
|
|
1946
|
-
user.provider || "
|
|
1947
|
-
user.hasPassword ? "" :
|
|
2046
|
+
user.provider || t2("users.passwordProvider"),
|
|
2047
|
+
user.hasPassword ? "" : ` \xB7 ${t2("users.noPasswordSet")}`
|
|
1948
2048
|
] })
|
|
1949
2049
|
] }),
|
|
1950
2050
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
|
|
1951
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { style: styles.td, children: "
|
|
1952
|
-
/* @__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") }) })
|
|
1953
2053
|
] }),
|
|
1954
2054
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { children: [
|
|
1955
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { style: styles.td, children: "created" }),
|
|
1956
|
-
/* @__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) })
|
|
1957
2057
|
] })
|
|
1958
2058
|
] }) }),
|
|
1959
2059
|
user.deletedAt ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { ...styles.notice, marginTop: 12 }, role: "status", children: [
|
|
1960
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
"."
|
|
1964
|
-
] }),
|
|
1965
|
-
" 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")
|
|
1966
2063
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { ...styles.toolbar, marginTop: 12 }, children: [
|
|
1967
2064
|
user.suspended ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1968
2065
|
"button",
|
|
@@ -1971,7 +2068,7 @@ function UsersScreen({
|
|
|
1971
2068
|
style: styles.button,
|
|
1972
2069
|
onClick: () => void unsuspend(),
|
|
1973
2070
|
disabled: isLoading,
|
|
1974
|
-
children: "
|
|
2071
|
+
children: t2("users.unsuspend")
|
|
1975
2072
|
}
|
|
1976
2073
|
) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1977
2074
|
"button",
|
|
@@ -1980,7 +2077,7 @@ function UsersScreen({
|
|
|
1980
2077
|
style: styles.buttonDanger,
|
|
1981
2078
|
onClick: () => void suspend(),
|
|
1982
2079
|
disabled: isLoading,
|
|
1983
|
-
children: "
|
|
2080
|
+
children: t2("users.suspend")
|
|
1984
2081
|
}
|
|
1985
2082
|
),
|
|
1986
2083
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
@@ -1990,51 +2087,49 @@ function UsersScreen({
|
|
|
1990
2087
|
style: styles.button,
|
|
1991
2088
|
onClick: () => void revokeSessions().then(() => sessions.refresh()),
|
|
1992
2089
|
disabled: isLoading,
|
|
1993
|
-
children: "
|
|
2090
|
+
children: t2("users.signOutEverywhere")
|
|
1994
2091
|
}
|
|
1995
2092
|
)
|
|
1996
2093
|
] }),
|
|
1997
2094
|
billingClient ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
1998
|
-
/* @__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") }),
|
|
1999
2096
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2000
2097
|
SubscriberBilling,
|
|
2001
2098
|
{
|
|
2002
2099
|
client: billingClient,
|
|
2003
|
-
subscriber: { type: "user", id: user.id }
|
|
2100
|
+
subscriber: { type: "user", id: user.id },
|
|
2101
|
+
locale
|
|
2004
2102
|
}
|
|
2005
2103
|
)
|
|
2006
2104
|
] }) : null,
|
|
2007
2105
|
!user.deletedAt ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
2008
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h2", { style: styles.subtitle, children: "
|
|
2009
|
-
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: [
|
|
2010
2108
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: styles.mono, children: s.ipAddress ?? "\u2014" }),
|
|
2011
2109
|
" ",
|
|
2012
|
-
(0,
|
|
2013
|
-
(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),
|
|
2014
2112
|
" "
|
|
2015
2113
|
] }) : null,
|
|
2016
2114
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: styles.muted, children: s.userAgent ?? "" }),
|
|
2017
2115
|
" ",
|
|
2018
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.
|
|
2019
|
-
"since ",
|
|
2020
|
-
new Date(s.createdAt).toLocaleString()
|
|
2021
|
-
] })
|
|
2116
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: styles.muted, children: t2("users.since", { date: (0, import_client12.formatAdminDate)(s.createdAt, locale) }) })
|
|
2022
2117
|
] }, s.id)) }),
|
|
2023
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h2", { style: styles.subtitle, children: "
|
|
2024
|
-
history.events.length === 0 && !history.isLoading ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { style: styles.muted, children: "
|
|
2025
|
-
/* @__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 }),
|
|
2026
2121
|
" ",
|
|
2027
2122
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: styles.muted, children: e.method }),
|
|
2028
2123
|
" ",
|
|
2029
2124
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: styles.mono, children: e.ipAddress ?? "\u2014" }),
|
|
2030
2125
|
" ",
|
|
2031
|
-
(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,
|
|
2032
2127
|
e.location?.proxy || e.location?.hosting ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
2033
2128
|
" ",
|
|
2034
|
-
/* @__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") })
|
|
2035
2130
|
] }) : null,
|
|
2036
2131
|
" ",
|
|
2037
|
-
/* @__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) })
|
|
2038
2133
|
] }, e.id)) }),
|
|
2039
2134
|
history.hasMore && !history.isLoading ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2040
2135
|
"button",
|
|
@@ -2042,7 +2137,7 @@ function UsersScreen({
|
|
|
2042
2137
|
type: "button",
|
|
2043
2138
|
style: { ...styles.button, marginTop: 8 },
|
|
2044
2139
|
onClick: () => void history.loadMore(),
|
|
2045
|
-
children: "
|
|
2140
|
+
children: t2("common.loadMore")
|
|
2046
2141
|
}
|
|
2047
2142
|
) : null
|
|
2048
2143
|
] }) : null
|
|
@@ -2051,24 +2146,33 @@ function UsersScreen({
|
|
|
2051
2146
|
}
|
|
2052
2147
|
|
|
2053
2148
|
// src/screens/CatalogScreen.tsx
|
|
2149
|
+
var import_client13 = require("@fonderie/client");
|
|
2054
2150
|
var import_react_admin12 = require("@fonderie/react-admin");
|
|
2055
2151
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
2056
|
-
function CatalogScreen({ client }) {
|
|
2152
|
+
function CatalogScreen({ client, locale }) {
|
|
2153
|
+
const t2 = (0, import_client13.createAdminT)(locale);
|
|
2057
2154
|
const { catalog, isLoading, error, refresh, deletePlan } = (0, import_react_admin12.useAdminCatalog)(client);
|
|
2058
2155
|
const money = (v) => v == null ? "\u2014" : (v / 100).toFixed(2);
|
|
2059
2156
|
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: styles.container, children: [
|
|
2060
2157
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2061
2158
|
PageHeader,
|
|
2062
2159
|
{
|
|
2063
|
-
title: "
|
|
2064
|
-
lead: "
|
|
2065
|
-
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
|
+
)
|
|
2066
2170
|
}
|
|
2067
2171
|
),
|
|
2068
2172
|
error ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { style: styles.error, role: "alert", children: error.explanation }) : null,
|
|
2069
|
-
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,
|
|
2070
2174
|
catalog ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
|
|
2071
|
-
/* @__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") }),
|
|
2072
2176
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2073
2177
|
"pre",
|
|
2074
2178
|
{
|
|
@@ -2083,15 +2187,15 @@ function CatalogScreen({ client }) {
|
|
|
2083
2187
|
children: JSON.stringify(catalog.configured, null, 2)
|
|
2084
2188
|
}
|
|
2085
2189
|
),
|
|
2086
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h2", { style: styles.subtitle, children: "
|
|
2087
|
-
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: [
|
|
2088
2192
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("tr", { children: [
|
|
2089
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { style: styles.th, children: "
|
|
2090
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { style: styles.th, children: "
|
|
2091
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { style: styles.th, children: "
|
|
2092
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { style: styles.th, children: "
|
|
2093
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { style: styles.th, children: "
|
|
2094
|
-
/* @__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") }),
|
|
2095
2199
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { style: styles.th })
|
|
2096
2200
|
] }) }),
|
|
2097
2201
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tbody", { children: catalog.stored.map((p) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("tr", { children: [
|
|
@@ -2107,18 +2211,18 @@ function CatalogScreen({ client }) {
|
|
|
2107
2211
|
p.pricing?.currency ?? ""
|
|
2108
2212
|
] }),
|
|
2109
2213
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { style: styles.td, children: money(p.pricing?.yearly) }),
|
|
2110
|
-
/* @__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" }),
|
|
2111
2215
|
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { style: styles.td, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2112
2216
|
"button",
|
|
2113
2217
|
{
|
|
2114
2218
|
type: "button",
|
|
2115
2219
|
style: styles.buttonDanger,
|
|
2116
2220
|
onClick: () => {
|
|
2117
|
-
if (window.confirm(
|
|
2221
|
+
if (window.confirm(t2("catalog.deleteConfirm", { name: p.name })))
|
|
2118
2222
|
void deletePlan(p.id).catch(() => {
|
|
2119
2223
|
});
|
|
2120
2224
|
},
|
|
2121
|
-
children: "
|
|
2225
|
+
children: t2("common.delete")
|
|
2122
2226
|
}
|
|
2123
2227
|
) })
|
|
2124
2228
|
] }, p.id)) })
|
|
@@ -2128,19 +2232,26 @@ function CatalogScreen({ client }) {
|
|
|
2128
2232
|
}
|
|
2129
2233
|
|
|
2130
2234
|
// src/screens/SubscriberScreen.tsx
|
|
2235
|
+
var import_client14 = require("@fonderie/client");
|
|
2131
2236
|
var import_react_admin13 = require("@fonderie/react-admin");
|
|
2132
2237
|
var import_react7 = require("react");
|
|
2133
2238
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
2134
2239
|
var FILTERS = [
|
|
2135
|
-
{
|
|
2136
|
-
{
|
|
2137
|
-
{
|
|
2138
|
-
{
|
|
2139
|
-
{
|
|
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" }
|
|
2140
2245
|
];
|
|
2141
|
-
function SubscriberScreen({
|
|
2246
|
+
function SubscriberScreen({
|
|
2247
|
+
client,
|
|
2248
|
+
pageSize = 50,
|
|
2249
|
+
onOpenUser,
|
|
2250
|
+
locale
|
|
2251
|
+
}) {
|
|
2252
|
+
const t2 = (0, import_client14.createAdminT)(locale);
|
|
2142
2253
|
const list = (0, import_react_admin13.useAdminSubscribers)(client, { limit: pageSize });
|
|
2143
|
-
const [filter, setFilter] = (0, import_react7.useState)("
|
|
2254
|
+
const [filter, setFilter] = (0, import_react7.useState)("all");
|
|
2144
2255
|
const [open, setOpen] = (0, import_react7.useState)(null);
|
|
2145
2256
|
const [type, setType] = (0, import_react7.useState)("workspace");
|
|
2146
2257
|
const [idInput, setIdInput] = (0, import_react7.useState)("");
|
|
@@ -2150,26 +2261,33 @@ function SubscriberScreen({ client, pageSize = 50, onOpenUser }) {
|
|
|
2150
2261
|
PageHeader,
|
|
2151
2262
|
{
|
|
2152
2263
|
title: `${open.type}/${open.id}`,
|
|
2153
|
-
lead: "
|
|
2264
|
+
lead: t2("billing.subscriptions.detailLead"),
|
|
2154
2265
|
actions: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("button", { type: "button", style: styles.buttonGhost, onClick: () => setOpen(null), children: [
|
|
2155
2266
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Icon, { name: "back", size: 14 }),
|
|
2156
|
-
"
|
|
2267
|
+
t2("billing.subscriptions.back")
|
|
2157
2268
|
] })
|
|
2158
2269
|
}
|
|
2159
2270
|
),
|
|
2160
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SubscriberBilling, { client, subscriber: open })
|
|
2271
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SubscriberBilling, { client, subscriber: open, locale })
|
|
2161
2272
|
] });
|
|
2162
2273
|
}
|
|
2163
|
-
const match = FILTERS.find((f) => f.
|
|
2274
|
+
const match = FILTERS.find((f) => f.id === filter)?.match ?? (() => true);
|
|
2164
2275
|
const rows = list.subscriptions.filter((s) => match(s.status));
|
|
2165
|
-
const openRow = (
|
|
2276
|
+
const openRow = (t3, id) => t3 === "user" && onOpenUser ? onOpenUser(id) : setOpen({ type: t3, id });
|
|
2166
2277
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: styles.container, children: [
|
|
2167
2278
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2168
2279
|
PageHeader,
|
|
2169
2280
|
{
|
|
2170
|
-
title: "
|
|
2171
|
-
lead: "
|
|
2172
|
-
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
|
+
)
|
|
2173
2291
|
}
|
|
2174
2292
|
),
|
|
2175
2293
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { style: { ...styles.toolbar, justifyContent: "space-between" }, children: [
|
|
@@ -2185,23 +2303,23 @@ function SubscriberScreen({ client, pageSize = 50, onOpenUser }) {
|
|
|
2185
2303
|
padding: 0,
|
|
2186
2304
|
minWidth: 0
|
|
2187
2305
|
},
|
|
2188
|
-
"aria-label": "
|
|
2306
|
+
"aria-label": t2("billing.subscriptions.filterLabel"),
|
|
2189
2307
|
children: FILTERS.map((f) => {
|
|
2190
2308
|
const n = list.subscriptions.filter((s) => f.match(s.status)).length;
|
|
2191
|
-
const on = filter === f.
|
|
2309
|
+
const on = filter === f.id;
|
|
2192
2310
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
2193
2311
|
"button",
|
|
2194
2312
|
{
|
|
2195
2313
|
type: "button",
|
|
2196
2314
|
"aria-pressed": on,
|
|
2197
|
-
onClick: () => setFilter(f.
|
|
2315
|
+
onClick: () => setFilter(f.id),
|
|
2198
2316
|
style: { ...on ? styles.buttonPrimary : styles.button, height: 28 },
|
|
2199
2317
|
children: [
|
|
2200
|
-
f.
|
|
2318
|
+
t2(`billing.subscriptions.filter.${f.id}`),
|
|
2201
2319
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { style: { opacity: 0.7 }, children: n })
|
|
2202
2320
|
]
|
|
2203
2321
|
},
|
|
2204
|
-
f.
|
|
2322
|
+
f.id
|
|
2205
2323
|
);
|
|
2206
2324
|
})
|
|
2207
2325
|
}
|
|
@@ -2221,10 +2339,10 @@ function SubscriberScreen({ client, pageSize = 50, onOpenUser }) {
|
|
|
2221
2339
|
value: type,
|
|
2222
2340
|
onChange: (e) => setType(e.target.value),
|
|
2223
2341
|
style: styles.input,
|
|
2224
|
-
"aria-label": "
|
|
2342
|
+
"aria-label": t2("billing.subscriptions.typeLabel"),
|
|
2225
2343
|
children: [
|
|
2226
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("option", { value: "workspace", children: "
|
|
2227
|
-
/* @__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") })
|
|
2228
2346
|
]
|
|
2229
2347
|
}
|
|
2230
2348
|
),
|
|
@@ -2233,36 +2351,29 @@ function SubscriberScreen({ client, pageSize = 50, onOpenUser }) {
|
|
|
2233
2351
|
{
|
|
2234
2352
|
value: idInput,
|
|
2235
2353
|
onChange: (e) => setIdInput(e.target.value),
|
|
2236
|
-
placeholder: "
|
|
2354
|
+
placeholder: t2("billing.subscriptions.idPlaceholder"),
|
|
2237
2355
|
style: { ...styles.input, width: 220 },
|
|
2238
|
-
"aria-label": "
|
|
2356
|
+
"aria-label": t2("billing.subscriptions.idLabel")
|
|
2239
2357
|
}
|
|
2240
2358
|
),
|
|
2241
2359
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("button", { type: "submit", style: styles.button, disabled: !idInput.trim(), children: [
|
|
2242
2360
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Icon, { name: "search", size: 14 }),
|
|
2243
|
-
"
|
|
2361
|
+
t2("common.open")
|
|
2244
2362
|
] })
|
|
2245
2363
|
]
|
|
2246
2364
|
}
|
|
2247
2365
|
)
|
|
2248
2366
|
] }),
|
|
2249
2367
|
list.error ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { style: styles.error, role: "alert", children: list.error.explanation }) : null,
|
|
2250
|
-
rows.length === 0 && !list.isLoading ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2251
|
-
Empty,
|
|
2252
|
-
{
|
|
2253
|
-
icon: "subscriber",
|
|
2254
|
-
title: filter === "All" ? "No subscriptions yet" : `No ${filter.toLowerCase()} subscriptions`,
|
|
2255
|
-
children: "Subscriptions appear here once someone checks out."
|
|
2256
|
-
}
|
|
2257
|
-
) : /* @__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: [
|
|
2258
2369
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("tr", { children: [
|
|
2259
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("th", { style: styles.th, children: "
|
|
2260
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("th", { style: styles.th, children: "
|
|
2261
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("th", { style: styles.th, children: "
|
|
2262
|
-
/* @__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") })
|
|
2263
2374
|
] }) }),
|
|
2264
2375
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("tbody", { children: rows.map((s) => {
|
|
2265
|
-
const end = periodEnd(s);
|
|
2376
|
+
const end = periodEnd(s, locale);
|
|
2266
2377
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("tr", { children: [
|
|
2267
2378
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("td", { style: styles.td, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
2268
2379
|
"button",
|
|
@@ -2282,14 +2393,14 @@ function SubscriberScreen({ client, pageSize = 50, onOpenUser }) {
|
|
|
2282
2393
|
" ",
|
|
2283
2394
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { style: styles.muted, children: [
|
|
2284
2395
|
"\xB7 ",
|
|
2285
|
-
s.interval
|
|
2396
|
+
intervalLabel(t2, s.interval)
|
|
2286
2397
|
] })
|
|
2287
2398
|
] }),
|
|
2288
2399
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("td", { style: styles.td, children: [
|
|
2289
|
-
/* @__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) }),
|
|
2290
2401
|
s.cancelAtPeriodEnd && s.status !== "canceled" ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
2291
2402
|
" ",
|
|
2292
|
-
/* @__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") })
|
|
2293
2404
|
] }) : null
|
|
2294
2405
|
] }),
|
|
2295
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: [
|
|
@@ -2300,28 +2411,28 @@ function SubscriberScreen({ client, pageSize = 50, onOpenUser }) {
|
|
|
2300
2411
|
] }, s.id);
|
|
2301
2412
|
}) })
|
|
2302
2413
|
] }),
|
|
2303
|
-
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,
|
|
2304
2415
|
list.hasMore && !list.isLoading ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2305
2416
|
"button",
|
|
2306
2417
|
{
|
|
2307
2418
|
type: "button",
|
|
2308
2419
|
style: { ...styles.button, marginTop: 8 },
|
|
2309
2420
|
onClick: () => void list.loadMore(),
|
|
2310
|
-
children: "
|
|
2421
|
+
children: t2("common.loadMore")
|
|
2311
2422
|
}
|
|
2312
2423
|
) : null
|
|
2313
2424
|
] });
|
|
2314
2425
|
}
|
|
2315
2426
|
|
|
2316
2427
|
// src/screens/AuditScreen.tsx
|
|
2428
|
+
var import_client15 = require("@fonderie/client");
|
|
2317
2429
|
var import_react_admin14 = require("@fonderie/react-admin");
|
|
2318
2430
|
var import_react8 = require("react");
|
|
2319
2431
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2320
|
-
function AuditScreen({ client, pageSize = 50 }) {
|
|
2321
|
-
const
|
|
2322
|
-
const [
|
|
2323
|
-
|
|
2324
|
-
);
|
|
2432
|
+
function AuditScreen({ client, pageSize = 50, locale }) {
|
|
2433
|
+
const t2 = (0, import_client15.createAdminT)(locale);
|
|
2434
|
+
const [draft, setDraft] = (0, import_react8.useState)({ workspaceId: "", type: "", actorId: "", from: "", to: "" });
|
|
2435
|
+
const [filter, setFilter] = (0, import_react8.useState)({});
|
|
2325
2436
|
const { events, hasMore, isLoading, error, refresh, loadMore } = (0, import_react_admin14.useAdminAudit)(client, {
|
|
2326
2437
|
...filter,
|
|
2327
2438
|
limit: pageSize
|
|
@@ -2337,13 +2448,7 @@ function AuditScreen({ client, pageSize = 50 }) {
|
|
|
2337
2448
|
}
|
|
2338
2449
|
);
|
|
2339
2450
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { style: styles.container, children: [
|
|
2340
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2341
|
-
PageHeader,
|
|
2342
|
-
{
|
|
2343
|
-
title: "Audit",
|
|
2344
|
-
lead: "What happened, across every workspace unless you name one. The chain's integrity verdict is on the Doctor page."
|
|
2345
|
-
}
|
|
2346
|
-
),
|
|
2451
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(PageHeader, { title: t2("audit.title"), lead: t2("audit.lead") }),
|
|
2347
2452
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
2348
2453
|
"form",
|
|
2349
2454
|
{
|
|
@@ -2353,16 +2458,41 @@ function AuditScreen({ client, pageSize = 50 }) {
|
|
|
2353
2458
|
setFilter({
|
|
2354
2459
|
...draft.workspaceId.trim() ? { workspaceId: draft.workspaceId.trim() } : {},
|
|
2355
2460
|
...draft.type.trim() ? { type: draft.type.trim() } : {},
|
|
2356
|
-
...draft.actorId.trim() ? { actorId: draft.actorId.trim() } : {}
|
|
2461
|
+
...draft.actorId.trim() ? { actorId: draft.actorId.trim() } : {},
|
|
2462
|
+
// Dates are whole days in the operator's time zone: "to" includes that day.
|
|
2463
|
+
...draft.from ? { from: /* @__PURE__ */ new Date(`${draft.from}T00:00:00`) } : {},
|
|
2464
|
+
...draft.to ? { to: /* @__PURE__ */ new Date(`${draft.to}T23:59:59.999`) } : {}
|
|
2357
2465
|
});
|
|
2358
2466
|
},
|
|
2359
2467
|
children: [
|
|
2360
|
-
field("workspaceId",
|
|
2361
|
-
field("type", "
|
|
2362
|
-
field("actorId", "
|
|
2468
|
+
field("workspaceId", t2("audit.workspacePlaceholder")),
|
|
2469
|
+
field("type", t2("audit.typePlaceholder")),
|
|
2470
|
+
field("actorId", t2("audit.actorPlaceholder")),
|
|
2471
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2472
|
+
"input",
|
|
2473
|
+
{
|
|
2474
|
+
type: "date",
|
|
2475
|
+
value: draft.from,
|
|
2476
|
+
onChange: (e) => setDraft({ ...draft, from: e.target.value }),
|
|
2477
|
+
style: styles.input,
|
|
2478
|
+
"aria-label": t2("audit.fromLabel"),
|
|
2479
|
+
title: t2("audit.fromTitle")
|
|
2480
|
+
}
|
|
2481
|
+
),
|
|
2482
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2483
|
+
"input",
|
|
2484
|
+
{
|
|
2485
|
+
type: "date",
|
|
2486
|
+
value: draft.to,
|
|
2487
|
+
onChange: (e) => setDraft({ ...draft, to: e.target.value }),
|
|
2488
|
+
style: styles.input,
|
|
2489
|
+
"aria-label": t2("audit.toLabel"),
|
|
2490
|
+
title: t2("audit.toTitle")
|
|
2491
|
+
}
|
|
2492
|
+
),
|
|
2363
2493
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("button", { type: "submit", style: styles.buttonPrimary, disabled: isLoading, children: [
|
|
2364
2494
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Icon, { name: "search", size: 14 }),
|
|
2365
|
-
"
|
|
2495
|
+
t2("common.filter")
|
|
2366
2496
|
] }),
|
|
2367
2497
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2368
2498
|
"button",
|
|
@@ -2371,37 +2501,37 @@ function AuditScreen({ client, pageSize = 50 }) {
|
|
|
2371
2501
|
style: styles.button,
|
|
2372
2502
|
onClick: () => void refresh(),
|
|
2373
2503
|
disabled: isLoading,
|
|
2374
|
-
children: "
|
|
2504
|
+
children: t2("common.refresh")
|
|
2375
2505
|
}
|
|
2376
2506
|
)
|
|
2377
2507
|
]
|
|
2378
2508
|
}
|
|
2379
2509
|
),
|
|
2380
2510
|
error ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { style: styles.error, role: "alert", children: error.explanation }) : null,
|
|
2381
|
-
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: [
|
|
2382
2512
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("tr", { children: [
|
|
2383
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("th", { style: styles.th, children: "
|
|
2384
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("th", { style: styles.th, children: "
|
|
2385
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("th", { style: styles.th, children: "
|
|
2386
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("th", { style: styles.th, children: "
|
|
2387
|
-
/* @__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") })
|
|
2388
2518
|
] }) }),
|
|
2389
2519
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("tbody", { children: events.map((e) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("tr", { children: [
|
|
2390
|
-
/* @__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) }),
|
|
2391
2521
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("td", { style: { ...styles.td, ...styles.mono }, children: e.type }),
|
|
2392
2522
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("td", { style: { ...styles.td, ...styles.mono }, children: String(e.payload["workspaceId"] ?? "\u2014") }),
|
|
2393
2523
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("td", { style: { ...styles.td, ...styles.mono }, children: e.actorId ?? "\u2014" }),
|
|
2394
2524
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("td", { style: { ...styles.td, ...styles.muted }, children: e.requestId ?? "" })
|
|
2395
2525
|
] }, e.id)) })
|
|
2396
2526
|
] }),
|
|
2397
|
-
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,
|
|
2398
2528
|
hasMore && !isLoading ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2399
2529
|
"button",
|
|
2400
2530
|
{
|
|
2401
2531
|
type: "button",
|
|
2402
2532
|
style: { ...styles.button, marginTop: 8 },
|
|
2403
2533
|
onClick: () => void loadMore(),
|
|
2404
|
-
children: "
|
|
2534
|
+
children: t2("common.loadMore")
|
|
2405
2535
|
}
|
|
2406
2536
|
) : null
|
|
2407
2537
|
] });
|
|
@@ -2439,34 +2569,43 @@ function useNarrow() {
|
|
|
2439
2569
|
return narrow;
|
|
2440
2570
|
}
|
|
2441
2571
|
var NAV = [
|
|
2442
|
-
{ group: "
|
|
2572
|
+
{ group: "nav.groups.today", items: [{ page: "attention", label: "nav.items.attention" }] },
|
|
2443
2573
|
{
|
|
2444
|
-
group: "
|
|
2574
|
+
group: "nav.groups.system",
|
|
2445
2575
|
items: [
|
|
2446
|
-
{ page: "modules", label: "
|
|
2447
|
-
{ page: "environment", label: "
|
|
2448
|
-
{ page: "doctor", label: "
|
|
2449
|
-
{ 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" }
|
|
2450
2580
|
]
|
|
2451
2581
|
},
|
|
2452
|
-
{ group: "People", items: [{ page: "users", label: "Users", needs: "auth" }] },
|
|
2453
2582
|
{
|
|
2454
|
-
group: "
|
|
2583
|
+
group: "nav.groups.people",
|
|
2584
|
+
items: [{ page: "users", label: "nav.items.users", needs: "auth" }]
|
|
2585
|
+
},
|
|
2586
|
+
{
|
|
2587
|
+
group: "nav.groups.money",
|
|
2455
2588
|
items: [
|
|
2456
|
-
{ page: "catalog", label: "
|
|
2457
|
-
{ page: "subscriber", label: "
|
|
2589
|
+
{ page: "catalog", label: "nav.items.catalog", needs: "billing" },
|
|
2590
|
+
{ page: "subscriber", label: "nav.items.subscriptions", needs: "billing" }
|
|
2458
2591
|
]
|
|
2459
2592
|
},
|
|
2460
|
-
{ group: "Settings", items: [{ page: "settings", label: "Config & secrets", needs: "config" }] },
|
|
2461
|
-
{ group: "Messaging", items: [{ page: "templates", label: "Templates", needs: "courier" }] },
|
|
2462
2593
|
{
|
|
2463
|
-
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",
|
|
2464
2603
|
items: [
|
|
2465
|
-
{ page: "audit", label: "
|
|
2466
|
-
{ page: "log", label: "
|
|
2467
|
-
{ page: "operators", label: "
|
|
2468
|
-
{ page: "tokens", label: "
|
|
2469
|
-
{ 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" }
|
|
2470
2609
|
]
|
|
2471
2610
|
}
|
|
2472
2611
|
];
|
|
@@ -2484,8 +2623,11 @@ function AdminShell({
|
|
|
2484
2623
|
envLabel,
|
|
2485
2624
|
footer,
|
|
2486
2625
|
operators = false,
|
|
2487
|
-
currentOperator
|
|
2626
|
+
currentOperator,
|
|
2627
|
+
publicConfigUrl,
|
|
2628
|
+
locale
|
|
2488
2629
|
}) {
|
|
2630
|
+
const t2 = (0, import_client16.createAdminT)(locale);
|
|
2489
2631
|
const narrow = useNarrow();
|
|
2490
2632
|
const [drawer, setDrawer] = (0, import_react9.useState)(false);
|
|
2491
2633
|
const [own, setOwn] = (0, import_react9.useState)("attention");
|
|
@@ -2508,40 +2650,41 @@ function AdminShell({
|
|
|
2508
2650
|
let body;
|
|
2509
2651
|
switch (current) {
|
|
2510
2652
|
case "attention":
|
|
2511
|
-
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AttentionScreen, { client });
|
|
2653
|
+
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AttentionScreen, { client, locale });
|
|
2512
2654
|
break;
|
|
2513
2655
|
case "modules":
|
|
2514
|
-
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ModulesScreen, { client });
|
|
2656
|
+
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ModulesScreen, { client, locale });
|
|
2515
2657
|
break;
|
|
2516
2658
|
case "doctor":
|
|
2517
|
-
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DoctorScreen, { client });
|
|
2659
|
+
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DoctorScreen, { client, locale });
|
|
2518
2660
|
break;
|
|
2519
2661
|
case "environment":
|
|
2520
|
-
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(EnvironmentScreen, { client });
|
|
2662
|
+
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(EnvironmentScreen, { client, locale });
|
|
2521
2663
|
break;
|
|
2522
2664
|
case "routes":
|
|
2523
|
-
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(RoutesScreen, { client });
|
|
2665
|
+
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(RoutesScreen, { client, locale });
|
|
2524
2666
|
break;
|
|
2525
2667
|
case "tokens":
|
|
2526
|
-
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TokensScreen, { client });
|
|
2668
|
+
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(TokensScreen, { client, locale });
|
|
2527
2669
|
break;
|
|
2528
2670
|
case "operators":
|
|
2529
|
-
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(OperatorsScreen, { client, me: currentOperator });
|
|
2671
|
+
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(OperatorsScreen, { client, me: currentOperator, locale });
|
|
2530
2672
|
break;
|
|
2531
2673
|
case "migrations":
|
|
2532
|
-
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(MigrationsScreen, { client });
|
|
2674
|
+
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(MigrationsScreen, { client, locale });
|
|
2533
2675
|
break;
|
|
2534
2676
|
case "log":
|
|
2535
|
-
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AdminLogScreen, { client });
|
|
2677
|
+
body = /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AdminLogScreen, { client, locale });
|
|
2536
2678
|
break;
|
|
2537
2679
|
case "catalog":
|
|
2538
|
-
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" }) });
|
|
2539
2681
|
break;
|
|
2540
2682
|
case "subscriber":
|
|
2541
2683
|
body = billingClient ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2542
2684
|
SubscriberScreen,
|
|
2543
2685
|
{
|
|
2544
2686
|
client: billingClient,
|
|
2687
|
+
locale,
|
|
2545
2688
|
...authClient ? {
|
|
2546
2689
|
onOpenUser: (id) => {
|
|
2547
2690
|
setOpenUser(id);
|
|
@@ -2549,10 +2692,10 @@ function AdminShell({
|
|
|
2549
2692
|
}
|
|
2550
2693
|
} : {}
|
|
2551
2694
|
}
|
|
2552
|
-
) : /* @__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" }) });
|
|
2553
2696
|
break;
|
|
2554
2697
|
case "audit":
|
|
2555
|
-
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" }) });
|
|
2556
2699
|
break;
|
|
2557
2700
|
case "users":
|
|
2558
2701
|
body = authClient ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
@@ -2560,16 +2703,17 @@ function AdminShell({
|
|
|
2560
2703
|
{
|
|
2561
2704
|
client: authClient,
|
|
2562
2705
|
billingClient,
|
|
2563
|
-
openUserId: openUser
|
|
2706
|
+
openUserId: openUser,
|
|
2707
|
+
locale
|
|
2564
2708
|
},
|
|
2565
2709
|
openUser ?? "list"
|
|
2566
|
-
) : /* @__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" }) });
|
|
2567
2711
|
break;
|
|
2568
2712
|
case "settings":
|
|
2569
|
-
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: [
|
|
2570
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: [
|
|
2571
2715
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Icon, { name: "back", size: 14 }),
|
|
2572
|
-
"
|
|
2716
|
+
t2("nav.items.settings")
|
|
2573
2717
|
] }) }),
|
|
2574
2718
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2575
2719
|
import_react_config_admin_screens.ConfigEditorScreen,
|
|
@@ -2577,41 +2721,85 @@ function AdminShell({
|
|
|
2577
2721
|
client: configClient,
|
|
2578
2722
|
kind: editing.kind,
|
|
2579
2723
|
configKey: editing.key,
|
|
2580
|
-
...environment !== void 0 ? { environment } : {},
|
|
2581
|
-
|
|
2582
|
-
|
|
2724
|
+
...editing.environment !== void 0 ? { environment: editing.environment } : environment !== void 0 ? { environment } : {},
|
|
2725
|
+
...editing.environments ? { environments: editing.environments } : {},
|
|
2726
|
+
onSaved: () => setEditing(null),
|
|
2727
|
+
onDeleted: () => setEditing(null),
|
|
2728
|
+
locale
|
|
2729
|
+
},
|
|
2730
|
+
`${editing.kind}:${editing.key}:${editing.environment ?? ""}`
|
|
2583
2731
|
)
|
|
2584
2732
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2585
2733
|
import_react_config_admin_screens.ConfigListScreen,
|
|
2586
2734
|
{
|
|
2587
2735
|
client: configClient,
|
|
2736
|
+
locale,
|
|
2588
2737
|
...environment !== void 0 ? { environment } : {},
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2738
|
+
...publicConfigUrl ? { publicConfigUrl } : {},
|
|
2739
|
+
onSelectConfig: (key, env) => setEditing({ kind: "config", key, environment: env }),
|
|
2740
|
+
onSelectSecret: (key, env) => setEditing({ kind: "secret", key, environment: env }),
|
|
2741
|
+
onCreateConfig: (c) => setEditing({
|
|
2742
|
+
kind: "config",
|
|
2743
|
+
key: "",
|
|
2744
|
+
environments: c.environments,
|
|
2745
|
+
...c.environment ? { environment: c.environment } : {}
|
|
2746
|
+
}),
|
|
2747
|
+
onCreateSecret: (c) => setEditing({
|
|
2748
|
+
kind: "secret",
|
|
2749
|
+
key: "",
|
|
2750
|
+
environments: c.environments,
|
|
2751
|
+
...c.environment ? { environment: c.environment } : {}
|
|
2752
|
+
})
|
|
2593
2753
|
}
|
|
2594
2754
|
);
|
|
2595
2755
|
break;
|
|
2596
2756
|
case "templates":
|
|
2597
|
-
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: [
|
|
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: [
|
|
2759
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Icon, { name: "back", size: 14 }),
|
|
2760
|
+
t2("nav.items.templates")
|
|
2761
|
+
] }) }),
|
|
2762
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2763
|
+
import_react_courier_admin_screens.TemplateCreateScreen,
|
|
2764
|
+
{
|
|
2765
|
+
client: courierClient,
|
|
2766
|
+
locale,
|
|
2767
|
+
...editing.type ? { type: editing.type } : {},
|
|
2768
|
+
...editing.locales ? { locales: editing.locales } : {},
|
|
2769
|
+
onCreated: (c) => setEditing({ kind: "template", type: c.type, locale: c.locale, system: false })
|
|
2770
|
+
}
|
|
2771
|
+
)
|
|
2772
|
+
] }) : editing?.kind === "template" ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
2598
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: [
|
|
2599
2774
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Icon, { name: "back", size: 14 }),
|
|
2600
|
-
"
|
|
2775
|
+
t2("nav.items.templates")
|
|
2601
2776
|
] }) }),
|
|
2602
2777
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2603
2778
|
import_react_courier_admin_screens.TemplateEditorScreen,
|
|
2604
2779
|
{
|
|
2605
2780
|
client: courierClient,
|
|
2606
2781
|
type: editing.type,
|
|
2607
|
-
|
|
2608
|
-
|
|
2782
|
+
locale: editing.locale,
|
|
2783
|
+
system: editing.system,
|
|
2784
|
+
onSaved: () => setEditing(null),
|
|
2785
|
+
onDeleted: () => setEditing(null),
|
|
2786
|
+
onAddLocale: (type) => setEditing({ kind: "template-new", type }),
|
|
2787
|
+
uiLocale: locale
|
|
2788
|
+
},
|
|
2789
|
+
`${editing.type}:${editing.locale ?? ""}`
|
|
2609
2790
|
)
|
|
2610
2791
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2611
2792
|
import_react_courier_admin_screens.TemplateListScreen,
|
|
2612
2793
|
{
|
|
2613
2794
|
client: courierClient,
|
|
2614
|
-
|
|
2795
|
+
locale,
|
|
2796
|
+
onSelectTemplate: (tpl) => setEditing({
|
|
2797
|
+
kind: "template",
|
|
2798
|
+
type: tpl.type,
|
|
2799
|
+
locale: tpl.locale ?? null,
|
|
2800
|
+
system: tpl.system === true
|
|
2801
|
+
}),
|
|
2802
|
+
onCreateTemplate: (c) => setEditing({ kind: "template-new", locales: c.locales })
|
|
2615
2803
|
}
|
|
2616
2804
|
);
|
|
2617
2805
|
break;
|
|
@@ -2643,7 +2831,7 @@ function AdminShell({
|
|
|
2643
2831
|
{
|
|
2644
2832
|
type: "button",
|
|
2645
2833
|
style: styles.buttonGhost,
|
|
2646
|
-
"aria-label": "
|
|
2834
|
+
"aria-label": t2("shell.closeMenu"),
|
|
2647
2835
|
onClick: () => setDrawer(false),
|
|
2648
2836
|
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Icon, { name: "close" })
|
|
2649
2837
|
}
|
|
@@ -2656,14 +2844,14 @@ function AdminShell({
|
|
|
2656
2844
|
...styles.nav,
|
|
2657
2845
|
...narrow ? { width: 280, maxWidth: "85vw", boxShadow: "0 10px 40px rgba(0,0,0,.25)" } : {}
|
|
2658
2846
|
},
|
|
2659
|
-
"aria-label": "
|
|
2847
|
+
"aria-label": t2("shell.navLabel"),
|
|
2660
2848
|
children: [
|
|
2661
2849
|
brand,
|
|
2662
2850
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: styles.navScroll, children: NAV.map((g) => {
|
|
2663
2851
|
const items = g.items.filter((i) => !i.needs || has[i.needs]);
|
|
2664
2852
|
if (items.length === 0) return null;
|
|
2665
2853
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
|
|
2666
|
-
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: styles.navGroup, children: g.group }),
|
|
2854
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { style: styles.navGroup, children: t2(g.group) }),
|
|
2667
2855
|
items.map((i) => {
|
|
2668
2856
|
const active = current === i.page;
|
|
2669
2857
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
@@ -2680,7 +2868,7 @@ function AdminShell({
|
|
|
2680
2868
|
},
|
|
2681
2869
|
children: [
|
|
2682
2870
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Icon, { name: ICON[i.page], style: active ? styles.navIconActive : void 0 }),
|
|
2683
|
-
i.label
|
|
2871
|
+
t2(i.label)
|
|
2684
2872
|
]
|
|
2685
2873
|
},
|
|
2686
2874
|
i.page
|
|
@@ -2692,7 +2880,8 @@ function AdminShell({
|
|
|
2692
2880
|
]
|
|
2693
2881
|
}
|
|
2694
2882
|
);
|
|
2695
|
-
const
|
|
2883
|
+
const titleKey = NAV.flatMap((g) => g.items).find((i) => i.page === current)?.label;
|
|
2884
|
+
const title = titleKey ? t2(titleKey) : "";
|
|
2696
2885
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: { ...styles.shell, ...narrow ? { flexDirection: "column" } : {} }, children: [
|
|
2697
2886
|
narrow ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
2698
2887
|
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { style: styles.topbar, children: [
|
|
@@ -2701,7 +2890,7 @@ function AdminShell({
|
|
|
2701
2890
|
{
|
|
2702
2891
|
type: "button",
|
|
2703
2892
|
style: styles.buttonGhost,
|
|
2704
|
-
"aria-label": "
|
|
2893
|
+
"aria-label": t2("shell.openMenu"),
|
|
2705
2894
|
"aria-expanded": drawer,
|
|
2706
2895
|
onClick: () => setDrawer(true),
|
|
2707
2896
|
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Icon, { name: "menu" })
|