149 lines
6.8 KiB
Markdown
149 lines
6.8 KiB
Markdown
|
|
# T08c: Frontend Mail UI + Global Search UI — Implementation Briefing
|
||
|
|
|
||
|
|
## Task
|
||
|
|
Implement frontend UI for Mail plugin (folder tree, mail list, reading pane, compose, templates, signatures, rules, labels, PGP, vacation, shared mailbox, delegates) and enhance Global Search UI with tabs.
|
||
|
|
|
||
|
|
## Acceptance Criteria (17 ACs — skip AC1/DMS and AC16/Docker, already done)
|
||
|
|
2. Mail route /mail renders folder tree + mail list + reading pane
|
||
|
|
3. Mail: click folder → mail list updates with folder mails
|
||
|
|
4. Mail: click mail → detail with sanitized HTML body + attachments
|
||
|
|
5. Mail: compose button → editor with toolbar (bold, italic, link, template insert)
|
||
|
|
6. Mail: reply/forward buttons → compose pre-filled
|
||
|
|
7. Mail: template picker dropdown in compose → inserts template body
|
||
|
|
8. Mail: signature manager in settings → create/edit/delete signatures
|
||
|
|
9. Mail: rule editor → condition builder + action selector
|
||
|
|
10. Mail: label manager → create labels with colors, assign to mails
|
||
|
|
11. Mail: PGP settings → import private key, view contact public keys
|
||
|
|
12. Mail: vacation responder toggle → date range + auto-reply text
|
||
|
|
13. Mail: shared mailbox selector → switch between personal+shared accounts
|
||
|
|
14. Mail: attachment download → file stream downloaded
|
||
|
|
15. Mail: create event from mail → calendar event modal pre-filled
|
||
|
|
16. Global search results page → tabs for companies/contacts/mails/files/events
|
||
|
|
17. Global search autocomplete in TopBar → dropdown with suggestions
|
||
|
|
|
||
|
|
## Backend API Endpoints (all implemented, prefix /api/v1/mail)
|
||
|
|
### Accounts
|
||
|
|
- GET /accounts — list accounts (password never returned)
|
||
|
|
- POST /accounts — create account (AES-256 encrypted password)
|
||
|
|
- PATCH /accounts/{id} — update account
|
||
|
|
- DELETE /accounts/{id} — delete account
|
||
|
|
- GET /accounts/shared — list shared mailboxes
|
||
|
|
- POST /accounts/{id}/users — assign shared mailbox users
|
||
|
|
- POST /accounts/{id}/delegates — create delegate access
|
||
|
|
- POST /accounts/{id}/send-permissions — grant send permission
|
||
|
|
- POST /accounts/{id}/test-connection — test IMAP connection
|
||
|
|
- POST /accounts/{id}/sync — trigger IMAP sync
|
||
|
|
|
||
|
|
### Folders
|
||
|
|
- GET /folders?account_id=X — list folders with counts
|
||
|
|
- POST /folders — create folder
|
||
|
|
- PATCH /folders/{id} — rename folder
|
||
|
|
- DELETE /folders/{id} — delete folder
|
||
|
|
|
||
|
|
### Mails
|
||
|
|
- GET /?folder_id=X&page=1 — paginated mail list
|
||
|
|
- GET /{id} — mail detail (sanitized HTML, attachments)
|
||
|
|
- POST /send — send mail via SMTP
|
||
|
|
- POST /{id}/reply — reply with In-Reply-To
|
||
|
|
- POST /{id}/forward — forward mail
|
||
|
|
- PATCH /{id}/flags — toggle seen/flagged
|
||
|
|
- POST /{id}/link — link to contact/company
|
||
|
|
- POST /{id}/create-event — create calendar event from mail
|
||
|
|
- POST /{id}/labels — assign label to mail
|
||
|
|
|
||
|
|
### Search & Threads
|
||
|
|
- GET /search?q=text — FTS search
|
||
|
|
- GET /threads — threaded view
|
||
|
|
|
||
|
|
### Attachments
|
||
|
|
- GET /{mail_id}/attachments/{att_id} — file stream download
|
||
|
|
|
||
|
|
### Templates
|
||
|
|
- POST /templates — create template
|
||
|
|
- GET /templates — list templates
|
||
|
|
- POST /templates/substitute — substitute variables
|
||
|
|
|
||
|
|
### Signatures
|
||
|
|
- POST /signatures — create signature
|
||
|
|
- GET /signatures — list signatures
|
||
|
|
|
||
|
|
### Rules
|
||
|
|
- POST /rules — create rule (conditions + actions)
|
||
|
|
- GET /rules — list rules sorted by priority
|
||
|
|
- DELETE /rules/{id} — delete rule
|
||
|
|
|
||
|
|
### Vacation
|
||
|
|
- POST /vacation — configure auto-reply
|
||
|
|
- POST /vacation/test-dedup — test dedup
|
||
|
|
|
||
|
|
### PGP
|
||
|
|
- POST /pgp/keys — import private key (encrypted)
|
||
|
|
- GET /pgp/keys — list PGP keys
|
||
|
|
- POST /pgp/encrypt — encrypt message
|
||
|
|
- POST /contacts/{contact_id}/pgp-key — store contact public key
|
||
|
|
|
||
|
|
### Labels
|
||
|
|
- POST /labels — create label (with color)
|
||
|
|
- GET /labels — list labels
|
||
|
|
|
||
|
|
## Frontend Architecture (follow existing patterns)
|
||
|
|
- **Framework:** React + TypeScript + Vite
|
||
|
|
- **Routing:** react-router-dom (src/routes/index.tsx)
|
||
|
|
- **State:** TanStack Query (useQuery/useMutation)
|
||
|
|
- **HTTP:** axios via src/api/client.ts (apiClient, baseURL /api/v1)
|
||
|
|
- **API pattern:** See src/api/calendar.ts or src/api/dms.ts
|
||
|
|
- **UI components:** src/components/ui/ (Button, Card, Input, Modal, Table, Badge, etc.)
|
||
|
|
- **Shared:** src/components/shared/ (DataGrid, SearchDropdown, Tabs)
|
||
|
|
- **Layout:** src/components/layout/AppShell.tsx + Sidebar.tsx
|
||
|
|
- **i18n:** src/i18n/ (add de.json + en.json keys for Mail)
|
||
|
|
- **Existing search page:** src/pages/GlobalSearchResults.tsx (enhance with tabs)
|
||
|
|
|
||
|
|
## Files to Create
|
||
|
|
- `src/api/mail.ts` — Mail API client (types + functions for all endpoints)
|
||
|
|
- `src/pages/Mail.tsx` — Mail page (folder tree + mail list + reading pane)
|
||
|
|
- `src/pages/MailSettings.tsx` — Mail settings (signatures, rules, PGP, vacation, labels)
|
||
|
|
- `src/components/mail/MailFolderTree.tsx` — folder tree sidebar
|
||
|
|
- `src/components/mail/MailList.tsx` — mail list with pagination
|
||
|
|
- `src/components/mail/MailDetail.tsx` — reading pane (sanitized HTML, attachments)
|
||
|
|
- `src/components/mail/ComposeModal.tsx` — compose editor (bold/italic/link/template)
|
||
|
|
- `src/components/mail/TemplatePicker.tsx` — template dropdown
|
||
|
|
- `src/components/mail/SignatureManager.tsx` — signature CRUD
|
||
|
|
- `src/components/mail/RuleEditor.tsx` — rule condition builder + action selector
|
||
|
|
- `src/components/mail/LabelManager.tsx` — label CRUD with colors
|
||
|
|
- `src/components/mail/VacationResponder.tsx` — vacation toggle + date range
|
||
|
|
- `src/components/mail/PgpSettings.tsx` — PGP key import + contact keys
|
||
|
|
- `src/components/mail/SharedMailboxSelector.tsx` — account switcher
|
||
|
|
- `src/components/mail/MailSearchBar.tsx` — mail search input
|
||
|
|
- `src/__tests__/mail/MailPage.test.tsx` — mail page tests
|
||
|
|
- `src/__tests__/mail/ComposeModal.test.tsx` — compose tests
|
||
|
|
- `src/__tests__/mail/MailSettings.test.tsx` — settings tests
|
||
|
|
- `src/__tests__/search/GlobalSearchTabs.test.tsx` — search tabs tests
|
||
|
|
|
||
|
|
## Files to Modify
|
||
|
|
- `src/routes/index.tsx` — Add /mail, /mail/settings routes
|
||
|
|
- `src/components/layout/Sidebar.tsx` — Add Mail nav link
|
||
|
|
- `src/pages/GlobalSearchResults.tsx` — Add tabs (companies/contacts/mails/files/events)
|
||
|
|
- `src/components/layout/AppShell.tsx` — Add search autocomplete in TopBar
|
||
|
|
- `src/i18n/locales/de.json` — Mail translations
|
||
|
|
- `src/i18n/locales/en.json` — Mail translations
|
||
|
|
|
||
|
|
## Test Spec
|
||
|
|
- Run: `cd /a0/usr/workdir/dev-projects/leocrm/frontend && npx vitest run src/__tests__/mail/ src/__tests__/search/ --reporter=verbose`
|
||
|
|
- Build: `npx vite build`
|
||
|
|
- Type check: `npx tsc --noEmit`
|
||
|
|
- Coverage target: 80%
|
||
|
|
- Follow existing test pattern from src/__tests__/dms/ or src/__tests__/companies/
|
||
|
|
|
||
|
|
## Forbidden Patterns
|
||
|
|
- No inline styles — use Tailwind classes
|
||
|
|
- No any types — use proper TypeScript interfaces
|
||
|
|
- No direct fetch() — use apiClient from src/api/client.ts
|
||
|
|
- No hardcoded strings — use i18n (t() function)
|
||
|
|
- No Lorem Ipsum — use realistic test data
|
||
|
|
- No missing loading/error/empty states
|
||
|
|
- No dangerouslySetInnerHTML without sanitization check
|
||
|
|
|
||
|
|
## Estimated Size
|
||
|
|
- ~700 lines code (pages + components + API client)
|
||
|
|
- ~350+ lines tests
|