Add combined Copy+Close action on case page (with back-to-list) and case list #14

Open
opened 2026-05-31 23:36:53 +02:00 by Brummel · 0 comments
Owner

Request

A single combined action that, in one click:

  • Case page (server/templates/case_page.html): copy the document text to the clipboard, close the case, and return to the case list at /cases.
  • Case list (server/templates/my_cases.html): per row, copy that case's document text to the clipboard and close the case (staying on the list).

Today these are separate controls; the request is to fuse copy + close (+ back-to-list on the case page) into one button so a finished case is handled in one gesture.

Current state (verified)

The building blocks already exist as separate controls:

  • Copy is client-side only — button #copy-btn at server/templates/case_page.html:575, click handler at server/templates/case_page.html:624 reads #doc-body .innerText and calls navigator.clipboard.writeText() (with a textarea/execCommand fallback).
  • Close is a server action — POST /cases/{case_id}/close, handler at server/src/routes/case_actions.rs:437, route wired at server/src/routes/mod.rs:52. It persists a .closed JSON marker (server/src/paths.rs:58, struct CloseMarker { closed_at: String }); reopen removes it.
  • The case-page close button is a POST form at server/templates/case_page.html:440.
  • Back-to-list is a plain link <a class="back" href="/cases"> at server/templates/case_page.html:380.
  • The case list already has a per-row close button (POST form, formaction="/cases/{case_id}/close") at server/templates/my_cases.html:153, inside the bulk <form method="post">. There is no copy control on the list today.
  • Page handlers: case page GET /cases/{case_id} (server/src/routes/user_web.rs:728), case list GET /cases (server/src/routes/user_web.rs:617).

Design considerations (to resolve during implementation)

  • Clipboard-then-navigate ordering. navigator.clipboard.writeText() must complete inside the user-gesture context before any form-submit navigation fires, or the copy is lost. The combined handler needs to await the clipboard write and only then submit the close form.
  • Claim (unverified): the close handler at server/src/routes/case_actions.rs:437 likely already redirects back to /cases; if so, the case-page "back-to-list" part is satisfied by the existing close redirect and needs no extra navigation. Verify the handler's response before adding redundant navigation.
  • List-page copy source. Each list row renders only an analysis_html preview (server/templates/my_cases.html), not necessarily the full document text in the DOM. A per-row copy therefore needs the full document text either embedded per row or fetched on click. Decide which; this drives feasibility and page weight.
  • CSRF: the close forms use the csrf::field macro; any new submit path must carry the same token.

Acceptance checklist

  • Case page: one control copies the document to the clipboard, closes the case, and lands on /cases, with the clipboard write guaranteed to complete before navigation.
  • Case list: one per-row control copies that case's document and closes it, staying on /cases.
  • Existing standalone copy and close controls behave unchanged (or are intentionally consolidated).
  • Works with the clipboard.writeText fallback path for browsers without the async Clipboard API.
## Request A single combined action that, in one click: - **Case page** (`server/templates/case_page.html`): copy the document text to the clipboard, close the case, and return to the case list at `/cases`. - **Case list** (`server/templates/my_cases.html`): per row, copy that case's document text to the clipboard and close the case (staying on the list). Today these are separate controls; the request is to fuse copy + close (+ back-to-list on the case page) into one button so a finished case is handled in one gesture. ## Current state (verified) The building blocks already exist as separate controls: - Copy is client-side only — button `#copy-btn` at `server/templates/case_page.html:575`, click handler at `server/templates/case_page.html:624` reads `#doc-body` `.innerText` and calls `navigator.clipboard.writeText()` (with a `textarea`/`execCommand` fallback). - Close is a server action — `POST /cases/{case_id}/close`, handler at `server/src/routes/case_actions.rs:437`, route wired at `server/src/routes/mod.rs:52`. It persists a `.closed` JSON marker (`server/src/paths.rs:58`, `struct CloseMarker { closed_at: String }`); `reopen` removes it. - The case-page close button is a POST form at `server/templates/case_page.html:440`. - Back-to-list is a plain link `<a class="back" href="/cases">` at `server/templates/case_page.html:380`. - The case list already has a per-row close button (POST form, `formaction="/cases/{case_id}/close"`) at `server/templates/my_cases.html:153`, inside the bulk `<form method="post">`. There is no copy control on the list today. - Page handlers: case page `GET /cases/{case_id}` (`server/src/routes/user_web.rs:728`), case list `GET /cases` (`server/src/routes/user_web.rs:617`). ## Design considerations (to resolve during implementation) - **Clipboard-then-navigate ordering.** `navigator.clipboard.writeText()` must complete inside the user-gesture context before any form-submit navigation fires, or the copy is lost. The combined handler needs to `await` the clipboard write and only then submit the close form. - Claim (unverified): the close handler at `server/src/routes/case_actions.rs:437` likely already redirects back to `/cases`; if so, the case-page "back-to-list" part is satisfied by the existing close redirect and needs no extra navigation. Verify the handler's response before adding redundant navigation. - **List-page copy source.** Each list row renders only an `analysis_html` preview (`server/templates/my_cases.html`), not necessarily the full document text in the DOM. A per-row copy therefore needs the full document text either embedded per row or fetched on click. Decide which; this drives feasibility and page weight. - CSRF: the close forms use the `csrf::field` macro; any new submit path must carry the same token. ## Acceptance checklist - [ ] Case page: one control copies the document to the clipboard, closes the case, and lands on `/cases`, with the clipboard write guaranteed to complete before navigation. - [ ] Case list: one per-row control copies that case's document and closes it, staying on `/cases`. - [ ] Existing standalone copy and close controls behave unchanged (or are intentionally consolidated). - [ ] Works with the `clipboard.writeText` fallback path for browsers without the async Clipboard API.
Brummel added the feature label 2026-05-31 23:36:53 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Brummel/doctate#14