From 5e366fb2abb86261f796f0db452b1ed3efb434e4 Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Sat, 28 Mar 2026 14:07:06 +0300 Subject: [PATCH] feat: registry health indicator Show colored dot next to each registry name: - Yellow (pulsing): checking connectivity - Green: connected and reachable - Red: unreachable or auth failed Health is checked automatically when the registries page loads and updated when "Test Connection" is clicked. --- .../routes/settings/registries/+page.svelte | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/web/src/routes/settings/registries/+page.svelte b/web/src/routes/settings/registries/+page.svelte index 7c53735..1a1f032 100644 --- a/web/src/routes/settings/registries/+page.svelte +++ b/web/src/routes/settings/registries/+page.svelte @@ -20,6 +20,7 @@ let formOwner = $state(''); let formSaving = $state(false); let testingId = $state(null); + let healthStatus = $state>({}); let errors = $state>({}); @@ -37,7 +38,11 @@ async function loadRegistryList() { loading = true; - try { registries = await listRegistries(); } catch (err) { toasts.error(err instanceof Error ? err.message : $t('settingsRegistries.loadFailed')); } finally { loading = false; } + try { + registries = await listRegistries(); + // Check health of all registries in the background. + checkAllHealth(); + } catch (err) { toasts.error(err instanceof Error ? err.message : $t('settingsRegistries.loadFailed')); } finally { loading = false; } } async function handleSave() { @@ -61,9 +66,26 @@ async function handleTestConnection(registry: Registry) { testingId = registry.id; - try { await testRegistry(registry.id); toasts.success($t('settingsRegistries.testSuccess', { name: registry.name })); } - catch (err) { toasts.error(err instanceof Error ? err.message : $t('settingsRegistries.testFailed')); } - finally { testingId = null; } + try { + await testRegistry(registry.id); + toasts.success($t('settingsRegistries.testSuccess', { name: registry.name })); + healthStatus[registry.id] = 'healthy'; + } catch (err) { + toasts.error(err instanceof Error ? err.message : $t('settingsRegistries.testFailed')); + healthStatus[registry.id] = 'unhealthy'; + } finally { testingId = null; } + } + + async function checkAllHealth() { + for (const reg of registries) { + healthStatus[reg.id] = 'checking'; + try { + await testRegistry(reg.id); + healthStatus[reg.id] = 'healthy'; + } catch { + healthStatus[reg.id] = 'unhealthy'; + } + } } $effect(() => { loadRegistryList(); }); @@ -134,6 +156,13 @@
+ {#if healthStatus[registry.id] === 'checking'} + + {:else if healthStatus[registry.id] === 'healthy'} + + {:else if healthStatus[registry.id] === 'unhealthy'} + + {/if}

{registry.name}

{registry.type}