refactor: provider descriptor registry — eliminate provider-specific hardcoding
Replace all if/else chains keyed on provider type strings with a descriptor-driven architecture. Each provider type (immich, gitea, planka, scheduler, nut, google_photos) has a descriptor in frontend/src/lib/providers/ that declares config fields, event tracking fields, collection metadata, validation, and hooks. Components now use getDescriptor(type) and render dynamically. Dashboard provider card shows provider name + type when global filter is active. Grid-items derived from registry.
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
import EntitySelect from '$lib/components/EntitySelect.svelte';
|
||||
import { eventTypeFilterItems, sortFilterItems, providerDefaultIcon } from '$lib/grid-items';
|
||||
import { globalProviderFilter } from '$lib/stores/provider-filter.svelte';
|
||||
import { getDescriptor } from '$lib/providers';
|
||||
|
||||
import type { DashboardStatus } from '$lib/types';
|
||||
let status = $state<DashboardStatus | null>(null);
|
||||
@@ -181,8 +182,18 @@
|
||||
? providers.filter(p => p.type === globalProviderFilter.providerType).length
|
||||
: displayProviders);
|
||||
|
||||
const statCards = $derived(status ? [
|
||||
{ icon: 'mdiServer', label: 'dashboard.providers', value: filteredProviderCount, color: '#0d9488' },
|
||||
const providerCard = $derived.by(() => {
|
||||
const gp = globalProviderFilter.provider;
|
||||
if (gp) {
|
||||
const desc = getDescriptor(gp.type);
|
||||
return { icon: providerDefaultIcon(gp), label: '', literalLabel: desc?.defaultName ?? gp.type, value: 0, literalValue: gp.name, color: '#0d9488' };
|
||||
}
|
||||
return { icon: 'mdiServer', label: 'dashboard.providers', value: filteredProviderCount, color: '#0d9488' };
|
||||
});
|
||||
|
||||
interface StatCard { icon: string; label: string; literalLabel?: string; value: number; literalValue?: string; suffix?: string; color: string }
|
||||
const statCards = $derived<StatCard[]>(status ? [
|
||||
providerCard,
|
||||
{ icon: 'mdiRadar', label: 'dashboard.activeTrackers', value: displayActive, suffix: ` / ${displayTotal}`, color: '#6366f1' },
|
||||
{ icon: 'mdiTarget', label: 'dashboard.targets', value: displayTargets, color: '#f59e0b' },
|
||||
...(status.command_trackers !== undefined ? [{ icon: 'mdiConsoleLine', label: 'nav.commandTrackers', value: displayCommandTrackers, color: '#8b5cf6' }] : []),
|
||||
@@ -238,9 +249,9 @@
|
||||
<MdiIcon name={card.icon} size={22} />
|
||||
</div>
|
||||
<div>
|
||||
<p class="text-sm" style="color: var(--color-muted-foreground);">{t(card.label)}</p>
|
||||
<p class="text-sm" style="color: var(--color-muted-foreground);">{card.literalLabel || t(card.label)}</p>
|
||||
<p class="stat-value font-mono" style="animation-delay: {i * 80 + 200}ms;">
|
||||
{card.value}{#if card.suffix}<span class="stat-suffix">{card.suffix}</span>{/if}
|
||||
{#if card.literalValue}{card.literalValue}{:else}{card.value}{/if}{#if card.suffix}<span class="stat-suffix">{card.suffix}</span>{/if}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user