From 7564796c3912249b1583c18fee1da2132ffb6c87 Mon Sep 17 00:00:00 2001 From: Bobban Rydh Date: Fri, 18 Sep 2026 20:31:04 +0200 Subject: [PATCH] Add a per-row Test button to the Integrations list The add/edit forms already had "Test connection", backed by existing POST /api/integrations/:id/test (admin-only, pings with the stored config) and POST /api/integrations/test (for a not-yet-saved one) -- but there was no way to re-test an already-configured integration without opening its edit form. Add a "Test" button next to Edit/ Delete on each row, showing an OK/latency or Failed/error badge inline once it returns. Pure frontend wiring to the existing endpoint, no server changes needed. Co-Authored-By: Claude Sonnet 5 --- web/src/pages/Integrations.tsx | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/web/src/pages/Integrations.tsx b/web/src/pages/Integrations.tsx index ef268c1..8f6366d 100644 --- a/web/src/pages/Integrations.tsx +++ b/web/src/pages/Integrations.tsx @@ -29,6 +29,8 @@ export default function Integrations({ user }: { user: CurrentUser }) { const [editingIntegration, setEditingIntegration] = useState(null); const [error, setError] = useState(null); const [integrationColors, setIntegrationColors] = useState>({}); + const [testingId, setTestingId] = useState(null); + const [testResults, setTestResults] = useState>({}); useEffect(() => { api.settings.integrationColors().then((res) => setIntegrationColors(res.integrationColors)).catch(() => {}); @@ -52,6 +54,18 @@ export default function Integrations({ user }: { user: CurrentUser }) { } } + async function testIntegration(i: IntegrationSummary) { + setTestingId(i.id); + try { + const result = await api.integrations.testExisting(i.id, {}); + setTestResults((prev) => ({ ...prev, [i.id]: result })); + } catch (err) { + setTestResults((prev) => ({ ...prev, [i.id]: { ok: false, error: err instanceof Error ? err.message : String(err) } })); + } finally { + setTestingId(null); + } + } + async function removeIntegration(i: IntegrationSummary) { if (!confirm(`Delete integration "${i.name}"?`)) return; try { @@ -159,7 +173,17 @@ export default function Integrations({ user }: { user: CurrentUser }) { {isAdmin && ( -
+
+ + {testResults[i.id] && testingId !== i.id && ( + + {testResults[i.id].ok + ? `OK${testResults[i.id].latencyMs !== undefined ? ` (${testResults[i.id].latencyMs}ms)` : ""}` + : "Failed"} + + )} @@ -167,6 +191,9 @@ export default function Integrations({ user }: { user: CurrentUser }) { Delete
+ {testResults[i.id] && !testResults[i.id].ok && testingId !== i.id && ( +
{testResults[i.id].error}
+ )} )}