Fix rilevamento modifiche nella scheda: articoli e allegati
Uscendo dalla scheda il prompt di salvataggio non compariva e il pulsante "Salva" restava nascosto, perche' IsDirty non vedeva il lavoro fatto: - gli articoli scelti dalla griglia (OpenSelectArt) non marcavano mai la scheda come modificata; - ValueComparer confronta solo i campi del form, quindi ogni RecalcDirty() successivo azzerava il flag alzato con forceTrue da scanner e allegati. Non bastava confrontare Articoli: Clone() e' un MemberwiseClone, quindi _originalScheda condivide la stessa lista. Ora il confronto usa uno snapshot dei barcode preso all'apertura piu' un flag per gli allegati (che vivono in AttachedList fino al salvataggio), e RecalcDirty() perde forceTrue: non puo' piu' essere azzerato. Le chiamate su insert/remove degli articoli erano anche fatte prima della modifica della lista, quindi valutavano lo stato precedente. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -230,6 +230,11 @@
|
|||||||
private int _noteFieldKey;
|
private int _noteFieldKey;
|
||||||
private bool IsDirty { get; set; }
|
private bool IsDirty { get; set; }
|
||||||
private Scheda _originalScheda = null!;
|
private Scheda _originalScheda = null!;
|
||||||
|
// Clone() e' un MemberwiseClone, quindi _originalScheda condivide la stessa lista
|
||||||
|
// Articoli: per accorgerci degli articoli aggiunti/rimossi serve uno snapshot a parte.
|
||||||
|
private List<string> _originalBarcodes = [];
|
||||||
|
// Gli allegati vivono in AttachedList finche' non si salva: li tracciamo con un flag.
|
||||||
|
private bool _attachmentsDirty;
|
||||||
private List<AttachedDto>? AttachedList { get; set; }
|
private List<AttachedDto>? AttachedList { get; set; }
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
@@ -240,6 +245,7 @@
|
|||||||
OnScannerService.OnErrorScan += OnErrorScan;
|
OnScannerService.OnErrorScan += OnErrorScan;
|
||||||
|
|
||||||
_originalScheda = Scheda.Clone();
|
_originalScheda = Scheda.Clone();
|
||||||
|
_originalBarcodes = Scheda.Articoli.ConvertAll(x => x.Barcode);
|
||||||
Snackbar.Configuration.PositionClass = Defaults.Classes.Position.TopCenter;
|
Snackbar.Configuration.PositionClass = Defaults.Classes.Position.TopCenter;
|
||||||
|
|
||||||
LoadAttached();
|
LoadAttached();
|
||||||
@@ -456,14 +462,29 @@
|
|||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecalcDirty(bool forceTrue = false)
|
private void RecalcDirty()
|
||||||
{
|
{
|
||||||
IsDirty = forceTrue || !ValueComparer.AreEqual(Scheda, _originalScheda);
|
IsDirty = _attachmentsDirty
|
||||||
|
|| !ValueComparer.AreEqual(Scheda, _originalScheda)
|
||||||
|
|| !BarcodesUnchanged();
|
||||||
|
|
||||||
if (IsDirty) LabelSave = !IsNew ? "Aggiorna" : "Salva";
|
if (IsDirty) LabelSave = !IsNew ? "Aggiorna" : "Salva";
|
||||||
else LabelSave = null;
|
else LabelSave = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool BarcodesUnchanged()
|
||||||
|
{
|
||||||
|
if (Scheda.Articoli.Count != _originalBarcodes.Count) return false;
|
||||||
|
|
||||||
|
for (var i = 0; i < _originalBarcodes.Count; i++)
|
||||||
|
{
|
||||||
|
if (!Scheda.Articoli[i].Barcode.Equals(_originalBarcodes[i], StringComparison.Ordinal))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static class ValueComparer
|
private static class ValueComparer
|
||||||
{
|
{
|
||||||
public static bool AreEqual(Scheda? a, Scheda? b)
|
public static bool AreEqual(Scheda? a, Scheda? b)
|
||||||
@@ -526,7 +547,8 @@
|
|||||||
|
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
|
|
||||||
RecalcDirty(true);
|
_attachmentsDirty = true;
|
||||||
|
RecalcDirty();
|
||||||
|
|
||||||
// Processa in background e aggiorna UI man mano (o a blocchi)
|
// Processa in background e aggiorna UI man mano (o a blocchi)
|
||||||
_ = Task.Run(async () =>
|
_ = Task.Run(async () =>
|
||||||
@@ -618,7 +640,11 @@
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(() =>
|
||||||
|
{
|
||||||
|
RecalcDirty();
|
||||||
|
StateHasChanged();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -631,7 +657,8 @@
|
|||||||
AttachedList[index].ToRemove = true;
|
AttachedList[index].ToRemove = true;
|
||||||
|
|
||||||
AttachedList.RemoveAt(index);
|
AttachedList.RemoveAt(index);
|
||||||
RecalcDirty(true);
|
_attachmentsDirty = true;
|
||||||
|
RecalcDirty();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -701,14 +728,13 @@
|
|||||||
|
|
||||||
if (art != null)
|
if (art != null)
|
||||||
{
|
{
|
||||||
RecalcDirty(true);
|
|
||||||
|
|
||||||
Scheda.Articoli.Insert(0, new SchedaArticolo
|
Scheda.Articoli.Insert(0, new SchedaArticolo
|
||||||
{
|
{
|
||||||
Barcode = art.Barcode,
|
Barcode = art.Barcode,
|
||||||
Descrizione = art.Descrizione
|
Descrizione = art.Descrizione
|
||||||
});
|
});
|
||||||
|
|
||||||
|
RecalcDirty();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -748,8 +774,8 @@
|
|||||||
var index = Scheda.Articoli.FindIndex(x => x.Barcode.Equals(barcode));
|
var index = Scheda.Articoli.FindIndex(x => x.Barcode.Equals(barcode));
|
||||||
if (index < 0) return;
|
if (index < 0) return;
|
||||||
|
|
||||||
RecalcDirty(true);
|
|
||||||
Scheda.Articoli.RemoveAt(index);
|
Scheda.Articoli.RemoveAt(index);
|
||||||
|
RecalcDirty();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user