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 <noreply@anthropic.com>
This commit is contained in:
1 parent
d5b6c55383
commit
7564796c39
1 file changed
+28
-1
@@ -29,6 +29,8 @@ export default function Integrations({ user }: { user: CurrentUser }) {
|
|||||||
const [editingIntegration, setEditingIntegration] = useState<IntegrationSummary | null>(null);
|
const [editingIntegration, setEditingIntegration] = useState<IntegrationSummary | null>(null);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [integrationColors, setIntegrationColors] = useState<Record<string, string>>({});
|
const [integrationColors, setIntegrationColors] = useState<Record<string, string>>({});
|
||||||
|
const [testingId, setTestingId] = useState<number | null>(null);
|
||||||
|
const [testResults, setTestResults] = useState<Record<number, { ok: boolean; latencyMs?: number; error?: string }>>({});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
api.settings.integrationColors().then((res) => setIntegrationColors(res.integrationColors)).catch(() => {});
|
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) {
|
async function removeIntegration(i: IntegrationSummary) {
|
||||||
if (!confirm(`Delete integration "${i.name}"?`)) return;
|
if (!confirm(`Delete integration "${i.name}"?`)) return;
|
||||||
try {
|
try {
|
||||||
@@ -159,7 +173,17 @@ export default function Integrations({ user }: { user: CurrentUser }) {
|
|||||||
</td>
|
</td>
|
||||||
{isAdmin && (
|
{isAdmin && (
|
||||||
<td>
|
<td>
|
||||||
<div className="btn-list flex-nowrap">
|
<div className="btn-list flex-nowrap align-items-center">
|
||||||
|
<button className="btn btn-sm" onClick={() => testIntegration(i)} disabled={testingId === i.id}>
|
||||||
|
{testingId === i.id ? "Testing…" : "Test"}
|
||||||
|
</button>
|
||||||
|
{testResults[i.id] && testingId !== i.id && (
|
||||||
|
<span className={`badge ${testResults[i.id].ok ? "bg-green-lt text-green" : "bg-red-lt text-red"}`}>
|
||||||
|
{testResults[i.id].ok
|
||||||
|
? `OK${testResults[i.id].latencyMs !== undefined ? ` (${testResults[i.id].latencyMs}ms)` : ""}`
|
||||||
|
: "Failed"}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
<button className="btn btn-sm" onClick={() => setEditingIntegration(i)}>
|
<button className="btn btn-sm" onClick={() => setEditingIntegration(i)}>
|
||||||
Edit
|
Edit
|
||||||
</button>
|
</button>
|
||||||
@@ -167,6 +191,9 @@ export default function Integrations({ user }: { user: CurrentUser }) {
|
|||||||
Delete
|
Delete
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{testResults[i.id] && !testResults[i.id].ok && testingId !== i.id && (
|
||||||
|
<div className="text-red small mt-1">{testResults[i.id].error}</div>
|
||||||
|
)}
|
||||||
</td>
|
</td>
|
||||||
)}
|
)}
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
Reference in new issue
Block a user