@fonderie/vue-admin-screens 0.5.0 → 0.7.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 +385 -178
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -4
- package/dist/index.d.ts +38 -4
- package/dist/index.js +362 -151
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -27,6 +27,7 @@ __export(index_exports, {
|
|
|
27
27
|
CatalogScreen: () => CatalogScreen,
|
|
28
28
|
ConfigScreen: () => ConfigScreen,
|
|
29
29
|
DoctorScreen: () => DoctorScreen,
|
|
30
|
+
MigrationsScreen: () => MigrationsScreen,
|
|
30
31
|
ModulesScreen: () => ModulesScreen,
|
|
31
32
|
RoutesScreen: () => RoutesScreen,
|
|
32
33
|
SubscriberScreen: () => SubscriberScreen,
|
|
@@ -38,7 +39,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
38
39
|
// src/screens/AdminShell.ts
|
|
39
40
|
var import_vue_config_admin_screens = require("@fonderie/vue-config-admin-screens");
|
|
40
41
|
var import_vue_courier_admin_screens = require("@fonderie/vue-courier-admin-screens");
|
|
41
|
-
var
|
|
42
|
+
var import_vue14 = require("vue");
|
|
42
43
|
|
|
43
44
|
// src/styles.ts
|
|
44
45
|
var styles = {
|
|
@@ -416,52 +417,133 @@ var RoutesScreen = (0, import_vue7.defineComponent)({
|
|
|
416
417
|
}
|
|
417
418
|
});
|
|
418
419
|
|
|
419
|
-
// src/screens/
|
|
420
|
+
// src/screens/MigrationsScreen.ts
|
|
420
421
|
var import_vue_admin7 = require("@fonderie/vue-admin");
|
|
421
422
|
var import_vue8 = require("vue");
|
|
423
|
+
function why(m, everApplied) {
|
|
424
|
+
if (m.pending.length === 0) return null;
|
|
425
|
+
if (m.blockedBy) return `Apply "${m.blockedBy}" first \u2014 it runs before this one and is behind.`;
|
|
426
|
+
if (everApplied && m.pending.some((p) => p.impact === "destructive"))
|
|
427
|
+
return "Contains a migration that deletes data. No down-migration brings it back \u2014 apply this one through CI or `npm run migrate`.";
|
|
428
|
+
return null;
|
|
429
|
+
}
|
|
430
|
+
var MigrationsScreen = (0, import_vue8.defineComponent)({
|
|
431
|
+
name: "FonderieMigrationsScreen",
|
|
432
|
+
props: { client: { type: Object, required: true } },
|
|
433
|
+
setup(props) {
|
|
434
|
+
const { report, isLoading, error, refresh, apply } = (0, import_vue_admin7.useAdminMigrations)(props.client);
|
|
435
|
+
const section = (m, everApplied) => {
|
|
436
|
+
const blocked = why(m, everApplied);
|
|
437
|
+
const files = m.pending.map((p) => p.file);
|
|
438
|
+
return (0, import_vue8.h)("section", { style: { marginBottom: "24px" } }, [
|
|
439
|
+
(0, import_vue8.h)("h2", { style: styles.subtitle }, `${m.name} \u2014 ${m.pending.length} pending`),
|
|
440
|
+
(0, import_vue8.h)(
|
|
441
|
+
"ul",
|
|
442
|
+
m.pending.map(
|
|
443
|
+
(p) => (0, import_vue8.h)("li", [
|
|
444
|
+
(0, import_vue8.h)("code", p.file),
|
|
445
|
+
" ",
|
|
446
|
+
(0, import_vue8.h)(
|
|
447
|
+
"span",
|
|
448
|
+
{ style: p.impact === "destructive" ? styles.bad : styles.advice },
|
|
449
|
+
p.impact
|
|
450
|
+
),
|
|
451
|
+
p.destructive.length > 0 ? (0, import_vue8.h)(
|
|
452
|
+
"ul",
|
|
453
|
+
p.destructive.map((s) => (0, import_vue8.h)("li", [(0, import_vue8.h)("code", s.slice(0, 120))]))
|
|
454
|
+
) : null
|
|
455
|
+
])
|
|
456
|
+
)
|
|
457
|
+
),
|
|
458
|
+
blocked ? (0, import_vue8.h)("p", { style: styles.advice }, blocked) : (0, import_vue8.h)(
|
|
459
|
+
"button",
|
|
460
|
+
{
|
|
461
|
+
type: "button",
|
|
462
|
+
style: styles.button,
|
|
463
|
+
disabled: isLoading.value || !m.appliable,
|
|
464
|
+
onClick: () => {
|
|
465
|
+
if (window.confirm(
|
|
466
|
+
`Apply ${m.pending.length} migration(s) to "${m.name}"? This changes the database schema.`
|
|
467
|
+
))
|
|
468
|
+
void apply(m.name, files).catch(() => {
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
},
|
|
472
|
+
`Apply ${m.pending.length} migration${m.pending.length === 1 ? "" : "s"}`
|
|
473
|
+
)
|
|
474
|
+
]);
|
|
475
|
+
};
|
|
476
|
+
return () => page(
|
|
477
|
+
"Migrations",
|
|
478
|
+
{ isLoading, error },
|
|
479
|
+
() => {
|
|
480
|
+
const r = report.value;
|
|
481
|
+
if (!r) return null;
|
|
482
|
+
const behind = r.modules.filter((m) => m.pending.length > 0);
|
|
483
|
+
if (behind.length === 0) return (0, import_vue8.h)("p", { style: styles.ok }, "Every module is up to date.");
|
|
484
|
+
return [
|
|
485
|
+
r.everApplied ? null : (0, import_vue8.h)(
|
|
486
|
+
"p",
|
|
487
|
+
{ style: styles.advice },
|
|
488
|
+
"This database has never been migrated \u2014 treating it as a first install, so nothing is held back."
|
|
489
|
+
),
|
|
490
|
+
...behind.map((m) => section(m, r.everApplied))
|
|
491
|
+
].filter(Boolean);
|
|
492
|
+
},
|
|
493
|
+
[refreshButton("Refresh", isLoading.value, () => void refresh())],
|
|
494
|
+
{
|
|
495
|
+
errorText: (e) => e.status === 403 ? "Applying migrations needs a token with the write scope." : e.explanation
|
|
496
|
+
}
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
// src/screens/TokensScreen.ts
|
|
502
|
+
var import_vue_admin8 = require("@fonderie/vue-admin");
|
|
503
|
+
var import_vue9 = require("vue");
|
|
422
504
|
var ALL = ["read", "write", "secrets"];
|
|
423
|
-
var TokensScreen = (0,
|
|
505
|
+
var TokensScreen = (0, import_vue9.defineComponent)({
|
|
424
506
|
name: "FonderieTokensScreen",
|
|
425
507
|
props: { client: { type: Object, required: true } },
|
|
426
508
|
setup(props) {
|
|
427
|
-
const { report, isLoading, error, issue, revoke } = (0,
|
|
428
|
-
const name = (0,
|
|
429
|
-
const scopes = (0,
|
|
430
|
-
const days = (0,
|
|
431
|
-
const minted = (0,
|
|
509
|
+
const { report, isLoading, error, issue, revoke } = (0, import_vue_admin8.useAdminTokens)(props.client);
|
|
510
|
+
const name = (0, import_vue9.ref)("");
|
|
511
|
+
const scopes = (0, import_vue9.ref)(["read"]);
|
|
512
|
+
const days = (0, import_vue9.ref)("");
|
|
513
|
+
const minted = (0, import_vue9.ref)(null);
|
|
432
514
|
const toggle = (s) => scopes.value = scopes.value.includes(s) ? scopes.value.filter((x) => x !== s) : [...scopes.value, s];
|
|
433
515
|
return () => {
|
|
434
516
|
const r = report.value;
|
|
435
|
-
return (0,
|
|
436
|
-
(0,
|
|
437
|
-
error.value ? (0,
|
|
517
|
+
return (0, import_vue9.h)("div", { style: styles.container }, [
|
|
518
|
+
(0, import_vue9.h)("h1", { style: styles.title }, "Access"),
|
|
519
|
+
error.value ? (0, import_vue9.h)(
|
|
438
520
|
"p",
|
|
439
521
|
{ style: styles.error, role: "alert" },
|
|
440
522
|
error.value.status === 401 ? "Issuing and revoking need the root token (the one in your deployment config)." : error.value.explanation
|
|
441
523
|
) : null,
|
|
442
|
-
(0,
|
|
443
|
-
r ? (0,
|
|
444
|
-
(0,
|
|
524
|
+
(0, import_vue9.h)("h2", { style: styles.subtitle }, "Root token"),
|
|
525
|
+
r ? (0, import_vue9.h)("p", [
|
|
526
|
+
(0, import_vue9.h)(
|
|
445
527
|
"span",
|
|
446
528
|
{ style: r.admin.ok ? styles.ok : styles.bad },
|
|
447
529
|
r.admin.ok ? "strong" : "weak"
|
|
448
530
|
),
|
|
449
531
|
...r.admin.problems.map(
|
|
450
|
-
(p) => (0,
|
|
532
|
+
(p) => (0, import_vue9.h)("div", { key: p.message, style: styles.bad }, p.message)
|
|
451
533
|
)
|
|
452
534
|
]) : null,
|
|
453
|
-
(0,
|
|
454
|
-
r?.issued === null ? (0,
|
|
535
|
+
(0, import_vue9.h)("h2", { style: styles.subtitle }, "Issued tokens"),
|
|
536
|
+
r?.issued === null ? (0, import_vue9.h)(
|
|
455
537
|
"p",
|
|
456
538
|
{ style: styles.muted },
|
|
457
539
|
"Issuing is off \u2014 give AdminModule a store and run its migrations."
|
|
458
540
|
) : [
|
|
459
|
-
minted.value ? (0,
|
|
541
|
+
minted.value ? (0, import_vue9.h)("p", { style: styles.ok }, [
|
|
460
542
|
"Copy this now \u2014 it is never shown again. ",
|
|
461
|
-
(0,
|
|
543
|
+
(0, import_vue9.h)("span", { style: styles.mono }, minted.value.token),
|
|
462
544
|
` (${minted.value.name})`
|
|
463
545
|
]) : null,
|
|
464
|
-
(0,
|
|
546
|
+
(0, import_vue9.h)(
|
|
465
547
|
"form",
|
|
466
548
|
{
|
|
467
549
|
style: styles.toolbar,
|
|
@@ -481,7 +563,7 @@ var TokensScreen = (0, import_vue8.defineComponent)({
|
|
|
481
563
|
}
|
|
482
564
|
},
|
|
483
565
|
[
|
|
484
|
-
(0,
|
|
566
|
+
(0, import_vue9.h)("input", {
|
|
485
567
|
value: name.value,
|
|
486
568
|
onInput: (e) => name.value = e.target.value,
|
|
487
569
|
placeholder: "name",
|
|
@@ -489,8 +571,8 @@ var TokensScreen = (0, import_vue8.defineComponent)({
|
|
|
489
571
|
"aria-label": "Name"
|
|
490
572
|
}),
|
|
491
573
|
...ALL.map(
|
|
492
|
-
(s) => (0,
|
|
493
|
-
(0,
|
|
574
|
+
(s) => (0, import_vue9.h)("label", { key: s, style: { ...styles.badge, cursor: "pointer" } }, [
|
|
575
|
+
(0, import_vue9.h)("input", {
|
|
494
576
|
type: "checkbox",
|
|
495
577
|
checked: scopes.value.includes(s),
|
|
496
578
|
onChange: () => toggle(s)
|
|
@@ -498,14 +580,14 @@ var TokensScreen = (0, import_vue8.defineComponent)({
|
|
|
498
580
|
` ${s}`
|
|
499
581
|
])
|
|
500
582
|
),
|
|
501
|
-
(0,
|
|
583
|
+
(0, import_vue9.h)("input", {
|
|
502
584
|
value: days.value,
|
|
503
585
|
onInput: (e) => days.value = e.target.value,
|
|
504
586
|
placeholder: "days (optional)",
|
|
505
587
|
style: { ...styles.button, cursor: "text", width: "140px" },
|
|
506
588
|
"aria-label": "Days"
|
|
507
589
|
}),
|
|
508
|
-
(0,
|
|
590
|
+
(0, import_vue9.h)(
|
|
509
591
|
"button",
|
|
510
592
|
{
|
|
511
593
|
type: "submit",
|
|
@@ -519,10 +601,10 @@ var TokensScreen = (0, import_vue8.defineComponent)({
|
|
|
519
601
|
r?.issued && r.issued.length > 0 ? table(
|
|
520
602
|
["Name", "Scopes", "Created", "Expires", "Last used", ""],
|
|
521
603
|
r.issued.map(
|
|
522
|
-
(t) => (0,
|
|
604
|
+
(t) => (0, import_vue9.h)("tr", { key: t.id }, [
|
|
523
605
|
td([
|
|
524
606
|
t.name,
|
|
525
|
-
t.revokedAt ? (0,
|
|
607
|
+
t.revokedAt ? (0, import_vue9.h)("span", { style: styles.badge }, " revoked") : ""
|
|
526
608
|
]),
|
|
527
609
|
td(t.scopes.join(", "), styles.mono),
|
|
528
610
|
td(
|
|
@@ -538,7 +620,7 @@ var TokensScreen = (0, import_vue8.defineComponent)({
|
|
|
538
620
|
styles.muted
|
|
539
621
|
),
|
|
540
622
|
td(
|
|
541
|
-
t.revokedAt ? "" : (0,
|
|
623
|
+
t.revokedAt ? "" : (0, import_vue9.h)(
|
|
542
624
|
"button",
|
|
543
625
|
{
|
|
544
626
|
type: "button",
|
|
@@ -556,21 +638,21 @@ var TokensScreen = (0, import_vue8.defineComponent)({
|
|
|
556
638
|
)
|
|
557
639
|
])
|
|
558
640
|
)
|
|
559
|
-
) : (0,
|
|
641
|
+
) : (0, import_vue9.h)("p", { style: styles.muted }, "None issued.")
|
|
560
642
|
],
|
|
561
|
-
(0,
|
|
562
|
-
r && r.legacy.length === 0 ? (0,
|
|
643
|
+
(0, import_vue9.h)("h2", { style: styles.subtitle }, "Legacy per-brick tokens"),
|
|
644
|
+
r && r.legacy.length === 0 ? (0, import_vue9.h)(
|
|
563
645
|
"p",
|
|
564
646
|
{ style: styles.muted },
|
|
565
647
|
"None \u2014 every brick's admin surface goes through this token."
|
|
566
|
-
) : (0,
|
|
648
|
+
) : (0, import_vue9.h)(
|
|
567
649
|
"ul",
|
|
568
650
|
{ style: styles.list },
|
|
569
651
|
(r?.legacy ?? []).map(
|
|
570
|
-
(l) => (0,
|
|
571
|
-
(0,
|
|
652
|
+
(l) => (0, import_vue9.h)("li", { key: l.module, style: styles.row }, [
|
|
653
|
+
(0, import_vue9.h)("span", { style: styles.mono }, l.module),
|
|
572
654
|
" ",
|
|
573
|
-
(0,
|
|
655
|
+
(0, import_vue9.h)(
|
|
574
656
|
"span",
|
|
575
657
|
{ style: styles.muted },
|
|
576
658
|
"still registers its standalone routes with its own token (deprecated)"
|
|
@@ -584,38 +666,50 @@ var TokensScreen = (0, import_vue8.defineComponent)({
|
|
|
584
666
|
});
|
|
585
667
|
|
|
586
668
|
// src/screens/UsersScreen.ts
|
|
587
|
-
var
|
|
588
|
-
var
|
|
589
|
-
var UsersScreen = (0,
|
|
669
|
+
var import_vue_admin9 = require("@fonderie/vue-admin");
|
|
670
|
+
var import_vue10 = require("vue");
|
|
671
|
+
var UsersScreen = (0, import_vue10.defineComponent)({
|
|
590
672
|
name: "FonderieUsersScreen",
|
|
591
|
-
props: {
|
|
673
|
+
props: {
|
|
674
|
+
client: { type: Object, required: true },
|
|
675
|
+
pageSize: { type: Number, default: 50 }
|
|
676
|
+
},
|
|
592
677
|
setup(props) {
|
|
593
|
-
const input = (0,
|
|
594
|
-
const email = (0,
|
|
595
|
-
const
|
|
678
|
+
const input = (0, import_vue10.ref)("");
|
|
679
|
+
const email = (0, import_vue10.ref)("");
|
|
680
|
+
const selectedId = (0, import_vue10.ref)("");
|
|
681
|
+
const list = (0, import_vue_admin9.useAdminUsers)(props.client, { limit: props.pageSize });
|
|
682
|
+
const { user, isLoading, error, suspend, unsuspend, revokeSessions } = (0, import_vue_admin9.useAdminUser)(
|
|
596
683
|
props.client,
|
|
597
|
-
{ email }
|
|
684
|
+
{ email, id: selectedId }
|
|
598
685
|
);
|
|
599
|
-
const userId = (0,
|
|
600
|
-
const sessions = (0,
|
|
601
|
-
const history = (0,
|
|
602
|
-
const
|
|
603
|
-
const
|
|
686
|
+
const userId = (0, import_vue10.computed)(() => user.value?.id ?? null);
|
|
687
|
+
const sessions = (0, import_vue_admin9.useAdminUserSessions)(props.client, userId);
|
|
688
|
+
const history = (0, import_vue_admin9.useAdminLoginHistory)(props.client, userId, { limit: 20 });
|
|
689
|
+
const showList = (0, import_vue10.computed)(() => !email.value && !selectedId.value);
|
|
690
|
+
const yesNo = (v) => (0, import_vue10.h)("span", { style: v ? styles.ok : styles.muted }, v ? "yes" : "no");
|
|
691
|
+
const row = (k, v) => (0, import_vue10.h)("tr", [td(k), td(v)]);
|
|
692
|
+
const clear = () => {
|
|
693
|
+
email.value = "";
|
|
694
|
+
selectedId.value = "";
|
|
695
|
+
input.value = "";
|
|
696
|
+
};
|
|
604
697
|
return () => {
|
|
605
698
|
const u = user.value;
|
|
606
|
-
return (0,
|
|
607
|
-
(0,
|
|
608
|
-
(0,
|
|
699
|
+
return (0, import_vue10.h)("div", { style: styles.container }, [
|
|
700
|
+
(0, import_vue10.h)("h1", { style: styles.title }, "Users"),
|
|
701
|
+
(0, import_vue10.h)(
|
|
609
702
|
"form",
|
|
610
703
|
{
|
|
611
704
|
style: styles.toolbar,
|
|
612
705
|
onSubmit: (e) => {
|
|
613
706
|
e.preventDefault();
|
|
707
|
+
selectedId.value = "";
|
|
614
708
|
email.value = input.value.trim();
|
|
615
709
|
}
|
|
616
710
|
},
|
|
617
711
|
[
|
|
618
|
-
(0,
|
|
712
|
+
(0, import_vue10.h)("input", {
|
|
619
713
|
type: "email",
|
|
620
714
|
value: input.value,
|
|
621
715
|
onInput: (e) => input.value = e.target.value,
|
|
@@ -623,28 +717,67 @@ var UsersScreen = (0, import_vue9.defineComponent)({
|
|
|
623
717
|
style: { ...styles.button, cursor: "text", minWidth: "280px" },
|
|
624
718
|
"aria-label": "Email"
|
|
625
719
|
}),
|
|
626
|
-
(0,
|
|
720
|
+
(0, import_vue10.h)(
|
|
627
721
|
"button",
|
|
628
722
|
{ type: "submit", style: styles.button, disabled: isLoading.value },
|
|
629
723
|
"Look up"
|
|
630
|
-
)
|
|
724
|
+
),
|
|
725
|
+
showList.value ? refreshButton("Refresh", list.isLoading.value, () => void list.refresh()) : refreshButton("\u2190 All users", false, clear)
|
|
631
726
|
]
|
|
632
727
|
),
|
|
633
|
-
|
|
728
|
+
showList.value ? (0, import_vue10.h)("div", [
|
|
729
|
+
list.error.value ? (0, import_vue10.h)("p", { style: styles.error, role: "alert" }, list.error.value.explanation) : null,
|
|
730
|
+
list.users.value.length === 0 && !list.isLoading.value ? (0, import_vue10.h)("p", { style: styles.muted }, "No users yet.") : table(
|
|
731
|
+
["Email", "Name", "Created", "Status"],
|
|
732
|
+
list.users.value.map(
|
|
733
|
+
(u2) => (0, import_vue10.h)("tr", { key: u2.id }, [
|
|
734
|
+
td(
|
|
735
|
+
(0, import_vue10.h)(
|
|
736
|
+
"button",
|
|
737
|
+
{
|
|
738
|
+
type: "button",
|
|
739
|
+
style: { ...styles.navItem, padding: 0 },
|
|
740
|
+
onClick: () => selectedId.value = u2.id
|
|
741
|
+
},
|
|
742
|
+
u2.email
|
|
743
|
+
)
|
|
744
|
+
),
|
|
745
|
+
td(
|
|
746
|
+
`${u2.firstName ?? ""} ${u2.lastName ?? ""}`.trim() || (0, import_vue10.h)("span", { style: styles.muted }, "\u2014")
|
|
747
|
+
),
|
|
748
|
+
td(new Date(u2.createdAt).toLocaleDateString()),
|
|
749
|
+
td(
|
|
750
|
+
u2.suspended ? (0, import_vue10.h)("span", { style: styles.badge }, "suspended") : u2.deletedAt ? (0, import_vue10.h)("span", { style: styles.badge }, "deleted") : (0, import_vue10.h)("span", { style: styles.muted }, "active")
|
|
751
|
+
)
|
|
752
|
+
])
|
|
753
|
+
)
|
|
754
|
+
),
|
|
755
|
+
list.isLoading.value ? (0, import_vue10.h)("p", { style: styles.status }, "Loading\u2026") : null,
|
|
756
|
+
list.hasMore.value && !list.isLoading.value ? (0, import_vue10.h)(
|
|
757
|
+
"button",
|
|
758
|
+
{
|
|
759
|
+
type: "button",
|
|
760
|
+
style: { ...styles.button, marginTop: "8px" },
|
|
761
|
+
onClick: () => void list.loadMore()
|
|
762
|
+
},
|
|
763
|
+
"Load more"
|
|
764
|
+
) : null
|
|
765
|
+
]) : null,
|
|
766
|
+
error.value ? (0, import_vue10.h)(
|
|
634
767
|
"p",
|
|
635
768
|
{ style: styles.error, role: "alert" },
|
|
636
769
|
error.value.status === 404 ? "No user with that email." : error.value.explanation
|
|
637
770
|
) : null,
|
|
638
771
|
u ? [
|
|
639
|
-
(0,
|
|
772
|
+
(0, import_vue10.h)("h2", { style: styles.subtitle }, [
|
|
640
773
|
u.firstName || u.lastName ? `${u.firstName} ${u.lastName}`.trim() : u.email,
|
|
641
774
|
" ",
|
|
642
|
-
u.suspended ? (0,
|
|
643
|
-
u.deletedAt ? (0,
|
|
775
|
+
u.suspended ? (0, import_vue10.h)("span", { style: styles.badge }, "suspended") : null,
|
|
776
|
+
u.deletedAt ? (0, import_vue10.h)("span", { style: styles.badge }, "deleted") : null
|
|
644
777
|
]),
|
|
645
|
-
(0,
|
|
646
|
-
(0,
|
|
647
|
-
row("id", (0,
|
|
778
|
+
(0, import_vue10.h)("table", { style: styles.table }, [
|
|
779
|
+
(0, import_vue10.h)("tbody", [
|
|
780
|
+
row("id", (0, import_vue10.h)("span", { style: styles.mono }, u.id)),
|
|
648
781
|
row("email", [u.email, " \xB7 verified ", yesNo(u.isEmailVerified)]),
|
|
649
782
|
row("MFA", yesNo(u.mfaEnabled)),
|
|
650
783
|
row(
|
|
@@ -653,12 +786,12 @@ var UsersScreen = (0, import_vue9.defineComponent)({
|
|
|
653
786
|
),
|
|
654
787
|
row(
|
|
655
788
|
"last login",
|
|
656
|
-
u.lastLogin ? new Date(u.lastLogin).toLocaleString() : (0,
|
|
789
|
+
u.lastLogin ? new Date(u.lastLogin).toLocaleString() : (0, import_vue10.h)("span", { style: styles.muted }, "never")
|
|
657
790
|
),
|
|
658
791
|
row("created", new Date(u.createdAt).toLocaleString())
|
|
659
792
|
])
|
|
660
793
|
]),
|
|
661
|
-
(0,
|
|
794
|
+
(0, import_vue10.h)("div", { style: { ...styles.toolbar, marginTop: "12px" } }, [
|
|
662
795
|
u.suspended ? refreshButton("Unsuspend", isLoading.value, () => void unsuspend()) : refreshButton("Suspend", isLoading.value, () => void suspend()),
|
|
663
796
|
refreshButton(
|
|
664
797
|
"Sign out everywhere",
|
|
@@ -666,17 +799,17 @@ var UsersScreen = (0, import_vue9.defineComponent)({
|
|
|
666
799
|
() => void revokeSessions().then(() => sessions.refresh())
|
|
667
800
|
)
|
|
668
801
|
]),
|
|
669
|
-
(0,
|
|
670
|
-
sessions.sessions.value.length === 0 ? (0,
|
|
802
|
+
(0, import_vue10.h)("h2", { style: styles.subtitle }, "Live sessions"),
|
|
803
|
+
sessions.sessions.value.length === 0 ? (0, import_vue10.h)("p", { style: styles.muted }, "None.") : (0, import_vue10.h)(
|
|
671
804
|
"ul",
|
|
672
805
|
{ style: styles.list },
|
|
673
806
|
sessions.sessions.value.map(
|
|
674
|
-
(s) => (0,
|
|
675
|
-
(0,
|
|
807
|
+
(s) => (0, import_vue10.h)("li", { key: s.id, style: styles.row }, [
|
|
808
|
+
(0, import_vue10.h)("span", { style: styles.mono }, s.ipAddress ?? "\u2014"),
|
|
676
809
|
" ",
|
|
677
|
-
(0,
|
|
810
|
+
(0, import_vue10.h)("span", { style: styles.muted }, s.userAgent ?? ""),
|
|
678
811
|
" ",
|
|
679
|
-
(0,
|
|
812
|
+
(0, import_vue10.h)(
|
|
680
813
|
"span",
|
|
681
814
|
{ style: styles.muted },
|
|
682
815
|
`since ${new Date(s.createdAt).toLocaleString()}`
|
|
@@ -684,25 +817,25 @@ var UsersScreen = (0, import_vue9.defineComponent)({
|
|
|
684
817
|
])
|
|
685
818
|
)
|
|
686
819
|
),
|
|
687
|
-
(0,
|
|
688
|
-
history.events.value.length === 0 && !history.isLoading.value ? (0,
|
|
820
|
+
(0, import_vue10.h)("h2", { style: styles.subtitle }, "Recent sign-ins"),
|
|
821
|
+
history.events.value.length === 0 && !history.isLoading.value ? (0, import_vue10.h)("p", { style: styles.muted }, "None recorded.") : (0, import_vue10.h)(
|
|
689
822
|
"ul",
|
|
690
823
|
{ style: styles.list },
|
|
691
824
|
history.events.value.map(
|
|
692
|
-
(e) => (0,
|
|
693
|
-
(0,
|
|
825
|
+
(e) => (0, import_vue10.h)("li", { key: e.id, style: styles.row }, [
|
|
826
|
+
(0, import_vue10.h)(
|
|
694
827
|
"span",
|
|
695
828
|
{ style: e.outcome === "success" ? styles.ok : styles.bad },
|
|
696
829
|
e.outcome
|
|
697
830
|
),
|
|
698
831
|
" ",
|
|
699
|
-
(0,
|
|
832
|
+
(0, import_vue10.h)("span", { style: styles.muted }, e.method),
|
|
700
833
|
" ",
|
|
701
|
-
(0,
|
|
834
|
+
(0, import_vue10.h)("span", { style: styles.muted }, new Date(e.createdAt).toLocaleString())
|
|
702
835
|
])
|
|
703
836
|
)
|
|
704
837
|
),
|
|
705
|
-
history.hasMore.value && !history.isLoading.value ? (0,
|
|
838
|
+
history.hasMore.value && !history.isLoading.value ? (0, import_vue10.h)(
|
|
706
839
|
"button",
|
|
707
840
|
{
|
|
708
841
|
type: "button",
|
|
@@ -718,26 +851,26 @@ var UsersScreen = (0, import_vue9.defineComponent)({
|
|
|
718
851
|
});
|
|
719
852
|
|
|
720
853
|
// src/screens/CatalogScreen.ts
|
|
721
|
-
var
|
|
722
|
-
var
|
|
723
|
-
var CatalogScreen = (0,
|
|
854
|
+
var import_vue_admin10 = require("@fonderie/vue-admin");
|
|
855
|
+
var import_vue11 = require("vue");
|
|
856
|
+
var CatalogScreen = (0, import_vue11.defineComponent)({
|
|
724
857
|
name: "FonderieCatalogScreen",
|
|
725
858
|
props: { client: { type: Object, required: true } },
|
|
726
859
|
setup(props) {
|
|
727
|
-
const { catalog, isLoading, error, refresh, deletePlan } = (0,
|
|
860
|
+
const { catalog, isLoading, error, refresh, deletePlan } = (0, import_vue_admin10.useAdminCatalog)(props.client);
|
|
728
861
|
const money = (v) => v == null ? "\u2014" : (v / 100).toFixed(2);
|
|
729
862
|
return () => {
|
|
730
863
|
const c = catalog.value;
|
|
731
|
-
return (0,
|
|
732
|
-
(0,
|
|
733
|
-
(0,
|
|
864
|
+
return (0, import_vue11.h)("div", { style: styles.container }, [
|
|
865
|
+
(0, import_vue11.h)("div", { style: styles.toolbar }, [
|
|
866
|
+
(0, import_vue11.h)("h1", { style: { ...styles.title, marginBottom: 0 } }, "Catalog"),
|
|
734
867
|
refreshButton("Refresh", isLoading.value, () => void refresh())
|
|
735
868
|
]),
|
|
736
|
-
error.value ? (0,
|
|
737
|
-
isLoading.value && !c ? (0,
|
|
869
|
+
error.value ? (0, import_vue11.h)("p", { style: styles.error, role: "alert" }, error.value.explanation) : null,
|
|
870
|
+
isLoading.value && !c ? (0, import_vue11.h)("p", { style: styles.status }, "Loading\u2026") : null,
|
|
738
871
|
c ? [
|
|
739
|
-
(0,
|
|
740
|
-
(0,
|
|
872
|
+
(0, import_vue11.h)("h2", { style: styles.subtitle }, "Configured (code)"),
|
|
873
|
+
(0, import_vue11.h)(
|
|
741
874
|
"pre",
|
|
742
875
|
{
|
|
743
876
|
style: {
|
|
@@ -749,14 +882,14 @@ var CatalogScreen = (0, import_vue10.defineComponent)({
|
|
|
749
882
|
},
|
|
750
883
|
JSON.stringify(c.configured, null, 2)
|
|
751
884
|
),
|
|
752
|
-
(0,
|
|
753
|
-
c.stored.length === 0 ? (0,
|
|
885
|
+
(0, import_vue11.h)("h2", { style: styles.subtitle }, "Stored (database)"),
|
|
886
|
+
c.stored.length === 0 ? (0, import_vue11.h)("p", { style: styles.muted }, "No stored plans.") : table(
|
|
754
887
|
["Plan", "Tier", "Seats", "Monthly", "Yearly", "Trial", ""],
|
|
755
888
|
c.stored.map(
|
|
756
|
-
(p) => (0,
|
|
889
|
+
(p) => (0, import_vue11.h)("tr", { key: p.id }, [
|
|
757
890
|
td([
|
|
758
|
-
(0,
|
|
759
|
-
p.description ? (0,
|
|
891
|
+
(0, import_vue11.h)("strong", p.name),
|
|
892
|
+
p.description ? (0, import_vue11.h)("div", { style: styles.muted }, p.description) : ""
|
|
760
893
|
]),
|
|
761
894
|
td(String(p.tier)),
|
|
762
895
|
td(p.seats == null ? "\u221E" : String(p.seats)),
|
|
@@ -764,7 +897,7 @@ var CatalogScreen = (0, import_vue10.defineComponent)({
|
|
|
764
897
|
td(money(p.pricing?.yearly)),
|
|
765
898
|
td(p.trialDays ? `${p.trialDays} d` : "\u2014"),
|
|
766
899
|
td(
|
|
767
|
-
(0,
|
|
900
|
+
(0, import_vue11.h)(
|
|
768
901
|
"button",
|
|
769
902
|
{
|
|
770
903
|
type: "button",
|
|
@@ -788,20 +921,30 @@ var CatalogScreen = (0, import_vue10.defineComponent)({
|
|
|
788
921
|
});
|
|
789
922
|
|
|
790
923
|
// src/screens/SubscriberScreen.ts
|
|
791
|
-
var
|
|
792
|
-
var
|
|
793
|
-
var SubscriberScreen = (0,
|
|
924
|
+
var import_vue_admin11 = require("@fonderie/vue-admin");
|
|
925
|
+
var import_vue12 = require("vue");
|
|
926
|
+
var SubscriberScreen = (0, import_vue12.defineComponent)({
|
|
794
927
|
name: "FonderieSubscriberScreen",
|
|
795
|
-
props: {
|
|
928
|
+
props: {
|
|
929
|
+
client: { type: Object, required: true },
|
|
930
|
+
pageSize: { type: Number, default: 50 }
|
|
931
|
+
},
|
|
796
932
|
setup(props) {
|
|
797
|
-
const type = (0,
|
|
798
|
-
const idInput = (0,
|
|
799
|
-
const subscriber = (0,
|
|
800
|
-
const
|
|
801
|
-
const
|
|
802
|
-
const
|
|
803
|
-
|
|
804
|
-
|
|
933
|
+
const type = (0, import_vue12.ref)("user");
|
|
934
|
+
const idInput = (0, import_vue12.ref)("");
|
|
935
|
+
const subscriber = (0, import_vue12.ref)(null);
|
|
936
|
+
const list = (0, import_vue_admin11.useAdminSubscribers)(props.client, { limit: props.pageSize });
|
|
937
|
+
const { subscription, wallet, ledger, hasMoreLedger, isLoading, error, loadMoreLedger, grant } = (0, import_vue_admin11.useAdminSubscriber)(props.client, subscriber, { limit: 20 });
|
|
938
|
+
const open = (t, id) => {
|
|
939
|
+
granted.value = null;
|
|
940
|
+
type.value = t;
|
|
941
|
+
idInput.value = id;
|
|
942
|
+
subscriber.value = { type: t, id };
|
|
943
|
+
};
|
|
944
|
+
const amount = (0, import_vue12.ref)("");
|
|
945
|
+
const note = (0, import_vue12.ref)("");
|
|
946
|
+
const granted = (0, import_vue12.ref)(null);
|
|
947
|
+
const input = (model, placeholder, extra = {}) => (0, import_vue12.h)("input", {
|
|
805
948
|
value: model.value,
|
|
806
949
|
onInput: (e) => model.value = e.target.value,
|
|
807
950
|
placeholder,
|
|
@@ -811,9 +954,9 @@ var SubscriberScreen = (0, import_vue11.defineComponent)({
|
|
|
811
954
|
return () => {
|
|
812
955
|
const s = subscription.value;
|
|
813
956
|
const w = wallet.value;
|
|
814
|
-
return (0,
|
|
815
|
-
(0,
|
|
816
|
-
(0,
|
|
957
|
+
return (0, import_vue12.h)("div", { style: styles.container }, [
|
|
958
|
+
(0, import_vue12.h)("h1", { style: styles.title }, "Subscriber"),
|
|
959
|
+
(0, import_vue12.h)(
|
|
817
960
|
"form",
|
|
818
961
|
{
|
|
819
962
|
style: styles.toolbar,
|
|
@@ -824,7 +967,7 @@ var SubscriberScreen = (0, import_vue11.defineComponent)({
|
|
|
824
967
|
}
|
|
825
968
|
},
|
|
826
969
|
[
|
|
827
|
-
(0,
|
|
970
|
+
(0, import_vue12.h)(
|
|
828
971
|
"select",
|
|
829
972
|
{
|
|
830
973
|
value: type.value,
|
|
@@ -833,49 +976,109 @@ var SubscriberScreen = (0, import_vue11.defineComponent)({
|
|
|
833
976
|
"aria-label": "Type"
|
|
834
977
|
},
|
|
835
978
|
[
|
|
836
|
-
(0,
|
|
837
|
-
(0,
|
|
979
|
+
(0, import_vue12.h)("option", { value: "user" }, "user"),
|
|
980
|
+
(0, import_vue12.h)("option", { value: "workspace" }, "workspace")
|
|
838
981
|
]
|
|
839
982
|
),
|
|
840
983
|
input(idInput, "subscriber id", { minWidth: "280px" }),
|
|
841
|
-
(0,
|
|
984
|
+
(0, import_vue12.h)(
|
|
842
985
|
"button",
|
|
843
986
|
{ type: "submit", style: styles.button, disabled: isLoading.value },
|
|
844
987
|
"Look up"
|
|
988
|
+
),
|
|
989
|
+
subscriber.value ? (0, import_vue12.h)(
|
|
990
|
+
"button",
|
|
991
|
+
{
|
|
992
|
+
type: "button",
|
|
993
|
+
style: styles.button,
|
|
994
|
+
onClick: () => {
|
|
995
|
+
subscriber.value = null;
|
|
996
|
+
idInput.value = "";
|
|
997
|
+
granted.value = null;
|
|
998
|
+
}
|
|
999
|
+
},
|
|
1000
|
+
"\u2190 All subscribers"
|
|
1001
|
+
) : (0, import_vue12.h)(
|
|
1002
|
+
"button",
|
|
1003
|
+
{
|
|
1004
|
+
type: "button",
|
|
1005
|
+
style: styles.button,
|
|
1006
|
+
disabled: list.isLoading.value,
|
|
1007
|
+
onClick: () => void list.refresh()
|
|
1008
|
+
},
|
|
1009
|
+
"Refresh"
|
|
845
1010
|
)
|
|
846
1011
|
]
|
|
847
1012
|
),
|
|
848
|
-
|
|
1013
|
+
!subscriber.value ? (0, import_vue12.h)("div", [
|
|
1014
|
+
list.error.value ? (0, import_vue12.h)("p", { style: styles.error, role: "alert" }, list.error.value.explanation) : null,
|
|
1015
|
+
list.subscriptions.value.length === 0 && !list.isLoading.value ? (0, import_vue12.h)("p", { style: styles.muted }, "No subscribers yet.") : table(
|
|
1016
|
+
["Subscriber", "Plan", "Status", "Renews"],
|
|
1017
|
+
list.subscriptions.value.map(
|
|
1018
|
+
(sub) => (0, import_vue12.h)("tr", { key: sub.id }, [
|
|
1019
|
+
td(
|
|
1020
|
+
(0, import_vue12.h)(
|
|
1021
|
+
"button",
|
|
1022
|
+
{
|
|
1023
|
+
type: "button",
|
|
1024
|
+
style: { ...styles.navItem, padding: 0, ...styles.mono },
|
|
1025
|
+
onClick: () => open(sub.subscriberType, sub.subscriberId)
|
|
1026
|
+
},
|
|
1027
|
+
`${sub.subscriberType}/${sub.subscriberId}`
|
|
1028
|
+
)
|
|
1029
|
+
),
|
|
1030
|
+
td(`${sub.plan} \xB7 ${sub.interval}`),
|
|
1031
|
+
td(
|
|
1032
|
+
sub.cancelAtPeriodEnd ? [sub.status, " ", (0, import_vue12.h)("span", { style: styles.badge }, "cancels")] : sub.status
|
|
1033
|
+
),
|
|
1034
|
+
td(
|
|
1035
|
+
sub.currentPeriodEnd ? new Date(sub.currentPeriodEnd).toLocaleDateString() : (0, import_vue12.h)("span", { style: styles.muted }, "\u2014")
|
|
1036
|
+
)
|
|
1037
|
+
])
|
|
1038
|
+
)
|
|
1039
|
+
),
|
|
1040
|
+
list.isLoading.value ? (0, import_vue12.h)("p", { style: styles.status }, "Loading\u2026") : null,
|
|
1041
|
+
list.hasMore.value && !list.isLoading.value ? (0, import_vue12.h)(
|
|
1042
|
+
"button",
|
|
1043
|
+
{
|
|
1044
|
+
type: "button",
|
|
1045
|
+
style: { ...styles.button, marginTop: "8px" },
|
|
1046
|
+
onClick: () => void list.loadMore()
|
|
1047
|
+
},
|
|
1048
|
+
"Load more"
|
|
1049
|
+
) : null
|
|
1050
|
+
]) : null,
|
|
1051
|
+
error.value ? (0, import_vue12.h)("p", { style: styles.error, role: "alert" }, error.value.explanation) : null,
|
|
849
1052
|
subscriber.value && !isLoading.value ? [
|
|
850
|
-
(0,
|
|
851
|
-
s ? (0,
|
|
852
|
-
(0,
|
|
853
|
-
(0,
|
|
854
|
-
(0,
|
|
1053
|
+
(0, import_vue12.h)("h2", { style: styles.subtitle }, "Subscription"),
|
|
1054
|
+
s ? (0, import_vue12.h)("table", { style: styles.table }, [
|
|
1055
|
+
(0, import_vue12.h)("tbody", [
|
|
1056
|
+
(0, import_vue12.h)("tr", [td("plan"), td([(0, import_vue12.h)("strong", s.plan), ` \xB7 ${s.interval}`])]),
|
|
1057
|
+
(0, import_vue12.h)("tr", [
|
|
855
1058
|
td("status"),
|
|
856
1059
|
td(`${s.status}${s.cancelAtPeriodEnd ? " \xB7 cancels at period end" : ""}`)
|
|
857
1060
|
]),
|
|
858
|
-
(0,
|
|
1061
|
+
(0, import_vue12.h)("tr", [
|
|
859
1062
|
td("period"),
|
|
860
1063
|
td(
|
|
861
1064
|
`${s.currentPeriodStart ? new Date(s.currentPeriodStart).toLocaleDateString() : "\u2014"} \u2192 ${s.currentPeriodEnd ? new Date(s.currentPeriodEnd).toLocaleDateString() : "\u2014"}`
|
|
862
1065
|
)
|
|
863
1066
|
]),
|
|
864
|
-
(0,
|
|
1067
|
+
(0, import_vue12.h)("tr", [td("provider"), td(s.providerSubscriptionId ?? "\u2014", styles.mono)])
|
|
865
1068
|
])
|
|
866
|
-
]) : (0,
|
|
867
|
-
(0,
|
|
1069
|
+
]) : (0, import_vue12.h)("p", { style: styles.muted }, "No subscription."),
|
|
1070
|
+
(0, import_vue12.h)("h2", { style: styles.subtitle }, "Wallet"),
|
|
868
1071
|
w ? [
|
|
869
|
-
(0,
|
|
870
|
-
(0,
|
|
1072
|
+
(0, import_vue12.h)("p", [
|
|
1073
|
+
(0, import_vue12.h)("strong", w.balance),
|
|
871
1074
|
` ${w.currency} `,
|
|
872
|
-
(0,
|
|
1075
|
+
(0, import_vue12.h)(
|
|
873
1076
|
"span",
|
|
874
1077
|
{ style: styles.muted },
|
|
875
1078
|
`(granted ${w.granted ?? "0"} \xB7 purchased ${w.purchased ?? "0"}) \xB7 minor units, precision ${w.precision}`
|
|
876
1079
|
)
|
|
877
1080
|
]),
|
|
878
|
-
(0,
|
|
1081
|
+
(0, import_vue12.h)(
|
|
879
1082
|
"form",
|
|
880
1083
|
{
|
|
881
1084
|
style: styles.toolbar,
|
|
@@ -900,7 +1103,7 @@ var SubscriberScreen = (0, import_vue11.defineComponent)({
|
|
|
900
1103
|
[
|
|
901
1104
|
input(amount, "amount (minor units)"),
|
|
902
1105
|
input(note, "reason (optional)", { minWidth: "220px" }),
|
|
903
|
-
(0,
|
|
1106
|
+
(0, import_vue12.h)(
|
|
904
1107
|
"button",
|
|
905
1108
|
{
|
|
906
1109
|
type: "submit",
|
|
@@ -909,14 +1112,14 @@ var SubscriberScreen = (0, import_vue11.defineComponent)({
|
|
|
909
1112
|
},
|
|
910
1113
|
"Grant"
|
|
911
1114
|
),
|
|
912
|
-
granted.value ? (0,
|
|
1115
|
+
granted.value ? (0, import_vue12.h)("span", { style: styles.ok }, granted.value) : null
|
|
913
1116
|
]
|
|
914
1117
|
),
|
|
915
|
-
(0,
|
|
916
|
-
ledger.value.length === 0 ? (0,
|
|
1118
|
+
(0, import_vue12.h)("h2", { style: styles.subtitle }, "Ledger"),
|
|
1119
|
+
ledger.value.length === 0 ? (0, import_vue12.h)("p", { style: styles.muted }, "Nothing moved yet.") : table(
|
|
917
1120
|
["When", "Kind", "Amount", "Note"],
|
|
918
1121
|
ledger.value.map(
|
|
919
|
-
(t) => (0,
|
|
1122
|
+
(t) => (0, import_vue12.h)("tr", { key: t.id }, [
|
|
920
1123
|
td(new Date(t.createdAt).toLocaleString(), styles.muted),
|
|
921
1124
|
td(t.type),
|
|
922
1125
|
td(t.amount, styles.mono),
|
|
@@ -924,7 +1127,7 @@ var SubscriberScreen = (0, import_vue11.defineComponent)({
|
|
|
924
1127
|
])
|
|
925
1128
|
)
|
|
926
1129
|
),
|
|
927
|
-
hasMoreLedger.value ? (0,
|
|
1130
|
+
hasMoreLedger.value ? (0, import_vue12.h)(
|
|
928
1131
|
"button",
|
|
929
1132
|
{
|
|
930
1133
|
type: "button",
|
|
@@ -933,7 +1136,7 @@ var SubscriberScreen = (0, import_vue11.defineComponent)({
|
|
|
933
1136
|
},
|
|
934
1137
|
"Load more"
|
|
935
1138
|
) : null
|
|
936
|
-
] : (0,
|
|
1139
|
+
] : (0, import_vue12.h)(
|
|
937
1140
|
"p",
|
|
938
1141
|
{ style: styles.muted },
|
|
939
1142
|
"No wallet \u2014 billing has no wallet configuration."
|
|
@@ -945,31 +1148,31 @@ var SubscriberScreen = (0, import_vue11.defineComponent)({
|
|
|
945
1148
|
});
|
|
946
1149
|
|
|
947
1150
|
// src/screens/AuditScreen.ts
|
|
948
|
-
var
|
|
949
|
-
var
|
|
950
|
-
var AuditScreen = (0,
|
|
1151
|
+
var import_vue_admin12 = require("@fonderie/vue-admin");
|
|
1152
|
+
var import_vue13 = require("vue");
|
|
1153
|
+
var AuditScreen = (0, import_vue13.defineComponent)({
|
|
951
1154
|
name: "FonderieAuditScreen",
|
|
952
1155
|
props: {
|
|
953
1156
|
client: { type: Object, required: true },
|
|
954
1157
|
pageSize: { type: Number, default: 50 }
|
|
955
1158
|
},
|
|
956
1159
|
setup(props) {
|
|
957
|
-
const draft = (0,
|
|
958
|
-
const query = (0,
|
|
959
|
-
const { events, hasMore, isLoading, error, refresh, loadMore } = (0,
|
|
1160
|
+
const draft = (0, import_vue13.ref)({ workspaceId: "", type: "", actorId: "" });
|
|
1161
|
+
const query = (0, import_vue13.ref)({ limit: props.pageSize });
|
|
1162
|
+
const { events, hasMore, isLoading, error, refresh, loadMore } = (0, import_vue_admin12.useAdminAudit)(
|
|
960
1163
|
props.client,
|
|
961
1164
|
query
|
|
962
1165
|
);
|
|
963
|
-
const field = (key, placeholder) => (0,
|
|
1166
|
+
const field = (key, placeholder) => (0, import_vue13.h)("input", {
|
|
964
1167
|
value: draft.value[key],
|
|
965
1168
|
onInput: (e) => draft.value = { ...draft.value, [key]: e.target.value },
|
|
966
1169
|
placeholder,
|
|
967
1170
|
style: { ...styles.button, cursor: "text" },
|
|
968
1171
|
"aria-label": placeholder
|
|
969
1172
|
});
|
|
970
|
-
return () => (0,
|
|
971
|
-
(0,
|
|
972
|
-
(0,
|
|
1173
|
+
return () => (0, import_vue13.h)("div", { style: styles.container }, [
|
|
1174
|
+
(0, import_vue13.h)("h1", { style: styles.title }, "Audit"),
|
|
1175
|
+
(0, import_vue13.h)(
|
|
973
1176
|
"form",
|
|
974
1177
|
{
|
|
975
1178
|
style: styles.toolbar,
|
|
@@ -988,7 +1191,7 @@ var AuditScreen = (0, import_vue12.defineComponent)({
|
|
|
988
1191
|
field("workspaceId", "workspace id (all if empty)"),
|
|
989
1192
|
field("type", "event type"),
|
|
990
1193
|
field("actorId", "actor id"),
|
|
991
|
-
(0,
|
|
1194
|
+
(0, import_vue13.h)(
|
|
992
1195
|
"button",
|
|
993
1196
|
{ type: "submit", style: styles.button, disabled: isLoading.value },
|
|
994
1197
|
"Filter"
|
|
@@ -996,11 +1199,11 @@ var AuditScreen = (0, import_vue12.defineComponent)({
|
|
|
996
1199
|
refreshButton("Refresh", isLoading.value, () => void refresh())
|
|
997
1200
|
]
|
|
998
1201
|
),
|
|
999
|
-
error.value ? (0,
|
|
1000
|
-
events.value.length === 0 && !isLoading.value ? (0,
|
|
1202
|
+
error.value ? (0, import_vue13.h)("p", { style: styles.error, role: "alert" }, error.value.explanation) : null,
|
|
1203
|
+
events.value.length === 0 && !isLoading.value ? (0, import_vue13.h)("p", { style: styles.muted }, "Nothing recorded for this filter.") : table(
|
|
1001
1204
|
["When", "Type", "Workspace", "Actor", "Request"],
|
|
1002
1205
|
events.value.map(
|
|
1003
|
-
(e) => (0,
|
|
1206
|
+
(e) => (0, import_vue13.h)("tr", { key: e.id }, [
|
|
1004
1207
|
td(new Date(e.createdAt).toLocaleString(), styles.muted),
|
|
1005
1208
|
td(e.type, styles.mono),
|
|
1006
1209
|
td(String(e.payload["workspaceId"] ?? "\u2014"), styles.mono),
|
|
@@ -1009,8 +1212,8 @@ var AuditScreen = (0, import_vue12.defineComponent)({
|
|
|
1009
1212
|
])
|
|
1010
1213
|
)
|
|
1011
1214
|
),
|
|
1012
|
-
isLoading.value ? (0,
|
|
1013
|
-
hasMore.value && !isLoading.value ? (0,
|
|
1215
|
+
isLoading.value ? (0, import_vue13.h)("p", { style: styles.status }, "Loading\u2026") : null,
|
|
1216
|
+
hasMore.value && !isLoading.value ? (0, import_vue13.h)(
|
|
1014
1217
|
"button",
|
|
1015
1218
|
{
|
|
1016
1219
|
type: "button",
|
|
@@ -1050,11 +1253,12 @@ var NAV = [
|
|
|
1050
1253
|
items: [
|
|
1051
1254
|
{ page: "audit", label: "Audit", needs: "audit" },
|
|
1052
1255
|
{ page: "log", label: "Admin log" },
|
|
1053
|
-
{ page: "tokens", label: "Access" }
|
|
1256
|
+
{ page: "tokens", label: "Access" },
|
|
1257
|
+
{ page: "migrations", label: "Migrations" }
|
|
1054
1258
|
]
|
|
1055
1259
|
}
|
|
1056
1260
|
];
|
|
1057
|
-
var AdminShell = (0,
|
|
1261
|
+
var AdminShell = (0, import_vue14.defineComponent)({
|
|
1058
1262
|
name: "FonderieAdminShell",
|
|
1059
1263
|
props: {
|
|
1060
1264
|
client: { type: Object, required: true },
|
|
@@ -1075,15 +1279,15 @@ var AdminShell = (0, import_vue13.defineComponent)({
|
|
|
1075
1279
|
},
|
|
1076
1280
|
emits: { navigate: (_page) => true },
|
|
1077
1281
|
setup(props, { emit }) {
|
|
1078
|
-
const own = (0,
|
|
1079
|
-
const current = (0,
|
|
1080
|
-
const editing = (0,
|
|
1282
|
+
const own = (0, import_vue14.ref)("attention");
|
|
1283
|
+
const current = (0, import_vue14.computed)(() => props.page ?? own.value);
|
|
1284
|
+
const editing = (0, import_vue14.ref)(null);
|
|
1081
1285
|
const go = (p) => {
|
|
1082
1286
|
editing.value = null;
|
|
1083
1287
|
emit("navigate", p);
|
|
1084
1288
|
if (props.page === void 0) own.value = p;
|
|
1085
1289
|
};
|
|
1086
|
-
const back = () => (0,
|
|
1290
|
+
const back = () => (0, import_vue14.h)(
|
|
1087
1291
|
"button",
|
|
1088
1292
|
{ type: "button", style: styles.button, onClick: () => editing.value = null },
|
|
1089
1293
|
"\u2190 Back"
|
|
@@ -1092,43 +1296,45 @@ var AdminShell = (0, import_vue13.defineComponent)({
|
|
|
1092
1296
|
const c = props.client;
|
|
1093
1297
|
switch (current.value) {
|
|
1094
1298
|
case "attention":
|
|
1095
|
-
return (0,
|
|
1299
|
+
return (0, import_vue14.h)(AttentionScreen, { client: c });
|
|
1096
1300
|
case "modules":
|
|
1097
|
-
return (0,
|
|
1301
|
+
return (0, import_vue14.h)(ModulesScreen, { client: c });
|
|
1098
1302
|
case "doctor":
|
|
1099
|
-
return (0,
|
|
1303
|
+
return (0, import_vue14.h)(DoctorScreen, { client: c });
|
|
1100
1304
|
case "config":
|
|
1101
|
-
return (0,
|
|
1305
|
+
return (0, import_vue14.h)(ConfigScreen, { client: c });
|
|
1102
1306
|
case "routes":
|
|
1103
|
-
return (0,
|
|
1307
|
+
return (0, import_vue14.h)(RoutesScreen, { client: c });
|
|
1104
1308
|
case "tokens":
|
|
1105
|
-
return (0,
|
|
1309
|
+
return (0, import_vue14.h)(TokensScreen, { client: c });
|
|
1310
|
+
case "migrations":
|
|
1311
|
+
return (0, import_vue14.h)(MigrationsScreen, { client: c });
|
|
1106
1312
|
case "log":
|
|
1107
|
-
return (0,
|
|
1313
|
+
return (0, import_vue14.h)(AdminLogScreen, { client: c });
|
|
1108
1314
|
case "catalog":
|
|
1109
|
-
return props.billingClient ? (0,
|
|
1315
|
+
return props.billingClient ? (0, import_vue14.h)(CatalogScreen, { client: props.billingClient }) : (0, import_vue14.h)(
|
|
1110
1316
|
"p",
|
|
1111
1317
|
{ style: styles.status },
|
|
1112
1318
|
"Pass a BillingAdminClient to see the catalog here."
|
|
1113
1319
|
);
|
|
1114
1320
|
case "subscriber":
|
|
1115
|
-
return props.billingClient ? (0,
|
|
1321
|
+
return props.billingClient ? (0, import_vue14.h)(SubscriberScreen, { client: props.billingClient }) : (0, import_vue14.h)(
|
|
1116
1322
|
"p",
|
|
1117
1323
|
{ style: styles.status },
|
|
1118
1324
|
"Pass a BillingAdminClient to look up subscribers here."
|
|
1119
1325
|
);
|
|
1120
1326
|
case "audit":
|
|
1121
|
-
return props.auditClient ? (0,
|
|
1327
|
+
return props.auditClient ? (0, import_vue14.h)(AuditScreen, { client: props.auditClient }) : (0, import_vue14.h)(
|
|
1122
1328
|
"p",
|
|
1123
1329
|
{ style: styles.status },
|
|
1124
1330
|
"Pass an AuditAdminClient to see the audit trail here."
|
|
1125
1331
|
);
|
|
1126
1332
|
case "users":
|
|
1127
|
-
return props.authClient ? (0,
|
|
1333
|
+
return props.authClient ? (0, import_vue14.h)(UsersScreen, { client: props.authClient }) : (0, import_vue14.h)("p", { style: styles.status }, "Pass an AuthAdminClient to look up users here.");
|
|
1128
1334
|
case "settings": {
|
|
1129
1335
|
const cc = props.configClient;
|
|
1130
1336
|
if (!cc)
|
|
1131
|
-
return (0,
|
|
1337
|
+
return (0, import_vue14.h)(
|
|
1132
1338
|
"p",
|
|
1133
1339
|
{ style: styles.status },
|
|
1134
1340
|
"Pass a ConfigAdminClient to manage config and secrets here."
|
|
@@ -1137,7 +1343,7 @@ var AdminShell = (0, import_vue13.defineComponent)({
|
|
|
1137
1343
|
if (e && e.kind !== "template")
|
|
1138
1344
|
return [
|
|
1139
1345
|
back(),
|
|
1140
|
-
(0,
|
|
1346
|
+
(0, import_vue14.h)(import_vue_config_admin_screens.ConfigEditorScreen, {
|
|
1141
1347
|
client: cc,
|
|
1142
1348
|
kind: e.kind,
|
|
1143
1349
|
configKey: e.key,
|
|
@@ -1145,7 +1351,7 @@ var AdminShell = (0, import_vue13.defineComponent)({
|
|
|
1145
1351
|
onSaved: () => editing.value = null
|
|
1146
1352
|
})
|
|
1147
1353
|
];
|
|
1148
|
-
return (0,
|
|
1354
|
+
return (0, import_vue14.h)(import_vue_config_admin_screens.ConfigListScreen, {
|
|
1149
1355
|
client: cc,
|
|
1150
1356
|
...props.environment !== void 0 ? { environment: props.environment } : {},
|
|
1151
1357
|
"onSelect-config": (key) => editing.value = { kind: "config", key },
|
|
@@ -1155,7 +1361,7 @@ var AdminShell = (0, import_vue13.defineComponent)({
|
|
|
1155
1361
|
case "templates": {
|
|
1156
1362
|
const kc = props.courierClient;
|
|
1157
1363
|
if (!kc)
|
|
1158
|
-
return (0,
|
|
1364
|
+
return (0, import_vue14.h)(
|
|
1159
1365
|
"p",
|
|
1160
1366
|
{ style: styles.status },
|
|
1161
1367
|
"Pass a CourierAdminClient to manage templates here."
|
|
@@ -1164,21 +1370,21 @@ var AdminShell = (0, import_vue13.defineComponent)({
|
|
|
1164
1370
|
if (e?.kind === "template")
|
|
1165
1371
|
return [
|
|
1166
1372
|
back(),
|
|
1167
|
-
(0,
|
|
1373
|
+
(0, import_vue14.h)(import_vue_courier_admin_screens.TemplateEditorScreen, {
|
|
1168
1374
|
client: kc,
|
|
1169
1375
|
type: e.type,
|
|
1170
1376
|
onSaved: () => editing.value = null
|
|
1171
1377
|
})
|
|
1172
1378
|
];
|
|
1173
|
-
return (0,
|
|
1379
|
+
return (0, import_vue14.h)(import_vue_courier_admin_screens.TemplateListScreen, {
|
|
1174
1380
|
client: kc,
|
|
1175
1381
|
"onSelect-template": (t) => editing.value = { kind: "template", type: t.type }
|
|
1176
1382
|
});
|
|
1177
1383
|
}
|
|
1178
1384
|
}
|
|
1179
1385
|
};
|
|
1180
|
-
return () => (0,
|
|
1181
|
-
(0,
|
|
1386
|
+
return () => (0, import_vue14.h)("div", { style: styles.shell }, [
|
|
1387
|
+
(0, import_vue14.h)(
|
|
1182
1388
|
"nav",
|
|
1183
1389
|
{ style: styles.nav, "aria-label": "Admin" },
|
|
1184
1390
|
NAV.map((g) => {
|
|
@@ -1186,10 +1392,10 @@ var AdminShell = (0, import_vue13.defineComponent)({
|
|
|
1186
1392
|
(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)
|
|
1187
1393
|
);
|
|
1188
1394
|
if (items.length === 0) return null;
|
|
1189
|
-
return (0,
|
|
1190
|
-
(0,
|
|
1395
|
+
return (0, import_vue14.h)("div", { key: g.group }, [
|
|
1396
|
+
(0, import_vue14.h)("div", { style: styles.navGroup }, g.group),
|
|
1191
1397
|
...items.map(
|
|
1192
|
-
(i) => (0,
|
|
1398
|
+
(i) => (0, import_vue14.h)(
|
|
1193
1399
|
"button",
|
|
1194
1400
|
{
|
|
1195
1401
|
key: i.page,
|
|
@@ -1207,7 +1413,7 @@ var AdminShell = (0, import_vue13.defineComponent)({
|
|
|
1207
1413
|
]);
|
|
1208
1414
|
})
|
|
1209
1415
|
),
|
|
1210
|
-
(0,
|
|
1416
|
+
(0, import_vue14.h)("main", { style: styles.main }, body())
|
|
1211
1417
|
]);
|
|
1212
1418
|
}
|
|
1213
1419
|
});
|
|
@@ -1220,6 +1426,7 @@ var AdminShell = (0, import_vue13.defineComponent)({
|
|
|
1220
1426
|
CatalogScreen,
|
|
1221
1427
|
ConfigScreen,
|
|
1222
1428
|
DoctorScreen,
|
|
1429
|
+
MigrationsScreen,
|
|
1223
1430
|
ModulesScreen,
|
|
1224
1431
|
RoutesScreen,
|
|
1225
1432
|
SubscriberScreen,
|