{"id":"6a32b5f514d963ddfc391be5","title":"2026 06 17","path":"how-to/committee/release-notes/2026-06-17","contentMarkdown":"# 17-Jun-2026 — conversation collapse/reply, sort toggle, and content-aware single send [#278](https://github.com/nbarrett/ngx-ramblers/issues/278)\n\n## [build 700](https://github.com/nbarrett/ngx-ramblers/actions/runs/27697269343) — [commit 512c941](https://github.com/nbarrett/ngx-ramblers/commit/512c941ea206ec8cbe14afcf094f32701d624541)\n\n_____\n\nImproves the committee inbox conversation view (collapse/expand like other\nemail clients, reply or reply-all to a chosen message, sort order, cleaner\nsummaries and grouping) and makes outbound sends choose between one combined\nmessage and per-recipient sends based on whether the content personalises.\nPart of the Gmail inbox work in #278.\n\n## What's new\n\nSee https://github.com/nbarrett/ngx-ramblers/issues/278\n\n- Conversation messages collapse and expand like Gmail/Outlook: the newest\nopens, the rest show a one-line summary (sender, \"to ...\", a clean\npreview) and expand on click.\n- Reply or Reply all to a specific message, via square icon buttons; on a\ncollapsed message the buttons appear on hover so you can reply without\nopening it.\n- Sort the conversation newest-first (default) or oldest-first with a toggle.\n- Maximise the inbox to fill the whole screen, hiding the nav bar, page\nchrome and banners; Restore to return. The maximised state is kept in the\nURL (maximise query parameter) and carries through to the email composer\nwhen you reply, so the composer opens maximised too; the maximised view\nshows the site logo top-left.\n- The inbox toolbar is a single row with the site logo left-most, and the\nselected view (all / mine / a specific role mailbox / junk) is kept in the\nURL, so the chosen mailbox survives reload and can be linked.\n- Clicking Reply puts the cursor straight into the message editor so you can\nstart typing immediately.\n- Denser conversation list (sender and date share a line) and a toolbar that\nstacks full-width on small screens instead of overflowing the page.\n- Copies of the same send are grouped into a single entry showing the\ncombined recipient list, and an exact duplicate is no longer shown.\n- The collapsed preview shows real message text instead of leaking HTML/CSS.\n- Sending to several recipients now goes out as one message addressed to all\nof them when the content has no personalisation; if the content uses\nmember merge fields, it is sent per-recipient so each copy is personalised.\n\n## At a glance\n\n| Area | Before | Now |\n| --- | --- | --- |\n| Older messages | All fully expanded | Collapsed one-line summaries, click to open |\n| Reply | Only the latest message | Reply or Reply all to any message; hover to reveal on collapsed |\n| Order | Fixed oldest-first | Newest-first by default, toggle to oldest-first |\n| Same send to many | One row per recipient copy | One grouped entry, combined recipients |\n| Collapsed preview | Leaked `<style>`/CSS | Clean text |\n| Send to several people | One transactional send each (you were copied N times) | One combined send when not personalised; per-recipient only when it uses merge fields |\n\n## Where to find it\n\n- Admin -> Email inbox: conversation view, grouping, sort, reply/reply-all.\n- The email composer: the content-aware single combined send.\n\n## How it behaves\n\n- Conversation: newest message expanded, others collapsed to a summary\n(sender + \"to <recipients>\" + preview); click to toggle. Square Reply and\nReply all icons sit on the message - always shown when expanded, revealed\non hover when collapsed. The header Reply still answers the latest.\n- Sort: the conversation lists newest-first by default; a toggle switches to\noldest-first.\n- Maximise: a toggle expands the inbox into a panel fixed over the whole\nviewport, hiding the nav bar, breadcrumb, title and banners so the\nconversation and message panes fill the screen; the button reads Restore\nwhile maximised and the state is stored in the URL so it survives reload\nand can be linked. On small screens the toolbar stacks full-width.\n- Grouping: copies of one send (same sender and subject within a few\nminutes) merge into a single entry with combined To/Cc. Exact duplicates\nare removed, and a server guard stops the same message being stored twice.\n- Sending: the content is inspected for member merge fields. With none, all\nexternal recipients are sent one combined email (Cc/Bcc applied once); with\nmerge fields, recipients are sent individually so each is personalised.\nGroup members are always sent per-recipient.\n\n## How to try it out\n\n1. Open a multi-message conversation in Admin -> Email inbox. Older messages\nare collapsed; hover one to reveal its reply buttons, or open it and use\nReply / Reply all. Flip the sort order with the toggle.\n2. Send a committee email to several named people with no merge fields and\nyourself in Cc. You should receive a single copy, and the inbox shows one\ngrouped entry listing all recipients.\n\n## Technical changes\n\n- Reply all carries a flag through to the composer so the original\nrecipients are pre-selected: To is the sender and Cc is pre-filled with the\nother recipients (minus the sender and own role addresses), rather than\noffered as a \"Cc these roles\" suggestion as a plain reply does. The\ncomposer's Cc and Bcc panels now render whenever they hold recipients, so\nthe stepper summary and the visible selection can never differ.\n- Client inbox.component: collapse/expand state, Reply and Reply all per\nmessage (reply-all augments Cc with the original recipients, minus the\nsender and own role addresses), recipient summary, newest/oldest sort\ntoggle, send-grouping (same sender and subject within five minutes), exact\ndedupe by Gmail message id, HTML-stripped preview, square hover-revealed\nreply icons and detail-pane padding; the inbox toolbar is a single\nnon-wrapping row with the maximise/restore toggle inline and the site logo\nleft-most, and the view selector writes the role local-part to the URL (a\nnew StoredValue key) and reads it back on init; the compose editor's TipTap\ntoolbar is sticky while scrolling; the compose editor is focused on reply\nhand-off (via a ViewChild setter, so it fires when the editor renders);\ndenser conversation rows (sender and date on one line) and a toolbar that\nstacks full-width below the small breakpoint.\n- Maximise is now a reusable app-maximisable-panel component used by both the\ninbox and the email composer, replacing the duplicated full-screen shell in\neach. It owns the maximised state (StoredValue.MAXIMISE in the URL), renders\nthe fixed full-viewport overlay with a Restore/Maximise toggle and a 44px\nSiteLogoComponent, and projects the host content; maximise carries across\nthe reply hand-off and the composer's Back to inbox preserves the maximise\n(and thread) parameter. The overlay takes its own compositor layer\n(translateZ) and forces a reflow plus a resize on entering maximised and\nagain once web fonts load, so action buttons paint correctly when maximised\non a slow first paint instead of needing a manual refresh. The composer's\naction-bar buttons also carry their own sizing so they no longer depend on\nBootstrap's global .btn winning the cascade.\n- Server inbox-message-import: an idempotency guard so a message already on a\nthread is not stored a second time.\n- Server batch-transactional-send: when the content has no member merge\nfields, external recipients are sent one combined email (Cc/Bcc once);\notherwise recipients are sent per-recipient. Members remain per-recipient.\n- Requires a server restart for the import guard and the send change; the\nconversation-view changes hot-reload.\n\n## Email composer recipients redesign\n\nThe unbranded recipients step is rebuilt around an email-client-style chip\nfield, and the picker that was spread across five stacked panels becomes one\ncollapsible frame.\n\n- \"Who is this email going to?\" is a single collapsible frame (open by\ndefault, and always opened for an unbranded send); collapsed, it summarises\nwho is chosen by name across To/Cc/Bcc.\n- To/Cc/Bcc are chip/token fields: type to add, with type-ahead over saved\naddresses, and Cc/Bcc reveal on demand. Each recipient is a removable chip\nyou can drag between lines, or click to open a small editor to rename it,\nswitch its field, toggle save-for-reuse, or remove it. The suggestion list\nis keyboard-navigable (arrow keys and Enter).\n- Group-member tags and recipient chips share one look, matched to the\n\"Before you can continue\" validation summary (peach fill, sunset border,\nbold maroon name); the member tag shows a shortened, consistent qualifier\n(\"with Head Office consent\" / \"without Head Office consent\", date forms\nkept). A text filter now survives selecting several matching members in a\nrow instead of clearing after each pick.\n- The Sender and Template step shows the banner preview beside its selects in\na column instead of full-width, so it is no longer oversized.\n- Clicking the Compose step opens the body editor and focuses it.\n- The composer notification alert sits directly under the action bar with\neven spacing and a warning icon and title; membership expiry dates in sent\nemails use the standard Ramblers date format; and the send progress bar is\ngreen throughout (red only on failure).\n\n### Technical changes (recipients)\n\n- New app-recipient-field standalone component holds the To/Cc/Bcc chip\nfields, type-ahead, drag-between-fields, the per-chip editor popover and\nkeyboard navigation; it replaces the five fieldsets in the unbranded flow,\nwhose now-dead handlers and fields were removed from email-composer.\n- The shared app-maximisable-panel gained a [panelControls] projection slot,\nso the maximised row is logo-left, injected-controls, Restore-right, and it\nshows the site logo whenever maximised regardless of showHeader; the inbox\nand composer both feed their toolbars through the slot.\n- member-multi-select renders selected tags via an ng-label-tmp (name, muted\nqualifier, remove), styles them to match the recipient chips, sets\nclearSearchOnAdd to false so a filter survives multi-select, and shortens\nthe consent qualifiers.\n- notification-config-selector lays the email-type and banner selects in a\nleft column with the banner preview in a right column.\n- email-preview shows a warning icon and title on its error alert.\n- Server batch-transactional-send formats MEMBER_EXP with the Ramblers\nstandard DISPLAY_DATE instead of yyyy-MM-dd (needs a server restart).\n\n## Email composer in pictures\n\n### Maximise and restore\n\nAny maximised admin view now shows the same top row: the site logo on the left, that view's own controls in the middle, and a Restore button on the right. Maximise fills the screen and hides the site navigation and page chrome; Restore returns to the normal layout. The state is kept in the URL, so a maximised view survives a reload and can be linked, and replying from the inbox opens the composer already maximised.\n\n![](https://ngx-ramblers.org.uk/api/aws/s3/site-content/f7a851ba-6bd6-48a8-bad1-d0c6bb1bd690.png)\n\n*Maximised composer: site logo on the left, the view's own controls in the middle, Restore on the right.*\n\n![](https://ngx-ramblers.org.uk/api/aws/s3/site-content/d8dd3e7e-07f2-41bd-b746-9aa809a48543.png)\n\n*Recipients are chips. Type an address and press Enter; To, Cc and Bcc hold removable tokens, with Cc and Bcc revealed on demand.*\n\n![](https://ngx-ramblers.org.uk/api/aws/s3/site-content/d7bda77e-2296-4979-840b-b46054bc2d61.png)\n\n*Click a chip to open a small editor: rename the person, switch their field, save the address for re-use, or remove it.*\n\n![](https://ngx-ramblers.org.uk/api/aws/s3/site-content/7142a22c-fb8c-4fd1-8086-6aac7bfeb5e4.png)\n\n*Group members shown as tags with a short consent qualifier. A text filter now survives selecting several matching people in a row.*\n\n![](https://ngx-ramblers.org.uk/api/aws/s3/site-content/b6729c54-e940-4409-9a4f-c1c3d66fa41f.png)\n\n*Sender and Template: the banner preview now sits in a column beside its selects instead of spanning the full width.*","contentHtml":"<h1>17-Jun-2026 — conversation collapse/reply, sort toggle, and content-aware single send <a href=\"https://github.com/nbarrett/ngx-ramblers/issues/278\">#278</a></h1>\n<h2><a href=\"https://github.com/nbarrett/ngx-ramblers/actions/runs/27697269343\">build 700</a> — <a href=\"https://github.com/nbarrett/ngx-ramblers/commit/512c941ea206ec8cbe14afcf094f32701d624541\">commit 512c941</a></h2>\n<hr>\n<p>Improves the committee inbox conversation view (collapse/expand like other\nemail clients, reply or reply-all to a chosen message, sort order, cleaner\nsummaries and grouping) and makes outbound sends choose between one combined\nmessage and per-recipient sends based on whether the content personalises.\nPart of the Gmail inbox work in #278.</p>\n<h2>What&#39;s new</h2>\n<p>See <a href=\"https://github.com/nbarrett/ngx-ramblers/issues/278\">https://github.com/nbarrett/ngx-ramblers/issues/278</a></p>\n<ul>\n<li>Conversation messages collapse and expand like Gmail/Outlook: the newest\nopens, the rest show a one-line summary (sender, &quot;to ...&quot;, a clean\npreview) and expand on click.</li>\n<li>Reply or Reply all to a specific message, via square icon buttons; on a\ncollapsed message the buttons appear on hover so you can reply without\nopening it.</li>\n<li>Sort the conversation newest-first (default) or oldest-first with a toggle.</li>\n<li>Maximise the inbox to fill the whole screen, hiding the nav bar, page\nchrome and banners; Restore to return. The maximised state is kept in the\nURL (maximise query parameter) and carries through to the email composer\nwhen you reply, so the composer opens maximised too; the maximised view\nshows the site logo top-left.</li>\n<li>The inbox toolbar is a single row with the site logo left-most, and the\nselected view (all / mine / a specific role mailbox / junk) is kept in the\nURL, so the chosen mailbox survives reload and can be linked.</li>\n<li>Clicking Reply puts the cursor straight into the message editor so you can\nstart typing immediately.</li>\n<li>Denser conversation list (sender and date share a line) and a toolbar that\nstacks full-width on small screens instead of overflowing the page.</li>\n<li>Copies of the same send are grouped into a single entry showing the\ncombined recipient list, and an exact duplicate is no longer shown.</li>\n<li>The collapsed preview shows real message text instead of leaking HTML/CSS.</li>\n<li>Sending to several recipients now goes out as one message addressed to all\nof them when the content has no personalisation; if the content uses\nmember merge fields, it is sent per-recipient so each copy is personalised.</li>\n</ul>\n<h2>At a glance</h2>\n<table>\n<thead>\n<tr>\n<th>Area</th>\n<th>Before</th>\n<th>Now</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Older messages</td>\n<td>All fully expanded</td>\n<td>Collapsed one-line summaries, click to open</td>\n</tr>\n<tr>\n<td>Reply</td>\n<td>Only the latest message</td>\n<td>Reply or Reply all to any message; hover to reveal on collapsed</td>\n</tr>\n<tr>\n<td>Order</td>\n<td>Fixed oldest-first</td>\n<td>Newest-first by default, toggle to oldest-first</td>\n</tr>\n<tr>\n<td>Same send to many</td>\n<td>One row per recipient copy</td>\n<td>One grouped entry, combined recipients</td>\n</tr>\n<tr>\n<td>Collapsed preview</td>\n<td>Leaked <code>&lt;style&gt;</code>/CSS</td>\n<td>Clean text</td>\n</tr>\n<tr>\n<td>Send to several people</td>\n<td>One transactional send each (you were copied N times)</td>\n<td>One combined send when not personalised; per-recipient only when it uses merge fields</td>\n</tr>\n</tbody></table>\n<h2>Where to find it</h2>\n<ul>\n<li>Admin -&gt; Email inbox: conversation view, grouping, sort, reply/reply-all.</li>\n<li>The email composer: the content-aware single combined send.</li>\n</ul>\n<h2>How it behaves</h2>\n<ul>\n<li>Conversation: newest message expanded, others collapsed to a summary\n(sender + &quot;to <recipients>&quot; + preview); click to toggle. Square Reply and\nReply all icons sit on the message - always shown when expanded, revealed\non hover when collapsed. The header Reply still answers the latest.</li>\n<li>Sort: the conversation lists newest-first by default; a toggle switches to\noldest-first.</li>\n<li>Maximise: a toggle expands the inbox into a panel fixed over the whole\nviewport, hiding the nav bar, breadcrumb, title and banners so the\nconversation and message panes fill the screen; the button reads Restore\nwhile maximised and the state is stored in the URL so it survives reload\nand can be linked. On small screens the toolbar stacks full-width.</li>\n<li>Grouping: copies of one send (same sender and subject within a few\nminutes) merge into a single entry with combined To/Cc. Exact duplicates\nare removed, and a server guard stops the same message being stored twice.</li>\n<li>Sending: the content is inspected for member merge fields. With none, all\nexternal recipients are sent one combined email (Cc/Bcc applied once); with\nmerge fields, recipients are sent individually so each is personalised.\nGroup members are always sent per-recipient.</li>\n</ul>\n<h2>How to try it out</h2>\n<ol>\n<li>Open a multi-message conversation in Admin -&gt; Email inbox. Older messages\nare collapsed; hover one to reveal its reply buttons, or open it and use\nReply / Reply all. Flip the sort order with the toggle.</li>\n<li>Send a committee email to several named people with no merge fields and\nyourself in Cc. You should receive a single copy, and the inbox shows one\ngrouped entry listing all recipients.</li>\n</ol>\n<h2>Technical changes</h2>\n<ul>\n<li>Reply all carries a flag through to the composer so the original\nrecipients are pre-selected: To is the sender and Cc is pre-filled with the\nother recipients (minus the sender and own role addresses), rather than\noffered as a &quot;Cc these roles&quot; suggestion as a plain reply does. The\ncomposer&#39;s Cc and Bcc panels now render whenever they hold recipients, so\nthe stepper summary and the visible selection can never differ.</li>\n<li>Client inbox.component: collapse/expand state, Reply and Reply all per\nmessage (reply-all augments Cc with the original recipients, minus the\nsender and own role addresses), recipient summary, newest/oldest sort\ntoggle, send-grouping (same sender and subject within five minutes), exact\ndedupe by Gmail message id, HTML-stripped preview, square hover-revealed\nreply icons and detail-pane padding; the inbox toolbar is a single\nnon-wrapping row with the maximise/restore toggle inline and the site logo\nleft-most, and the view selector writes the role local-part to the URL (a\nnew StoredValue key) and reads it back on init; the compose editor&#39;s TipTap\ntoolbar is sticky while scrolling; the compose editor is focused on reply\nhand-off (via a ViewChild setter, so it fires when the editor renders);\ndenser conversation rows (sender and date on one line) and a toolbar that\nstacks full-width below the small breakpoint.</li>\n<li>Maximise is now a reusable app-maximisable-panel component used by both the\ninbox and the email composer, replacing the duplicated full-screen shell in\neach. It owns the maximised state (StoredValue.MAXIMISE in the URL), renders\nthe fixed full-viewport overlay with a Restore/Maximise toggle and a 44px\nSiteLogoComponent, and projects the host content; maximise carries across\nthe reply hand-off and the composer&#39;s Back to inbox preserves the maximise\n(and thread) parameter. The overlay takes its own compositor layer\n(translateZ) and forces a reflow plus a resize on entering maximised and\nagain once web fonts load, so action buttons paint correctly when maximised\non a slow first paint instead of needing a manual refresh. The composer&#39;s\naction-bar buttons also carry their own sizing so they no longer depend on\nBootstrap&#39;s global .btn winning the cascade.</li>\n<li>Server inbox-message-import: an idempotency guard so a message already on a\nthread is not stored a second time.</li>\n<li>Server batch-transactional-send: when the content has no member merge\nfields, external recipients are sent one combined email (Cc/Bcc once);\notherwise recipients are sent per-recipient. Members remain per-recipient.</li>\n<li>Requires a server restart for the import guard and the send change; the\nconversation-view changes hot-reload.</li>\n</ul>\n<h2>Email composer recipients redesign</h2>\n<p>The unbranded recipients step is rebuilt around an email-client-style chip\nfield, and the picker that was spread across five stacked panels becomes one\ncollapsible frame.</p>\n<ul>\n<li>&quot;Who is this email going to?&quot; is a single collapsible frame (open by\ndefault, and always opened for an unbranded send); collapsed, it summarises\nwho is chosen by name across To/Cc/Bcc.</li>\n<li>To/Cc/Bcc are chip/token fields: type to add, with type-ahead over saved\naddresses, and Cc/Bcc reveal on demand. Each recipient is a removable chip\nyou can drag between lines, or click to open a small editor to rename it,\nswitch its field, toggle save-for-reuse, or remove it. The suggestion list\nis keyboard-navigable (arrow keys and Enter).</li>\n<li>Group-member tags and recipient chips share one look, matched to the\n&quot;Before you can continue&quot; validation summary (peach fill, sunset border,\nbold maroon name); the member tag shows a shortened, consistent qualifier\n(&quot;with Head Office consent&quot; / &quot;without Head Office consent&quot;, date forms\nkept). A text filter now survives selecting several matching members in a\nrow instead of clearing after each pick.</li>\n<li>The Sender and Template step shows the banner preview beside its selects in\na column instead of full-width, so it is no longer oversized.</li>\n<li>Clicking the Compose step opens the body editor and focuses it.</li>\n<li>The composer notification alert sits directly under the action bar with\neven spacing and a warning icon and title; membership expiry dates in sent\nemails use the standard Ramblers date format; and the send progress bar is\ngreen throughout (red only on failure).</li>\n</ul>\n<h3>Technical changes (recipients)</h3>\n<ul>\n<li>New app-recipient-field standalone component holds the To/Cc/Bcc chip\nfields, type-ahead, drag-between-fields, the per-chip editor popover and\nkeyboard navigation; it replaces the five fieldsets in the unbranded flow,\nwhose now-dead handlers and fields were removed from email-composer.</li>\n<li>The shared app-maximisable-panel gained a [panelControls] projection slot,\nso the maximised row is logo-left, injected-controls, Restore-right, and it\nshows the site logo whenever maximised regardless of showHeader; the inbox\nand composer both feed their toolbars through the slot.</li>\n<li>member-multi-select renders selected tags via an ng-label-tmp (name, muted\nqualifier, remove), styles them to match the recipient chips, sets\nclearSearchOnAdd to false so a filter survives multi-select, and shortens\nthe consent qualifiers.</li>\n<li>notification-config-selector lays the email-type and banner selects in a\nleft column with the banner preview in a right column.</li>\n<li>email-preview shows a warning icon and title on its error alert.</li>\n<li>Server batch-transactional-send formats MEMBER_EXP with the Ramblers\nstandard DISPLAY_DATE instead of yyyy-MM-dd (needs a server restart).</li>\n</ul>\n<h2>Email composer in pictures</h2>\n<h3>Maximise and restore</h3>\n<p>Any maximised admin view now shows the same top row: the site logo on the left, that view&#39;s own controls in the middle, and a Restore button on the right. Maximise fills the screen and hides the site navigation and page chrome; Restore returns to the normal layout. The state is kept in the URL, so a maximised view survives a reload and can be linked, and replying from the inbox opens the composer already maximised.</p>\n<p><img src=\"https://ngx-ramblers.org.uk/api/aws/s3/site-content/f7a851ba-6bd6-48a8-bad1-d0c6bb1bd690.png\" alt=\"\"></p>\n<p><em>Maximised composer: site logo on the left, the view&#39;s own controls in the middle, Restore on the right.</em></p>\n<p><img src=\"https://ngx-ramblers.org.uk/api/aws/s3/site-content/d8dd3e7e-07f2-41bd-b746-9aa809a48543.png\" alt=\"\"></p>\n<p><em>Recipients are chips. Type an address and press Enter; To, Cc and Bcc hold removable tokens, with Cc and Bcc revealed on demand.</em></p>\n<p><img src=\"https://ngx-ramblers.org.uk/api/aws/s3/site-content/d7bda77e-2296-4979-840b-b46054bc2d61.png\" alt=\"\"></p>\n<p><em>Click a chip to open a small editor: rename the person, switch their field, save the address for re-use, or remove it.</em></p>\n<p><img src=\"https://ngx-ramblers.org.uk/api/aws/s3/site-content/7142a22c-fb8c-4fd1-8086-6aac7bfeb5e4.png\" alt=\"\"></p>\n<p><em>Group members shown as tags with a short consent qualifier. A text filter now survives selecting several matching people in a row.</em></p>\n<p><img src=\"https://ngx-ramblers.org.uk/api/aws/s3/site-content/b6729c54-e940-4409-9a4f-c1c3d66fa41f.png\" alt=\"\"></p>\n<p><em>Sender and Template: the banner preview now sits in a column beside its selects instead of spanning the full width.</em></p>\n"}