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.
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
let formOwner = $state('');
|
||||
let formSaving = $state(false);
|
||||
let testingId = $state<string | null>(null);
|
||||
let healthStatus = $state<Record<string, 'checking' | 'healthy' | 'unhealthy'>>({});
|
||||
|
||||
let errors = $state<Record<string, string>>({});
|
||||
|
||||
@@ -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 @@
|
||||
<div class="flex items-center justify-between rounded-xl border border-[var(--border-primary)] bg-[var(--surface-card)] p-4 shadow-[var(--shadow-sm)] transition-all duration-150 hover:shadow-[var(--shadow-md)]">
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
{#if healthStatus[registry.id] === 'checking'}
|
||||
<span class="h-2.5 w-2.5 shrink-0 rounded-full bg-yellow-400 animate-pulse" title="Checking..."></span>
|
||||
{:else if healthStatus[registry.id] === 'healthy'}
|
||||
<span class="h-2.5 w-2.5 shrink-0 rounded-full bg-emerald-500" title="Connected"></span>
|
||||
{:else if healthStatus[registry.id] === 'unhealthy'}
|
||||
<span class="h-2.5 w-2.5 shrink-0 rounded-full bg-red-500" title="Unreachable"></span>
|
||||
{/if}
|
||||
<h3 class="text-sm font-semibold text-[var(--text-primary)]">{registry.name}</h3>
|
||||
<span class="rounded-full bg-[var(--surface-card-hover)] px-2 py-0.5 text-xs font-medium text-[var(--text-tertiary)]">{registry.type}</span>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user