diff --git a/frontend/src/app/dialogs/show-runner-metadata-frame.tsx b/frontend/src/app/dialogs/show-runner-metadata-frame.tsx new file mode 100644 index 0000000000..ee67590fa7 --- /dev/null +++ b/frontend/src/app/dialogs/show-runner-metadata-frame.tsx @@ -0,0 +1,50 @@ +import { useSuspenseQuery } from "@tanstack/react-query"; +import { type DialogContentProps, Frame } from "@/components"; +import { useEngineCompatDataProvider } from "@/components/actors"; + +interface ShowRunnerMetadataFrameContentProps extends DialogContentProps { + runnerId: string; +} + +export default function ShowRunnerMetadataFrameContent({ + runnerId, +}: ShowRunnerMetadataFrameContentProps) { + const provider = useEngineCompatDataProvider(); + + const { data: runners } = useSuspenseQuery({ + ...provider.runnersQueryOptions(), + }); + + const runner = runners?.find((r) => r.runnerId === runnerId); + + if (!runner) { + return ( + <> + + Runner Metadata + + Runner not found. + + ); + } + + const metadataJson = runner.metadata + ? JSON.stringify(runner.metadata, null, 2) + : "{}"; + + return ( + <> + + Runner Metadata + + Metadata for runner: {runner.name} + + + +
+					{metadataJson}
+				
+
+ + ); +} diff --git a/frontend/src/app/runners-table.tsx b/frontend/src/app/runners-table.tsx index aca5ec735b..d31f5d465c 100644 --- a/frontend/src/app/runners-table.tsx +++ b/frontend/src/app/runners-table.tsx @@ -1,4 +1,5 @@ import { + faEllipsisH, faPlus, faSignalAlt, faSignalAlt2, @@ -8,11 +9,15 @@ import { } from "@rivet-gg/icons"; import type { Rivet } from "@rivetkit/engine-api-full"; import { useInfiniteQuery } from "@tanstack/react-query"; -import { Link } from "@tanstack/react-router"; +import { Link, useNavigate } from "@tanstack/react-router"; import { formatDistance } from "date-fns"; import { Button, DiscreteCopyButton, + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, Skeleton, Table, TableBody, @@ -50,6 +55,7 @@ export function RunnersTable({ Datacenter Slots Created + @@ -126,6 +132,8 @@ function RowSkeleton() { } function Row(runner: Rivet.Runner) { + const navigate = useNavigate(); + return ( @@ -155,6 +163,33 @@ function Row(runner: Rivet.Runner) { + + + + + + + + { + navigate({ + to: ".", + search: (prev) => ({ + ...prev, + modal: "show-runner-metadata", + runnerId: runner.runnerId, + }), + }); + }} + > + Show metadata + + + + ); } diff --git a/frontend/src/app/use-dialog.tsx b/frontend/src/app/use-dialog.tsx index 14f84484b7..07b894f14b 100644 --- a/frontend/src/app/use-dialog.tsx +++ b/frontend/src/app/use-dialog.tsx @@ -38,6 +38,9 @@ export const useDialog = { DeleteConfig: createDialogHook( () => import("@/app/dialogs/confirm-delete-config-frame"), ), + ShowRunnerMetadata: createDialogHook( + () => import("@/app/dialogs/show-runner-metadata-frame"), + ), Billing: createDialogHook(() => import("@/app/dialogs/billing-frame")), ProvideEngineCredentials: createDialogHook( () => import("@/app/dialogs/provide-engine-credentials-frame"), diff --git a/frontend/src/routes/_context/_cloud.tsx b/frontend/src/routes/_context/_cloud.tsx index d9779d4d27..d54839cb6b 100644 --- a/frontend/src/routes/_context/_cloud.tsx +++ b/frontend/src/routes/_context/_cloud.tsx @@ -47,6 +47,7 @@ function CloudModals() { const ConnectHetznerDialog = useDialog.ConnectHetzner.Dialog; const EditProviderConfigDialog = useDialog.EditProviderConfig.Dialog; const DeleteConfigDialog = useDialog.DeleteConfig.Dialog; + const ShowRunnerMetadataDialog = useDialog.ShowRunnerMetadata.Dialog; return ( <> @@ -284,6 +285,25 @@ function CloudModals() { }, }} /> + { + if (!value) { + navigate({ + to: ".", + search: (old) => ({ + ...old, + modal: undefined, + runnerId: undefined, + }), + }); + } + }, + }} + /> ); } diff --git a/frontend/src/routes/_context/_engine.tsx b/frontend/src/routes/_context/_engine.tsx index 085a73dd1b..8785102207 100644 --- a/frontend/src/routes/_context/_engine.tsx +++ b/frontend/src/routes/_context/_engine.tsx @@ -44,6 +44,7 @@ function EngineModals() { const ConnectHetznerDialog = useDialog.ConnectHetzner.Dialog; const EditProviderConfigDialog = useDialog.EditProviderConfig.Dialog; const DeleteConfigDialog = useDialog.DeleteConfig.Dialog; + const ShowRunnerMetadataDialog = useDialog.ShowRunnerMetadata.Dialog; return ( <> @@ -265,6 +266,25 @@ function EngineModals() { }, }} /> + { + if (!value) { + navigate({ + to: ".", + search: (old) => ({ + ...old, + modal: undefined, + runnerId: undefined, + }), + }); + } + }, + }} + /> ); }