Disegno Tecnico: un'immagine BMP viene rifiutata e l'errore non si vede #107

Closed
opened 2026-10-25 17:06:26 +00:00 by Adriano · 3 comments
Owner

src/frontend/flask_app/templates/maker/task_editor.html:2418 (uploadTaskFile) accetta solo png/jpeg/webp/pdf, ma l'input (accept="image/*,application/pdf", righe ~860 e ~876) lascia scegliere un .bmp: errorMessage «Formato file non supportato» compare solo nel banner in cima alla pagina (riga 251), fuori vista quando si è scesi al task. Riprodotto 25/10/2026 su daitarn, task 8 ricetta 3, con sider_2_1.bmp (le foto Sider sono BMP). Il backend (src/backend/api/routers/files.py:25) ammette jpeg/png/gif/webp/pdf con controllo dei magic byte. Stesso controllo in templates/maker/recipe_editor.html:690 (uploadFile).

src/frontend/flask_app/templates/maker/task_editor.html:2418 (uploadTaskFile) accetta solo png/jpeg/webp/pdf, ma l'input (accept="image/*,application/pdf", righe ~860 e ~876) lascia scegliere un .bmp: errorMessage «Formato file non supportato» compare solo nel banner in cima alla pagina (riga 251), fuori vista quando si è scesi al task. Riprodotto 25/10/2026 su daitarn, task 8 ricetta 3, con sider_2_1.bmp (le foto Sider sono BMP). Il backend (src/backend/api/routers/files.py:25) ammette jpeg/png/gif/webp/pdf con controllo dei magic byte. Stesso controllo in templates/maker/recipe_editor.html:690 (uploadFile).
Adriano added the bug label 2026-10-25 17:06:26 +00:00
Author
Owner

ESITO: richiesta
RIF: gitea:Adriano/TieMeasureFlow#107
COSA: Disegno Tecnico del task (e disegno della ricetta): un'immagine che il browser sa leggere ma il backend non ammette (BMP) si converte in PNG nel browser prima del ritaglio e del caricamento; l'errore di caricamento compare anche dentro il riquadro Disegno Tecnico del task.

BASE: ramo lavoro/daitarn-tmf-107 da 5737655, worktree C:/Users/Adriano/lavoro/TieMeasureFlow-107.

