mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-20 17:50:12 +02:00
fix(inventory): malformed rgba no longer bricks the Filaments page (#1055)
A single legacy spool with a 7-char rgba ('FFFFFFF', missing one F)
caused GET /api/v1/inventory/spools to 500 with a pydantic
ResponseValidationError, leaving the reporter with a blank Filaments
page and "Add Spool" silently failing. Root cause spans three layers:
1. Write path: SpoolUpdate.rgba had no pattern constraint (only
SpoolCreate did), so PATCH could plant malformed values in the DB.
2. Frontend: ColorSection hex input's `val.length <= 6 ? 'FF' : ''`
emitted 7-char rgba for 5-char input (XXXXX + FF = 7) and for
7-char typed input (no alpha appended).
3. Read path: SpoolResponse inherited the write-side pattern, so a
single bad row 500'd the entire list endpoint instead of being
tolerated through serialize.
SpoolUpdate.rgba now carries the same ^[0-9A-Fa-f]{8}$ pattern as
SpoolCreate. The hex input emits a fully-formed 8-char RRGGBBAA on
every keystroke — 8-char paste passes through, 7-char drops the
stray, shorter input pads RGB with '0' and appends FF alpha.
SpoolResponse.rgba is now Optional[str] with no pattern — write-side
validation is the right place for format rules; responses must
tolerate historical rows.
Tests: 16 schema tests (SpoolCreate/Update reject, SpoolResponse
tolerate), 7 frontend tests covering every input length 0–8 plus
non-hex strip. A user who already has a bad row in their DB now sees
it render with a default color instead of having to hand-edit SQLite.
This commit is contained in:
@@ -253,12 +253,22 @@ export function SpoolFormModal({
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
if (spool) {
|
||||
// Legacy rows may carry a malformed rgba (e.g. the 7-char 'FFFFFFF'
|
||||
// from #1055 before the create/update pattern was enforced). The
|
||||
// backend SpoolUpdate schema rejects non-8-char hex on PATCH, so
|
||||
// re-submitting a malformed value would 422 every edit on that spool
|
||||
// — even edits that don't touch color. Normalize on load: any value
|
||||
// that isn't exactly 8 hex chars falls back to the default, so the
|
||||
// user can save unrelated fields (weight, material, note) without
|
||||
// first being forced to fix a color they may not even be aware is
|
||||
// broken. Saving also purges the bad value from the DB.
|
||||
const validRgba = spool.rgba && /^[0-9A-Fa-f]{8}$/.test(spool.rgba) ? spool.rgba : '808080FF';
|
||||
setFormData({
|
||||
material: spool.material || '',
|
||||
subtype: spool.subtype || '',
|
||||
brand: spool.brand || '',
|
||||
color_name: spool.color_name || '',
|
||||
rgba: spool.rgba || '808080FF',
|
||||
rgba: validRgba,
|
||||
label_weight: spool.label_weight || 1000,
|
||||
core_weight: spool.core_weight || 250,
|
||||
core_weight_catalog_id: spool.core_weight_catalog_id ?? null,
|
||||
|
||||
Reference in New Issue
Block a user