diff --git a/CHANGELOG.md b/CHANGELOG.md index 591f508..9147dfe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix timezone display in Mailbox Activity / Admin Logs pages: timestamps from the server were parsed as local time when no timezone indicator was present, causing relative times ("1h ago") and absolute dates to be shifted by the client's UTC offset. - Worker tasks: use a fresh DB session for `send_user_notification` calls and move notifications after `db.commit()` to prevent the post-rollback `greenlet_spawn` SQLAlchemy error. - Worker tasks: ensure `last_check_at` and error status are always committed before notifications, fixing accounts being endlessly re-queued after IMAP auth failures. +## v0.4.0 (2026-03-28) + +### Features + +- **dashboard**: Replace per-run table with per-account Mailbox Status view + ([`6afd7c8`](https://github.com/christianlouis/InboxConverge/commit/6afd7c871e7c694a93f119aa66f1b798c9b5b2bd)) + + +## [Unreleased] + +### Changed + +- Dashboard "Recent Processing Runs" table replaced with a per-account **Mailbox Status** view: each account now shows its last-check status (OK / Error / Pending), relative last-check time, any error message, and lifetime processed/failed counters. The noisy per-run table is gone; full activity history remains available on the Logs page. +- Stats cards updated: "Emails Forwarded Today" → "Emails Processed" (all-time total from account records); "Errors" → "Accounts with Errors" (count of accounts currently showing an error). +### Fixed +- Provider logos now appear on the Mail Accounts page: `provider_name` is correctly saved when creating accounts via the provider wizard and propagated through backend/frontend schemas. +- Fetch-emails button now shows a text label ("Fetch"), a descriptive tooltip, a "Fetching…" loading state, and a brief green "Queued!" confirmation after the action completes. ## v0.3.2 (2026-03-28) diff --git a/backend/app/api/v1/endpoints/mail_accounts.py b/backend/app/api/v1/endpoints/mail_accounts.py index 3d870f4..34174a2 100644 --- a/backend/app/api/v1/endpoints/mail_accounts.py +++ b/backend/app/api/v1/endpoints/mail_accounts.py @@ -104,6 +104,7 @@ async def create_mail_account( check_interval_minutes=account_in.check_interval_minutes, max_emails_per_check=account_in.max_emails_per_check, delete_after_forward=account_in.delete_after_forward, + provider_name=account_in.provider_name, ) db.add(account) diff --git a/backend/app/models/schemas.py b/backend/app/models/schemas.py index 51d6fff..f630f60 100644 --- a/backend/app/models/schemas.py +++ b/backend/app/models/schemas.py @@ -113,6 +113,7 @@ class MailAccountBase(BaseModel): check_interval_minutes: int = Field(default=5, gt=0, le=1440) max_emails_per_check: int = Field(default=50, gt=0, le=1000) delete_after_forward: bool = True + provider_name: Optional[str] = Field(None, max_length=100) class MailAccountCreate(MailAccountBase): @@ -135,6 +136,7 @@ class MailAccountUpdate(BaseModel): check_interval_minutes: Optional[int] = Field(None, gt=0, le=1440) max_emails_per_check: Optional[int] = Field(None, gt=0, le=1000) delete_after_forward: Optional[bool] = None + provider_name: Optional[str] = Field(None, max_length=100) class MailAccountResponse(MailAccountBase): diff --git a/docs/TODO.md b/docs/TODO.md index 243de06..a1709bf 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -6,6 +6,10 @@ Comprehensive task breakdown for repository improvements and production readines - [x] Fixed timezone display bug in Mailbox Activity and Admin Logs pages: ISO timestamps without a `Z` suffix were parsed as local time by JavaScript, shifting "Xm ago" / "Xh ago" displays and absolute dates by the client's UTC offset. - [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] **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. - [x] Fixed 21 mypy type errors: `Column[T]` vs native type mismatches in `notification_service.py`, `mail_processor.py`, `auth.py`, `tasks.py`, `providers.py`, `mail_accounts.py`, and `main.py` (`lifespan` parameter rename). - [x] **Provider logos rework**: Logos now displayed as full-width banner strips at the top of each account card using `next/image fill + object-contain`. Handles all aspect ratios (1:1 square to 6:1 wordmark) without distortion. Proton Mail added. diff --git a/frontend/src/app/accounts/page.tsx b/frontend/src/app/accounts/page.tsx index 6e6aae5..714aa91 100644 --- a/frontend/src/app/accounts/page.tsx +++ b/frontend/src/app/accounts/page.tsx @@ -53,6 +53,7 @@ export default function AccountsPage() { const [isModalOpen, setIsModalOpen] = useState(false); const [editingAccount, setEditingAccount] = useState(null); const [pullingIds, setPullingIds] = useState>(new Set()); + const [successIds, setSuccessIds] = useState>(new Set()); const queryClient = useQueryClient(); const { data: accounts, isLoading } = useQuery({ @@ -101,6 +102,14 @@ export default function AccountsPage() { setPullingIds((prev) => new Set(prev).add(id)); try { await mailAccountsApi.pullNow(id); + setSuccessIds((prev) => new Set(prev).add(id)); + setTimeout(() => { + setSuccessIds((prev) => { + const next = new Set(prev); + next.delete(id); + return next; + }); + }, 2000); } catch { alert('Failed to queue pull'); } finally { @@ -227,11 +236,22 @@ export default function AccountsPage() {