@fonderie/react-admin-screens 1.1.0 → 1.2.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 +575 -333
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -3
- package/dist/index.d.ts +11 -3
- package/dist/index.js +561 -320
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/screens/AdminShell.tsx
|
|
2
2
|
import { ConfigEditorScreen, ConfigListScreen } from "@fonderie/react-config-admin-screens";
|
|
3
3
|
import { TemplateEditorScreen, TemplateListScreen } from "@fonderie/react-courier-admin-screens";
|
|
4
|
-
import { useEffect, useState as
|
|
4
|
+
import { useEffect, useState as useState7 } from "react";
|
|
5
5
|
|
|
6
6
|
// src/styles.ts
|
|
7
7
|
var t = {
|
|
@@ -1073,33 +1073,265 @@ function MigrationsScreen({ client }) {
|
|
|
1073
1073
|
] });
|
|
1074
1074
|
}
|
|
1075
1075
|
|
|
1076
|
-
// src/screens/
|
|
1077
|
-
import {
|
|
1076
|
+
// src/screens/OperatorsScreen.tsx
|
|
1077
|
+
import { useAdminOperators } from "@fonderie/react-admin";
|
|
1078
1078
|
import { useState as useState2 } from "react";
|
|
1079
1079
|
import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1080
|
+
var LEVELS = [
|
|
1081
|
+
{ label: "Read only", scopes: ["read"], hint: "look around, change nothing" },
|
|
1082
|
+
{ label: "Editor", scopes: ["read", "write"], hint: "change config, templates, users" },
|
|
1083
|
+
{
|
|
1084
|
+
label: "Owner",
|
|
1085
|
+
scopes: ["read", "write", "secrets"],
|
|
1086
|
+
hint: "secrets, tokens and operators too"
|
|
1087
|
+
}
|
|
1088
|
+
];
|
|
1089
|
+
var levelOf = (scopes) => scopes.includes("secrets") ? "Owner" : scopes.includes("write") ? "Editor" : "Read only";
|
|
1090
|
+
function Minted({ link, onClose }) {
|
|
1091
|
+
const [copied, setCopied] = useState2(false);
|
|
1092
|
+
const url = `${window.location.origin}${link.url}`;
|
|
1093
|
+
return /* @__PURE__ */ jsxs9(
|
|
1094
|
+
"div",
|
|
1095
|
+
{
|
|
1096
|
+
style: {
|
|
1097
|
+
...styles.notice,
|
|
1098
|
+
background: "color-mix(in srgb, var(--fonderie-accent,#00d294) 10%, transparent)",
|
|
1099
|
+
borderColor: "color-mix(in srgb, var(--fonderie-accent,#00d294) 35%, transparent)"
|
|
1100
|
+
},
|
|
1101
|
+
children: [
|
|
1102
|
+
/* @__PURE__ */ jsxs9("strong", { children: [
|
|
1103
|
+
"Send this link to ",
|
|
1104
|
+
link.email,
|
|
1105
|
+
". It is shown once."
|
|
1106
|
+
] }),
|
|
1107
|
+
" It works once and expires",
|
|
1108
|
+
" ",
|
|
1109
|
+
new Date(link.expiresAt).toLocaleString(),
|
|
1110
|
+
".",
|
|
1111
|
+
/* @__PURE__ */ jsxs9("div", { style: { display: "flex", gap: 8, marginTop: 8, alignItems: "center" }, children: [
|
|
1112
|
+
/* @__PURE__ */ jsx9("code", { style: { ...styles.code, flex: 1, padding: "7px 10px", wordBreak: "break-all" }, children: url }),
|
|
1113
|
+
/* @__PURE__ */ jsx9(
|
|
1114
|
+
"button",
|
|
1115
|
+
{
|
|
1116
|
+
type: "button",
|
|
1117
|
+
style: styles.button,
|
|
1118
|
+
onClick: () => {
|
|
1119
|
+
void navigator.clipboard?.writeText(url);
|
|
1120
|
+
setCopied(true);
|
|
1121
|
+
},
|
|
1122
|
+
children: copied ? "Copied" : "Copy"
|
|
1123
|
+
}
|
|
1124
|
+
),
|
|
1125
|
+
/* @__PURE__ */ jsx9("button", { type: "button", style: styles.buttonGhost, onClick: onClose, "aria-label": "Dismiss", children: /* @__PURE__ */ jsx9(Icon, { name: "close", size: 14 }) })
|
|
1126
|
+
] })
|
|
1127
|
+
]
|
|
1128
|
+
}
|
|
1129
|
+
);
|
|
1130
|
+
}
|
|
1131
|
+
function OperatorsScreen({ client, me }) {
|
|
1132
|
+
const { report, isLoading, error, invite, recover, update, revokeLink } = useAdminOperators(client);
|
|
1133
|
+
const [email, setEmail] = useState2("");
|
|
1134
|
+
const [level, setLevel] = useState2("Editor");
|
|
1135
|
+
const [minted, setMinted] = useState2(null);
|
|
1136
|
+
const scopesFor = (label) => LEVELS.find((l) => l.label === label)?.scopes ?? ["read"];
|
|
1137
|
+
const status = (o) => o.disabledAt ? /* @__PURE__ */ jsx9(Pill, { tone: "neutral", children: "disabled" }) : o.locked ? /* @__PURE__ */ jsx9(Pill, { tone: "warn", children: "locked" }) : !o.enrolled ? /* @__PURE__ */ jsx9(Pill, { tone: "warn", children: "setting up" }) : /* @__PURE__ */ jsx9(Pill, { tone: "ok", children: "active" });
|
|
1138
|
+
return /* @__PURE__ */ jsxs9("div", { style: styles.container, children: [
|
|
1139
|
+
/* @__PURE__ */ jsx9(
|
|
1140
|
+
PageHeader,
|
|
1141
|
+
{
|
|
1142
|
+
title: "Operators",
|
|
1143
|
+
lead: "The people who can sign in to this console. Each one uses a password and an authenticator app; there is no sign-up."
|
|
1144
|
+
}
|
|
1145
|
+
),
|
|
1146
|
+
error ? /* @__PURE__ */ jsx9("p", { style: styles.error, role: "alert", children: error.status === 403 && error.reason === "FORBIDDEN" ? "Managing operators needs the Owner level." : error.explanation }) : null,
|
|
1147
|
+
minted ? /* @__PURE__ */ jsx9(Minted, { link: minted, onClose: () => setMinted(null) }) : null,
|
|
1148
|
+
/* @__PURE__ */ jsxs9(
|
|
1149
|
+
"form",
|
|
1150
|
+
{
|
|
1151
|
+
style: {
|
|
1152
|
+
...styles.card,
|
|
1153
|
+
display: "flex",
|
|
1154
|
+
gap: 8,
|
|
1155
|
+
alignItems: "center",
|
|
1156
|
+
flexWrap: "wrap",
|
|
1157
|
+
marginBottom: 20
|
|
1158
|
+
},
|
|
1159
|
+
onSubmit: (e) => {
|
|
1160
|
+
e.preventDefault();
|
|
1161
|
+
void invite({ email: email.trim(), scopes: scopesFor(level) }).then((l) => {
|
|
1162
|
+
setMinted(l);
|
|
1163
|
+
setEmail("");
|
|
1164
|
+
}).catch(() => {
|
|
1165
|
+
});
|
|
1166
|
+
},
|
|
1167
|
+
children: [
|
|
1168
|
+
/* @__PURE__ */ jsx9(Icon, { name: "users", size: 16 }),
|
|
1169
|
+
/* @__PURE__ */ jsx9("strong", { style: { fontSize: 13.5, marginRight: 4 }, children: "Invite" }),
|
|
1170
|
+
/* @__PURE__ */ jsx9(
|
|
1171
|
+
"input",
|
|
1172
|
+
{
|
|
1173
|
+
type: "email",
|
|
1174
|
+
required: true,
|
|
1175
|
+
value: email,
|
|
1176
|
+
onChange: (e) => setEmail(e.target.value),
|
|
1177
|
+
placeholder: "teammate@company.com",
|
|
1178
|
+
style: { ...styles.input, flex: 1, minWidth: 220 },
|
|
1179
|
+
"aria-label": "Email to invite"
|
|
1180
|
+
}
|
|
1181
|
+
),
|
|
1182
|
+
/* @__PURE__ */ jsx9(
|
|
1183
|
+
"select",
|
|
1184
|
+
{
|
|
1185
|
+
value: level,
|
|
1186
|
+
onChange: (e) => setLevel(e.target.value),
|
|
1187
|
+
style: styles.input,
|
|
1188
|
+
"aria-label": "Access level",
|
|
1189
|
+
children: LEVELS.map((l) => /* @__PURE__ */ jsxs9("option", { value: l.label, children: [
|
|
1190
|
+
l.label,
|
|
1191
|
+
" \u2014 ",
|
|
1192
|
+
l.hint
|
|
1193
|
+
] }, l.label))
|
|
1194
|
+
}
|
|
1195
|
+
),
|
|
1196
|
+
/* @__PURE__ */ jsxs9("button", { type: "submit", style: styles.buttonPrimary, disabled: !email.trim(), children: [
|
|
1197
|
+
/* @__PURE__ */ jsx9(Icon, { name: "plus", size: 14 }),
|
|
1198
|
+
"Create invite link"
|
|
1199
|
+
] })
|
|
1200
|
+
]
|
|
1201
|
+
}
|
|
1202
|
+
),
|
|
1203
|
+
isLoading && !report ? /* @__PURE__ */ jsx9("p", { style: styles.status, children: "Loading\u2026" }) : report && report.operators.length === 0 ? /* @__PURE__ */ jsx9(Empty, { icon: "users", title: "No operators yet" }) : report ? /* @__PURE__ */ jsxs9("table", { style: styles.table, children: [
|
|
1204
|
+
/* @__PURE__ */ jsx9("thead", { children: /* @__PURE__ */ jsxs9("tr", { children: [
|
|
1205
|
+
/* @__PURE__ */ jsx9("th", { style: styles.th, children: "Operator" }),
|
|
1206
|
+
/* @__PURE__ */ jsx9("th", { style: styles.th, children: "Access" }),
|
|
1207
|
+
/* @__PURE__ */ jsx9("th", { style: styles.th, children: "Status" }),
|
|
1208
|
+
/* @__PURE__ */ jsx9("th", { style: styles.th, children: "Last sign-in" }),
|
|
1209
|
+
/* @__PURE__ */ jsx9("th", { style: styles.th })
|
|
1210
|
+
] }) }),
|
|
1211
|
+
/* @__PURE__ */ jsx9("tbody", { children: report.operators.map((o) => /* @__PURE__ */ jsxs9("tr", { children: [
|
|
1212
|
+
/* @__PURE__ */ jsxs9("td", { style: styles.td, children: [
|
|
1213
|
+
/* @__PURE__ */ jsx9("div", { style: { fontWeight: 600 }, children: o.name || o.email }),
|
|
1214
|
+
o.name ? /* @__PURE__ */ jsx9("div", { style: styles.muted, children: o.email }) : null
|
|
1215
|
+
] }),
|
|
1216
|
+
/* @__PURE__ */ jsx9("td", { style: styles.td, children: /* @__PURE__ */ jsx9(
|
|
1217
|
+
"select",
|
|
1218
|
+
{
|
|
1219
|
+
value: levelOf(o.scopes),
|
|
1220
|
+
onChange: (e) => void update(o.id, { scopes: scopesFor(e.target.value) }).catch(() => {
|
|
1221
|
+
}),
|
|
1222
|
+
style: { ...styles.input, height: 28, fontSize: 12.5 },
|
|
1223
|
+
disabled: o.email === me,
|
|
1224
|
+
"aria-label": `Access level for ${o.email}`,
|
|
1225
|
+
children: LEVELS.map((l) => /* @__PURE__ */ jsx9("option", { value: l.label, children: l.label }, l.label))
|
|
1226
|
+
}
|
|
1227
|
+
) }),
|
|
1228
|
+
/* @__PURE__ */ jsxs9("td", { style: styles.td, children: [
|
|
1229
|
+
status(o),
|
|
1230
|
+
o.enrolled && o.backupCodesLeft <= 2 && !o.disabledAt ? /* @__PURE__ */ jsxs9("div", { style: { ...styles.muted, marginTop: 4 }, children: [
|
|
1231
|
+
o.backupCodesLeft,
|
|
1232
|
+
" backup code(s) left"
|
|
1233
|
+
] }) : null
|
|
1234
|
+
] }),
|
|
1235
|
+
/* @__PURE__ */ jsx9("td", { style: { ...styles.td, ...styles.muted, whiteSpace: "nowrap" }, children: o.lastLoginAt ? new Date(o.lastLoginAt).toLocaleString() : "never" }),
|
|
1236
|
+
/* @__PURE__ */ jsx9("td", { style: { ...styles.td, textAlign: "right", whiteSpace: "nowrap" }, children: o.email === me ? /* @__PURE__ */ jsx9("span", { style: styles.muted, children: "you" }) : /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
1237
|
+
/* @__PURE__ */ jsx9(
|
|
1238
|
+
"button",
|
|
1239
|
+
{
|
|
1240
|
+
type: "button",
|
|
1241
|
+
style: { ...styles.button, height: 28, marginRight: 6 },
|
|
1242
|
+
onClick: () => {
|
|
1243
|
+
if (window.confirm(
|
|
1244
|
+
`Create a recovery link for ${o.email}? It signs them out everywhere; the link sets a new password and a new authenticator.`
|
|
1245
|
+
))
|
|
1246
|
+
void recover(o.id).then(setMinted).catch(() => {
|
|
1247
|
+
});
|
|
1248
|
+
},
|
|
1249
|
+
children: "Recovery link"
|
|
1250
|
+
}
|
|
1251
|
+
),
|
|
1252
|
+
/* @__PURE__ */ jsx9(
|
|
1253
|
+
"button",
|
|
1254
|
+
{
|
|
1255
|
+
type: "button",
|
|
1256
|
+
style: {
|
|
1257
|
+
...o.disabledAt ? styles.button : styles.buttonDanger,
|
|
1258
|
+
height: 28
|
|
1259
|
+
},
|
|
1260
|
+
onClick: () => {
|
|
1261
|
+
if (o.disabledAt || window.confirm(`Disable ${o.email}? They are signed out immediately.`))
|
|
1262
|
+
void update(o.id, { disabled: !o.disabledAt }).catch(() => {
|
|
1263
|
+
});
|
|
1264
|
+
},
|
|
1265
|
+
children: o.disabledAt ? "Enable" : "Disable"
|
|
1266
|
+
}
|
|
1267
|
+
)
|
|
1268
|
+
] }) })
|
|
1269
|
+
] }, o.id)) })
|
|
1270
|
+
] }) : null,
|
|
1271
|
+
report && report.links.length > 0 ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
1272
|
+
/* @__PURE__ */ jsx9("h2", { style: styles.subtitle, children: "Pending links" }),
|
|
1273
|
+
/* @__PURE__ */ jsx9("ul", { style: styles.list, children: report.links.map((l) => /* @__PURE__ */ jsxs9(
|
|
1274
|
+
"li",
|
|
1275
|
+
{
|
|
1276
|
+
style: { ...styles.row, display: "flex", gap: 12, alignItems: "center" },
|
|
1277
|
+
children: [
|
|
1278
|
+
/* @__PURE__ */ jsx9(Pill, { tone: l.kind === "invite" ? "info" : "warn", dot: false, children: l.kind }),
|
|
1279
|
+
/* @__PURE__ */ jsxs9("span", { style: { flex: 1 }, children: [
|
|
1280
|
+
l.email,
|
|
1281
|
+
l.kind === "invite" ? /* @__PURE__ */ jsxs9("span", { style: styles.muted, children: [
|
|
1282
|
+
" \xB7 ",
|
|
1283
|
+
levelOf(l.scopes)
|
|
1284
|
+
] }) : null
|
|
1285
|
+
] }),
|
|
1286
|
+
/* @__PURE__ */ jsxs9("span", { style: styles.muted, children: [
|
|
1287
|
+
"expires ",
|
|
1288
|
+
new Date(l.expiresAt).toLocaleString()
|
|
1289
|
+
] }),
|
|
1290
|
+
/* @__PURE__ */ jsx9(
|
|
1291
|
+
"button",
|
|
1292
|
+
{
|
|
1293
|
+
type: "button",
|
|
1294
|
+
style: { ...styles.buttonDanger, height: 28 },
|
|
1295
|
+
onClick: () => void revokeLink(l.id).catch(() => {
|
|
1296
|
+
}),
|
|
1297
|
+
children: "Revoke"
|
|
1298
|
+
}
|
|
1299
|
+
)
|
|
1300
|
+
]
|
|
1301
|
+
},
|
|
1302
|
+
l.id
|
|
1303
|
+
)) })
|
|
1304
|
+
] }) : null
|
|
1305
|
+
] });
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
// src/screens/TokensScreen.tsx
|
|
1309
|
+
import { useAdminTokens } from "@fonderie/react-admin";
|
|
1310
|
+
import { useState as useState3 } from "react";
|
|
1311
|
+
import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1080
1312
|
var ALL = ["read", "write", "secrets"];
|
|
1081
1313
|
function TokensScreen({ client }) {
|
|
1082
1314
|
const { report, isLoading, error, issue, revoke } = useAdminTokens(client);
|
|
1083
|
-
const [name, setName] =
|
|
1084
|
-
const [scopes, setScopes] =
|
|
1085
|
-
const [days, setDays] =
|
|
1086
|
-
const [minted, setMinted] =
|
|
1315
|
+
const [name, setName] = useState3("");
|
|
1316
|
+
const [scopes, setScopes] = useState3(["read"]);
|
|
1317
|
+
const [days, setDays] = useState3("");
|
|
1318
|
+
const [minted, setMinted] = useState3(null);
|
|
1087
1319
|
const toggle = (s) => setScopes((prev) => prev.includes(s) ? prev.filter((x) => x !== s) : [...prev, s]);
|
|
1088
|
-
return /* @__PURE__ */
|
|
1089
|
-
/* @__PURE__ */
|
|
1320
|
+
return /* @__PURE__ */ jsxs10("div", { style: styles.container, children: [
|
|
1321
|
+
/* @__PURE__ */ jsx10(
|
|
1090
1322
|
PageHeader,
|
|
1091
1323
|
{
|
|
1092
|
-
title: "
|
|
1093
|
-
lead: "
|
|
1324
|
+
title: "Tokens",
|
|
1325
|
+
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."
|
|
1094
1326
|
}
|
|
1095
1327
|
),
|
|
1096
|
-
error ? /* @__PURE__ */
|
|
1097
|
-
/* @__PURE__ */
|
|
1098
|
-
report ? /* @__PURE__ */
|
|
1099
|
-
/* @__PURE__ */
|
|
1100
|
-
/* @__PURE__ */
|
|
1101
|
-
/* @__PURE__ */
|
|
1102
|
-
report.admin.problems.map((p) => /* @__PURE__ */
|
|
1328
|
+
error ? /* @__PURE__ */ jsx10("p", { style: styles.error, role: "alert", children: error.status === 401 ? "Issuing and revoking need the root token (the one in your deployment config)." : error.explanation }) : null,
|
|
1329
|
+
/* @__PURE__ */ jsx10("h2", { style: { ...styles.subtitle, marginTop: 0 }, children: "Root token" }),
|
|
1330
|
+
report ? /* @__PURE__ */ jsxs10("div", { style: { ...styles.card, display: "flex", gap: 12, alignItems: "flex-start" }, children: [
|
|
1331
|
+
/* @__PURE__ */ jsx10(Icon, { name: "lock", size: 18, style: { marginTop: 2 } }),
|
|
1332
|
+
/* @__PURE__ */ jsxs10("div", { children: [
|
|
1333
|
+
/* @__PURE__ */ jsx10(Pill, { tone: report.admin.ok ? "ok" : "bad", children: report.admin.ok ? "strong" : "weak" }),
|
|
1334
|
+
report.admin.problems.map((p) => /* @__PURE__ */ jsx10(
|
|
1103
1335
|
"div",
|
|
1104
1336
|
{
|
|
1105
1337
|
style: { marginTop: 6, color: "var(--fonderie-danger,#e00)", fontSize: 13 },
|
|
@@ -1109,9 +1341,9 @@ function TokensScreen({ client }) {
|
|
|
1109
1341
|
))
|
|
1110
1342
|
] })
|
|
1111
1343
|
] }) : null,
|
|
1112
|
-
/* @__PURE__ */
|
|
1113
|
-
report?.issued === null ? /* @__PURE__ */
|
|
1114
|
-
minted ? /* @__PURE__ */
|
|
1344
|
+
/* @__PURE__ */ jsx10("h2", { style: styles.subtitle, children: "Issued tokens" }),
|
|
1345
|
+
report?.issued === null ? /* @__PURE__ */ jsx10("p", { style: styles.muted, children: "Issuing is off \u2014 give AdminModule a store and run its migrations." }) : /* @__PURE__ */ jsxs10(Fragment5, { children: [
|
|
1346
|
+
minted ? /* @__PURE__ */ jsxs10(
|
|
1115
1347
|
"div",
|
|
1116
1348
|
{
|
|
1117
1349
|
style: {
|
|
@@ -1120,11 +1352,11 @@ function TokensScreen({ client }) {
|
|
|
1120
1352
|
borderColor: "color-mix(in srgb, var(--fonderie-accent,#00d294) 35%, transparent)"
|
|
1121
1353
|
},
|
|
1122
1354
|
children: [
|
|
1123
|
-
/* @__PURE__ */
|
|
1355
|
+
/* @__PURE__ */ jsx10("strong", { children: "Copy this now \u2014 it is never shown again." }),
|
|
1124
1356
|
" (",
|
|
1125
1357
|
minted.name,
|
|
1126
1358
|
")",
|
|
1127
|
-
/* @__PURE__ */
|
|
1359
|
+
/* @__PURE__ */ jsx10(
|
|
1128
1360
|
"div",
|
|
1129
1361
|
{
|
|
1130
1362
|
style: {
|
|
@@ -1140,7 +1372,7 @@ function TokensScreen({ client }) {
|
|
|
1140
1372
|
]
|
|
1141
1373
|
}
|
|
1142
1374
|
) : null,
|
|
1143
|
-
/* @__PURE__ */
|
|
1375
|
+
/* @__PURE__ */ jsxs10(
|
|
1144
1376
|
"form",
|
|
1145
1377
|
{
|
|
1146
1378
|
style: styles.toolbar,
|
|
@@ -1159,7 +1391,7 @@ function TokensScreen({ client }) {
|
|
|
1159
1391
|
});
|
|
1160
1392
|
},
|
|
1161
1393
|
children: [
|
|
1162
|
-
/* @__PURE__ */
|
|
1394
|
+
/* @__PURE__ */ jsx10(
|
|
1163
1395
|
"input",
|
|
1164
1396
|
{
|
|
1165
1397
|
value: name,
|
|
@@ -1169,7 +1401,7 @@ function TokensScreen({ client }) {
|
|
|
1169
1401
|
"aria-label": "Name"
|
|
1170
1402
|
}
|
|
1171
1403
|
),
|
|
1172
|
-
ALL.map((s) => /* @__PURE__ */
|
|
1404
|
+
ALL.map((s) => /* @__PURE__ */ jsxs10(
|
|
1173
1405
|
"label",
|
|
1174
1406
|
{
|
|
1175
1407
|
style: {
|
|
@@ -1181,14 +1413,14 @@ function TokensScreen({ client }) {
|
|
|
1181
1413
|
fontSize: 13
|
|
1182
1414
|
},
|
|
1183
1415
|
children: [
|
|
1184
|
-
/* @__PURE__ */
|
|
1416
|
+
/* @__PURE__ */ jsx10("input", { type: "checkbox", checked: scopes.includes(s), onChange: () => toggle(s) }),
|
|
1185
1417
|
" ",
|
|
1186
1418
|
s
|
|
1187
1419
|
]
|
|
1188
1420
|
},
|
|
1189
1421
|
s
|
|
1190
1422
|
)),
|
|
1191
|
-
/* @__PURE__ */
|
|
1423
|
+
/* @__PURE__ */ jsx10(
|
|
1192
1424
|
"input",
|
|
1193
1425
|
{
|
|
1194
1426
|
value: days,
|
|
@@ -1198,14 +1430,14 @@ function TokensScreen({ client }) {
|
|
|
1198
1430
|
"aria-label": "Days"
|
|
1199
1431
|
}
|
|
1200
1432
|
),
|
|
1201
|
-
/* @__PURE__ */
|
|
1433
|
+
/* @__PURE__ */ jsxs10(
|
|
1202
1434
|
"button",
|
|
1203
1435
|
{
|
|
1204
1436
|
type: "submit",
|
|
1205
1437
|
style: styles.buttonPrimary,
|
|
1206
1438
|
disabled: !name.trim() || scopes.length === 0 || isLoading,
|
|
1207
1439
|
children: [
|
|
1208
|
-
/* @__PURE__ */
|
|
1440
|
+
/* @__PURE__ */ jsx10(Icon, { name: "plus", size: 14 }),
|
|
1209
1441
|
"Issue token"
|
|
1210
1442
|
]
|
|
1211
1443
|
}
|
|
@@ -1213,32 +1445,32 @@ function TokensScreen({ client }) {
|
|
|
1213
1445
|
]
|
|
1214
1446
|
}
|
|
1215
1447
|
),
|
|
1216
|
-
report?.issued && report.issued.length > 0 ? /* @__PURE__ */
|
|
1217
|
-
/* @__PURE__ */
|
|
1218
|
-
/* @__PURE__ */
|
|
1219
|
-
/* @__PURE__ */
|
|
1220
|
-
/* @__PURE__ */
|
|
1221
|
-
/* @__PURE__ */
|
|
1222
|
-
/* @__PURE__ */
|
|
1223
|
-
/* @__PURE__ */
|
|
1448
|
+
report?.issued && report.issued.length > 0 ? /* @__PURE__ */ jsxs10("table", { style: styles.table, children: [
|
|
1449
|
+
/* @__PURE__ */ jsx10("thead", { children: /* @__PURE__ */ jsxs10("tr", { children: [
|
|
1450
|
+
/* @__PURE__ */ jsx10("th", { style: styles.th, children: "Name" }),
|
|
1451
|
+
/* @__PURE__ */ jsx10("th", { style: styles.th, children: "Scopes" }),
|
|
1452
|
+
/* @__PURE__ */ jsx10("th", { style: styles.th, children: "Created" }),
|
|
1453
|
+
/* @__PURE__ */ jsx10("th", { style: styles.th, children: "Expires" }),
|
|
1454
|
+
/* @__PURE__ */ jsx10("th", { style: styles.th, children: "Last used" }),
|
|
1455
|
+
/* @__PURE__ */ jsx10("th", { style: styles.th })
|
|
1224
1456
|
] }) }),
|
|
1225
|
-
/* @__PURE__ */
|
|
1226
|
-
/* @__PURE__ */
|
|
1457
|
+
/* @__PURE__ */ jsx10("tbody", { children: report.issued.map((t2) => /* @__PURE__ */ jsxs10("tr", { children: [
|
|
1458
|
+
/* @__PURE__ */ jsxs10("td", { style: styles.td, children: [
|
|
1227
1459
|
t2.name,
|
|
1228
|
-
t2.revokedAt ? /* @__PURE__ */
|
|
1460
|
+
t2.revokedAt ? /* @__PURE__ */ jsxs10(Fragment5, { children: [
|
|
1229
1461
|
" ",
|
|
1230
|
-
/* @__PURE__ */
|
|
1462
|
+
/* @__PURE__ */ jsx10(Pill, { tone: "neutral", children: "revoked" })
|
|
1231
1463
|
] }) : null
|
|
1232
1464
|
] }),
|
|
1233
|
-
/* @__PURE__ */
|
|
1234
|
-
/* @__PURE__ */
|
|
1465
|
+
/* @__PURE__ */ jsx10("td", { style: { ...styles.td, ...styles.mono }, children: t2.scopes.join(", ") }),
|
|
1466
|
+
/* @__PURE__ */ jsxs10("td", { style: { ...styles.td, ...styles.muted }, children: [
|
|
1235
1467
|
new Date(t2.createdAt).toLocaleDateString(),
|
|
1236
1468
|
" \xB7 ",
|
|
1237
1469
|
t2.createdBy
|
|
1238
1470
|
] }),
|
|
1239
|
-
/* @__PURE__ */
|
|
1240
|
-
/* @__PURE__ */
|
|
1241
|
-
/* @__PURE__ */
|
|
1471
|
+
/* @__PURE__ */ jsx10("td", { style: { ...styles.td, ...styles.muted }, children: t2.expiresAt ? new Date(t2.expiresAt).toLocaleDateString() : "never" }),
|
|
1472
|
+
/* @__PURE__ */ jsx10("td", { style: { ...styles.td, ...styles.muted }, children: t2.lastUsedAt ? new Date(t2.lastUsedAt).toLocaleString() : "never" }),
|
|
1473
|
+
/* @__PURE__ */ jsx10("td", { style: styles.td, children: t2.revokedAt ? null : /* @__PURE__ */ jsx10(
|
|
1242
1474
|
"button",
|
|
1243
1475
|
{
|
|
1244
1476
|
type: "button",
|
|
@@ -1254,13 +1486,13 @@ function TokensScreen({ client }) {
|
|
|
1254
1486
|
}
|
|
1255
1487
|
) })
|
|
1256
1488
|
] }, t2.id)) })
|
|
1257
|
-
] }) : /* @__PURE__ */
|
|
1489
|
+
] }) : /* @__PURE__ */ jsx10(Empty, { icon: "tokens", title: "No scoped tokens yet", children: "Issue a read-only token for a dashboard or a teammate instead of sharing the root." })
|
|
1258
1490
|
] }),
|
|
1259
|
-
/* @__PURE__ */
|
|
1260
|
-
report && report.legacy.length === 0 ? /* @__PURE__ */
|
|
1261
|
-
/* @__PURE__ */
|
|
1491
|
+
/* @__PURE__ */ jsx10("h2", { style: styles.subtitle, children: "Legacy per-brick tokens" }),
|
|
1492
|
+
report && report.legacy.length === 0 ? /* @__PURE__ */ jsx10("p", { style: styles.muted, children: "None \u2014 every brick's admin surface goes through this token." }) : /* @__PURE__ */ jsx10("ul", { style: styles.list, children: report?.legacy.map((l) => /* @__PURE__ */ jsxs10("li", { style: styles.row, children: [
|
|
1493
|
+
/* @__PURE__ */ jsx10("span", { style: styles.mono, children: l.module }),
|
|
1262
1494
|
" ",
|
|
1263
|
-
/* @__PURE__ */
|
|
1495
|
+
/* @__PURE__ */ jsx10("span", { style: styles.muted, children: "still registers its standalone routes with its own token (deprecated)" })
|
|
1264
1496
|
] }, l.module)) })
|
|
1265
1497
|
] });
|
|
1266
1498
|
}
|
|
@@ -1273,11 +1505,11 @@ import {
|
|
|
1273
1505
|
useAdminUserSessions,
|
|
1274
1506
|
useAdminUsers
|
|
1275
1507
|
} from "@fonderie/react-admin";
|
|
1276
|
-
import { useState as
|
|
1277
|
-
import { Fragment as
|
|
1508
|
+
import { useState as useState4 } from "react";
|
|
1509
|
+
import { Fragment as Fragment6, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1278
1510
|
function UsersScreen({ client, pageSize = 50 }) {
|
|
1279
|
-
const [input, setInput] =
|
|
1280
|
-
const [selected, setSelected] =
|
|
1511
|
+
const [input, setInput] = useState4("");
|
|
1512
|
+
const [selected, setSelected] = useState4(null);
|
|
1281
1513
|
const list = useAdminUsers(client, { limit: pageSize });
|
|
1282
1514
|
const { user, isLoading, error, suspend, unsuspend, revokeSessions } = useAdminUser(
|
|
1283
1515
|
client,
|
|
@@ -1286,20 +1518,20 @@ function UsersScreen({ client, pageSize = 50 }) {
|
|
|
1286
1518
|
const userId = user?.id ?? null;
|
|
1287
1519
|
const sessions = useAdminUserSessions(client, userId);
|
|
1288
1520
|
const history = useAdminLoginHistory(client, userId, { limit: 20 });
|
|
1289
|
-
const yesNo = (v) => v ? /* @__PURE__ */
|
|
1521
|
+
const yesNo = (v) => v ? /* @__PURE__ */ jsx11(Pill, { tone: "ok", children: "yes" }) : /* @__PURE__ */ jsx11(Pill, { tone: "neutral", children: "no" });
|
|
1290
1522
|
const clear = () => {
|
|
1291
1523
|
setSelected(null);
|
|
1292
1524
|
setInput("");
|
|
1293
1525
|
};
|
|
1294
|
-
return /* @__PURE__ */
|
|
1295
|
-
/* @__PURE__ */
|
|
1526
|
+
return /* @__PURE__ */ jsxs11("div", { style: styles.container, children: [
|
|
1527
|
+
/* @__PURE__ */ jsx11(
|
|
1296
1528
|
PageHeader,
|
|
1297
1529
|
{
|
|
1298
1530
|
title: "Users",
|
|
1299
1531
|
lead: "Everyone signed up. Open an account for its sessions, sign-ins and the suspend and sign-out controls."
|
|
1300
1532
|
}
|
|
1301
1533
|
),
|
|
1302
|
-
/* @__PURE__ */
|
|
1534
|
+
/* @__PURE__ */ jsxs11(
|
|
1303
1535
|
"form",
|
|
1304
1536
|
{
|
|
1305
1537
|
style: styles.toolbar,
|
|
@@ -1309,7 +1541,7 @@ function UsersScreen({ client, pageSize = 50 }) {
|
|
|
1309
1541
|
setSelected(email ? { email } : null);
|
|
1310
1542
|
},
|
|
1311
1543
|
children: [
|
|
1312
|
-
/* @__PURE__ */
|
|
1544
|
+
/* @__PURE__ */ jsx11(
|
|
1313
1545
|
"input",
|
|
1314
1546
|
{
|
|
1315
1547
|
type: "email",
|
|
@@ -1320,14 +1552,14 @@ function UsersScreen({ client, pageSize = 50 }) {
|
|
|
1320
1552
|
"aria-label": "Email"
|
|
1321
1553
|
}
|
|
1322
1554
|
),
|
|
1323
|
-
/* @__PURE__ */
|
|
1324
|
-
/* @__PURE__ */
|
|
1555
|
+
/* @__PURE__ */ jsxs11("button", { type: "submit", style: styles.buttonPrimary, disabled: isLoading, children: [
|
|
1556
|
+
/* @__PURE__ */ jsx11(Icon, { name: "search", size: 14 }),
|
|
1325
1557
|
"Look up"
|
|
1326
1558
|
] }),
|
|
1327
|
-
selected ? /* @__PURE__ */
|
|
1328
|
-
/* @__PURE__ */
|
|
1559
|
+
selected ? /* @__PURE__ */ jsxs11("button", { type: "button", style: styles.buttonGhost, onClick: clear, children: [
|
|
1560
|
+
/* @__PURE__ */ jsx11(Icon, { name: "back", size: 14 }),
|
|
1329
1561
|
"All users"
|
|
1330
|
-
] }) : /* @__PURE__ */
|
|
1562
|
+
] }) : /* @__PURE__ */ jsx11(
|
|
1331
1563
|
"button",
|
|
1332
1564
|
{
|
|
1333
1565
|
type: "button",
|
|
@@ -1340,18 +1572,18 @@ function UsersScreen({ client, pageSize = 50 }) {
|
|
|
1340
1572
|
]
|
|
1341
1573
|
}
|
|
1342
1574
|
),
|
|
1343
|
-
error ? /* @__PURE__ */
|
|
1344
|
-
!selected ? /* @__PURE__ */
|
|
1345
|
-
list.error ? /* @__PURE__ */
|
|
1346
|
-
list.users.length === 0 && !list.isLoading ? /* @__PURE__ */
|
|
1347
|
-
/* @__PURE__ */
|
|
1348
|
-
/* @__PURE__ */
|
|
1349
|
-
/* @__PURE__ */
|
|
1350
|
-
/* @__PURE__ */
|
|
1351
|
-
/* @__PURE__ */
|
|
1575
|
+
error ? /* @__PURE__ */ jsx11("p", { style: styles.error, role: "alert", children: error.status === 404 ? "No user with that email." : error.explanation }) : null,
|
|
1576
|
+
!selected ? /* @__PURE__ */ jsxs11(Fragment6, { children: [
|
|
1577
|
+
list.error ? /* @__PURE__ */ jsx11("p", { style: styles.error, role: "alert", children: list.error.explanation }) : null,
|
|
1578
|
+
list.users.length === 0 && !list.isLoading ? /* @__PURE__ */ jsx11(Empty, { icon: "users", title: "No users yet", children: "Sign-ups appear here as they happen." }) : /* @__PURE__ */ jsxs11("table", { style: styles.table, children: [
|
|
1579
|
+
/* @__PURE__ */ jsx11("thead", { children: /* @__PURE__ */ jsxs11("tr", { children: [
|
|
1580
|
+
/* @__PURE__ */ jsx11("th", { style: styles.th, children: "Email" }),
|
|
1581
|
+
/* @__PURE__ */ jsx11("th", { style: styles.th, children: "Name" }),
|
|
1582
|
+
/* @__PURE__ */ jsx11("th", { style: styles.th, children: "Created" }),
|
|
1583
|
+
/* @__PURE__ */ jsx11("th", { style: styles.th, children: "Status" })
|
|
1352
1584
|
] }) }),
|
|
1353
|
-
/* @__PURE__ */
|
|
1354
|
-
/* @__PURE__ */
|
|
1585
|
+
/* @__PURE__ */ jsx11("tbody", { children: list.users.map((u) => /* @__PURE__ */ jsxs11("tr", { children: [
|
|
1586
|
+
/* @__PURE__ */ jsx11("td", { style: styles.td, children: /* @__PURE__ */ jsx11(
|
|
1355
1587
|
"button",
|
|
1356
1588
|
{
|
|
1357
1589
|
type: "button",
|
|
@@ -1360,17 +1592,17 @@ function UsersScreen({ client, pageSize = 50 }) {
|
|
|
1360
1592
|
children: u.email
|
|
1361
1593
|
}
|
|
1362
1594
|
) }),
|
|
1363
|
-
/* @__PURE__ */
|
|
1364
|
-
/* @__PURE__ */
|
|
1365
|
-
/* @__PURE__ */
|
|
1366
|
-
u.suspended ? /* @__PURE__ */
|
|
1367
|
-
u.deletedAt ? /* @__PURE__ */
|
|
1368
|
-
!u.suspended && !u.deletedAt ? /* @__PURE__ */
|
|
1595
|
+
/* @__PURE__ */ jsx11("td", { style: styles.td, children: `${u.firstName ?? ""} ${u.lastName ?? ""}`.trim() || /* @__PURE__ */ jsx11("span", { style: styles.muted, children: "\u2014" }) }),
|
|
1596
|
+
/* @__PURE__ */ jsx11("td", { style: styles.td, children: new Date(u.createdAt).toLocaleDateString() }),
|
|
1597
|
+
/* @__PURE__ */ jsxs11("td", { style: styles.td, children: [
|
|
1598
|
+
u.suspended ? /* @__PURE__ */ jsx11(Pill, { tone: "warn", children: "suspended" }) : null,
|
|
1599
|
+
u.deletedAt ? /* @__PURE__ */ jsx11(Pill, { tone: "neutral", children: "deleted" }) : null,
|
|
1600
|
+
!u.suspended && !u.deletedAt ? /* @__PURE__ */ jsx11(Pill, { tone: "ok", children: "active" }) : null
|
|
1369
1601
|
] })
|
|
1370
1602
|
] }, u.id)) })
|
|
1371
1603
|
] }),
|
|
1372
|
-
list.isLoading ? /* @__PURE__ */
|
|
1373
|
-
list.hasMore && !list.isLoading ? /* @__PURE__ */
|
|
1604
|
+
list.isLoading ? /* @__PURE__ */ jsx11("p", { style: styles.status, children: "Loading\u2026" }) : null,
|
|
1605
|
+
list.hasMore && !list.isLoading ? /* @__PURE__ */ jsx11(
|
|
1374
1606
|
"button",
|
|
1375
1607
|
{
|
|
1376
1608
|
type: "button",
|
|
@@ -1380,48 +1612,48 @@ function UsersScreen({ client, pageSize = 50 }) {
|
|
|
1380
1612
|
}
|
|
1381
1613
|
) : null
|
|
1382
1614
|
] }) : null,
|
|
1383
|
-
user ? /* @__PURE__ */
|
|
1384
|
-
/* @__PURE__ */
|
|
1615
|
+
user ? /* @__PURE__ */ jsxs11(Fragment6, { children: [
|
|
1616
|
+
/* @__PURE__ */ jsxs11("h2", { style: styles.subtitle, children: [
|
|
1385
1617
|
user.firstName || user.lastName ? `${user.firstName} ${user.lastName}`.trim() : user.email,
|
|
1386
1618
|
" ",
|
|
1387
|
-
user.suspended ? /* @__PURE__ */
|
|
1388
|
-
user.deletedAt ? /* @__PURE__ */
|
|
1619
|
+
user.suspended ? /* @__PURE__ */ jsx11(Pill, { tone: "warn", children: "suspended" }) : null,
|
|
1620
|
+
user.deletedAt ? /* @__PURE__ */ jsx11(Pill, { tone: "neutral", children: "deleted" }) : null
|
|
1389
1621
|
] }),
|
|
1390
|
-
/* @__PURE__ */
|
|
1391
|
-
/* @__PURE__ */
|
|
1392
|
-
/* @__PURE__ */
|
|
1393
|
-
/* @__PURE__ */
|
|
1622
|
+
/* @__PURE__ */ jsx11("table", { style: styles.table, children: /* @__PURE__ */ jsxs11("tbody", { children: [
|
|
1623
|
+
/* @__PURE__ */ jsxs11("tr", { children: [
|
|
1624
|
+
/* @__PURE__ */ jsx11("td", { style: styles.td, children: "id" }),
|
|
1625
|
+
/* @__PURE__ */ jsx11("td", { style: { ...styles.td, ...styles.mono }, children: user.id })
|
|
1394
1626
|
] }),
|
|
1395
|
-
/* @__PURE__ */
|
|
1396
|
-
/* @__PURE__ */
|
|
1397
|
-
/* @__PURE__ */
|
|
1627
|
+
/* @__PURE__ */ jsxs11("tr", { children: [
|
|
1628
|
+
/* @__PURE__ */ jsx11("td", { style: styles.td, children: "email" }),
|
|
1629
|
+
/* @__PURE__ */ jsxs11("td", { style: styles.td, children: [
|
|
1398
1630
|
user.email,
|
|
1399
1631
|
" \xB7 verified ",
|
|
1400
1632
|
yesNo(user.isEmailVerified)
|
|
1401
1633
|
] })
|
|
1402
1634
|
] }),
|
|
1403
|
-
/* @__PURE__ */
|
|
1404
|
-
/* @__PURE__ */
|
|
1405
|
-
/* @__PURE__ */
|
|
1635
|
+
/* @__PURE__ */ jsxs11("tr", { children: [
|
|
1636
|
+
/* @__PURE__ */ jsx11("td", { style: styles.td, children: "MFA" }),
|
|
1637
|
+
/* @__PURE__ */ jsx11("td", { style: styles.td, children: yesNo(user.mfaEnabled) })
|
|
1406
1638
|
] }),
|
|
1407
|
-
/* @__PURE__ */
|
|
1408
|
-
/* @__PURE__ */
|
|
1409
|
-
/* @__PURE__ */
|
|
1639
|
+
/* @__PURE__ */ jsxs11("tr", { children: [
|
|
1640
|
+
/* @__PURE__ */ jsx11("td", { style: styles.td, children: "provider" }),
|
|
1641
|
+
/* @__PURE__ */ jsxs11("td", { style: styles.td, children: [
|
|
1410
1642
|
user.provider || "password",
|
|
1411
1643
|
user.hasPassword ? "" : " \xB7 no password set"
|
|
1412
1644
|
] })
|
|
1413
1645
|
] }),
|
|
1414
|
-
/* @__PURE__ */
|
|
1415
|
-
/* @__PURE__ */
|
|
1416
|
-
/* @__PURE__ */
|
|
1646
|
+
/* @__PURE__ */ jsxs11("tr", { children: [
|
|
1647
|
+
/* @__PURE__ */ jsx11("td", { style: styles.td, children: "last login" }),
|
|
1648
|
+
/* @__PURE__ */ jsx11("td", { style: styles.td, children: user.lastLogin ? new Date(user.lastLogin).toLocaleString() : /* @__PURE__ */ jsx11("span", { style: styles.muted, children: "never" }) })
|
|
1417
1649
|
] }),
|
|
1418
|
-
/* @__PURE__ */
|
|
1419
|
-
/* @__PURE__ */
|
|
1420
|
-
/* @__PURE__ */
|
|
1650
|
+
/* @__PURE__ */ jsxs11("tr", { children: [
|
|
1651
|
+
/* @__PURE__ */ jsx11("td", { style: styles.td, children: "created" }),
|
|
1652
|
+
/* @__PURE__ */ jsx11("td", { style: styles.td, children: new Date(user.createdAt).toLocaleString() })
|
|
1421
1653
|
] })
|
|
1422
1654
|
] }) }),
|
|
1423
|
-
/* @__PURE__ */
|
|
1424
|
-
user.suspended ? /* @__PURE__ */
|
|
1655
|
+
/* @__PURE__ */ jsxs11("div", { style: { ...styles.toolbar, marginTop: 12 }, children: [
|
|
1656
|
+
user.suspended ? /* @__PURE__ */ jsx11(
|
|
1425
1657
|
"button",
|
|
1426
1658
|
{
|
|
1427
1659
|
type: "button",
|
|
@@ -1430,7 +1662,7 @@ function UsersScreen({ client, pageSize = 50 }) {
|
|
|
1430
1662
|
disabled: isLoading,
|
|
1431
1663
|
children: "Unsuspend"
|
|
1432
1664
|
}
|
|
1433
|
-
) : /* @__PURE__ */
|
|
1665
|
+
) : /* @__PURE__ */ jsx11(
|
|
1434
1666
|
"button",
|
|
1435
1667
|
{
|
|
1436
1668
|
type: "button",
|
|
@@ -1440,7 +1672,7 @@ function UsersScreen({ client, pageSize = 50 }) {
|
|
|
1440
1672
|
children: "Suspend"
|
|
1441
1673
|
}
|
|
1442
1674
|
),
|
|
1443
|
-
/* @__PURE__ */
|
|
1675
|
+
/* @__PURE__ */ jsx11(
|
|
1444
1676
|
"button",
|
|
1445
1677
|
{
|
|
1446
1678
|
type: "button",
|
|
@@ -1451,38 +1683,38 @@ function UsersScreen({ client, pageSize = 50 }) {
|
|
|
1451
1683
|
}
|
|
1452
1684
|
)
|
|
1453
1685
|
] }),
|
|
1454
|
-
/* @__PURE__ */
|
|
1455
|
-
sessions.sessions.length === 0 ? /* @__PURE__ */
|
|
1456
|
-
/* @__PURE__ */
|
|
1686
|
+
/* @__PURE__ */ jsx11("h2", { style: styles.subtitle, children: "Live sessions" }),
|
|
1687
|
+
sessions.sessions.length === 0 ? /* @__PURE__ */ jsx11("p", { style: styles.muted, children: "None." }) : /* @__PURE__ */ jsx11("ul", { style: styles.list, children: sessions.sessions.map((s) => /* @__PURE__ */ jsxs11("li", { style: styles.row, children: [
|
|
1688
|
+
/* @__PURE__ */ jsx11("span", { style: styles.mono, children: s.ipAddress ?? "\u2014" }),
|
|
1457
1689
|
" ",
|
|
1458
|
-
describeLocation(s.location) ? /* @__PURE__ */
|
|
1690
|
+
describeLocation(s.location) ? /* @__PURE__ */ jsxs11("span", { style: styles.muted, children: [
|
|
1459
1691
|
describeLocation(s.location),
|
|
1460
1692
|
" "
|
|
1461
1693
|
] }) : null,
|
|
1462
|
-
/* @__PURE__ */
|
|
1694
|
+
/* @__PURE__ */ jsx11("span", { style: styles.muted, children: s.userAgent ?? "" }),
|
|
1463
1695
|
" ",
|
|
1464
|
-
/* @__PURE__ */
|
|
1696
|
+
/* @__PURE__ */ jsxs11("span", { style: styles.muted, children: [
|
|
1465
1697
|
"since ",
|
|
1466
1698
|
new Date(s.createdAt).toLocaleString()
|
|
1467
1699
|
] })
|
|
1468
1700
|
] }, s.id)) }),
|
|
1469
|
-
/* @__PURE__ */
|
|
1470
|
-
history.events.length === 0 && !history.isLoading ? /* @__PURE__ */
|
|
1471
|
-
/* @__PURE__ */
|
|
1701
|
+
/* @__PURE__ */ jsx11("h2", { style: styles.subtitle, children: "Recent sign-ins" }),
|
|
1702
|
+
history.events.length === 0 && !history.isLoading ? /* @__PURE__ */ jsx11("p", { style: styles.muted, children: "None recorded." }) : /* @__PURE__ */ jsx11("ul", { style: styles.list, children: history.events.map((e) => /* @__PURE__ */ jsxs11("li", { style: styles.row, children: [
|
|
1703
|
+
/* @__PURE__ */ jsx11(Pill, { tone: e.outcome === "success" ? "ok" : "bad", children: e.outcome }),
|
|
1472
1704
|
" ",
|
|
1473
|
-
/* @__PURE__ */
|
|
1705
|
+
/* @__PURE__ */ jsx11("span", { style: styles.muted, children: e.method }),
|
|
1474
1706
|
" ",
|
|
1475
|
-
/* @__PURE__ */
|
|
1707
|
+
/* @__PURE__ */ jsx11("span", { style: styles.mono, children: e.ipAddress ?? "\u2014" }),
|
|
1476
1708
|
" ",
|
|
1477
|
-
describeLocation(e.location) ? /* @__PURE__ */
|
|
1478
|
-
e.location?.proxy || e.location?.hosting ? /* @__PURE__ */
|
|
1709
|
+
describeLocation(e.location) ? /* @__PURE__ */ jsx11("span", { style: styles.muted, children: describeLocation(e.location) }) : null,
|
|
1710
|
+
e.location?.proxy || e.location?.hosting ? /* @__PURE__ */ jsxs11(Fragment6, { children: [
|
|
1479
1711
|
" ",
|
|
1480
|
-
/* @__PURE__ */
|
|
1712
|
+
/* @__PURE__ */ jsx11(Pill, { tone: "warn", children: e.location.proxy ? "proxy/VPN" : "hosting" })
|
|
1481
1713
|
] }) : null,
|
|
1482
1714
|
" ",
|
|
1483
|
-
/* @__PURE__ */
|
|
1715
|
+
/* @__PURE__ */ jsx11("span", { style: styles.muted, children: new Date(e.createdAt).toLocaleString() })
|
|
1484
1716
|
] }, e.id)) }),
|
|
1485
|
-
history.hasMore && !history.isLoading ? /* @__PURE__ */
|
|
1717
|
+
history.hasMore && !history.isLoading ? /* @__PURE__ */ jsx11(
|
|
1486
1718
|
"button",
|
|
1487
1719
|
{
|
|
1488
1720
|
type: "button",
|
|
@@ -1497,24 +1729,24 @@ function UsersScreen({ client, pageSize = 50 }) {
|
|
|
1497
1729
|
|
|
1498
1730
|
// src/screens/CatalogScreen.tsx
|
|
1499
1731
|
import { useAdminCatalog } from "@fonderie/react-admin";
|
|
1500
|
-
import { Fragment as
|
|
1732
|
+
import { Fragment as Fragment7, jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1501
1733
|
function CatalogScreen({ client }) {
|
|
1502
1734
|
const { catalog, isLoading, error, refresh, deletePlan } = useAdminCatalog(client);
|
|
1503
1735
|
const money = (v) => v == null ? "\u2014" : (v / 100).toFixed(2);
|
|
1504
|
-
return /* @__PURE__ */
|
|
1505
|
-
/* @__PURE__ */
|
|
1736
|
+
return /* @__PURE__ */ jsxs12("div", { style: styles.container, children: [
|
|
1737
|
+
/* @__PURE__ */ jsx12(
|
|
1506
1738
|
PageHeader,
|
|
1507
1739
|
{
|
|
1508
1740
|
title: "Catalog",
|
|
1509
1741
|
lead: "What you sell: plans as configured in code, and as stored in the database, side by side.",
|
|
1510
|
-
actions: /* @__PURE__ */
|
|
1742
|
+
actions: /* @__PURE__ */ jsx12(RefreshButton, { onClick: () => void refresh(), busy: isLoading })
|
|
1511
1743
|
}
|
|
1512
1744
|
),
|
|
1513
|
-
error ? /* @__PURE__ */
|
|
1514
|
-
isLoading && !catalog ? /* @__PURE__ */
|
|
1515
|
-
catalog ? /* @__PURE__ */
|
|
1516
|
-
/* @__PURE__ */
|
|
1517
|
-
/* @__PURE__ */
|
|
1745
|
+
error ? /* @__PURE__ */ jsx12("p", { style: styles.error, role: "alert", children: error.explanation }) : null,
|
|
1746
|
+
isLoading && !catalog ? /* @__PURE__ */ jsx12("p", { style: styles.status, children: "Loading\u2026" }) : null,
|
|
1747
|
+
catalog ? /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
1748
|
+
/* @__PURE__ */ jsx12("h2", { style: { ...styles.subtitle, marginTop: 0 }, children: "Configured (code)" }),
|
|
1749
|
+
/* @__PURE__ */ jsx12(
|
|
1518
1750
|
"pre",
|
|
1519
1751
|
{
|
|
1520
1752
|
style: {
|
|
@@ -1528,32 +1760,32 @@ function CatalogScreen({ client }) {
|
|
|
1528
1760
|
children: JSON.stringify(catalog.configured, null, 2)
|
|
1529
1761
|
}
|
|
1530
1762
|
),
|
|
1531
|
-
/* @__PURE__ */
|
|
1532
|
-
catalog.stored.length === 0 ? /* @__PURE__ */
|
|
1533
|
-
/* @__PURE__ */
|
|
1534
|
-
/* @__PURE__ */
|
|
1535
|
-
/* @__PURE__ */
|
|
1536
|
-
/* @__PURE__ */
|
|
1537
|
-
/* @__PURE__ */
|
|
1538
|
-
/* @__PURE__ */
|
|
1539
|
-
/* @__PURE__ */
|
|
1540
|
-
/* @__PURE__ */
|
|
1763
|
+
/* @__PURE__ */ jsx12("h2", { style: styles.subtitle, children: "Stored (database)" }),
|
|
1764
|
+
catalog.stored.length === 0 ? /* @__PURE__ */ jsx12(Empty, { icon: "catalog", title: "No stored plans", children: "Plans are configured in code; nothing has been written to the database." }) : /* @__PURE__ */ jsxs12("table", { style: styles.table, children: [
|
|
1765
|
+
/* @__PURE__ */ jsx12("thead", { children: /* @__PURE__ */ jsxs12("tr", { children: [
|
|
1766
|
+
/* @__PURE__ */ jsx12("th", { style: styles.th, children: "Plan" }),
|
|
1767
|
+
/* @__PURE__ */ jsx12("th", { style: styles.th, children: "Tier" }),
|
|
1768
|
+
/* @__PURE__ */ jsx12("th", { style: styles.th, children: "Seats" }),
|
|
1769
|
+
/* @__PURE__ */ jsx12("th", { style: styles.th, children: "Monthly" }),
|
|
1770
|
+
/* @__PURE__ */ jsx12("th", { style: styles.th, children: "Yearly" }),
|
|
1771
|
+
/* @__PURE__ */ jsx12("th", { style: styles.th, children: "Trial" }),
|
|
1772
|
+
/* @__PURE__ */ jsx12("th", { style: styles.th })
|
|
1541
1773
|
] }) }),
|
|
1542
|
-
/* @__PURE__ */
|
|
1543
|
-
/* @__PURE__ */
|
|
1544
|
-
/* @__PURE__ */
|
|
1545
|
-
p.description ? /* @__PURE__ */
|
|
1774
|
+
/* @__PURE__ */ jsx12("tbody", { children: catalog.stored.map((p) => /* @__PURE__ */ jsxs12("tr", { children: [
|
|
1775
|
+
/* @__PURE__ */ jsxs12("td", { style: styles.td, children: [
|
|
1776
|
+
/* @__PURE__ */ jsx12("strong", { children: p.name }),
|
|
1777
|
+
p.description ? /* @__PURE__ */ jsx12("div", { style: styles.muted, children: p.description }) : null
|
|
1546
1778
|
] }),
|
|
1547
|
-
/* @__PURE__ */
|
|
1548
|
-
/* @__PURE__ */
|
|
1549
|
-
/* @__PURE__ */
|
|
1779
|
+
/* @__PURE__ */ jsx12("td", { style: styles.td, children: p.tier }),
|
|
1780
|
+
/* @__PURE__ */ jsx12("td", { style: styles.td, children: p.seats ?? "\u221E" }),
|
|
1781
|
+
/* @__PURE__ */ jsxs12("td", { style: styles.td, children: [
|
|
1550
1782
|
money(p.pricing?.monthly),
|
|
1551
1783
|
" ",
|
|
1552
1784
|
p.pricing?.currency ?? ""
|
|
1553
1785
|
] }),
|
|
1554
|
-
/* @__PURE__ */
|
|
1555
|
-
/* @__PURE__ */
|
|
1556
|
-
/* @__PURE__ */
|
|
1786
|
+
/* @__PURE__ */ jsx12("td", { style: styles.td, children: money(p.pricing?.yearly) }),
|
|
1787
|
+
/* @__PURE__ */ jsx12("td", { style: styles.td, children: p.trialDays ? `${p.trialDays} d` : "\u2014" }),
|
|
1788
|
+
/* @__PURE__ */ jsx12("td", { style: styles.td, children: /* @__PURE__ */ jsx12(
|
|
1557
1789
|
"button",
|
|
1558
1790
|
{
|
|
1559
1791
|
type: "button",
|
|
@@ -1574,32 +1806,32 @@ function CatalogScreen({ client }) {
|
|
|
1574
1806
|
|
|
1575
1807
|
// src/screens/SubscriberScreen.tsx
|
|
1576
1808
|
import { useAdminSubscriber, useAdminSubscribers } from "@fonderie/react-admin";
|
|
1577
|
-
import { useState as
|
|
1578
|
-
import { Fragment as
|
|
1809
|
+
import { useState as useState5 } from "react";
|
|
1810
|
+
import { Fragment as Fragment8, jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1579
1811
|
function SubscriberScreen({ client, pageSize = 50 }) {
|
|
1580
|
-
const [type, setType] =
|
|
1581
|
-
const [idInput, setIdInput] =
|
|
1582
|
-
const [subscriber, setSubscriber] =
|
|
1812
|
+
const [type, setType] = useState5("user");
|
|
1813
|
+
const [idInput, setIdInput] = useState5("");
|
|
1814
|
+
const [subscriber, setSubscriber] = useState5(null);
|
|
1583
1815
|
const list = useAdminSubscribers(client, { limit: pageSize });
|
|
1584
1816
|
const { subscription, wallet, ledger, hasMoreLedger, isLoading, error, loadMoreLedger, grant } = useAdminSubscriber(client, subscriber, { limit: 20 });
|
|
1585
|
-
const [amount, setAmount] =
|
|
1586
|
-
const [note, setNote] =
|
|
1587
|
-
const [granted, setGranted] =
|
|
1817
|
+
const [amount, setAmount] = useState5("");
|
|
1818
|
+
const [note, setNote] = useState5("");
|
|
1819
|
+
const [granted, setGranted] = useState5(null);
|
|
1588
1820
|
const open = (t2, id) => {
|
|
1589
1821
|
setGranted(null);
|
|
1590
1822
|
setType(t2);
|
|
1591
1823
|
setIdInput(id);
|
|
1592
1824
|
setSubscriber({ type: t2, id });
|
|
1593
1825
|
};
|
|
1594
|
-
return /* @__PURE__ */
|
|
1595
|
-
/* @__PURE__ */
|
|
1826
|
+
return /* @__PURE__ */ jsxs13("div", { style: styles.container, children: [
|
|
1827
|
+
/* @__PURE__ */ jsx13(
|
|
1596
1828
|
PageHeader,
|
|
1597
1829
|
{
|
|
1598
1830
|
title: "Subscribers",
|
|
1599
1831
|
lead: "Who is subscribed. Open one for their plan, wallet and ledger, and to grant credit."
|
|
1600
1832
|
}
|
|
1601
1833
|
),
|
|
1602
|
-
/* @__PURE__ */
|
|
1834
|
+
/* @__PURE__ */ jsxs13(
|
|
1603
1835
|
"form",
|
|
1604
1836
|
{
|
|
1605
1837
|
style: styles.toolbar,
|
|
@@ -1609,7 +1841,7 @@ function SubscriberScreen({ client, pageSize = 50 }) {
|
|
|
1609
1841
|
setSubscriber(idInput.trim() ? { type, id: idInput.trim() } : null);
|
|
1610
1842
|
},
|
|
1611
1843
|
children: [
|
|
1612
|
-
/* @__PURE__ */
|
|
1844
|
+
/* @__PURE__ */ jsxs13(
|
|
1613
1845
|
"select",
|
|
1614
1846
|
{
|
|
1615
1847
|
value: type,
|
|
@@ -1617,12 +1849,12 @@ function SubscriberScreen({ client, pageSize = 50 }) {
|
|
|
1617
1849
|
style: styles.input,
|
|
1618
1850
|
"aria-label": "Type",
|
|
1619
1851
|
children: [
|
|
1620
|
-
/* @__PURE__ */
|
|
1621
|
-
/* @__PURE__ */
|
|
1852
|
+
/* @__PURE__ */ jsx13("option", { value: "user", children: "user" }),
|
|
1853
|
+
/* @__PURE__ */ jsx13("option", { value: "workspace", children: "workspace" })
|
|
1622
1854
|
]
|
|
1623
1855
|
}
|
|
1624
1856
|
),
|
|
1625
|
-
/* @__PURE__ */
|
|
1857
|
+
/* @__PURE__ */ jsx13(
|
|
1626
1858
|
"input",
|
|
1627
1859
|
{
|
|
1628
1860
|
value: idInput,
|
|
@@ -1632,11 +1864,11 @@ function SubscriberScreen({ client, pageSize = 50 }) {
|
|
|
1632
1864
|
"aria-label": "Subscriber id"
|
|
1633
1865
|
}
|
|
1634
1866
|
),
|
|
1635
|
-
/* @__PURE__ */
|
|
1636
|
-
/* @__PURE__ */
|
|
1867
|
+
/* @__PURE__ */ jsxs13("button", { type: "submit", style: styles.buttonPrimary, disabled: isLoading, children: [
|
|
1868
|
+
/* @__PURE__ */ jsx13(Icon, { name: "search", size: 14 }),
|
|
1637
1869
|
"Look up"
|
|
1638
1870
|
] }),
|
|
1639
|
-
subscriber ? /* @__PURE__ */
|
|
1871
|
+
subscriber ? /* @__PURE__ */ jsxs13(
|
|
1640
1872
|
"button",
|
|
1641
1873
|
{
|
|
1642
1874
|
type: "button",
|
|
@@ -1647,11 +1879,11 @@ function SubscriberScreen({ client, pageSize = 50 }) {
|
|
|
1647
1879
|
setGranted(null);
|
|
1648
1880
|
},
|
|
1649
1881
|
children: [
|
|
1650
|
-
/* @__PURE__ */
|
|
1882
|
+
/* @__PURE__ */ jsx13(Icon, { name: "back", size: 14 }),
|
|
1651
1883
|
"All subscribers"
|
|
1652
1884
|
]
|
|
1653
1885
|
}
|
|
1654
|
-
) : /* @__PURE__ */
|
|
1886
|
+
) : /* @__PURE__ */ jsx13(
|
|
1655
1887
|
"button",
|
|
1656
1888
|
{
|
|
1657
1889
|
type: "button",
|
|
@@ -1664,18 +1896,18 @@ function SubscriberScreen({ client, pageSize = 50 }) {
|
|
|
1664
1896
|
]
|
|
1665
1897
|
}
|
|
1666
1898
|
),
|
|
1667
|
-
error ? /* @__PURE__ */
|
|
1668
|
-
!subscriber ? /* @__PURE__ */
|
|
1669
|
-
list.error ? /* @__PURE__ */
|
|
1670
|
-
list.subscriptions.length === 0 && !list.isLoading ? /* @__PURE__ */
|
|
1671
|
-
/* @__PURE__ */
|
|
1672
|
-
/* @__PURE__ */
|
|
1673
|
-
/* @__PURE__ */
|
|
1674
|
-
/* @__PURE__ */
|
|
1675
|
-
/* @__PURE__ */
|
|
1899
|
+
error ? /* @__PURE__ */ jsx13("p", { style: styles.error, role: "alert", children: error.explanation }) : null,
|
|
1900
|
+
!subscriber ? /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
1901
|
+
list.error ? /* @__PURE__ */ jsx13("p", { style: styles.error, role: "alert", children: list.error.explanation }) : null,
|
|
1902
|
+
list.subscriptions.length === 0 && !list.isLoading ? /* @__PURE__ */ jsx13(Empty, { icon: "subscriber", title: "No subscribers yet", children: "Subscriptions appear here once someone checks out." }) : /* @__PURE__ */ jsxs13("table", { style: styles.table, children: [
|
|
1903
|
+
/* @__PURE__ */ jsx13("thead", { children: /* @__PURE__ */ jsxs13("tr", { children: [
|
|
1904
|
+
/* @__PURE__ */ jsx13("th", { style: styles.th, children: "Subscriber" }),
|
|
1905
|
+
/* @__PURE__ */ jsx13("th", { style: styles.th, children: "Plan" }),
|
|
1906
|
+
/* @__PURE__ */ jsx13("th", { style: styles.th, children: "Status" }),
|
|
1907
|
+
/* @__PURE__ */ jsx13("th", { style: styles.th, children: "Renews" })
|
|
1676
1908
|
] }) }),
|
|
1677
|
-
/* @__PURE__ */
|
|
1678
|
-
/* @__PURE__ */
|
|
1909
|
+
/* @__PURE__ */ jsx13("tbody", { children: list.subscriptions.map((s) => /* @__PURE__ */ jsxs13("tr", { children: [
|
|
1910
|
+
/* @__PURE__ */ jsx13("td", { style: styles.td, children: /* @__PURE__ */ jsxs13(
|
|
1679
1911
|
"button",
|
|
1680
1912
|
{
|
|
1681
1913
|
type: "button",
|
|
@@ -1688,29 +1920,29 @@ function SubscriberScreen({ client, pageSize = 50 }) {
|
|
|
1688
1920
|
]
|
|
1689
1921
|
}
|
|
1690
1922
|
) }),
|
|
1691
|
-
/* @__PURE__ */
|
|
1692
|
-
/* @__PURE__ */
|
|
1923
|
+
/* @__PURE__ */ jsxs13("td", { style: styles.td, children: [
|
|
1924
|
+
/* @__PURE__ */ jsx13("strong", { children: s.plan }),
|
|
1693
1925
|
" \xB7 ",
|
|
1694
1926
|
s.interval
|
|
1695
1927
|
] }),
|
|
1696
|
-
/* @__PURE__ */
|
|
1697
|
-
/* @__PURE__ */
|
|
1928
|
+
/* @__PURE__ */ jsxs13("td", { style: styles.td, children: [
|
|
1929
|
+
/* @__PURE__ */ jsx13(
|
|
1698
1930
|
Pill,
|
|
1699
1931
|
{
|
|
1700
1932
|
tone: s.status === "active" ? "ok" : s.status === "trialing" ? "info" : s.status === "past_due" ? "warn" : "neutral",
|
|
1701
1933
|
children: s.status
|
|
1702
1934
|
}
|
|
1703
1935
|
),
|
|
1704
|
-
s.cancelAtPeriodEnd ? /* @__PURE__ */
|
|
1936
|
+
s.cancelAtPeriodEnd ? /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
1705
1937
|
" ",
|
|
1706
|
-
/* @__PURE__ */
|
|
1938
|
+
/* @__PURE__ */ jsx13(Pill, { tone: "warn", dot: false, children: "cancels" })
|
|
1707
1939
|
] }) : null
|
|
1708
1940
|
] }),
|
|
1709
|
-
/* @__PURE__ */
|
|
1941
|
+
/* @__PURE__ */ jsx13("td", { style: styles.td, children: s.currentPeriodEnd ? new Date(s.currentPeriodEnd).toLocaleDateString() : /* @__PURE__ */ jsx13("span", { style: styles.muted, children: "\u2014" }) })
|
|
1710
1942
|
] }, s.id)) })
|
|
1711
1943
|
] }),
|
|
1712
|
-
list.isLoading ? /* @__PURE__ */
|
|
1713
|
-
list.hasMore && !list.isLoading ? /* @__PURE__ */
|
|
1944
|
+
list.isLoading ? /* @__PURE__ */ jsx13("p", { style: styles.status, children: "Loading\u2026" }) : null,
|
|
1945
|
+
list.hasMore && !list.isLoading ? /* @__PURE__ */ jsx13(
|
|
1714
1946
|
"button",
|
|
1715
1947
|
{
|
|
1716
1948
|
type: "button",
|
|
@@ -1720,27 +1952,27 @@ function SubscriberScreen({ client, pageSize = 50 }) {
|
|
|
1720
1952
|
}
|
|
1721
1953
|
) : null
|
|
1722
1954
|
] }) : null,
|
|
1723
|
-
subscriber && !isLoading ? /* @__PURE__ */
|
|
1724
|
-
/* @__PURE__ */
|
|
1725
|
-
subscription ? /* @__PURE__ */
|
|
1726
|
-
/* @__PURE__ */
|
|
1727
|
-
/* @__PURE__ */
|
|
1728
|
-
/* @__PURE__ */
|
|
1729
|
-
/* @__PURE__ */
|
|
1955
|
+
subscriber && !isLoading ? /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
1956
|
+
/* @__PURE__ */ jsx13("h2", { style: styles.subtitle, children: "Subscription" }),
|
|
1957
|
+
subscription ? /* @__PURE__ */ jsx13("table", { style: styles.table, children: /* @__PURE__ */ jsxs13("tbody", { children: [
|
|
1958
|
+
/* @__PURE__ */ jsxs13("tr", { children: [
|
|
1959
|
+
/* @__PURE__ */ jsx13("td", { style: styles.td, children: "plan" }),
|
|
1960
|
+
/* @__PURE__ */ jsxs13("td", { style: styles.td, children: [
|
|
1961
|
+
/* @__PURE__ */ jsx13("strong", { children: subscription.plan }),
|
|
1730
1962
|
" \xB7 ",
|
|
1731
1963
|
subscription.interval
|
|
1732
1964
|
] })
|
|
1733
1965
|
] }),
|
|
1734
|
-
/* @__PURE__ */
|
|
1735
|
-
/* @__PURE__ */
|
|
1736
|
-
/* @__PURE__ */
|
|
1966
|
+
/* @__PURE__ */ jsxs13("tr", { children: [
|
|
1967
|
+
/* @__PURE__ */ jsx13("td", { style: styles.td, children: "status" }),
|
|
1968
|
+
/* @__PURE__ */ jsxs13("td", { style: styles.td, children: [
|
|
1737
1969
|
subscription.status,
|
|
1738
1970
|
subscription.cancelAtPeriodEnd ? " \xB7 cancels at period end" : ""
|
|
1739
1971
|
] })
|
|
1740
1972
|
] }),
|
|
1741
|
-
/* @__PURE__ */
|
|
1742
|
-
/* @__PURE__ */
|
|
1743
|
-
/* @__PURE__ */
|
|
1973
|
+
/* @__PURE__ */ jsxs13("tr", { children: [
|
|
1974
|
+
/* @__PURE__ */ jsx13("td", { style: styles.td, children: "period" }),
|
|
1975
|
+
/* @__PURE__ */ jsxs13("td", { style: styles.td, children: [
|
|
1744
1976
|
subscription.currentPeriodStart ? new Date(subscription.currentPeriodStart).toLocaleDateString() : "\u2014",
|
|
1745
1977
|
" ",
|
|
1746
1978
|
"\u2192",
|
|
@@ -1748,14 +1980,14 @@ function SubscriberScreen({ client, pageSize = 50 }) {
|
|
|
1748
1980
|
subscription.currentPeriodEnd ? new Date(subscription.currentPeriodEnd).toLocaleDateString() : "\u2014"
|
|
1749
1981
|
] })
|
|
1750
1982
|
] }),
|
|
1751
|
-
/* @__PURE__ */
|
|
1752
|
-
/* @__PURE__ */
|
|
1753
|
-
/* @__PURE__ */
|
|
1983
|
+
/* @__PURE__ */ jsxs13("tr", { children: [
|
|
1984
|
+
/* @__PURE__ */ jsx13("td", { style: styles.td, children: "provider" }),
|
|
1985
|
+
/* @__PURE__ */ jsx13("td", { style: { ...styles.td, ...styles.mono }, children: subscription.providerSubscriptionId ?? "\u2014" })
|
|
1754
1986
|
] })
|
|
1755
|
-
] }) }) : /* @__PURE__ */
|
|
1756
|
-
/* @__PURE__ */
|
|
1757
|
-
wallet ? /* @__PURE__ */
|
|
1758
|
-
/* @__PURE__ */
|
|
1987
|
+
] }) }) : /* @__PURE__ */ jsx13("p", { style: styles.muted, children: "No subscription." }),
|
|
1988
|
+
/* @__PURE__ */ jsx13("h2", { style: styles.subtitle, children: "Wallet" }),
|
|
1989
|
+
wallet ? /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
1990
|
+
/* @__PURE__ */ jsxs13(
|
|
1759
1991
|
"p",
|
|
1760
1992
|
{
|
|
1761
1993
|
style: {
|
|
@@ -1766,7 +1998,7 @@ function SubscriberScreen({ client, pageSize = 50 }) {
|
|
|
1766
1998
|
flexWrap: "wrap"
|
|
1767
1999
|
},
|
|
1768
2000
|
children: [
|
|
1769
|
-
/* @__PURE__ */
|
|
2001
|
+
/* @__PURE__ */ jsx13(
|
|
1770
2002
|
"strong",
|
|
1771
2003
|
{
|
|
1772
2004
|
style: {
|
|
@@ -1779,7 +2011,7 @@ function SubscriberScreen({ client, pageSize = 50 }) {
|
|
|
1779
2011
|
" ",
|
|
1780
2012
|
wallet.currency,
|
|
1781
2013
|
" ",
|
|
1782
|
-
/* @__PURE__ */
|
|
2014
|
+
/* @__PURE__ */ jsxs13("span", { style: styles.muted, children: [
|
|
1783
2015
|
"(granted ",
|
|
1784
2016
|
wallet.granted ?? "0",
|
|
1785
2017
|
" \xB7 purchased ",
|
|
@@ -1790,7 +2022,7 @@ function SubscriberScreen({ client, pageSize = 50 }) {
|
|
|
1790
2022
|
]
|
|
1791
2023
|
}
|
|
1792
2024
|
),
|
|
1793
|
-
/* @__PURE__ */
|
|
2025
|
+
/* @__PURE__ */ jsxs13(
|
|
1794
2026
|
"form",
|
|
1795
2027
|
{
|
|
1796
2028
|
style: styles.toolbar,
|
|
@@ -1809,7 +2041,7 @@ function SubscriberScreen({ client, pageSize = 50 }) {
|
|
|
1809
2041
|
});
|
|
1810
2042
|
},
|
|
1811
2043
|
children: [
|
|
1812
|
-
/* @__PURE__ */
|
|
2044
|
+
/* @__PURE__ */ jsx13(
|
|
1813
2045
|
"input",
|
|
1814
2046
|
{
|
|
1815
2047
|
value: amount,
|
|
@@ -1819,7 +2051,7 @@ function SubscriberScreen({ client, pageSize = 50 }) {
|
|
|
1819
2051
|
"aria-label": "Amount"
|
|
1820
2052
|
}
|
|
1821
2053
|
),
|
|
1822
|
-
/* @__PURE__ */
|
|
2054
|
+
/* @__PURE__ */ jsx13(
|
|
1823
2055
|
"input",
|
|
1824
2056
|
{
|
|
1825
2057
|
value: note,
|
|
@@ -1829,38 +2061,38 @@ function SubscriberScreen({ client, pageSize = 50 }) {
|
|
|
1829
2061
|
"aria-label": "Reason"
|
|
1830
2062
|
}
|
|
1831
2063
|
),
|
|
1832
|
-
/* @__PURE__ */
|
|
2064
|
+
/* @__PURE__ */ jsxs13(
|
|
1833
2065
|
"button",
|
|
1834
2066
|
{
|
|
1835
2067
|
type: "submit",
|
|
1836
2068
|
style: styles.buttonPrimary,
|
|
1837
2069
|
disabled: !/^\d+$/.test(amount.trim()),
|
|
1838
2070
|
children: [
|
|
1839
|
-
/* @__PURE__ */
|
|
2071
|
+
/* @__PURE__ */ jsx13(Icon, { name: "plus", size: 14 }),
|
|
1840
2072
|
"Grant"
|
|
1841
2073
|
]
|
|
1842
2074
|
}
|
|
1843
2075
|
),
|
|
1844
|
-
granted ? /* @__PURE__ */
|
|
2076
|
+
granted ? /* @__PURE__ */ jsx13("span", { style: styles.ok, children: granted }) : null
|
|
1845
2077
|
]
|
|
1846
2078
|
}
|
|
1847
2079
|
),
|
|
1848
|
-
/* @__PURE__ */
|
|
1849
|
-
ledger.length === 0 ? /* @__PURE__ */
|
|
1850
|
-
/* @__PURE__ */
|
|
1851
|
-
/* @__PURE__ */
|
|
1852
|
-
/* @__PURE__ */
|
|
1853
|
-
/* @__PURE__ */
|
|
1854
|
-
/* @__PURE__ */
|
|
2080
|
+
/* @__PURE__ */ jsx13("h2", { style: styles.subtitle, children: "Ledger" }),
|
|
2081
|
+
ledger.length === 0 ? /* @__PURE__ */ jsx13(Empty, { icon: "subscriber", title: "Nothing moved yet" }) : /* @__PURE__ */ jsxs13("table", { style: styles.table, children: [
|
|
2082
|
+
/* @__PURE__ */ jsx13("thead", { children: /* @__PURE__ */ jsxs13("tr", { children: [
|
|
2083
|
+
/* @__PURE__ */ jsx13("th", { style: styles.th, children: "When" }),
|
|
2084
|
+
/* @__PURE__ */ jsx13("th", { style: styles.th, children: "Kind" }),
|
|
2085
|
+
/* @__PURE__ */ jsx13("th", { style: styles.th, children: "Amount" }),
|
|
2086
|
+
/* @__PURE__ */ jsx13("th", { style: styles.th, children: "Note" })
|
|
1855
2087
|
] }) }),
|
|
1856
|
-
/* @__PURE__ */
|
|
1857
|
-
/* @__PURE__ */
|
|
1858
|
-
/* @__PURE__ */
|
|
1859
|
-
/* @__PURE__ */
|
|
1860
|
-
/* @__PURE__ */
|
|
2088
|
+
/* @__PURE__ */ jsx13("tbody", { children: ledger.map((t2) => /* @__PURE__ */ jsxs13("tr", { children: [
|
|
2089
|
+
/* @__PURE__ */ jsx13("td", { style: { ...styles.td, ...styles.muted }, children: new Date(t2.createdAt).toLocaleString() }),
|
|
2090
|
+
/* @__PURE__ */ jsx13("td", { style: styles.td, children: t2.type }),
|
|
2091
|
+
/* @__PURE__ */ jsx13("td", { style: { ...styles.td, ...styles.mono }, children: t2.amount }),
|
|
2092
|
+
/* @__PURE__ */ jsx13("td", { style: { ...styles.td, ...styles.muted }, children: t2.description ?? "" })
|
|
1861
2093
|
] }, t2.id)) })
|
|
1862
2094
|
] }),
|
|
1863
|
-
hasMoreLedger ? /* @__PURE__ */
|
|
2095
|
+
hasMoreLedger ? /* @__PURE__ */ jsx13(
|
|
1864
2096
|
"button",
|
|
1865
2097
|
{
|
|
1866
2098
|
type: "button",
|
|
@@ -1869,25 +2101,25 @@ function SubscriberScreen({ client, pageSize = 50 }) {
|
|
|
1869
2101
|
children: "Load more"
|
|
1870
2102
|
}
|
|
1871
2103
|
) : null
|
|
1872
|
-
] }) : /* @__PURE__ */
|
|
2104
|
+
] }) : /* @__PURE__ */ jsx13("p", { style: styles.muted, children: "No wallet \u2014 billing has no wallet configuration." })
|
|
1873
2105
|
] }) : null
|
|
1874
2106
|
] });
|
|
1875
2107
|
}
|
|
1876
2108
|
|
|
1877
2109
|
// src/screens/AuditScreen.tsx
|
|
1878
2110
|
import { useAdminAudit } from "@fonderie/react-admin";
|
|
1879
|
-
import { useState as
|
|
1880
|
-
import { jsx as
|
|
2111
|
+
import { useState as useState6 } from "react";
|
|
2112
|
+
import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1881
2113
|
function AuditScreen({ client, pageSize = 50 }) {
|
|
1882
|
-
const [draft, setDraft] =
|
|
1883
|
-
const [filter, setFilter] =
|
|
2114
|
+
const [draft, setDraft] = useState6({ workspaceId: "", type: "", actorId: "" });
|
|
2115
|
+
const [filter, setFilter] = useState6(
|
|
1884
2116
|
{}
|
|
1885
2117
|
);
|
|
1886
2118
|
const { events, hasMore, isLoading, error, refresh, loadMore } = useAdminAudit(client, {
|
|
1887
2119
|
...filter,
|
|
1888
2120
|
limit: pageSize
|
|
1889
2121
|
});
|
|
1890
|
-
const field = (key, placeholder) => /* @__PURE__ */
|
|
2122
|
+
const field = (key, placeholder) => /* @__PURE__ */ jsx14(
|
|
1891
2123
|
"input",
|
|
1892
2124
|
{
|
|
1893
2125
|
value: draft[key],
|
|
@@ -1897,15 +2129,15 @@ function AuditScreen({ client, pageSize = 50 }) {
|
|
|
1897
2129
|
"aria-label": placeholder
|
|
1898
2130
|
}
|
|
1899
2131
|
);
|
|
1900
|
-
return /* @__PURE__ */
|
|
1901
|
-
/* @__PURE__ */
|
|
2132
|
+
return /* @__PURE__ */ jsxs14("div", { style: styles.container, children: [
|
|
2133
|
+
/* @__PURE__ */ jsx14(
|
|
1902
2134
|
PageHeader,
|
|
1903
2135
|
{
|
|
1904
2136
|
title: "Audit",
|
|
1905
2137
|
lead: "What happened, across every workspace unless you name one. The chain's integrity verdict is on the Doctor page."
|
|
1906
2138
|
}
|
|
1907
2139
|
),
|
|
1908
|
-
/* @__PURE__ */
|
|
2140
|
+
/* @__PURE__ */ jsxs14(
|
|
1909
2141
|
"form",
|
|
1910
2142
|
{
|
|
1911
2143
|
style: styles.toolbar,
|
|
@@ -1921,11 +2153,11 @@ function AuditScreen({ client, pageSize = 50 }) {
|
|
|
1921
2153
|
field("workspaceId", "workspace id (all if empty)"),
|
|
1922
2154
|
field("type", "event type"),
|
|
1923
2155
|
field("actorId", "actor id"),
|
|
1924
|
-
/* @__PURE__ */
|
|
1925
|
-
/* @__PURE__ */
|
|
2156
|
+
/* @__PURE__ */ jsxs14("button", { type: "submit", style: styles.buttonPrimary, disabled: isLoading, children: [
|
|
2157
|
+
/* @__PURE__ */ jsx14(Icon, { name: "search", size: 14 }),
|
|
1926
2158
|
"Filter"
|
|
1927
2159
|
] }),
|
|
1928
|
-
/* @__PURE__ */
|
|
2160
|
+
/* @__PURE__ */ jsx14(
|
|
1929
2161
|
"button",
|
|
1930
2162
|
{
|
|
1931
2163
|
type: "button",
|
|
@@ -1938,25 +2170,25 @@ function AuditScreen({ client, pageSize = 50 }) {
|
|
|
1938
2170
|
]
|
|
1939
2171
|
}
|
|
1940
2172
|
),
|
|
1941
|
-
error ? /* @__PURE__ */
|
|
1942
|
-
events.length === 0 && !isLoading ? /* @__PURE__ */
|
|
1943
|
-
/* @__PURE__ */
|
|
1944
|
-
/* @__PURE__ */
|
|
1945
|
-
/* @__PURE__ */
|
|
1946
|
-
/* @__PURE__ */
|
|
1947
|
-
/* @__PURE__ */
|
|
1948
|
-
/* @__PURE__ */
|
|
2173
|
+
error ? /* @__PURE__ */ jsx14("p", { style: styles.error, role: "alert", children: error.explanation }) : null,
|
|
2174
|
+
events.length === 0 && !isLoading ? /* @__PURE__ */ jsx14(Empty, { icon: "audit", title: "Nothing recorded for this filter" }) : /* @__PURE__ */ jsxs14("table", { style: styles.table, children: [
|
|
2175
|
+
/* @__PURE__ */ jsx14("thead", { children: /* @__PURE__ */ jsxs14("tr", { children: [
|
|
2176
|
+
/* @__PURE__ */ jsx14("th", { style: styles.th, children: "When" }),
|
|
2177
|
+
/* @__PURE__ */ jsx14("th", { style: styles.th, children: "Type" }),
|
|
2178
|
+
/* @__PURE__ */ jsx14("th", { style: styles.th, children: "Workspace" }),
|
|
2179
|
+
/* @__PURE__ */ jsx14("th", { style: styles.th, children: "Actor" }),
|
|
2180
|
+
/* @__PURE__ */ jsx14("th", { style: styles.th, children: "Request" })
|
|
1949
2181
|
] }) }),
|
|
1950
|
-
/* @__PURE__ */
|
|
1951
|
-
/* @__PURE__ */
|
|
1952
|
-
/* @__PURE__ */
|
|
1953
|
-
/* @__PURE__ */
|
|
1954
|
-
/* @__PURE__ */
|
|
1955
|
-
/* @__PURE__ */
|
|
2182
|
+
/* @__PURE__ */ jsx14("tbody", { children: events.map((e) => /* @__PURE__ */ jsxs14("tr", { children: [
|
|
2183
|
+
/* @__PURE__ */ jsx14("td", { style: { ...styles.td, ...styles.muted }, children: new Date(e.createdAt).toLocaleString() }),
|
|
2184
|
+
/* @__PURE__ */ jsx14("td", { style: { ...styles.td, ...styles.mono }, children: e.type }),
|
|
2185
|
+
/* @__PURE__ */ jsx14("td", { style: { ...styles.td, ...styles.mono }, children: String(e.payload["workspaceId"] ?? "\u2014") }),
|
|
2186
|
+
/* @__PURE__ */ jsx14("td", { style: { ...styles.td, ...styles.mono }, children: e.actorId ?? "\u2014" }),
|
|
2187
|
+
/* @__PURE__ */ jsx14("td", { style: { ...styles.td, ...styles.muted }, children: e.requestId ?? "" })
|
|
1956
2188
|
] }, e.id)) })
|
|
1957
2189
|
] }),
|
|
1958
|
-
isLoading ? /* @__PURE__ */
|
|
1959
|
-
hasMore && !isLoading ? /* @__PURE__ */
|
|
2190
|
+
isLoading ? /* @__PURE__ */ jsx14("p", { style: styles.status, children: "Loading\u2026" }) : null,
|
|
2191
|
+
hasMore && !isLoading ? /* @__PURE__ */ jsx14(
|
|
1960
2192
|
"button",
|
|
1961
2193
|
{
|
|
1962
2194
|
type: "button",
|
|
@@ -1969,7 +2201,7 @@ function AuditScreen({ client, pageSize = 50 }) {
|
|
|
1969
2201
|
}
|
|
1970
2202
|
|
|
1971
2203
|
// src/screens/AdminShell.tsx
|
|
1972
|
-
import { Fragment as
|
|
2204
|
+
import { Fragment as Fragment9, jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1973
2205
|
var ICON = {
|
|
1974
2206
|
attention: "attention",
|
|
1975
2207
|
modules: "modules",
|
|
@@ -1984,12 +2216,13 @@ var ICON = {
|
|
|
1984
2216
|
audit: "audit",
|
|
1985
2217
|
log: "log",
|
|
1986
2218
|
tokens: "tokens",
|
|
2219
|
+
operators: "users",
|
|
1987
2220
|
migrations: "migrations"
|
|
1988
2221
|
};
|
|
1989
2222
|
var NARROW = "(max-width: 820px)";
|
|
1990
2223
|
function useNarrow() {
|
|
1991
2224
|
const query = typeof window !== "undefined" && window.matchMedia ? window.matchMedia(NARROW) : null;
|
|
1992
|
-
const [narrow, setNarrow] =
|
|
2225
|
+
const [narrow, setNarrow] = useState7(() => query?.matches ?? false);
|
|
1993
2226
|
useEffect(() => {
|
|
1994
2227
|
if (!query) return;
|
|
1995
2228
|
const on = (e) => setNarrow(e.matches);
|
|
@@ -2024,7 +2257,8 @@ var NAV = [
|
|
|
2024
2257
|
items: [
|
|
2025
2258
|
{ page: "audit", label: "Audit", needs: "audit" },
|
|
2026
2259
|
{ page: "log", label: "Admin log" },
|
|
2027
|
-
{ page: "
|
|
2260
|
+
{ page: "operators", label: "Operators", needs: "operators" },
|
|
2261
|
+
{ page: "tokens", label: "Tokens" },
|
|
2028
2262
|
{ page: "migrations", label: "Migrations" }
|
|
2029
2263
|
]
|
|
2030
2264
|
}
|
|
@@ -2041,70 +2275,76 @@ function AdminShell({
|
|
|
2041
2275
|
onNavigate,
|
|
2042
2276
|
appName = "Admin",
|
|
2043
2277
|
envLabel,
|
|
2044
|
-
footer
|
|
2278
|
+
footer,
|
|
2279
|
+
operators = false,
|
|
2280
|
+
currentOperator
|
|
2045
2281
|
}) {
|
|
2046
2282
|
const narrow = useNarrow();
|
|
2047
|
-
const [drawer, setDrawer] =
|
|
2048
|
-
const [own, setOwn] =
|
|
2283
|
+
const [drawer, setDrawer] = useState7(false);
|
|
2284
|
+
const [own, setOwn] = useState7("attention");
|
|
2049
2285
|
const current = page ?? own;
|
|
2050
2286
|
const go = (p) => {
|
|
2051
2287
|
if (onNavigate) onNavigate(p);
|
|
2052
2288
|
if (page === void 0) setOwn(p);
|
|
2053
2289
|
setDrawer(false);
|
|
2054
2290
|
};
|
|
2055
|
-
const [editing, setEditing] =
|
|
2291
|
+
const [editing, setEditing] = useState7(null);
|
|
2056
2292
|
const has = {
|
|
2057
2293
|
config: Boolean(configClient),
|
|
2058
2294
|
courier: Boolean(courierClient),
|
|
2059
2295
|
auth: Boolean(authClient),
|
|
2060
2296
|
billing: Boolean(billingClient),
|
|
2061
|
-
audit: Boolean(auditClient)
|
|
2297
|
+
audit: Boolean(auditClient),
|
|
2298
|
+
operators
|
|
2062
2299
|
};
|
|
2063
2300
|
let body;
|
|
2064
2301
|
switch (current) {
|
|
2065
2302
|
case "attention":
|
|
2066
|
-
body = /* @__PURE__ */
|
|
2303
|
+
body = /* @__PURE__ */ jsx15(AttentionScreen, { client });
|
|
2067
2304
|
break;
|
|
2068
2305
|
case "modules":
|
|
2069
|
-
body = /* @__PURE__ */
|
|
2306
|
+
body = /* @__PURE__ */ jsx15(ModulesScreen, { client });
|
|
2070
2307
|
break;
|
|
2071
2308
|
case "doctor":
|
|
2072
|
-
body = /* @__PURE__ */
|
|
2309
|
+
body = /* @__PURE__ */ jsx15(DoctorScreen, { client });
|
|
2073
2310
|
break;
|
|
2074
2311
|
case "environment":
|
|
2075
|
-
body = /* @__PURE__ */
|
|
2312
|
+
body = /* @__PURE__ */ jsx15(EnvironmentScreen, { client });
|
|
2076
2313
|
break;
|
|
2077
2314
|
case "routes":
|
|
2078
|
-
body = /* @__PURE__ */
|
|
2315
|
+
body = /* @__PURE__ */ jsx15(RoutesScreen, { client });
|
|
2079
2316
|
break;
|
|
2080
2317
|
case "tokens":
|
|
2081
|
-
body = /* @__PURE__ */
|
|
2318
|
+
body = /* @__PURE__ */ jsx15(TokensScreen, { client });
|
|
2319
|
+
break;
|
|
2320
|
+
case "operators":
|
|
2321
|
+
body = /* @__PURE__ */ jsx15(OperatorsScreen, { client, me: currentOperator });
|
|
2082
2322
|
break;
|
|
2083
2323
|
case "migrations":
|
|
2084
|
-
body = /* @__PURE__ */
|
|
2324
|
+
body = /* @__PURE__ */ jsx15(MigrationsScreen, { client });
|
|
2085
2325
|
break;
|
|
2086
2326
|
case "log":
|
|
2087
|
-
body = /* @__PURE__ */
|
|
2327
|
+
body = /* @__PURE__ */ jsx15(AdminLogScreen, { client });
|
|
2088
2328
|
break;
|
|
2089
2329
|
case "catalog":
|
|
2090
|
-
body = billingClient ? /* @__PURE__ */
|
|
2330
|
+
body = billingClient ? /* @__PURE__ */ jsx15(CatalogScreen, { client: billingClient }) : /* @__PURE__ */ jsx15("p", { style: { ...styles.status, padding: "32px 40px" }, children: "Pass a BillingAdminClient to see the catalog here." });
|
|
2091
2331
|
break;
|
|
2092
2332
|
case "subscriber":
|
|
2093
|
-
body = billingClient ? /* @__PURE__ */
|
|
2333
|
+
body = billingClient ? /* @__PURE__ */ jsx15(SubscriberScreen, { client: billingClient }) : /* @__PURE__ */ jsx15("p", { style: { ...styles.status, padding: "32px 40px" }, children: "Pass a BillingAdminClient to look up subscribers here." });
|
|
2094
2334
|
break;
|
|
2095
2335
|
case "audit":
|
|
2096
|
-
body = auditClient ? /* @__PURE__ */
|
|
2336
|
+
body = auditClient ? /* @__PURE__ */ jsx15(AuditScreen, { client: auditClient }) : /* @__PURE__ */ jsx15("p", { style: { ...styles.status, padding: "32px 40px" }, children: "Pass an AuditAdminClient to see the audit trail here." });
|
|
2097
2337
|
break;
|
|
2098
2338
|
case "users":
|
|
2099
|
-
body = authClient ? /* @__PURE__ */
|
|
2339
|
+
body = authClient ? /* @__PURE__ */ jsx15(UsersScreen, { client: authClient }) : /* @__PURE__ */ jsx15("p", { style: { ...styles.status, padding: "32px 40px" }, children: "Pass an AuthAdminClient to look up users here." });
|
|
2100
2340
|
break;
|
|
2101
2341
|
case "settings":
|
|
2102
|
-
body = !configClient ? /* @__PURE__ */
|
|
2103
|
-
/* @__PURE__ */
|
|
2104
|
-
/* @__PURE__ */
|
|
2342
|
+
body = !configClient ? /* @__PURE__ */ jsx15("p", { style: { ...styles.status, padding: "32px 40px" }, children: "Pass a ConfigAdminClient to manage config and secrets here." }) : editing && editing.kind !== "template" ? /* @__PURE__ */ jsxs15(Fragment9, { children: [
|
|
2343
|
+
/* @__PURE__ */ jsx15("div", { style: { padding: "24px 40px 0" }, children: /* @__PURE__ */ jsxs15("button", { type: "button", style: styles.buttonGhost, onClick: () => setEditing(null), children: [
|
|
2344
|
+
/* @__PURE__ */ jsx15(Icon, { name: "back", size: 14 }),
|
|
2105
2345
|
"Config & secrets"
|
|
2106
2346
|
] }) }),
|
|
2107
|
-
/* @__PURE__ */
|
|
2347
|
+
/* @__PURE__ */ jsx15(
|
|
2108
2348
|
ConfigEditorScreen,
|
|
2109
2349
|
{
|
|
2110
2350
|
client: configClient,
|
|
@@ -2114,7 +2354,7 @@ function AdminShell({
|
|
|
2114
2354
|
onSaved: () => setEditing(null)
|
|
2115
2355
|
}
|
|
2116
2356
|
)
|
|
2117
|
-
] }) : /* @__PURE__ */
|
|
2357
|
+
] }) : /* @__PURE__ */ jsx15(
|
|
2118
2358
|
ConfigListScreen,
|
|
2119
2359
|
{
|
|
2120
2360
|
client: configClient,
|
|
@@ -2127,12 +2367,12 @@ function AdminShell({
|
|
|
2127
2367
|
);
|
|
2128
2368
|
break;
|
|
2129
2369
|
case "templates":
|
|
2130
|
-
body = !courierClient ? /* @__PURE__ */
|
|
2131
|
-
/* @__PURE__ */
|
|
2132
|
-
/* @__PURE__ */
|
|
2370
|
+
body = !courierClient ? /* @__PURE__ */ jsx15("p", { style: { ...styles.status, padding: "32px 40px" }, children: "Pass a CourierAdminClient to manage templates here." }) : editing?.kind === "template" ? /* @__PURE__ */ jsxs15(Fragment9, { children: [
|
|
2371
|
+
/* @__PURE__ */ jsx15("div", { style: { padding: "24px 40px 0" }, children: /* @__PURE__ */ jsxs15("button", { type: "button", style: styles.buttonGhost, onClick: () => setEditing(null), children: [
|
|
2372
|
+
/* @__PURE__ */ jsx15(Icon, { name: "back", size: 14 }),
|
|
2133
2373
|
"Templates"
|
|
2134
2374
|
] }) }),
|
|
2135
|
-
/* @__PURE__ */
|
|
2375
|
+
/* @__PURE__ */ jsx15(
|
|
2136
2376
|
TemplateEditorScreen,
|
|
2137
2377
|
{
|
|
2138
2378
|
client: courierClient,
|
|
@@ -2140,7 +2380,7 @@ function AdminShell({
|
|
|
2140
2380
|
onSaved: () => setEditing(null)
|
|
2141
2381
|
}
|
|
2142
2382
|
)
|
|
2143
|
-
] }) : /* @__PURE__ */
|
|
2383
|
+
] }) : /* @__PURE__ */ jsx15(
|
|
2144
2384
|
TemplateListScreen,
|
|
2145
2385
|
{
|
|
2146
2386
|
client: courierClient,
|
|
@@ -2150,11 +2390,11 @@ function AdminShell({
|
|
|
2150
2390
|
break;
|
|
2151
2391
|
}
|
|
2152
2392
|
const production = envLabel ? /^prod/i.test(envLabel) : false;
|
|
2153
|
-
const brand = /* @__PURE__ */
|
|
2154
|
-
/* @__PURE__ */
|
|
2155
|
-
/* @__PURE__ */
|
|
2156
|
-
/* @__PURE__ */
|
|
2157
|
-
envLabel ? /* @__PURE__ */
|
|
2393
|
+
const brand = /* @__PURE__ */ jsxs15("div", { style: styles.navBrand, children: [
|
|
2394
|
+
/* @__PURE__ */ jsx15("div", { style: styles.navMark, children: /* @__PURE__ */ jsx15(Icon, { name: "mark", size: 15 }) }),
|
|
2395
|
+
/* @__PURE__ */ jsxs15("div", { style: { minWidth: 0, flex: 1 }, children: [
|
|
2396
|
+
/* @__PURE__ */ jsx15("div", { style: styles.navBrandTitle, children: appName }),
|
|
2397
|
+
envLabel ? /* @__PURE__ */ jsx15(
|
|
2158
2398
|
"span",
|
|
2159
2399
|
{
|
|
2160
2400
|
style: {
|
|
@@ -2171,18 +2411,18 @@ function AdminShell({
|
|
|
2171
2411
|
}
|
|
2172
2412
|
) : null
|
|
2173
2413
|
] }),
|
|
2174
|
-
narrow ? /* @__PURE__ */
|
|
2414
|
+
narrow ? /* @__PURE__ */ jsx15(
|
|
2175
2415
|
"button",
|
|
2176
2416
|
{
|
|
2177
2417
|
type: "button",
|
|
2178
2418
|
style: styles.buttonGhost,
|
|
2179
2419
|
"aria-label": "Close menu",
|
|
2180
2420
|
onClick: () => setDrawer(false),
|
|
2181
|
-
children: /* @__PURE__ */
|
|
2421
|
+
children: /* @__PURE__ */ jsx15(Icon, { name: "close" })
|
|
2182
2422
|
}
|
|
2183
2423
|
) : null
|
|
2184
2424
|
] });
|
|
2185
|
-
const nav = /* @__PURE__ */
|
|
2425
|
+
const nav = /* @__PURE__ */ jsxs15(
|
|
2186
2426
|
"nav",
|
|
2187
2427
|
{
|
|
2188
2428
|
style: {
|
|
@@ -2192,14 +2432,14 @@ function AdminShell({
|
|
|
2192
2432
|
"aria-label": "Admin",
|
|
2193
2433
|
children: [
|
|
2194
2434
|
brand,
|
|
2195
|
-
/* @__PURE__ */
|
|
2435
|
+
/* @__PURE__ */ jsx15("div", { style: styles.navScroll, children: NAV.map((g) => {
|
|
2196
2436
|
const items = g.items.filter((i) => !i.needs || has[i.needs]);
|
|
2197
2437
|
if (items.length === 0) return null;
|
|
2198
|
-
return /* @__PURE__ */
|
|
2199
|
-
/* @__PURE__ */
|
|
2438
|
+
return /* @__PURE__ */ jsxs15("div", { children: [
|
|
2439
|
+
/* @__PURE__ */ jsx15("div", { style: styles.navGroup, children: g.group }),
|
|
2200
2440
|
items.map((i) => {
|
|
2201
2441
|
const active = current === i.page;
|
|
2202
|
-
return /* @__PURE__ */
|
|
2442
|
+
return /* @__PURE__ */ jsxs15(
|
|
2203
2443
|
"button",
|
|
2204
2444
|
{
|
|
2205
2445
|
type: "button",
|
|
@@ -2211,7 +2451,7 @@ function AdminShell({
|
|
|
2211
2451
|
go(i.page);
|
|
2212
2452
|
},
|
|
2213
2453
|
children: [
|
|
2214
|
-
/* @__PURE__ */
|
|
2454
|
+
/* @__PURE__ */ jsx15(Icon, { name: ICON[i.page], style: active ? styles.navIconActive : void 0 }),
|
|
2215
2455
|
i.label
|
|
2216
2456
|
]
|
|
2217
2457
|
},
|
|
@@ -2220,15 +2460,15 @@ function AdminShell({
|
|
|
2220
2460
|
})
|
|
2221
2461
|
] }, g.group);
|
|
2222
2462
|
}) }),
|
|
2223
|
-
footer ? /* @__PURE__ */
|
|
2463
|
+
footer ? /* @__PURE__ */ jsx15("div", { style: styles.navFooter, children: footer }) : null
|
|
2224
2464
|
]
|
|
2225
2465
|
}
|
|
2226
2466
|
);
|
|
2227
2467
|
const title = NAV.flatMap((g) => g.items).find((i) => i.page === current)?.label ?? "";
|
|
2228
|
-
return /* @__PURE__ */
|
|
2229
|
-
narrow ? /* @__PURE__ */
|
|
2230
|
-
/* @__PURE__ */
|
|
2231
|
-
/* @__PURE__ */
|
|
2468
|
+
return /* @__PURE__ */ jsxs15("div", { style: { ...styles.shell, ...narrow ? { flexDirection: "column" } : {} }, children: [
|
|
2469
|
+
narrow ? /* @__PURE__ */ jsxs15(Fragment9, { children: [
|
|
2470
|
+
/* @__PURE__ */ jsxs15("div", { style: styles.topbar, children: [
|
|
2471
|
+
/* @__PURE__ */ jsx15(
|
|
2232
2472
|
"button",
|
|
2233
2473
|
{
|
|
2234
2474
|
type: "button",
|
|
@@ -2236,18 +2476,18 @@ function AdminShell({
|
|
|
2236
2476
|
"aria-label": "Open menu",
|
|
2237
2477
|
"aria-expanded": drawer,
|
|
2238
2478
|
onClick: () => setDrawer(true),
|
|
2239
|
-
children: /* @__PURE__ */
|
|
2479
|
+
children: /* @__PURE__ */ jsx15(Icon, { name: "menu" })
|
|
2240
2480
|
}
|
|
2241
2481
|
),
|
|
2242
|
-
/* @__PURE__ */
|
|
2243
|
-
envLabel ? /* @__PURE__ */
|
|
2482
|
+
/* @__PURE__ */ jsx15("span", { style: { fontWeight: 600, fontSize: 14 }, children: title }),
|
|
2483
|
+
envLabel ? /* @__PURE__ */ jsx15("span", { style: { ...styles.badge, marginLeft: "auto" }, children: envLabel }) : null
|
|
2244
2484
|
] }),
|
|
2245
|
-
drawer ? /* @__PURE__ */
|
|
2485
|
+
drawer ? /* @__PURE__ */ jsxs15("div", { style: styles.drawer, children: [
|
|
2246
2486
|
nav,
|
|
2247
|
-
/* @__PURE__ */
|
|
2487
|
+
/* @__PURE__ */ jsx15("div", { style: styles.scrim, onClick: () => setDrawer(false), "aria-hidden": "true" })
|
|
2248
2488
|
] }) : null
|
|
2249
2489
|
] }) : nav,
|
|
2250
|
-
/* @__PURE__ */
|
|
2490
|
+
/* @__PURE__ */ jsx15("main", { className: "fonderie-admin-main", style: styles.main, children: body })
|
|
2251
2491
|
] });
|
|
2252
2492
|
}
|
|
2253
2493
|
export {
|
|
@@ -2260,6 +2500,7 @@ export {
|
|
|
2260
2500
|
EnvironmentScreen,
|
|
2261
2501
|
MigrationsScreen,
|
|
2262
2502
|
ModulesScreen,
|
|
2503
|
+
OperatorsScreen,
|
|
2263
2504
|
RoutesScreen,
|
|
2264
2505
|
SubscriberScreen,
|
|
2265
2506
|
TokensScreen,
|