Removed dialogs for editing equipment and points, and their related resources
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user