feat: add Scheduler provider + multi-provider UX fixes
Scheduler provider: - Virtual provider (no external service) that emits SCHEDULED_MESSAGE events on user-defined intervals or cron expressions - Custom variables stored in tracker filters, flattened into template context - fire_count persists across triggers via tracker state - APScheduler CronTrigger support for cron-mode schedules - Default templates (EN+RU), seeded on startup Multi-provider UX fixes: - Tracking config hides Immich-specific sections (periodic, scheduled, memory, asset display) for non-Immich providers - Command config driven by provider capabilities — hides commands/settings for providers without bot commands - Template config hides empty "Scheduled Messages" group - Test menu on tracker targets is provider-aware (Immich shows all 4 test types, others show only basic) - Removed redundant Test button from tracker card - System-owned tracking configs (user_id=0) seeded for Gitea + Scheduler - Fixed ownership checks to allow system configs in tracker-target links - Capabilities cache shared across template-configs and command-configs - Command tracker bot selector uses EntitySelect instead of raw select - Sample context includes Gitea + Scheduler variables for template preview
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
import { slide } from 'svelte/transition';
|
||||
import { api } from '$lib/api';
|
||||
import { t } from '$lib/i18n';
|
||||
import { templateConfigsCache } from '$lib/stores/caches.svelte';
|
||||
import { templateConfigsCache, capabilitiesCache } from '$lib/stores/caches.svelte';
|
||||
import PageHeader from '$lib/components/PageHeader.svelte';
|
||||
import Card from '$lib/components/Card.svelte';
|
||||
import Loading from '$lib/components/Loading.svelte';
|
||||
@@ -109,8 +109,8 @@
|
||||
let form = $state(defaultForm());
|
||||
let previewTargetType = $state('telegram');
|
||||
|
||||
// Provider capabilities: loaded dynamically
|
||||
let allCapabilities = $state<Record<string, any>>({});
|
||||
// Provider capabilities: from shared cache
|
||||
let allCapabilities = $derived(capabilitiesCache.items);
|
||||
let providerTypes = $derived(Object.keys(allCapabilities));
|
||||
|
||||
// Dynamic slot definitions based on selected provider_type
|
||||
@@ -137,10 +137,10 @@
|
||||
onMount(load);
|
||||
async function load() {
|
||||
try {
|
||||
[, varsRef, allCapabilities] = await Promise.all([
|
||||
[, varsRef] = await Promise.all([
|
||||
templateConfigsCache.fetch(true),
|
||||
api('/template-configs/variables'),
|
||||
api('/providers/capabilities'),
|
||||
capabilitiesCache.fetch(),
|
||||
]);
|
||||
} catch (err: any) { error = err.message || t('common.loadError'); snackError(error); }
|
||||
finally { loaded = true; highlightFromUrl(); }
|
||||
@@ -284,7 +284,7 @@
|
||||
<IconGridSelect items={previewTargetTypeItems()} bind:value={previewTargetType} columns={2} />
|
||||
</div>
|
||||
|
||||
{#each templateSlots as group}
|
||||
{#each templateSlots.filter(g => g.slots.length > 0) as group}
|
||||
<fieldset class="border border-[var(--color-border)] rounded-md p-3">
|
||||
<legend class="text-sm font-medium px-1">{t(`templateConfig.${group.group}`)}{#if group.group === 'eventMessages'}<Hint text={t('hints.eventMessages')} />{:else if group.group === 'scheduledMessages'}<Hint text={t('hints.scheduledMessages')} />{/if}</legend>
|
||||
<div class="space-y-3 mt-2">
|
||||
|
||||
Reference in New Issue
Block a user