main
tag: launch-2026-06-01
tag: magicmirror-v0.1.1
tag: magicmirror-v0.3.0
tag: mnw-cli-v0.1.2
tag: mnw-cli-v0.1.3
tag: mnw-cli-v0.1.4
tag: pom-v0.4.1
tag: pom-v0.4.2
tag: pom-v0.4.3
tag: pom-v0.4.4
tag: pom-v0.4.5
tag: wam-v0.3.0
tag: wam-v0.3.1
Files
Commits
Tags
Notes
Issues
Fix item save feedback, redesign public download list
Return 'Saved.' HTML for HTMX item update requests instead of raw
JSON. Redesign public item page version history as a flat download
list showing version number, label (or filename), size, and
download button. Renamed section from "Version History" to
"Downloads".
Co-Authored-By
Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2 files changed,
+19 insertions,
-14 deletions
366
366
367
367
{% if !versions.is_empty() %}
368
368
<section class="item-versions">
369
-
<h2>Version History</h2>
369
+
<h2>Downloads</h2>
370
370
{% for version in versions %}
371
-
<div class="version-item">
372
-
<div class="version-header">
373
-
<span class="version-number">v{{ version.number }}</span>
374
-
<span class="version-date">{{ version.uploaded_date }}</span>
375
-
</div>
376
-
{% if version.has_file %}
377
-
<div class="version-download" style="margin-top: 0.5rem;">
378
-
<span class="version-notes" style="margin-right: 1rem;">{{ version.size }}</span>
379
-
<button class="secondary" style="padding: 0.4rem 0.8rem; font-size: 0.85rem;"
380
-
onclick="downloadVersion('{{ version.id }}')">Download</button>
381
-
</div>
371
+
{% if version.has_file %}
372
+
<div style="display: flex; align-items: center; gap: 1rem; padding: 0.6rem 0; border-bottom: 1px solid var(--border);">
373
+
<span style="min-width: 4em; font-family: var(--font-mono); font-size: 0.9rem;">v{{ version.number }}</span>
374
+
{% if let Some(label) = version.label %}
375
+
<span style="flex: 1;">{{ label }}</span>
376
+
{% else %}
377
+
<span style="flex: 1; opacity: 0.5;">{% match version.file_name %}{% when Some with (name) %}{{ name }}{% when None %}Download{% endmatch %}</span>
382
378
{% endif %}
379
+
<span style="font-size: 0.85rem; opacity: 0.6; min-width: 5em; text-align: right;">{{ version.size }}</span>
380
+
<button class="secondary" style="padding: 0.4rem 0.8rem; font-size: 0.85rem;"
381
+
onclick="downloadVersion('{{ version.id }}')">Download</button>
383
382
</div>
383
+
{% endif %}
384
384
{% endfor %}
385
385
</section>
386
386
{% endif %}
165
165
#[tracing::instrument(skip_all, name = "items::update_item", fields(item_id))]
166
166
pub(in crate::routes::api) async fn update_item(
167
167
State(state): State<AppState>,
168
+
headers: HeaderMap,
168
169
AuthUser(user): AuthUser,
169
170
Path(id): Path<ItemId>,
170
171
Form(req): Form<UpdateItemRequest>,
171
-
) -> Result<impl IntoResponse> {
172
+
) -> Result<Response> {
172
173
tracing::Span::current().record("item_id", tracing::field::display(&id));
173
174
user.check_not_suspended()?;
174
175
verify_item_ownership(&state, id, user.id).await?;
254
255
255
256
db::projects::bump_cache_generation(&state.db, updated.project_id).await?;
256
257
258
+
if is_htmx_request(&headers) {
259
+
return Ok(axum::response::Html("Saved.".to_string()).into_response());
260
+
}
261
+
257
262
Ok(Json(ItemResponse {
258
263
id: updated.id,
259
264
project_id: updated.project_id,
266
271
web_only: updated.web_only,
267
272
ai_tier: updated.ai_tier,
268
273
ai_disclosure: updated.ai_disclosure,
269
-
}))
274
+
}).into_response())
270
275
}
271
276
272
277
/// Soft-delete an item owned by the authenticated user (recoverable for 7 days).