fix delete confirm opens as a true viewport-centered modal

The delete dialog rendered with the bare [open] attribute, so it centered on the page (not the viewport) and drew no backdrop. Upgrade it to showModal via the client, matching the feedback modal: a grey backdrop, a Discard control (oxblood outline) top-right, and the Delete button centered at the bottom. Also look up the delete target across all months, so deleting a workout from a month other than the current one still opens the dialog.

Commit
5c86689744d649971e61700dade1a1659b4c113d
Author
Marius Peter <dev@marius-peter.com>
Author date
Committer
Marius Peter <dev@marius-peter.com>
Committer date
Changed files
lib/presenter/pages_logbook.ml
index ea3e2aa8..328a1b6b 100644..100644
@@ -110,18 +110,29 @@
110 110 tag "dialog"
111 111 [ class_ "confirm-dialog"; Dream_html.attr "open" ]
112 112 [
113 Removed: tag "h2" [] [ txt "Delete this workout log?" ];
113 Added: tag "div"
114 Added: [ class_ "confirm-dialog-heading" ]
115 Added: [
116 Added: tag "h2" [] [ txt "Delete this workout log?" ];
117 Added: (* Discard: an oxblood-outline control top-right. The client closes
118 Added: the modal in place; without script it is a link back to the
119 Added: logbook. *)
120 Added: tag "a"
121 Added: [
122 Added: href Routes.logbook;
123 Added: class_ "button outline confirm-dialog-close";
124 Added: Dream_html.attr "data-hito-confirm-dismiss";
125 Added: ]
126 Added: [ txt "Discard" ];
127 Added: ];
114 128 tag "p" []
115 129 [
116 130 txt "Delete %s from %s. This cannot be undone." record.workout_name
117 131 record.date;
118 132 ];
119 133 tag "div"
120 Removed: [ class_ "button-group" ]
134 Added: [ class_ "confirm-dialog-actions" ]
121 135 [
122 Removed: tag "a"
123 Removed: [ href Routes.logbook; class_ "button secondary" ]
124 Removed: [ txt "Keep workout" ];
125 136 tag "form"
126 137 [
127 138 action Routes.delete_record record.id;
lib/web/assets/hito.css
index 90d4a644..8a7c9196 100644..100644
@@ -685,8 +685,26 @@
685 685 background: var(--oxblood-hover);
686 686 }
687 687 .confirm-dialog button.danger:hover { background: var(--oxblood); }
688 Removed: .confirm-dialog .delete-record-form { flex: 1 1 10rem; margin: 0; }
689 Removed: .confirm-dialog .delete-record-form button { width: 100%; }
688 Added: .confirm-dialog .delete-record-form { margin: 0; }
689 Added: /* Heading row: title left, an oxblood-outline Discard control top-right. */
690 Added: .confirm-dialog-heading {
691 Added: display: flex;
692 Added: align-items: flex-start;
693 Added: justify-content: space-between;
694 Added: gap: 1rem;
695 Added: }
696 Added: .confirm-dialog-heading h2 { margin: 0; }
697 Added: .confirm-dialog-close { flex: 0 0 auto; }
698 Added: /* The delete action sits centred at the bottom of the modal. */
699 Added: .confirm-dialog-actions {
700 Added: display: flex;
701 Added: justify-content: center;
702 Added: margin-top: 1.25rem;
703 Added: }
704 Added: .confirm-dialog-actions .delete-record-form button {
705 Added: width: auto;
706 Added: min-width: 12rem;
707 Added: }
690 708
691 709 .logbook-detail-row {
692 710 display: block;
lib/web/handlers_logbook.ml
index 4e0166fc..46bfc659 100644..100644
@@ -299,7 +299,7 @@
299 299 (fun entry ->
300 300 String.equal entry.View_model.Logbook_entry.id id
301 301 && not entry.View_model.Logbook_entry.imported)
302 Removed: records
302 Added: all_records
303 303 | None -> None
304 304 in
305 305 let expanded_record =
lib/web/workout_client.ml
index 120940a6..a3821cb9 100644..100644
@@ -194,6 +194,16 @@
194 194 open_feedback_modal ()
195 195 | _ -> ()
196 196
197 Added: (* A server-rendered confirm dialog (e.g. delete) arrives with the [open]
198 Added: attribute so it works without script. With script, upgrade it to a true
199 Added: modal so it centres on the viewport and draws a backdrop. *)
200 Added: let open_marked_confirm_modal () =
201 Added: match query_one document "dialog.confirm-dialog[open]" with
202 Added: | Some modal ->
203 Added: modal##removeAttribute (Js.string "open");
204 Added: ignore (Js.Unsafe.meth_call modal "showModal" [||])
205 Added: | None -> ()
206 Added:
197 207 let replace selector html =
198 208 let next = Dom_html.createDiv document in
199 209 next##.innerHTML := Js.string html;
@@ -219,6 +229,7 @@
219 229 start_timer ();
220 230 dismiss_toast ();
221 231 open_marked_feedback_modal ();
232 Added: open_marked_confirm_modal ();
222 233 true
223 234 | _ -> false
224 235
@@ -404,9 +415,11 @@
404 415 Js._false
405 416 | None -> (
406 417 match closest "[data-hito-confirm-dismiss]" target with
407 Removed: | Some _ ->
418 Added: | Some dismiss ->
408 419 Dom.preventDefault event;
409 Removed: close_modal ();
420 Added: (match closest "dialog" dismiss with
421 Added: | Some modal -> ignore (Js.Unsafe.meth_call modal "close" [||])
422 Added: | None -> close_modal ());
410 423 Js._false
411 424 | None -> (
412 425 match closest "[data-hito-confirm-accept]" target with
@@ -493,4 +506,5 @@
493 506 Js._false
494 507 |> ignore;
495 508 start_timer ();
496 Removed: dismiss_toast ()
509 Added: dismiss_toast ();
510 Added: open_marked_confirm_modal ()