feat: default tracker configs, email validation, expandable target links
- Tracker now has default_tracking_config_id and default_template_config_id that apply to all linked targets unless overridden per-target - Dispatch falls back to tracker defaults when per-link configs are null - Email bot creation validates SMTP connection before saving - Email notifications sent as HTML (links render properly) - Linked target items are expandable: collapsed shows config CrossLinks, expanded shows config selectors; action buttons always visible - Fix email bot test button icon (mdiEmailSend → mdiSend) - Fix target type icons in LinkedTargetsSection for all types - Provider filter moved above search in sidebar
This commit is contained in:
@@ -61,6 +61,7 @@
|
||||
const defaultForm = () => ({
|
||||
name: '', icon: '', provider_id: 0, collection_ids: [] as string[],
|
||||
scan_interval: 60, batch_duration: 0,
|
||||
default_tracking_config_id: 0, default_template_config_id: 0,
|
||||
filters: {} as Record<string, any>,
|
||||
});
|
||||
let form = $state(defaultForm());
|
||||
@@ -143,6 +144,8 @@
|
||||
name: trk.name, icon: trk.icon || '', provider_id: trk.provider_id,
|
||||
collection_ids: [...(trk.collection_ids || [])],
|
||||
scan_interval: trk.scan_interval, batch_duration: trk.batch_duration ?? 0,
|
||||
default_tracking_config_id: (trk as any).default_tracking_config_id || 0,
|
||||
default_template_config_id: (trk as any).default_template_config_id || 0,
|
||||
filters: trk.filters || {},
|
||||
};
|
||||
previousCollectionIds = [...(trk.collection_ids || [])];
|
||||
@@ -179,11 +182,16 @@
|
||||
async function doSave() {
|
||||
submitting = true;
|
||||
try {
|
||||
const payload = {
|
||||
...form,
|
||||
default_tracking_config_id: form.default_tracking_config_id || null,
|
||||
default_template_config_id: form.default_template_config_id || null,
|
||||
};
|
||||
if (editing) {
|
||||
await api(`/notification-trackers/${editing}`, { method: 'PUT', body: JSON.stringify(form) });
|
||||
await api(`/notification-trackers/${editing}`, { method: 'PUT', body: JSON.stringify(payload) });
|
||||
snackSuccess(t('snack.trackerUpdated'));
|
||||
} else {
|
||||
await api('/notification-trackers', { method: 'POST', body: JSON.stringify(form) });
|
||||
await api('/notification-trackers', { method: 'POST', body: JSON.stringify(payload) });
|
||||
snackSuccess(t('snack.trackerCreated'));
|
||||
}
|
||||
showForm = false; editing = null; linkWarning = null; await load();
|
||||
@@ -371,6 +379,8 @@
|
||||
{providerItems}
|
||||
{collections}
|
||||
bind:collectionFilter
|
||||
trackingConfigItems={trackingConfigs.filter(c => !selectedProviderType || c.provider_type === selectedProviderType).map(c => ({ value: c.id, label: c.name, icon: (c as any).icon || 'mdiCog' }))}
|
||||
templateConfigItems={templateConfigs.filter(c => !selectedProviderType || c.provider_type === selectedProviderType).map(c => ({ value: c.id, label: c.name, icon: (c as any).icon || 'mdiFileDocumentEdit' }))}
|
||||
{editing}
|
||||
{submitting}
|
||||
{linkCheckLoading}
|
||||
@@ -406,7 +416,7 @@
|
||||
</Card>
|
||||
{:else if !showForm}
|
||||
<div class="space-y-3 stagger-children">
|
||||
{#each notificationTrackers as tracker}
|
||||
{#each notificationTrackers as tracker (tracker.id)}
|
||||
<Card hover entityId={tracker.id}>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user