Feat/crm mail ui #30

Merged
maaz519 merged 8 commits from feat/crm-mail-ui into goutamnextflow 2026-07-18 12:31:19 +00:00

8 Commits

Author SHA1 Message Date
maaz519 28907acf0e fix(dashboard): portal modals to .dash-root so they anchor to the viewport
A transformed/overflow panel ancestor was trapping the modal overlay's
position:fixed, so the modal rendered offset inside the messenger/inbox panel
and clipped (Group settings sat inside the thread pane; the compose modal's
top was cut at the panel edge). Portal the overlay up to .dash-root — above
those panels but still inside the scoped design-system CSS — so it centers on
the viewport and the 90vh cap works. Falls back to inline render if no
.dash-root is present.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 17:52:32 +05:30
maaz519 54add81187 fix(dashboard): keep tall modal footers on-screen
The modal body is a flex child with overflow-y:auto but had no min-height:0,
so it refused to shrink below content height and pushed the footer past the
90vh cap (visible on the tall Group settings modal — the Done button was
clipped). Add flex:1 1 auto + min-height:0 so the body scrolls and the
footer stays pinned.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 17:46:55 +05:30
maaz519 4ad0decad0 feat(messenger): group settings UI — rename, member list, add/remove
- messenger-api: useGroupSettings(threadId) — members query + rename/add/
  remove commands + isAdmin (from the member roles); live + mock
- messenger: a settings (gear) button on group thread headers opens a
  GroupSettingsModal — editable name (admin), member list with role pills,
  admin-gated remove, and add-from-directory search
- controls are admin-gated in the UI; IIOS/OPA re-enforces server-side

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 17:43:52 +05:30
maaz519 0b433790a5 feat(inbox): attachments in mail reader + composer
- mail-api: MailMessage carries attachment; reply + sendInternal +
  sendExternal accept uploaded attachments; mock updated
- mail.tsx: MailAttachmentView (inline image or file chip via signed URL),
  StagedChip; attach button in the reply footer and the New Message
  composer (multi-file, up to 10); text optional when a file is attached
- messenger: file-chip icon uses paperclip (was an unknown name)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 17:31:22 +05:30
maaz519 7982c243c0 feat: attachments in Messenger — upload/preview images + files
- media-api: useUploadAttachment (presign → direct PUT to IIOS storage),
  useDownloadUrl (short-lived signed URL), isImage, 25MB cap
- socket + REST send now carry attachment {contentRef, mimeType, sizeBytes}
- composer: 📎 attach button, staged chip, send with attachment (text optional)
- MessageBubble renders AttachmentView (inline image or file chip), aligned
  to the message side; empty bubble suppressed for attachment-only messages

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 17:17:45 +05:30
maaz519 1490fa3460 fix(messenger): reply focuses composer + quoted message jumps to original
- Clicking Reply now focuses the composer input (was requiring a manual click).
- A quoted message is clickable → scrolls to the original and flashes it briefly
  (was inert). Message elements register refs by id for the jump.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 17:03:44 +05:30
maaz519 36f43d7d2a refactor(inbox): fold mail INTO the Inbox (one unified surface, no Mail tab)
The Inbox is the single communication surface — mentions, needs-reply, system
alerts, support updates AND the mail behind them, all in one list. Removed the
separate Mail tab.

- Inbox is now two-pane: the item list (crm.inbox.*) on the left; clicking an item
  tied to a thread opens its conversation (MailReader) on the right to read + reply.
  Non-threaded items (e.g. system alerts) show their detail. Item actions
  (Done/Snooze/Archive) work for every item.
- Compose new mail (in-app or email) from the Inbox header.
- mail.tsx trimmed to reusable MailReader + NewMailModal (no standalone tab);
  sidebar + dashboard reverted to no Mail entry.
- The existing work-item Inbox stays the notifier; this makes it the reader too.
  HTML bodies still render in a sandboxed iframe. tsc + next build clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 16:43:48 +05:30
maaz519 46aa7a767c feat(mail): dedicated Mail reader in the CRM
A Mail surface in the Communication group, distinct from Messenger (chat) and the
work-item Inbox: read app-to-app + email messages (subject + rendered body), reply,
and compose (in-app to a person, or external to an email).

- mail-api.ts: crm.mail.list/history/reply + compose (crm.mail.internal/send), reusing
  the messenger directory for the people picker. Live via the AppShell SDK; mock in demo mode.
- mail.tsx: thread list + reader + reply + New-mail composer. HTML bodies render inside a
  SANDBOXED iframe (no scripts) — safe against untrusted email HTML.
- Wired into the sidebar (Communication) + dashboard switch.

The existing work-item Inbox stays as the notifier (IIOS's projector already flags new
mail there); this is where you read it. tsc + next build clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 16:38:16 +05:30