feat: deferred dispatch, release-check provider, settings polish
- Defer quiet-hours dispatches into new deferred_dispatch table; drain job + periodic catch-up scan re-fire at window end with coalescing on (link, event_type, collection_id). - Add ON DELETE SET NULL migration on event_log_id and partial unique index on (link_id, collection_id, event_type) WHERE status='pending'. - Add release-check provider abstraction (Gitea/GitHub) with SSRF-safe URL validation, settings UI cassette, and scheduled polling. - Replace importlib-only version lookup with version.py helper that prefers the higher of installed metadata vs source pyproject so stale editable dev installs stop misreporting. - Aurora frontend polish: MetaStrip component, ReleaseCassette, EventDetailModal expansion, and i18n additions.
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
import { snackSuccess, snackError } from '$lib/stores/snackbar.svelte';
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
import ErrorBanner from '$lib/components/ErrorBanner.svelte';
|
||||
import MetaStrip, { type MetaTile } from '$lib/components/MetaStrip.svelte';
|
||||
import type { EmailBot } from '$lib/types';
|
||||
|
||||
let { onreload }: { onreload: () => Promise<void> } = $props();
|
||||
@@ -39,6 +40,30 @@
|
||||
}
|
||||
});
|
||||
|
||||
function emailBotTiles(bot: EmailBot): MetaTile[] {
|
||||
const tiles: MetaTile[] = [];
|
||||
tiles.push({
|
||||
icon: 'mdiEmailOutline',
|
||||
label: bot.email,
|
||||
tone: 'lavender',
|
||||
mono: true,
|
||||
});
|
||||
tiles.push({
|
||||
icon: 'mdiServerNetwork',
|
||||
label: `${bot.smtp_host}:${bot.smtp_port}`,
|
||||
tone: 'sky',
|
||||
mono: true,
|
||||
});
|
||||
if (bot.smtp_use_tls) {
|
||||
tiles.push({
|
||||
icon: 'mdiLockOutline',
|
||||
label: 'TLS',
|
||||
tone: 'mint',
|
||||
});
|
||||
}
|
||||
return tiles;
|
||||
}
|
||||
|
||||
function openNewEmail() { emailForm = defaultEmailForm(); nameManuallyEdited = false; editingEmail = null; showEmailForm = true; }
|
||||
function editEmailBot(bot: EmailBot) {
|
||||
emailForm = {
|
||||
@@ -165,16 +190,16 @@
|
||||
<EmptyState icon="mdiEmailOutline" message={t('emailBot.noBots')} />
|
||||
</Card>
|
||||
{:else}
|
||||
<div class="space-y-3 stagger-children">
|
||||
<div class="list-stack stagger-children">
|
||||
{#each emailBots as bot}
|
||||
<Card hover entityId={bot.id}>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span style="color: var(--color-primary);"><MdiIcon name={bot.icon || 'mdiEmailOutline'} size={20} /></span>
|
||||
<p class="font-medium">{bot.name}</p>
|
||||
<div class="list-row">
|
||||
<div class="list-row__identity">
|
||||
<div class="flex items-center gap-2 min-w-0">
|
||||
<span style="color: var(--color-primary);" class="shrink-0"><MdiIcon name={bot.icon || 'mdiEmailOutline'} size={20} /></span>
|
||||
<p class="font-medium truncate">{bot.name}</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 mt-1 flex-wrap">
|
||||
<div class="flex items-center gap-2 mt-1 flex-wrap list-row__secondary">
|
||||
<span class="text-xs text-[var(--color-muted-foreground)] font-mono">{bot.email}</span>
|
||||
<span class="text-xs px-1.5 py-0.5 rounded bg-[var(--color-muted)] text-[var(--color-muted-foreground)]">{bot.smtp_host}:{bot.smtp_port}</span>
|
||||
{#if bot.smtp_use_tls}
|
||||
@@ -182,7 +207,8 @@
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-1">
|
||||
<MetaStrip tiles={emailBotTiles(bot)} />
|
||||
<div class="list-row__actions">
|
||||
<IconButton icon="mdiSend" title={t('emailBot.testConnection')} onclick={() => testEmailBot(bot.id)} disabled={emailTesting[bot.id]} />
|
||||
<IconButton icon="mdiPencil" title={t('common.edit')} onclick={() => editEmailBot(bot)} />
|
||||
<IconButton icon="mdiDelete" title={t('common.delete')} onclick={() => removeEmail(bot.id)} variant="danger" />
|
||||
|
||||
Reference in New Issue
Block a user