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:
@@ -35,10 +35,12 @@
|
||||
...allProviders.map(p => ({ value: p.id, icon: providerDefaultIcon(p), label: p.name, desc: p.type })),
|
||||
]);
|
||||
let providerFilterValue = $state(globalProviderFilter.id ?? 0);
|
||||
let _syncingFilter = false;
|
||||
|
||||
// Sync filter value → store
|
||||
$effect(() => {
|
||||
const v = providerFilterValue;
|
||||
if (_syncingFilter) return;
|
||||
globalProviderFilter.set(v === 0 ? null : v);
|
||||
});
|
||||
|
||||
@@ -46,7 +48,9 @@
|
||||
$effect(() => {
|
||||
const storeId = globalProviderFilter.id;
|
||||
if (storeId === null && providerFilterValue !== 0) {
|
||||
_syncingFilter = true;
|
||||
providerFilterValue = 0;
|
||||
_syncingFilter = false;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -85,6 +89,11 @@
|
||||
ptype ? items.filter(i => i.provider_type === ptype) : items;
|
||||
|
||||
const targets = targetsCache.items;
|
||||
// Single pass to count targets by type
|
||||
const targetsByType = new Map<string, number>();
|
||||
for (const t of targets) {
|
||||
targetsByType.set(t.type, (targetsByType.get(t.type) || 0) + 1);
|
||||
}
|
||||
return {
|
||||
providers: pid ? 1 : providersCache.items.length,
|
||||
notification_trackers: filterById(notificationTrackersCache.items as any[]).length,
|
||||
@@ -97,14 +106,14 @@
|
||||
telegram_bots: telegramBotsCache.items.length,
|
||||
email_bots: emailBotsCache.items.length,
|
||||
matrix_bots: matrixBotsCache.items.length,
|
||||
targets_telegram: targets.filter(t => t.type === 'telegram').length,
|
||||
targets_webhook: targets.filter(t => t.type === 'webhook').length,
|
||||
targets_email: targets.filter(t => t.type === 'email').length,
|
||||
targets_discord: targets.filter(t => t.type === 'discord').length,
|
||||
targets_slack: targets.filter(t => t.type === 'slack').length,
|
||||
targets_ntfy: targets.filter(t => t.type === 'ntfy').length,
|
||||
targets_matrix: targets.filter(t => t.type === 'matrix').length,
|
||||
targets_broadcast: targets.filter(t => t.type === 'broadcast').length,
|
||||
targets_telegram: targetsByType.get('telegram') || 0,
|
||||
targets_webhook: targetsByType.get('webhook') || 0,
|
||||
targets_email: targetsByType.get('email') || 0,
|
||||
targets_discord: targetsByType.get('discord') || 0,
|
||||
targets_slack: targetsByType.get('slack') || 0,
|
||||
targets_ntfy: targetsByType.get('ntfy') || 0,
|
||||
targets_matrix: targetsByType.get('matrix') || 0,
|
||||
targets_broadcast: targetsByType.get('broadcast') || 0,
|
||||
} as Record<string, number>;
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user