- Docker table: Restart and Stop buttons per container row (docker_compose_restart / docker_compose_stop) - Git repos list: Fetch and Pull buttons per repo; Pull disabled when working tree is dirty - systemd units list: Restart button per unit (systemctl_restart) - Caddy: Edit link on /caddy page, new /caddy/edit page with textarea + 3-step Validate → Save+Reload flow - All buttons open ConfirmDialog with exact agent-call preview, then stream output via StreamingTerminal - Add docker_compose_stop to ops-agent/commands.yml.example Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
70 lines
2.3 KiB
TypeScript
70 lines
2.3 KiB
TypeScript
import { redirect } from 'next/navigation'
|
|
import Link from 'next/link'
|
|
import { codeToHtml } from 'shiki'
|
|
import { getCurrentUser } from '@/lib/session'
|
|
import { execAgent } from '@/lib/agent-client'
|
|
import { parseCertList, type CertInfo } from '@/lib/parse-caddy'
|
|
import CaddyView from './_components/caddy-view'
|
|
|
|
export const dynamic = 'force-dynamic'
|
|
|
|
export default async function CaddyPage() {
|
|
const user = await getCurrentUser()
|
|
if (!user) redirect('/login')
|
|
|
|
let configHtml = ''
|
|
let configError: string | null = null
|
|
try {
|
|
const raw = await execAgent('caddy_show_config')
|
|
configHtml = await codeToHtml(raw || '# (empty)', {
|
|
lang: 'caddyfile',
|
|
theme: 'github-dark',
|
|
})
|
|
} catch (err) {
|
|
configError = err instanceof Error ? err.message : 'failed'
|
|
}
|
|
|
|
let initialCerts: CertInfo[] = []
|
|
let certsError: string | null = null
|
|
try {
|
|
const raw = await execAgent('caddy_list_certs')
|
|
initialCerts = parseCertList(raw)
|
|
} catch (err) {
|
|
certsError = err instanceof Error ? err.message : 'failed'
|
|
}
|
|
|
|
return (
|
|
<div className="min-h-screen bg-background p-6">
|
|
<div className="mx-auto max-w-6xl space-y-8">
|
|
<div>
|
|
<h1 className="text-2xl font-semibold tracking-tight">Caddy</h1>
|
|
<p className="text-sm text-muted-foreground">Config view and TLS certificate status</p>
|
|
</div>
|
|
|
|
<section className="space-y-3">
|
|
<div className="flex items-center justify-between">
|
|
<h2 className="text-lg font-medium tracking-tight">Caddyfile</h2>
|
|
<Link
|
|
href="/caddy/edit"
|
|
className="rounded-md border border-border px-3 py-1 text-xs hover:bg-muted/50 transition-colors"
|
|
>
|
|
Edit
|
|
</Link>
|
|
</div>
|
|
{configError ? (
|
|
<div className="rounded-lg border border-destructive/50 bg-destructive/10 p-4 text-sm text-destructive">
|
|
{configError}
|
|
</div>
|
|
) : (
|
|
<div
|
|
className="overflow-x-auto rounded-lg border border-border text-sm [&>pre]:p-4"
|
|
dangerouslySetInnerHTML={{ __html: configHtml }}
|
|
/>
|
|
)}
|
|
</section>
|
|
|
|
<CaddyView initialCerts={initialCerts} certsError={certsError} />
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|