MODIFICHE

  1. Nuovo file src/frontend/flask_app/static/js/image_to_png.js, due funzioni globali:
    • tmfNeedsPng(type): true se type comincia con 'image/' e non è fra image/png, image/jpeg, image/jpg, image/gif, image/webp. Funzione pura.
    • async tmfImageToPng(file): se !tmfNeedsPng(file.type) ritorna file invariato. Altrimenti createImageBitmap(file), poi canvas con le stesse dimensioni, drawImage, canvas.toBlob(..., 'image/png'), e ritorna new File([blob], <nome senza estensione> + '.png', {type: 'image/png'}). Se la decodifica fallisce (es. TIFF) ritorna null.
    • In coda, if (typeof module !== 'undefined') module.exports = { tmfNeedsPng, tmfImageToPng }; per il test node, sullo schema di static/js/dxf_recipe_wizard.js se ne ha uno.
  2. templates/maker/task_editor.html:
    • includere lo script, come gli altri static/js della pagina (cercare url_for('static', filename='js/);
    • uploadTaskFile (~riga 2415): come primo passo dopo if (!file) return;, file = await tmfImageToPng(file); se null → errorMessage «Formato immagine non leggibile. Usa PNG, JPG o PDF.» e uploadErrorTask = taskId, return. Poi il controllo allowedTypes resta com'è.
    • nuovo stato uploadErrorTask: null: valorizzato a taskId in ogni ramo di errore di uploadTaskFile (formato, dimensione, errore upload, errore salvataggio, catch); azzerato all'inizio di un upload riuscito e quando errorMessage si svuota non serve gestirlo.
    • nel riquadro Disegno Tecnico (~riga 831), sotto le due template x-if, una riga <p x-show="uploadErrorTask === task.id && errorMessage" x-text="errorMessage" class="text-xs text-red-600 dark:text-red-400 mt-2"></p>. Il banner in cima resta.
  3. templates/maker/recipe_editor.html uploadFile (~riga 686): stesso primo passo file = await tmfImageToPng(file) (null → errorMessage come sopra) e inclusione dello script. Niente riga inline nuova lì.
  4. Testo nuovo con _() e voce in translations/it e translations/en messages.po (en: "Unreadable image format. Use PNG, JPG or PDF."). Niente .mo.
  5. Commento «#107» breve su ogni modifica.

TEST

  • Nuovo src/frontend/flask_app/tests/js/test_image_to_png.js eseguito con node (schema di tests/js/test_dxf_preview.js): tmfNeedsPng('image/bmp') true, ('image/png') false, ('image/jpeg') false, ('application/pdf') false; tmfImageToPng con un finto file png → stesso oggetto.
  • Verificare come i test js vengono lanciati dalla suite pytest (cercare test che invocano node) e seguire lo stesso modo.
  • tests/test_dxf_recipe_routes.py o il test della pagina task_editor esistente: la pagina contiene image_to_png.js e uploadErrorTask.
  • Suite da src/frontend/flask_app: C:/Users/Adriano/lavoro/TieMeasureFlow-dxfcal-frontend/.venv/Scripts/python.exe -m pytest tests -q -p no:cacheprovider. Base: 9 failed noti (test_admin_user_pin, csrf x2, local_dt x4, test_measure TestTaskComplete, test_template_js_syntax::test_select_recipe_inline_js_is_valid). Nessun fallimento nuovo.

NON TOCCARE: src/backend/** (il backend resta stretto: niente BMP lato server), vendor/**, il wizard DXF (blocco ~662-830 di task_editor.html e dxf_recipe_wizard.js), measure/task_execute.html, la modale di ritaglio ImageCrop.

PROVA (Opus): dopo merge e riavvio, headless Edge sul task 8 ricetta 3 con sider_2_1.bmp → modale di ritaglio, «Usa originale», task con file_path .png e anteprima.

ESITO: richiesta RIF: gitea:Adriano/TieMeasureFlow#107 COSA: Disegno Tecnico del task (e disegno della ricetta): un'immagine che il browser sa leggere ma il backend non ammette (BMP) si converte in PNG nel browser prima del ritaglio e del caricamento; l'errore di caricamento compare anche dentro il riquadro Disegno Tecnico del task. BASE: ramo lavoro/daitarn-tmf-107 da 5737655, worktree C:/Users/Adriano/lavoro/TieMeasureFlow-107. MODIFICHE 1. Nuovo file src/frontend/flask_app/static/js/image_to_png.js, due funzioni globali: - `tmfNeedsPng(type)`: true se `type` comincia con 'image/' e non è fra image/png, image/jpeg, image/jpg, image/gif, image/webp. Funzione pura. - `async tmfImageToPng(file)`: se `!tmfNeedsPng(file.type)` ritorna `file` invariato. Altrimenti `createImageBitmap(file)`, poi canvas con le stesse dimensioni, drawImage, `canvas.toBlob(..., 'image/png')`, e ritorna `new File([blob], <nome senza estensione> + '.png', {type: 'image/png'})`. Se la decodifica fallisce (es. TIFF) ritorna null. - In coda, `if (typeof module !== 'undefined') module.exports = { tmfNeedsPng, tmfImageToPng };` per il test node, sullo schema di static/js/dxf_recipe_wizard.js se ne ha uno. 2. templates/maker/task_editor.html: - includere lo script, come gli altri static/js della pagina (cercare `url_for('static', filename='js/`); - uploadTaskFile (~riga 2415): come primo passo dopo `if (!file) return;`, `file = await tmfImageToPng(file)`; se null → errorMessage «Formato immagine non leggibile. Usa PNG, JPG o PDF.» e uploadErrorTask = taskId, return. Poi il controllo allowedTypes resta com'è. - nuovo stato `uploadErrorTask: null`: valorizzato a taskId in ogni ramo di errore di uploadTaskFile (formato, dimensione, errore upload, errore salvataggio, catch); azzerato all'inizio di un upload riuscito e quando errorMessage si svuota non serve gestirlo. - nel riquadro Disegno Tecnico (~riga 831), sotto le due template x-if, una riga `<p x-show="uploadErrorTask === task.id && errorMessage" x-text="errorMessage" class="text-xs text-red-600 dark:text-red-400 mt-2"></p>`. Il banner in cima resta. 3. templates/maker/recipe_editor.html uploadFile (~riga 686): stesso primo passo `file = await tmfImageToPng(file)` (null → errorMessage come sopra) e inclusione dello script. Niente riga inline nuova lì. 4. Testo nuovo con `_()` e voce in translations/it e translations/en messages.po (en: "Unreadable image format. Use PNG, JPG or PDF."). Niente .mo. 5. Commento «#107» breve su ogni modifica. TEST - Nuovo src/frontend/flask_app/tests/js/test_image_to_png.js eseguito con node (schema di tests/js/test_dxf_preview.js): tmfNeedsPng('image/bmp') true, ('image/png') false, ('image/jpeg') false, ('application/pdf') false; tmfImageToPng con un finto file png → stesso oggetto. - Verificare come i test js vengono lanciati dalla suite pytest (cercare test che invocano node) e seguire lo stesso modo. - tests/test_dxf_recipe_routes.py o il test della pagina task_editor esistente: la pagina contiene `image_to_png.js` e `uploadErrorTask`. - Suite da src/frontend/flask_app: `C:/Users/Adriano/lavoro/TieMeasureFlow-dxfcal-frontend/.venv/Scripts/python.exe -m pytest tests -q -p no:cacheprovider`. Base: 9 failed noti (test_admin_user_pin, csrf x2, local_dt x4, test_measure TestTaskComplete, test_template_js_syntax::test_select_recipe_inline_js_is_valid). Nessun fallimento nuovo. NON TOCCARE: src/backend/** (il backend resta stretto: niente BMP lato server), vendor/**, il wizard DXF (blocco ~662-830 di task_editor.html e dxf_recipe_wizard.js), measure/task_execute.html, la modale di ritaglio ImageCrop. PROVA (Opus): dopo merge e riavvio, headless Edge sul task 8 ricetta 3 con sider_2_1.bmp → modale di ritaglio, «Usa originale», task con file_path .png e anteprima.
Adriano added the assegnata:daitarn label 2026-10-25 17:06:47 +00:00
Author
Owner

🔵 daitarn — preso in carico 2026-10-25T17:06:43Z
ramo: lavoro/daitarn · capacità: build-windows, gpu

🔵 daitarn — **preso in carico** 2026-10-25T17:06:43Z ramo: `lavoro/daitarn` · capacità: build-windows, gpu
Author
Owner

Soluzione

ESITO: fatto
RIF: gitea:Adriano/TieMeasureFlow#107
COSA: le immagini leggibili dal browser ma non ammesse dal backend (BMP) si convertono in PNG nel browser prima di ritaglio e upload; l'errore di upload compare anche nel riquadro Disegno Tecnico del task.
FILE (sotto src/frontend/flask_app/):

  • static/js/image_to_png.js (nuovo) — tmfNeedsPng(type), tmfImageToPng(file): canvas → File PNG, null se non decodificabile
  • templates/maker/task_editor.html — script incluso; uploadTaskFile converte per primo; stato uploadErrorTask e riga d'errore nel riquadro Disegno Tecnico
  • templates/maker/recipe_editor.html — uploadFile converte per primo
  • translations it/en messages.po — «Formato immagine non leggibile. Usa PNG, JPG o PDF.»
  • tests/js/test_image_to_png.js, tests/test_image_to_png_js.py, tests/test_maker.py
    Commit a3e032d e 249999f (Sonnet, claude-sonnet-5-5), ramo lavoro/daitarn-tmf-dxfcal pushato.
    PROVA:
  • pytest tests (flask_app) → 9 failed noti, 411 passed, 2 skipped
  • daitarn 25/10/2026, TMF riavviato, headless Edge su ricetta 3 task 8 con sider_2_1.bmp: modale di ritaglio aperta, «Usa originale» → POST /maker/api/upload con file sider_2_1.png, image/png, magic \x89PNG, 5,4 MB (upload intercettato, task non modificato); errore simulato visibile nel riquadro del task 8.
    MANCA: nulla.
**Soluzione** ESITO: fatto RIF: gitea:Adriano/TieMeasureFlow#107 COSA: le immagini leggibili dal browser ma non ammesse dal backend (BMP) si convertono in PNG nel browser prima di ritaglio e upload; l'errore di upload compare anche nel riquadro Disegno Tecnico del task. FILE (sotto src/frontend/flask_app/): - static/js/image_to_png.js (nuovo) — tmfNeedsPng(type), tmfImageToPng(file): canvas → File PNG, null se non decodificabile - templates/maker/task_editor.html — script incluso; uploadTaskFile converte per primo; stato uploadErrorTask e riga d'errore nel riquadro Disegno Tecnico - templates/maker/recipe_editor.html — uploadFile converte per primo - translations it/en messages.po — «Formato immagine non leggibile. Usa PNG, JPG o PDF.» - tests/js/test_image_to_png.js, tests/test_image_to_png_js.py, tests/test_maker.py Commit a3e032d e 249999f (Sonnet, claude-sonnet-5-5), ramo lavoro/daitarn-tmf-dxfcal pushato. PROVA: - pytest tests (flask_app) → 9 failed noti, 411 passed, 2 skipped - daitarn 25/10/2026, TMF riavviato, headless Edge su ricetta 3 task 8 con sider_2_1.bmp: modale di ritaglio aperta, «Usa originale» → POST /maker/api/upload con file sider_2_1.png, image/png, magic \x89PNG, 5,4 MB (upload intercettato, task non modificato); errore simulato visibile nel riquadro del task 8. MANCA: nulla.
Adriano removed the assegnata:daitarn label 2026-10-25 17:12:26 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Adriano/TieMeasureFlow#107