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:
@@ -18,8 +18,14 @@
|
||||
import { snackSuccess, snackError } from '$lib/stores/snackbar.svelte';
|
||||
import { highlightFromUrl } from '$lib/highlight';
|
||||
import { globalProviderFilter } from '$lib/stores/provider-filter.svelte';
|
||||
import { getDescriptor, buildTrackingFormDefaults } from '$lib/providers';
|
||||
import type { TrackingConfig } from '$lib/types';
|
||||
|
||||
/** Grid-select item source lookup — maps descriptor string name to actual function. */
|
||||
const gridItemSources: Record<string, () => any[]> = {
|
||||
sortByItems, sortOrderItems, albumModeItems, assetTypeItems, memorySourceItems,
|
||||
};
|
||||
|
||||
let allConfigs = $derived(trackingConfigsCache.items);
|
||||
let filterText = $state('');
|
||||
let filterType = $state('');
|
||||
@@ -34,34 +40,12 @@
|
||||
let error = $state('');
|
||||
let confirmDelete = $state<{ id: number; onconfirm: () => Promise<void> } | null>(null);
|
||||
|
||||
const defaultForm = () => ({
|
||||
const defaultForm = (): Record<string, any> => ({
|
||||
provider_type: '', name: '', icon: '',
|
||||
// Immich event tracking
|
||||
track_assets_added: true, track_assets_removed: false,
|
||||
track_collection_renamed: true, track_collection_deleted: true, track_sharing_changed: false,
|
||||
track_images: true, track_videos: true, notify_favorites_only: false,
|
||||
include_tags: true, include_asset_details: false,
|
||||
max_assets_to_show: 5, assets_order_by: 'none', assets_order: 'descending',
|
||||
periodic_enabled: false, periodic_interval_days: 1, periodic_start_date: '2025-01-01', periodic_times: '12:00',
|
||||
scheduled_enabled: false, scheduled_times: '09:00', scheduled_collection_mode: 'per_collection',
|
||||
scheduled_limit: 10, scheduled_favorite_only: false, scheduled_asset_type: 'all',
|
||||
scheduled_min_rating: 0, scheduled_order_by: 'random', scheduled_order: 'descending',
|
||||
memory_enabled: false, memory_source: 'albums', memory_times: '09:00', memory_collection_mode: 'combined',
|
||||
memory_limit: 10, memory_favorite_only: false, memory_asset_type: 'all', memory_min_rating: 0,
|
||||
// Scheduler event tracking
|
||||
track_scheduled_message: true,
|
||||
// Gitea event tracking
|
||||
track_push: true, track_issue_opened: true, track_issue_closed: true, track_issue_commented: false,
|
||||
track_pr_opened: true, track_pr_closed: true, track_pr_merged: true, track_pr_commented: false,
|
||||
track_release_published: true,
|
||||
// Planka event tracking
|
||||
track_card_created: true, track_card_updated: false, track_card_moved: true, track_card_deleted: false,
|
||||
track_card_commented: true, track_comment_updated: false,
|
||||
track_board_created: true, track_board_updated: false, track_board_deleted: true,
|
||||
track_list_created: false, track_list_updated: false, track_list_deleted: false,
|
||||
track_attachment_created: true, track_card_label_added: false, track_task_completed: true,
|
||||
...buildTrackingFormDefaults(),
|
||||
});
|
||||
let form = $state(defaultForm());
|
||||
let form: Record<string, any> = $state(defaultForm());
|
||||
let descriptor = $derived(getDescriptor(form.provider_type));
|
||||
|
||||
onMount(load);
|
||||
async function load() {
|
||||
@@ -130,137 +114,86 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Event tracking -->
|
||||
<!-- Event tracking — driven by descriptor -->
|
||||
{#if descriptor}
|
||||
<fieldset class="border border-[var(--color-border)] rounded-md p-3">
|
||||
<legend class="text-sm font-medium px-1">{t('trackingConfig.eventTracking')}</legend>
|
||||
{#if form.provider_type === 'scheduler'}
|
||||
<div class="grid grid-cols-2 gap-2 mt-2">
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_scheduled_message} /> {t('trackingConfig.scheduledMessage')}</label>
|
||||
{#each descriptor.eventFields as field (field.key)}
|
||||
<label class="flex items-center gap-2 text-sm">
|
||||
<input type="checkbox" bind:checked={form[field.key]} />
|
||||
{t(field.label)}
|
||||
{#if field.hint}<Hint text={t(field.hint)} />{/if}
|
||||
</label>
|
||||
{/each}
|
||||
</div>
|
||||
{:else if form.provider_type === 'gitea'}
|
||||
<div class="grid grid-cols-2 gap-2 mt-2">
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_push} /> {t('trackingConfig.push')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_issue_opened} /> {t('trackingConfig.issueOpened')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_issue_closed} /> {t('trackingConfig.issueClosed')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_issue_commented} /> {t('trackingConfig.issueCommented')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_pr_opened} /> {t('trackingConfig.prOpened')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_pr_closed} /> {t('trackingConfig.prClosed')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_pr_merged} /> {t('trackingConfig.prMerged')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_pr_commented} /> {t('trackingConfig.prCommented')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_release_published} /> {t('trackingConfig.releasePublished')}</label>
|
||||
</div>
|
||||
{:else if form.provider_type === 'planka'}
|
||||
<div class="grid grid-cols-2 gap-2 mt-2">
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_card_created} /> {t('trackingConfig.cardCreated')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_card_updated} /> {t('trackingConfig.cardUpdated')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_card_moved} /> {t('trackingConfig.cardMoved')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_card_deleted} /> {t('trackingConfig.cardDeleted')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_card_commented} /> {t('trackingConfig.cardCommented')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_comment_updated} /> {t('trackingConfig.commentUpdated')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_board_created} /> {t('trackingConfig.boardCreated')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_board_updated} /> {t('trackingConfig.boardUpdated')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_board_deleted} /> {t('trackingConfig.boardDeleted')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_list_created} /> {t('trackingConfig.listCreated')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_list_updated} /> {t('trackingConfig.listUpdated')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_list_deleted} /> {t('trackingConfig.listDeleted')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_attachment_created} /> {t('trackingConfig.attachmentCreated')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_card_label_added} /> {t('trackingConfig.cardLabelAdded')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_task_completed} /> {t('trackingConfig.taskCompleted')}</label>
|
||||
</div>
|
||||
{:else if form.provider_type === 'nut'}
|
||||
<div class="grid grid-cols-2 gap-2 mt-2">
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_ups_online} /> {t('trackingConfig.upsOnline')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_ups_on_battery} /> {t('trackingConfig.upsOnBattery')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_ups_low_battery} /> {t('trackingConfig.upsLowBattery')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_ups_battery_restored} /> {t('trackingConfig.upsBatteryRestored')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_ups_comms_lost} /> {t('trackingConfig.upsCommsLost')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_ups_comms_restored} /> {t('trackingConfig.upsCommsRestored')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_ups_replace_battery} /> {t('trackingConfig.upsReplaceBattery')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_ups_overload} /> {t('trackingConfig.upsOverload')}</label>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="grid grid-cols-2 gap-2 mt-2">
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_assets_added} /> {t('trackingConfig.assetsAdded')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_assets_removed} /> {t('trackingConfig.assetsRemoved')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_collection_renamed} /> {t('trackingConfig.albumRenamed')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_collection_deleted} /> {t('trackingConfig.albumDeleted')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_sharing_changed} /> {t('trackingConfig.sharingChanged')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_images} /> {t('trackingConfig.trackImages')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.track_videos} /> {t('trackingConfig.trackVideos')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.notify_favorites_only} /> {t('trackingConfig.favoritesOnly')}<Hint text={t('hints.favoritesOnly')} /></label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.include_tags} /> {t('trackingConfig.includePeople')}</label>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.include_asset_details} /> {t('trackingConfig.includeDetails')}</label>
|
||||
</div>
|
||||
{/if}
|
||||
{#if form.provider_type === 'immich'}
|
||||
{#if descriptor.extraTrackingFields?.length}
|
||||
<div class="grid grid-cols-3 gap-3 mt-3">
|
||||
<div>
|
||||
<label for="tc-max" class="block text-xs mb-1">{t('trackingConfig.maxAssets')}<Hint text={t('hints.maxAssets')} /></label>
|
||||
<input id="tc-max" type="number" bind:value={form.max_assets_to_show} min="0" max="50" class="w-full px-2 py-1 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs mb-1">{t('trackingConfig.sortBy')}</label>
|
||||
<IconGridSelect items={sortByItems()} bind:value={form.assets_order_by} columns={2} compact />
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs mb-1">{t('trackingConfig.sortOrder')}</label>
|
||||
<IconGridSelect items={sortOrderItems()} bind:value={form.assets_order} columns={2} compact />
|
||||
</div>
|
||||
{#each descriptor.extraTrackingFields as field (field.key)}
|
||||
<div>
|
||||
<label class="block text-xs mb-1">
|
||||
{t(field.label)}
|
||||
{#if field.hint}<Hint text={t(field.hint)} />{/if}
|
||||
</label>
|
||||
{#if field.type === 'grid-select' && field.gridItems}
|
||||
<IconGridSelect items={gridItemSources[field.gridItems]()} bind:value={form[field.key]} columns={field.gridColumns ?? 2} compact />
|
||||
{:else}
|
||||
<input type="number" bind:value={form[field.key]} min={field.min} max={field.max}
|
||||
class="w-full px-2 py-1 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" />
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</fieldset>
|
||||
|
||||
{#if form.provider_type === 'immich'}
|
||||
<!-- Periodic summary -->
|
||||
<!-- Feature sections (periodic, scheduled, memory) — driven by descriptor -->
|
||||
{#each descriptor.featureSections ?? [] as section (section.key)}
|
||||
<fieldset class="border border-[var(--color-border)] rounded-md p-3">
|
||||
<legend class="text-sm font-medium px-1">{t('trackingConfig.periodicSummary')}<Hint text={t('hints.periodicSummary')} /></legend>
|
||||
<label class="flex items-center gap-2 text-sm mt-1"><input type="checkbox" bind:checked={form.periodic_enabled} /> {t('trackingConfig.enabled')}</label>
|
||||
{#if form.periodic_enabled}
|
||||
<legend class="text-sm font-medium px-1">
|
||||
{t(section.legend)}
|
||||
{#if section.legendHint}<Hint text={t(section.legendHint)} />{/if}
|
||||
</legend>
|
||||
<label class="flex items-center gap-2 text-sm mt-1">
|
||||
<input type="checkbox" bind:checked={form[section.enabledField]} />
|
||||
{t('trackingConfig.enabled')}
|
||||
</label>
|
||||
{#if form[section.enabledField]}
|
||||
<div class="grid grid-cols-3 gap-3 mt-3">
|
||||
<div><label class="block text-xs mb-1">{t('trackingConfig.intervalDays')}</label><input type="number" bind:value={form.periodic_interval_days} min="1" class="w-full px-2 py-1 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" /></div>
|
||||
<div><label class="block text-xs mb-1">{t('trackingConfig.startDate')}<Hint text={t('hints.periodicStartDate')} /></label><input type="date" bind:value={form.periodic_start_date} class="w-full px-2 py-1 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" /></div>
|
||||
<div><label class="block text-xs mb-1">{t('trackingConfig.times')}<Hint text={t('hints.times')} /></label><input bind:value={form.periodic_times} placeholder="12:00" class="w-full px-2 py-1 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" /></div>
|
||||
{#each section.fields as field (field.key)}
|
||||
<div>
|
||||
<label class="block text-xs mb-1">
|
||||
{t(field.label)}
|
||||
{#if field.hint}<Hint text={t(field.hint)} />{/if}
|
||||
</label>
|
||||
{#if field.type === 'grid-select' && field.gridItems}
|
||||
<IconGridSelect items={gridItemSources[field.gridItems]()} bind:value={form[field.key]} columns={field.gridColumns ?? 2} compact />
|
||||
{:else}
|
||||
<input type={field.key.includes('date') ? 'date' : field.key.includes('times') ? 'text' : 'number'}
|
||||
bind:value={form[field.key]} min={field.min} max={field.max}
|
||||
placeholder={field.key.includes('times') ? String(field.defaultValue ?? '') : ''}
|
||||
class="w-full px-2 py-1 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" />
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
{#each section.checkboxes ?? [] as cb (cb.key)}
|
||||
<label class="flex items-center gap-2 text-sm">
|
||||
<input type="checkbox" bind:checked={form[cb.key]} />
|
||||
{t(cb.label)}
|
||||
{#if cb.hint}<Hint text={t(cb.hint)} />{/if}
|
||||
</label>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</fieldset>
|
||||
|
||||
<!-- Scheduled assets -->
|
||||
<fieldset class="border border-[var(--color-border)] rounded-md p-3">
|
||||
<legend class="text-sm font-medium px-1">{t('trackingConfig.scheduledAssets')}<Hint text={t('hints.scheduledAssets')} /></legend>
|
||||
<label class="flex items-center gap-2 text-sm mt-1"><input type="checkbox" bind:checked={form.scheduled_enabled} /> {t('trackingConfig.enabled')}</label>
|
||||
{#if form.scheduled_enabled}
|
||||
<div class="grid grid-cols-3 gap-3 mt-3">
|
||||
<div><label class="block text-xs mb-1">{t('trackingConfig.times')}<Hint text={t('hints.times')} /></label><input bind:value={form.scheduled_times} placeholder="09:00" class="w-full px-2 py-1 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" /></div>
|
||||
<div><label class="block text-xs mb-1">{t('trackingConfig.albumMode')}<Hint text={t('hints.albumMode')} /></label>
|
||||
<IconGridSelect items={albumModeItems()} bind:value={form.scheduled_collection_mode} columns={3} compact /></div>
|
||||
<div><label class="block text-xs mb-1">{t('trackingConfig.maxAssets')}<Hint text={t('hints.maxAssets')} /></label><input type="number" bind:value={form.scheduled_limit} min="1" max="100" class="w-full px-2 py-1 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" /></div>
|
||||
<div><label class="block text-xs mb-1">{t('trackingConfig.assetType')}</label>
|
||||
<IconGridSelect items={assetTypeItems()} bind:value={form.scheduled_asset_type} columns={3} compact /></div>
|
||||
<div><label class="block text-xs mb-1">{t('trackingConfig.minRating')}<Hint text={t('hints.minRating')} /></label><input type="number" bind:value={form.scheduled_min_rating} min="0" max="5" class="w-full px-2 py-1 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" /></div>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.scheduled_favorite_only} /> {t('trackingConfig.favoritesOnly')}<Hint text={t('hints.favoritesOnly')} /></label>
|
||||
{/each}
|
||||
{:else if form.provider_type}
|
||||
<Card>
|
||||
<div class="flex items-center gap-2 text-sm" style="color: var(--color-error-fg);">
|
||||
<MdiIcon name="mdiAlertCircle" size={18} />
|
||||
{t('trackingConfig.unknownProviderType')}: {form.provider_type}
|
||||
</div>
|
||||
{/if}
|
||||
</fieldset>
|
||||
|
||||
<!-- Memory mode -->
|
||||
<fieldset class="border border-[var(--color-border)] rounded-md p-3">
|
||||
<legend class="text-sm font-medium px-1">{t('trackingConfig.memoryMode')}<Hint text={t('hints.memoryMode')} /></legend>
|
||||
<label class="flex items-center gap-2 text-sm mt-1"><input type="checkbox" bind:checked={form.memory_enabled} /> {t('trackingConfig.enabled')}</label>
|
||||
{#if form.memory_enabled}
|
||||
<div class="grid grid-cols-3 gap-3 mt-3">
|
||||
<div><label class="block text-xs mb-1">{t('trackingConfig.memorySource')}<Hint text={t('hints.memorySource')} /></label>
|
||||
<IconGridSelect items={memorySourceItems()} bind:value={form.memory_source} columns={2} compact /></div>
|
||||
<div><label class="block text-xs mb-1">{t('trackingConfig.times')}<Hint text={t('hints.times')} /></label><input bind:value={form.memory_times} placeholder="09:00" class="w-full px-2 py-1 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" /></div>
|
||||
<div><label class="block text-xs mb-1">{t('trackingConfig.albumMode')}<Hint text={t('hints.albumMode')} /></label>
|
||||
<IconGridSelect items={albumModeItems()} bind:value={form.memory_collection_mode} columns={3} compact /></div>
|
||||
<div><label class="block text-xs mb-1">{t('trackingConfig.maxAssets')}<Hint text={t('hints.maxAssets')} /></label><input type="number" bind:value={form.memory_limit} min="1" max="100" class="w-full px-2 py-1 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" /></div>
|
||||
<div><label class="block text-xs mb-1">{t('trackingConfig.assetType')}</label>
|
||||
<IconGridSelect items={assetTypeItems()} bind:value={form.memory_asset_type} columns={3} compact /></div>
|
||||
<div><label class="block text-xs mb-1">{t('trackingConfig.minRating')}<Hint text={t('hints.minRating')} /></label><input type="number" bind:value={form.memory_min_rating} min="0" max="5" class="w-full px-2 py-1 border border-[var(--color-border)] rounded-md text-sm bg-[var(--color-background)]" /></div>
|
||||
<label class="flex items-center gap-2 text-sm"><input type="checkbox" bind:checked={form.memory_favorite_only} /> {t('trackingConfig.favoritesOnly')}<Hint text={t('hints.favoritesOnly')} /></label>
|
||||
</div>
|
||||
{/if}
|
||||
</fieldset>
|
||||
</Card>
|
||||
{/if}
|
||||
|
||||
<button type="submit" class="px-4 py-2 bg-[var(--color-primary)] text-[var(--color-primary-foreground)] rounded-md text-sm font-medium hover:opacity-90">
|
||||
@@ -294,6 +227,7 @@
|
||||
{:else}
|
||||
<div class="space-y-3 stagger-children">
|
||||
{#each configs as config}
|
||||
{@const desc = getDescriptor(config.provider_type)}
|
||||
<Card hover entityId={config.id}>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
@@ -303,7 +237,7 @@
|
||||
<span class="text-xs px-1.5 py-0.5 rounded bg-[var(--color-muted)] text-[var(--color-muted-foreground)] font-mono">{config.provider_type}</span>
|
||||
</div>
|
||||
<p class="text-sm text-[var(--color-muted-foreground)]">
|
||||
{[config.track_assets_added && t('trackingConfig.added'), config.track_assets_removed && t('trackingConfig.removed'), config.track_collection_renamed && t('trackingConfig.renamed'), config.track_collection_deleted && t('trackingConfig.deleted')].filter(Boolean).join(', ')}
|
||||
{(desc?.eventFields ?? []).filter(f => (config as Record<string, any>)[f.key]).map(f => t(f.label)).join(', ')}
|
||||
{config.periodic_enabled ? ` · ${t('trackingConfig.periodic')}` : ''}
|
||||
{config.scheduled_enabled ? ` · ${t('trackingConfig.scheduled')}` : ''}
|
||||
{config.memory_enabled ? ` · ${t('trackingConfig.memory')}` : ''}
|
||||
|
||||
Reference in New Issue
Block a user