From 60b253f98a0124b487d007c9ca19e541c2af68ab Mon Sep 17 00:00:00 2001 From: maziggy Date: Wed, 10 Jun 2026 08:02:36 +0200 Subject: [PATCH] fix(failure-reason): consistent camelCase keys across UI surfaces The Stats page's Failure Analysis widget and the per-archive run sub-table rendered the raw PrintLogEntry.failure_reason value without translating, so the camelCase keys saved by the new Print Log row editor (#1687 part 4) surfaced as literal "filamentRunout" / "cloggedNozzle" text. The Print Log table did translate the value, so the inconsistency was visible from one surface to the next. EditArchiveModal was also still saving the localised label as the column value while the new editor saved the key - same column, two formats, two failure modes (group fragmentation on language switch, new PATCH validation rejection on round-trip). Three surfaces fixed in one drop: 1. StatsPage.tsx and PrintLogTable.tsx wrap the value in t('editArchive.failureReasons.${reason}', { defaultValue: reason }) - the defaultValue path keeps legacy translated-text rows rendering unchanged. 2. EditArchiveModal stores the camelCase key on save and reverse- looks up any legacy translated-text value against the current locale on open. Every save thereafter converts that row forward to the key format, so the column self-heals over time. 3. Added htmlFor/id to the failure-reason label/select pair (a11y plus testability). --- CHANGELOG.md | 2 + .../components/EditArchiveModal.test.tsx | 43 ++++ .../components/PrintLogModal.test.tsx | 17 ++ .../src/__tests__/pages/StatsPage.test.tsx | 43 ++++ frontend/src/components/EditArchiveModal.tsx | 19 +- frontend/src/components/PrintLogTable.tsx | 2 +- frontend/src/pages/StatsPage.tsx | 4 +- .../{index-QVjYxA_R.js => index-DdAEkh5e.js} | 232 +++++++++--------- static/index.html | 2 +- 9 files changed, 242 insertions(+), 122 deletions(-) rename static/assets/{index-QVjYxA_R.js => index-DdAEkh5e.js} (92%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 584c328b4..c5cba8380 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ All notable changes to Bambuddy will be documented in this file. - **Print Log page: per-row delete (#1687 part 1, reported by @IndividualGhost1905)** — Reporter noted that the existing "Also remove this print from Quick Stats" toggle on archive delete is one-shot: if you tick "keep stats" at delete time, there was no later way to drop the row from /stats; and rows that aren't tied to an archive (errors, aborts, manual entries) had no delete affordance at all. **Fix:** every row in the Archives → Print Log table now has a trash icon next to the filament cell, gated on `archives:delete_own` (own rows) or `archives:delete_all` (any row), matching the archive-delete permission shape. Click → confirm modal → row is gone, and because /archives/stats aggregates over `PrintLogEntry` the filament / time / cost contribution drops out of Quick Stats in the same response cycle. The matching archive (if any) is untouched — the log row is a sibling, not a child. **Backend:** new `DELETE /print-log/{entry_id}` mirrors `delete_archive`'s ownership flow via `require_ownership_permission(ARCHIVES_DELETE_ALL, ARCHIVES_DELETE_OWN)`; owners can drop their own rows, admins can drop any row, missing IDs return 404 rather than 200-silently. **Frontend:** new `deletePrintLogEntry` API helper, per-row mutation that invalidates both `print-log` and `archives-stats` query keys so the totals re-render without a manual refresh. **i18n:** 4 new keys (`deleteEntryTitle`, `deleteEntryConfirm`, `entryDeleted`, `entryDeleteFailed`) translated across all 11 locales (de / en / es / fr / it / ja / ko / pt-BR / tr / zh-CN / zh-TW). **Tests:** 3 backend integration cases — delete drops the row from /stats while keeping the linked archive listed, missing ID returns 404, delete-one does not touch siblings (regression guard against an accidental `delete(PrintLogEntry)` without a `where`). Frontend ArchivesPage / PrintLogModal vitests stay green (31 / 31). i18n parity green (5099 leaves × 11 locales). Issue #1687 also asks for per-row tagging (already covered by `EditArchiveModal`'s tags field) and per-row filament-usage-history edits (deferred — see the issue thread for the reasoning). ### Fixed +- **Stats page Failure Analysis widget rendered raw camelCase keys instead of translated reasons (#1687 follow-up, reported by @IndividualGhost1905)** — After #1687 part 4 shipped the per-row Print Log editor, the reporter classified a couple of failed runs and saw "filamentRunout" / "cloggedNozzle" (the literal camelCase keys) appear under Statistics → Failure Analysis → Top Failure Reasons, while the same rows rendered correctly as "Filament runout" / "Clogged nozzle" on the Print Log table. Surfaced an inconsistency I introduced when shipping the new editor: the new Print Log row editor saves the camelCase key (`filamentRunout`) which is what the new backend PATCH validates against, but the older `EditArchiveModal` was still saving the localised label (`"Filament runout"`) as the value — two formats landing in the same `PrintLogEntry.failure_reason` column from two different UI surfaces. The Failure Analysis widget at `frontend/src/pages/StatsPage.tsx:817` and the per-archive run history sub-table at `frontend/src/components/PrintLogTable.tsx:81` both rendered the raw column value without running it through i18n, so the new key-form values surfaced as literal keys. **Fix — three sites in one drop:** (1) `StatsPage.tsx` and (2) `PrintLogTable.tsx` now wrap the value in `t('editArchive.failureReasons.${reason}', { defaultValue: reason })` — same pattern already used at `ArchivesPage.tsx:3874` for the Print Log table. The `defaultValue` fallback keeps legacy translated-text rows rendering as-is, no regression. (3) `EditArchiveModal.tsx` now saves the camelCase key (`