import { useMemo, useState } from "react";
import { Link } from "react-router";
import { ChevronDownIcon } from "@heroicons/react/16/solid";
import { ComputerDesktopIcon } from "@heroicons/react/24/outline";
import type { ServerSandboxProvidersSettings } from "@qltysh/fabro-api-client";
import { useServerSettings } from "../lib/queries";
import {
Dot,
Panel,
PanelSkeleton,
Row,
SettingsPageIntro,
} from "../components/settings-panel";
import { plural } from "../lib/plural";
export function meta() {
return [{ title: "Sandboxes — Fabro" }];
}
type SandboxProviderId = "local" | "docker" | "daytona";
type SandboxProvider = {
id: SandboxProviderId;
name: string;
description: string;
enabled: boolean;
secretName?: string;
};
const DESCRIPTION =
"Runtime environments where workflow stages execute. Configured via settings.toml.";
export default function SettingsSandboxes() {
const query = useServerSettings();
const settings = query.data;
return (
);
}
function ProvidersPanel({ settings }: { settings: ServerSandboxProvidersSettings }) {
const providers: SandboxProvider[] = useMemo(
() => [
{
id: "local",
name: "Local",
description: "Run stages directly on the Fabro host.",
enabled: settings.local.enabled,
},
{
id: "docker",
name: "Docker",
description: "Run stages in isolated Docker containers on the host daemon.",
enabled: settings.docker.enabled,
},
{
id: "daytona",
name: "Daytona",
description: "Run stages in cloud sandboxes managed by Daytona.",
enabled: settings.daytona.enabled,
secretName: "DAYTONA_API_KEY",
},
],
[settings],
);
const { enabled, disabled } = useMemo(() => {
const enabled: SandboxProvider[] = [];
const disabled: SandboxProvider[] = [];
for (const provider of providers) {
if (provider.enabled) {
enabled.push(provider);
} else {
disabled.push(provider);
}
}
return { enabled, disabled };
}, [providers]);
const [showDisabled, setShowDisabled] = useState(false);
const showDisabledRows = enabled.length === 0 || showDisabled;
return (
{enabled.map((provider) => (
))}
{showDisabledRows
? disabled.map((provider) => (
))
: null}
{enabled.length > 0 && disabled.length > 0 ? (
) : null}
);
}
function ProviderRow({ provider }: { provider: SandboxProvider }) {
return (
{provider.name}
{provider.description}
}
>
);
}
function ProviderLogo({ provider }: { provider: SandboxProvider }) {
const [failed, setFailed] = useState(false);
const chip =
"grid size-10 shrink-0 place-items-center rounded-md bg-ice-50 ring-1 ring-line-strong";
const dim = provider.enabled ? "" : "opacity-60";
if (provider.id === "local") {
return (
);
}
if (failed) {
return (
{provider.name.charAt(0)}
);
}
return (
setFailed(true)}
className="size-7"
/>
);
}
function ProviderStatus({ provider }: { provider: SandboxProvider }) {
return (
{provider.enabled ? "Enabled" : "Disabled"}
{!provider.enabled && provider.secretName ? (
Add secret →
) : null}
);
}