Commit 338deb0
* feat(admin): add note partials and render_partial for HTMX swaps
Extract the per-note markup into themes/default/admin/_note_item.html plus a new _note_edit_form.html. Add ThemeEngine.render_partial() so the admin notes endpoints can return self-contained HTML fragments without the heavy default render context (no nav/favicon/featured_posts fetches).
Partials live only in the default theme — the AsyncHybridLoader fallback means blue-tech and terminal pick them up automatically. The three admin templates now {% include %} the shared partial.
Refs #71
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(admin): make notes endpoints respond to HTMX form submissions
Branch /admin/notes POST/PUT/DELETE on the HX-Request header. HTMX requests get rendered HTML partials (_note_item.html); non-HTMX callers continue to get JSON (NoteResponse / {status: deleted}). Form-urlencoded payloads from HTMX forms are now accepted alongside JSON via parse_note_create / parse_note_update helpers.
Also: unchecking the is_public checkbox in the edit form now persists is_public=False (form data omits absent checkboxes, so the parser explicitly sets the field). Auth failures on HTMX requests now attach HX-Redirect: /auth/login so the browser bounces to login without any client JS.
Adds two new routes for inline editing: GET /admin/notes/{id}/edit (returns _note_edit_form.html) and GET /admin/notes/{id}/view (returns _note_item.html, used by the edit form's Cancel button).
Refs #71
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(admin): cover HTMX/JSON dual-response notes CRUD
13 new tests against the admin notes endpoints:
- JSON path returns NoteResponse; HTMX path returns rendered HTML partial
- Unchecked is_public checkbox persists False (both create and update)
- 404s on missing notes for PUT/DELETE/edit-form
- DELETE with HX-Request returns empty 200; without it returns {status: deleted}
- HX-Redirect header attached only on HTMX auth failures
Refs #71
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(deps): add python-multipart for form parsing
Required by Starlette/FastAPI's request.form() to parse application/x-www-form-urlencoded bodies, which the new HTMX admin notes flow relies on. Without it, PUT /admin/notes/{id} from the inline edit form returns 500 with 'The python-multipart library must be installed to use form parsing.'
Refs #71
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(admin): address Copilot review on #78
Three issues raised by Copilot's PR review:
1. parse_note_create/parse_note_update now catch JSON decode errors and Pydantic ValidationError, re-raising as HTTPException(422). Previously a malformed JSON body or missing required field would bubble up as 500 because the validation happened outside FastAPI's parameter binding.
2. Form parsing no longer coerces missing fields to empty strings. Absent fields are simply not included in the dict, so Pydantic enforces required-ness on create (path/text both 422 if missing) and absent text on update is treated as 'no change' (text=None) instead of overwriting with ''.
3. ThemeEngine.render_partial now saves and restores loader.current_theme in a try/finally so concurrent HTMX requests with different themes can't leak state into each other.
Adds 6 new tests covering the 422 paths, missing-field behaviors on form data, and theme-state restoration (including on render exceptions).
Refs #71, #78
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 4545f16 commit 338deb0
9 files changed
Lines changed: 695 additions & 115 deletions
File tree
- src/squishmark
- routers
- services/theme
- tests
- themes
- blue-tech/admin
- default/admin
- terminal/admin
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| 32 | + | |
32 | 33 | | |
33 | 34 | | |
34 | 35 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
7 | 8 | | |
8 | | - | |
| 9 | + | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
12 | 13 | | |
13 | | - | |
| 14 | + | |
14 | 15 | | |
15 | 16 | | |
16 | 17 | | |
| |||
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
25 | 31 | | |
26 | 32 | | |
27 | 33 | | |
| |||
66 | 72 | | |
67 | 73 | | |
68 | 74 | | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
69 | 78 | | |
70 | 79 | | |
71 | 80 | | |
| |||
74 | 83 | | |
75 | 84 | | |
76 | 85 | | |
| 86 | + | |
| 87 | + | |
77 | 88 | | |
78 | 89 | | |
79 | 90 | | |
80 | 91 | | |
81 | | - | |
| 92 | + | |
82 | 93 | | |
83 | 94 | | |
84 | | - | |
| 95 | + | |
85 | 96 | | |
86 | 97 | | |
87 | 98 | | |
| |||
90 | 101 | | |
91 | 102 | | |
92 | 103 | | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
93 | 191 | | |
94 | 192 | | |
95 | 193 | | |
| |||
122 | 220 | | |
123 | 221 | | |
124 | 222 | | |
125 | | - | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
133 | | - | |
134 | | - | |
135 | | - | |
136 | | - | |
| 223 | + | |
137 | 224 | | |
138 | 225 | | |
139 | 226 | | |
| |||
180 | 267 | | |
181 | 268 | | |
182 | 269 | | |
| 270 | + | |
183 | 271 | | |
184 | 272 | | |
185 | | - | |
186 | | - | |
187 | | - | |
188 | | - | |
189 | | - | |
190 | | - | |
191 | | - | |
192 | | - | |
193 | | - | |
194 | | - | |
195 | | - | |
196 | | - | |
| 273 | + | |
197 | 274 | | |
198 | 275 | | |
199 | | - | |
| 276 | + | |
200 | 277 | | |
| 278 | + | |
201 | 279 | | |
202 | 280 | | |
203 | | - | |
204 | | - | |
205 | | - | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
206 | 284 | | |
207 | 285 | | |
208 | 286 | | |
209 | 287 | | |
210 | 288 | | |
211 | 289 | | |
212 | 290 | | |
213 | | - | |
214 | | - | |
215 | | - | |
216 | | - | |
217 | | - | |
218 | | - | |
219 | | - | |
220 | | - | |
221 | | - | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
222 | 296 | | |
223 | 297 | | |
224 | | - | |
| 298 | + | |
225 | 299 | | |
| 300 | + | |
226 | 301 | | |
227 | 302 | | |
228 | 303 | | |
229 | | - | |
230 | | - | |
231 | | - | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
232 | 308 | | |
233 | 309 | | |
234 | 310 | | |
| |||
237 | 313 | | |
238 | 314 | | |
239 | 315 | | |
240 | | - | |
241 | | - | |
242 | | - | |
243 | | - | |
244 | | - | |
245 | | - | |
246 | | - | |
247 | | - | |
248 | | - | |
249 | | - | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
250 | 321 | | |
251 | 322 | | |
252 | | - | |
| 323 | + | |
253 | 324 | | |
| 325 | + | |
254 | 326 | | |
255 | 327 | | |
256 | 328 | | |
257 | | - | |
258 | | - | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
259 | 332 | | |
260 | 333 | | |
261 | 334 | | |
262 | 335 | | |
| 336 | + | |
| 337 | + | |
263 | 338 | | |
264 | 339 | | |
265 | 340 | | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
266 | 373 | | |
267 | 374 | | |
268 | 375 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
282 | 282 | | |
283 | 283 | | |
284 | 284 | | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
285 | 309 | | |
286 | 310 | | |
287 | 311 | | |
| |||
0 commit comments