mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-10-30 16:47:01 +09:00
Reusable, non-blocking notification layer on top of the Queue Bus: notify.send(event, to, data) records a Notification + per-channel NotificationDelivery, queues them, and a daemon consumer delivers via pluggable channel adapters (in-app, email, chat) inheriting retry, backoff and dead-letter. - Jinja2 email system: branded, dark-mode, Outlook-safe base layout + per-event templates (security/backup/monitoring/welcome/invitation). The legacy inline f-string email was removed and now renders here. - In-app center API (inbox/unread-count/mark-read) + per-user Socket.IO push. - Admin delivery log (stats/filter/retry). - Email providers (SMTP/SendGrid/Postmark/SES/Mailgun) with encrypted credentials + test; the email adapter prefers the default provider and falls back to the legacy SMTP config; surfaced in ConnectionRegistry. - NotificationService.send_all() is now a non-blocking shim that routes system alerts through the bus. Migrations 023 + 024. Tests: backend/tests/test_notification_bus.py (20). Full suite: 391 passed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
48 lines
1.9 KiB
Python
48 lines
1.9 KiB
Python
"""Brand tokens for rendered notifications.
|
|
|
|
Single source of truth for the colors/wordmark used by email templates (and,
|
|
later, any other rich channel). Mirrors the frontend SCSS design system
|
|
(`frontend/src/styles/_variables.scss`) so email matches the app:
|
|
|
|
accent #6d7cff success #3ddc97 warning #f5b945 danger #fb6f6f
|
|
|
|
The severity *tints* below are tuned for legibility on a light email canvas
|
|
(emails render light-first; a dark-mode media query swaps the chrome).
|
|
"""
|
|
|
|
BRAND = {
|
|
'name': 'ServerKit',
|
|
'accent': '#6d7cff',
|
|
'accent_hover': '#5a67e8',
|
|
# Light canvas
|
|
'page_bg': '#eef0f6',
|
|
'card_bg': '#ffffff',
|
|
'border': '#e6e8f0',
|
|
'ink': '#1b1e2b', # primary text
|
|
'muted': '#646b7d', # secondary text
|
|
'faint': '#9aa1b2', # footer / least important
|
|
'code_bg': '#f3f4f9', # monospace value chips
|
|
# Dark canvas (used by the prefers-color-scheme media query)
|
|
'dark_page_bg': '#0f1117',
|
|
'dark_card_bg': '#171a23',
|
|
'dark_border': '#272b38',
|
|
'dark_ink': '#e9ebf2',
|
|
'dark_muted': '#9aa1b2',
|
|
'dark_code_bg': '#1f2330',
|
|
}
|
|
|
|
# Per-severity styling: a light tint background, a readable text color, and a
|
|
# saturated dot — all solid hex so they survive every email client.
|
|
SEVERITY_STYLES = {
|
|
'critical': {'bg': '#fdecec', 'text': '#c0392b', 'dot': '#fb6f6f', 'label': 'Critical'},
|
|
'warning': {'bg': '#fdf5e3', 'text': '#9a6a12', 'dot': '#f5b945', 'label': 'Warning'},
|
|
'info': {'bg': '#eef0ff', 'text': '#454dc4', 'dot': '#6d7cff', 'label': 'Info'},
|
|
'success': {'bg': '#e7f9f1', 'text': '#11784f', 'dot': '#3ddc97', 'label': 'Success'},
|
|
'test': {'bg': '#f1f2f6', 'text': '#5b6170', 'dot': '#9aa1b2', 'label': 'Test'},
|
|
}
|
|
|
|
|
|
def style_for(severity):
|
|
"""Return the tint/text/dot triple for a severity (falls back to info)."""
|
|
return SEVERITY_STYLES.get(severity, SEVERITY_STYLES['info'])
|