+ x-data="dxfRecipeWizard(task.id, () => csrfToken(), {{ {'requestFailed': _('Richiesta non riuscita'), 'saved': _('Ricetta salvata'), 'dxfEntities': _('entità'), 'imageField': _('campo')}|tojson_attr }})">
@@ -710,6 +710,15 @@
diff --git a/src/frontend/flask_app/tests/js/test_dxf_preview.js b/src/frontend/flask_app/tests/js/test_dxf_preview.js
index af123a4..8782586 100644
--- a/src/frontend/flask_app/tests/js/test_dxf_preview.js
+++ b/src/frontend/flask_app/tests/js/test_dxf_preview.js
@@ -85,6 +85,25 @@ const PREVIEW = {
await w2.loadDxfPreview();
check('errore col detail', w2.dxfPreviewError === 'DXF illeggibile: x' && w2.dxfPreview === null, w2.dxfPreviewError);
+ // #102: anteprima dell'immagine
+ const wi = dxfRecipeWizard(1, () => 'tok', { imageField: 'campo' });
+ check('#102 senza immagine: summary vuoto', wi.imagePreviewSummary === '');
+ global.URL.createObjectURL = () => 'blob:x';
+ global.URL.revokeObjectURL = () => {};
+ wi._setImage({ name: 'a.bmp' });
+ check('#102 _setImage imposta URL e nome', wi.imagePreviewUrl === 'blob:x' && wi.imageName === 'a.bmp');
+ wi.onImagePreviewLoad({ naturalWidth: 2000, naturalHeight: 1000 });
+ check('#102 senza scala: solo pixel', /2[. ]?000 × 1[. ]?000 px$/.test(wi.imagePreviewSummary), wi.imagePreviewSummary);
+ wi.mmPx = '0,01';
+ check('#102 con mm/px a mano: campo in mm', /px · campo ≈ 20,00 × 10,00 mm$/.test(wi.imagePreviewSummary), wi.imagePreviewSummary);
+ wi.mmPx = ''; wi.calState = 'calibrated'; wi.calPxMm = 100;
+ check('#102 con calibrazione stazione: campo in mm', /campo ≈ 20,00 × 10,00 mm$/.test(wi.imagePreviewSummary), wi.imagePreviewSummary);
+ wi.onImagePreviewError();
+ check('#102 errore
![]()
: imageBroken e file ancora valido', wi.imageBroken === true && wi.imageFile && wi.imagePx === null);
+ wi._setImage(null);
+ check('#102 _setImage(null) azzera', wi.imagePreviewUrl === '' && wi.imageFile === null && wi.imageName === ''
+ && wi.imagePx === null && wi.imageBroken === false && wi.imagePreviewSummary === '');
+
if (failures) { console.log(failures + ' fallimenti'); process.exit(1); }
console.log('tutto ok');
})();
diff --git a/src/frontend/flask_app/tests/test_dxf_recipe_routes.py b/src/frontend/flask_app/tests/test_dxf_recipe_routes.py
index b510e3d..322de1a 100644
--- a/src/frontend/flask_app/tests/test_dxf_recipe_routes.py
+++ b/src/frontend/flask_app/tests/test_dxf_recipe_routes.py
@@ -280,4 +280,5 @@ class TestPages:
assert "@dxf-recipe-saved" in html
assert 'x-model="mmPx"' in html # #98: campo mm/px a mano
assert "dxfPreviewD()" in html and "view-box.camel" in html # #101: anteprima SVG del DXF
+ assert "imagePreviewUrl" in html and "imagePreviewSummary" in html # #102: anteprima immagine
assert "Pezzo scuro su fondo chiaro" in html or "Dark part on light" in html
diff --git a/src/frontend/flask_app/translations/en/LC_MESSAGES/messages.po b/src/frontend/flask_app/translations/en/LC_MESSAGES/messages.po
index 59d29b1..1798e9a 100644
--- a/src/frontend/flask_app/translations/en/LC_MESSAGES/messages.po
+++ b/src/frontend/flask_app/translations/en/LC_MESSAGES/messages.po
@@ -3499,3 +3499,11 @@ msgstr "Reading DXF…"
msgid "entità"
msgstr "entities"
+
+#: templates/maker/task_editor.html (#102)
+msgid "campo"
+msgstr "field"
+
+#: templates/maker/task_editor.html (#102)
+msgid "Anteprima non disponibile per questo formato"
+msgstr "Preview not available for this format"
diff --git a/src/frontend/flask_app/translations/it/LC_MESSAGES/messages.po b/src/frontend/flask_app/translations/it/LC_MESSAGES/messages.po
index 545d8c2..23be8ae 100644
--- a/src/frontend/flask_app/translations/it/LC_MESSAGES/messages.po
+++ b/src/frontend/flask_app/translations/it/LC_MESSAGES/messages.po
@@ -3483,3 +3483,11 @@ msgstr "Lettura DXF…"
msgid "entità"
msgstr "entità"
+
+#: templates/maker/task_editor.html (#102)
+msgid "campo"
+msgstr "campo"
+
+#: templates/maker/task_editor.html (#102)
+msgid "Anteprima non disponibile per questo formato"
+msgstr "Anteprima non disponibile per questo formato"