import { useEffect, useState } from "react"; import { api, type IntegrationField, type IntegrationSummary, type IntegrationType } from "../api/client"; const TYPE_LABELS: Record = { tailscale: "Tailscale", proxmox: "Proxmox", synology: "Synology", semaphore: "Semaphore", gitea: "Gitea", dockhand: "Dockhand", }; export default function IntegrationEditForm({ integration, onSaved, onCancel, }: { integration: IntegrationSummary; onSaved: () => void; onCancel: () => void; }) { const [fields, setFields] = useState(null); const [name, setName] = useState(integration.name); const [values, setValues] = useState>({}); const [loading, setLoading] = useState(true); const [loadError, setLoadError] = useState(null); const [testResult, setTestResult] = useState<{ ok: boolean; latencyMs?: number; error?: string } | null>(null); const [testing, setTesting] = useState(false); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); useEffect(() => { Promise.all([api.integrations.fields(), api.integrations.getConfig(integration.id)]) .then(([fieldsRes, configRes]) => { setFields(fieldsRes.fields[integration.type] ?? []); setValues(configRes.config); setName(configRes.integration.name); }) .catch((err) => setLoadError(err instanceof Error ? err.message : String(err))) .finally(() => setLoading(false)); }, [integration.id, integration.type]); function setField(key: string, value: string | boolean) { setValues((v) => ({ ...v, [key]: value })); setTestResult(null); } /** Only fields the admin actually typed a value for — a blank secret input means "keep the current value". */ function collectOverrides(): Record { const overrides: Record = {}; for (const f of fields ?? []) { const v = values[f.key]; if (f.type === "checkbox") { overrides[f.key] = Boolean(v); } else if (typeof v === "string" && v !== "") { overrides[f.key] = v; } } return overrides; } async function testConnection() { setTesting(true); setTestResult(null); try { const result = await api.integrations.testExisting(integration.id, collectOverrides()); setTestResult(result); } catch (err) { setTestResult({ ok: false, error: err instanceof Error ? err.message : String(err) }); } finally { setTesting(false); } } async function submit(e: React.FormEvent) { e.preventDefault(); setSaving(true); setError(null); try { await api.integrations.update(integration.id, { name, config: collectOverrides() }); onSaved(); } catch (err) { setError(err instanceof Error ? err.message : String(err)); } finally { setSaving(false); } } if (loading) { return (
Loading…
); } return (

Edit {integration.name} ({TYPE_LABELS[integration.type]})

{(loadError || error) && (
{loadError ?? error}
)}
setName(e.target.value)} />
{fields?.map((field) => (
{field.type === "checkbox" ? ( ) : ( <> setField(field.key, e.target.value)} /> )}
))} {testResult && (
{testResult.ok ? (
Connection OK{testResult.latencyMs !== undefined ? ` (${testResult.latencyMs}ms)` : ""}.
) : (
Connection failed: {testResult.error}
)}
)}
); }