Add MDI icon picker to all entity types
Some checks failed
Validate / Hassfest (push) Has been cancelled

- Install @mdi/js (~7000 Material Design Icons)
- IconPicker component: dropdown with search, popular icons grid,
  clear option. Stores icon name as string (e.g. "mdiCamera")
- MdiIcon component: renders SVG from icon name
- Backend: add `icon` field to ImmichServer, TelegramBot,
  TrackingConfig, TemplateConfig, NotificationTarget, AlbumTracker
- All 6 entity pages: icon picker next to name input in create/edit
  forms, icon displayed on entity cards

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-19 18:01:22 +03:00
parent af9bfb7b22
commit 5a0b0b78f6
11 changed files with 182 additions and 24 deletions

View File

@@ -5,6 +5,8 @@
import PageHeader from '$lib/components/PageHeader.svelte';
import Card from '$lib/components/Card.svelte';
import Loading from '$lib/components/Loading.svelte';
import IconPicker from '$lib/components/IconPicker.svelte';
import MdiIcon from '$lib/components/MdiIcon.svelte';
let configs = $state<any[]>([]);
let loaded = $state(false);
@@ -13,7 +15,7 @@
let error = $state('');
const defaultForm = () => ({
name: '', track_assets_added: true, track_assets_removed: false,
name: '', icon: '', track_assets_added: true, track_assets_removed: false,
track_album_renamed: true, track_album_deleted: true,
track_images: true, track_videos: true, notify_favorites_only: false,
include_people: true, include_asset_details: false,
@@ -66,8 +68,11 @@
<form onsubmit={save} class="space-y-5">
<div>
<label for="tc-name" class="block text-sm font-medium mb-1">{t('trackingConfig.name')}</label>
<input id="tc-name" bind:value={form.name} required placeholder={t('trackingConfig.namePlaceholder')}
class="w-full px-3 py-2 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" />
<div class="flex gap-2">
<IconPicker value={form.icon} onselect={(v) => form.icon = v} />
<input id="tc-name" bind:value={form.name} required placeholder={t('trackingConfig.namePlaceholder')}
class="flex-1 px-3 py-2 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" />
</div>
</div>
<!-- Event tracking -->
@@ -183,7 +188,10 @@
<Card>
<div class="flex items-center justify-between">
<div>
<p class="font-medium">{config.name}</p>
<div class="flex items-center gap-2">
{#if config.icon}<MdiIcon name={config.icon} />{/if}
<p class="font-medium">{config.name}</p>
</div>
<p class="text-sm text-[var(--color-muted-foreground)]">
{[config.track_assets_added && 'added', config.track_assets_removed && 'removed', config.track_album_renamed && 'renamed', config.track_album_deleted && 'deleted'].filter(Boolean).join(', ')}
{config.periodic_enabled ? ' · periodic' : ''}