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 the row id is a parameter, and why the row grew one |
| 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 | //! The blog pair ([`super::blog_delete_act`]) converted because its templates |
| 26 | //! already gave each row a real id. This one's `<tr>` did not, and the handler |
| 27 | //! it replaces reached the row through `closest('tr')`. So the template grew |
| 28 | //! `id="version-row-{id}"` in the same change. That is worth telling apart from |
| 29 | //! the two rows that are still hand-written: `partials/link_row.html` and |
| 30 | //! `partials/tag.html` target `closest .<class>` on rows whose identity is a |
| 31 | //! CSS class and nothing else, and inventing an id for them would be describing |
| 32 | //! a fact the page does not have. A version row has an id in the database and |
| 33 | //! the template was simply not writing it down. |
| 34 | //! |
| 35 | //! # The download button beside it is not here, and that is measured |
| 36 | //! |
| 37 | //! Wiki [[mnw-shape-conversion-plans]] Shape 3 step 4 says |
| 38 | //! `download-version-btn` is `Action::get`. It is not. |
| 39 | //! `GET /api/versions/{id}/download` (`routes::storage::downloads`) answers |
| 40 | //! **JSON carrying a presigned URL**, and the handler then navigates to it, so |
| 41 | //! a described `Action::get` would send the reader to a JSON body. Making it |
| 42 | //! sayable is a route change — answer a redirect, or serve the route through |
| 43 | //! the description layer so it can answer `Outcome::Goto` with a |
| 44 | //! `Destination::External` — rather than a control change, so the handler |
| 45 | //! stays. |
| 46 | |
| 47 | use Tone; |
| 48 | use Act; |
| 49 | use ; |
| 50 | |
| 51 | /// The delete button for one version's row. |
| 52 | /// |
| 53 | /// Both ids are needed and they are not the same fact: the route is addressed |
| 54 | /// by item and version together, and the row is named by the version alone. |
| 55 | |
| 56 | |
| 57 | Act |
| 58 | new |
| 59 | "Delete", |
| 60 | delete |
| 61 | .replacing, |
| 62 | |
| 63 | .tone |
| 64 | .confirm, |
| 65 | |
| 66 | |
| 67 | |
| 68 | /// The same act as a fragment, for the Askama call site. |
| 69 | |
| 70 | |
| 71 | use Serves as _; |
| 72 | |
| 73 | new.fragment |
| 74 | |
| 75 | |
| 76 | |
| 77 | |
| 78 | /// What the click handler said in four places, said once: where it goes, |
| 79 | /// what it replaces, and what to ask first. |
| 80 | |
| 81 | |
| 82 | let html = html; |
| 83 | |
| 84 | assert! |
| 85 | html.contains, |
| 86 | "{html}" |
| 87 | ; |
| 88 | assert!; |
| 89 | assert! |
| 90 | html.contains, |
| 91 | "{html}" |
| 92 | ; |
| 93 | |
| 94 | |
| 95 | /// The tone. The template said nothing at all here -- the button was |
| 96 | /// `btn-secondary`, so the page did not mark the destructive act even to |
| 97 | /// the stylesheet. |
| 98 | |
| 99 | |
| 100 | let html = html; |
| 101 | |
| 102 | assert!; |
| 103 | |
| 104 | |
| 105 | /// The negative half, as `export_act` asserts it: the dispatcher is gone |
| 106 | /// from this control, not merely bypassed. |
| 107 | |
| 108 | |
| 109 | let html = html; |
| 110 | |
| 111 | assert!; |
| 112 | assert!; |
| 113 | |
| 114 | |
| 115 |