max / makenotwork
| 1 | //! The Askama entry point for a described "delete this version" button. |
| 2 | //! |
| 3 | //! Shape 3 step 4 (`108557ec`), the step the plan calls the clean tail: the one |
| 4 | //! part of `static/item-upload.js` that retires with no host remnant. It waited |
| 5 | //! on `27d5e5b8` (a described act inside an Askama page) and on `35756077` (the |
| 6 | //! unlayered `button` rule taking the tone off every described act). Both are |
| 7 | //! settled, so it converts. |
| 8 | //! |
| 9 | //! # What the description says that the markup did not |
| 10 | //! |
| 11 | //! Everything, in this case. There was no markup: the button carried a class |
| 12 | //! and a `data-version-id`, and the whole act lived in a click handler in |
| 13 | //! `item-upload.js` — a `confirm()` string, a `fetch` with CSRF headers, and a |
| 14 | //! `btn.closest('tr').remove()` on success. None of that is legible to anything |
| 15 | //! but a browser. As an [`Act`] it is one sentence: what it is called, where it |
| 16 | //! goes, what it replaces, that it is destructive, and what to ask first. |
| 17 | //! |
| 18 | //! # Why it names what it replaced, and why the spelling changed |
| 19 | //! |
| 20 | //! `DELETE /api/items/{item}/versions/{version}` is a plain API route the |
| 21 | //! description layer does not serve; it answers `200` with an empty body, so it |
| 22 | //! cannot name what it changed and the control has to. See |
| 23 | //! [`Action::replaces`]. |
| 24 | //! |
| 25 | //! It said `#version-row-{id}`, an id the Askama table grew in the same change |
| 26 | //! that landed this module, because the handler it replaced reached the row |
| 27 | //! through `closest('tr')`. The table is described now (`super::item_files`, |
| 28 | //! `138ad5ab`) and a described row carries `data-row` and no id at all, so an |
| 29 | //! id target would name nothing. [`Action::replacing_enclosing`] is the same |
| 30 | //! sentence in the spelling a described row understands, and it needs no |
| 31 | //! parameter: the act is inside the row it removes. |
| 32 | //! |
| 33 | //! # The download button beside it is sayable now, and was not when this landed |
| 34 | //! |
| 35 | //! `download-version-btn` is `Action::get`. `GET /api/versions/{id}/download` |
| 36 | //! (`routes::storage::downloads`) answers **303 to the presigned URL**, so |
| 37 | //! navigating to it is the download and `Action::get` says the truth. The button |
| 38 | //! is a plain navigation in `static/item-upload.js` today and becomes an act |
| 39 | //! whenever the files tab converts. |
| 40 | |
| 41 | use declare; |
| 42 | |
| 43 | declare! |
| 44 | /// The delete button for one version's row. |
| 45 | /// |
| 46 | /// Both ids are needed for the address, which is item and version together. |
| 47 | /// The row it removes is the one it sits in, so nothing has to name it. |
| 48 | |
| 49 | pub shape act ; |
| 50 | |
| 51 | act "Delete" to delete "/api/items/{item_id}/versions/{version_id}" replacing_enclosing |
| 52 | tone Danger; |
| 53 | confirm "Delete this version?"; |
| 54 | |
| 55 | |
| 56 | |
| 57 | |
| 58 | |
| 59 | use Node; |
| 60 | |
| 61 | /// What the click handler said in four places, said once: where it goes, |
| 62 | /// what it replaces, and what to ask first. |
| 63 | /// |
| 64 | /// Rendered through a bare `Node::Act` rather than through the panel: this |
| 65 | /// module owns the sentence, and `super::item_files` asserts it arrives in |
| 66 | /// the row. |
| 67 | |
| 68 | use Serves as _; |
| 69 | |
| 70 | new.fragment |
| 71 | |
| 72 | |
| 73 | |
| 74 | |
| 75 | let html = html; |
| 76 | |
| 77 | assert! |
| 78 | html.contains, |
| 79 | "{html}" |
| 80 | ; |
| 81 | // The row it sits in, rather than an id the table had to grow. |
| 82 | assert!; |
| 83 | assert! |
| 84 | html.contains, |
| 85 | "{html}" |
| 86 | ; |
| 87 | |
| 88 | |
| 89 | /// The tone. The template said nothing at all here -- the button was |
| 90 | /// `btn-secondary`, so the page did not mark the destructive act even to |
| 91 | /// the stylesheet. |
| 92 | |
| 93 | |
| 94 | assert!; |
| 95 | |
| 96 | |
| 97 | /// The negative half, as `export_act` asserts it: the dispatcher is gone |
| 98 | /// from this control, not merely bypassed. |
| 99 | |
| 100 | |
| 101 | let html = html; |
| 102 | |
| 103 | assert!; |
| 104 | assert!; |
| 105 | |
| 106 | |
| 107 |