_fitCanvasToImage() prima scalava solo canvas e sfondo: gli oggetti già
piazzati restavano alle vecchie coordinate pixel, e un salvataggio subito
dopo scriveva il nuovo imageScale accanto a posizioni mai spostate -
markers/frecce/aree finivano fuori posto anche nel viewer dell'operatore.
Ora, quando la scala cambia (f = newScale/oldScale, conservata in
this._currentScale), ogni oggetto viene ricalcolato coerentemente con
getAnnotationsJson/loadAnnotationsJson (il riferimento):
- left/top sempre *= f
- area (fabric.Rect): width/height *= f, non scaleX/scaleY - è quello che
getAnnotationsJson legge e loadAnnotationsJson ricostruisce
- text (IText): fontSize *= f, stesso motivo
- marker/arrow (Group): scaleX/scaleY *= f, il loro width/height non viene
mai riletto al caricamento
- arrow: arrowX1/Y1/X2/Y2 *= f, sono nello stesso spazio di left/top
(li aggiorna anche object:modified con un delta) e finiscono nel JSON
Aggiunta guardia beforeunload quando isDirty (annotazioni non salvate).
Test in tests/js/test_annotation_editor_resize.js (node, senza Fabric.js
reale: richiede jsdom non installato e il progetto non ha npm deps -
canvas stand-in minimale che copre solo la superficie usata da
_fitCanvasToImage). annotation-viewer.js non toccato.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Stessa regola del backend (neutralise_csv_cell): un valore che, tolti gli
spazi iniziali, comincia con =, +, -, @, TAB o CR riceve un apice davanti
prima di finire in cella - Excel/LibreOffice lo trattano come testo invece
che come formula. Solo per campi testuali (lot/seriale/descrizione):
formatNumber, usato per le colonne numeriche, non passa da qui, quindi un
valore negativo resta un numero. Aggiunto anche il quoting per \r, che
prima passava non quotato.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
buildMeasurementCSV leggeva m.subtask_name/unit/nominal/tolerance_plus/
tolerance_minus/operator_name: nessuno di questi campi esiste su
MeasurementResponse. I dati reali stanno annidati in m.subtask (description,
unit, nominal, utl, ltl - misurati.py:task_complete() li allega lato server).
tolleranza + = utl-nominal, tolleranza - = nominal-ltl, solo quando entrambi
i lati sono presenti (nessun NaN su tolleranza a un lato solo). Unità dalla
quota, "mm" solo se assente. Operatore: measured_by (id), l'unico campo
reale - non esiste un nome operatore da nessuna parte in questi dati.
Test node in tests/js/test_csv_export.js (stesso pattern di test_numpad.js).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
toggleSign() usciva subito a display vuoto: il segno del calibro, che arriva
prima delle cifre, veniva scartato. Ora '-'/'+' impostano il segno in modo
esplicito (non toggle) quando arrivano da tastiera/HID; toggleSign() (bottone
manuale +/-) funziona anche a vuoto.
_trackBurst riconosce l'inizio di una raffica solo dal secondo carattere:
prima ripuliva il display in ritardo, concatenando cifre digitate a mano.
Ora la raffica ripulisce il display fino al proprio inizio quando la pausa
prima di essa è > 300ms. Parte intera oltre 6 cifre: rifiutata con evento
numpad-error invece di essere troncata in silenzio.
Test node in tests/js/test_numpad.js, lanciato da pytest
(tests/test_numpad_js.py, skip se node manca).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>