import { useState } from "react"; import { checkSiteCustomDomain, deleteSiteVariable, deploySite, rollbackSiteDeployment, setSiteCustomDomain, setSiteVariable, } from "~/fns/sites"; import { useAction } from "~/hooks/use-action"; import { Badge } from "~/ui/Badge"; import { EmptyState } from "~/ui/EmptyState"; import { formatBytes } from "~/lib/format"; import { Panel } from "~/ui/Panel"; import { RelativeTime } from "~/ui/RelativeTime"; import { Button } from "~/ui/Button"; import { CheckboxField, TextField } from "~/ui/Field"; import { ErrorBanner } from "~/ui/Callout"; import type { RepoParams, SiteData } from "./SitesSettings"; import { ExternalLink } from "~/ui/TextLink"; const STATUS_TONES = { queued: "neutral", building: "warning", active: "success", failed: "danger", superseded: "neutral", } as const; export function SiteEnvPanel({ data, params }: { data: SiteData; params: RepoParams }) { const save = useAction(setSiteVariable); const remove = useAction(deleteSiteVariable); if (!data.site) return null; return (
{ event.preventDefault(); const element = event.currentTarget; const form = new FormData(element); const ok = await save.run({ data: { ...params, name: String(form.get("name") ?? "").trim(), value: String(form.get("value") ?? ""), secret: form.get("secret") === "on", preview: form.get("preview") === "on", }, }); if (ok) element.reset(); }} >
); } export function SiteDomainPanel({ data, params }: { data: SiteData; params: RepoParams }) { const update = useAction(setSiteCustomDomain); const check = useAction(checkSiteCustomDomain); const [details, setDetails] = useState>>(null); const site = data.site; if (!site) return null; if (!data.customDomainsEnabled) { return (

Custom domains are not configured on this forge.

); } return ( {site.domainStatus} ) } >
{ event.preventDefault(); const domain = String(new FormData(event.currentTarget).get("domain") ?? "").trim(); await update.run({ data: { ...params, domain: domain || null } }); }} >
{site.customDomain && ( )}
{details && (
Status: {details.status}
{details.records.map((record) => (
{record.type} {record.name} = {record.value}
))}
)}
); } export function SiteDeploymentsPanel({ data, params }: { data: SiteData; params: RepoParams }) { const deploy = useAction(deploySite); const rollback = useAction(rollbackSiteDeployment); if (!data.site) return null; const activeId = data.site.activeDeploymentId; return ( deploy.run({ data: params })}> Deploy now } > {data.deployments.length === 0 ? ( ) : (
    {data.deployments.map((row) => (
  • {row.status} {row.environment === "preview" ? `Preview ${row.branch}` : "Production"} {row.ref}@{row.sha.slice(0, 7)} {row.kind === "worker" ? "worker" : "static"} {row.fileCount > 0 && ( {row.fileCount} files, {formatBytes(row.totalBytes)} )} {row.error && {row.error}} {row.status === "active" && row.url && ( Visit )} {row.environment === "production" && row.status === "superseded" && row.id !== activeId && ( )}
  • ))}
)}
); }