From 23de433bdb9f280acb6ba9eb217f91220ab82e4c Mon Sep 17 00:00:00 2001 From: Ty Balascio Date: Fri, 25 Sep 2026 20:23:29 -0700 Subject: [PATCH] fix(fe): attach the session's processed PNGs to the draft photos onPhotosReady built the draft photos from the raw captured JPEGs and dropped every PNG the session had already produced, so processedBlob was never set on the M2 path (only the legacy PhotoImport path set it). photoUpload then omitted the processed multipart field, slab_photos.processed_blob stayed NULL, and publish.py - which selects WHERE processed_blob IS NOT NULL - uploaded zero images to Woo. The verified SLAB-UAT-901 draft had images: 0. Attach results.inventoryPng to the calibration photo and each successful batchApply entry to its sibling, and add the dimension-overlay copy as its own photo adjacent to the calibration one (REVIEW-5). --- frontend/src/App.svelte | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index bfbb610..6a3f764 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -118,17 +118,46 @@ widthAvgIn: results.widths.avg, }) : draft(); + // The session already produced the processed PNGs: the calibration + // inventory PNG in results.inventoryPng and each sibling's in + // results.batchApply (parallel to s.batch). Attach them as + // processedBlob so the server upload carries real images (PUBLISH-40). + const calIdx = s.calibrationIndex; + const apply = results?.batchApply; const photos = s.batch.map((source, i) => ({ id: `cap-${i}-${source.blob.size}`, seq: i + 1, - isCalibration: i === s.calibrationIndex, + isCalibration: i === calIdx, url: URL.createObjectURL(source.blob), blob: source.blob, widthPx: source.widthPx, heightPx: source.heightPx, + processedBlob: + i === calIdx + ? results?.inventoryPng + : apply?.[i]?.status === 'ok' + ? apply[i].inventoryPng + : undefined, })); + // The dimension-overlay copy (REVIEW-5) is its own photo, adjacent to + // the calibration one and never flagged as it. Absent when the overlay + // encode failed (known separate defect) — the lineup just shows no overlay. + if (results?.overlayPng && calIdx != null) { + const overlay = { + id: `overlay-${calIdx}-${results.overlayPng.size}`, + seq: calIdx + 2, + isCalibration: false, + url: URL.createObjectURL(results.overlayPng), + blob: results.overlayPng, + widthPx: s.batch[calIdx]?.widthPx, + heightPx: s.batch[calIdx]?.heightPx, + processedBlob: results.overlayPng, + }; + photos.splice(calIdx + 1, 0, overlay); + for (const p of photos) p.seq = photos.indexOf(p) + 1; + } d.photos = photos; - d.calibrationPhotoId = s.calibrationIndex != null ? photos[s.calibrationIndex]?.id ?? '' : ''; + d.calibrationPhotoId = calIdx != null ? photos[calIdx]?.id ?? '' : ''; slab.set(d); await saveDraft(d); }