@tangle-network/sandbox-ui 0.22.0 → 0.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth.js +1 -3
- package/dist/{chunk-ZNYEJERQ.js → chunk-7X2DHDQ6.js} +673 -588
- package/dist/{chunk-UHFJXO24.js → chunk-7ZA5SEK3.js} +177 -1
- package/dist/{chunk-R3ZMMCT3.js → chunk-IOB2PW5Z.js} +13 -5
- package/dist/dashboard.d.ts +65 -2
- package/dist/dashboard.js +6 -3
- package/dist/globals.css +0 -92
- package/dist/index.d.ts +1 -1
- package/dist/index.js +9 -7
- package/dist/pages.js +1 -2
- package/dist/primitives.js +3 -5
- package/dist/styles.css +0 -92
- package/package.json +17 -17
- package/dist/assets.d.ts +0 -81
- package/dist/assets.js +0 -935
- package/dist/chunk-SM7IJY4I.js +0 -178
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Button
|
|
3
|
-
} from "./chunk-SM7IJY4I.js";
|
|
4
|
-
import {
|
|
2
|
+
Button,
|
|
5
3
|
Logo
|
|
6
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7ZA5SEK3.js";
|
|
7
5
|
import {
|
|
8
6
|
cn
|
|
9
7
|
} from "./chunk-EI44GEQ5.js";
|
|
@@ -498,9 +496,10 @@ function getBarColor(percent) {
|
|
|
498
496
|
if (percent >= 70) return "bg-[var(--surface-warning-text)]";
|
|
499
497
|
return "bg-primary";
|
|
500
498
|
}
|
|
501
|
-
function ResourceMeter({ label, value, max = 100, unit, icon, className }) {
|
|
502
|
-
const percent = max > 0 ? Math.min(value / max * 100, 100) : 0;
|
|
499
|
+
function ResourceMeter({ label, value, max = 100, unit, valueLabel, icon, className }) {
|
|
500
|
+
const percent = max > 0 ? Math.max(0, Math.min(value / max * 100, 100)) : 0;
|
|
503
501
|
const barColor = getBarColor(percent);
|
|
502
|
+
const readout = valueLabel ?? (unit ? `${value}${unit}/${max}${unit}` : `${Math.round(percent)}%`);
|
|
504
503
|
return /* @__PURE__ */ jsxs5("div", { className: cn("flex items-center gap-3", className), children: [
|
|
505
504
|
/* @__PURE__ */ jsxs5("span", { className: "flex shrink-0 items-center gap-1 text-[10px] font-mono text-muted-foreground uppercase tracking-wide", children: [
|
|
506
505
|
icon,
|
|
@@ -513,10 +512,94 @@ function ResourceMeter({ label, value, max = 100, unit, icon, className }) {
|
|
|
513
512
|
style: { width: `${percent}%` }
|
|
514
513
|
}
|
|
515
514
|
) }),
|
|
516
|
-
/* @__PURE__ */ jsx6("span", { className: "shrink-0 text-[10px] font-mono tabular-nums text-muted-foreground", children:
|
|
515
|
+
/* @__PURE__ */ jsx6("span", { className: "shrink-0 text-[10px] font-mono tabular-nums text-muted-foreground", children: readout })
|
|
517
516
|
] });
|
|
518
517
|
}
|
|
519
518
|
|
|
519
|
+
// src/dashboard/resource-snapshot.tsx
|
|
520
|
+
import { Skeleton as Skeleton2 } from "@tangle-network/ui/primitives";
|
|
521
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
522
|
+
function ResourceSnapshot({
|
|
523
|
+
title = "Resources",
|
|
524
|
+
action,
|
|
525
|
+
items,
|
|
526
|
+
loading = false,
|
|
527
|
+
error = null,
|
|
528
|
+
className
|
|
529
|
+
}) {
|
|
530
|
+
const rowCount = items.length > 0 ? items.length : 3;
|
|
531
|
+
return /* @__PURE__ */ jsxs6(
|
|
532
|
+
"div",
|
|
533
|
+
{
|
|
534
|
+
className: cn(
|
|
535
|
+
"flex flex-col rounded-lg border border-border bg-card p-6",
|
|
536
|
+
className
|
|
537
|
+
),
|
|
538
|
+
children: [
|
|
539
|
+
/* @__PURE__ */ jsxs6("div", { className: "mb-4 flex items-center justify-between gap-2", children: [
|
|
540
|
+
/* @__PURE__ */ jsx7("h3", { className: "font-display font-semibold text-foreground text-sm", children: title }),
|
|
541
|
+
action
|
|
542
|
+
] }),
|
|
543
|
+
error ? /* @__PURE__ */ jsx7("p", { className: "text-[var(--surface-danger-text)] text-xs", children: error }) : loading ? /* @__PURE__ */ jsx7("div", { className: "space-y-3", children: Array.from({ length: rowCount }).map((_, i) => /* @__PURE__ */ jsx7(Skeleton2, { className: "h-4 w-full" }, i)) }) : /* @__PURE__ */ jsx7("div", { className: "space-y-3", children: items.map((item, idx) => /* @__PURE__ */ jsx7(
|
|
544
|
+
ResourceMeter,
|
|
545
|
+
{
|
|
546
|
+
label: item.label,
|
|
547
|
+
value: item.value,
|
|
548
|
+
max: item.max,
|
|
549
|
+
unit: item.unit,
|
|
550
|
+
valueLabel: item.valueLabel,
|
|
551
|
+
icon: item.icon
|
|
552
|
+
},
|
|
553
|
+
item.id ?? `${item.label}-${idx}`
|
|
554
|
+
)) })
|
|
555
|
+
]
|
|
556
|
+
}
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// src/dashboard/activity-feed.tsx
|
|
561
|
+
import * as React3 from "react";
|
|
562
|
+
import { Skeleton as Skeleton3 } from "@tangle-network/ui/primitives";
|
|
563
|
+
import { timeAgo } from "@tangle-network/ui/utils";
|
|
564
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
565
|
+
function ActivityFeed({
|
|
566
|
+
title = "Recent activity",
|
|
567
|
+
action,
|
|
568
|
+
items,
|
|
569
|
+
loading = false,
|
|
570
|
+
maxItems = 6,
|
|
571
|
+
emptyLabel = "No recent activity",
|
|
572
|
+
className
|
|
573
|
+
}) {
|
|
574
|
+
const sorted = React3.useMemo(
|
|
575
|
+
() => [...items].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0)).slice(0, maxItems),
|
|
576
|
+
[items, maxItems]
|
|
577
|
+
);
|
|
578
|
+
return /* @__PURE__ */ jsxs7(
|
|
579
|
+
"div",
|
|
580
|
+
{
|
|
581
|
+
className: cn(
|
|
582
|
+
"flex flex-col rounded-lg border border-border bg-card p-6",
|
|
583
|
+
className
|
|
584
|
+
),
|
|
585
|
+
children: [
|
|
586
|
+
/* @__PURE__ */ jsxs7("div", { className: "mb-4 flex items-center justify-between gap-2", children: [
|
|
587
|
+
/* @__PURE__ */ jsx8("h3", { className: "font-display font-semibold text-foreground text-sm", children: title }),
|
|
588
|
+
action
|
|
589
|
+
] }),
|
|
590
|
+
loading ? /* @__PURE__ */ jsx8("div", { className: "space-y-3", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx8(Skeleton3, { className: "h-9 w-full" }, i)) }) : sorted.length === 0 ? /* @__PURE__ */ jsx8("p", { className: "text-muted-foreground text-sm", children: emptyLabel }) : /* @__PURE__ */ jsx8("ul", { className: "space-y-3", children: sorted.map((item) => /* @__PURE__ */ jsxs7("li", { className: "flex items-start gap-3", children: [
|
|
591
|
+
item.icon && /* @__PURE__ */ jsx8("span", { className: "mt-0.5 shrink-0 text-muted-foreground", children: item.icon }),
|
|
592
|
+
/* @__PURE__ */ jsxs7("div", { className: "min-w-0 flex-1", children: [
|
|
593
|
+
/* @__PURE__ */ jsx8("p", { className: "truncate font-medium text-foreground text-sm", children: item.title }),
|
|
594
|
+
item.detail && /* @__PURE__ */ jsx8("p", { className: "truncate text-muted-foreground text-xs", children: item.detail })
|
|
595
|
+
] }),
|
|
596
|
+
item.timestamp != null && /* @__PURE__ */ jsx8("span", { className: "shrink-0 text-muted-foreground text-xs tabular-nums", children: timeAgo(item.timestamp) })
|
|
597
|
+
] }, item.id)) })
|
|
598
|
+
]
|
|
599
|
+
}
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
|
|
520
603
|
// src/dashboard/sandbox-card.tsx
|
|
521
604
|
import {
|
|
522
605
|
DropdownMenu as DropdownMenu2,
|
|
@@ -541,7 +624,7 @@ import {
|
|
|
541
624
|
Plus,
|
|
542
625
|
Users
|
|
543
626
|
} from "lucide-react";
|
|
544
|
-
import { Fragment as Fragment3, jsx as
|
|
627
|
+
import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
545
628
|
function canAdminSandbox(sandbox) {
|
|
546
629
|
if (!sandbox.team) return true;
|
|
547
630
|
return sandbox.team.role === "owner" || sandbox.team.role === "admin";
|
|
@@ -564,115 +647,115 @@ function SandboxCard({
|
|
|
564
647
|
const isRunning = sandbox.status === "running";
|
|
565
648
|
const isTransitioning = sandbox.status === "provisioning" || sandbox.status === "creating";
|
|
566
649
|
const isStopped = !isRunning && !isTransitioning;
|
|
567
|
-
return /* @__PURE__ */
|
|
650
|
+
return /* @__PURE__ */ jsxs8("div", { className: cn(
|
|
568
651
|
"group relative flex flex-col justify-between overflow-hidden rounded-lg border bg-card p-5 transition-colors",
|
|
569
652
|
isRunning ? "border-[var(--status-running)]/30" : "border-border",
|
|
570
653
|
"hover:border-foreground/15",
|
|
571
654
|
className
|
|
572
655
|
), children: [
|
|
573
|
-
/* @__PURE__ */
|
|
574
|
-
/* @__PURE__ */
|
|
575
|
-
/* @__PURE__ */
|
|
576
|
-
/* @__PURE__ */
|
|
656
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-start justify-between", children: [
|
|
657
|
+
/* @__PURE__ */ jsxs8("div", { children: [
|
|
658
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
|
|
659
|
+
/* @__PURE__ */ jsxs8("h3", { className: "flex items-center gap-2 text-sm font-bold text-foreground", children: [
|
|
577
660
|
sandbox.name,
|
|
578
|
-
isRunning && /* @__PURE__ */
|
|
579
|
-
/* @__PURE__ */
|
|
580
|
-
/* @__PURE__ */
|
|
661
|
+
isRunning && /* @__PURE__ */ jsxs8("span", { className: "relative flex h-2 w-2", children: [
|
|
662
|
+
/* @__PURE__ */ jsx9("span", { className: "absolute inline-flex h-full w-full animate-pulse rounded-full bg-[var(--status-running)] opacity-75" }),
|
|
663
|
+
/* @__PURE__ */ jsx9("span", { className: "relative inline-flex h-1.5 w-1.5 rounded-full bg-[var(--status-running)]" })
|
|
581
664
|
] })
|
|
582
665
|
] }),
|
|
583
|
-
sandbox.team && /* @__PURE__ */
|
|
666
|
+
sandbox.team && /* @__PURE__ */ jsxs8(
|
|
584
667
|
"span",
|
|
585
668
|
{
|
|
586
669
|
className: "inline-flex items-center gap-1 rounded-full bg-[var(--accent-surface-soft)] px-2 py-0.5 text-[10px] font-semibold text-[var(--accent-text)]",
|
|
587
670
|
title: `Shared with ${sandbox.team.name ?? "Team"} \xB7 ${sandbox.team.role}`,
|
|
588
671
|
children: [
|
|
589
|
-
/* @__PURE__ */
|
|
672
|
+
/* @__PURE__ */ jsx9(Users, { className: "h-3 w-3", "aria-hidden": "true" }),
|
|
590
673
|
sandbox.team.name ?? "Team"
|
|
591
674
|
]
|
|
592
675
|
}
|
|
593
676
|
)
|
|
594
677
|
] }),
|
|
595
|
-
/* @__PURE__ */
|
|
678
|
+
/* @__PURE__ */ jsxs8("p", { className: "mt-0.5 font-mono text-[10px] tracking-wider text-muted-foreground uppercase", children: [
|
|
596
679
|
sandbox.nodeId || "Unknown Node",
|
|
597
|
-
sandbox.team && /* @__PURE__ */
|
|
680
|
+
sandbox.team && /* @__PURE__ */ jsxs8("span", { className: "ml-2 normal-case tracking-normal", children: [
|
|
598
681
|
"\xB7 your role: ",
|
|
599
682
|
sandbox.team.role
|
|
600
683
|
] })
|
|
601
684
|
] })
|
|
602
685
|
] }),
|
|
603
|
-
/* @__PURE__ */
|
|
604
|
-
/* @__PURE__ */
|
|
686
|
+
/* @__PURE__ */ jsxs8(DropdownMenu2, { children: [
|
|
687
|
+
/* @__PURE__ */ jsx9(DropdownMenuTrigger2, { asChild: true, children: /* @__PURE__ */ jsx9(
|
|
605
688
|
"button",
|
|
606
689
|
{
|
|
607
690
|
type: "button",
|
|
608
691
|
className: "rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground outline-none",
|
|
609
692
|
"aria-label": "Sandbox options",
|
|
610
|
-
children: /* @__PURE__ */
|
|
693
|
+
children: /* @__PURE__ */ jsx9(MoreVertical, { className: "h-4 w-4" })
|
|
611
694
|
}
|
|
612
695
|
) }),
|
|
613
|
-
/* @__PURE__ */
|
|
614
|
-
isRunning && /* @__PURE__ */
|
|
615
|
-
onStop && /* @__PURE__ */
|
|
616
|
-
/* @__PURE__ */
|
|
696
|
+
/* @__PURE__ */ jsxs8(DropdownMenuContent2, { align: "end", className: "min-w-[180px]", children: [
|
|
697
|
+
isRunning && /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
698
|
+
onStop && /* @__PURE__ */ jsxs8(DropdownMenuItem2, { onClick: () => onStop(sandbox.id), children: [
|
|
699
|
+
/* @__PURE__ */ jsx9(PowerOff, { className: "mr-2 h-4 w-4" }),
|
|
617
700
|
" Stop Sandbox"
|
|
618
701
|
] }),
|
|
619
|
-
onKeepAlive && /* @__PURE__ */
|
|
620
|
-
/* @__PURE__ */
|
|
702
|
+
onKeepAlive && /* @__PURE__ */ jsxs8(DropdownMenuItem2, { onClick: () => onKeepAlive(sandbox.id), children: [
|
|
703
|
+
/* @__PURE__ */ jsx9(Clock, { className: "mr-2 h-4 w-4" }),
|
|
621
704
|
" Keep Alive"
|
|
622
705
|
] }),
|
|
623
|
-
(onStop || onKeepAlive) && /* @__PURE__ */
|
|
624
|
-
onUsage && /* @__PURE__ */
|
|
625
|
-
/* @__PURE__ */
|
|
706
|
+
(onStop || onKeepAlive) && /* @__PURE__ */ jsx9(DropdownMenuSeparator2, {}),
|
|
707
|
+
onUsage && /* @__PURE__ */ jsxs8(DropdownMenuItem2, { onClick: () => onUsage(sandbox.id), children: [
|
|
708
|
+
/* @__PURE__ */ jsx9(BarChart2, { className: "mr-2 h-4 w-4" }),
|
|
626
709
|
" View Usage"
|
|
627
710
|
] }),
|
|
628
|
-
onHealth && /* @__PURE__ */
|
|
629
|
-
/* @__PURE__ */
|
|
711
|
+
onHealth && /* @__PURE__ */ jsxs8(DropdownMenuItem2, { onClick: () => onHealth(sandbox.id), children: [
|
|
712
|
+
/* @__PURE__ */ jsx9(Activity, { className: "mr-2 h-4 w-4" }),
|
|
630
713
|
" Health Check"
|
|
631
714
|
] }),
|
|
632
|
-
(onUsage || onHealth) && /* @__PURE__ */
|
|
633
|
-
onFork && /* @__PURE__ */
|
|
634
|
-
/* @__PURE__ */
|
|
635
|
-
/* @__PURE__ */
|
|
715
|
+
(onUsage || onHealth) && /* @__PURE__ */ jsx9(DropdownMenuSeparator2, {}),
|
|
716
|
+
onFork && /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
717
|
+
/* @__PURE__ */ jsxs8(DropdownMenuItem2, { onClick: () => onFork(sandbox.id), children: [
|
|
718
|
+
/* @__PURE__ */ jsx9(Copy, { className: "mr-2 h-4 w-4" }),
|
|
636
719
|
" Fork Sandbox"
|
|
637
720
|
] }),
|
|
638
|
-
/* @__PURE__ */
|
|
721
|
+
/* @__PURE__ */ jsx9(DropdownMenuSeparator2, {})
|
|
639
722
|
] })
|
|
640
723
|
] }),
|
|
641
|
-
isStopped && /* @__PURE__ */
|
|
642
|
-
onResume && /* @__PURE__ */
|
|
643
|
-
/* @__PURE__ */
|
|
724
|
+
isStopped && /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
725
|
+
onResume && /* @__PURE__ */ jsxs8(DropdownMenuItem2, { onClick: () => onResume(sandbox.id), children: [
|
|
726
|
+
/* @__PURE__ */ jsx9(Power, { className: "mr-2 h-4 w-4" }),
|
|
644
727
|
" Resume Sandbox"
|
|
645
728
|
] }),
|
|
646
|
-
onFork && /* @__PURE__ */
|
|
647
|
-
/* @__PURE__ */
|
|
729
|
+
onFork && /* @__PURE__ */ jsxs8(DropdownMenuItem2, { onClick: () => onFork(sandbox.id), children: [
|
|
730
|
+
/* @__PURE__ */ jsx9(Copy, { className: "mr-2 h-4 w-4" }),
|
|
648
731
|
" Fork Sandbox"
|
|
649
732
|
] }),
|
|
650
|
-
(onResume || onFork) && /* @__PURE__ */
|
|
733
|
+
(onResume || onFork) && /* @__PURE__ */ jsx9(DropdownMenuSeparator2, {})
|
|
651
734
|
] }),
|
|
652
|
-
onDelete && canAdminSandbox(sandbox) && /* @__PURE__ */
|
|
653
|
-
/* @__PURE__ */
|
|
735
|
+
onDelete && canAdminSandbox(sandbox) && /* @__PURE__ */ jsxs8(DropdownMenuItem2, { className: "text-destructive focus:bg-destructive/10 focus:text-destructive", onClick: () => onDelete(sandbox.id), children: [
|
|
736
|
+
/* @__PURE__ */ jsx9(Trash2, { className: "mr-2 h-4 w-4" }),
|
|
654
737
|
" Delete Sandbox"
|
|
655
738
|
] })
|
|
656
739
|
] })
|
|
657
740
|
] })
|
|
658
741
|
] }),
|
|
659
|
-
/* @__PURE__ */
|
|
660
|
-
/* @__PURE__ */
|
|
661
|
-
/* @__PURE__ */
|
|
662
|
-
/* @__PURE__ */
|
|
663
|
-
/* @__PURE__ */
|
|
664
|
-
/* @__PURE__ */
|
|
742
|
+
/* @__PURE__ */ jsxs8("div", { className: "my-4", children: [
|
|
743
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3 rounded-md border border-border bg-muted/30 p-3", children: [
|
|
744
|
+
/* @__PURE__ */ jsx9("div", { className: cn("flex h-10 w-10 items-center justify-center rounded-md", isRunning ? "bg-[var(--surface-success-bg)]" : "bg-muted"), children: sandbox.imageIcon ? sandbox.imageIcon : sandbox.image?.includes("node") ? /* @__PURE__ */ jsx9(Code2, { className: cn("h-5 w-5", isRunning ? "text-[var(--surface-success-text)]" : "text-muted-foreground") }) : /* @__PURE__ */ jsx9(Terminal, { className: cn("h-5 w-5", isRunning ? "text-[var(--surface-success-text)]" : "text-muted-foreground") }) }),
|
|
745
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex flex-col", children: [
|
|
746
|
+
/* @__PURE__ */ jsx9("span", { className: "text-[10px] text-muted-foreground uppercase tracking-widest font-bold", children: "Environment" }),
|
|
747
|
+
/* @__PURE__ */ jsx9("span", { className: "text-xs font-medium text-foreground font-mono mt-0.5", children: sandbox.image || "Universal" })
|
|
665
748
|
] })
|
|
666
749
|
] }),
|
|
667
|
-
isTransitioning && /* @__PURE__ */
|
|
668
|
-
/* @__PURE__ */
|
|
669
|
-
/* @__PURE__ */
|
|
670
|
-
/* @__PURE__ */
|
|
750
|
+
isTransitioning && /* @__PURE__ */ jsxs8("div", { className: "mt-3", children: [
|
|
751
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex justify-between text-xs text-muted-foreground font-medium mb-1", children: [
|
|
752
|
+
/* @__PURE__ */ jsx9("span", { children: sandbox.provisioningMessage || "Starting..." }),
|
|
753
|
+
/* @__PURE__ */ jsxs8("span", { children: [
|
|
671
754
|
sandbox.provisioningPercent || 0,
|
|
672
755
|
"%"
|
|
673
756
|
] })
|
|
674
757
|
] }),
|
|
675
|
-
/* @__PURE__ */
|
|
758
|
+
/* @__PURE__ */ jsx9("div", { className: "h-1 w-full overflow-hidden rounded-full bg-muted", children: /* @__PURE__ */ jsx9(
|
|
676
759
|
"div",
|
|
677
760
|
{
|
|
678
761
|
className: "h-full bg-primary transition-all duration-500 rounded-full",
|
|
@@ -681,18 +764,18 @@ function SandboxCard({
|
|
|
681
764
|
) })
|
|
682
765
|
] })
|
|
683
766
|
] }),
|
|
684
|
-
/* @__PURE__ */
|
|
767
|
+
/* @__PURE__ */ jsx9("div", { className: "border-t border-border pt-3", children: isRunning ? /* @__PURE__ */ jsxs8(
|
|
685
768
|
"button",
|
|
686
769
|
{
|
|
687
770
|
type: "button",
|
|
688
771
|
onClick: () => onOpenIDE?.(sandbox.id),
|
|
689
772
|
className: "flex w-full items-center justify-center gap-2 rounded-md bg-[var(--btn-primary-bg)] px-4 py-2 text-sm font-semibold text-[var(--btn-primary-text)] transition-colors hover:bg-[var(--btn-primary-hover)] active:scale-[0.97]",
|
|
690
773
|
children: [
|
|
691
|
-
/* @__PURE__ */
|
|
774
|
+
/* @__PURE__ */ jsx9(Network, { className: "h-4 w-4" }),
|
|
692
775
|
"Connect Session"
|
|
693
776
|
]
|
|
694
777
|
}
|
|
695
|
-
) : /* @__PURE__ */
|
|
778
|
+
) : /* @__PURE__ */ jsxs8(
|
|
696
779
|
"button",
|
|
697
780
|
{
|
|
698
781
|
type: "button",
|
|
@@ -703,7 +786,7 @@ function SandboxCard({
|
|
|
703
786
|
isTransitioning ? "bg-muted text-muted-foreground cursor-not-allowed border-border" : "bg-card text-foreground hover:bg-muted border-border active:scale-[0.97]"
|
|
704
787
|
),
|
|
705
788
|
children: [
|
|
706
|
-
/* @__PURE__ */
|
|
789
|
+
/* @__PURE__ */ jsx9(Play, { className: "h-4 w-4" }),
|
|
707
790
|
isTransitioning ? "Starting..." : "Wake Sandbox"
|
|
708
791
|
]
|
|
709
792
|
}
|
|
@@ -711,7 +794,7 @@ function SandboxCard({
|
|
|
711
794
|
] });
|
|
712
795
|
}
|
|
713
796
|
function NewSandboxCard({ onClick, className }) {
|
|
714
|
-
return /* @__PURE__ */
|
|
797
|
+
return /* @__PURE__ */ jsxs8(
|
|
715
798
|
"button",
|
|
716
799
|
{
|
|
717
800
|
type: "button",
|
|
@@ -721,16 +804,16 @@ function NewSandboxCard({ onClick, className }) {
|
|
|
721
804
|
className
|
|
722
805
|
),
|
|
723
806
|
children: [
|
|
724
|
-
/* @__PURE__ */
|
|
725
|
-
/* @__PURE__ */
|
|
726
|
-
/* @__PURE__ */
|
|
807
|
+
/* @__PURE__ */ jsx9("div", { className: "flex h-12 w-12 items-center justify-center rounded-lg bg-muted text-muted-foreground", children: /* @__PURE__ */ jsx9(Plus, { className: "h-6 w-6" }) }),
|
|
808
|
+
/* @__PURE__ */ jsx9("span", { className: "mt-4 text-sm font-semibold text-foreground", children: "New Sandbox" }),
|
|
809
|
+
/* @__PURE__ */ jsx9("span", { className: "mt-1 text-xs text-muted-foreground", children: "Deploy a new isolated environment" })
|
|
727
810
|
]
|
|
728
811
|
}
|
|
729
812
|
);
|
|
730
813
|
}
|
|
731
814
|
|
|
732
815
|
// src/dashboard/sandbox-table.tsx
|
|
733
|
-
import * as
|
|
816
|
+
import * as React4 from "react";
|
|
734
817
|
import {
|
|
735
818
|
Activity as Activity2,
|
|
736
819
|
BarChart2 as BarChart22,
|
|
@@ -757,7 +840,7 @@ import {
|
|
|
757
840
|
DropdownMenuSeparator as DropdownMenuSeparator3,
|
|
758
841
|
DropdownMenuTrigger as DropdownMenuTrigger3
|
|
759
842
|
} from "@tangle-network/ui/primitives";
|
|
760
|
-
import { Fragment as Fragment5, jsx as
|
|
843
|
+
import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
761
844
|
var statusColors = {
|
|
762
845
|
running: { dot: "bg-[var(--code-success)] animate-pulse", text: "text-[var(--code-success)]", bar: "bg-[var(--code-success)]" },
|
|
763
846
|
hibernating: { dot: "bg-muted-foreground", text: "text-muted-foreground", bar: "bg-muted-foreground" },
|
|
@@ -771,15 +854,15 @@ function isResumable(status) {
|
|
|
771
854
|
return status !== "running" && status !== "provisioning" && status !== "creating";
|
|
772
855
|
}
|
|
773
856
|
function MiniMeter({ label, percent, className }) {
|
|
774
|
-
return /* @__PURE__ */
|
|
775
|
-
/* @__PURE__ */
|
|
776
|
-
/* @__PURE__ */
|
|
777
|
-
/* @__PURE__ */
|
|
857
|
+
return /* @__PURE__ */ jsxs9("div", { className: cn("space-y-1", className), children: [
|
|
858
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex justify-between text-[10px] font-mono text-muted-foreground", children: [
|
|
859
|
+
/* @__PURE__ */ jsx10("span", { className: "font-bold", children: label }),
|
|
860
|
+
/* @__PURE__ */ jsxs9("span", { className: "text-primary", children: [
|
|
778
861
|
percent,
|
|
779
862
|
"%"
|
|
780
863
|
] })
|
|
781
864
|
] }),
|
|
782
|
-
/* @__PURE__ */
|
|
865
|
+
/* @__PURE__ */ jsx10("div", { className: "h-1.5 w-full bg-background rounded-full overflow-hidden", children: /* @__PURE__ */ jsx10("div", { className: "h-full bg-primary rounded-full", style: { width: `${percent}%` } }) })
|
|
783
866
|
] });
|
|
784
867
|
}
|
|
785
868
|
function SandboxTable({
|
|
@@ -818,17 +901,17 @@ function SandboxTable({
|
|
|
818
901
|
const handler = resolveResumeHandler(sb.status);
|
|
819
902
|
return handler ? () => handler(sb.id) : void 0;
|
|
820
903
|
};
|
|
821
|
-
return /* @__PURE__ */
|
|
822
|
-
/* @__PURE__ */
|
|
823
|
-
/* @__PURE__ */
|
|
824
|
-
/* @__PURE__ */
|
|
825
|
-
/* @__PURE__ */
|
|
826
|
-
hasTeamSandboxes && /* @__PURE__ */
|
|
827
|
-
/* @__PURE__ */
|
|
828
|
-
/* @__PURE__ */
|
|
829
|
-
/* @__PURE__ */
|
|
904
|
+
return /* @__PURE__ */ jsxs9("div", { className: cn("w-full", className), children: [
|
|
905
|
+
/* @__PURE__ */ jsx10("div", { className: "w-full bg-card rounded-2xl overflow-hidden border border-border", children: /* @__PURE__ */ jsx10("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs9("table", { className: "w-full text-left border-collapse", children: [
|
|
906
|
+
/* @__PURE__ */ jsx10("thead", { children: /* @__PURE__ */ jsxs9("tr", { className: "bg-background border-b border-border", children: [
|
|
907
|
+
/* @__PURE__ */ jsx10("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Status" }),
|
|
908
|
+
/* @__PURE__ */ jsx10("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Sandbox Name" }),
|
|
909
|
+
hasTeamSandboxes && /* @__PURE__ */ jsx10("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Scope" }),
|
|
910
|
+
/* @__PURE__ */ jsx10("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Environment" }),
|
|
911
|
+
/* @__PURE__ */ jsx10("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Resources" }),
|
|
912
|
+
/* @__PURE__ */ jsx10("th", { className: "px-6 py-4 text-xs font-semibold text-muted-foreground uppercase tracking-wider text-right", children: "Actions" })
|
|
830
913
|
] }) }),
|
|
831
|
-
/* @__PURE__ */
|
|
914
|
+
/* @__PURE__ */ jsx10("tbody", { className: "divide-y divide-border", children: sandboxes.map((sb) => {
|
|
832
915
|
const sc = statusColors[sb.status] ?? statusColors.stopped;
|
|
833
916
|
const isActive = sb.status === "running";
|
|
834
917
|
const isHibernating = sb.status === "hibernating";
|
|
@@ -850,7 +933,7 @@ function SandboxTable({
|
|
|
850
933
|
// IDE, Delete, …), which keep their native
|
|
851
934
|
// semantics. Mouse users get the click-anywhere
|
|
852
935
|
// affordance; nobody loses access.
|
|
853
|
-
/* @__PURE__ */
|
|
936
|
+
/* @__PURE__ */ jsxs9(
|
|
854
937
|
"tr",
|
|
855
938
|
{
|
|
856
939
|
className: cn(
|
|
@@ -859,69 +942,69 @@ function SandboxTable({
|
|
|
859
942
|
),
|
|
860
943
|
onClick: onRowClick,
|
|
861
944
|
children: [
|
|
862
|
-
/* @__PURE__ */
|
|
863
|
-
/* @__PURE__ */
|
|
864
|
-
/* @__PURE__ */
|
|
945
|
+
/* @__PURE__ */ jsx10("td", { className: "px-6 py-5 whitespace-nowrap", children: /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
|
|
946
|
+
/* @__PURE__ */ jsx10("span", { className: cn("flex h-2.5 w-2.5 rounded-full", sc.dot) }),
|
|
947
|
+
/* @__PURE__ */ jsx10("span", { className: cn("text-xs font-bold uppercase tracking-wide", sc.text), children: sb.status.charAt(0).toUpperCase() + sb.status.slice(1) })
|
|
865
948
|
] }) }),
|
|
866
|
-
/* @__PURE__ */
|
|
867
|
-
/* @__PURE__ */
|
|
868
|
-
sb.nodeId && /* @__PURE__ */
|
|
949
|
+
/* @__PURE__ */ jsx10("td", { className: "px-6 py-5", children: /* @__PURE__ */ jsxs9("div", { className: "flex flex-col", children: [
|
|
950
|
+
/* @__PURE__ */ jsx10("span", { className: "text-sm font-bold text-foreground group-hover:text-primary transition-colors", children: sb.name }),
|
|
951
|
+
sb.nodeId && /* @__PURE__ */ jsx10("span", { className: "text-[10px] font-mono text-muted-foreground", children: sb.nodeId })
|
|
869
952
|
] }) }),
|
|
870
|
-
hasTeamSandboxes && /* @__PURE__ */
|
|
953
|
+
hasTeamSandboxes && /* @__PURE__ */ jsx10("td", { className: "px-6 py-5", children: sb.team ? /* @__PURE__ */ jsxs9(
|
|
871
954
|
"div",
|
|
872
955
|
{
|
|
873
956
|
className: "inline-flex items-center gap-1.5 rounded-full bg-[var(--accent-surface-soft)] px-2.5 py-1 text-[11px] font-semibold text-[var(--accent-text)]",
|
|
874
957
|
title: `Shared with ${sb.team.name ?? "Team"} \xB7 ${sb.team.role}`,
|
|
875
958
|
children: [
|
|
876
|
-
/* @__PURE__ */
|
|
877
|
-
/* @__PURE__ */
|
|
878
|
-
/* @__PURE__ */
|
|
959
|
+
/* @__PURE__ */ jsx10(Users2, { className: "h-3 w-3", "aria-hidden": "true" }),
|
|
960
|
+
/* @__PURE__ */ jsx10("span", { children: sb.team.name ?? "Team" }),
|
|
961
|
+
/* @__PURE__ */ jsxs9("span", { className: "font-normal text-muted-foreground", children: [
|
|
879
962
|
"\xB7 ",
|
|
880
963
|
sb.team.role
|
|
881
964
|
] })
|
|
882
965
|
]
|
|
883
966
|
}
|
|
884
|
-
) : /* @__PURE__ */
|
|
967
|
+
) : /* @__PURE__ */ jsxs9(
|
|
885
968
|
"div",
|
|
886
969
|
{
|
|
887
970
|
className: "inline-flex items-center gap-1.5 rounded-full bg-muted px-2.5 py-1 text-[11px] font-medium text-muted-foreground",
|
|
888
971
|
title: "Personal sandbox",
|
|
889
972
|
children: [
|
|
890
|
-
/* @__PURE__ */
|
|
973
|
+
/* @__PURE__ */ jsx10(User, { className: "h-3 w-3", "aria-hidden": "true" }),
|
|
891
974
|
"Personal"
|
|
892
975
|
]
|
|
893
976
|
}
|
|
894
977
|
) }),
|
|
895
|
-
/* @__PURE__ */
|
|
896
|
-
sb.imageIcon && /* @__PURE__ */
|
|
897
|
-
sb.image && /* @__PURE__ */
|
|
978
|
+
/* @__PURE__ */ jsx10("td", { className: "px-6 py-5", children: /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3", children: [
|
|
979
|
+
sb.imageIcon && /* @__PURE__ */ jsx10("div", { className: "w-8 h-8 rounded-lg bg-muted/50 flex items-center justify-center", children: sb.imageIcon }),
|
|
980
|
+
sb.image && /* @__PURE__ */ jsx10("span", { className: "text-xs font-bold text-foreground", children: sb.image })
|
|
898
981
|
] }) }),
|
|
899
|
-
/* @__PURE__ */
|
|
900
|
-
/* @__PURE__ */
|
|
901
|
-
/* @__PURE__ */
|
|
902
|
-
] }) : isProvisioning ? /* @__PURE__ */
|
|
903
|
-
/* @__PURE__ */
|
|
982
|
+
/* @__PURE__ */ jsx10("td", { className: "px-6 py-5", children: isActive ? /* @__PURE__ */ jsxs9("div", { className: "space-y-3 w-48", children: [
|
|
983
|
+
/* @__PURE__ */ jsx10(MiniMeter, { label: "CPU", percent: sb.cpuPercent ?? 0 }),
|
|
984
|
+
/* @__PURE__ */ jsx10(MiniMeter, { label: "RAM", percent: sb.ramTotal ? Math.round((sb.ramUsed ?? 0) / sb.ramTotal * 100) : 0 })
|
|
985
|
+
] }) : isProvisioning ? /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 text-primary italic text-[10px] font-bold", children: [
|
|
986
|
+
/* @__PURE__ */ jsx10(RefreshCw, { className: "h-3.5 w-3.5 animate-spin" }),
|
|
904
987
|
sb.provisioningMessage ?? "Allocating nodes..."
|
|
905
|
-
] }) : isHibernating ? /* @__PURE__ */
|
|
906
|
-
/* @__PURE__ */
|
|
907
|
-
/* @__PURE__ */
|
|
988
|
+
] }) : isHibernating ? /* @__PURE__ */ jsxs9("div", { className: "space-y-3 w-48 opacity-30", children: [
|
|
989
|
+
/* @__PURE__ */ jsx10(MiniMeter, { label: "CPU", percent: 0 }),
|
|
990
|
+
/* @__PURE__ */ jsx10(MiniMeter, { label: "RAM", percent: 0 })
|
|
908
991
|
] }) : null }),
|
|
909
|
-
/* @__PURE__ */
|
|
910
|
-
isActive && /* @__PURE__ */
|
|
911
|
-
/* @__PURE__ */
|
|
992
|
+
/* @__PURE__ */ jsx10("td", { className: "px-6 py-5 text-right", children: /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-end gap-1", children: [
|
|
993
|
+
isActive && /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
994
|
+
/* @__PURE__ */ jsx10("button", { type: "button", onClick: (e) => {
|
|
912
995
|
stopRowClick(e);
|
|
913
996
|
onOpenIDE?.(sb.id);
|
|
914
|
-
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "Open IDE", children: /* @__PURE__ */
|
|
915
|
-
/* @__PURE__ */
|
|
997
|
+
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "Open IDE", children: /* @__PURE__ */ jsx10(Code22, { className: "h-4 w-4" }) }),
|
|
998
|
+
/* @__PURE__ */ jsx10("button", { type: "button", onClick: (e) => {
|
|
916
999
|
stopRowClick(e);
|
|
917
1000
|
onOpenTerminal?.(sb.id);
|
|
918
|
-
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "Terminal", children: /* @__PURE__ */
|
|
919
|
-
/* @__PURE__ */
|
|
1001
|
+
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "Terminal", children: /* @__PURE__ */ jsx10(Terminal2, { className: "h-4 w-4" }) }),
|
|
1002
|
+
/* @__PURE__ */ jsx10("button", { type: "button", onClick: (e) => {
|
|
920
1003
|
stopRowClick(e);
|
|
921
1004
|
onSSH?.(sb.id);
|
|
922
|
-
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "SSH", children: /* @__PURE__ */
|
|
1005
|
+
}, className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90", title: "SSH", children: /* @__PURE__ */ jsx10(Key, { className: "h-4 w-4" }) })
|
|
923
1006
|
] }),
|
|
924
|
-
resumeHandler && /* @__PURE__ */
|
|
1007
|
+
resumeHandler && /* @__PURE__ */ jsxs9(
|
|
925
1008
|
"button",
|
|
926
1009
|
{
|
|
927
1010
|
type: "button",
|
|
@@ -932,7 +1015,7 @@ function SandboxTable({
|
|
|
932
1015
|
className: "inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-border text-primary text-[10px] font-bold uppercase tracking-wider hover:bg-[var(--accent-surface-soft)] active:scale-95 transition-all",
|
|
933
1016
|
title: resumeLabel,
|
|
934
1017
|
children: [
|
|
935
|
-
/* @__PURE__ */
|
|
1018
|
+
/* @__PURE__ */ jsx10(Play2, { className: "h-3 w-3" }),
|
|
936
1019
|
resumeLabel
|
|
937
1020
|
]
|
|
938
1021
|
}
|
|
@@ -946,55 +1029,55 @@ function SandboxTable({
|
|
|
946
1029
|
if (isActive) {
|
|
947
1030
|
const lifecycle = [];
|
|
948
1031
|
if (onStop) lifecycle.push(
|
|
949
|
-
/* @__PURE__ */
|
|
950
|
-
/* @__PURE__ */
|
|
1032
|
+
/* @__PURE__ */ jsxs9(DropdownMenuItem3, { onClick: runItem(onStop), children: [
|
|
1033
|
+
/* @__PURE__ */ jsx10(PowerOff2, { className: "mr-2 h-4 w-4" }),
|
|
951
1034
|
" Stop Sandbox"
|
|
952
1035
|
] }, "stop")
|
|
953
1036
|
);
|
|
954
1037
|
if (onKeepAlive) lifecycle.push(
|
|
955
|
-
/* @__PURE__ */
|
|
956
|
-
/* @__PURE__ */
|
|
1038
|
+
/* @__PURE__ */ jsxs9(DropdownMenuItem3, { onClick: runItem(onKeepAlive), children: [
|
|
1039
|
+
/* @__PURE__ */ jsx10(Clock2, { className: "mr-2 h-4 w-4" }),
|
|
957
1040
|
" Keep Alive"
|
|
958
1041
|
] }, "keep-alive")
|
|
959
1042
|
);
|
|
960
1043
|
if (lifecycle.length) overflowSections.push(lifecycle);
|
|
961
1044
|
const observability = [];
|
|
962
1045
|
if (onUsage) observability.push(
|
|
963
|
-
/* @__PURE__ */
|
|
964
|
-
/* @__PURE__ */
|
|
1046
|
+
/* @__PURE__ */ jsxs9(DropdownMenuItem3, { onClick: runItem(onUsage), children: [
|
|
1047
|
+
/* @__PURE__ */ jsx10(BarChart22, { className: "mr-2 h-4 w-4" }),
|
|
965
1048
|
" View Usage"
|
|
966
1049
|
] }, "usage")
|
|
967
1050
|
);
|
|
968
1051
|
if (onHealth) observability.push(
|
|
969
|
-
/* @__PURE__ */
|
|
970
|
-
/* @__PURE__ */
|
|
1052
|
+
/* @__PURE__ */ jsxs9(DropdownMenuItem3, { onClick: runItem(onHealth), children: [
|
|
1053
|
+
/* @__PURE__ */ jsx10(Activity2, { className: "mr-2 h-4 w-4" }),
|
|
971
1054
|
" Health Check"
|
|
972
1055
|
] }, "health")
|
|
973
1056
|
);
|
|
974
1057
|
if (observability.length) overflowSections.push(observability);
|
|
975
1058
|
if (onFork) overflowSections.push([
|
|
976
|
-
/* @__PURE__ */
|
|
977
|
-
/* @__PURE__ */
|
|
1059
|
+
/* @__PURE__ */ jsxs9(DropdownMenuItem3, { onClick: runItem(onFork), children: [
|
|
1060
|
+
/* @__PURE__ */ jsx10(Copy2, { className: "mr-2 h-4 w-4" }),
|
|
978
1061
|
" Fork Sandbox"
|
|
979
1062
|
] }, "fork")
|
|
980
1063
|
]);
|
|
981
1064
|
} else if (isResumable(sb.status)) {
|
|
982
1065
|
if (onFork) overflowSections.push([
|
|
983
|
-
/* @__PURE__ */
|
|
984
|
-
/* @__PURE__ */
|
|
1066
|
+
/* @__PURE__ */ jsxs9(DropdownMenuItem3, { onClick: runItem(onFork), children: [
|
|
1067
|
+
/* @__PURE__ */ jsx10(Copy2, { className: "mr-2 h-4 w-4" }),
|
|
985
1068
|
" Fork Sandbox"
|
|
986
1069
|
] }, "fork")
|
|
987
1070
|
]);
|
|
988
1071
|
}
|
|
989
1072
|
if (onMore) overflowSections.push([
|
|
990
|
-
/* @__PURE__ */
|
|
991
|
-
/* @__PURE__ */
|
|
1073
|
+
/* @__PURE__ */ jsxs9(DropdownMenuItem3, { onClick: runItem(onMore), children: [
|
|
1074
|
+
/* @__PURE__ */ jsx10(ExternalLink, { className: "mr-2 h-4 w-4" }),
|
|
992
1075
|
" View Details"
|
|
993
1076
|
] }, "view-details")
|
|
994
1077
|
]);
|
|
995
1078
|
if (overflowSections.length === 0) return null;
|
|
996
|
-
return /* @__PURE__ */
|
|
997
|
-
/* @__PURE__ */
|
|
1079
|
+
return /* @__PURE__ */ jsxs9(DropdownMenu3, { children: [
|
|
1080
|
+
/* @__PURE__ */ jsx10(DropdownMenuTrigger3, { asChild: true, children: /* @__PURE__ */ jsx10(
|
|
998
1081
|
"button",
|
|
999
1082
|
{
|
|
1000
1083
|
type: "button",
|
|
@@ -1002,19 +1085,19 @@ function SandboxTable({
|
|
|
1002
1085
|
className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-all active:scale-90 outline-none",
|
|
1003
1086
|
"aria-label": "More actions",
|
|
1004
1087
|
title: "More actions",
|
|
1005
|
-
children: /* @__PURE__ */
|
|
1088
|
+
children: /* @__PURE__ */ jsx10(MoreVertical2, { className: "h-4 w-4" })
|
|
1006
1089
|
}
|
|
1007
1090
|
) }),
|
|
1008
|
-
/* @__PURE__ */
|
|
1009
|
-
sectionIdx > 0 && /* @__PURE__ */
|
|
1091
|
+
/* @__PURE__ */ jsx10(DropdownMenuContent3, { align: "end", className: "min-w-[180px]", children: overflowSections.map((section, sectionIdx) => /* @__PURE__ */ jsxs9(React4.Fragment, { children: [
|
|
1092
|
+
sectionIdx > 0 && /* @__PURE__ */ jsx10(DropdownMenuSeparator3, {}),
|
|
1010
1093
|
section
|
|
1011
1094
|
] }, sectionIdx)) })
|
|
1012
1095
|
] });
|
|
1013
1096
|
})(),
|
|
1014
|
-
onDelete && canAdminSandbox(sb) && /* @__PURE__ */
|
|
1097
|
+
onDelete && canAdminSandbox(sb) && /* @__PURE__ */ jsx10("button", { type: "button", onClick: (e) => {
|
|
1015
1098
|
stopRowClick(e);
|
|
1016
1099
|
onDelete(sb.id);
|
|
1017
|
-
}, className: "p-2 rounded-lg hover:bg-[var(--surface-danger-bg)] text-muted-foreground hover:text-[var(--surface-danger-text)] transition-all active:scale-90", title: "Delete", children: /* @__PURE__ */
|
|
1100
|
+
}, className: "p-2 rounded-lg hover:bg-[var(--surface-danger-bg)] text-muted-foreground hover:text-[var(--surface-danger-text)] transition-all active:scale-90", title: "Delete", children: /* @__PURE__ */ jsx10(Trash22, { className: "h-4 w-4" }) })
|
|
1018
1101
|
] }) })
|
|
1019
1102
|
]
|
|
1020
1103
|
},
|
|
@@ -1023,17 +1106,17 @@ function SandboxTable({
|
|
|
1023
1106
|
);
|
|
1024
1107
|
}) })
|
|
1025
1108
|
] }) }) }),
|
|
1026
|
-
totalPages > 1 && /* @__PURE__ */
|
|
1027
|
-
/* @__PURE__ */
|
|
1109
|
+
totalPages > 1 && /* @__PURE__ */ jsxs9("div", { className: "mt-6 flex flex-col md:flex-row justify-between items-center text-muted-foreground text-xs font-medium gap-4", children: [
|
|
1110
|
+
/* @__PURE__ */ jsxs9("p", { children: [
|
|
1028
1111
|
"Showing ",
|
|
1029
1112
|
sandboxes.length,
|
|
1030
1113
|
" of ",
|
|
1031
1114
|
totalCount,
|
|
1032
1115
|
" active sandboxes"
|
|
1033
1116
|
] }),
|
|
1034
|
-
/* @__PURE__ */
|
|
1035
|
-
/* @__PURE__ */
|
|
1036
|
-
Array.from({ length: Math.min(totalPages, 5) }, (_, i) => i + 1).map((p) => /* @__PURE__ */
|
|
1117
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
|
|
1118
|
+
/* @__PURE__ */ jsx10("button", { type: "button", onClick: () => onPageChange?.(page - 1), disabled: page <= 1, className: "p-2 rounded-lg border border-border hover:bg-muted/50 transition-colors disabled:opacity-30", children: /* @__PURE__ */ jsx10(ChevronLeft, { className: "h-4 w-4" }) }),
|
|
1119
|
+
Array.from({ length: Math.min(totalPages, 5) }, (_, i) => i + 1).map((p) => /* @__PURE__ */ jsx10(
|
|
1037
1120
|
"button",
|
|
1038
1121
|
{
|
|
1039
1122
|
type: "button",
|
|
@@ -1046,7 +1129,7 @@ function SandboxTable({
|
|
|
1046
1129
|
},
|
|
1047
1130
|
p
|
|
1048
1131
|
)),
|
|
1049
|
-
/* @__PURE__ */
|
|
1132
|
+
/* @__PURE__ */ jsx10("button", { type: "button", onClick: () => onPageChange?.(page + 1), disabled: page >= totalPages, className: "p-2 rounded-lg border border-border hover:bg-muted/50 transition-colors disabled:opacity-30", children: /* @__PURE__ */ jsx10(ChevronRight, { className: "h-4 w-4" }) })
|
|
1050
1133
|
] })
|
|
1051
1134
|
] })
|
|
1052
1135
|
] });
|
|
@@ -1054,51 +1137,51 @@ function SandboxTable({
|
|
|
1054
1137
|
|
|
1055
1138
|
// src/dashboard/invoice-table.tsx
|
|
1056
1139
|
import { Download, FileText } from "lucide-react";
|
|
1057
|
-
import { jsx as
|
|
1140
|
+
import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1058
1141
|
var statusStyle = {
|
|
1059
1142
|
paid: "bg-[var(--accent-surface-soft)] text-primary border border-border",
|
|
1060
1143
|
pending: "bg-[var(--surface-warning-bg)] text-[var(--surface-warning-text)] border border-[var(--surface-warning-border)]",
|
|
1061
1144
|
failed: "bg-[var(--surface-danger-bg)] text-[var(--surface-danger-text)] border border-[var(--surface-danger-border)]"
|
|
1062
1145
|
};
|
|
1063
1146
|
function InvoiceTable({ invoices, onExportAll, onLoadMore, onViewInvoice, hasMore, className }) {
|
|
1064
|
-
return /* @__PURE__ */
|
|
1065
|
-
/* @__PURE__ */
|
|
1066
|
-
/* @__PURE__ */
|
|
1067
|
-
onExportAll && /* @__PURE__ */
|
|
1068
|
-
/* @__PURE__ */
|
|
1147
|
+
return /* @__PURE__ */ jsxs10("section", { className, children: [
|
|
1148
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex justify-between items-center mb-6 px-2", children: [
|
|
1149
|
+
/* @__PURE__ */ jsx11("h2", { className: "text-2xl font-bold text-foreground tracking-tight", children: "Invoice History" }),
|
|
1150
|
+
onExportAll && /* @__PURE__ */ jsxs10("button", { type: "button", onClick: onExportAll, className: "text-[10px] font-mono text-primary uppercase tracking-widest flex items-center gap-2 hover:underline", children: [
|
|
1151
|
+
/* @__PURE__ */ jsx11(Download, { className: "h-3.5 w-3.5" }),
|
|
1069
1152
|
"Export All"
|
|
1070
1153
|
] })
|
|
1071
1154
|
] }),
|
|
1072
|
-
/* @__PURE__ */
|
|
1073
|
-
/* @__PURE__ */
|
|
1074
|
-
/* @__PURE__ */
|
|
1075
|
-
/* @__PURE__ */
|
|
1076
|
-
/* @__PURE__ */
|
|
1077
|
-
/* @__PURE__ */
|
|
1078
|
-
/* @__PURE__ */
|
|
1155
|
+
/* @__PURE__ */ jsx11("div", { className: "bg-card rounded-xl overflow-hidden border border-border", children: /* @__PURE__ */ jsxs10("table", { className: "w-full text-left border-collapse", children: [
|
|
1156
|
+
/* @__PURE__ */ jsx11("thead", { children: /* @__PURE__ */ jsxs10("tr", { className: "bg-background border-b border-border", children: [
|
|
1157
|
+
/* @__PURE__ */ jsx11("th", { className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest", children: "Invoice ID" }),
|
|
1158
|
+
/* @__PURE__ */ jsx11("th", { className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest", children: "Date" }),
|
|
1159
|
+
/* @__PURE__ */ jsx11("th", { className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest", children: "Amount" }),
|
|
1160
|
+
/* @__PURE__ */ jsx11("th", { className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest", children: "Status" }),
|
|
1161
|
+
/* @__PURE__ */ jsx11("th", { className: "px-6 py-4 font-mono text-[10px] text-muted-foreground uppercase tracking-widest text-right", children: "Action" })
|
|
1079
1162
|
] }) }),
|
|
1080
|
-
/* @__PURE__ */
|
|
1081
|
-
/* @__PURE__ */
|
|
1082
|
-
/* @__PURE__ */
|
|
1083
|
-
/* @__PURE__ */
|
|
1163
|
+
/* @__PURE__ */ jsx11("tbody", { className: "divide-y divide-border", children: invoices.map((inv) => /* @__PURE__ */ jsxs10("tr", { className: "hover:bg-muted/50 transition-colors", children: [
|
|
1164
|
+
/* @__PURE__ */ jsx11("td", { className: "px-6 py-5 font-mono text-xs text-foreground", children: inv.id }),
|
|
1165
|
+
/* @__PURE__ */ jsx11("td", { className: "px-6 py-5 text-sm text-foreground", children: inv.date }),
|
|
1166
|
+
/* @__PURE__ */ jsxs10("td", { className: "px-6 py-5 text-sm font-bold text-foreground", children: [
|
|
1084
1167
|
"$",
|
|
1085
1168
|
inv.amount.toFixed(2)
|
|
1086
1169
|
] }),
|
|
1087
|
-
/* @__PURE__ */
|
|
1088
|
-
/* @__PURE__ */
|
|
1170
|
+
/* @__PURE__ */ jsx11("td", { className: "px-6 py-5", children: /* @__PURE__ */ jsx11("span", { className: cn("px-2 py-1 text-[10px] font-mono rounded uppercase", statusStyle[inv.status] ?? statusStyle.paid), children: inv.status }) }),
|
|
1171
|
+
/* @__PURE__ */ jsx11("td", { className: "px-6 py-5 text-right", children: /* @__PURE__ */ jsx11("button", { type: "button", onClick: () => onViewInvoice?.(inv.id), className: "text-muted-foreground hover:text-foreground transition-colors", children: /* @__PURE__ */ jsx11(FileText, { className: "h-4 w-4" }) }) })
|
|
1089
1172
|
] }, inv.id)) })
|
|
1090
1173
|
] }) }),
|
|
1091
|
-
hasMore && onLoadMore && /* @__PURE__ */
|
|
1174
|
+
hasMore && onLoadMore && /* @__PURE__ */ jsx11("div", { className: "mt-6 flex justify-center", children: /* @__PURE__ */ jsx11("button", { type: "button", onClick: onLoadMore, className: "px-8 py-2 text-[10px] font-mono text-muted-foreground border border-border rounded-full hover:bg-muted/50 transition-colors uppercase tracking-widest", children: "Load More History" }) })
|
|
1092
1175
|
] });
|
|
1093
1176
|
}
|
|
1094
1177
|
|
|
1095
1178
|
// src/dashboard/plan-cards.tsx
|
|
1096
1179
|
import { Check } from "lucide-react";
|
|
1097
|
-
import { jsx as
|
|
1180
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1098
1181
|
function PlanCards({ plans, className }) {
|
|
1099
|
-
return /* @__PURE__ */
|
|
1100
|
-
/* @__PURE__ */
|
|
1101
|
-
/* @__PURE__ */
|
|
1182
|
+
return /* @__PURE__ */ jsxs11("section", { className, children: [
|
|
1183
|
+
/* @__PURE__ */ jsx12("h2", { className: "text-2xl font-bold text-foreground tracking-tight mb-5 px-2", children: "Subscription Plans" }),
|
|
1184
|
+
/* @__PURE__ */ jsx12("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-6", children: plans.map((plan) => /* @__PURE__ */ jsxs11(
|
|
1102
1185
|
"div",
|
|
1103
1186
|
{
|
|
1104
1187
|
className: cn(
|
|
@@ -1106,23 +1189,23 @@ function PlanCards({ plans, className }) {
|
|
|
1106
1189
|
plan.popular ? "bg-muted/50 border-border" : "bg-card border-border hover:bg-muted/50 hover:border-primary/20"
|
|
1107
1190
|
),
|
|
1108
1191
|
children: [
|
|
1109
|
-
plan.popular && /* @__PURE__ */
|
|
1110
|
-
/* @__PURE__ */
|
|
1111
|
-
/* @__PURE__ */
|
|
1112
|
-
/* @__PURE__ */
|
|
1192
|
+
plan.popular && /* @__PURE__ */ jsx12("div", { className: "absolute top-0 right-0 bg-[var(--accent-surface-soft)] border-l border-b border-border px-4 py-1 text-[10px] font-bold text-[var(--accent-text)] uppercase tracking-widest rounded-bl-lg", children: "Popular" }),
|
|
1193
|
+
/* @__PURE__ */ jsxs11("div", { className: "mb-4", children: [
|
|
1194
|
+
/* @__PURE__ */ jsx12("div", { className: cn("text-xs font-mono uppercase tracking-widest mb-2", plan.popular ? "text-primary" : "text-muted-foreground"), children: plan.name }),
|
|
1195
|
+
/* @__PURE__ */ jsxs11("div", { className: "text-3xl font-bold text-foreground", children: [
|
|
1113
1196
|
"$",
|
|
1114
1197
|
plan.price,
|
|
1115
|
-
/* @__PURE__ */
|
|
1198
|
+
/* @__PURE__ */ jsxs11("span", { className: "text-sm font-normal text-muted-foreground tracking-normal", children: [
|
|
1116
1199
|
"/",
|
|
1117
1200
|
plan.period ?? "mo"
|
|
1118
1201
|
] })
|
|
1119
1202
|
] })
|
|
1120
1203
|
] }),
|
|
1121
|
-
/* @__PURE__ */
|
|
1122
|
-
/* @__PURE__ */
|
|
1204
|
+
/* @__PURE__ */ jsx12("ul", { className: "space-y-2 mb-5 text-sm text-muted-foreground", children: plan.features.map((f, i) => /* @__PURE__ */ jsxs11("li", { className: "flex items-center gap-2", children: [
|
|
1205
|
+
/* @__PURE__ */ jsx12(Check, { className: "h-3.5 w-3.5 text-primary shrink-0" }),
|
|
1123
1206
|
f.text
|
|
1124
1207
|
] }, i)) }),
|
|
1125
|
-
/* @__PURE__ */
|
|
1208
|
+
/* @__PURE__ */ jsx12(
|
|
1126
1209
|
"button",
|
|
1127
1210
|
{
|
|
1128
1211
|
type: "button",
|
|
@@ -1142,29 +1225,29 @@ function PlanCards({ plans, className }) {
|
|
|
1142
1225
|
}
|
|
1143
1226
|
|
|
1144
1227
|
// src/dashboard/dashboard-layout.tsx
|
|
1145
|
-
import * as
|
|
1228
|
+
import * as React5 from "react";
|
|
1146
1229
|
import { Plus as Plus2, Bell } from "lucide-react";
|
|
1147
|
-
import { Fragment as Fragment7, jsx as
|
|
1230
|
+
import { Fragment as Fragment7, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1148
1231
|
function SettingsIconSmall({ className }) {
|
|
1149
|
-
return /* @__PURE__ */
|
|
1150
|
-
/* @__PURE__ */
|
|
1151
|
-
/* @__PURE__ */
|
|
1152
|
-
/* @__PURE__ */
|
|
1232
|
+
return /* @__PURE__ */ jsxs12("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1233
|
+
/* @__PURE__ */ jsx13("title", { children: "Settings" }),
|
|
1234
|
+
/* @__PURE__ */ jsx13("path", { d: "M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z" }),
|
|
1235
|
+
/* @__PURE__ */ jsx13("circle", { cx: "12", cy: "12", r: "3" })
|
|
1153
1236
|
] });
|
|
1154
1237
|
}
|
|
1155
1238
|
function MenuIcon({ className }) {
|
|
1156
|
-
return /* @__PURE__ */
|
|
1157
|
-
/* @__PURE__ */
|
|
1158
|
-
/* @__PURE__ */
|
|
1159
|
-
/* @__PURE__ */
|
|
1160
|
-
/* @__PURE__ */
|
|
1239
|
+
return /* @__PURE__ */ jsxs12("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1240
|
+
/* @__PURE__ */ jsx13("title", { children: "Menu icon" }),
|
|
1241
|
+
/* @__PURE__ */ jsx13("line", { x1: "4", x2: "20", y1: "12", y2: "12" }),
|
|
1242
|
+
/* @__PURE__ */ jsx13("line", { x1: "4", x2: "20", y1: "6", y2: "6" }),
|
|
1243
|
+
/* @__PURE__ */ jsx13("line", { x1: "4", x2: "20", y1: "18", y2: "18" })
|
|
1161
1244
|
] });
|
|
1162
1245
|
}
|
|
1163
1246
|
function XIcon({ className }) {
|
|
1164
|
-
return /* @__PURE__ */
|
|
1165
|
-
/* @__PURE__ */
|
|
1166
|
-
/* @__PURE__ */
|
|
1167
|
-
/* @__PURE__ */
|
|
1247
|
+
return /* @__PURE__ */ jsxs12("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1248
|
+
/* @__PURE__ */ jsx13("title", { children: "Close icon" }),
|
|
1249
|
+
/* @__PURE__ */ jsx13("path", { d: "M18 6 6 18" }),
|
|
1250
|
+
/* @__PURE__ */ jsx13("path", { d: "m6 6 12 12" })
|
|
1168
1251
|
] });
|
|
1169
1252
|
}
|
|
1170
1253
|
function formatNotifDate(raw) {
|
|
@@ -1178,7 +1261,7 @@ function DefaultLink2({
|
|
|
1178
1261
|
children,
|
|
1179
1262
|
...rest
|
|
1180
1263
|
}) {
|
|
1181
|
-
return /* @__PURE__ */
|
|
1264
|
+
return /* @__PURE__ */ jsx13("a", { href: href ?? to, className, ...rest, children });
|
|
1182
1265
|
}
|
|
1183
1266
|
function DashboardLayoutInner({
|
|
1184
1267
|
children,
|
|
@@ -1205,10 +1288,10 @@ function DashboardLayoutInner({
|
|
|
1205
1288
|
notifications: notifData
|
|
1206
1289
|
}) {
|
|
1207
1290
|
const Link = LinkComponent;
|
|
1208
|
-
const [mobileMenuOpen, setMobileMenuOpen] =
|
|
1209
|
-
const [notificationsOpen, setNotificationsOpen] =
|
|
1210
|
-
const notifRef =
|
|
1211
|
-
|
|
1291
|
+
const [mobileMenuOpen, setMobileMenuOpen] = React5.useState(false);
|
|
1292
|
+
const [notificationsOpen, setNotificationsOpen] = React5.useState(false);
|
|
1293
|
+
const notifRef = React5.useRef(null);
|
|
1294
|
+
React5.useEffect(() => {
|
|
1212
1295
|
if (!notificationsOpen) return;
|
|
1213
1296
|
const handler = (e) => {
|
|
1214
1297
|
if (notifRef.current && !notifRef.current.contains(e.target)) {
|
|
@@ -1226,23 +1309,23 @@ function DashboardLayoutInner({
|
|
|
1226
1309
|
};
|
|
1227
1310
|
}, [notificationsOpen]);
|
|
1228
1311
|
const { contentMargin, hidden, mode, hasPanels, panelOpen } = useSidebar();
|
|
1229
|
-
const modeSet =
|
|
1230
|
-
const sidebarUser =
|
|
1312
|
+
const modeSet = React5.useMemo(() => new Set(modeItems), [modeItems]);
|
|
1313
|
+
const sidebarUser = React5.useMemo(
|
|
1231
1314
|
() => user ? { email: user.email, name: user.name, tier: user.tier, avatarUrl: user.avatarUrl } : void 0,
|
|
1232
1315
|
[user?.email, user?.name, user?.tier, user?.avatarUrl]
|
|
1233
1316
|
);
|
|
1234
1317
|
const activePanel = panels.find((p) => p.mode === mode);
|
|
1235
|
-
const buildSidebarContent =
|
|
1236
|
-
(showLabels) => /* @__PURE__ */
|
|
1237
|
-
/* @__PURE__ */
|
|
1238
|
-
/* @__PURE__ */
|
|
1239
|
-
/* @__PURE__ */
|
|
1318
|
+
const buildSidebarContent = React5.useCallback(
|
|
1319
|
+
(showLabels) => /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
1320
|
+
/* @__PURE__ */ jsxs12(SidebarRail, { wide: showLabels, children: [
|
|
1321
|
+
/* @__PURE__ */ jsx13(SidebarRailHeader, { children: /* @__PURE__ */ jsx13(Link, { href: "/", to: "/", className: "p-1 rounded-md transition-colors hover:bg-muted/50", children: /* @__PURE__ */ jsx13(Logo, { variant, size: "sm", iconOnly: true }) }) }),
|
|
1322
|
+
/* @__PURE__ */ jsx13(SidebarRailNav, { children: navItems.map((item, i) => {
|
|
1240
1323
|
const isMode = modeSet.has(item.id);
|
|
1241
1324
|
const prevIsMode = i > 0 && modeSet.has(navItems[i - 1].id);
|
|
1242
1325
|
const showSep = i > 0 && isMode && !prevIsMode;
|
|
1243
|
-
return /* @__PURE__ */
|
|
1244
|
-
showSep && /* @__PURE__ */
|
|
1245
|
-
isMode ? /* @__PURE__ */
|
|
1326
|
+
return /* @__PURE__ */ jsxs12(React5.Fragment, { children: [
|
|
1327
|
+
showSep && /* @__PURE__ */ jsx13(RailSeparator, {}),
|
|
1328
|
+
isMode ? /* @__PURE__ */ jsx13(
|
|
1246
1329
|
RailModeButton,
|
|
1247
1330
|
{
|
|
1248
1331
|
mode: item.id,
|
|
@@ -1251,7 +1334,7 @@ function DashboardLayoutInner({
|
|
|
1251
1334
|
badge: item.badge,
|
|
1252
1335
|
showLabel: showLabels
|
|
1253
1336
|
}
|
|
1254
|
-
) : /* @__PURE__ */
|
|
1337
|
+
) : /* @__PURE__ */ jsx13(Link, { href: item.href, to: item.href, children: /* @__PURE__ */ jsx13(
|
|
1255
1338
|
RailButton,
|
|
1256
1339
|
{
|
|
1257
1340
|
icon: item.icon,
|
|
@@ -1262,11 +1345,11 @@ function DashboardLayoutInner({
|
|
|
1262
1345
|
) })
|
|
1263
1346
|
] }, item.id);
|
|
1264
1347
|
}) }),
|
|
1265
|
-
/* @__PURE__ */
|
|
1266
|
-
onSettingsClick ? /* @__PURE__ */
|
|
1348
|
+
/* @__PURE__ */ jsxs12(SidebarRailFooter, { children: [
|
|
1349
|
+
onSettingsClick ? /* @__PURE__ */ jsx13(RailButton, { icon: SettingsIconSmall, label: "Settings", onClick: onSettingsClick, showLabel: showLabels }) : /* @__PURE__ */ jsx13(Link, { href: settingsHref, to: settingsHref, children: /* @__PURE__ */ jsx13(RailButton, { icon: SettingsIconSmall, label: "Settings", showLabel: showLabels }) }),
|
|
1267
1350
|
railFooter,
|
|
1268
|
-
/* @__PURE__ */
|
|
1269
|
-
/* @__PURE__ */
|
|
1351
|
+
/* @__PURE__ */ jsx13(RailSeparator, {}),
|
|
1352
|
+
/* @__PURE__ */ jsx13(
|
|
1270
1353
|
ProfileAvatar,
|
|
1271
1354
|
{
|
|
1272
1355
|
user: sidebarUser,
|
|
@@ -1280,9 +1363,9 @@ function DashboardLayoutInner({
|
|
|
1280
1363
|
)
|
|
1281
1364
|
] })
|
|
1282
1365
|
] }),
|
|
1283
|
-
panels.length > 0 && /* @__PURE__ */
|
|
1284
|
-
/* @__PURE__ */
|
|
1285
|
-
/* @__PURE__ */
|
|
1366
|
+
panels.length > 0 && /* @__PURE__ */ jsxs12(SidebarPanel, { children: [
|
|
1367
|
+
/* @__PURE__ */ jsx13(SidebarPanelHeader, { title: activePanel?.title ?? mode }),
|
|
1368
|
+
/* @__PURE__ */ jsx13(SidebarPanelContent, { children: activePanel?.content })
|
|
1286
1369
|
] })
|
|
1287
1370
|
] }),
|
|
1288
1371
|
// biome-ignore lint/correctness/useExhaustiveDependencies: intentional — only the inputs that actually affect the sidebar tree
|
|
@@ -1305,10 +1388,10 @@ function DashboardLayoutInner({
|
|
|
1305
1388
|
mode
|
|
1306
1389
|
]
|
|
1307
1390
|
);
|
|
1308
|
-
const sidebarContent =
|
|
1309
|
-
const mobileSidebarContent =
|
|
1310
|
-
return /* @__PURE__ */
|
|
1311
|
-
/* @__PURE__ */
|
|
1391
|
+
const sidebarContent = React5.useMemo(() => buildSidebarContent(false), [buildSidebarContent]);
|
|
1392
|
+
const mobileSidebarContent = React5.useMemo(() => buildSidebarContent(true), [buildSidebarContent]);
|
|
1393
|
+
return /* @__PURE__ */ jsxs12("div", { className: cn("min-h-screen bg-background text-foreground", className), children: [
|
|
1394
|
+
/* @__PURE__ */ jsxs12(
|
|
1312
1395
|
"nav",
|
|
1313
1396
|
{
|
|
1314
1397
|
className: "fixed top-0 z-50 bg-card border-b border-border flex justify-between items-center px-8 h-14 font-sans text-[13px] tracking-tight transition-[left,width] duration-200 ease-in-out",
|
|
@@ -1317,9 +1400,9 @@ function DashboardLayoutInner({
|
|
|
1317
1400
|
width: hidden ? "100%" : `calc(100% - ${contentMargin}px)`
|
|
1318
1401
|
},
|
|
1319
1402
|
children: [
|
|
1320
|
-
/* @__PURE__ */
|
|
1321
|
-
/* @__PURE__ */
|
|
1322
|
-
topNavLinks && topNavLinks.length > 0 && /* @__PURE__ */
|
|
1403
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-8", children: [
|
|
1404
|
+
/* @__PURE__ */ jsx13(Link, { href: "/", to: "/", className: "lg:hidden flex items-center p-1 rounded-md hover:bg-muted/50 transition-colors", children: /* @__PURE__ */ jsx13(Logo, { variant, size: "sm", iconOnly: true }) }),
|
|
1405
|
+
topNavLinks && topNavLinks.length > 0 && /* @__PURE__ */ jsx13("div", { className: "hidden md:flex gap-6", children: topNavLinks.map((link) => /* @__PURE__ */ jsx13(
|
|
1323
1406
|
Link,
|
|
1324
1407
|
{
|
|
1325
1408
|
href: link.href,
|
|
@@ -1333,21 +1416,21 @@ function DashboardLayoutInner({
|
|
|
1333
1416
|
link.href
|
|
1334
1417
|
)) })
|
|
1335
1418
|
] }),
|
|
1336
|
-
/* @__PURE__ */
|
|
1337
|
-
onNewSandbox && /* @__PURE__ */
|
|
1419
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-4", children: [
|
|
1420
|
+
onNewSandbox && /* @__PURE__ */ jsxs12(
|
|
1338
1421
|
"button",
|
|
1339
1422
|
{
|
|
1340
1423
|
type: "button",
|
|
1341
1424
|
onClick: onNewSandbox,
|
|
1342
1425
|
className: "hidden md:flex items-center gap-2 bg-[var(--btn-primary-bg)] border border-[var(--border-accent)] text-[var(--btn-primary-text)] px-4 py-2 rounded-lg font-bold hover:bg-[var(--btn-primary-hover)] transition-all active:scale-95 text-xs",
|
|
1343
1426
|
children: [
|
|
1344
|
-
/* @__PURE__ */
|
|
1427
|
+
/* @__PURE__ */ jsx13(Plus2, { className: "h-3.5 w-3.5" }),
|
|
1345
1428
|
"New Sandbox"
|
|
1346
1429
|
]
|
|
1347
1430
|
}
|
|
1348
1431
|
),
|
|
1349
|
-
/* @__PURE__ */
|
|
1350
|
-
/* @__PURE__ */
|
|
1432
|
+
/* @__PURE__ */ jsxs12("div", { className: "relative", ref: notifRef, children: [
|
|
1433
|
+
/* @__PURE__ */ jsxs12(
|
|
1351
1434
|
"button",
|
|
1352
1435
|
{
|
|
1353
1436
|
type: "button",
|
|
@@ -1356,15 +1439,15 @@ function DashboardLayoutInner({
|
|
|
1356
1439
|
"aria-label": "Notifications",
|
|
1357
1440
|
"aria-expanded": notificationsOpen,
|
|
1358
1441
|
children: [
|
|
1359
|
-
/* @__PURE__ */
|
|
1360
|
-
(notifData?.unreadCount ?? 0) > 0 && /* @__PURE__ */
|
|
1442
|
+
/* @__PURE__ */ jsx13(Bell, { className: "h-4 w-4" }),
|
|
1443
|
+
(notifData?.unreadCount ?? 0) > 0 && /* @__PURE__ */ jsx13("span", { className: "absolute top-1 right-1 h-2 w-2 rounded-full bg-destructive" })
|
|
1361
1444
|
]
|
|
1362
1445
|
}
|
|
1363
1446
|
),
|
|
1364
|
-
notificationsOpen && /* @__PURE__ */
|
|
1365
|
-
/* @__PURE__ */
|
|
1366
|
-
/* @__PURE__ */
|
|
1367
|
-
(notifData?.unreadCount ?? 0) > 0 && notifData?.onMarkAllRead && /* @__PURE__ */
|
|
1447
|
+
notificationsOpen && /* @__PURE__ */ jsxs12("div", { className: "absolute right-0 top-full mt-2 w-80 rounded-lg border border-border bg-card shadow-lg z-50", children: [
|
|
1448
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between border-b border-border px-4 py-3", children: [
|
|
1449
|
+
/* @__PURE__ */ jsx13("p", { className: "font-bold text-foreground text-sm", children: "Notifications" }),
|
|
1450
|
+
(notifData?.unreadCount ?? 0) > 0 && notifData?.onMarkAllRead && /* @__PURE__ */ jsx13(
|
|
1368
1451
|
"button",
|
|
1369
1452
|
{
|
|
1370
1453
|
type: "button",
|
|
@@ -1376,11 +1459,11 @@ function DashboardLayoutInner({
|
|
|
1376
1459
|
}
|
|
1377
1460
|
)
|
|
1378
1461
|
] }),
|
|
1379
|
-
!notifData?.items || notifData.items.length === 0 ? /* @__PURE__ */
|
|
1380
|
-
/* @__PURE__ */
|
|
1381
|
-
/* @__PURE__ */
|
|
1382
|
-
/* @__PURE__ */
|
|
1383
|
-
] }) : /* @__PURE__ */
|
|
1462
|
+
!notifData?.items || notifData.items.length === 0 ? /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center justify-center px-4 py-8 text-center", children: [
|
|
1463
|
+
/* @__PURE__ */ jsx13(Bell, { className: "h-8 w-8 text-muted-foreground/40 mb-2" }),
|
|
1464
|
+
/* @__PURE__ */ jsx13("p", { className: "text-muted-foreground text-sm", children: "No notifications yet" }),
|
|
1465
|
+
/* @__PURE__ */ jsx13("p", { className: "text-muted-foreground/60 text-xs mt-1", children: "We'll notify you about important updates" })
|
|
1466
|
+
] }) : /* @__PURE__ */ jsx13("div", { className: "max-h-80 overflow-y-auto", children: notifData.items.map((n) => /* @__PURE__ */ jsxs12(
|
|
1384
1467
|
"button",
|
|
1385
1468
|
{
|
|
1386
1469
|
type: "button",
|
|
@@ -1392,9 +1475,9 @@ function DashboardLayoutInner({
|
|
|
1392
1475
|
if (!n.read) notifData.onMarkRead?.(n.id);
|
|
1393
1476
|
},
|
|
1394
1477
|
children: [
|
|
1395
|
-
/* @__PURE__ */
|
|
1396
|
-
/* @__PURE__ */
|
|
1397
|
-
/* @__PURE__ */
|
|
1478
|
+
/* @__PURE__ */ jsx13("p", { className: cn("text-sm", !n.read ? "font-semibold text-foreground" : "text-muted-foreground"), children: n.title }),
|
|
1479
|
+
/* @__PURE__ */ jsx13("p", { className: "text-xs text-muted-foreground mt-0.5 line-clamp-2", children: n.message }),
|
|
1480
|
+
/* @__PURE__ */ jsx13("p", { className: "text-[10px] text-muted-foreground/50 mt-1", children: formatNotifDate(n.createdAt) })
|
|
1398
1481
|
]
|
|
1399
1482
|
},
|
|
1400
1483
|
n.id
|
|
@@ -1402,7 +1485,7 @@ function DashboardLayoutInner({
|
|
|
1402
1485
|
] })
|
|
1403
1486
|
] })
|
|
1404
1487
|
] }),
|
|
1405
|
-
/* @__PURE__ */
|
|
1488
|
+
/* @__PURE__ */ jsx13(
|
|
1406
1489
|
"button",
|
|
1407
1490
|
{
|
|
1408
1491
|
type: "button",
|
|
@@ -1410,14 +1493,14 @@ function DashboardLayoutInner({
|
|
|
1410
1493
|
className: "rounded-md p-2 hover:bg-muted/50 lg:hidden",
|
|
1411
1494
|
"aria-label": mobileMenuOpen ? "Close menu" : "Open menu",
|
|
1412
1495
|
"aria-expanded": mobileMenuOpen,
|
|
1413
|
-
children: mobileMenuOpen ? /* @__PURE__ */
|
|
1496
|
+
children: mobileMenuOpen ? /* @__PURE__ */ jsx13(XIcon, { className: "h-6 w-6" }) : /* @__PURE__ */ jsx13(MenuIcon, { className: "h-6 w-6" })
|
|
1414
1497
|
}
|
|
1415
1498
|
)
|
|
1416
1499
|
]
|
|
1417
1500
|
}
|
|
1418
1501
|
),
|
|
1419
|
-
mobileMenuOpen && /* @__PURE__ */
|
|
1420
|
-
/* @__PURE__ */
|
|
1502
|
+
mobileMenuOpen && /* @__PURE__ */ jsx13("div", { className: "fixed inset-0 z-30 bg-black/50 lg:hidden", onClick: () => setMobileMenuOpen(false), "aria-hidden": "true" }),
|
|
1503
|
+
/* @__PURE__ */ jsx13(
|
|
1421
1504
|
"aside",
|
|
1422
1505
|
{
|
|
1423
1506
|
className: cn(
|
|
@@ -1430,13 +1513,13 @@ function DashboardLayoutInner({
|
|
|
1430
1513
|
children: mobileSidebarContent
|
|
1431
1514
|
}
|
|
1432
1515
|
),
|
|
1433
|
-
/* @__PURE__ */
|
|
1434
|
-
/* @__PURE__ */
|
|
1516
|
+
/* @__PURE__ */ jsx13(Sidebar, { className: cn("hidden lg:flex", sidebarClassName), children: sidebarContent }),
|
|
1517
|
+
/* @__PURE__ */ jsx13(SidebarContent, { className: cn("pt-16 px-6 pb-8 lg:px-8 bg-background", contentClassName), children }),
|
|
1435
1518
|
footer
|
|
1436
1519
|
] });
|
|
1437
1520
|
}
|
|
1438
1521
|
function DashboardLayout({ defaultPanelOpen, defaultMode, ...props }) {
|
|
1439
|
-
return /* @__PURE__ */
|
|
1522
|
+
return /* @__PURE__ */ jsx13(SidebarProvider, { defaultPanelOpen, defaultMode, hasPanels: (props.panels?.length ?? 0) > 0, children: /* @__PURE__ */ jsx13(DashboardLayoutInner, { defaultPanelOpen, defaultMode, ...props }) });
|
|
1440
1523
|
}
|
|
1441
1524
|
|
|
1442
1525
|
// src/dashboard/profile-selector.tsx
|
|
@@ -1451,7 +1534,7 @@ import {
|
|
|
1451
1534
|
DropdownMenuSeparator as DropdownMenuSeparator4,
|
|
1452
1535
|
DropdownMenuTrigger as DropdownMenuTrigger4
|
|
1453
1536
|
} from "@tangle-network/ui/primitives";
|
|
1454
|
-
import { Fragment as Fragment8, jsx as
|
|
1537
|
+
import { Fragment as Fragment8, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1455
1538
|
function ProfileSelector({
|
|
1456
1539
|
profiles,
|
|
1457
1540
|
selectedId,
|
|
@@ -1466,77 +1549,77 @@ function ProfileSelector({
|
|
|
1466
1549
|
const selected = profiles.find((p) => p.id === selectedId);
|
|
1467
1550
|
const builtinProfiles = profiles.filter((p) => p.is_builtin);
|
|
1468
1551
|
const customProfiles = profiles.filter((p) => !p.is_builtin);
|
|
1469
|
-
return /* @__PURE__ */
|
|
1470
|
-
label && /* @__PURE__ */
|
|
1471
|
-
/* @__PURE__ */
|
|
1472
|
-
/* @__PURE__ */
|
|
1473
|
-
/* @__PURE__ */
|
|
1474
|
-
/* @__PURE__ */
|
|
1552
|
+
return /* @__PURE__ */ jsxs13("div", { className, children: [
|
|
1553
|
+
label && /* @__PURE__ */ jsx14("label", { className: "mb-2 block font-medium text-sm", children: label }),
|
|
1554
|
+
/* @__PURE__ */ jsxs13(DropdownMenu4, { children: [
|
|
1555
|
+
/* @__PURE__ */ jsx14(DropdownMenuTrigger4, { asChild: true, children: /* @__PURE__ */ jsxs13(Button2, { variant: "outline", className: "w-full justify-between", children: [
|
|
1556
|
+
/* @__PURE__ */ jsx14("span", { className: "truncate", children: selected ? selected.name : placeholder }),
|
|
1557
|
+
/* @__PURE__ */ jsx14(ChevronDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })
|
|
1475
1558
|
] }) }),
|
|
1476
|
-
/* @__PURE__ */
|
|
1477
|
-
/* @__PURE__ */
|
|
1559
|
+
/* @__PURE__ */ jsxs13(DropdownMenuContent4, { className: "w-[300px]", align: "start", children: [
|
|
1560
|
+
/* @__PURE__ */ jsxs13(
|
|
1478
1561
|
DropdownMenuItem4,
|
|
1479
1562
|
{
|
|
1480
1563
|
onClick: () => onSelect(null),
|
|
1481
1564
|
className: "flex items-center justify-between",
|
|
1482
1565
|
children: [
|
|
1483
|
-
/* @__PURE__ */
|
|
1484
|
-
!selectedId && /* @__PURE__ */
|
|
1566
|
+
/* @__PURE__ */ jsx14("span", { children: placeholder }),
|
|
1567
|
+
!selectedId && /* @__PURE__ */ jsx14(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
1485
1568
|
]
|
|
1486
1569
|
}
|
|
1487
1570
|
),
|
|
1488
|
-
builtinProfiles.length > 0 && /* @__PURE__ */
|
|
1489
|
-
/* @__PURE__ */
|
|
1490
|
-
/* @__PURE__ */
|
|
1491
|
-
builtinProfiles.map((profile) => /* @__PURE__ */
|
|
1571
|
+
builtinProfiles.length > 0 && /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
1572
|
+
/* @__PURE__ */ jsx14(DropdownMenuSeparator4, {}),
|
|
1573
|
+
/* @__PURE__ */ jsx14(DropdownMenuLabel2, { children: "Built-in Profiles" }),
|
|
1574
|
+
builtinProfiles.map((profile) => /* @__PURE__ */ jsxs13(
|
|
1492
1575
|
DropdownMenuItem4,
|
|
1493
1576
|
{
|
|
1494
1577
|
onClick: () => onSelect(profile),
|
|
1495
1578
|
className: "flex flex-col items-start gap-1",
|
|
1496
1579
|
children: [
|
|
1497
|
-
/* @__PURE__ */
|
|
1498
|
-
/* @__PURE__ */
|
|
1499
|
-
/* @__PURE__ */
|
|
1500
|
-
profile.extends && /* @__PURE__ */
|
|
1580
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex w-full items-center justify-between", children: [
|
|
1581
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
|
|
1582
|
+
/* @__PURE__ */ jsx14("span", { className: "font-medium", children: profile.name }),
|
|
1583
|
+
profile.extends && /* @__PURE__ */ jsxs13(Badge, { variant: "secondary", className: "border-0 text-xs", children: [
|
|
1501
1584
|
"extends ",
|
|
1502
1585
|
profile.extends
|
|
1503
1586
|
] })
|
|
1504
1587
|
] }),
|
|
1505
|
-
selectedId === profile.id && /* @__PURE__ */
|
|
1588
|
+
selectedId === profile.id && /* @__PURE__ */ jsx14(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
1506
1589
|
] }),
|
|
1507
|
-
profile.description && /* @__PURE__ */
|
|
1590
|
+
profile.description && /* @__PURE__ */ jsx14("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description })
|
|
1508
1591
|
]
|
|
1509
1592
|
},
|
|
1510
1593
|
profile.id
|
|
1511
1594
|
))
|
|
1512
1595
|
] }),
|
|
1513
|
-
customProfiles.length > 0 && /* @__PURE__ */
|
|
1514
|
-
/* @__PURE__ */
|
|
1515
|
-
/* @__PURE__ */
|
|
1516
|
-
customProfiles.map((profile) => /* @__PURE__ */
|
|
1596
|
+
customProfiles.length > 0 && /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
1597
|
+
/* @__PURE__ */ jsx14(DropdownMenuSeparator4, {}),
|
|
1598
|
+
/* @__PURE__ */ jsx14(DropdownMenuLabel2, { children: "Custom Profiles" }),
|
|
1599
|
+
customProfiles.map((profile) => /* @__PURE__ */ jsxs13(
|
|
1517
1600
|
DropdownMenuItem4,
|
|
1518
1601
|
{
|
|
1519
1602
|
onClick: () => onSelect(profile),
|
|
1520
1603
|
className: "flex flex-col items-start gap-1",
|
|
1521
1604
|
children: [
|
|
1522
|
-
/* @__PURE__ */
|
|
1523
|
-
/* @__PURE__ */
|
|
1524
|
-
/* @__PURE__ */
|
|
1525
|
-
profile.model && /* @__PURE__ */
|
|
1605
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex w-full items-center justify-between", children: [
|
|
1606
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
|
|
1607
|
+
/* @__PURE__ */ jsx14("span", { className: "font-medium", children: profile.name }),
|
|
1608
|
+
profile.model && /* @__PURE__ */ jsx14(Badge, { variant: "secondary", className: "border-0 text-xs", children: profile.model.split("/").pop() })
|
|
1526
1609
|
] }),
|
|
1527
|
-
selectedId === profile.id && /* @__PURE__ */
|
|
1610
|
+
selectedId === profile.id && /* @__PURE__ */ jsx14(Check2, { className: "h-4 w-4 text-[var(--surface-success-text)]" })
|
|
1528
1611
|
] }),
|
|
1529
|
-
profile.description && /* @__PURE__ */
|
|
1530
|
-
showMetrics && profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */
|
|
1531
|
-
/* @__PURE__ */
|
|
1612
|
+
profile.description && /* @__PURE__ */ jsx14("span", { className: "line-clamp-1 text-muted-foreground text-xs", children: profile.description }),
|
|
1613
|
+
showMetrics && profile.metrics && profile.metrics.total_runs > 0 && /* @__PURE__ */ jsxs13("div", { className: "flex gap-3 text-muted-foreground text-xs", children: [
|
|
1614
|
+
/* @__PURE__ */ jsxs13("span", { children: [
|
|
1532
1615
|
profile.metrics.total_runs,
|
|
1533
1616
|
" runs"
|
|
1534
1617
|
] }),
|
|
1535
|
-
/* @__PURE__ */
|
|
1618
|
+
/* @__PURE__ */ jsxs13("span", { children: [
|
|
1536
1619
|
profile.metrics.success_rate.toFixed(0),
|
|
1537
1620
|
"% success"
|
|
1538
1621
|
] }),
|
|
1539
|
-
/* @__PURE__ */
|
|
1622
|
+
/* @__PURE__ */ jsxs13("span", { children: [
|
|
1540
1623
|
"~",
|
|
1541
1624
|
(profile.metrics.avg_duration_ms / 1e3).toFixed(1),
|
|
1542
1625
|
"s avg"
|
|
@@ -1547,26 +1630,26 @@ function ProfileSelector({
|
|
|
1547
1630
|
profile.id
|
|
1548
1631
|
))
|
|
1549
1632
|
] }),
|
|
1550
|
-
(onCreateClick || onManageClick) && /* @__PURE__ */
|
|
1551
|
-
/* @__PURE__ */
|
|
1552
|
-
onCreateClick && /* @__PURE__ */
|
|
1633
|
+
(onCreateClick || onManageClick) && /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
1634
|
+
/* @__PURE__ */ jsx14(DropdownMenuSeparator4, {}),
|
|
1635
|
+
onCreateClick && /* @__PURE__ */ jsxs13(
|
|
1553
1636
|
DropdownMenuItem4,
|
|
1554
1637
|
{
|
|
1555
1638
|
onClick: onCreateClick,
|
|
1556
1639
|
className: "text-[var(--surface-info-text)]",
|
|
1557
1640
|
children: [
|
|
1558
|
-
/* @__PURE__ */
|
|
1641
|
+
/* @__PURE__ */ jsx14(Plus3, { className: "mr-2 h-4 w-4" }),
|
|
1559
1642
|
"Create New Profile"
|
|
1560
1643
|
]
|
|
1561
1644
|
}
|
|
1562
1645
|
),
|
|
1563
|
-
onManageClick && /* @__PURE__ */
|
|
1646
|
+
onManageClick && /* @__PURE__ */ jsxs13(
|
|
1564
1647
|
DropdownMenuItem4,
|
|
1565
1648
|
{
|
|
1566
1649
|
onClick: onManageClick,
|
|
1567
1650
|
className: "text-muted-foreground",
|
|
1568
1651
|
children: [
|
|
1569
|
-
/* @__PURE__ */
|
|
1652
|
+
/* @__PURE__ */ jsx14(Settings, { className: "mr-2 h-4 w-4" }),
|
|
1570
1653
|
"Manage Profiles"
|
|
1571
1654
|
]
|
|
1572
1655
|
}
|
|
@@ -1592,26 +1675,26 @@ function ProfileComparison({
|
|
|
1592
1675
|
const fastestProfile = profilesWithMetrics.reduce(
|
|
1593
1676
|
(best, p) => (p.metrics?.avg_duration_ms ?? Number.POSITIVE_INFINITY) < (best.metrics?.avg_duration_ms ?? Number.POSITIVE_INFINITY) ? p : best
|
|
1594
1677
|
);
|
|
1595
|
-
return /* @__PURE__ */
|
|
1596
|
-
/* @__PURE__ */
|
|
1597
|
-
/* @__PURE__ */
|
|
1678
|
+
return /* @__PURE__ */ jsxs13("div", { className: `rounded-lg border border-border p-4 ${className ?? ""}`, children: [
|
|
1679
|
+
/* @__PURE__ */ jsx14("h4", { className: "mb-3 font-medium text-sm", children: "Profile Performance" }),
|
|
1680
|
+
/* @__PURE__ */ jsx14("div", { className: "space-y-3", children: profilesWithMetrics.map((profile) => {
|
|
1598
1681
|
const isBestSuccess = profile.id === bestSuccess.id;
|
|
1599
1682
|
const isFastest = profile.id === fastestProfile.id;
|
|
1600
|
-
return /* @__PURE__ */
|
|
1683
|
+
return /* @__PURE__ */ jsxs13(
|
|
1601
1684
|
"div",
|
|
1602
1685
|
{
|
|
1603
1686
|
className: "flex items-center justify-between gap-4",
|
|
1604
1687
|
children: [
|
|
1605
|
-
/* @__PURE__ */
|
|
1606
|
-
/* @__PURE__ */
|
|
1607
|
-
isBestSuccess && /* @__PURE__ */
|
|
1608
|
-
isFastest && !isBestSuccess && /* @__PURE__ */
|
|
1688
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
|
|
1689
|
+
/* @__PURE__ */ jsx14("span", { className: "font-medium", children: profile.name }),
|
|
1690
|
+
isBestSuccess && /* @__PURE__ */ jsx14(Badge, { className: "border border-[var(--surface-success-border)] bg-[var(--surface-success-bg)] text-[var(--surface-success-text)] text-xs", children: "Best Success" }),
|
|
1691
|
+
isFastest && !isBestSuccess && /* @__PURE__ */ jsx14(Badge, { className: "border border-[var(--surface-info-border)] bg-[var(--surface-info-bg)] text-[var(--surface-info-text)] text-xs", children: "Fastest" })
|
|
1609
1692
|
] }),
|
|
1610
|
-
/* @__PURE__ */
|
|
1611
|
-
/* @__PURE__ */
|
|
1612
|
-
/* @__PURE__ */
|
|
1693
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-4 text-sm", children: [
|
|
1694
|
+
/* @__PURE__ */ jsxs13("span", { children: [
|
|
1695
|
+
/* @__PURE__ */ jsx14("span", { className: "text-muted-foreground", children: "Success:" }),
|
|
1613
1696
|
" ",
|
|
1614
|
-
/* @__PURE__ */
|
|
1697
|
+
/* @__PURE__ */ jsxs13(
|
|
1615
1698
|
"span",
|
|
1616
1699
|
{
|
|
1617
1700
|
className: (profile.metrics?.success_rate ?? 0) >= 80 ? "text-[var(--surface-success-text)]" : (profile.metrics?.success_rate ?? 0) >= 50 ? "text-[var(--surface-warning-text)]" : "text-[var(--surface-danger-text)]",
|
|
@@ -1622,13 +1705,13 @@ function ProfileComparison({
|
|
|
1622
1705
|
}
|
|
1623
1706
|
)
|
|
1624
1707
|
] }),
|
|
1625
|
-
/* @__PURE__ */
|
|
1626
|
-
/* @__PURE__ */
|
|
1708
|
+
/* @__PURE__ */ jsxs13("span", { children: [
|
|
1709
|
+
/* @__PURE__ */ jsx14("span", { className: "text-muted-foreground", children: "Avg:" }),
|
|
1627
1710
|
" ",
|
|
1628
1711
|
((profile.metrics?.avg_duration_ms ?? 0) / 1e3).toFixed(1),
|
|
1629
1712
|
"s"
|
|
1630
1713
|
] }),
|
|
1631
|
-
/* @__PURE__ */
|
|
1714
|
+
/* @__PURE__ */ jsxs13("span", { className: "text-muted-foreground", children: [
|
|
1632
1715
|
profile.metrics?.total_runs,
|
|
1633
1716
|
" runs"
|
|
1634
1717
|
] })
|
|
@@ -1642,8 +1725,8 @@ function ProfileComparison({
|
|
|
1642
1725
|
}
|
|
1643
1726
|
|
|
1644
1727
|
// src/dashboard/metric-area-chart.tsx
|
|
1645
|
-
import * as
|
|
1646
|
-
import { jsx as
|
|
1728
|
+
import * as React6 from "react";
|
|
1729
|
+
import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1647
1730
|
var TONE_VARS = {
|
|
1648
1731
|
primary: "var(--brand-primary, hsl(var(--primary)))",
|
|
1649
1732
|
success: "var(--status-running, #22c55e)",
|
|
@@ -1689,7 +1772,7 @@ function MetricAreaChart({
|
|
|
1689
1772
|
emptyState,
|
|
1690
1773
|
className
|
|
1691
1774
|
}) {
|
|
1692
|
-
const gradientId =
|
|
1775
|
+
const gradientId = React6.useId();
|
|
1693
1776
|
const width = 400;
|
|
1694
1777
|
const values = points.map((p) => p.value).filter((v) => v !== null);
|
|
1695
1778
|
const latest = values.length > 0 ? values[values.length - 1] : null;
|
|
@@ -1697,7 +1780,7 @@ function MetricAreaChart({
|
|
|
1697
1780
|
const yMax = maxValue ?? (observedMax > 0 ? observedMax * 1.1 : 1);
|
|
1698
1781
|
const segments = buildSegments(points, width, height, yMax);
|
|
1699
1782
|
const color = TONE_VARS[tone];
|
|
1700
|
-
return /* @__PURE__ */
|
|
1783
|
+
return /* @__PURE__ */ jsxs14(
|
|
1701
1784
|
"div",
|
|
1702
1785
|
{
|
|
1703
1786
|
className: cn(
|
|
@@ -1706,21 +1789,21 @@ function MetricAreaChart({
|
|
|
1706
1789
|
),
|
|
1707
1790
|
"data-testid": `metric-chart-${label.toLowerCase().replace(/\s+/g, "-")}`,
|
|
1708
1791
|
children: [
|
|
1709
|
-
/* @__PURE__ */
|
|
1710
|
-
/* @__PURE__ */
|
|
1711
|
-
/* @__PURE__ */
|
|
1712
|
-
/* @__PURE__ */
|
|
1713
|
-
detail && /* @__PURE__ */
|
|
1792
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-baseline justify-between gap-3", children: [
|
|
1793
|
+
/* @__PURE__ */ jsx15("p", { className: "font-medium text-muted-foreground text-xs uppercase tracking-[0.12em]", children: label }),
|
|
1794
|
+
/* @__PURE__ */ jsxs14("div", { className: "text-right", children: [
|
|
1795
|
+
/* @__PURE__ */ jsx15("span", { className: "font-semibold text-foreground text-xl tabular-nums tracking-tight", children: latest === null ? "\u2014" : formatValue(latest) }),
|
|
1796
|
+
detail && /* @__PURE__ */ jsx15("span", { className: "ml-1.5 text-muted-foreground text-xs", children: detail })
|
|
1714
1797
|
] })
|
|
1715
1798
|
] }),
|
|
1716
|
-
/* @__PURE__ */
|
|
1799
|
+
/* @__PURE__ */ jsx15("div", { className: "mt-3", children: values.length === 0 ? /* @__PURE__ */ jsx15(
|
|
1717
1800
|
"div",
|
|
1718
1801
|
{
|
|
1719
1802
|
className: "flex items-center justify-center text-muted-foreground text-xs",
|
|
1720
1803
|
style: { height },
|
|
1721
1804
|
children: emptyState ?? "Waiting for samples\u2026"
|
|
1722
1805
|
}
|
|
1723
|
-
) : /* @__PURE__ */
|
|
1806
|
+
) : /* @__PURE__ */ jsxs14(
|
|
1724
1807
|
"svg",
|
|
1725
1808
|
{
|
|
1726
1809
|
viewBox: `0 0 ${width} ${height}`,
|
|
@@ -1730,7 +1813,7 @@ function MetricAreaChart({
|
|
|
1730
1813
|
role: "img",
|
|
1731
1814
|
"aria-label": `${label} chart`,
|
|
1732
1815
|
children: [
|
|
1733
|
-
[0.25, 0.5, 0.75].map((fraction) => /* @__PURE__ */
|
|
1816
|
+
[0.25, 0.5, 0.75].map((fraction) => /* @__PURE__ */ jsx15(
|
|
1734
1817
|
"line",
|
|
1735
1818
|
{
|
|
1736
1819
|
x1: 0,
|
|
@@ -1745,13 +1828,13 @@ function MetricAreaChart({
|
|
|
1745
1828
|
},
|
|
1746
1829
|
fraction
|
|
1747
1830
|
)),
|
|
1748
|
-
/* @__PURE__ */
|
|
1749
|
-
/* @__PURE__ */
|
|
1750
|
-
/* @__PURE__ */
|
|
1831
|
+
/* @__PURE__ */ jsx15("defs", { children: /* @__PURE__ */ jsxs14("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
1832
|
+
/* @__PURE__ */ jsx15("stop", { offset: "0%", stopColor: color, stopOpacity: 0.28 }),
|
|
1833
|
+
/* @__PURE__ */ jsx15("stop", { offset: "100%", stopColor: color, stopOpacity: 0.02 })
|
|
1751
1834
|
] }) }),
|
|
1752
|
-
segments.map((segment) => /* @__PURE__ */
|
|
1753
|
-
/* @__PURE__ */
|
|
1754
|
-
/* @__PURE__ */
|
|
1835
|
+
segments.map((segment) => /* @__PURE__ */ jsxs14(React6.Fragment, { children: [
|
|
1836
|
+
/* @__PURE__ */ jsx15("path", { d: segment.area, fill: `url(#${gradientId})` }),
|
|
1837
|
+
/* @__PURE__ */ jsx15(
|
|
1755
1838
|
"path",
|
|
1756
1839
|
{
|
|
1757
1840
|
d: segment.path,
|
|
@@ -1767,9 +1850,9 @@ function MetricAreaChart({
|
|
|
1767
1850
|
]
|
|
1768
1851
|
}
|
|
1769
1852
|
) }),
|
|
1770
|
-
/* @__PURE__ */
|
|
1771
|
-
/* @__PURE__ */
|
|
1772
|
-
/* @__PURE__ */
|
|
1853
|
+
/* @__PURE__ */ jsxs14("div", { className: "mt-1.5 flex justify-between text-[10px] text-muted-foreground tabular-nums", children: [
|
|
1854
|
+
/* @__PURE__ */ jsx15("span", { children: values.length > 0 ? formatValue(0) : "" }),
|
|
1855
|
+
/* @__PURE__ */ jsx15("span", { children: values.length > 0 ? formatValue(yMax) : "" })
|
|
1773
1856
|
] })
|
|
1774
1857
|
]
|
|
1775
1858
|
}
|
|
@@ -1789,7 +1872,7 @@ import {
|
|
|
1789
1872
|
} from "lucide-react";
|
|
1790
1873
|
import { Button as Button3 } from "@tangle-network/ui/primitives";
|
|
1791
1874
|
import { Badge as Badge2 } from "@tangle-network/ui/primitives";
|
|
1792
|
-
import { Fragment as Fragment10, jsx as
|
|
1875
|
+
import { Fragment as Fragment10, jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1793
1876
|
var statusConfig = {
|
|
1794
1877
|
pending: {
|
|
1795
1878
|
icon: Clock3,
|
|
@@ -1873,19 +1956,19 @@ function VariantList({
|
|
|
1873
1956
|
isActioning,
|
|
1874
1957
|
className
|
|
1875
1958
|
}) {
|
|
1876
|
-
return /* @__PURE__ */
|
|
1959
|
+
return /* @__PURE__ */ jsx16("div", { className: `space-y-2 ${className || ""}`, children: variants.map((variant) => {
|
|
1877
1960
|
const status = statusConfig[variant.status];
|
|
1878
1961
|
const StatusIcon = status.icon;
|
|
1879
1962
|
const isSelected = variant.id === selectedId;
|
|
1880
|
-
return /* @__PURE__ */
|
|
1963
|
+
return /* @__PURE__ */ jsxs15(
|
|
1881
1964
|
"div",
|
|
1882
1965
|
{
|
|
1883
1966
|
className: `cursor-pointer rounded-lg border px-3 py-2.5 transition-colors ${isSelected ? "border-primary/30 bg-[var(--accent-surface-soft)]" : "border-border bg-card hover:border-primary/20 hover:bg-muted/50"}`,
|
|
1884
1967
|
onClick: () => onSelect?.(variant.id),
|
|
1885
1968
|
children: [
|
|
1886
|
-
/* @__PURE__ */
|
|
1887
|
-
/* @__PURE__ */
|
|
1888
|
-
/* @__PURE__ */
|
|
1969
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2", children: [
|
|
1970
|
+
/* @__PURE__ */ jsxs15(Badge2, { className: `shrink-0 ${status.bg} ${status.border} ${status.color}`, children: [
|
|
1971
|
+
/* @__PURE__ */ jsx16(
|
|
1889
1972
|
StatusIcon,
|
|
1890
1973
|
{
|
|
1891
1974
|
className: `mr-1 h-3 w-3 ${status.animate ? "animate-spin" : ""}`
|
|
@@ -1893,27 +1976,27 @@ function VariantList({
|
|
|
1893
1976
|
),
|
|
1894
1977
|
status.label
|
|
1895
1978
|
] }),
|
|
1896
|
-
/* @__PURE__ */
|
|
1897
|
-
variant.sublabel && /* @__PURE__ */
|
|
1979
|
+
/* @__PURE__ */ jsx16("span", { className: "truncate text-sm font-medium text-foreground", children: variant.label }),
|
|
1980
|
+
variant.sublabel && /* @__PURE__ */ jsxs15("span", { className: "shrink-0 text-xs text-muted-foreground", children: [
|
|
1898
1981
|
"(",
|
|
1899
1982
|
variant.sublabel,
|
|
1900
1983
|
")"
|
|
1901
1984
|
] }),
|
|
1902
|
-
variant.durationMs && /* @__PURE__ */
|
|
1903
|
-
/* @__PURE__ */
|
|
1985
|
+
variant.durationMs && /* @__PURE__ */ jsxs15("span", { className: "flex shrink-0 items-center gap-1 text-xs text-muted-foreground", children: [
|
|
1986
|
+
/* @__PURE__ */ jsx16(Timer, { className: "h-3 w-3" }),
|
|
1904
1987
|
(variant.durationMs / 1e3).toFixed(1),
|
|
1905
1988
|
"s"
|
|
1906
1989
|
] }),
|
|
1907
|
-
/* @__PURE__ */
|
|
1908
|
-
variant.outcome && /* @__PURE__ */
|
|
1990
|
+
/* @__PURE__ */ jsxs15("div", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: [
|
|
1991
|
+
variant.outcome && /* @__PURE__ */ jsx16(
|
|
1909
1992
|
Badge2,
|
|
1910
1993
|
{
|
|
1911
1994
|
className: `${outcomeConfig[variant.outcome].bg} ${outcomeConfig[variant.outcome].border} ${outcomeConfig[variant.outcome].color}`,
|
|
1912
1995
|
children: outcomeConfig[variant.outcome].label
|
|
1913
1996
|
}
|
|
1914
1997
|
),
|
|
1915
|
-
variant.status === "completed" && variant.outcome === "pending_review" && onAccept && onReject && /* @__PURE__ */
|
|
1916
|
-
/* @__PURE__ */
|
|
1998
|
+
variant.status === "completed" && variant.outcome === "pending_review" && onAccept && onReject && /* @__PURE__ */ jsxs15(Fragment10, { children: [
|
|
1999
|
+
/* @__PURE__ */ jsxs15(
|
|
1917
2000
|
Button3,
|
|
1918
2001
|
{
|
|
1919
2002
|
variant: "outline",
|
|
@@ -1925,12 +2008,12 @@ function VariantList({
|
|
|
1925
2008
|
},
|
|
1926
2009
|
disabled: isActioning === variant.id,
|
|
1927
2010
|
children: [
|
|
1928
|
-
/* @__PURE__ */
|
|
2011
|
+
/* @__PURE__ */ jsx16(Check3, { className: "mr-1 h-3 w-3" }),
|
|
1929
2012
|
"Accept"
|
|
1930
2013
|
]
|
|
1931
2014
|
}
|
|
1932
2015
|
),
|
|
1933
|
-
/* @__PURE__ */
|
|
2016
|
+
/* @__PURE__ */ jsxs15(
|
|
1934
2017
|
Button3,
|
|
1935
2018
|
{
|
|
1936
2019
|
variant: "outline",
|
|
@@ -1942,13 +2025,13 @@ function VariantList({
|
|
|
1942
2025
|
},
|
|
1943
2026
|
disabled: isActioning === variant.id,
|
|
1944
2027
|
children: [
|
|
1945
|
-
/* @__PURE__ */
|
|
2028
|
+
/* @__PURE__ */ jsx16(X, { className: "mr-1 h-3 w-3" }),
|
|
1946
2029
|
"Reject"
|
|
1947
2030
|
]
|
|
1948
2031
|
}
|
|
1949
2032
|
)
|
|
1950
2033
|
] }),
|
|
1951
|
-
variant.detailsUrl && /* @__PURE__ */
|
|
2034
|
+
variant.detailsUrl && /* @__PURE__ */ jsx16(
|
|
1952
2035
|
Button3,
|
|
1953
2036
|
{
|
|
1954
2037
|
variant: "ghost",
|
|
@@ -1958,13 +2041,13 @@ function VariantList({
|
|
|
1958
2041
|
e.stopPropagation();
|
|
1959
2042
|
window.open(variant.detailsUrl, "_blank");
|
|
1960
2043
|
},
|
|
1961
|
-
children: /* @__PURE__ */
|
|
2044
|
+
children: /* @__PURE__ */ jsx16(ExternalLink2, { className: "h-3.5 w-3.5" })
|
|
1962
2045
|
}
|
|
1963
2046
|
)
|
|
1964
2047
|
] })
|
|
1965
2048
|
] }),
|
|
1966
|
-
variant.error && /* @__PURE__ */
|
|
1967
|
-
variant.summary && /* @__PURE__ */
|
|
2049
|
+
variant.error && /* @__PURE__ */ jsx16("p", { className: "mt-1.5 text-xs text-[var(--surface-danger-text)]", children: variant.error }),
|
|
2050
|
+
variant.summary && /* @__PURE__ */ jsx16("p", { className: "mt-1.5 line-clamp-2 text-xs text-muted-foreground", children: variant.summary })
|
|
1968
2051
|
]
|
|
1969
2052
|
},
|
|
1970
2053
|
variant.id
|
|
@@ -1975,7 +2058,7 @@ function VariantList({
|
|
|
1975
2058
|
// src/dashboard/system-logs.tsx
|
|
1976
2059
|
import { Terminal as Terminal3 } from "lucide-react";
|
|
1977
2060
|
import { useEffect as useEffect2, useRef as useRef2, useState as useState4 } from "react";
|
|
1978
|
-
import { jsx as
|
|
2061
|
+
import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1979
2062
|
function SystemLogsViewer({ apiUrl, token, className }) {
|
|
1980
2063
|
const [logs, setLogs] = useState4([]);
|
|
1981
2064
|
const [error, setError] = useState4(null);
|
|
@@ -2028,18 +2111,18 @@ function SystemLogsViewer({ apiUrl, token, className }) {
|
|
|
2028
2111
|
const isAtBottom = scrollHeight - scrollTop - clientHeight < 20;
|
|
2029
2112
|
setIsFollowing((prev) => prev === isAtBottom ? prev : isAtBottom);
|
|
2030
2113
|
};
|
|
2031
|
-
return /* @__PURE__ */
|
|
2032
|
-
/* @__PURE__ */
|
|
2033
|
-
/* @__PURE__ */
|
|
2034
|
-
/* @__PURE__ */
|
|
2035
|
-
/* @__PURE__ */
|
|
2114
|
+
return /* @__PURE__ */ jsxs16("div", { className: cn("flex flex-col h-full bg-background text-foreground font-mono text-sm leading-relaxed overflow-hidden rounded-lg border border-border", className), children: [
|
|
2115
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex-none flex items-center justify-between border-b border-border bg-muted/50 backdrop-blur-md px-4 py-2", children: [
|
|
2116
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2", children: [
|
|
2117
|
+
/* @__PURE__ */ jsx17(Terminal3, { className: "h-4 w-4 text-primary animate-pulse" }),
|
|
2118
|
+
/* @__PURE__ */ jsx17("span", { className: "font-bold text-xs uppercase tracking-widest text-muted-foreground", children: "System Traces" })
|
|
2036
2119
|
] }),
|
|
2037
|
-
/* @__PURE__ */
|
|
2038
|
-
error && /* @__PURE__ */
|
|
2039
|
-
/* @__PURE__ */
|
|
2120
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-3", children: [
|
|
2121
|
+
error && /* @__PURE__ */ jsxs16("span", { className: "text-destructive text-xs flex items-center gap-1", children: [
|
|
2122
|
+
/* @__PURE__ */ jsx17("span", { className: "w-2 h-2 rounded-full bg-destructive animate-ping" }),
|
|
2040
2123
|
" Error fetching logs"
|
|
2041
2124
|
] }),
|
|
2042
|
-
/* @__PURE__ */
|
|
2125
|
+
/* @__PURE__ */ jsx17(
|
|
2043
2126
|
"button",
|
|
2044
2127
|
{
|
|
2045
2128
|
onClick: () => {
|
|
@@ -2054,29 +2137,29 @@ function SystemLogsViewer({ apiUrl, token, className }) {
|
|
|
2054
2137
|
)
|
|
2055
2138
|
] })
|
|
2056
2139
|
] }),
|
|
2057
|
-
/* @__PURE__ */
|
|
2140
|
+
/* @__PURE__ */ jsx17(
|
|
2058
2141
|
"div",
|
|
2059
2142
|
{
|
|
2060
2143
|
ref: scrollRef,
|
|
2061
2144
|
onScroll: handleScroll,
|
|
2062
2145
|
className: "flex-1 overflow-y-auto p-4 space-y-1",
|
|
2063
|
-
children: logs.length === 0 && !error ? /* @__PURE__ */
|
|
2064
|
-
/* @__PURE__ */
|
|
2146
|
+
children: logs.length === 0 && !error ? /* @__PURE__ */ jsx17("div", { className: "flex h-full items-center justify-center text-muted-foreground italic", children: "Waiting for orchestrator logs..." }) : logs.map((log, i) => /* @__PURE__ */ jsxs16("div", { className: "break-words", children: [
|
|
2147
|
+
/* @__PURE__ */ jsxs16("span", { className: "text-muted-foreground mr-3 select-none", children: [
|
|
2065
2148
|
"[",
|
|
2066
2149
|
log.timestamp || i.toString().padStart(4, "0"),
|
|
2067
2150
|
"]"
|
|
2068
2151
|
] }),
|
|
2069
|
-
/* @__PURE__ */
|
|
2152
|
+
/* @__PURE__ */ jsxs16("span", { className: "text-primary/70 mr-2", children: [
|
|
2070
2153
|
"[",
|
|
2071
2154
|
log.level,
|
|
2072
2155
|
"]"
|
|
2073
2156
|
] }),
|
|
2074
|
-
/* @__PURE__ */
|
|
2157
|
+
/* @__PURE__ */ jsxs16("span", { className: "text-muted-foreground mr-2", children: [
|
|
2075
2158
|
"[",
|
|
2076
2159
|
log.scope,
|
|
2077
2160
|
"]"
|
|
2078
2161
|
] }),
|
|
2079
|
-
/* @__PURE__ */
|
|
2162
|
+
/* @__PURE__ */ jsx17("span", { className: log.level.toUpperCase() === "ERROR" || log.message.toLowerCase().includes("failed") ? "text-destructive" : log.level.toUpperCase() === "WARN" ? "text-warning" : "text-foreground", children: log.message })
|
|
2080
2163
|
] }, `${log.timestamp}-${log.scope}-${i}`))
|
|
2081
2164
|
}
|
|
2082
2165
|
)
|
|
@@ -2086,51 +2169,51 @@ function SystemLogsViewer({ apiUrl, token, className }) {
|
|
|
2086
2169
|
// src/dashboard/usage-summary.tsx
|
|
2087
2170
|
import { Clock as Clock4, Layers, MessageSquare, DollarSign } from "lucide-react";
|
|
2088
2171
|
import { StatCard } from "@tangle-network/ui/primitives";
|
|
2089
|
-
import { Skeleton as
|
|
2090
|
-
import { jsx as
|
|
2172
|
+
import { Skeleton as Skeleton4 } from "@tangle-network/ui/primitives";
|
|
2173
|
+
import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2091
2174
|
function UsageSummary({ data, loading = false, className }) {
|
|
2092
2175
|
if (loading || !data) {
|
|
2093
|
-
return /* @__PURE__ */
|
|
2176
|
+
return /* @__PURE__ */ jsx18("div", { className: cn("grid grid-cols-2 gap-4 lg:grid-cols-4", className), children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsx18(Skeleton4, { className: "h-28 rounded-xl" }, i)) });
|
|
2094
2177
|
}
|
|
2095
|
-
return /* @__PURE__ */
|
|
2096
|
-
/* @__PURE__ */
|
|
2178
|
+
return /* @__PURE__ */ jsxs17("div", { className: cn("grid grid-cols-2 gap-4 lg:grid-cols-4", className), children: [
|
|
2179
|
+
/* @__PURE__ */ jsx18(
|
|
2097
2180
|
StatCard,
|
|
2098
2181
|
{
|
|
2099
2182
|
variant: "sandbox",
|
|
2100
2183
|
title: "Compute Hours",
|
|
2101
2184
|
value: data.computeHours.toFixed(1),
|
|
2102
2185
|
subtitle: "This billing period",
|
|
2103
|
-
icon: /* @__PURE__ */
|
|
2186
|
+
icon: /* @__PURE__ */ jsx18(Clock4, { className: "h-5 w-5" })
|
|
2104
2187
|
}
|
|
2105
2188
|
),
|
|
2106
|
-
/* @__PURE__ */
|
|
2189
|
+
/* @__PURE__ */ jsx18(
|
|
2107
2190
|
StatCard,
|
|
2108
2191
|
{
|
|
2109
2192
|
variant: "sandbox",
|
|
2110
2193
|
title: "Active Sessions",
|
|
2111
2194
|
value: data.activeSessions,
|
|
2112
2195
|
subtitle: "Currently running",
|
|
2113
|
-
icon: /* @__PURE__ */
|
|
2196
|
+
icon: /* @__PURE__ */ jsx18(Layers, { className: "h-5 w-5" })
|
|
2114
2197
|
}
|
|
2115
2198
|
),
|
|
2116
|
-
/* @__PURE__ */
|
|
2199
|
+
/* @__PURE__ */ jsx18(
|
|
2117
2200
|
StatCard,
|
|
2118
2201
|
{
|
|
2119
2202
|
variant: "sandbox",
|
|
2120
2203
|
title: "Messages Sent",
|
|
2121
2204
|
value: data.messagesSent.toLocaleString(),
|
|
2122
2205
|
subtitle: "Agent interactions",
|
|
2123
|
-
icon: /* @__PURE__ */
|
|
2206
|
+
icon: /* @__PURE__ */ jsx18(MessageSquare, { className: "h-5 w-5" })
|
|
2124
2207
|
}
|
|
2125
2208
|
),
|
|
2126
|
-
/* @__PURE__ */
|
|
2209
|
+
/* @__PURE__ */ jsx18(
|
|
2127
2210
|
StatCard,
|
|
2128
2211
|
{
|
|
2129
2212
|
variant: "sandbox",
|
|
2130
2213
|
title: "Estimated Cost",
|
|
2131
2214
|
value: `$${data.estimatedCost.toFixed(2)}`,
|
|
2132
2215
|
subtitle: "This billing period",
|
|
2133
|
-
icon: /* @__PURE__ */
|
|
2216
|
+
icon: /* @__PURE__ */ jsx18(DollarSign, { className: "h-5 w-5" })
|
|
2134
2217
|
}
|
|
2135
2218
|
)
|
|
2136
2219
|
] });
|
|
@@ -2138,66 +2221,66 @@ function UsageSummary({ data, loading = false, className }) {
|
|
|
2138
2221
|
|
|
2139
2222
|
// src/dashboard/git-panel.tsx
|
|
2140
2223
|
import { GitBranch, GitCommit, FileEdit, FilePlus, File } from "lucide-react";
|
|
2141
|
-
import { jsx as
|
|
2224
|
+
import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2142
2225
|
function GitPanel({ status, log, loading = false, onRefresh, className }) {
|
|
2143
2226
|
if (loading) {
|
|
2144
|
-
return /* @__PURE__ */
|
|
2145
|
-
/* @__PURE__ */
|
|
2227
|
+
return /* @__PURE__ */ jsx19("div", { className: cn("rounded-lg border border-border bg-card p-5", className), children: /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
2228
|
+
/* @__PURE__ */ jsx19("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-primary border-t-transparent" }),
|
|
2146
2229
|
"Loading git info..."
|
|
2147
2230
|
] }) });
|
|
2148
2231
|
}
|
|
2149
2232
|
if (!status) {
|
|
2150
|
-
return /* @__PURE__ */
|
|
2151
|
-
/* @__PURE__ */
|
|
2233
|
+
return /* @__PURE__ */ jsx19("div", { className: cn("rounded-lg border border-border bg-card p-5", className), children: /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
2234
|
+
/* @__PURE__ */ jsx19(GitBranch, { className: "h-4 w-4" }),
|
|
2152
2235
|
"No git repository detected"
|
|
2153
2236
|
] }) });
|
|
2154
2237
|
}
|
|
2155
2238
|
const changedCount = status.staged.length + status.modified.length + status.untracked.length;
|
|
2156
|
-
return /* @__PURE__ */
|
|
2157
|
-
/* @__PURE__ */
|
|
2158
|
-
/* @__PURE__ */
|
|
2159
|
-
/* @__PURE__ */
|
|
2160
|
-
/* @__PURE__ */
|
|
2161
|
-
status.isDirty && /* @__PURE__ */
|
|
2239
|
+
return /* @__PURE__ */ jsxs18("div", { className: cn("rounded-lg border border-border bg-card overflow-hidden", className), children: [
|
|
2240
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center justify-between border-b border-border bg-muted/30 px-4 py-3", children: [
|
|
2241
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2", children: [
|
|
2242
|
+
/* @__PURE__ */ jsx19(GitBranch, { className: "h-4 w-4 text-primary" }),
|
|
2243
|
+
/* @__PURE__ */ jsx19("span", { className: "text-sm font-bold text-foreground", children: status.branch }),
|
|
2244
|
+
status.isDirty && /* @__PURE__ */ jsxs18("span", { className: "rounded-full bg-[var(--surface-warning-bg)] px-1.5 py-0.5 text-[10px] font-bold text-[var(--surface-warning-text)]", children: [
|
|
2162
2245
|
changedCount,
|
|
2163
2246
|
" change",
|
|
2164
2247
|
changedCount !== 1 ? "s" : ""
|
|
2165
2248
|
] })
|
|
2166
2249
|
] }),
|
|
2167
|
-
onRefresh && /* @__PURE__ */
|
|
2250
|
+
onRefresh && /* @__PURE__ */ jsx19("button", { type: "button", onClick: onRefresh, className: "text-xs text-muted-foreground hover:text-foreground transition-colors", children: "Refresh" })
|
|
2168
2251
|
] }),
|
|
2169
|
-
changedCount > 0 && /* @__PURE__ */
|
|
2170
|
-
status.staged.map((f) => /* @__PURE__ */
|
|
2171
|
-
/* @__PURE__ */
|
|
2172
|
-
/* @__PURE__ */
|
|
2173
|
-
/* @__PURE__ */
|
|
2252
|
+
changedCount > 0 && /* @__PURE__ */ jsx19("div", { className: "border-b border-border px-4 py-3", children: /* @__PURE__ */ jsxs18("div", { className: "space-y-1.5", children: [
|
|
2253
|
+
status.staged.map((f) => /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2254
|
+
/* @__PURE__ */ jsx19(FilePlus, { className: "h-3 w-3 text-[var(--surface-success-text)]" }),
|
|
2255
|
+
/* @__PURE__ */ jsx19("span", { className: "font-mono text-foreground truncate", children: f }),
|
|
2256
|
+
/* @__PURE__ */ jsx19("span", { className: "text-[var(--surface-success-text)] text-[10px] font-bold ml-auto", children: "STAGED" })
|
|
2174
2257
|
] }, `s-${f}`)),
|
|
2175
|
-
status.modified.map((f) => /* @__PURE__ */
|
|
2176
|
-
/* @__PURE__ */
|
|
2177
|
-
/* @__PURE__ */
|
|
2258
|
+
status.modified.map((f) => /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2259
|
+
/* @__PURE__ */ jsx19(FileEdit, { className: "h-3 w-3 text-[var(--surface-warning-text)]" }),
|
|
2260
|
+
/* @__PURE__ */ jsx19("span", { className: "font-mono text-foreground truncate", children: f })
|
|
2178
2261
|
] }, `m-${f}`)),
|
|
2179
|
-
status.untracked.map((f) => /* @__PURE__ */
|
|
2180
|
-
/* @__PURE__ */
|
|
2181
|
-
/* @__PURE__ */
|
|
2262
|
+
status.untracked.map((f) => /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2263
|
+
/* @__PURE__ */ jsx19(File, { className: "h-3 w-3 text-muted-foreground" }),
|
|
2264
|
+
/* @__PURE__ */ jsx19("span", { className: "font-mono text-muted-foreground truncate", children: f })
|
|
2182
2265
|
] }, `u-${f}`))
|
|
2183
2266
|
] }) }),
|
|
2184
|
-
log.length > 0 && /* @__PURE__ */
|
|
2185
|
-
/* @__PURE__ */
|
|
2186
|
-
/* @__PURE__ */
|
|
2187
|
-
/* @__PURE__ */
|
|
2188
|
-
/* @__PURE__ */
|
|
2189
|
-
/* @__PURE__ */
|
|
2190
|
-
/* @__PURE__ */
|
|
2267
|
+
log.length > 0 && /* @__PURE__ */ jsxs18("div", { className: "px-4 py-3", children: [
|
|
2268
|
+
/* @__PURE__ */ jsx19("div", { className: "mb-2 text-[10px] font-bold uppercase tracking-widest text-muted-foreground", children: "Recent Commits" }),
|
|
2269
|
+
/* @__PURE__ */ jsx19("div", { className: "space-y-2", children: log.slice(0, 5).map((commit) => /* @__PURE__ */ jsxs18("div", { className: "flex items-start gap-2 text-xs", children: [
|
|
2270
|
+
/* @__PURE__ */ jsx19(GitCommit, { className: "h-3 w-3 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2271
|
+
/* @__PURE__ */ jsxs18("div", { className: "min-w-0", children: [
|
|
2272
|
+
/* @__PURE__ */ jsx19("span", { className: "font-mono text-primary mr-1.5", children: commit.shortSha }),
|
|
2273
|
+
/* @__PURE__ */ jsx19("span", { className: "text-foreground", children: commit.message })
|
|
2191
2274
|
] })
|
|
2192
2275
|
] }, commit.shortSha)) })
|
|
2193
2276
|
] }),
|
|
2194
|
-
(status.ahead > 0 || status.behind > 0) && /* @__PURE__ */
|
|
2195
|
-
status.ahead > 0 && /* @__PURE__ */
|
|
2277
|
+
(status.ahead > 0 || status.behind > 0) && /* @__PURE__ */ jsxs18("div", { className: "border-t border-border px-4 py-2 flex items-center gap-3 text-xs text-muted-foreground", children: [
|
|
2278
|
+
status.ahead > 0 && /* @__PURE__ */ jsxs18("span", { children: [
|
|
2196
2279
|
"\u2191 ",
|
|
2197
2280
|
status.ahead,
|
|
2198
2281
|
" ahead"
|
|
2199
2282
|
] }),
|
|
2200
|
-
status.behind > 0 && /* @__PURE__ */
|
|
2283
|
+
status.behind > 0 && /* @__PURE__ */ jsxs18("span", { children: [
|
|
2201
2284
|
"\u2193 ",
|
|
2202
2285
|
status.behind,
|
|
2203
2286
|
" behind"
|
|
@@ -2207,14 +2290,14 @@ function GitPanel({ status, log, loading = false, onRefresh, className }) {
|
|
|
2207
2290
|
}
|
|
2208
2291
|
|
|
2209
2292
|
// src/dashboard/ports-list.tsx
|
|
2210
|
-
import * as
|
|
2293
|
+
import * as React8 from "react";
|
|
2211
2294
|
import { Copy as Copy3, Check as Check4, Globe, Plus as Plus4, Trash2 as Trash23 } from "lucide-react";
|
|
2212
|
-
import { jsx as
|
|
2295
|
+
import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
2213
2296
|
function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, className }) {
|
|
2214
|
-
const [newPort, setNewPort] =
|
|
2215
|
-
const [copiedPort, setCopiedPort] =
|
|
2216
|
-
const copyTimerRef =
|
|
2217
|
-
|
|
2297
|
+
const [newPort, setNewPort] = React8.useState("");
|
|
2298
|
+
const [copiedPort, setCopiedPort] = React8.useState(null);
|
|
2299
|
+
const copyTimerRef = React8.useRef(null);
|
|
2300
|
+
React8.useEffect(() => {
|
|
2218
2301
|
return () => {
|
|
2219
2302
|
if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
|
|
2220
2303
|
};
|
|
@@ -2236,48 +2319,48 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2236
2319
|
setNewPort("");
|
|
2237
2320
|
}
|
|
2238
2321
|
};
|
|
2239
|
-
return /* @__PURE__ */
|
|
2240
|
-
ports.length > 0 ? /* @__PURE__ */
|
|
2241
|
-
/* @__PURE__ */
|
|
2242
|
-
/* @__PURE__ */
|
|
2243
|
-
/* @__PURE__ */
|
|
2244
|
-
/* @__PURE__ */
|
|
2245
|
-
/* @__PURE__ */
|
|
2322
|
+
return /* @__PURE__ */ jsxs19("div", { className: cn("space-y-4", className), children: [
|
|
2323
|
+
ports.length > 0 ? /* @__PURE__ */ jsx20("div", { className: "rounded-lg border border-border overflow-hidden", children: /* @__PURE__ */ jsxs19("table", { className: "w-full text-sm", children: [
|
|
2324
|
+
/* @__PURE__ */ jsx20("thead", { className: "bg-muted/30 border-b border-border", children: /* @__PURE__ */ jsxs19("tr", { children: [
|
|
2325
|
+
/* @__PURE__ */ jsx20("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Port" }),
|
|
2326
|
+
/* @__PURE__ */ jsx20("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Public URL" }),
|
|
2327
|
+
/* @__PURE__ */ jsx20("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Status" }),
|
|
2328
|
+
/* @__PURE__ */ jsx20("th", { className: "px-4 py-2.5 text-right text-xs font-medium text-muted-foreground w-20" })
|
|
2246
2329
|
] }) }),
|
|
2247
|
-
/* @__PURE__ */
|
|
2248
|
-
/* @__PURE__ */
|
|
2249
|
-
/* @__PURE__ */
|
|
2330
|
+
/* @__PURE__ */ jsx20("tbody", { className: "divide-y divide-border", children: ports.map((p) => /* @__PURE__ */ jsxs19("tr", { children: [
|
|
2331
|
+
/* @__PURE__ */ jsx20("td", { className: "px-4 py-3 font-mono text-xs text-foreground", children: p.port }),
|
|
2332
|
+
/* @__PURE__ */ jsx20("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsxs19(
|
|
2250
2333
|
"button",
|
|
2251
2334
|
{
|
|
2252
2335
|
type: "button",
|
|
2253
2336
|
onClick: () => handleCopy(p.url, p.port),
|
|
2254
2337
|
className: "flex items-center gap-2 font-mono text-xs text-primary hover:underline cursor-pointer group",
|
|
2255
2338
|
children: [
|
|
2256
|
-
/* @__PURE__ */
|
|
2257
|
-
copiedPort === p.port ? /* @__PURE__ */
|
|
2339
|
+
/* @__PURE__ */ jsx20("span", { className: "truncate max-w-[300px]", children: p.url }),
|
|
2340
|
+
copiedPort === p.port ? /* @__PURE__ */ jsx20(Check4, { className: "h-3 w-3 text-[var(--surface-success-text)] shrink-0" }) : /* @__PURE__ */ jsx20(Copy3, { className: "h-3 w-3 opacity-0 group-hover:opacity-100 transition-opacity shrink-0" })
|
|
2258
2341
|
]
|
|
2259
2342
|
}
|
|
2260
2343
|
) }),
|
|
2261
|
-
/* @__PURE__ */
|
|
2344
|
+
/* @__PURE__ */ jsx20("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx20("span", { className: cn(
|
|
2262
2345
|
"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider",
|
|
2263
2346
|
p.status === "active" ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : "bg-[var(--surface-warning-bg)] text-[var(--surface-warning-text)]"
|
|
2264
2347
|
), children: p.status }) }),
|
|
2265
|
-
/* @__PURE__ */
|
|
2348
|
+
/* @__PURE__ */ jsx20("td", { className: "px-4 py-3 text-right", children: onRemovePort && /* @__PURE__ */ jsx20(
|
|
2266
2349
|
"button",
|
|
2267
2350
|
{
|
|
2268
2351
|
type: "button",
|
|
2269
2352
|
onClick: () => onRemovePort(p.port),
|
|
2270
2353
|
className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
|
|
2271
|
-
children: /* @__PURE__ */
|
|
2354
|
+
children: /* @__PURE__ */ jsx20(Trash23, { className: "h-3.5 w-3.5" })
|
|
2272
2355
|
}
|
|
2273
2356
|
) })
|
|
2274
2357
|
] }, p.port)) })
|
|
2275
|
-
] }) }) : /* @__PURE__ */
|
|
2276
|
-
/* @__PURE__ */
|
|
2277
|
-
/* @__PURE__ */
|
|
2358
|
+
] }) }) : /* @__PURE__ */ jsxs19("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2359
|
+
/* @__PURE__ */ jsx20(Globe, { className: "mx-auto h-8 w-8 text-muted-foreground mb-2" }),
|
|
2360
|
+
/* @__PURE__ */ jsx20("p", { className: "text-sm text-muted-foreground", children: "No ports exposed yet" })
|
|
2278
2361
|
] }),
|
|
2279
|
-
/* @__PURE__ */
|
|
2280
|
-
/* @__PURE__ */
|
|
2362
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-3", children: [
|
|
2363
|
+
/* @__PURE__ */ jsx20(
|
|
2281
2364
|
"input",
|
|
2282
2365
|
{
|
|
2283
2366
|
type: "number",
|
|
@@ -2290,7 +2373,7 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2290
2373
|
className: "flex-1 rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
2291
2374
|
}
|
|
2292
2375
|
),
|
|
2293
|
-
/* @__PURE__ */
|
|
2376
|
+
/* @__PURE__ */ jsxs19(
|
|
2294
2377
|
"button",
|
|
2295
2378
|
{
|
|
2296
2379
|
type: "button",
|
|
@@ -2298,7 +2381,7 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2298
2381
|
disabled: !newPort || isExposing,
|
|
2299
2382
|
className: "inline-flex items-center gap-2 rounded-lg bg-primary/20 border border-primary/30 px-4 py-2 text-sm font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors disabled:opacity-50",
|
|
2300
2383
|
children: [
|
|
2301
|
-
/* @__PURE__ */
|
|
2384
|
+
/* @__PURE__ */ jsx20(Plus4, { className: "h-4 w-4" }),
|
|
2302
2385
|
"Expose"
|
|
2303
2386
|
]
|
|
2304
2387
|
}
|
|
@@ -2308,9 +2391,9 @@ function PortsList({ ports, onExposePort, onRemovePort, isExposing = false, clas
|
|
|
2308
2391
|
}
|
|
2309
2392
|
|
|
2310
2393
|
// src/dashboard/process-list.tsx
|
|
2311
|
-
import * as
|
|
2394
|
+
import * as React9 from "react";
|
|
2312
2395
|
import { Activity as Activity3, Plus as Plus5, Skull, Terminal as Terminal4 } from "lucide-react";
|
|
2313
|
-
import { jsx as
|
|
2396
|
+
import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
2314
2397
|
function formatUptime(startedAt) {
|
|
2315
2398
|
if (!startedAt) return "-";
|
|
2316
2399
|
const ms = Date.now() - new Date(startedAt).getTime();
|
|
@@ -2320,7 +2403,7 @@ function formatUptime(startedAt) {
|
|
|
2320
2403
|
return `${Math.floor(ms / 36e5)}h ${Math.floor(ms % 36e5 / 6e4)}m`;
|
|
2321
2404
|
}
|
|
2322
2405
|
function ProcessList({ processes, onSpawn, onKill, loading = false, className }) {
|
|
2323
|
-
const [newCommand, setNewCommand] =
|
|
2406
|
+
const [newCommand, setNewCommand] = React9.useState("");
|
|
2324
2407
|
const handleSpawn = () => {
|
|
2325
2408
|
const cmd = newCommand.trim();
|
|
2326
2409
|
if (cmd) {
|
|
@@ -2328,43 +2411,43 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2328
2411
|
setNewCommand("");
|
|
2329
2412
|
}
|
|
2330
2413
|
};
|
|
2331
|
-
return /* @__PURE__ */
|
|
2332
|
-
loading ? /* @__PURE__ */
|
|
2333
|
-
/* @__PURE__ */
|
|
2334
|
-
/* @__PURE__ */
|
|
2335
|
-
] }) : processes.length > 0 ? /* @__PURE__ */
|
|
2336
|
-
/* @__PURE__ */
|
|
2337
|
-
/* @__PURE__ */
|
|
2338
|
-
/* @__PURE__ */
|
|
2339
|
-
/* @__PURE__ */
|
|
2340
|
-
/* @__PURE__ */
|
|
2341
|
-
/* @__PURE__ */
|
|
2414
|
+
return /* @__PURE__ */ jsxs20("div", { className: cn("space-y-4", className), children: [
|
|
2415
|
+
loading ? /* @__PURE__ */ jsxs20("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2416
|
+
/* @__PURE__ */ jsx21(Activity3, { className: "mx-auto h-6 w-6 text-muted-foreground animate-spin mb-2" }),
|
|
2417
|
+
/* @__PURE__ */ jsx21("p", { className: "text-sm text-muted-foreground", children: "Loading processes..." })
|
|
2418
|
+
] }) : processes.length > 0 ? /* @__PURE__ */ jsx21("div", { className: "rounded-lg border border-border overflow-hidden", children: /* @__PURE__ */ jsxs20("table", { className: "w-full text-sm", children: [
|
|
2419
|
+
/* @__PURE__ */ jsx21("thead", { className: "bg-muted/30 border-b border-border", children: /* @__PURE__ */ jsxs20("tr", { children: [
|
|
2420
|
+
/* @__PURE__ */ jsx21("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "PID" }),
|
|
2421
|
+
/* @__PURE__ */ jsx21("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Command" }),
|
|
2422
|
+
/* @__PURE__ */ jsx21("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Status" }),
|
|
2423
|
+
/* @__PURE__ */ jsx21("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Uptime" }),
|
|
2424
|
+
/* @__PURE__ */ jsx21("th", { className: "px-4 py-2.5 text-right text-xs font-medium text-muted-foreground w-20" })
|
|
2342
2425
|
] }) }),
|
|
2343
|
-
/* @__PURE__ */
|
|
2344
|
-
/* @__PURE__ */
|
|
2345
|
-
/* @__PURE__ */
|
|
2346
|
-
/* @__PURE__ */
|
|
2426
|
+
/* @__PURE__ */ jsx21("tbody", { className: "divide-y divide-border", children: processes.map((p) => /* @__PURE__ */ jsxs20("tr", { children: [
|
|
2427
|
+
/* @__PURE__ */ jsx21("td", { className: "px-4 py-3 font-mono text-xs text-foreground", children: p.pid }),
|
|
2428
|
+
/* @__PURE__ */ jsx21("td", { className: "px-4 py-3 font-mono text-xs text-foreground truncate max-w-[250px]", children: p.command }),
|
|
2429
|
+
/* @__PURE__ */ jsx21("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx21("span", { className: cn(
|
|
2347
2430
|
"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider",
|
|
2348
2431
|
p.running ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : "bg-muted text-muted-foreground"
|
|
2349
2432
|
), children: p.running ? "running" : `exited (${p.exitCode ?? "?"})` }) }),
|
|
2350
|
-
/* @__PURE__ */
|
|
2351
|
-
/* @__PURE__ */
|
|
2433
|
+
/* @__PURE__ */ jsx21("td", { className: "px-4 py-3 font-mono text-xs text-muted-foreground", children: formatUptime(p.startedAt) }),
|
|
2434
|
+
/* @__PURE__ */ jsx21("td", { className: "px-4 py-3 text-right", children: p.running && /* @__PURE__ */ jsx21(
|
|
2352
2435
|
"button",
|
|
2353
2436
|
{
|
|
2354
2437
|
type: "button",
|
|
2355
2438
|
onClick: () => onKill(p.pid),
|
|
2356
2439
|
className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
|
|
2357
2440
|
title: "Kill process",
|
|
2358
|
-
children: /* @__PURE__ */
|
|
2441
|
+
children: /* @__PURE__ */ jsx21(Skull, { className: "h-3.5 w-3.5" })
|
|
2359
2442
|
}
|
|
2360
2443
|
) })
|
|
2361
2444
|
] }, `${p.pid}-${p.startedAt ?? p.command}`)) })
|
|
2362
|
-
] }) }) : /* @__PURE__ */
|
|
2363
|
-
/* @__PURE__ */
|
|
2364
|
-
/* @__PURE__ */
|
|
2445
|
+
] }) }) : /* @__PURE__ */ jsxs20("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2446
|
+
/* @__PURE__ */ jsx21(Terminal4, { className: "mx-auto h-8 w-8 text-muted-foreground mb-2" }),
|
|
2447
|
+
/* @__PURE__ */ jsx21("p", { className: "text-sm text-muted-foreground", children: "No processes running" })
|
|
2365
2448
|
] }),
|
|
2366
|
-
/* @__PURE__ */
|
|
2367
|
-
/* @__PURE__ */
|
|
2449
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-3", children: [
|
|
2450
|
+
/* @__PURE__ */ jsx21(
|
|
2368
2451
|
"input",
|
|
2369
2452
|
{
|
|
2370
2453
|
type: "text",
|
|
@@ -2375,7 +2458,7 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2375
2458
|
className: "flex-1 rounded-lg border border-border bg-background px-3 py-2 text-sm font-mono text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
2376
2459
|
}
|
|
2377
2460
|
),
|
|
2378
|
-
/* @__PURE__ */
|
|
2461
|
+
/* @__PURE__ */ jsxs20(
|
|
2379
2462
|
"button",
|
|
2380
2463
|
{
|
|
2381
2464
|
type: "button",
|
|
@@ -2383,7 +2466,7 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2383
2466
|
disabled: !newCommand.trim(),
|
|
2384
2467
|
className: "inline-flex items-center gap-2 rounded-lg bg-primary/20 border border-primary/30 px-4 py-2 text-sm font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors disabled:opacity-50",
|
|
2385
2468
|
children: [
|
|
2386
|
-
/* @__PURE__ */
|
|
2469
|
+
/* @__PURE__ */ jsx21(Plus5, { className: "h-4 w-4" }),
|
|
2387
2470
|
"Spawn"
|
|
2388
2471
|
]
|
|
2389
2472
|
}
|
|
@@ -2393,11 +2476,11 @@ function ProcessList({ processes, onSpawn, onKill, loading = false, className })
|
|
|
2393
2476
|
}
|
|
2394
2477
|
|
|
2395
2478
|
// src/dashboard/network-config.tsx
|
|
2396
|
-
import * as
|
|
2479
|
+
import * as React10 from "react";
|
|
2397
2480
|
import { Network as Network2, Plus as Plus6, Trash2 as Trash24, ShieldAlert } from "lucide-react";
|
|
2398
|
-
import { jsx as
|
|
2481
|
+
import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
2399
2482
|
function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
2400
|
-
const [newCidr, setNewCidr] =
|
|
2483
|
+
const [newCidr, setNewCidr] = React10.useState("");
|
|
2401
2484
|
const isValidCidr = (value) => {
|
|
2402
2485
|
const match = value.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,2})$/);
|
|
2403
2486
|
if (!match) return false;
|
|
@@ -2418,21 +2501,21 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2418
2501
|
}
|
|
2419
2502
|
};
|
|
2420
2503
|
if (loading || !config) {
|
|
2421
|
-
return /* @__PURE__ */
|
|
2422
|
-
/* @__PURE__ */
|
|
2423
|
-
/* @__PURE__ */
|
|
2504
|
+
return /* @__PURE__ */ jsxs21("div", { className: cn("rounded-lg border border-border bg-muted/20 p-6 text-center", className), children: [
|
|
2505
|
+
/* @__PURE__ */ jsx22(Network2, { className: "mx-auto h-6 w-6 text-muted-foreground animate-pulse mb-2" }),
|
|
2506
|
+
/* @__PURE__ */ jsx22("p", { className: "text-sm text-muted-foreground", children: "Loading network configuration..." })
|
|
2424
2507
|
] });
|
|
2425
2508
|
}
|
|
2426
|
-
return /* @__PURE__ */
|
|
2427
|
-
/* @__PURE__ */
|
|
2428
|
-
/* @__PURE__ */
|
|
2429
|
-
/* @__PURE__ */
|
|
2430
|
-
/* @__PURE__ */
|
|
2431
|
-
/* @__PURE__ */
|
|
2432
|
-
/* @__PURE__ */
|
|
2509
|
+
return /* @__PURE__ */ jsxs21("div", { className: cn("space-y-4", className), children: [
|
|
2510
|
+
/* @__PURE__ */ jsxs21("div", { className: "flex items-center justify-between rounded-lg border border-border bg-card px-4 py-3", children: [
|
|
2511
|
+
/* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-3", children: [
|
|
2512
|
+
/* @__PURE__ */ jsx22(ShieldAlert, { className: "h-4 w-4 text-muted-foreground" }),
|
|
2513
|
+
/* @__PURE__ */ jsxs21("div", { children: [
|
|
2514
|
+
/* @__PURE__ */ jsx22("p", { className: "text-sm font-medium text-foreground", children: "Block Outbound Traffic" }),
|
|
2515
|
+
/* @__PURE__ */ jsx22("p", { className: "text-xs text-muted-foreground", children: "Prevent the sandbox from making external network requests" })
|
|
2433
2516
|
] })
|
|
2434
2517
|
] }),
|
|
2435
|
-
/* @__PURE__ */
|
|
2518
|
+
/* @__PURE__ */ jsx22(
|
|
2436
2519
|
"button",
|
|
2437
2520
|
{
|
|
2438
2521
|
type: "button",
|
|
@@ -2444,7 +2527,7 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2444
2527
|
"relative inline-flex h-6 w-11 items-center rounded-full transition-colors",
|
|
2445
2528
|
config.blockOutbound ? "bg-destructive" : "bg-muted"
|
|
2446
2529
|
),
|
|
2447
|
-
children: /* @__PURE__ */
|
|
2530
|
+
children: /* @__PURE__ */ jsx22(
|
|
2448
2531
|
"span",
|
|
2449
2532
|
{
|
|
2450
2533
|
className: cn(
|
|
@@ -2456,22 +2539,22 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2456
2539
|
}
|
|
2457
2540
|
)
|
|
2458
2541
|
] }),
|
|
2459
|
-
/* @__PURE__ */
|
|
2460
|
-
/* @__PURE__ */
|
|
2461
|
-
config.allowList.length > 0 ? /* @__PURE__ */
|
|
2462
|
-
/* @__PURE__ */
|
|
2463
|
-
/* @__PURE__ */
|
|
2542
|
+
/* @__PURE__ */ jsxs21("div", { children: [
|
|
2543
|
+
/* @__PURE__ */ jsx22("h4", { className: "text-xs font-medium text-muted-foreground mb-2 uppercase tracking-wider", children: "Allowlist (CIDR)" }),
|
|
2544
|
+
config.allowList.length > 0 ? /* @__PURE__ */ jsx22("div", { className: "space-y-1.5 mb-3", children: config.allowList.map((cidr) => /* @__PURE__ */ jsxs21("div", { className: "flex items-center justify-between rounded border border-border bg-muted/20 px-3 py-2", children: [
|
|
2545
|
+
/* @__PURE__ */ jsx22("span", { className: "font-mono text-xs text-foreground", children: cidr }),
|
|
2546
|
+
/* @__PURE__ */ jsx22(
|
|
2464
2547
|
"button",
|
|
2465
2548
|
{
|
|
2466
2549
|
type: "button",
|
|
2467
2550
|
onClick: () => handleRemoveCidr(cidr),
|
|
2468
2551
|
className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
|
|
2469
|
-
children: /* @__PURE__ */
|
|
2552
|
+
children: /* @__PURE__ */ jsx22(Trash24, { className: "h-3 w-3" })
|
|
2470
2553
|
}
|
|
2471
2554
|
)
|
|
2472
|
-
] }, cidr)) }) : /* @__PURE__ */
|
|
2473
|
-
/* @__PURE__ */
|
|
2474
|
-
/* @__PURE__ */
|
|
2555
|
+
] }, cidr)) }) : /* @__PURE__ */ jsx22("p", { className: "text-xs text-muted-foreground mb-3", children: "No CIDR rules configured. All traffic is allowed." }),
|
|
2556
|
+
/* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-3", children: [
|
|
2557
|
+
/* @__PURE__ */ jsx22(
|
|
2475
2558
|
"input",
|
|
2476
2559
|
{
|
|
2477
2560
|
type: "text",
|
|
@@ -2482,7 +2565,7 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2482
2565
|
className: "flex-1 rounded-lg border border-border bg-background px-3 py-2 text-sm font-mono text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
2483
2566
|
}
|
|
2484
2567
|
),
|
|
2485
|
-
/* @__PURE__ */
|
|
2568
|
+
/* @__PURE__ */ jsxs21(
|
|
2486
2569
|
"button",
|
|
2487
2570
|
{
|
|
2488
2571
|
type: "button",
|
|
@@ -2490,7 +2573,7 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2490
2573
|
disabled: !newCidr.trim(),
|
|
2491
2574
|
className: "inline-flex items-center gap-2 rounded-lg bg-primary/20 border border-primary/30 px-4 py-2 text-sm font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors disabled:opacity-50",
|
|
2492
2575
|
children: [
|
|
2493
|
-
/* @__PURE__ */
|
|
2576
|
+
/* @__PURE__ */ jsx22(Plus6, { className: "h-4 w-4" }),
|
|
2494
2577
|
"Add"
|
|
2495
2578
|
]
|
|
2496
2579
|
}
|
|
@@ -2501,9 +2584,9 @@ function NetworkConfig({ config, onUpdate, loading = false, className }) {
|
|
|
2501
2584
|
}
|
|
2502
2585
|
|
|
2503
2586
|
// src/dashboard/backend-config.tsx
|
|
2504
|
-
import * as
|
|
2587
|
+
import * as React11 from "react";
|
|
2505
2588
|
import { Bot, Plus as Plus7, RefreshCw as RefreshCw2, Trash2 as Trash25, Server, Wrench } from "lucide-react";
|
|
2506
|
-
import { Fragment as Fragment11, jsx as
|
|
2589
|
+
import { Fragment as Fragment11, jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
2507
2590
|
function BackendConfig({
|
|
2508
2591
|
status,
|
|
2509
2592
|
mcpServers,
|
|
@@ -2513,10 +2596,10 @@ function BackendConfig({
|
|
|
2513
2596
|
loading = false,
|
|
2514
2597
|
className
|
|
2515
2598
|
}) {
|
|
2516
|
-
const [showAddMcp, setShowAddMcp] =
|
|
2517
|
-
const [mcpName, setMcpName] =
|
|
2518
|
-
const [mcpCommand, setMcpCommand] =
|
|
2519
|
-
const [mcpArgs, setMcpArgs] =
|
|
2599
|
+
const [showAddMcp, setShowAddMcp] = React11.useState(false);
|
|
2600
|
+
const [mcpName, setMcpName] = React11.useState("");
|
|
2601
|
+
const [mcpCommand, setMcpCommand] = React11.useState("");
|
|
2602
|
+
const [mcpArgs, setMcpArgs] = React11.useState("");
|
|
2520
2603
|
const handleAddMcp = () => {
|
|
2521
2604
|
const name = mcpName.trim();
|
|
2522
2605
|
const command = mcpCommand.trim();
|
|
@@ -2533,91 +2616,91 @@ function BackendConfig({
|
|
|
2533
2616
|
}
|
|
2534
2617
|
};
|
|
2535
2618
|
if (loading || !status) {
|
|
2536
|
-
return /* @__PURE__ */
|
|
2537
|
-
/* @__PURE__ */
|
|
2538
|
-
/* @__PURE__ */
|
|
2619
|
+
return /* @__PURE__ */ jsxs22("div", { className: cn("rounded-lg border border-border bg-muted/20 p-6 text-center", className), children: [
|
|
2620
|
+
/* @__PURE__ */ jsx23(Bot, { className: "mx-auto h-6 w-6 text-muted-foreground animate-pulse mb-2" }),
|
|
2621
|
+
/* @__PURE__ */ jsx23("p", { className: "text-sm text-muted-foreground", children: "Loading backend status..." })
|
|
2539
2622
|
] });
|
|
2540
2623
|
}
|
|
2541
|
-
return /* @__PURE__ */
|
|
2542
|
-
/* @__PURE__ */
|
|
2543
|
-
/* @__PURE__ */
|
|
2544
|
-
/* @__PURE__ */
|
|
2545
|
-
/* @__PURE__ */
|
|
2624
|
+
return /* @__PURE__ */ jsxs22("div", { className: cn("space-y-4", className), children: [
|
|
2625
|
+
/* @__PURE__ */ jsxs22("div", { className: "rounded-lg border border-border bg-card overflow-hidden", children: [
|
|
2626
|
+
/* @__PURE__ */ jsxs22("div", { className: "px-4 py-3 border-b border-border bg-muted/30 flex items-center justify-between", children: [
|
|
2627
|
+
/* @__PURE__ */ jsx23("h4", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider", children: "Agent Status" }),
|
|
2628
|
+
/* @__PURE__ */ jsxs22(
|
|
2546
2629
|
"button",
|
|
2547
2630
|
{
|
|
2548
2631
|
type: "button",
|
|
2549
2632
|
onClick: onRestart,
|
|
2550
2633
|
className: "inline-flex items-center gap-1.5 rounded-md bg-muted px-2.5 py-1 text-xs font-medium text-foreground hover:bg-muted/80 transition-colors border border-border",
|
|
2551
2634
|
children: [
|
|
2552
|
-
/* @__PURE__ */
|
|
2635
|
+
/* @__PURE__ */ jsx23(RefreshCw2, { className: "h-3 w-3" }),
|
|
2553
2636
|
"Restart"
|
|
2554
2637
|
]
|
|
2555
2638
|
}
|
|
2556
2639
|
)
|
|
2557
2640
|
] }),
|
|
2558
|
-
/* @__PURE__ */
|
|
2559
|
-
/* @__PURE__ */
|
|
2560
|
-
/* @__PURE__ */
|
|
2641
|
+
/* @__PURE__ */ jsx23("div", { className: "p-4", children: /* @__PURE__ */ jsxs22("dl", { className: "grid grid-cols-[100px_1fr] gap-y-3 text-sm", children: [
|
|
2642
|
+
/* @__PURE__ */ jsx23("dt", { className: "text-muted-foreground", children: "Status" }),
|
|
2643
|
+
/* @__PURE__ */ jsx23("dd", { children: /* @__PURE__ */ jsx23("span", { className: cn(
|
|
2561
2644
|
"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-[10px] font-bold uppercase tracking-wider",
|
|
2562
2645
|
status.running ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : "bg-destructive/10 text-destructive"
|
|
2563
2646
|
), children: status.running ? "Running" : "Stopped" }) }),
|
|
2564
|
-
/* @__PURE__ */
|
|
2565
|
-
/* @__PURE__ */
|
|
2566
|
-
status.provider && /* @__PURE__ */
|
|
2567
|
-
/* @__PURE__ */
|
|
2568
|
-
/* @__PURE__ */
|
|
2647
|
+
/* @__PURE__ */ jsx23("dt", { className: "text-muted-foreground", children: "Model" }),
|
|
2648
|
+
/* @__PURE__ */ jsx23("dd", { className: "font-mono text-xs", children: status.model ?? "Default" }),
|
|
2649
|
+
status.provider && /* @__PURE__ */ jsxs22(Fragment11, { children: [
|
|
2650
|
+
/* @__PURE__ */ jsx23("dt", { className: "text-muted-foreground", children: "Provider" }),
|
|
2651
|
+
/* @__PURE__ */ jsx23("dd", { className: "font-mono text-xs", children: status.provider })
|
|
2569
2652
|
] })
|
|
2570
2653
|
] }) })
|
|
2571
2654
|
] }),
|
|
2572
|
-
/* @__PURE__ */
|
|
2573
|
-
/* @__PURE__ */
|
|
2574
|
-
/* @__PURE__ */
|
|
2575
|
-
/* @__PURE__ */
|
|
2655
|
+
/* @__PURE__ */ jsxs22("div", { className: "rounded-lg border border-border bg-card overflow-hidden", children: [
|
|
2656
|
+
/* @__PURE__ */ jsxs22("div", { className: "px-4 py-3 border-b border-border bg-muted/30 flex items-center justify-between", children: [
|
|
2657
|
+
/* @__PURE__ */ jsxs22("h4", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider flex items-center gap-2", children: [
|
|
2658
|
+
/* @__PURE__ */ jsx23(Wrench, { className: "h-3.5 w-3.5" }),
|
|
2576
2659
|
"MCP Servers"
|
|
2577
2660
|
] }),
|
|
2578
|
-
/* @__PURE__ */
|
|
2661
|
+
/* @__PURE__ */ jsxs22(
|
|
2579
2662
|
"button",
|
|
2580
2663
|
{
|
|
2581
2664
|
type: "button",
|
|
2582
2665
|
onClick: () => setShowAddMcp(!showAddMcp),
|
|
2583
2666
|
className: "inline-flex items-center gap-1.5 rounded-md bg-primary/20 border border-primary/30 px-2.5 py-1 text-xs font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors",
|
|
2584
2667
|
children: [
|
|
2585
|
-
/* @__PURE__ */
|
|
2668
|
+
/* @__PURE__ */ jsx23(Plus7, { className: "h-3 w-3" }),
|
|
2586
2669
|
"Add"
|
|
2587
2670
|
]
|
|
2588
2671
|
}
|
|
2589
2672
|
)
|
|
2590
2673
|
] }),
|
|
2591
|
-
mcpServers.length > 0 ? /* @__PURE__ */
|
|
2592
|
-
/* @__PURE__ */
|
|
2593
|
-
/* @__PURE__ */
|
|
2594
|
-
/* @__PURE__ */
|
|
2595
|
-
/* @__PURE__ */
|
|
2596
|
-
/* @__PURE__ */
|
|
2674
|
+
mcpServers.length > 0 ? /* @__PURE__ */ jsx23("div", { className: "divide-y divide-border", children: mcpServers.map((s) => /* @__PURE__ */ jsxs22("div", { className: "flex items-center justify-between px-4 py-3", children: [
|
|
2675
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
2676
|
+
/* @__PURE__ */ jsx23(Server, { className: "h-3.5 w-3.5 text-muted-foreground shrink-0" }),
|
|
2677
|
+
/* @__PURE__ */ jsxs22("div", { className: "min-w-0", children: [
|
|
2678
|
+
/* @__PURE__ */ jsx23("p", { className: "text-sm font-medium text-foreground truncate", children: s.name }),
|
|
2679
|
+
/* @__PURE__ */ jsxs22("p", { className: "text-xs font-mono text-muted-foreground truncate", children: [
|
|
2597
2680
|
s.command,
|
|
2598
2681
|
" ",
|
|
2599
2682
|
s.args?.join(" ") ?? ""
|
|
2600
2683
|
] })
|
|
2601
2684
|
] })
|
|
2602
2685
|
] }),
|
|
2603
|
-
/* @__PURE__ */
|
|
2604
|
-
s.status && /* @__PURE__ */
|
|
2686
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
2687
|
+
s.status && /* @__PURE__ */ jsx23("span", { className: cn(
|
|
2605
2688
|
"inline-flex items-center rounded-full px-1.5 py-0.5 text-[9px] font-bold uppercase",
|
|
2606
2689
|
s.status === "running" ? "bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : s.status === "error" ? "bg-destructive/10 text-destructive" : "bg-muted text-muted-foreground"
|
|
2607
2690
|
), children: s.status }),
|
|
2608
|
-
/* @__PURE__ */
|
|
2691
|
+
/* @__PURE__ */ jsx23(
|
|
2609
2692
|
"button",
|
|
2610
2693
|
{
|
|
2611
2694
|
type: "button",
|
|
2612
2695
|
onClick: () => onRemoveMcp(s.name),
|
|
2613
2696
|
className: "p-1 text-muted-foreground hover:text-destructive transition-colors rounded",
|
|
2614
|
-
children: /* @__PURE__ */
|
|
2697
|
+
children: /* @__PURE__ */ jsx23(Trash25, { className: "h-3.5 w-3.5" })
|
|
2615
2698
|
}
|
|
2616
2699
|
)
|
|
2617
2700
|
] })
|
|
2618
|
-
] }, s.name)) }) : /* @__PURE__ */
|
|
2619
|
-
showAddMcp && /* @__PURE__ */
|
|
2620
|
-
/* @__PURE__ */
|
|
2701
|
+
] }, s.name)) }) : /* @__PURE__ */ jsx23("div", { className: "p-4 text-center", children: /* @__PURE__ */ jsx23("p", { className: "text-xs text-muted-foreground", children: "No MCP servers configured" }) }),
|
|
2702
|
+
showAddMcp && /* @__PURE__ */ jsxs22("div", { className: "p-4 border-t border-border bg-muted/10 space-y-2", children: [
|
|
2703
|
+
/* @__PURE__ */ jsx23(
|
|
2621
2704
|
"input",
|
|
2622
2705
|
{
|
|
2623
2706
|
type: "text",
|
|
@@ -2627,7 +2710,7 @@ function BackendConfig({
|
|
|
2627
2710
|
className: "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
2628
2711
|
}
|
|
2629
2712
|
),
|
|
2630
|
-
/* @__PURE__ */
|
|
2713
|
+
/* @__PURE__ */ jsx23(
|
|
2631
2714
|
"input",
|
|
2632
2715
|
{
|
|
2633
2716
|
type: "text",
|
|
@@ -2637,7 +2720,7 @@ function BackendConfig({
|
|
|
2637
2720
|
className: "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm font-mono text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
2638
2721
|
}
|
|
2639
2722
|
),
|
|
2640
|
-
/* @__PURE__ */
|
|
2723
|
+
/* @__PURE__ */ jsx23(
|
|
2641
2724
|
"input",
|
|
2642
2725
|
{
|
|
2643
2726
|
type: "text",
|
|
@@ -2647,8 +2730,8 @@ function BackendConfig({
|
|
|
2647
2730
|
className: "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm font-mono text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
2648
2731
|
}
|
|
2649
2732
|
),
|
|
2650
|
-
/* @__PURE__ */
|
|
2651
|
-
/* @__PURE__ */
|
|
2733
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex justify-end gap-2 pt-1", children: [
|
|
2734
|
+
/* @__PURE__ */ jsx23(
|
|
2652
2735
|
"button",
|
|
2653
2736
|
{
|
|
2654
2737
|
type: "button",
|
|
@@ -2657,7 +2740,7 @@ function BackendConfig({
|
|
|
2657
2740
|
children: "Cancel"
|
|
2658
2741
|
}
|
|
2659
2742
|
),
|
|
2660
|
-
/* @__PURE__ */
|
|
2743
|
+
/* @__PURE__ */ jsx23(
|
|
2661
2744
|
"button",
|
|
2662
2745
|
{
|
|
2663
2746
|
type: "button",
|
|
@@ -2674,9 +2757,9 @@ function BackendConfig({
|
|
|
2674
2757
|
}
|
|
2675
2758
|
|
|
2676
2759
|
// src/dashboard/snapshot-list.tsx
|
|
2677
|
-
import * as
|
|
2760
|
+
import * as React12 from "react";
|
|
2678
2761
|
import { Camera, Clock as Clock5, HardDrive, Plus as Plus8, RotateCcw } from "lucide-react";
|
|
2679
|
-
import { jsx as
|
|
2762
|
+
import { jsx as jsx24, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
2680
2763
|
function formatBytes(bytes) {
|
|
2681
2764
|
if (bytes == null || bytes < 0) return "-";
|
|
2682
2765
|
if (bytes === 0) return "0 B";
|
|
@@ -2691,33 +2774,33 @@ function formatDate(dateStr) {
|
|
|
2691
2774
|
return d.toLocaleDateString(void 0, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" });
|
|
2692
2775
|
}
|
|
2693
2776
|
function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loading = false, className }) {
|
|
2694
|
-
const [showCreate, setShowCreate] =
|
|
2695
|
-
const [tags, setTags] =
|
|
2777
|
+
const [showCreate, setShowCreate] = React12.useState(false);
|
|
2778
|
+
const [tags, setTags] = React12.useState("");
|
|
2696
2779
|
const handleCreate = () => {
|
|
2697
2780
|
const tagList = tags.trim() ? tags.trim().split(",").map((t) => t.trim()).filter(Boolean) : void 0;
|
|
2698
2781
|
onCreate(tagList);
|
|
2699
2782
|
setTags("");
|
|
2700
2783
|
setShowCreate(false);
|
|
2701
2784
|
};
|
|
2702
|
-
return /* @__PURE__ */
|
|
2703
|
-
/* @__PURE__ */
|
|
2704
|
-
/* @__PURE__ */
|
|
2705
|
-
/* @__PURE__ */
|
|
2785
|
+
return /* @__PURE__ */ jsxs23("div", { className: cn("space-y-4", className), children: [
|
|
2786
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between", children: [
|
|
2787
|
+
/* @__PURE__ */ jsx24("h3", { className: "text-sm font-bold text-foreground", children: "Snapshots" }),
|
|
2788
|
+
/* @__PURE__ */ jsxs23(
|
|
2706
2789
|
"button",
|
|
2707
2790
|
{
|
|
2708
2791
|
type: "button",
|
|
2709
2792
|
onClick: () => setShowCreate(!showCreate),
|
|
2710
2793
|
className: "inline-flex items-center gap-1.5 rounded-lg bg-primary/20 border border-primary/30 px-3 py-1.5 text-xs font-medium text-primary hover:bg-primary hover:text-primary-foreground transition-colors",
|
|
2711
2794
|
children: [
|
|
2712
|
-
/* @__PURE__ */
|
|
2795
|
+
/* @__PURE__ */ jsx24(Plus8, { className: "h-3.5 w-3.5" }),
|
|
2713
2796
|
"Create Snapshot"
|
|
2714
2797
|
]
|
|
2715
2798
|
}
|
|
2716
2799
|
)
|
|
2717
2800
|
] }),
|
|
2718
|
-
showCreate && /* @__PURE__ */
|
|
2719
|
-
/* @__PURE__ */
|
|
2720
|
-
/* @__PURE__ */
|
|
2801
|
+
showCreate && /* @__PURE__ */ jsxs23("div", { className: "rounded-lg border border-primary/20 bg-primary/5 p-4 space-y-3", children: [
|
|
2802
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm text-foreground font-medium", children: "Create a new snapshot of the current sandbox state." }),
|
|
2803
|
+
/* @__PURE__ */ jsx24(
|
|
2721
2804
|
"input",
|
|
2722
2805
|
{
|
|
2723
2806
|
type: "text",
|
|
@@ -2728,8 +2811,8 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2728
2811
|
className: "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring"
|
|
2729
2812
|
}
|
|
2730
2813
|
),
|
|
2731
|
-
/* @__PURE__ */
|
|
2732
|
-
/* @__PURE__ */
|
|
2814
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex justify-end gap-2", children: [
|
|
2815
|
+
/* @__PURE__ */ jsx24(
|
|
2733
2816
|
"button",
|
|
2734
2817
|
{
|
|
2735
2818
|
type: "button",
|
|
@@ -2738,44 +2821,44 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2738
2821
|
children: "Cancel"
|
|
2739
2822
|
}
|
|
2740
2823
|
),
|
|
2741
|
-
/* @__PURE__ */
|
|
2824
|
+
/* @__PURE__ */ jsxs23(
|
|
2742
2825
|
"button",
|
|
2743
2826
|
{
|
|
2744
2827
|
type: "button",
|
|
2745
2828
|
onClick: handleCreate,
|
|
2746
2829
|
className: "rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 transition-colors",
|
|
2747
2830
|
children: [
|
|
2748
|
-
/* @__PURE__ */
|
|
2831
|
+
/* @__PURE__ */ jsx24(Camera, { className: "h-3 w-3 mr-1.5 inline" }),
|
|
2749
2832
|
"Create"
|
|
2750
2833
|
]
|
|
2751
2834
|
}
|
|
2752
2835
|
)
|
|
2753
2836
|
] })
|
|
2754
2837
|
] }),
|
|
2755
|
-
loading ? /* @__PURE__ */
|
|
2756
|
-
/* @__PURE__ */
|
|
2757
|
-
/* @__PURE__ */
|
|
2758
|
-
] }) : snapshots.length > 0 ? /* @__PURE__ */
|
|
2759
|
-
/* @__PURE__ */
|
|
2760
|
-
/* @__PURE__ */
|
|
2761
|
-
/* @__PURE__ */
|
|
2762
|
-
/* @__PURE__ */
|
|
2763
|
-
/* @__PURE__ */
|
|
2764
|
-
/* @__PURE__ */
|
|
2838
|
+
loading ? /* @__PURE__ */ jsxs23("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2839
|
+
/* @__PURE__ */ jsx24(Camera, { className: "mx-auto h-6 w-6 text-muted-foreground animate-pulse mb-2" }),
|
|
2840
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm text-muted-foreground", children: "Loading snapshots..." })
|
|
2841
|
+
] }) : snapshots.length > 0 ? /* @__PURE__ */ jsx24("div", { className: "rounded-lg border border-border overflow-hidden", children: /* @__PURE__ */ jsxs23("table", { className: "w-full text-sm", children: [
|
|
2842
|
+
/* @__PURE__ */ jsx24("thead", { className: "bg-muted/30 border-b border-border", children: /* @__PURE__ */ jsxs23("tr", { children: [
|
|
2843
|
+
/* @__PURE__ */ jsx24("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "ID" }),
|
|
2844
|
+
/* @__PURE__ */ jsx24("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Created" }),
|
|
2845
|
+
/* @__PURE__ */ jsx24("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Size" }),
|
|
2846
|
+
/* @__PURE__ */ jsx24("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Tags" }),
|
|
2847
|
+
/* @__PURE__ */ jsx24("th", { className: "px-4 py-2.5 text-right text-xs font-medium text-muted-foreground w-24" })
|
|
2765
2848
|
] }) }),
|
|
2766
|
-
/* @__PURE__ */
|
|
2767
|
-
/* @__PURE__ */
|
|
2768
|
-
/* @__PURE__ */
|
|
2769
|
-
/* @__PURE__ */
|
|
2849
|
+
/* @__PURE__ */ jsx24("tbody", { className: "divide-y divide-border", children: snapshots.map((s) => /* @__PURE__ */ jsxs23("tr", { children: [
|
|
2850
|
+
/* @__PURE__ */ jsx24("td", { className: "px-4 py-3 font-mono text-xs text-foreground", children: s.id.slice(0, 12) }),
|
|
2851
|
+
/* @__PURE__ */ jsx24("td", { className: "px-4 py-3 text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs23("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
2852
|
+
/* @__PURE__ */ jsx24(Clock5, { className: "h-3 w-3" }),
|
|
2770
2853
|
formatDate(s.createdAt)
|
|
2771
2854
|
] }) }),
|
|
2772
|
-
/* @__PURE__ */
|
|
2773
|
-
/* @__PURE__ */
|
|
2855
|
+
/* @__PURE__ */ jsx24("td", { className: "px-4 py-3 text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs23("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
2856
|
+
/* @__PURE__ */ jsx24(HardDrive, { className: "h-3 w-3" }),
|
|
2774
2857
|
formatBytes(s.sizeBytes)
|
|
2775
2858
|
] }) }),
|
|
2776
|
-
/* @__PURE__ */
|
|
2777
|
-
/* @__PURE__ */
|
|
2778
|
-
/* @__PURE__ */
|
|
2859
|
+
/* @__PURE__ */ jsx24("td", { className: "px-4 py-3", children: s.tags?.length ? /* @__PURE__ */ jsx24("div", { className: "flex items-center gap-1 flex-wrap", children: s.tags.map((tag) => /* @__PURE__ */ jsx24("span", { className: "rounded-full bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground border border-border", children: tag }, tag)) }) : /* @__PURE__ */ jsx24("span", { className: "text-xs text-muted-foreground", children: "-" }) }),
|
|
2860
|
+
/* @__PURE__ */ jsx24("td", { className: "px-4 py-3 text-right", children: /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-end gap-2", children: [
|
|
2861
|
+
/* @__PURE__ */ jsxs23(
|
|
2779
2862
|
"button",
|
|
2780
2863
|
{
|
|
2781
2864
|
type: "button",
|
|
@@ -2783,12 +2866,12 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2783
2866
|
className: "inline-flex items-center gap-1.5 rounded-md bg-muted px-2.5 py-1 text-xs font-medium text-foreground hover:bg-muted/80 transition-colors border border-border",
|
|
2784
2867
|
title: "Restore to new sandbox",
|
|
2785
2868
|
children: [
|
|
2786
|
-
/* @__PURE__ */
|
|
2869
|
+
/* @__PURE__ */ jsx24(RotateCcw, { className: "h-3 w-3" }),
|
|
2787
2870
|
"Restore"
|
|
2788
2871
|
]
|
|
2789
2872
|
}
|
|
2790
2873
|
),
|
|
2791
|
-
onSaveAsTemplate && /* @__PURE__ */
|
|
2874
|
+
onSaveAsTemplate && /* @__PURE__ */ jsx24(
|
|
2792
2875
|
"button",
|
|
2793
2876
|
{
|
|
2794
2877
|
type: "button",
|
|
@@ -2800,16 +2883,16 @@ function SnapshotList({ snapshots, onCreate, onRestore, onSaveAsTemplate, loadin
|
|
|
2800
2883
|
)
|
|
2801
2884
|
] }) })
|
|
2802
2885
|
] }, s.id)) })
|
|
2803
|
-
] }) }) : /* @__PURE__ */
|
|
2804
|
-
/* @__PURE__ */
|
|
2805
|
-
/* @__PURE__ */
|
|
2806
|
-
/* @__PURE__ */
|
|
2886
|
+
] }) }) : /* @__PURE__ */ jsxs23("div", { className: "rounded-lg border border-border bg-muted/20 p-6 text-center", children: [
|
|
2887
|
+
/* @__PURE__ */ jsx24(Camera, { className: "mx-auto h-8 w-8 text-muted-foreground mb-2" }),
|
|
2888
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm text-muted-foreground", children: "No snapshots yet" }),
|
|
2889
|
+
/* @__PURE__ */ jsx24("p", { className: "text-xs text-muted-foreground mt-1", children: "Create a snapshot to save the current state of your sandbox." })
|
|
2807
2890
|
] })
|
|
2808
2891
|
] });
|
|
2809
2892
|
}
|
|
2810
2893
|
|
|
2811
2894
|
// src/dashboard/promo-banner.tsx
|
|
2812
|
-
import { Fragment as Fragment12, jsx as
|
|
2895
|
+
import { Fragment as Fragment12, jsx as jsx25, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
2813
2896
|
function PromoBanner({
|
|
2814
2897
|
title,
|
|
2815
2898
|
description,
|
|
@@ -2824,21 +2907,21 @@ function PromoBanner({
|
|
|
2824
2907
|
"mt-6 inline-flex items-center gap-2 rounded-md border border-white/20 bg-[var(--btn-primary-bg)] px-4 py-2 text-sm font-medium text-[var(--btn-primary-text)] transition-colors",
|
|
2825
2908
|
disabled ? "opacity-50 cursor-not-allowed" : "hover:bg-[var(--btn-primary-hover)]"
|
|
2826
2909
|
);
|
|
2827
|
-
const buttonContent = /* @__PURE__ */
|
|
2910
|
+
const buttonContent = /* @__PURE__ */ jsxs24(Fragment12, { children: [
|
|
2828
2911
|
buttonLabel,
|
|
2829
|
-
/* @__PURE__ */
|
|
2830
|
-
/* @__PURE__ */
|
|
2831
|
-
/* @__PURE__ */
|
|
2912
|
+
/* @__PURE__ */ jsxs24("svg", { "aria-hidden": "true", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "h-4 w-4", children: [
|
|
2913
|
+
/* @__PURE__ */ jsx25("path", { d: "M5 12h14" }),
|
|
2914
|
+
/* @__PURE__ */ jsx25("path", { d: "m12 5 7 7-7 7" })
|
|
2832
2915
|
] })
|
|
2833
2916
|
] });
|
|
2834
|
-
return /* @__PURE__ */
|
|
2835
|
-
/* @__PURE__ */
|
|
2836
|
-
/* @__PURE__ */
|
|
2837
|
-
/* @__PURE__ */
|
|
2838
|
-
href && !disabled ? /* @__PURE__ */
|
|
2917
|
+
return /* @__PURE__ */ jsxs24("div", { className: cn("relative overflow-hidden rounded-xl bg-[var(--brand-strong)] p-8 md:flex md:items-center md:justify-between", className), children: [
|
|
2918
|
+
/* @__PURE__ */ jsxs24("div", { className: "relative z-10", children: [
|
|
2919
|
+
/* @__PURE__ */ jsx25("h3", { className: "text-xl font-bold text-[var(--brand-strong-text)]", children: title }),
|
|
2920
|
+
/* @__PURE__ */ jsx25("p", { className: "mt-2 max-w-md text-sm text-[var(--brand-strong-text-muted)]", children: description }),
|
|
2921
|
+
href && !disabled ? /* @__PURE__ */ jsx25("a", { href, target: "_blank", rel: "noopener noreferrer", onClick, className: buttonClasses, children: buttonContent }) : /* @__PURE__ */ jsx25("button", { type: "button", onClick, disabled, className: buttonClasses, children: buttonContent })
|
|
2839
2922
|
] }),
|
|
2840
|
-
icon && /* @__PURE__ */
|
|
2841
|
-
/* @__PURE__ */
|
|
2923
|
+
icon && /* @__PURE__ */ jsx25("div", { className: "relative z-10 mt-6 flex items-center md:mt-0", children: /* @__PURE__ */ jsx25("div", { className: "flex h-16 w-16 items-center justify-center rounded-2xl border border-white/10 bg-white/10", children: icon }) }),
|
|
2924
|
+
/* @__PURE__ */ jsx25("div", { className: "pointer-events-none absolute inset-y-0 right-0 w-1/3 bg-gradient-to-l from-white/5 to-transparent" })
|
|
2842
2925
|
] });
|
|
2843
2926
|
}
|
|
2844
2927
|
|
|
@@ -2868,6 +2951,8 @@ export {
|
|
|
2868
2951
|
OutOfCreditsModal,
|
|
2869
2952
|
ClusterStatusBar,
|
|
2870
2953
|
ResourceMeter,
|
|
2954
|
+
ResourceSnapshot,
|
|
2955
|
+
ActivityFeed,
|
|
2871
2956
|
canAdminSandbox,
|
|
2872
2957
|
SandboxCard,
|
|
2873
2958
|
NewSandboxCard,
|