diff --git a/CHANGELOG.md b/CHANGELOG.md index 79508b9..b4ff8ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- **Domain-based logo fallback for mail accounts**: `ProviderLogoBanner` now shows provider logos even for accounts that have no `provider_name` set, by extracting the domain from the email address and matching it against a new `DOMAIN_ICON_MAP`. Covers Gmail, GMX, WEB.DE, Yahoo Mail, AOL, T-Online, Outlook/Hotmail, IONOS, Freenet, iCloud, Posteo, and Proton Mail. + ### Fixed - Convert `frontend/jest.config.js` to `jest.config.mjs` using ES module `import`/`export` syntax to resolve ESLint `@typescript-eslint/no-require-imports` error. diff --git a/docs/TODO.md b/docs/TODO.md index 155921b..21e770b 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -21,6 +21,7 @@ Comprehensive task breakdown for repository improvements and production readines - [x] Fixed worker `send_user_notification` using rolled-back DB session causing `greenlet_spawn has not been called` errors; status/`last_check_at` now always committed before sending notifications via a fresh session. - [x] **Dashboard redesign**: Replaced noisy "Recent Processing Runs" table with a per-account "Mailbox Status" view showing last-check status (OK/Error/Pending), relative timestamp, error messages, and lifetime counters. Stats cards updated to show all-time processed count and accounts-with-errors count. - [x] **Provider logos now saved on account creation**: `provider_name` field added to `MailAccountCreate` and `MailAccountUpdate` schemas (backend and frontend). `ProviderWizard` now passes `provider_name` in its `onSelect` callback; `AddMailAccountModal` stores it so logos are displayed correctly on the accounts page. +- [x] **Domain-based logo fallback**: `ProviderLogoBanner` now falls back to email-domain matching when `provider_name` is absent, so all known providers (GMX, WEB.DE, T-Online, etc.) show their logo even on legacy accounts. - [x] **Fetch button UX improvements**: The "fetch emails" button on the accounts page now shows a "Fetch" text label for clarity, a tooltip explaining its purpose, a spinning "Fetching…" state during the API call, and a brief green "Queued!" confirmation after success. - [x] **Pull Now**: Added "Pull Now" button on Accounts page that immediately queues a `process_mail_account` Celery task via `POST /mail-accounts/{id}/pull-now`. Button shows spinner while in flight and is disabled for inactive accounts. diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 671ba1c..3aad4d0 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -2819,7 +2819,7 @@ "version": "19.2.10", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.10.tgz", "integrity": "sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "csstype": "^3.2.2" @@ -4256,7 +4256,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/damerau-levenshtein": { diff --git a/frontend/src/app/accounts/page.tsx b/frontend/src/app/accounts/page.tsx index 714aa91..6409e1a 100644 --- a/frontend/src/app/accounts/page.tsx +++ b/frontend/src/app/accounts/page.tsx @@ -26,20 +26,60 @@ const PROVIDER_ICON_MAP: Record = { 'Proton Mail': 'protonmail', }; +// Fallback: map email domains to SVG icon filenames for accounts without a provider_name +const DOMAIN_ICON_MAP: Record = { + // Gmail + 'gmail.com': 'gmail', 'googlemail.com': 'gmail', + // GMX + 'gmx.de': 'gmx', 'gmx.net': 'gmx', 'gmx.at': 'gmx', 'gmx.ch': 'gmx', 'gmx.com': 'gmx', + // WEB.DE + 'web.de': 'webde', + // Outlook / Hotmail + 'outlook.com': 'outlook', 'hotmail.com': 'outlook', 'live.com': 'outlook', + 'msn.com': 'outlook', 'outlook.de': 'outlook', + // Yahoo Mail + 'yahoo.com': 'yahoo', 'yahoo.de': 'yahoo', 'yahoo.co.uk': 'yahoo', 'ymail.com': 'yahoo', + // AOL Mail + 'aol.com': 'aol', 'aim.com': 'aol', + // T-Online + 't-online.de': 'tonline', + // 1&1 / IONOS + 'online.de': 'ionos', 'onlinehome.de': 'ionos', '1und1.de': 'ionos', + // Freenet + 'freenet.de': 'freenet', + // iCloud Mail + 'icloud.com': 'icloud', 'me.com': 'icloud', 'mac.com': 'icloud', + // Posteo + 'posteo.de': 'posteo', 'posteo.net': 'posteo', + // Proton Mail + 'proton.me': 'protonmail', 'protonmail.com': 'protonmail', + 'protonmail.ch': 'protonmail', 'pm.me': 'protonmail', +}; + /** * Full-width logo banner rendered at the top of a card. * Uses next/image fill + object-contain so every logo – regardless of its * native aspect ratio (1:1 square up to ~6:1 wordmark) – fits correctly * inside the fixed-height strip without distortion. + * + * Resolves the icon by first checking provider_name, then falling back to + * the email domain so that accounts created without a provider_name still + * show the correct logo. */ -function ProviderLogoBanner({ providerName }: { providerName?: string | null }) { - const icon = providerName ? PROVIDER_ICON_MAP[providerName] : undefined; +function ProviderLogoBanner({ providerName, email }: { providerName?: string | null; email?: string | null }) { + let icon = providerName ? PROVIDER_ICON_MAP[providerName] : undefined; + if (!icon && email) { + const atIndex = email.lastIndexOf('@'); + const domain = atIndex !== -1 ? email.slice(atIndex + 1).toLowerCase() : undefined; + if (domain) icon = DOMAIN_ICON_MAP[domain]; + } if (!icon) return null; + const label = providerName ?? email?.split('@')[1] ?? 'provider'; return (
{`${providerName} {/* Provider logo banner – full-width strip that accommodates any aspect ratio */} - +