Removed dialogs for editing equipment and points, and their related resources

This commit is contained in:
retr0volkov
2025-07-30 09:08:22 +03:00 Unverified
parent edae732fac
commit 08eaa30209
77 changed files with 1498 additions and 1543 deletions
+158 -56
View File
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
@@ -21,14 +21,19 @@ public partial class MainWindowViewModel : ViewModelBase
{
public ObservableCollection<PointViewModel> Points { get; set; }
[ObservableProperty]
private object? _selectedItem;
[ObservableProperty]
private ViewModelBase? _selectedItemViewModel;
[RelayCommand]
private async Task AddPoint()
{
var point = await WeakReferenceMessenger.Default.Send(new NewPointMessage());
if (point == null) return;
IsLoading = true;
var point = new PointViewModel(new Point {Name = "Новый объект", Description = "Описание объекта"});
_context.Point.Add(point.GetPoint());
await _context.SaveChangesAsync();
@@ -37,49 +42,16 @@ public partial class MainWindowViewModel : ViewModelBase
IsLoading = false;
}
[RelayCommand]
private async Task EditPoint(PointViewModel point)
{
var p = await WeakReferenceMessenger.Default.Send(new EditPointMessage(point));
if (p == null) return;
IsLoading = true;
_context.Update(p.GetPoint());
await _context.SaveChangesAsync();
var index = Points.IndexOf(point);
if (index != -1)
Points[index] = p;
IsLoading = false;
}
[RelayCommand]
private async Task RemovePoint(PointViewModel point)
{
IsLoading = true;
var pointInDb = await _context.Point.FindAsync(point.GetPoint().Id);
if (pointInDb == null) return;
_context.Remove(pointInDb);
await _context.SaveChangesAsync();
Points.Remove(point);
IsLoading = false;
}
[RelayCommand]
private async Task ImportPoint(Window w)
{
Directory.CreateDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "GazpromApp"));
var files = await w.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
AllowMultiple = true,
SuggestedStartLocation =
await w.StorageProvider.TryGetFolderFromPathAsync(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments))
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "GazpromApp"))
});
if (files.Count < 1) return;
@@ -92,6 +64,7 @@ public partial class MainWindowViewModel : ViewModelBase
var decoded = HttpUtility.UrlDecode(url);
var point = DataSerialization.LoadPoint(decoded);
point?.SetPropertyParents();
point?.SetEquipmentParents();
if (point == null) continue;
_context.Point.Add(point);
@@ -108,33 +81,81 @@ public partial class MainWindowViewModel : ViewModelBase
[RelayCommand]
private async Task ExportPoint(Window w)
{
Directory.CreateDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "GazpromApp"));
var folder = await w.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{
AllowMultiple = false,
SuggestedStartLocation =
await w.StorageProvider.TryGetFolderFromPathAsync(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments))
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "GazpromApp"))
});
if (folder.Count != 1) return;
foreach (var point in Points)
DataSerialization.SavePoint(point.GetPoint(), Path.Combine(HttpUtility.UrlDecode(folder[0].Path.AbsolutePath), point.Name + ".json") );
}
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(SyncDbCommand))]
private bool _canSync = false;
private bool CanSyncDb() => CanSync;
[RelayCommand(CanExecute = nameof(CanSyncDb))]
private async Task SyncDb()
{
IsLoading = true;
foreach (var point in _pointsToUpdate)
{
_context.Update(point.GetPoint());
var index = Points.IndexOf(point);
if (index != -1)
Points[index] = point;
}
await _context.SaveChangesAsync();
foreach (var point in _pointsToDelete)
{
var pointInDb = await _context.Point.FindAsync(point.GetPoint().Id);
if (pointInDb == null) continue;
_context.Remove(pointInDb);
Points.Remove(point);
}
await _context.SaveChangesAsync();
_pointsToUpdate.Clear();
_pointsToDelete.Clear();
IsLoading = false;
CanSync = false;
}
// Visual and other properties
[ObservableProperty] private bool _isLoading = true;
private readonly AppDbContext _context;
private async Task LoadChildrenForProperties(List<Property> properties)
private async Task LoadChildrenForProperties(List<Property> properties, HashSet<Guid> loadedIds)
{
if (properties.Count == 0)
return;
var parentIds = properties.Select(p => p.Id).ToList();
var parentIds = properties.Select(p => p.Id)
.Where(id => !loadedIds.Contains(id))
.ToList();
if (parentIds.Count == 0)
return;
parentIds.ForEach(id => loadedIds.Add(id));
var children = await _context.Property
.Where(p => p.ParentPropertyId.HasValue && parentIds.Contains(p.ParentPropertyId.Value))
.AsNoTracking()
.OrderBy(p => p.CreationDate)
.ToListAsync();
if (children.Count != 0)
@@ -142,36 +163,85 @@ public partial class MainWindowViewModel : ViewModelBase
var childrenLookup = children.ToLookup(child => child.ParentPropertyId);
foreach (var parent in properties.Where(parent => childrenLookup.Contains(parent.Id)))
parent.Properties.AddRange(childrenLookup[parent.Id]);
{
parent.Properties.Clear();
parent.Properties.AddRange(childrenLookup[parent.Id]);
}
// ReSharper disable once TailRecursiveCall
await LoadChildrenForProperties(children);
await LoadChildrenForProperties(children, loadedIds);
}
}
private async Task LoadChildrenForEquipments(List<Equipment> equipments, HashSet<Guid> loadedIds)
{
if (equipments.Count == 0)
return;
var parentIds = equipments.Select(e => e.Id)
.Where(id => !loadedIds.Contains(id))
.ToList();
if (parentIds.Count == 0)
return;
parentIds.ForEach(id => loadedIds.Add(id));
var children = await _context.Equipment
.Where(e => e.ParentEquipmentId.HasValue && parentIds.Contains(e.ParentEquipmentId.Value))
.OrderBy(e => e.CreationDate)
.ToListAsync();
if (children.Count != 0)
{
var childrenLookup = children.ToLookup(child => child.ParentEquipmentId);
foreach (var parent in equipments.Where(parent => childrenLookup.Contains(parent.Id)))
{
parent.Equipments.Clear();
parent.Equipments.AddRange(childrenLookup[parent.Id]);
}
await LoadChildrenForEquipments(children, loadedIds);
}
}
private async Task LoadDataAsync()
{
IsLoading = true;
// ReSharper disable once EntityFramework.NPlusOne.IncompleteDataQuery
var pointsFromDb = await _context.Point
.Include(p => p.Images)
.OrderBy(p => p.CreationDate)
.Include(p => p.Images
.OrderBy(i => i.CreationDate))
.Include(p => p.Equipment
.OrderBy(e => e.CreationDate))
.ThenInclude(e => e.Properties
.OrderBy(p => p.CreationDate))
.Include(p => p.Equipment)
.ThenInclude(e => e.Properties)
.ThenInclude(e => e.Images
.OrderBy(i => i.CreationDate))
.Include(p => p.Equipment)
.ThenInclude(e => e.Images)
.Include(p => p.Equipment)
.ThenInclude(e => e.Inspections)
.Include(p => p.Properties)
.AsNoTracking()
.ThenInclude(e => e.Inspections
.OrderBy(i => i.CreationDate))
.Include(p => p.Properties
.OrderBy(p => p.CreationDate))
.ToListAsync();
var topLevelProperties = pointsFromDb.SelectMany(p => p.Properties)
.Concat(pointsFromDb.SelectMany(p => p.Equipment).SelectMany(e => e.Properties))
.ToList();
if (topLevelProperties.Count != 0)
await LoadChildrenForProperties(topLevelProperties);
var topLevelEquipments = pointsFromDb.SelectMany(p => p.Equipment)
.ToList();
if (topLevelProperties.Count != 0)
await LoadChildrenForProperties(topLevelProperties, []);
if (topLevelEquipments.Count != 0)
await LoadChildrenForEquipments(topLevelEquipments, []);
Points.Clear();
foreach (var point in pointsFromDb)
Points.Add(new PointViewModel(point));
@@ -179,16 +249,48 @@ public partial class MainWindowViewModel : ViewModelBase
IsLoading = false;
}
private readonly ObservableCollection<PointViewModel> _pointsToUpdate = [];
private readonly ObservableCollection<PointViewModel> _pointsToDelete = [];
private void EditPoint(object sender, EditPointMessage msg)
{
if (!_pointsToUpdate.Contains(msg.Point))
_pointsToUpdate.Add(msg.Point);
CanSync = true;
}
private void RemovePoint(object sender, RemovePointMessage msg)
{
if (!_pointsToDelete.Contains(msg.Point))
_pointsToDelete.Add(msg.Point);
Points.Remove(msg.Point);
CanSync = true;
}
private void HandleSelectionChanged(object sender, SelectionChangedMessage msg)
{
SelectedItemViewModel = msg.ViewModel switch
{
PointViewModel pointViewModel => new EditPointViewModel(pointViewModel),
EquipmentViewModel equipmentViewModel => new EditEquipmentViewModel(equipmentViewModel),
_ => msg.ViewModel
};
}
public MainWindowViewModel(AppDbContext context)
{
Points = [];
_context = context;
_ = LoadDataAsync();
WeakReferenceMessenger.Default.Register<EditPointMessage>(this, EditPoint);
WeakReferenceMessenger.Default.Register<RemovePointMessage>(this, RemovePoint);
WeakReferenceMessenger.Default.Register<SelectionChangedMessage>(this, HandleSelectionChanged);
}
public MainWindowViewModel()
{
Points = [new PointViewModel(new Point()) { Name = "Name test", Description = "Description test" }];
Points = [new PointViewModel(new Point()) { Name = "Новый объект", Description = "Описание объекта" }];
_context = new AppDbContext();
IsLoading = false;
}