// Slide-out drawer for editing an existing endpoint. // Reuses the NodeDetail drawer chrome (.drawer / .drawer-head / .drawer-body // / .drawer-actions) so the admin edit flow looks identical to the click-on- // a-node flow. const INPUT_STYLE = { width: '100%', padding: '6px 10px', background: 'var(--surface)', border: '1px solid var(--border-2)', borderRadius: 2, color: 'var(--text)', fontFamily: 'var(--mono)', fontSize: 12, outline: 'none', }; function AdminEditor({ server, groups, onClose, onSaved }) { const open = !!server; // Keep local form state separate so mid-edit typing doesn't fight polling. const [url, setUrl] = React.useState(''); const [group, setGroup] = React.useState(''); const [customGroup, setCustomGroup] = React.useState(false); const [probePath, setProbePath] = React.useState(''); const [okCodes, setOkCodes] = React.useState(''); const [busy, setBusy] = React.useState(false); const [err, setErr] = React.useState(null); React.useEffect(() => { if (!server) return; setUrl(server.url || ''); setGroup(server.group || ''); setCustomGroup(false); setProbePath(server.probePath || ''); setOkCodes(Array.isArray(server.okCodes) ? server.okCodes.join(', ') : ''); setErr(null); }, [server?.id]); if (!open) return
; function parseOkCodes(raw) { const xs = raw.split(/[,\s]+/).map(s => s.trim()).filter(Boolean); const out = []; for (const x of xs) { const n = Number(x); if (!Number.isFinite(n)) throw new Error(`okCodes: "${x}" is not a number`); out.push(Math.floor(n)); } return out; } async function save() { setErr(null); setBusy(true); try { const patch = { group: group.trim() }; if (probePath.trim()) patch.probePath = probePath.trim(); else patch.probePath = null; // explicit drop if (okCodes.trim()) patch.okCodes = parseOkCodes(okCodes); else patch.okCodes = null; const updated = await window.adminFetch(`/api/admin/servers/${server.id}`, { method: 'PATCH', body: JSON.stringify(patch), }); onSaved(updated); } catch (e) { setErr(e.message || 'save failed'); } finally { setBusy(false); } } const groupOpts = Array.from(new Set([...(groups || []), group])).filter(Boolean); return (