fix(web): integrations panel review fixes

- Trim whitespace before checking the typed-confirm value (paste-with-spaces
  was silently keeping the button disabled).
- Wrap onConfirmDisconnect in try/catch and surface disconnect_failed inline
  in the modal — operators on flaky networks now see why nothing happened.
- Invalidate quality-profile + root-folder caches alongside config on both
  save and disconnect, so a base_url change refetches the lists immediately.
This commit is contained in:
2026-04-29 23:11:32 -04:00
parent c281c8b5dd
commit b1b50187b3
+34 -13
View File
@@ -66,7 +66,13 @@
default_root_folder_path: rootPath
};
await putLidarrConfig(cfg);
await client.invalidateQueries({ queryKey: qk.lidarrConfig() });
// Invalidate config + profile/folder lists. A new base_url means a
// different server, so the cached lists must refetch.
await Promise.all([
client.invalidateQueries({ queryKey: qk.lidarrConfig() }),
client.invalidateQueries({ queryKey: qk.lidarrQualityProfiles() }),
client.invalidateQueries({ queryKey: qk.lidarrRootFolders() })
]);
apiKeyInput = '';
} catch (e) {
saveError = (e as { code?: string }).code ?? 'save_failed';
@@ -89,28 +95,40 @@
}
// Disconnect typed-confirm modal. Requires the literal "DISCONNECT" string
// to avoid muscle-memory clearing of an integration the operator depends on.
// (whitespace-trimmed) to avoid muscle-memory clearing of an integration the
// operator depends on.
let modalOpen = $state(false);
let disconnectInput = $state('');
const canDisconnect = $derived(disconnectInput === 'DISCONNECT');
let disconnectError = $state<string | null>(null);
const canDisconnect = $derived(disconnectInput.trim() === 'DISCONNECT');
async function onConfirmDisconnect() {
if (!canDisconnect) return;
await putLidarrConfig({
enabled: false,
base_url: '',
api_key: '',
default_quality_profile_id: 0,
default_root_folder_path: ''
});
await client.invalidateQueries({ queryKey: qk.lidarrConfig() });
modalOpen = false;
disconnectInput = '';
disconnectError = null;
try {
await putLidarrConfig({
enabled: false,
base_url: '',
api_key: '',
default_quality_profile_id: 0,
default_root_folder_path: ''
});
await Promise.all([
client.invalidateQueries({ queryKey: qk.lidarrConfig() }),
client.invalidateQueries({ queryKey: qk.lidarrQualityProfiles() }),
client.invalidateQueries({ queryKey: qk.lidarrRootFolders() })
]);
modalOpen = false;
disconnectInput = '';
} catch (e) {
disconnectError = (e as { code?: string }).code ?? 'disconnect_failed';
}
}
function cancelDisconnect() {
modalOpen = false;
disconnectInput = '';
disconnectError = null;
}
</script>
@@ -289,6 +307,9 @@
aria-label="Type DISCONNECT to confirm"
class="mt-3 w-full rounded-md border border-border bg-background px-3 py-2 font-mono text-sm text-text-primary placeholder:text-text-muted focus:outline-none focus:ring-2 focus:ring-accent"
/>
{#if disconnectError}
<p class="mt-2 text-sm text-error">Disconnect failed — {disconnectError}</p>
{/if}
<div class="mt-5 flex justify-end gap-2">
<button
type="button"