91e5cd58e9
Backend: - Scheduler lifecycle sync: create/update/delete tracker now syncs APScheduler jobs - Test-periodic/test-memory endpoints render actual Jinja2 templates with sample data - Cascade cleanup on tracker delete (TrackerState removed, EventLog nullified) - Fix user_id=0 FK violation for system-owned TemplateConfig (removed FK constraint) - Fix API key leak: only attach x-api-key header for internal provider URLs - Validate config ownership in tracker_targets create/update - Fix _response() double-emit of created_at in template/tracking configs - Add per-target-link test endpoints (test, test-periodic, test-memory) Frontend: - Fix orphaned provider on test exception in providers/new - Add submitting guard + disabled state to targets save button - Move test buttons from tracker card to per-target-link rows - Fix Svelte 5 async $state reactivity (spread reassignment for all Record mutations) - i18n for dashboard timeAgo and event type badges (EN + RU) - Add required attribute to chat select dropdown in targets - Fix font CSS vars to prioritize imported DM Sans / JetBrains Mono - Standardize empty states with centered icon + text across all 6 list pages - Add stagger-children animation class to all list containers - Fix slide transition duration consistency (200ms everywhere) - Standardize border-radius to rounded-md across all form inputs - Fix providers/new page structure (h2 + mb-8 spacing) - Fix tracker card action row overflow (flex-wrap justify-end) - JinjaEditor dark mode reactivity (recreate editor on theme change) - Add aria-labels to mobile nav items - Make ConfirmModal confirm button label/icon configurable - Remove double error reporting on providers page - Add telegram bot edit functionality (name editing via PUT) - i18n for External Domain label on provider forms Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
74 lines
1.9 KiB
Svelte
74 lines
1.9 KiB
Svelte
<script lang="ts">
|
|
import Modal from './Modal.svelte';
|
|
import MdiIcon from './MdiIcon.svelte';
|
|
import { t } from '$lib/i18n';
|
|
|
|
let { open = false, title = '', message = '', confirmLabel = '', confirmIcon = 'mdiDelete', onconfirm, oncancel } = $props<{
|
|
open: boolean;
|
|
title?: string;
|
|
message?: string;
|
|
confirmLabel?: string;
|
|
confirmIcon?: string;
|
|
onconfirm: () => void;
|
|
oncancel: () => void;
|
|
}>();
|
|
</script>
|
|
|
|
<Modal {open} title={title || t('common.confirm')} onclose={oncancel}>
|
|
<div class="flex items-start gap-3 mb-5">
|
|
<div class="flex items-center justify-center w-9 h-9 rounded-full flex-shrink-0"
|
|
style="background: var(--color-error-bg); color: var(--color-error-fg);">
|
|
<MdiIcon name="mdiAlertCircle" size={20} />
|
|
</div>
|
|
<p class="text-sm mt-1.5" style="color: var(--color-muted-foreground);">{message}</p>
|
|
</div>
|
|
<div class="flex gap-2 justify-end">
|
|
<button onclick={oncancel}
|
|
class="confirm-btn-cancel">
|
|
{t('common.cancel')}
|
|
</button>
|
|
<button onclick={onconfirm}
|
|
class="confirm-btn-delete">
|
|
<MdiIcon name={confirmIcon} size={15} />
|
|
{confirmLabel || t('common.delete')}
|
|
</button>
|
|
</div>
|
|
</Modal>
|
|
|
|
<style>
|
|
.confirm-btn-cancel {
|
|
padding: 0.5rem 1rem;
|
|
border-radius: 0.5rem;
|
|
font-size: 0.875rem;
|
|
border: 1px solid var(--color-border);
|
|
background: transparent;
|
|
color: var(--color-foreground);
|
|
cursor: pointer;
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.confirm-btn-cancel:hover {
|
|
background: var(--color-muted);
|
|
}
|
|
|
|
.confirm-btn-delete {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.375rem;
|
|
padding: 0.5rem 1rem;
|
|
border-radius: 0.5rem;
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
border: none;
|
|
background: var(--color-destructive);
|
|
color: white;
|
|
cursor: pointer;
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.confirm-btn-delete:hover {
|
|
box-shadow: 0 0 16px rgba(239, 68, 68, 0.3);
|
|
transform: translateY(-1px);
|
|
}
|
|
</style>
|