Files
doctate/server
Brummel 0308245524 feat(web): fuse copy + close into one control on the case page
A finished case is handled in one gesture: a text button below the
document copies the document text to the clipboard and then closes the
case, landing back on /cases. Replaces the icon-only trash-can close
that sat in the H1 title row.

Behaviour:
- Open case with a document: "Kopieren + Schließen" below the document.
  The submit handler awaits the clipboard write inside the user gesture,
  then submits the close form; a FAILED copy aborts the close and reveals
  an inline error, so a finished case never disappears from the default
  list while the clipboard is empty.
- Open case without a document: a bare "Schließen" button (nothing to
  copy) keeps the close affordance the removed trash-can used to provide.
- Closed case: neither button renders; the reopen affordance is
  untouched.

Frontend-only. No Rust route/handler change: POST /cases/{id}/close
already strips the case-page Referer to /cases, so "back to list" needs
no new server work. The two-path clipboard routine (async Clipboard API
+ textarea/execCommand fallback) is extracted into a shared copyDocText()
used by both the standalone icon copy button (kept, copy-without-close)
and the new combined control — one source, no drift.

Tests (RED-first, server/tests/case_page_test.rs): open+document renders
the copy-close form with the close action and CSRF token; closed case
hides it; the H1 trash-can is gone on an open case; the documentless
open case keeps a bare Schließen. Full server suite green, clippy clean,
fmt no-op. The JS submit-handler ordering (copy-before-navigate,
abort-on-fail) has no Rust render harness — same inherent layer gap as
the pre-existing #copy-btn — and is verified manually.

Covers the case-page half of #14; the per-row case-list copy+close is
deferred.

refs #14
2026-06-01 14:35:17 +02:00
..