@fonderie/vue-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 +494 -203
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +44 -2
- package/dist/index.d.ts +44 -2
- package/dist/index.js +475 -185
- 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.ts
|
|
2
2
|
import { ConfigEditorScreen, ConfigListScreen } from "@fonderie/vue-config-admin-screens";
|
|
3
3
|
import { TemplateEditorScreen, TemplateListScreen } from "@fonderie/vue-courier-admin-screens";
|
|
4
|
-
import { computed as computed2, defineComponent as
|
|
4
|
+
import { computed as computed2, defineComponent as defineComponent14, h as h16, onBeforeUnmount, onMounted, ref as ref7 } from "vue";
|
|
5
5
|
|
|
6
6
|
// src/styles.ts
|
|
7
7
|
var t = {
|
|
@@ -1167,42 +1167,319 @@ var MigrationsScreen = defineComponent7({
|
|
|
1167
1167
|
}
|
|
1168
1168
|
});
|
|
1169
1169
|
|
|
1170
|
+
// src/screens/OperatorsScreen.ts
|
|
1171
|
+
import { useAdminOperators } from "@fonderie/vue-admin";
|
|
1172
|
+
import { defineComponent as defineComponent8, h as h10, ref as ref2 } from "vue";
|
|
1173
|
+
var LEVELS = [
|
|
1174
|
+
{ label: "Read only", scopes: ["read"], hint: "look around, change nothing" },
|
|
1175
|
+
{ label: "Editor", scopes: ["read", "write"], hint: "change config, templates, users" },
|
|
1176
|
+
{
|
|
1177
|
+
label: "Owner",
|
|
1178
|
+
scopes: ["read", "write", "secrets"],
|
|
1179
|
+
hint: "secrets, tokens and operators too"
|
|
1180
|
+
}
|
|
1181
|
+
];
|
|
1182
|
+
var levelOf = (scopes) => scopes.includes("secrets") ? "Owner" : scopes.includes("write") ? "Editor" : "Read only";
|
|
1183
|
+
var scopesFor = (label) => LEVELS.find((l) => l.label === label)?.scopes ?? ["read"];
|
|
1184
|
+
var small = { height: "28px" };
|
|
1185
|
+
var OperatorsScreen = defineComponent8({
|
|
1186
|
+
name: "FonderieOperatorsScreen",
|
|
1187
|
+
props: {
|
|
1188
|
+
client: { type: Object, required: true },
|
|
1189
|
+
// The signed-in operator's email: their own row offers no disable or
|
|
1190
|
+
// recovery (the server refuses both for yourself anyway).
|
|
1191
|
+
me: { type: String, default: void 0 }
|
|
1192
|
+
},
|
|
1193
|
+
setup(props) {
|
|
1194
|
+
const { report, isLoading, error, invite, recover, update, revokeLink } = useAdminOperators(
|
|
1195
|
+
props.client
|
|
1196
|
+
);
|
|
1197
|
+
const email = ref2("");
|
|
1198
|
+
const level = ref2("Editor");
|
|
1199
|
+
const minted = ref2(null);
|
|
1200
|
+
const copied = ref2(false);
|
|
1201
|
+
const status = (o) => o.disabledAt ? pill("neutral", "disabled") : o.locked ? pill("warn", "locked") : !o.enrolled ? pill("warn", "setting up") : pill("ok", "active");
|
|
1202
|
+
const mintedNotice = (link) => {
|
|
1203
|
+
const url = `${window.location.origin}${link.url}`;
|
|
1204
|
+
return h10(
|
|
1205
|
+
"div",
|
|
1206
|
+
{
|
|
1207
|
+
style: {
|
|
1208
|
+
...styles.notice,
|
|
1209
|
+
background: "color-mix(in srgb, var(--fonderie-accent,#00d294) 10%, transparent)",
|
|
1210
|
+
borderColor: "color-mix(in srgb, var(--fonderie-accent,#00d294) 35%, transparent)"
|
|
1211
|
+
}
|
|
1212
|
+
},
|
|
1213
|
+
[
|
|
1214
|
+
h10("strong", `Send this link to ${link.email}. It is shown once.`),
|
|
1215
|
+
` It works once and expires ${new Date(link.expiresAt).toLocaleString()}.`,
|
|
1216
|
+
h10(
|
|
1217
|
+
"div",
|
|
1218
|
+
{ style: { display: "flex", gap: "8px", marginTop: "8px", alignItems: "center" } },
|
|
1219
|
+
[
|
|
1220
|
+
h10(
|
|
1221
|
+
"code",
|
|
1222
|
+
{ style: { ...styles.code, flex: 1, padding: "7px 10px", wordBreak: "break-all" } },
|
|
1223
|
+
url
|
|
1224
|
+
),
|
|
1225
|
+
h10(
|
|
1226
|
+
"button",
|
|
1227
|
+
{
|
|
1228
|
+
type: "button",
|
|
1229
|
+
style: styles.button,
|
|
1230
|
+
onClick: () => {
|
|
1231
|
+
void navigator.clipboard?.writeText(url);
|
|
1232
|
+
copied.value = true;
|
|
1233
|
+
}
|
|
1234
|
+
},
|
|
1235
|
+
copied.value ? "Copied" : "Copy"
|
|
1236
|
+
),
|
|
1237
|
+
h10(
|
|
1238
|
+
"button",
|
|
1239
|
+
{
|
|
1240
|
+
type: "button",
|
|
1241
|
+
style: styles.buttonGhost,
|
|
1242
|
+
"aria-label": "Dismiss",
|
|
1243
|
+
onClick: () => {
|
|
1244
|
+
minted.value = null;
|
|
1245
|
+
copied.value = false;
|
|
1246
|
+
}
|
|
1247
|
+
},
|
|
1248
|
+
[icon("close", 14)]
|
|
1249
|
+
)
|
|
1250
|
+
]
|
|
1251
|
+
)
|
|
1252
|
+
]
|
|
1253
|
+
);
|
|
1254
|
+
};
|
|
1255
|
+
const setMinted = (l) => {
|
|
1256
|
+
copied.value = false;
|
|
1257
|
+
minted.value = l;
|
|
1258
|
+
};
|
|
1259
|
+
return () => {
|
|
1260
|
+
const r = report.value;
|
|
1261
|
+
const e = error.value;
|
|
1262
|
+
return h10("div", { style: styles.container }, [
|
|
1263
|
+
pageHeader(
|
|
1264
|
+
"Operators",
|
|
1265
|
+
"The people who can sign in to this console. Each one uses a password and an authenticator app; there is no sign-up."
|
|
1266
|
+
),
|
|
1267
|
+
e ? h10(
|
|
1268
|
+
"p",
|
|
1269
|
+
{ style: styles.error, role: "alert" },
|
|
1270
|
+
e.status === 403 && e.reason === "FORBIDDEN" ? "Managing operators needs the Owner level." : e.explanation
|
|
1271
|
+
) : null,
|
|
1272
|
+
minted.value ? mintedNotice(minted.value) : null,
|
|
1273
|
+
h10(
|
|
1274
|
+
"form",
|
|
1275
|
+
{
|
|
1276
|
+
style: {
|
|
1277
|
+
...styles.card,
|
|
1278
|
+
display: "flex",
|
|
1279
|
+
gap: "8px",
|
|
1280
|
+
alignItems: "center",
|
|
1281
|
+
flexWrap: "wrap",
|
|
1282
|
+
marginBottom: "20px"
|
|
1283
|
+
},
|
|
1284
|
+
onSubmit: (ev) => {
|
|
1285
|
+
ev.preventDefault();
|
|
1286
|
+
void invite({ email: email.value.trim(), scopes: scopesFor(level.value) }).then((l) => {
|
|
1287
|
+
setMinted(l);
|
|
1288
|
+
email.value = "";
|
|
1289
|
+
}).catch(() => {
|
|
1290
|
+
});
|
|
1291
|
+
}
|
|
1292
|
+
},
|
|
1293
|
+
[
|
|
1294
|
+
icon("users", 16),
|
|
1295
|
+
h10("strong", { style: { fontSize: "13.5px", marginRight: "4px" } }, "Invite"),
|
|
1296
|
+
h10("input", {
|
|
1297
|
+
type: "email",
|
|
1298
|
+
required: true,
|
|
1299
|
+
value: email.value,
|
|
1300
|
+
onInput: (ev) => email.value = ev.target.value,
|
|
1301
|
+
placeholder: "teammate@company.com",
|
|
1302
|
+
style: { ...styles.input, flex: 1, minWidth: "220px" },
|
|
1303
|
+
"aria-label": "Email to invite"
|
|
1304
|
+
}),
|
|
1305
|
+
h10(
|
|
1306
|
+
"select",
|
|
1307
|
+
{
|
|
1308
|
+
value: level.value,
|
|
1309
|
+
onChange: (ev) => level.value = ev.target.value,
|
|
1310
|
+
style: styles.input,
|
|
1311
|
+
"aria-label": "Access level"
|
|
1312
|
+
},
|
|
1313
|
+
LEVELS.map(
|
|
1314
|
+
(l) => h10("option", { key: l.label, value: l.label }, `${l.label} \u2014 ${l.hint}`)
|
|
1315
|
+
)
|
|
1316
|
+
),
|
|
1317
|
+
h10(
|
|
1318
|
+
"button",
|
|
1319
|
+
{ type: "submit", style: styles.buttonPrimary, disabled: !email.value.trim() },
|
|
1320
|
+
[icon("plus", 14), "Create invite link"]
|
|
1321
|
+
)
|
|
1322
|
+
]
|
|
1323
|
+
),
|
|
1324
|
+
isLoading.value && !r ? h10("p", { style: styles.status }, "Loading\u2026") : r && r.operators.length === 0 ? empty("No operators yet", void 0, "users") : r ? table(
|
|
1325
|
+
["Operator", "Access", "Status", "Last sign-in", ""],
|
|
1326
|
+
r.operators.map((o) => {
|
|
1327
|
+
const mine = o.email === props.me;
|
|
1328
|
+
return h10("tr", { key: o.id }, [
|
|
1329
|
+
td([
|
|
1330
|
+
h10("div", { style: { fontWeight: 600 } }, o.name || o.email),
|
|
1331
|
+
o.name ? h10("div", { style: styles.muted }, o.email) : null
|
|
1332
|
+
]),
|
|
1333
|
+
td(
|
|
1334
|
+
h10(
|
|
1335
|
+
"select",
|
|
1336
|
+
{
|
|
1337
|
+
value: levelOf(o.scopes),
|
|
1338
|
+
disabled: mine,
|
|
1339
|
+
onChange: (ev) => void update(o.id, {
|
|
1340
|
+
scopes: scopesFor(ev.target.value)
|
|
1341
|
+
}).catch(() => {
|
|
1342
|
+
}),
|
|
1343
|
+
style: { ...styles.input, ...small, fontSize: "12.5px" },
|
|
1344
|
+
"aria-label": `Access level for ${o.email}`
|
|
1345
|
+
},
|
|
1346
|
+
LEVELS.map((l) => h10("option", { key: l.label, value: l.label }, l.label))
|
|
1347
|
+
)
|
|
1348
|
+
),
|
|
1349
|
+
td([
|
|
1350
|
+
status(o),
|
|
1351
|
+
o.enrolled && o.backupCodesLeft <= 2 && !o.disabledAt ? h10(
|
|
1352
|
+
"div",
|
|
1353
|
+
{ style: { ...styles.muted, marginTop: "4px" } },
|
|
1354
|
+
`${o.backupCodesLeft} backup code(s) left`
|
|
1355
|
+
) : null
|
|
1356
|
+
]),
|
|
1357
|
+
td(o.lastLoginAt ? new Date(o.lastLoginAt).toLocaleString() : "never", {
|
|
1358
|
+
...styles.muted,
|
|
1359
|
+
whiteSpace: "nowrap"
|
|
1360
|
+
}),
|
|
1361
|
+
td(
|
|
1362
|
+
mine ? h10("span", { style: styles.muted }, "you") : [
|
|
1363
|
+
h10(
|
|
1364
|
+
"button",
|
|
1365
|
+
{
|
|
1366
|
+
type: "button",
|
|
1367
|
+
style: { ...styles.button, ...small, marginRight: "6px" },
|
|
1368
|
+
onClick: () => {
|
|
1369
|
+
if (window.confirm(
|
|
1370
|
+
`Create a recovery link for ${o.email}? It signs them out everywhere; the link sets a new password and a new authenticator.`
|
|
1371
|
+
))
|
|
1372
|
+
void recover(o.id).then(setMinted).catch(() => {
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1375
|
+
},
|
|
1376
|
+
"Recovery link"
|
|
1377
|
+
),
|
|
1378
|
+
h10(
|
|
1379
|
+
"button",
|
|
1380
|
+
{
|
|
1381
|
+
type: "button",
|
|
1382
|
+
style: {
|
|
1383
|
+
...o.disabledAt ? styles.button : styles.buttonDanger,
|
|
1384
|
+
...small
|
|
1385
|
+
},
|
|
1386
|
+
onClick: () => {
|
|
1387
|
+
if (o.disabledAt || window.confirm(
|
|
1388
|
+
`Disable ${o.email}? They are signed out immediately.`
|
|
1389
|
+
))
|
|
1390
|
+
void update(o.id, { disabled: !o.disabledAt }).catch(
|
|
1391
|
+
() => {
|
|
1392
|
+
}
|
|
1393
|
+
);
|
|
1394
|
+
}
|
|
1395
|
+
},
|
|
1396
|
+
o.disabledAt ? "Enable" : "Disable"
|
|
1397
|
+
)
|
|
1398
|
+
],
|
|
1399
|
+
{ textAlign: "right", whiteSpace: "nowrap" }
|
|
1400
|
+
)
|
|
1401
|
+
]);
|
|
1402
|
+
})
|
|
1403
|
+
) : null,
|
|
1404
|
+
r && r.links.length > 0 ? [
|
|
1405
|
+
h10("h2", { style: styles.subtitle }, "Pending links"),
|
|
1406
|
+
h10(
|
|
1407
|
+
"ul",
|
|
1408
|
+
{ style: styles.list },
|
|
1409
|
+
r.links.map(
|
|
1410
|
+
(l) => h10(
|
|
1411
|
+
"li",
|
|
1412
|
+
{
|
|
1413
|
+
key: l.id,
|
|
1414
|
+
style: { ...styles.row, display: "flex", gap: "12px", alignItems: "center" }
|
|
1415
|
+
},
|
|
1416
|
+
[
|
|
1417
|
+
pill(l.kind === "invite" ? "info" : "warn", l.kind, false),
|
|
1418
|
+
h10("span", { style: { flex: 1 } }, [
|
|
1419
|
+
l.email,
|
|
1420
|
+
l.kind === "invite" ? h10("span", { style: styles.muted }, ` \xB7 ${levelOf(l.scopes)}`) : null
|
|
1421
|
+
]),
|
|
1422
|
+
h10(
|
|
1423
|
+
"span",
|
|
1424
|
+
{ style: styles.muted },
|
|
1425
|
+
`expires ${new Date(l.expiresAt).toLocaleString()}`
|
|
1426
|
+
),
|
|
1427
|
+
h10(
|
|
1428
|
+
"button",
|
|
1429
|
+
{
|
|
1430
|
+
type: "button",
|
|
1431
|
+
style: { ...styles.buttonDanger, ...small },
|
|
1432
|
+
onClick: () => void revokeLink(l.id).catch(() => {
|
|
1433
|
+
})
|
|
1434
|
+
},
|
|
1435
|
+
"Revoke"
|
|
1436
|
+
)
|
|
1437
|
+
]
|
|
1438
|
+
)
|
|
1439
|
+
)
|
|
1440
|
+
)
|
|
1441
|
+
] : null
|
|
1442
|
+
]);
|
|
1443
|
+
};
|
|
1444
|
+
}
|
|
1445
|
+
});
|
|
1446
|
+
|
|
1170
1447
|
// src/screens/TokensScreen.ts
|
|
1171
1448
|
import { useAdminTokens } from "@fonderie/vue-admin";
|
|
1172
|
-
import { defineComponent as
|
|
1449
|
+
import { defineComponent as defineComponent9, h as h11, ref as ref3 } from "vue";
|
|
1173
1450
|
var ALL = ["read", "write", "secrets"];
|
|
1174
|
-
var TokensScreen =
|
|
1451
|
+
var TokensScreen = defineComponent9({
|
|
1175
1452
|
name: "FonderieTokensScreen",
|
|
1176
1453
|
props: { client: { type: Object, required: true } },
|
|
1177
1454
|
setup(props) {
|
|
1178
1455
|
const { report, isLoading, error, issue, revoke } = useAdminTokens(props.client);
|
|
1179
|
-
const name =
|
|
1180
|
-
const scopes =
|
|
1181
|
-
const days =
|
|
1182
|
-
const minted =
|
|
1456
|
+
const name = ref3("");
|
|
1457
|
+
const scopes = ref3(["read"]);
|
|
1458
|
+
const days = ref3("");
|
|
1459
|
+
const minted = ref3(null);
|
|
1183
1460
|
const toggle = (s) => scopes.value = scopes.value.includes(s) ? scopes.value.filter((x) => x !== s) : [...scopes.value, s];
|
|
1184
1461
|
return () => {
|
|
1185
1462
|
const r = report.value;
|
|
1186
|
-
return
|
|
1463
|
+
return h11("div", { style: styles.container }, [
|
|
1187
1464
|
pageHeader(
|
|
1188
|
-
"
|
|
1189
|
-
"
|
|
1465
|
+
"Tokens",
|
|
1466
|
+
"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."
|
|
1190
1467
|
),
|
|
1191
|
-
error.value ?
|
|
1468
|
+
error.value ? h11(
|
|
1192
1469
|
"p",
|
|
1193
1470
|
{ style: styles.error, role: "alert" },
|
|
1194
1471
|
error.value.status === 401 ? "Issuing and revoking need the root token (the one in your deployment config)." : error.value.explanation
|
|
1195
1472
|
) : null,
|
|
1196
|
-
|
|
1197
|
-
r ?
|
|
1473
|
+
h11("h2", { style: { ...styles.subtitle, marginTop: 0 } }, "Root token"),
|
|
1474
|
+
r ? h11(
|
|
1198
1475
|
"div",
|
|
1199
1476
|
{ style: { ...styles.card, display: "flex", gap: "12px", alignItems: "flex-start" } },
|
|
1200
1477
|
[
|
|
1201
1478
|
icon("lock", 18, { marginTop: "2px" }),
|
|
1202
|
-
|
|
1479
|
+
h11("div", [
|
|
1203
1480
|
pill(r.admin.ok ? "ok" : "bad", r.admin.ok ? "strong" : "weak"),
|
|
1204
1481
|
...r.admin.problems.map(
|
|
1205
|
-
(p) =>
|
|
1482
|
+
(p) => h11(
|
|
1206
1483
|
"div",
|
|
1207
1484
|
{
|
|
1208
1485
|
key: p.message,
|
|
@@ -1218,13 +1495,13 @@ var TokensScreen = defineComponent8({
|
|
|
1218
1495
|
])
|
|
1219
1496
|
]
|
|
1220
1497
|
) : null,
|
|
1221
|
-
|
|
1222
|
-
r?.issued === null ?
|
|
1498
|
+
h11("h2", { style: styles.subtitle }, "Issued tokens"),
|
|
1499
|
+
r?.issued === null ? h11(
|
|
1223
1500
|
"p",
|
|
1224
1501
|
{ style: styles.muted },
|
|
1225
1502
|
"Issuing is off \u2014 give AdminModule a store and run its migrations."
|
|
1226
1503
|
) : [
|
|
1227
|
-
minted.value ?
|
|
1504
|
+
minted.value ? h11(
|
|
1228
1505
|
"div",
|
|
1229
1506
|
{
|
|
1230
1507
|
style: {
|
|
@@ -1234,9 +1511,9 @@ var TokensScreen = defineComponent8({
|
|
|
1234
1511
|
}
|
|
1235
1512
|
},
|
|
1236
1513
|
[
|
|
1237
|
-
|
|
1514
|
+
h11("strong", "Copy this now \u2014 it is never shown again."),
|
|
1238
1515
|
` (${minted.value.name})`,
|
|
1239
|
-
|
|
1516
|
+
h11(
|
|
1240
1517
|
"div",
|
|
1241
1518
|
{
|
|
1242
1519
|
style: {
|
|
@@ -1251,7 +1528,7 @@ var TokensScreen = defineComponent8({
|
|
|
1251
1528
|
)
|
|
1252
1529
|
]
|
|
1253
1530
|
) : null,
|
|
1254
|
-
|
|
1531
|
+
h11(
|
|
1255
1532
|
"form",
|
|
1256
1533
|
{
|
|
1257
1534
|
style: styles.toolbar,
|
|
@@ -1271,7 +1548,7 @@ var TokensScreen = defineComponent8({
|
|
|
1271
1548
|
}
|
|
1272
1549
|
},
|
|
1273
1550
|
[
|
|
1274
|
-
|
|
1551
|
+
h11("input", {
|
|
1275
1552
|
value: name.value,
|
|
1276
1553
|
onInput: (e) => name.value = e.target.value,
|
|
1277
1554
|
placeholder: "name",
|
|
@@ -1279,7 +1556,7 @@ var TokensScreen = defineComponent8({
|
|
|
1279
1556
|
"aria-label": "Name"
|
|
1280
1557
|
}),
|
|
1281
1558
|
...ALL.map(
|
|
1282
|
-
(s) =>
|
|
1559
|
+
(s) => h11(
|
|
1283
1560
|
"label",
|
|
1284
1561
|
{
|
|
1285
1562
|
key: s,
|
|
@@ -1293,7 +1570,7 @@ var TokensScreen = defineComponent8({
|
|
|
1293
1570
|
}
|
|
1294
1571
|
},
|
|
1295
1572
|
[
|
|
1296
|
-
|
|
1573
|
+
h11("input", {
|
|
1297
1574
|
type: "checkbox",
|
|
1298
1575
|
checked: scopes.value.includes(s),
|
|
1299
1576
|
onChange: () => toggle(s)
|
|
@@ -1302,14 +1579,14 @@ var TokensScreen = defineComponent8({
|
|
|
1302
1579
|
]
|
|
1303
1580
|
)
|
|
1304
1581
|
),
|
|
1305
|
-
|
|
1582
|
+
h11("input", {
|
|
1306
1583
|
value: days.value,
|
|
1307
1584
|
onInput: (e) => days.value = e.target.value,
|
|
1308
1585
|
placeholder: "days (optional)",
|
|
1309
1586
|
style: { ...styles.input, width: "140px" },
|
|
1310
1587
|
"aria-label": "Days"
|
|
1311
1588
|
}),
|
|
1312
|
-
|
|
1589
|
+
h11(
|
|
1313
1590
|
"button",
|
|
1314
1591
|
{
|
|
1315
1592
|
type: "submit",
|
|
@@ -1323,7 +1600,7 @@ var TokensScreen = defineComponent8({
|
|
|
1323
1600
|
r?.issued && r.issued.length > 0 ? table(
|
|
1324
1601
|
["Name", "Scopes", "Created", "Expires", "Last used", ""],
|
|
1325
1602
|
r.issued.map(
|
|
1326
|
-
(t2) =>
|
|
1603
|
+
(t2) => h11("tr", { key: t2.id }, [
|
|
1327
1604
|
td([t2.name, t2.revokedAt ? [" ", pill("neutral", "revoked")] : ""]),
|
|
1328
1605
|
td(t2.scopes.join(", "), styles.mono),
|
|
1329
1606
|
td(
|
|
@@ -1339,7 +1616,7 @@ var TokensScreen = defineComponent8({
|
|
|
1339
1616
|
styles.muted
|
|
1340
1617
|
),
|
|
1341
1618
|
td(
|
|
1342
|
-
t2.revokedAt ? "" :
|
|
1619
|
+
t2.revokedAt ? "" : h11(
|
|
1343
1620
|
"button",
|
|
1344
1621
|
{
|
|
1345
1622
|
type: "button",
|
|
@@ -1363,19 +1640,19 @@ var TokensScreen = defineComponent8({
|
|
|
1363
1640
|
"tokens"
|
|
1364
1641
|
)
|
|
1365
1642
|
],
|
|
1366
|
-
|
|
1367
|
-
r && r.legacy.length === 0 ?
|
|
1643
|
+
h11("h2", { style: styles.subtitle }, "Legacy per-brick tokens"),
|
|
1644
|
+
r && r.legacy.length === 0 ? h11(
|
|
1368
1645
|
"p",
|
|
1369
1646
|
{ style: styles.muted },
|
|
1370
1647
|
"None \u2014 every brick's admin surface goes through this token."
|
|
1371
|
-
) :
|
|
1648
|
+
) : h11(
|
|
1372
1649
|
"ul",
|
|
1373
1650
|
{ style: styles.list },
|
|
1374
1651
|
(r?.legacy ?? []).map(
|
|
1375
|
-
(l) =>
|
|
1376
|
-
|
|
1652
|
+
(l) => h11("li", { key: l.module, style: styles.row }, [
|
|
1653
|
+
h11("span", { style: styles.mono }, l.module),
|
|
1377
1654
|
" ",
|
|
1378
|
-
|
|
1655
|
+
h11(
|
|
1379
1656
|
"span",
|
|
1380
1657
|
{ style: styles.muted },
|
|
1381
1658
|
"still registers its standalone routes with its own token (deprecated)"
|
|
@@ -1396,17 +1673,17 @@ import {
|
|
|
1396
1673
|
useAdminUserSessions,
|
|
1397
1674
|
useAdminUsers
|
|
1398
1675
|
} from "@fonderie/vue-admin";
|
|
1399
|
-
import { computed, defineComponent as
|
|
1400
|
-
var UsersScreen =
|
|
1676
|
+
import { computed, defineComponent as defineComponent10, h as h12, ref as ref4 } from "vue";
|
|
1677
|
+
var UsersScreen = defineComponent10({
|
|
1401
1678
|
name: "FonderieUsersScreen",
|
|
1402
1679
|
props: {
|
|
1403
1680
|
client: { type: Object, required: true },
|
|
1404
1681
|
pageSize: { type: Number, default: 50 }
|
|
1405
1682
|
},
|
|
1406
1683
|
setup(props) {
|
|
1407
|
-
const input =
|
|
1408
|
-
const email =
|
|
1409
|
-
const selectedId =
|
|
1684
|
+
const input = ref4("");
|
|
1685
|
+
const email = ref4("");
|
|
1686
|
+
const selectedId = ref4("");
|
|
1410
1687
|
const list = useAdminUsers(props.client, { limit: props.pageSize });
|
|
1411
1688
|
const { user, isLoading, error, suspend, unsuspend, revokeSessions } = useAdminUser(
|
|
1412
1689
|
props.client,
|
|
@@ -1417,7 +1694,7 @@ var UsersScreen = defineComponent9({
|
|
|
1417
1694
|
const history = useAdminLoginHistory(props.client, userId, { limit: 20 });
|
|
1418
1695
|
const showList = computed(() => !email.value && !selectedId.value);
|
|
1419
1696
|
const yesNo = (v) => v ? pill("ok", "yes") : pill("neutral", "no");
|
|
1420
|
-
const row = (k, v) =>
|
|
1697
|
+
const row = (k, v) => h12("tr", [td(k), td(v)]);
|
|
1421
1698
|
const clear = () => {
|
|
1422
1699
|
email.value = "";
|
|
1423
1700
|
selectedId.value = "";
|
|
@@ -1425,12 +1702,12 @@ var UsersScreen = defineComponent9({
|
|
|
1425
1702
|
};
|
|
1426
1703
|
return () => {
|
|
1427
1704
|
const u = user.value;
|
|
1428
|
-
return
|
|
1705
|
+
return h12("div", { style: styles.container }, [
|
|
1429
1706
|
pageHeader(
|
|
1430
1707
|
"Users",
|
|
1431
1708
|
"Everyone signed up. Open an account for its sessions, sign-ins and the suspend and sign-out controls."
|
|
1432
1709
|
),
|
|
1433
|
-
|
|
1710
|
+
h12(
|
|
1434
1711
|
"form",
|
|
1435
1712
|
{
|
|
1436
1713
|
style: styles.toolbar,
|
|
@@ -1441,7 +1718,7 @@ var UsersScreen = defineComponent9({
|
|
|
1441
1718
|
}
|
|
1442
1719
|
},
|
|
1443
1720
|
[
|
|
1444
|
-
|
|
1721
|
+
h12("input", {
|
|
1445
1722
|
type: "email",
|
|
1446
1723
|
value: input.value,
|
|
1447
1724
|
onInput: (e) => input.value = e.target.value,
|
|
@@ -1449,7 +1726,7 @@ var UsersScreen = defineComponent9({
|
|
|
1449
1726
|
style: { ...styles.input, minWidth: "280px" },
|
|
1450
1727
|
"aria-label": "Email"
|
|
1451
1728
|
}),
|
|
1452
|
-
|
|
1729
|
+
h12(
|
|
1453
1730
|
"button",
|
|
1454
1731
|
{ type: "submit", style: styles.buttonPrimary, disabled: isLoading.value },
|
|
1455
1732
|
[icon("search", 14), "Look up"]
|
|
@@ -1457,14 +1734,14 @@ var UsersScreen = defineComponent9({
|
|
|
1457
1734
|
showList.value ? refreshButton("Refresh", list.isLoading.value, () => void list.refresh()) : actionButton([icon("back", 14), "All users"], false, clear, styles.buttonGhost)
|
|
1458
1735
|
]
|
|
1459
1736
|
),
|
|
1460
|
-
showList.value ?
|
|
1461
|
-
list.error.value ?
|
|
1737
|
+
showList.value ? h12("div", [
|
|
1738
|
+
list.error.value ? h12("p", { style: styles.error, role: "alert" }, list.error.value.explanation) : null,
|
|
1462
1739
|
list.users.value.length === 0 && !list.isLoading.value ? empty("No users yet", "Sign-ups appear here as they happen.", "users") : table(
|
|
1463
1740
|
["Email", "Name", "Created", "Status"],
|
|
1464
1741
|
list.users.value.map(
|
|
1465
|
-
(u2) =>
|
|
1742
|
+
(u2) => h12("tr", { key: u2.id }, [
|
|
1466
1743
|
td(
|
|
1467
|
-
|
|
1744
|
+
h12(
|
|
1468
1745
|
"button",
|
|
1469
1746
|
{
|
|
1470
1747
|
type: "button",
|
|
@@ -1475,7 +1752,7 @@ var UsersScreen = defineComponent9({
|
|
|
1475
1752
|
)
|
|
1476
1753
|
),
|
|
1477
1754
|
td(
|
|
1478
|
-
`${u2.firstName ?? ""} ${u2.lastName ?? ""}`.trim() ||
|
|
1755
|
+
`${u2.firstName ?? ""} ${u2.lastName ?? ""}`.trim() || h12("span", { style: styles.muted }, "\u2014")
|
|
1479
1756
|
),
|
|
1480
1757
|
td(new Date(u2.createdAt).toLocaleDateString()),
|
|
1481
1758
|
td(
|
|
@@ -1484,24 +1761,24 @@ var UsersScreen = defineComponent9({
|
|
|
1484
1761
|
])
|
|
1485
1762
|
)
|
|
1486
1763
|
),
|
|
1487
|
-
list.isLoading.value ?
|
|
1764
|
+
list.isLoading.value ? h12("p", { style: styles.status }, "Loading\u2026") : null,
|
|
1488
1765
|
list.hasMore.value && !list.isLoading.value ? loadMoreButton(() => void list.loadMore()) : null
|
|
1489
1766
|
]) : null,
|
|
1490
|
-
error.value ?
|
|
1767
|
+
error.value ? h12(
|
|
1491
1768
|
"p",
|
|
1492
1769
|
{ style: styles.error, role: "alert" },
|
|
1493
1770
|
error.value.status === 404 ? "No user with that email." : error.value.explanation
|
|
1494
1771
|
) : null,
|
|
1495
1772
|
u ? [
|
|
1496
|
-
|
|
1773
|
+
h12("h2", { style: styles.subtitle }, [
|
|
1497
1774
|
u.firstName || u.lastName ? `${u.firstName} ${u.lastName}`.trim() : u.email,
|
|
1498
1775
|
" ",
|
|
1499
1776
|
u.suspended ? pill("warn", "suspended") : null,
|
|
1500
1777
|
u.deletedAt ? pill("neutral", "deleted") : null
|
|
1501
1778
|
]),
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
row("id",
|
|
1779
|
+
h12("table", { style: styles.table }, [
|
|
1780
|
+
h12("tbody", [
|
|
1781
|
+
row("id", h12("span", { style: styles.mono }, u.id)),
|
|
1505
1782
|
row("email", [u.email, " \xB7 verified ", yesNo(u.isEmailVerified)]),
|
|
1506
1783
|
row("MFA", yesNo(u.mfaEnabled)),
|
|
1507
1784
|
row(
|
|
@@ -1510,12 +1787,12 @@ var UsersScreen = defineComponent9({
|
|
|
1510
1787
|
),
|
|
1511
1788
|
row(
|
|
1512
1789
|
"last login",
|
|
1513
|
-
u.lastLogin ? new Date(u.lastLogin).toLocaleString() :
|
|
1790
|
+
u.lastLogin ? new Date(u.lastLogin).toLocaleString() : h12("span", { style: styles.muted }, "never")
|
|
1514
1791
|
),
|
|
1515
1792
|
row("created", new Date(u.createdAt).toLocaleString())
|
|
1516
1793
|
])
|
|
1517
1794
|
]),
|
|
1518
|
-
|
|
1795
|
+
h12("div", { style: { ...styles.toolbar, marginTop: "12px" } }, [
|
|
1519
1796
|
u.suspended ? actionButton("Unsuspend", isLoading.value, () => void unsuspend()) : actionButton(
|
|
1520
1797
|
"Suspend",
|
|
1521
1798
|
isLoading.value,
|
|
@@ -1528,19 +1805,19 @@ var UsersScreen = defineComponent9({
|
|
|
1528
1805
|
() => void revokeSessions().then(() => sessions.refresh())
|
|
1529
1806
|
)
|
|
1530
1807
|
]),
|
|
1531
|
-
|
|
1532
|
-
sessions.sessions.value.length === 0 ?
|
|
1808
|
+
h12("h2", { style: styles.subtitle }, "Live sessions"),
|
|
1809
|
+
sessions.sessions.value.length === 0 ? h12("p", { style: styles.muted }, "None.") : h12(
|
|
1533
1810
|
"ul",
|
|
1534
1811
|
{ style: styles.list },
|
|
1535
1812
|
sessions.sessions.value.map(
|
|
1536
|
-
(s) =>
|
|
1537
|
-
|
|
1813
|
+
(s) => h12("li", { key: s.id, style: styles.row }, [
|
|
1814
|
+
h12("span", { style: styles.mono }, s.ipAddress ?? "\u2014"),
|
|
1538
1815
|
" ",
|
|
1539
|
-
|
|
1816
|
+
h12("span", { style: styles.muted }, describeLocation(s.location) ?? ""),
|
|
1540
1817
|
" ",
|
|
1541
|
-
|
|
1818
|
+
h12("span", { style: styles.muted }, s.userAgent ?? ""),
|
|
1542
1819
|
" ",
|
|
1543
|
-
|
|
1820
|
+
h12(
|
|
1544
1821
|
"span",
|
|
1545
1822
|
{ style: styles.muted },
|
|
1546
1823
|
`since ${new Date(s.createdAt).toLocaleString()}`
|
|
@@ -1548,22 +1825,22 @@ var UsersScreen = defineComponent9({
|
|
|
1548
1825
|
])
|
|
1549
1826
|
)
|
|
1550
1827
|
),
|
|
1551
|
-
|
|
1552
|
-
history.events.value.length === 0 && !history.isLoading.value ?
|
|
1828
|
+
h12("h2", { style: styles.subtitle }, "Recent sign-ins"),
|
|
1829
|
+
history.events.value.length === 0 && !history.isLoading.value ? h12("p", { style: styles.muted }, "None recorded.") : h12(
|
|
1553
1830
|
"ul",
|
|
1554
1831
|
{ style: styles.list },
|
|
1555
1832
|
history.events.value.map(
|
|
1556
|
-
(e) =>
|
|
1833
|
+
(e) => h12("li", { key: e.id, style: styles.row }, [
|
|
1557
1834
|
pill(e.outcome === "success" ? "ok" : "bad", e.outcome),
|
|
1558
1835
|
" ",
|
|
1559
|
-
|
|
1836
|
+
h12("span", { style: styles.muted }, e.method),
|
|
1560
1837
|
" ",
|
|
1561
|
-
|
|
1838
|
+
h12("span", { style: styles.mono }, e.ipAddress ?? "\u2014"),
|
|
1562
1839
|
" ",
|
|
1563
|
-
|
|
1840
|
+
h12("span", { style: styles.muted }, describeLocation(e.location) ?? ""),
|
|
1564
1841
|
e.location?.proxy || e.location?.hosting ? [" ", pill("warn", e.location.proxy ? "proxy/VPN" : "hosting")] : "",
|
|
1565
1842
|
" ",
|
|
1566
|
-
|
|
1843
|
+
h12("span", { style: styles.muted }, new Date(e.createdAt).toLocaleString())
|
|
1567
1844
|
])
|
|
1568
1845
|
)
|
|
1569
1846
|
),
|
|
@@ -1576,8 +1853,8 @@ var UsersScreen = defineComponent9({
|
|
|
1576
1853
|
|
|
1577
1854
|
// src/screens/CatalogScreen.ts
|
|
1578
1855
|
import { useAdminCatalog } from "@fonderie/vue-admin";
|
|
1579
|
-
import { defineComponent as
|
|
1580
|
-
var CatalogScreen =
|
|
1856
|
+
import { defineComponent as defineComponent11, h as h13 } from "vue";
|
|
1857
|
+
var CatalogScreen = defineComponent11({
|
|
1581
1858
|
name: "FonderieCatalogScreen",
|
|
1582
1859
|
props: { client: { type: Object, required: true } },
|
|
1583
1860
|
setup(props) {
|
|
@@ -1585,17 +1862,17 @@ var CatalogScreen = defineComponent10({
|
|
|
1585
1862
|
const money = (v) => v == null ? "\u2014" : (v / 100).toFixed(2);
|
|
1586
1863
|
return () => {
|
|
1587
1864
|
const c = catalog.value;
|
|
1588
|
-
return
|
|
1865
|
+
return h13("div", { style: styles.container }, [
|
|
1589
1866
|
pageHeader(
|
|
1590
1867
|
"Catalog",
|
|
1591
1868
|
"What you sell: plans as configured in code, and as stored in the database, side by side.",
|
|
1592
1869
|
[refreshButton("Refresh", isLoading.value, () => void refresh())]
|
|
1593
1870
|
),
|
|
1594
|
-
error.value ?
|
|
1595
|
-
isLoading.value && !c ?
|
|
1871
|
+
error.value ? h13("p", { style: styles.error, role: "alert" }, error.value.explanation) : null,
|
|
1872
|
+
isLoading.value && !c ? h13("p", { style: styles.status }, "Loading\u2026") : null,
|
|
1596
1873
|
c ? [
|
|
1597
|
-
|
|
1598
|
-
|
|
1874
|
+
h13("h2", { style: { ...styles.subtitle, marginTop: 0 } }, "Configured (code)"),
|
|
1875
|
+
h13(
|
|
1599
1876
|
"pre",
|
|
1600
1877
|
{
|
|
1601
1878
|
style: {
|
|
@@ -1609,7 +1886,7 @@ var CatalogScreen = defineComponent10({
|
|
|
1609
1886
|
},
|
|
1610
1887
|
JSON.stringify(c.configured, null, 2)
|
|
1611
1888
|
),
|
|
1612
|
-
|
|
1889
|
+
h13("h2", { style: styles.subtitle }, "Stored (database)"),
|
|
1613
1890
|
c.stored.length === 0 ? empty(
|
|
1614
1891
|
"No stored plans",
|
|
1615
1892
|
"Plans are configured in code; nothing has been written to the database.",
|
|
@@ -1617,10 +1894,10 @@ var CatalogScreen = defineComponent10({
|
|
|
1617
1894
|
) : table(
|
|
1618
1895
|
["Plan", "Tier", "Seats", "Monthly", "Yearly", "Trial", ""],
|
|
1619
1896
|
c.stored.map(
|
|
1620
|
-
(p) =>
|
|
1897
|
+
(p) => h13("tr", { key: p.id }, [
|
|
1621
1898
|
td([
|
|
1622
|
-
|
|
1623
|
-
p.description ?
|
|
1899
|
+
h13("strong", p.name),
|
|
1900
|
+
p.description ? h13("div", { style: styles.muted }, p.description) : ""
|
|
1624
1901
|
]),
|
|
1625
1902
|
td(String(p.tier)),
|
|
1626
1903
|
td(p.seats == null ? "\u221E" : String(p.seats)),
|
|
@@ -1628,7 +1905,7 @@ var CatalogScreen = defineComponent10({
|
|
|
1628
1905
|
td(money(p.pricing?.yearly)),
|
|
1629
1906
|
td(p.trialDays ? `${p.trialDays} d` : "\u2014"),
|
|
1630
1907
|
td(
|
|
1631
|
-
|
|
1908
|
+
h13(
|
|
1632
1909
|
"button",
|
|
1633
1910
|
{
|
|
1634
1911
|
type: "button",
|
|
@@ -1653,17 +1930,17 @@ var CatalogScreen = defineComponent10({
|
|
|
1653
1930
|
|
|
1654
1931
|
// src/screens/SubscriberScreen.ts
|
|
1655
1932
|
import { useAdminSubscriber, useAdminSubscribers } from "@fonderie/vue-admin";
|
|
1656
|
-
import { defineComponent as
|
|
1657
|
-
var SubscriberScreen =
|
|
1933
|
+
import { defineComponent as defineComponent12, h as h14, ref as ref5 } from "vue";
|
|
1934
|
+
var SubscriberScreen = defineComponent12({
|
|
1658
1935
|
name: "FonderieSubscriberScreen",
|
|
1659
1936
|
props: {
|
|
1660
1937
|
client: { type: Object, required: true },
|
|
1661
1938
|
pageSize: { type: Number, default: 50 }
|
|
1662
1939
|
},
|
|
1663
1940
|
setup(props) {
|
|
1664
|
-
const type =
|
|
1665
|
-
const idInput =
|
|
1666
|
-
const subscriber =
|
|
1941
|
+
const type = ref5("user");
|
|
1942
|
+
const idInput = ref5("");
|
|
1943
|
+
const subscriber = ref5(null);
|
|
1667
1944
|
const list = useAdminSubscribers(props.client, { limit: props.pageSize });
|
|
1668
1945
|
const { subscription, wallet, ledger, hasMoreLedger, isLoading, error, loadMoreLedger, grant } = useAdminSubscriber(props.client, subscriber, { limit: 20 });
|
|
1669
1946
|
const open = (t2, id) => {
|
|
@@ -1672,10 +1949,10 @@ var SubscriberScreen = defineComponent11({
|
|
|
1672
1949
|
idInput.value = id;
|
|
1673
1950
|
subscriber.value = { type: t2, id };
|
|
1674
1951
|
};
|
|
1675
|
-
const amount =
|
|
1676
|
-
const note =
|
|
1677
|
-
const granted =
|
|
1678
|
-
const input = (model, placeholder, extra = {}) =>
|
|
1952
|
+
const amount = ref5("");
|
|
1953
|
+
const note = ref5("");
|
|
1954
|
+
const granted = ref5(null);
|
|
1955
|
+
const input = (model, placeholder, extra = {}) => h14("input", {
|
|
1679
1956
|
value: model.value,
|
|
1680
1957
|
onInput: (e) => model.value = e.target.value,
|
|
1681
1958
|
placeholder,
|
|
@@ -1685,12 +1962,12 @@ var SubscriberScreen = defineComponent11({
|
|
|
1685
1962
|
return () => {
|
|
1686
1963
|
const s = subscription.value;
|
|
1687
1964
|
const w = wallet.value;
|
|
1688
|
-
return
|
|
1965
|
+
return h14("div", { style: styles.container }, [
|
|
1689
1966
|
pageHeader(
|
|
1690
1967
|
"Subscribers",
|
|
1691
1968
|
"Who is subscribed. Open one for their plan, wallet and ledger, and to grant credit."
|
|
1692
1969
|
),
|
|
1693
|
-
|
|
1970
|
+
h14(
|
|
1694
1971
|
"form",
|
|
1695
1972
|
{
|
|
1696
1973
|
style: styles.toolbar,
|
|
@@ -1701,7 +1978,7 @@ var SubscriberScreen = defineComponent11({
|
|
|
1701
1978
|
}
|
|
1702
1979
|
},
|
|
1703
1980
|
[
|
|
1704
|
-
|
|
1981
|
+
h14(
|
|
1705
1982
|
"select",
|
|
1706
1983
|
{
|
|
1707
1984
|
value: type.value,
|
|
@@ -1710,17 +1987,17 @@ var SubscriberScreen = defineComponent11({
|
|
|
1710
1987
|
"aria-label": "Type"
|
|
1711
1988
|
},
|
|
1712
1989
|
[
|
|
1713
|
-
|
|
1714
|
-
|
|
1990
|
+
h14("option", { value: "user" }, "user"),
|
|
1991
|
+
h14("option", { value: "workspace" }, "workspace")
|
|
1715
1992
|
]
|
|
1716
1993
|
),
|
|
1717
1994
|
input(idInput, "subscriber id", { minWidth: "280px" }),
|
|
1718
|
-
|
|
1995
|
+
h14(
|
|
1719
1996
|
"button",
|
|
1720
1997
|
{ type: "submit", style: styles.buttonPrimary, disabled: isLoading.value },
|
|
1721
1998
|
[icon("search", 14), "Look up"]
|
|
1722
1999
|
),
|
|
1723
|
-
subscriber.value ?
|
|
2000
|
+
subscriber.value ? h14(
|
|
1724
2001
|
"button",
|
|
1725
2002
|
{
|
|
1726
2003
|
type: "button",
|
|
@@ -1732,7 +2009,7 @@ var SubscriberScreen = defineComponent11({
|
|
|
1732
2009
|
}
|
|
1733
2010
|
},
|
|
1734
2011
|
[icon("back", 14), "All subscribers"]
|
|
1735
|
-
) :
|
|
2012
|
+
) : h14(
|
|
1736
2013
|
"button",
|
|
1737
2014
|
{
|
|
1738
2015
|
type: "button",
|
|
@@ -1744,8 +2021,8 @@ var SubscriberScreen = defineComponent11({
|
|
|
1744
2021
|
)
|
|
1745
2022
|
]
|
|
1746
2023
|
),
|
|
1747
|
-
!subscriber.value ?
|
|
1748
|
-
list.error.value ?
|
|
2024
|
+
!subscriber.value ? h14("div", [
|
|
2025
|
+
list.error.value ? h14("p", { style: styles.error, role: "alert" }, list.error.value.explanation) : null,
|
|
1749
2026
|
list.subscriptions.value.length === 0 && !list.isLoading.value ? empty(
|
|
1750
2027
|
"No subscribers yet",
|
|
1751
2028
|
"Subscriptions appear here once someone checks out.",
|
|
@@ -1753,9 +2030,9 @@ var SubscriberScreen = defineComponent11({
|
|
|
1753
2030
|
) : table(
|
|
1754
2031
|
["Subscriber", "Plan", "Status", "Renews"],
|
|
1755
2032
|
list.subscriptions.value.map(
|
|
1756
|
-
(sub) =>
|
|
2033
|
+
(sub) => h14("tr", { key: sub.id }, [
|
|
1757
2034
|
td(
|
|
1758
|
-
|
|
2035
|
+
h14(
|
|
1759
2036
|
"button",
|
|
1760
2037
|
{
|
|
1761
2038
|
type: "button",
|
|
@@ -1774,13 +2051,13 @@ var SubscriberScreen = defineComponent11({
|
|
|
1774
2051
|
sub.cancelAtPeriodEnd ? [" ", pill("warn", "cancels", false)] : null
|
|
1775
2052
|
]),
|
|
1776
2053
|
td(
|
|
1777
|
-
sub.currentPeriodEnd ? new Date(sub.currentPeriodEnd).toLocaleDateString() :
|
|
2054
|
+
sub.currentPeriodEnd ? new Date(sub.currentPeriodEnd).toLocaleDateString() : h14("span", { style: styles.muted }, "\u2014")
|
|
1778
2055
|
)
|
|
1779
2056
|
])
|
|
1780
2057
|
)
|
|
1781
2058
|
),
|
|
1782
|
-
list.isLoading.value ?
|
|
1783
|
-
list.hasMore.value && !list.isLoading.value ?
|
|
2059
|
+
list.isLoading.value ? h14("p", { style: styles.status }, "Loading\u2026") : null,
|
|
2060
|
+
list.hasMore.value && !list.isLoading.value ? h14(
|
|
1784
2061
|
"button",
|
|
1785
2062
|
{
|
|
1786
2063
|
type: "button",
|
|
@@ -1790,28 +2067,28 @@ var SubscriberScreen = defineComponent11({
|
|
|
1790
2067
|
"Load more"
|
|
1791
2068
|
) : null
|
|
1792
2069
|
]) : null,
|
|
1793
|
-
error.value ?
|
|
2070
|
+
error.value ? h14("p", { style: styles.error, role: "alert" }, error.value.explanation) : null,
|
|
1794
2071
|
subscriber.value && !isLoading.value ? [
|
|
1795
|
-
|
|
1796
|
-
s ?
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
2072
|
+
h14("h2", { style: styles.subtitle }, "Subscription"),
|
|
2073
|
+
s ? h14("table", { style: styles.table }, [
|
|
2074
|
+
h14("tbody", [
|
|
2075
|
+
h14("tr", [td("plan"), td([h14("strong", s.plan), ` \xB7 ${s.interval}`])]),
|
|
2076
|
+
h14("tr", [
|
|
1800
2077
|
td("status"),
|
|
1801
2078
|
td(`${s.status}${s.cancelAtPeriodEnd ? " \xB7 cancels at period end" : ""}`)
|
|
1802
2079
|
]),
|
|
1803
|
-
|
|
2080
|
+
h14("tr", [
|
|
1804
2081
|
td("period"),
|
|
1805
2082
|
td(
|
|
1806
2083
|
`${s.currentPeriodStart ? new Date(s.currentPeriodStart).toLocaleDateString() : "\u2014"} \u2192 ${s.currentPeriodEnd ? new Date(s.currentPeriodEnd).toLocaleDateString() : "\u2014"}`
|
|
1807
2084
|
)
|
|
1808
2085
|
]),
|
|
1809
|
-
|
|
2086
|
+
h14("tr", [td("provider"), td(s.providerSubscriptionId ?? "\u2014", styles.mono)])
|
|
1810
2087
|
])
|
|
1811
|
-
]) :
|
|
1812
|
-
|
|
2088
|
+
]) : h14("p", { style: styles.muted }, "No subscription."),
|
|
2089
|
+
h14("h2", { style: styles.subtitle }, "Wallet"),
|
|
1813
2090
|
w ? [
|
|
1814
|
-
|
|
2091
|
+
h14(
|
|
1815
2092
|
"p",
|
|
1816
2093
|
{
|
|
1817
2094
|
style: {
|
|
@@ -1823,7 +2100,7 @@ var SubscriberScreen = defineComponent11({
|
|
|
1823
2100
|
}
|
|
1824
2101
|
},
|
|
1825
2102
|
[
|
|
1826
|
-
|
|
2103
|
+
h14(
|
|
1827
2104
|
"strong",
|
|
1828
2105
|
{
|
|
1829
2106
|
style: {
|
|
@@ -1834,14 +2111,14 @@ var SubscriberScreen = defineComponent11({
|
|
|
1834
2111
|
w.balance
|
|
1835
2112
|
),
|
|
1836
2113
|
` ${w.currency} `,
|
|
1837
|
-
|
|
2114
|
+
h14(
|
|
1838
2115
|
"span",
|
|
1839
2116
|
{ style: styles.muted },
|
|
1840
2117
|
`(granted ${w.granted ?? "0"} \xB7 purchased ${w.purchased ?? "0"}) \xB7 minor units, precision ${w.precision}`
|
|
1841
2118
|
)
|
|
1842
2119
|
]
|
|
1843
2120
|
),
|
|
1844
|
-
|
|
2121
|
+
h14(
|
|
1845
2122
|
"form",
|
|
1846
2123
|
{
|
|
1847
2124
|
style: styles.toolbar,
|
|
@@ -1866,7 +2143,7 @@ var SubscriberScreen = defineComponent11({
|
|
|
1866
2143
|
[
|
|
1867
2144
|
input(amount, "amount (minor units)"),
|
|
1868
2145
|
input(note, "reason (optional)", { minWidth: "220px" }),
|
|
1869
|
-
|
|
2146
|
+
h14(
|
|
1870
2147
|
"button",
|
|
1871
2148
|
{
|
|
1872
2149
|
type: "submit",
|
|
@@ -1875,14 +2152,14 @@ var SubscriberScreen = defineComponent11({
|
|
|
1875
2152
|
},
|
|
1876
2153
|
[icon("plus", 14), "Grant"]
|
|
1877
2154
|
),
|
|
1878
|
-
granted.value ?
|
|
2155
|
+
granted.value ? h14("span", { style: styles.ok }, granted.value) : null
|
|
1879
2156
|
]
|
|
1880
2157
|
),
|
|
1881
|
-
|
|
2158
|
+
h14("h2", { style: styles.subtitle }, "Ledger"),
|
|
1882
2159
|
ledger.value.length === 0 ? empty("Nothing moved yet", void 0, "subscriber") : table(
|
|
1883
2160
|
["When", "Kind", "Amount", "Note"],
|
|
1884
2161
|
ledger.value.map(
|
|
1885
|
-
(t2) =>
|
|
2162
|
+
(t2) => h14("tr", { key: t2.id }, [
|
|
1886
2163
|
td(new Date(t2.createdAt).toLocaleString(), styles.muted),
|
|
1887
2164
|
td(t2.type),
|
|
1888
2165
|
td(t2.amount, styles.mono),
|
|
@@ -1890,7 +2167,7 @@ var SubscriberScreen = defineComponent11({
|
|
|
1890
2167
|
])
|
|
1891
2168
|
)
|
|
1892
2169
|
),
|
|
1893
|
-
hasMoreLedger.value ?
|
|
2170
|
+
hasMoreLedger.value ? h14(
|
|
1894
2171
|
"button",
|
|
1895
2172
|
{
|
|
1896
2173
|
type: "button",
|
|
@@ -1899,7 +2176,7 @@ var SubscriberScreen = defineComponent11({
|
|
|
1899
2176
|
},
|
|
1900
2177
|
"Load more"
|
|
1901
2178
|
) : null
|
|
1902
|
-
] :
|
|
2179
|
+
] : h14(
|
|
1903
2180
|
"p",
|
|
1904
2181
|
{ style: styles.muted },
|
|
1905
2182
|
"No wallet \u2014 billing has no wallet configuration."
|
|
@@ -1912,33 +2189,33 @@ var SubscriberScreen = defineComponent11({
|
|
|
1912
2189
|
|
|
1913
2190
|
// src/screens/AuditScreen.ts
|
|
1914
2191
|
import { useAdminAudit } from "@fonderie/vue-admin";
|
|
1915
|
-
import { defineComponent as
|
|
1916
|
-
var AuditScreen =
|
|
2192
|
+
import { defineComponent as defineComponent13, h as h15, ref as ref6 } from "vue";
|
|
2193
|
+
var AuditScreen = defineComponent13({
|
|
1917
2194
|
name: "FonderieAuditScreen",
|
|
1918
2195
|
props: {
|
|
1919
2196
|
client: { type: Object, required: true },
|
|
1920
2197
|
pageSize: { type: Number, default: 50 }
|
|
1921
2198
|
},
|
|
1922
2199
|
setup(props) {
|
|
1923
|
-
const draft =
|
|
1924
|
-
const query =
|
|
2200
|
+
const draft = ref6({ workspaceId: "", type: "", actorId: "" });
|
|
2201
|
+
const query = ref6({ limit: props.pageSize });
|
|
1925
2202
|
const { events, hasMore, isLoading, error, refresh, loadMore } = useAdminAudit(
|
|
1926
2203
|
props.client,
|
|
1927
2204
|
query
|
|
1928
2205
|
);
|
|
1929
|
-
const field = (key, placeholder) =>
|
|
2206
|
+
const field = (key, placeholder) => h15("input", {
|
|
1930
2207
|
value: draft.value[key],
|
|
1931
2208
|
onInput: (e) => draft.value = { ...draft.value, [key]: e.target.value },
|
|
1932
2209
|
placeholder,
|
|
1933
2210
|
style: styles.input,
|
|
1934
2211
|
"aria-label": placeholder
|
|
1935
2212
|
});
|
|
1936
|
-
return () =>
|
|
2213
|
+
return () => h15("div", { style: styles.container }, [
|
|
1937
2214
|
pageHeader(
|
|
1938
2215
|
"Audit",
|
|
1939
2216
|
"What happened, across every workspace unless you name one. The chain's integrity verdict is on the Doctor page."
|
|
1940
2217
|
),
|
|
1941
|
-
|
|
2218
|
+
h15(
|
|
1942
2219
|
"form",
|
|
1943
2220
|
{
|
|
1944
2221
|
style: styles.toolbar,
|
|
@@ -1957,7 +2234,7 @@ var AuditScreen = defineComponent12({
|
|
|
1957
2234
|
field("workspaceId", "workspace id (all if empty)"),
|
|
1958
2235
|
field("type", "event type"),
|
|
1959
2236
|
field("actorId", "actor id"),
|
|
1960
|
-
|
|
2237
|
+
h15(
|
|
1961
2238
|
"button",
|
|
1962
2239
|
{ type: "submit", style: styles.buttonPrimary, disabled: isLoading.value },
|
|
1963
2240
|
[icon("search", 14), "Filter"]
|
|
@@ -1965,11 +2242,11 @@ var AuditScreen = defineComponent12({
|
|
|
1965
2242
|
refreshButton("Refresh", isLoading.value, () => void refresh())
|
|
1966
2243
|
]
|
|
1967
2244
|
),
|
|
1968
|
-
error.value ?
|
|
2245
|
+
error.value ? h15("p", { style: styles.error, role: "alert" }, error.value.explanation) : null,
|
|
1969
2246
|
events.value.length === 0 && !isLoading.value ? empty("Nothing recorded for this filter", void 0, "audit") : table(
|
|
1970
2247
|
["When", "Type", "Workspace", "Actor", "Request"],
|
|
1971
2248
|
events.value.map(
|
|
1972
|
-
(e) =>
|
|
2249
|
+
(e) => h15("tr", { key: e.id }, [
|
|
1973
2250
|
td(new Date(e.createdAt).toLocaleString(), styles.muted),
|
|
1974
2251
|
td(e.type, styles.mono),
|
|
1975
2252
|
td(String(e.payload["workspaceId"] ?? "\u2014"), styles.mono),
|
|
@@ -1978,7 +2255,7 @@ var AuditScreen = defineComponent12({
|
|
|
1978
2255
|
])
|
|
1979
2256
|
)
|
|
1980
2257
|
),
|
|
1981
|
-
isLoading.value ?
|
|
2258
|
+
isLoading.value ? h15("p", { style: styles.status }, "Loading\u2026") : null,
|
|
1982
2259
|
hasMore.value && !isLoading.value ? loadMoreButton(() => void loadMore()) : null
|
|
1983
2260
|
]);
|
|
1984
2261
|
}
|
|
@@ -2011,7 +2288,8 @@ var NAV = [
|
|
|
2011
2288
|
items: [
|
|
2012
2289
|
{ page: "audit", label: "Audit", needs: "audit" },
|
|
2013
2290
|
{ page: "log", label: "Admin log" },
|
|
2014
|
-
{ page: "
|
|
2291
|
+
{ page: "operators", label: "Operators", needs: "operators" },
|
|
2292
|
+
{ page: "tokens", label: "Tokens" },
|
|
2015
2293
|
{ page: "migrations", label: "Migrations" }
|
|
2016
2294
|
]
|
|
2017
2295
|
}
|
|
@@ -2030,10 +2308,11 @@ var ICON = {
|
|
|
2030
2308
|
audit: "audit",
|
|
2031
2309
|
log: "log",
|
|
2032
2310
|
tokens: "tokens",
|
|
2311
|
+
operators: "users",
|
|
2033
2312
|
migrations: "migrations"
|
|
2034
2313
|
};
|
|
2035
2314
|
var NARROW = "(max-width: 820px)";
|
|
2036
|
-
var AdminShell =
|
|
2315
|
+
var AdminShell = defineComponent14({
|
|
2037
2316
|
name: "FonderieAdminShell",
|
|
2038
2317
|
props: {
|
|
2039
2318
|
client: { type: Object, required: true },
|
|
@@ -2055,62 +2334,72 @@ var AdminShell = defineComponent13({
|
|
|
2055
2334
|
appName: { type: String, default: "Admin" },
|
|
2056
2335
|
// A badge beside the name — the deployment's environment ("production").
|
|
2057
2336
|
// Production is tinted so an operator always knows where their clicks land.
|
|
2058
|
-
envLabel: { type: String, default: void 0 }
|
|
2337
|
+
envLabel: { type: String, default: void 0 },
|
|
2338
|
+
// The deployment has operator accounts (@fonderie/admin with a store):
|
|
2339
|
+
// shows the Operators page.
|
|
2340
|
+
operators: { type: Boolean, default: false },
|
|
2341
|
+
// The signed-in operator's email, when a person (not a token) is signed in.
|
|
2342
|
+
currentOperator: { type: String, default: void 0 }
|
|
2059
2343
|
},
|
|
2060
2344
|
// `footer` slot: pinned to the bottom of the sidebar — session controls
|
|
2061
2345
|
// (theme, sign out). The React shell takes the same thing as a `footer` prop.
|
|
2062
2346
|
emits: { navigate: (_page) => true },
|
|
2063
2347
|
setup(props, { emit, slots }) {
|
|
2064
2348
|
const query = typeof window !== "undefined" && window.matchMedia ? window.matchMedia(NARROW) : null;
|
|
2065
|
-
const narrow =
|
|
2066
|
-
const drawer =
|
|
2349
|
+
const narrow = ref7(query?.matches ?? false);
|
|
2350
|
+
const drawer = ref7(false);
|
|
2067
2351
|
const onMedia = (e) => narrow.value = e.matches;
|
|
2068
2352
|
onMounted(() => query?.addEventListener("change", onMedia));
|
|
2069
2353
|
onBeforeUnmount(() => query?.removeEventListener("change", onMedia));
|
|
2070
|
-
const own =
|
|
2354
|
+
const own = ref7("attention");
|
|
2071
2355
|
const current = computed2(() => props.page ?? own.value);
|
|
2072
|
-
const editing =
|
|
2356
|
+
const editing = ref7(null);
|
|
2073
2357
|
const go = (p) => {
|
|
2074
2358
|
editing.value = null;
|
|
2075
2359
|
emit("navigate", p);
|
|
2076
2360
|
if (props.page === void 0) own.value = p;
|
|
2077
2361
|
drawer.value = false;
|
|
2078
2362
|
};
|
|
2079
|
-
const back = (label) =>
|
|
2080
|
-
|
|
2363
|
+
const back = (label) => h16("div", { style: { padding: "24px 40px 0" } }, [
|
|
2364
|
+
h16(
|
|
2081
2365
|
"button",
|
|
2082
2366
|
{ type: "button", style: styles.buttonGhost, onClick: () => editing.value = null },
|
|
2083
2367
|
[icon("back", 14), label]
|
|
2084
2368
|
)
|
|
2085
2369
|
]);
|
|
2086
|
-
const missing = (text) =>
|
|
2370
|
+
const missing = (text) => h16("p", { style: { ...styles.status, padding: "32px 40px" } }, text);
|
|
2087
2371
|
const body = () => {
|
|
2088
2372
|
const c = props.client;
|
|
2089
2373
|
switch (current.value) {
|
|
2090
2374
|
case "attention":
|
|
2091
|
-
return
|
|
2375
|
+
return h16(AttentionScreen, { client: c });
|
|
2092
2376
|
case "modules":
|
|
2093
|
-
return
|
|
2377
|
+
return h16(ModulesScreen, { client: c });
|
|
2094
2378
|
case "doctor":
|
|
2095
|
-
return
|
|
2379
|
+
return h16(DoctorScreen, { client: c });
|
|
2096
2380
|
case "environment":
|
|
2097
|
-
return
|
|
2381
|
+
return h16(EnvironmentScreen, { client: c });
|
|
2098
2382
|
case "routes":
|
|
2099
|
-
return
|
|
2383
|
+
return h16(RoutesScreen, { client: c });
|
|
2100
2384
|
case "tokens":
|
|
2101
|
-
return
|
|
2385
|
+
return h16(TokensScreen, { client: c });
|
|
2386
|
+
case "operators":
|
|
2387
|
+
return h16(OperatorsScreen, {
|
|
2388
|
+
client: c,
|
|
2389
|
+
...props.currentOperator ? { me: props.currentOperator } : {}
|
|
2390
|
+
});
|
|
2102
2391
|
case "migrations":
|
|
2103
|
-
return
|
|
2392
|
+
return h16(MigrationsScreen, { client: c });
|
|
2104
2393
|
case "log":
|
|
2105
|
-
return
|
|
2394
|
+
return h16(AdminLogScreen, { client: c });
|
|
2106
2395
|
case "catalog":
|
|
2107
|
-
return props.billingClient ?
|
|
2396
|
+
return props.billingClient ? h16(CatalogScreen, { client: props.billingClient }) : missing("Pass a BillingAdminClient to see the catalog here.");
|
|
2108
2397
|
case "subscriber":
|
|
2109
|
-
return props.billingClient ?
|
|
2398
|
+
return props.billingClient ? h16(SubscriberScreen, { client: props.billingClient }) : missing("Pass a BillingAdminClient to look up subscribers here.");
|
|
2110
2399
|
case "audit":
|
|
2111
|
-
return props.auditClient ?
|
|
2400
|
+
return props.auditClient ? h16(AuditScreen, { client: props.auditClient }) : missing("Pass an AuditAdminClient to see the audit trail here.");
|
|
2112
2401
|
case "users":
|
|
2113
|
-
return props.authClient ?
|
|
2402
|
+
return props.authClient ? h16(UsersScreen, { client: props.authClient }) : missing("Pass an AuthAdminClient to look up users here.");
|
|
2114
2403
|
case "settings": {
|
|
2115
2404
|
const cc = props.configClient;
|
|
2116
2405
|
if (!cc) return missing("Pass a ConfigAdminClient to manage config and secrets here.");
|
|
@@ -2118,7 +2407,7 @@ var AdminShell = defineComponent13({
|
|
|
2118
2407
|
if (e && e.kind !== "template")
|
|
2119
2408
|
return [
|
|
2120
2409
|
back("Config & secrets"),
|
|
2121
|
-
|
|
2410
|
+
h16(ConfigEditorScreen, {
|
|
2122
2411
|
client: cc,
|
|
2123
2412
|
kind: e.kind,
|
|
2124
2413
|
configKey: e.key,
|
|
@@ -2126,7 +2415,7 @@ var AdminShell = defineComponent13({
|
|
|
2126
2415
|
onSaved: () => editing.value = null
|
|
2127
2416
|
})
|
|
2128
2417
|
];
|
|
2129
|
-
return
|
|
2418
|
+
return h16(ConfigListScreen, {
|
|
2130
2419
|
client: cc,
|
|
2131
2420
|
...props.environment !== void 0 ? { environment: props.environment } : {},
|
|
2132
2421
|
"onSelect-config": (key) => editing.value = { kind: "config", key },
|
|
@@ -2143,27 +2432,27 @@ var AdminShell = defineComponent13({
|
|
|
2143
2432
|
if (e?.kind === "template")
|
|
2144
2433
|
return [
|
|
2145
2434
|
back("Templates"),
|
|
2146
|
-
|
|
2435
|
+
h16(TemplateEditorScreen, {
|
|
2147
2436
|
client: kc,
|
|
2148
2437
|
type: e.type,
|
|
2149
2438
|
onSaved: () => editing.value = null
|
|
2150
2439
|
})
|
|
2151
2440
|
];
|
|
2152
|
-
return
|
|
2441
|
+
return h16(TemplateListScreen, {
|
|
2153
2442
|
client: kc,
|
|
2154
2443
|
"onSelect-template": (t2) => editing.value = { kind: "template", type: t2.type }
|
|
2155
2444
|
});
|
|
2156
2445
|
}
|
|
2157
2446
|
}
|
|
2158
2447
|
};
|
|
2159
|
-
const visible = (i) => !i.needs || (i.needs === "config" ? props.configClient : i.needs === "courier" ? props.courierClient : i.needs === "auth" ? props.authClient : i.needs === "billing" ? props.billingClient : props.auditClient);
|
|
2448
|
+
const visible = (i) => !i.needs || (i.needs === "operators" ? props.operators : i.needs === "config" ? props.configClient : i.needs === "courier" ? props.courierClient : i.needs === "auth" ? props.authClient : i.needs === "billing" ? props.billingClient : props.auditClient);
|
|
2160
2449
|
const brand = () => {
|
|
2161
2450
|
const production = props.envLabel ? /^prod/i.test(props.envLabel) : false;
|
|
2162
|
-
return
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
props.envLabel ?
|
|
2451
|
+
return h16("div", { style: styles.navBrand }, [
|
|
2452
|
+
h16("div", { style: styles.navMark }, [icon("mark", 15)]),
|
|
2453
|
+
h16("div", { style: { minWidth: 0, flex: 1 } }, [
|
|
2454
|
+
h16("div", { style: styles.navBrandTitle }, props.appName),
|
|
2455
|
+
props.envLabel ? h16(
|
|
2167
2456
|
"span",
|
|
2168
2457
|
{
|
|
2169
2458
|
style: {
|
|
@@ -2180,7 +2469,7 @@ var AdminShell = defineComponent13({
|
|
|
2180
2469
|
props.envLabel
|
|
2181
2470
|
) : null
|
|
2182
2471
|
]),
|
|
2183
|
-
narrow.value ?
|
|
2472
|
+
narrow.value ? h16(
|
|
2184
2473
|
"button",
|
|
2185
2474
|
{
|
|
2186
2475
|
type: "button",
|
|
@@ -2192,7 +2481,7 @@ var AdminShell = defineComponent13({
|
|
|
2192
2481
|
) : null
|
|
2193
2482
|
]);
|
|
2194
2483
|
};
|
|
2195
|
-
const nav = () =>
|
|
2484
|
+
const nav = () => h16(
|
|
2196
2485
|
"nav",
|
|
2197
2486
|
{
|
|
2198
2487
|
style: {
|
|
@@ -2203,17 +2492,17 @@ var AdminShell = defineComponent13({
|
|
|
2203
2492
|
},
|
|
2204
2493
|
[
|
|
2205
2494
|
brand(),
|
|
2206
|
-
|
|
2495
|
+
h16(
|
|
2207
2496
|
"div",
|
|
2208
2497
|
{ style: styles.navScroll },
|
|
2209
2498
|
NAV.map((g) => {
|
|
2210
2499
|
const items = g.items.filter(visible);
|
|
2211
2500
|
if (items.length === 0) return null;
|
|
2212
|
-
return
|
|
2213
|
-
|
|
2501
|
+
return h16("div", { key: g.group }, [
|
|
2502
|
+
h16("div", { style: styles.navGroup }, g.group),
|
|
2214
2503
|
...items.map((i) => {
|
|
2215
2504
|
const active = current.value === i.page;
|
|
2216
|
-
return
|
|
2505
|
+
return h16(
|
|
2217
2506
|
"button",
|
|
2218
2507
|
{
|
|
2219
2508
|
key: i.page,
|
|
@@ -2229,18 +2518,18 @@ var AdminShell = defineComponent13({
|
|
|
2229
2518
|
]);
|
|
2230
2519
|
})
|
|
2231
2520
|
),
|
|
2232
|
-
slots["footer"] ?
|
|
2521
|
+
slots["footer"] ? h16("div", { style: styles.navFooter }, slots["footer"]()) : null
|
|
2233
2522
|
]
|
|
2234
2523
|
);
|
|
2235
2524
|
return () => {
|
|
2236
2525
|
const title = NAV.flatMap((g) => g.items).find((i) => i.page === current.value)?.label ?? "";
|
|
2237
|
-
return
|
|
2526
|
+
return h16(
|
|
2238
2527
|
"div",
|
|
2239
2528
|
{ style: { ...styles.shell, ...narrow.value ? { flexDirection: "column" } : {} } },
|
|
2240
2529
|
[
|
|
2241
2530
|
...narrow.value ? [
|
|
2242
|
-
|
|
2243
|
-
|
|
2531
|
+
h16("div", { style: styles.topbar }, [
|
|
2532
|
+
h16(
|
|
2244
2533
|
"button",
|
|
2245
2534
|
{
|
|
2246
2535
|
type: "button",
|
|
@@ -2251,19 +2540,19 @@ var AdminShell = defineComponent13({
|
|
|
2251
2540
|
},
|
|
2252
2541
|
[icon("menu")]
|
|
2253
2542
|
),
|
|
2254
|
-
|
|
2255
|
-
props.envLabel ?
|
|
2543
|
+
h16("span", { style: { fontWeight: 600, fontSize: "14px" } }, title),
|
|
2544
|
+
props.envLabel ? h16("span", { style: { ...styles.badge, marginLeft: "auto" } }, props.envLabel) : null
|
|
2256
2545
|
]),
|
|
2257
|
-
drawer.value ?
|
|
2546
|
+
drawer.value ? h16("div", { style: styles.drawer }, [
|
|
2258
2547
|
nav(),
|
|
2259
|
-
|
|
2548
|
+
h16("div", {
|
|
2260
2549
|
style: styles.scrim,
|
|
2261
2550
|
"aria-hidden": "true",
|
|
2262
2551
|
onClick: () => drawer.value = false
|
|
2263
2552
|
})
|
|
2264
2553
|
]) : null
|
|
2265
2554
|
] : [nav()],
|
|
2266
|
-
|
|
2555
|
+
h16("main", { class: "fonderie-admin-main", style: styles.main }, body())
|
|
2267
2556
|
]
|
|
2268
2557
|
);
|
|
2269
2558
|
};
|
|
@@ -2279,6 +2568,7 @@ export {
|
|
|
2279
2568
|
EnvironmentScreen,
|
|
2280
2569
|
MigrationsScreen,
|
|
2281
2570
|
ModulesScreen,
|
|
2571
|
+
OperatorsScreen,
|
|
2282
2572
|
RoutesScreen,
|
|
2283
2573
|
SubscriberScreen,
|
|
2284
2574
|
TokensScreen,
|