feat(observability): phases 4-7 - complete frontend UI (big bang)

Add all frontend pages for observability & proxy management:
- Proxy Viewer: /proxies with grouped view, filtering, health indicators
- Proxy Creation: form with live validation, diagnostic hints, edit/delete
- Stale Containers: /containers/stale with dashboard widget, cleanup actions
- Event Log: /events with filters, pagination, real-time SSE streaming
- Navigation: proxies and events links in sidebar
- i18n: full EN/RU translations for all new features
- Settings: stale threshold configuration
This commit is contained in:
2026-03-30 11:29:10 +03:00
parent 7a85441b81
commit 79a40f3d9c
29 changed files with 2237 additions and 12 deletions
+19 -1
View File
@@ -20,6 +20,7 @@
let pollingInterval = $state('');
let baseVolumePath = $state('');
let notificationUrl = $state('');
let staleThresholdDays = $state('7');
let sslCertificateId = $state(0);
let sslCertName = $state('');
@@ -79,6 +80,7 @@
baseVolumePath = settings.base_volume_path ?? '';
sslCertificateId = settings.ssl_certificate_id ?? 0;
notificationUrl = settings.notification_url ?? '';
staleThresholdDays = String(settings.stale_threshold_days ?? 7);
} catch (err) {
toasts.error(err instanceof Error ? err.message : $t('settingsGeneral.loadFailed'));
} finally {
@@ -101,7 +103,8 @@
domain: domain.trim(), server_ip: serverIp.trim(), network: network.trim(),
subdomain_pattern: subdomainPattern.trim(), polling_interval: pollingInterval.trim(),
base_volume_path: baseVolumePath.trim(), notification_url: notificationUrl.trim(),
ssl_certificate_id: sslCertificateId
ssl_certificate_id: sslCertificateId,
stale_threshold_days: Math.max(1, parseInt(staleThresholdDays, 10) || 7)
});
toasts.success($t('settingsGeneral.saved'));
} catch (err) {
@@ -242,6 +245,21 @@
</div>
</div>
<!-- Stale Detection -->
<div class="mt-6 border-t border-[var(--border-primary)] pt-4">
<h3 class="mb-3 text-sm font-semibold text-[var(--text-primary)]">{$t('stale.title')}</h3>
<div class="max-w-xs">
<FormField
label={$t('settings.staleThreshold')}
name="staleThresholdDays"
type="number"
bind:value={staleThresholdDays}
placeholder="7"
helpText={$t('settings.staleThresholdHelp')}
/>
</div>
</div>
<div class="mt-6">
<button onclick={handleSave} disabled={saving} class="inline-flex items-center gap-2 rounded-lg bg-[var(--color-brand-600)] px-4 py-2.5 text-sm font-medium text-white shadow-sm transition-all duration-150 hover:bg-[var(--color-brand-700)] disabled:opacity-50 active:animate-press">
{#if saving}<IconLoader size={16} />{/if}