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
+7
View File
@@ -5,13 +5,20 @@
<map> <map>
<entry key="App.axaml" value="GazpromApp.csproj" /> <entry key="App.axaml" value="GazpromApp.csproj" />
<entry key="Views/EditEquipmentDialog.axaml" value="GazpromApp.csproj" /> <entry key="Views/EditEquipmentDialog.axaml" value="GazpromApp.csproj" />
<entry key="Views/EditEquipmentView.axaml" value="GazpromApp.csproj" />
<entry key="Views/EditPointDialog.axaml" value="GazpromApp.csproj" /> <entry key="Views/EditPointDialog.axaml" value="GazpromApp.csproj" />
<entry key="Views/EditPointView.axaml" value="GazpromApp.csproj" />
<entry key="Views/EquipmentView.axaml" value="GazpromApp.csproj" />
<entry key="Views/ErrorView.axaml" value="GazpromApp.csproj" /> <entry key="Views/ErrorView.axaml" value="GazpromApp.csproj" />
<entry key="Views/ImageView.axaml" value="GazpromApp.csproj" /> <entry key="Views/ImageView.axaml" value="GazpromApp.csproj" />
<entry key="Views/InspectionView.axaml" value="GazpromApp.csproj" />
<entry key="Views/MainWindow.axaml" value="GazpromApp.csproj" /> <entry key="Views/MainWindow.axaml" value="GazpromApp.csproj" />
<entry key="Views/NewEquipmentDialog.axaml" value="GazpromApp.csproj" /> <entry key="Views/NewEquipmentDialog.axaml" value="GazpromApp.csproj" />
<entry key="Views/NewPointDialog.axaml" value="GazpromApp.csproj" /> <entry key="Views/NewPointDialog.axaml" value="GazpromApp.csproj" />
<entry key="Views/NewPointView.axaml" value="GazpromApp.csproj" /> <entry key="Views/NewPointView.axaml" value="GazpromApp.csproj" />
<entry key="Views/PointView.axaml" value="GazpromApp.csproj" />
<entry key="Views/PropertyView.axaml" value="GazpromApp.csproj" />
<entry key="Views/SaveChangesView.axaml" value="GazpromApp.csproj" />
</map> </map>
</option> </option>
</component> </component>
+7
View File
@@ -9,5 +9,12 @@
<jdbc-url>jdbc:sqlite:identifier.sqlite</jdbc-url> <jdbc-url>jdbc:sqlite:identifier.sqlite</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir> <working-dir>$ProjectFileDir$</working-dir>
</data-source> </data-source>
<data-source source="LOCAL" name="GazpromApp.db" uuid="594ee7a3-9498-4753-a25d-1e2967c88d5c">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:$USER_HOME$/AppData/Local/GazpromApp/GazpromApp.db</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component> </component>
</project> </project>
+4 -1
View File
@@ -2,6 +2,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="GazpromApp.App" x:Class="GazpromApp.App"
xmlns:local="using:GazpromApp" xmlns:local="using:GazpromApp"
xmlns:icons="using:Material.Icons.Avalonia"
xmlns:material="using:Material.Styles.Themes"
RequestedThemeVariant="Default"> RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. --> <!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
@@ -10,6 +12,7 @@
</Application.DataTemplates> </Application.DataTemplates>
<Application.Styles> <Application.Styles>
<FluentTheme /> <material:MaterialTheme BaseTheme="Inherit" PrimaryColor="LightBlue" SecondaryColor="Amber"/>
<icons:MaterialIconStyles/>
</Application.Styles> </Application.Styles>
</Application> </Application>
+2
View File
@@ -26,6 +26,8 @@
</PackageReference> </PackageReference>
<PackageReference Include="AvaloniaUI.DiagnosticsSupport" Version="2.0.4" /> <PackageReference Include="AvaloniaUI.DiagnosticsSupport" Version="2.0.4" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" /> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
<PackageReference Include="Material.Avalonia" Version="3.12.0" />
<PackageReference Include="Material.Icons.Avalonia" Version="2.4.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.6"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.6">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
+2 -2
View File
@@ -1,9 +1,9 @@
using CommunityToolkit.Mvvm.Messaging.Messages; using System;
using GazpromApp.ViewModels; using GazpromApp.ViewModels;
namespace GazpromApp.Messages; namespace GazpromApp.Messages;
public class EditEquipmentMessage(EquipmentViewModel equipment) : AsyncRequestMessage<EquipmentViewModel?> public class EditEquipmentMessage(EquipmentViewModel equipment)
{ {
public EquipmentViewModel Equipment { get; } = equipment; public EquipmentViewModel Equipment { get; } = equipment;
} }
+3 -3
View File
@@ -1,9 +1,9 @@
using CommunityToolkit.Mvvm.Messaging.Messages; using GazpromApp.Models;
using GazpromApp.ViewModels; using GazpromApp.ViewModels;
namespace GazpromApp.Messages; namespace GazpromApp.Messages;
public class EditPointMessage(PointViewModel pointViewModel) : AsyncRequestMessage<PointViewModel?> public class EditPointMessage(PointViewModel point)
{ {
public PointViewModel Point { get; } = pointViewModel; public PointViewModel Point { get; } = point;
} }
-8
View File
@@ -1,8 +0,0 @@
using GazpromApp.ViewModels;
namespace GazpromApp.Messages;
public class NewEquipmentDone(EquipmentViewModel equipment)
{
public EquipmentViewModel Equipment { get; } = equipment;
}
-6
View File
@@ -1,6 +0,0 @@
using CommunityToolkit.Mvvm.Messaging.Messages;
using GazpromApp.ViewModels;
namespace GazpromApp.Messages;
public class NewEquipmentMessage : AsyncRequestMessage<EquipmentViewModel?>;
-8
View File
@@ -1,8 +0,0 @@
using GazpromApp.ViewModels;
namespace GazpromApp.Messages;
public class NewPointDone(PointViewModel pointViewModel)
{
public PointViewModel Point { get; } = pointViewModel;
}
-6
View File
@@ -1,6 +0,0 @@
using CommunityToolkit.Mvvm.Messaging.Messages;
using GazpromApp.ViewModels;
namespace GazpromApp.Messages;
public class NewPointMessage : AsyncRequestMessage<PointViewModel?>;
@@ -2,7 +2,7 @@
namespace GazpromApp.Messages; namespace GazpromApp.Messages;
public class EditEquipmentDone(EquipmentViewModel equipment) public class RemoveEquipmentMessage(EquipmentViewModel equipment)
{ {
public EquipmentViewModel Equipment { get; } = equipment; public EquipmentViewModel Equipment { get; } = equipment;
} }
+8
View File
@@ -0,0 +1,8 @@
using GazpromApp.ViewModels;
namespace GazpromApp.Messages;
public class RemoveInspectionMessage(InspectionViewModel inspection)
{
public InspectionViewModel Inspection { get; } = inspection;
}
@@ -2,7 +2,7 @@
namespace GazpromApp.Messages; namespace GazpromApp.Messages;
public class EditPointDone(PointViewModel pointViewModel) public class RemovePointMessage(PointViewModel pointViewModel)
{ {
public PointViewModel Point { get; } = pointViewModel; public PointViewModel Point { get; } = pointViewModel;
} }
+8
View File
@@ -0,0 +1,8 @@
using GazpromApp.ViewModels;
namespace GazpromApp.Messages;
public class RemovePropertyMessage(PropertyViewModel property)
{
public PropertyViewModel Property { get; } = property;
}
+11
View File
@@ -0,0 +1,11 @@
using System.Collections.Generic;
using Avalonia.Platform.Storage;
using CommunityToolkit.Mvvm.Messaging.Messages;
using GazpromApp.ViewModels;
namespace GazpromApp.Messages;
public class RequestImageMessage(ViewModelBase viewModel) : AsyncRequestMessage<IReadOnlyList<IStorageFile>>
{
private ViewModelBase Caller { get; set; } = viewModel;
}
+9
View File
@@ -0,0 +1,9 @@
using CommunityToolkit.Mvvm.Messaging.Messages;
using GazpromApp.ViewModels;
namespace GazpromApp.Messages;
public class SaveChangesMessage(SaveChangesViewModel saveChanges) : AsyncRequestMessage<SaveChangesViewModel?>
{
public SaveChangesViewModel SaveChanges { get; } = saveChanges;
}
+7
View File
@@ -0,0 +1,7 @@
namespace GazpromApp.Messages;
public class SaveChangesResult(bool save, bool cancel)
{
public bool Save { get; } = save;
public bool Cancel { get; } = cancel;
}
+8
View File
@@ -0,0 +1,8 @@
using GazpromApp.ViewModels;
namespace GazpromApp.Messages;
public class SelectionChangedMessage(ViewModelBase viewModel)
{
public ViewModelBase ViewModel { get; } = viewModel;
}
+22 -7
View File
@@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@@ -7,28 +8,42 @@ namespace GazpromApp.Models;
public class Equipment public class Equipment
{ {
public Equipment()
{
LocalId = Id == Guid.Empty ? Guid.NewGuid() : Id;
}
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[JsonIgnore] [JsonIgnore]
public int Id { get; set; } public Guid Id { get; set; }
[JsonIgnore]
[NotMapped]
public Guid LocalId { get; set; }
[Required] [Required]
public string? Name { get; set; } = string.Empty; public string? Name { get; set; } = string.Empty;
public string? Description { get; set; } = string.Empty; public string? Description { get; set; } = string.Empty;
public DateTime CreationDate { get; set; }
// Foreign keys // Foreign keys
[Required]
[JsonIgnore] [JsonIgnore]
public int PointId { get; set; } public Guid? PointId { get; set; }
[JsonIgnore] [JsonIgnore]
public List<int> ImageIds { get; set; } = []; public List<Guid> ImageIds { get; set; } = [];
[JsonIgnore] [JsonIgnore]
public List<int> InspectionIds { get; set; } = []; public List<Guid> InspectionIds { get; set; } = [];
[JsonIgnore]
public List<Guid> EquipmentIds { get; set; } = [];
public Guid? ParentEquipmentId { get; set; }
// Navigation Properties // Navigation Properties
public List<Image> Images { get; set; } = []; public List<Image> Images { get; set; } = [];
[JsonIgnore] [JsonIgnore]
public Point Point { get; set; } = null!; public Point? Point { get; set; } = null!;
public List<Property> Properties { get; set; } = []; public List<Property> Properties { get; set; } = [];
public List<Inspection> Inspections { get; set; } = []; public List<Inspection> Inspections { get; set; } = [];
public List<Equipment> Equipments { get; set; } = [];
public Equipment? ParentEquipment { get; set; }
} }
+6 -4
View File
@@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations; using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@@ -9,16 +10,17 @@ public class Image
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[JsonIgnore] [JsonIgnore]
public int Id { get; set; } public Guid Id { get; set; }
[Required] [Required]
public byte[] Bytes { get; set; } = []; public byte[] Bytes { get; set; } = [];
public DateTime CreationDate { get; set; }
// Foreign keys // Foreign keys
[JsonIgnore] [JsonIgnore]
public int? PointId { get; set; } public Guid? PointId { get; set; }
[JsonIgnore] [JsonIgnore]
public int? EquipmentId { get; set; } public Guid? EquipmentId { get; set; }
// Navigation Properties // Navigation Properties
[JsonIgnore] [JsonIgnore]
+3 -2
View File
@@ -10,10 +10,11 @@ public class Inspection
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[JsonIgnore] [JsonIgnore]
public int Id { get; set; } public Guid Id { get; set; }
[Required] [Required]
public string Name { get; set; } = string.Empty; public string Name { get; set; } = string.Empty;
public DateTime CreationDate { get; set; }
[Required] [Required]
public DateTimeOffset InspectionDate { get; set; } public DateTimeOffset InspectionDate { get; set; }
[Required] [Required]
@@ -23,7 +24,7 @@ public class Inspection
// Foreign keys // Foreign keys
[JsonIgnore] [JsonIgnore]
public int EquipmentId { get; set; } public Guid EquipmentId { get; set; }
// Navigation Properties // Navigation Properties
[JsonIgnore] [JsonIgnore]
+4 -2
View File
@@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@@ -10,11 +11,12 @@ public class Point
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[JsonIgnore] [JsonIgnore]
public int Id { get; set; } public Guid Id { get; set; } = Guid.NewGuid();
[Required] [Required]
public string? Name { get; set; } = string.Empty; public string? Name { get; set; } = string.Empty;
public string? Description { get; set; } = string.Empty; public string? Description { get; set; } = string.Empty;
public DateTime CreationDate { get; set; }
public double Latitude { get; set; } public double Latitude { get; set; }
public double Longitude { get; set; } public double Longitude { get; set; }
// Navigation Properties // Navigation Properties
+7 -5
View File
@@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@@ -10,27 +11,28 @@ public class Property
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[JsonIgnore] [JsonIgnore]
public int Id { get; set; } public Guid Id { get; set; }
[Required] [Required]
public string Name { get; set; } = string.Empty; public string Name { get; set; } = string.Empty;
public string Value { get; set; } = string.Empty; public string Value { get; set; } = string.Empty;
public DateTime CreationDate { get; set; }
// For self-referencing hierarchy (Property of a Property) // For self-referencing hierarchy (Property of a Property)
[JsonIgnore] [JsonIgnore]
public int? ParentPropertyId { get; set; } public Guid? ParentPropertyId { get; set; }
[JsonIgnore] [JsonIgnore]
public Property? Parent { get; set; } public Property? Parent { get; set; }
// For a Property of a Point // For a Property of a Point
[JsonIgnore] [JsonIgnore]
public int? PointId { get; set; } public Guid? PointId { get; set; }
[JsonIgnore] [JsonIgnore]
public Point? Point { get; set; } public Point? Point { get; set; }
// For a Property of an Equipment // For a Property of an Equipment
[JsonIgnore] [JsonIgnore]
public int? EquipmentId { get; set; } public Guid? EquipmentId { get; set; }
[JsonIgnore] [JsonIgnore]
public Equipment? Equipment { get; set; } public Equipment? Equipment { get; set; }
+13 -50
View File
@@ -1,4 +1,5 @@
using System; using System;
using System.IO;
using GazpromApp.Models; using GazpromApp.Models;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@@ -17,13 +18,15 @@ public class AppDbContext : DbContext
public AppDbContext() public AppDbContext()
{ {
var path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); var path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
DbPath = System.IO.Path.Combine(path, "GazpromApp.db"); Directory.CreateDirectory(Path.Combine(path, "GazpromApp"));
DbPath = Path.Combine(Path.Combine(path, "GazpromApp"), "GazpromApp.db");
} }
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{ {
var path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); var path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
DbPath = System.IO.Path.Combine(path, "GazpromApp.db"); Directory.CreateDirectory(Path.Combine(path, "GazpromApp"));
DbPath = Path.Combine(Path.Combine(path, "GazpromApp"), "GazpromApp.db");
} }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
@@ -41,6 +44,7 @@ public class AppDbContext : DbContext
.HasMany(p => p.Equipment) .HasMany(p => p.Equipment)
.WithOne(e => e.Point) .WithOne(e => e.Point)
.HasForeignKey(e => e.PointId) .HasForeignKey(e => e.PointId)
.IsRequired(false)
.OnDelete(DeleteBehavior.Cascade); // Deleting a Point deletes its Equipment. .OnDelete(DeleteBehavior.Cascade); // Deleting a Point deletes its Equipment.
modelBuilder.Entity<Point>() modelBuilder.Entity<Point>()
@@ -63,6 +67,13 @@ public class AppDbContext : DbContext
.HasForeignKey(i => i.EquipmentId) .HasForeignKey(i => i.EquipmentId)
.OnDelete(DeleteBehavior.Cascade); // Equipment has one Image. .OnDelete(DeleteBehavior.Cascade); // Equipment has one Image.
modelBuilder.Entity<Equipment>()
.HasMany(e => e.Equipments)
.WithOne(e => e.ParentEquipment)
.HasForeignKey(e => e.ParentEquipmentId)
.IsRequired(false)
.OnDelete(DeleteBehavior.Cascade); // Equipment has many Equipments.
// ==== PROPERTY RELATIONSHIPS ==== // ==== PROPERTY RELATIONSHIPS ====
// Property as a child of a Point // Property as a child of a Point
modelBuilder.Entity<Point>() modelBuilder.Entity<Point>()
@@ -87,53 +98,5 @@ public class AppDbContext : DbContext
.HasForeignKey(p => p.ParentPropertyId) .HasForeignKey(p => p.ParentPropertyId)
.IsRequired(false) .IsRequired(false)
.OnDelete(DeleteBehavior.Cascade); // Deleting a parent Property deletes its children. .OnDelete(DeleteBehavior.Cascade); // Deleting a parent Property deletes its children.
// modelBuilder.Entity<Point>()
// .Property(p => p.Id)
// .ValueGeneratedOnAdd();
// modelBuilder.Entity<Equipment>()
// .Property(e => e.Id)
// .ValueGeneratedOnAdd();
// modelBuilder.Entity<Image>()
// .Property(i => i.Id)
// .ValueGeneratedOnAdd();
// modelBuilder.Entity<Property>()
// .Property(p => p.Id)
// .ValueGeneratedOnAdd();
// modelBuilder.Entity<Inspection>()
// .Property(i => i.Id)
// .ValueGeneratedOnAdd();
//
// modelBuilder.Entity<Point>()
// .HasMany(p => p.Images)
// .WithMany(i => i.Points);
// modelBuilder.Entity<Point>()
// .HasMany(p => p.Equipment)
// .WithOne(e => e.Point)
// .HasForeignKey(e => e.PointId);
// modelBuilder.Entity<Point>()
// .HasMany(p => p.Properties)
// .WithOne(p => p.Point)
// .HasForeignKey(p => p.ParentId)
// .IsRequired(false);
//
// modelBuilder.Entity<Equipment>()
// .HasOne(e => e.Image)
// .WithMany(i => i.Equipment);
// modelBuilder.Entity<Equipment>()
// .HasMany(e => e.Properties)
// .WithOne(p => p.Equipment)
// .HasForeignKey(p => p.ParentId)
// .IsRequired(false);
// modelBuilder.Entity<Equipment>()
// .HasMany(e => e.Inspections)
// .WithOne(i => i.Equipment)
// .HasForeignKey(i => i.EquipmentId);
//
// modelBuilder.Entity<Property>()
// .HasMany(p => p.Properties)
// .WithOne(p => p.Parent)
// .HasForeignKey(p => p.ParentId)
// .IsRequired(false);
} }
} }
+53
View File
@@ -0,0 +1,53 @@
using System.Linq;
using GazpromApp.Models;
namespace GazpromApp.Utils;
public static class ParentsHelper
{
public static void SetPropertyParents(this Point point)
{
foreach (var prop in point.Properties)
{
SetPropertyParentsRecursively(prop);
}
foreach (var prop in point.Equipment.SelectMany(equipment => equipment.Properties))
{
SetPropertyParentsRecursively(prop);
}
}
private static void SetPropertyParentsRecursively(Property property)
{
foreach (var childProp in property.Properties)
{
childProp.Parent = property;
childProp.ParentPropertyId = property.Id;
SetPropertyParentsRecursively(childProp);
}
}
public static void SetEquipmentParents(this Point point)
{
foreach (var prop in point.Equipment)
{
SetEquipmentParentsRecursively(prop);
}
foreach (var prop in point.Equipment.SelectMany(equipment1 => equipment1.Equipments))
{
SetEquipmentParentsRecursively(prop);
}
}
private static void SetEquipmentParentsRecursively(Equipment equipment)
{
foreach (var childProp in equipment.Equipments)
{
childProp.ParentEquipment = equipment;
childProp.ParentEquipmentId = equipment.Id;
SetEquipmentParentsRecursively(childProp);
}
}
}
-30
View File
@@ -1,30 +0,0 @@
using GazpromApp.Models;
using System.Linq;
namespace GazpromApp.Utils;
public static class PropertyParentHelper
{
public static void SetPropertyParents(this Point point)
{
foreach (var prop in point.Properties)
{
SetParentsRecursively(prop);
}
foreach (var prop in point.Equipment.SelectMany(equipment => equipment.Properties))
{
SetParentsRecursively(prop);
}
}
private static void SetParentsRecursively(Property property)
{
foreach (var childProp in property.Properties)
{
childProp.Parent = property;
childProp.ParentPropertyId = property.Id;
SetParentsRecursively(childProp);
}
}
}
+56 -4
View File
@@ -1,7 +1,11 @@
using System; using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq; using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using GazpromApp.Messages;
using GazpromApp.Models; using GazpromApp.Models;
using GazpromApp.Utils; using GazpromApp.Utils;
@@ -9,6 +13,7 @@ namespace GazpromApp.ViewModels;
public partial class EquipmentViewModel : ViewModelBase public partial class EquipmentViewModel : ViewModelBase
{ {
public ViewModelBase? Parent { get; set; }
private Equipment Equipment { get; } private Equipment Equipment { get; }
[ObservableProperty] [ObservableProperty]
@@ -17,31 +22,72 @@ public partial class EquipmentViewModel : ViewModelBase
[ObservableProperty] [ObservableProperty]
private string? _description; private string? _description;
public ObservableCollection<ImageViewModel> Images { get; init; } = []; [ObservableProperty]
private DateTime _creationDate;
public ObservableCollection<PropertyViewModel> Properties { get; }
public ObservableCollection<InspectionViewModel> Inspections { get; } public ObservableCollection<ImageViewModel> Images { get; set; } = [];
public ObservableCollection<PropertyViewModel> Properties { get; set; }
public ObservableCollection<InspectionViewModel> Inspections { get; set; }
public ObservableCollection<EquipmentViewModel> Equipments { get; set; }
[ObservableProperty] [ObservableProperty]
private string _nearestInspection; private string _nearestInspection;
[RelayCommand]
private void AddEquipment()
{
Equipments.Add(new EquipmentViewModel{ Name = "Новое оборудование", Description = "Описание оборудования", Parent = this});
CallSavePoint(this);
}
[RelayCommand]
private void RemoveEquipment()
{
WeakReferenceMessenger.Default.Send(new RemoveEquipmentMessage(this));
}
private void RemoveEquipment(object sender, RemoveEquipmentMessage msg)
{
if (Equipments.Contains(msg.Equipment))
Equipments.Remove(msg.Equipment);
CallSavePoint(this);
}
private void CallSavePoint(EquipmentViewModel equipment)
{
var current = equipment;
while (current.Parent is EquipmentViewModel model)
current = model ?? throw new InvalidOperationException("Parent equipment not found in hierarchy");
if (current.Parent is PointViewModel pointViewModel)
WeakReferenceMessenger.Default.Send(new EditPointMessage(pointViewModel));
}
public EquipmentViewModel() public EquipmentViewModel()
{ {
Name = string.Empty; Name = string.Empty;
Description = string.Empty; Description = string.Empty;
CreationDate = DateTime.Now;
Properties = []; Properties = [];
Inspections = []; Inspections = [];
Equipments = [];
NearestInspection = "Нету инспекций"; NearestInspection = "Нету инспекций";
Equipment = new Equipment(); Equipment = new Equipment();
WeakReferenceMessenger.Default.Register<RemoveEquipmentMessage>(this, RemoveEquipment);
} }
public EquipmentViewModel(Equipment equipment) public EquipmentViewModel(Equipment equipment)
{ {
Name = equipment.Name; Name = equipment.Name;
Description = equipment.Description; Description = equipment.Description;
CreationDate = equipment.CreationDate;
Images = new ObservableCollection<ImageViewModel>(equipment.Images.Select(i => new ImageViewModel(i))); Images = new ObservableCollection<ImageViewModel>(equipment.Images.Select(i => new ImageViewModel(i)));
Properties = new ObservableCollection<PropertyViewModel>(equipment.Properties.Select(e => new PropertyViewModel(e))); Properties = new ObservableCollection<PropertyViewModel>(equipment.Properties.Select(e => new PropertyViewModel(e)));
Equipments = new ObservableCollection<EquipmentViewModel>(equipment.Equipments.Select(e => new EquipmentViewModel(e){Parent = this}));
var times = equipment.Inspections.Select(e => new InspectionViewModel(e)) var times = equipment.Inspections.Select(e => new InspectionViewModel(e))
.Select(e => e.GetNearestDates()) .Select(e => e.GetNearestDates())
@@ -59,14 +105,20 @@ public partial class EquipmentViewModel : ViewModelBase
if (Inspections.Count == 0) NearestInspection = "Нету инспекций"; if (Inspections.Count == 0) NearestInspection = "Нету инспекций";
Equipment = equipment; Equipment = equipment;
WeakReferenceMessenger.Default.Register<RemoveEquipmentMessage>(this, RemoveEquipment);
} }
public Equipment GetEquipment() public Equipment GetEquipment()
{ {
Equipment.Name = Name; Equipment.Name = Name;
Equipment.Description = Description; Equipment.Description = Description;
Equipment.CreationDate = CreationDate;
Equipment.Images = Images.Select(e => e.GetImage()).ToList(); Equipment.Images = Images.Select(e => e.GetImage()).ToList();
Equipment.Inspections = Inspections.Select(e => e.GetInspection()).ToList(); Equipment.Inspections = Inspections.Select(e => e.GetInspection()).ToList();
Equipment.Properties = Properties.Select(e => e.GetProperty()).ToList();
Equipment.Equipments = Equipments.Select(e => e.GetEquipment()).ToList();
return Equipment; return Equipment;
} }
} }
+34 -14
View File
@@ -1,31 +1,49 @@
using System.IO; using System;
using System.IO;
using System.Threading.Tasks;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using GazpromApp.Messages;
using GazpromApp.Models; using GazpromApp.Models;
namespace GazpromApp.ViewModels; namespace GazpromApp.ViewModels;
public partial class ImageViewModel : ViewModelBase public partial class ImageViewModel : ViewModelBase
{ {
public ViewModelBase? Parent;
private Image Image { get; } private Image Image { get; }
[ObservableProperty] [ObservableProperty] private byte[]? _bytes;
private byte[]? _bytes;
[ObservableProperty] private DateTime _creationDate;
// EF stuff // EF stuff
[ObservableProperty] [ObservableProperty] private Point? _point;
private Point? _point;
[ObservableProperty] private Equipment? _equipment;
[ObservableProperty]
private Equipment? _equipment; [ObservableProperty] private Bitmap? _fileName;
[ObservableProperty] [RelayCommand]
private Bitmap? _fileName; private async Task ViewImage() => _ = await WeakReferenceMessenger.Default.Send(new ViewImageMessage(this));
[RelayCommand]
private void DeleteImage() => _ = Parent switch
{
PointViewModel pmv => pmv.Images.Remove(this),
EquipmentViewModel emv => emv.Images.Remove(this),
EditPointViewModel editPointViewModel => editPointViewModel.Images.Remove(this),
EditEquipmentViewModel editEquipmentViewModel => editEquipmentViewModel.Images.Remove(this),
_ => false
};
public ImageViewModel(Image image) public ImageViewModel(Image image)
{ {
Bytes = image.Bytes; Bytes = image.Bytes;
CreationDate = image.CreationDate;
Equipment = image.Equipment; Equipment = image.Equipment;
Point = image.Point; Point = image.Point;
FileName = image.Bytes is { Length: > 0 } ? new Bitmap(new MemoryStream(image.Bytes)) : null; FileName = image.Bytes is { Length: > 0 } ? new Bitmap(new MemoryStream(image.Bytes)) : null;
@@ -35,6 +53,7 @@ public partial class ImageViewModel : ViewModelBase
public ImageViewModel() public ImageViewModel()
{ {
Bytes = null; Bytes = null;
CreationDate = DateTime.Now;
Equipment = null; Equipment = null;
Point = null; Point = null;
Image = new Image(); Image = new Image();
@@ -45,6 +64,7 @@ public partial class ImageViewModel : ViewModelBase
var ms = new MemoryStream(); var ms = new MemoryStream();
FileName?.Save(ms); FileName?.Save(ms);
Image.Bytes = ms.ToArray(); Image.Bytes = ms.ToArray();
Image.CreationDate = CreationDate;
Image.Equipment = Equipment; Image.Equipment = Equipment;
Image.Point = Point; Image.Point = Point;
return Image; return Image;
+23
View File
@@ -1,6 +1,10 @@
using System; using System;
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using GazpromApp.Enums; using GazpromApp.Enums;
using GazpromApp.Messages;
using GazpromApp.Models; using GazpromApp.Models;
namespace GazpromApp.ViewModels; namespace GazpromApp.ViewModels;
@@ -11,6 +15,8 @@ public partial class InspectionViewModel : ViewModelBase
[ObservableProperty] [ObservableProperty]
private string _name; private string _name;
[ObservableProperty] [ObservableProperty]
private DateTime _creationDate;
[ObservableProperty]
private DateTimeOffset _inspectionDate; private DateTimeOffset _inspectionDate;
[ObservableProperty] [ObservableProperty]
private PeriodType _periodType; private PeriodType _periodType;
@@ -21,10 +27,25 @@ public partial class InspectionViewModel : ViewModelBase
[ObservableProperty] [ObservableProperty]
private bool _isEditing; private bool _isEditing;
[RelayCommand]
private void EditInspection()
{
IsEditing = !IsEditing;
}
[RelayCommand]
private void RemoveInspection() => WeakReferenceMessenger.Default.Send(new RemoveInspectionMessage(this));
// ReSharper disable once MemberCanBeMadeStatic.Global
public PeriodType[] AllPeriods => Enum.GetValues<PeriodType>()
.Where(p => p != PeriodType.Unknown)
.ToArray();
public InspectionViewModel() public InspectionViewModel()
{ {
Name = string.Empty; Name = string.Empty;
CreationDate = DateTime.Now;
InspectionDate = DateTimeOffset.Now; InspectionDate = DateTimeOffset.Now;
PeriodType = 0; PeriodType = 0;
PeriodValue = 1; PeriodValue = 1;
@@ -34,6 +55,7 @@ public partial class InspectionViewModel : ViewModelBase
public InspectionViewModel(Inspection inspection) public InspectionViewModel(Inspection inspection)
{ {
Name = inspection.Name; Name = inspection.Name;
CreationDate = inspection.CreationDate;
InspectionDate = inspection.InspectionDate; InspectionDate = inspection.InspectionDate;
PeriodType = inspection.PeriodType.ToPeriodType(); PeriodType = inspection.PeriodType.ToPeriodType();
PeriodValue = inspection.PeriodValue; PeriodValue = inspection.PeriodValue;
@@ -43,6 +65,7 @@ public partial class InspectionViewModel : ViewModelBase
public Inspection GetInspection() public Inspection GetInspection()
{ {
Inspection.Name = Name; Inspection.Name = Name;
Inspection.CreationDate = CreationDate;
Inspection.InspectionDate = InspectionDate; Inspection.InspectionDate = InspectionDate;
Inspection.PeriodType = PeriodType.ToDescription(); Inspection.PeriodType = PeriodType.ToDescription();
Inspection.PeriodValue = PeriodValue; Inspection.PeriodValue = PeriodValue;
+43 -11
View File
@@ -1,5 +1,12 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using GazpromApp.Messages;
using GazpromApp.Models; using GazpromApp.Models;
namespace GazpromApp.ViewModels; namespace GazpromApp.ViewModels;
@@ -14,39 +21,64 @@ public partial class PointViewModel : ViewModelBase
[ObservableProperty] [ObservableProperty]
private string? _description; private string? _description;
[ObservableProperty]
private DateTime _creationDate;
[ObservableProperty] [ObservableProperty]
private double? _latitude; private double? _latitude;
[ObservableProperty] [ObservableProperty]
private double? _longitude; private double? _longitude;
[RelayCommand]
private void AddEquipment()
{
Equipment.Add(new EquipmentViewModel(new Equipment()) {Name = "Новое оборудование", Description = "Описание оборудования", Parent = this});
WeakReferenceMessenger.Default.Send(new EditPointMessage(this));
}
[RelayCommand]
private void RemovePoint()
{
WeakReferenceMessenger.Default.Send(new RemovePointMessage(this));
}
private void RemoveEquipment(object sender, RemoveEquipmentMessage msg)
{
if (msg.Equipment.GetEquipment().Point == GetPoint())
Equipment.Remove(msg.Equipment);
}
// EF stuff
[ObservableProperty] [ObservableProperty]
private List<Image> _images; private ObservableCollection<ImageViewModel> _images;
[ObservableProperty] [ObservableProperty]
private List<Equipment> _equipment; private ObservableCollection<EquipmentViewModel> _equipment;
[ObservableProperty] [ObservableProperty]
private List<Property> _properties; private ObservableCollection<PropertyViewModel> _properties;
public PointViewModel(Point point) public PointViewModel(Point point)
{ {
Point = point; Point = point;
Name = point.Name; Name = point.Name;
CreationDate = point.CreationDate;
Description = point.Description; Description = point.Description;
Latitude = point.Latitude; Latitude = point.Latitude;
Longitude = point.Longitude; Longitude = point.Longitude;
Images = point.Images; Images = new ObservableCollection<ImageViewModel>(point.Images.Select(i => new ImageViewModel(i)));
Equipment = point.Equipment; Equipment = new ObservableCollection<EquipmentViewModel>(point.Equipment.Select(i => new EquipmentViewModel(i){Parent = this}));
Properties = point.Properties; Properties = new ObservableCollection<PropertyViewModel>(point.Properties.Select(i => new PropertyViewModel(i)));
WeakReferenceMessenger.Default.Register<RemoveEquipmentMessage>(this, RemoveEquipment);
} }
public Point GetPoint() public Point GetPoint()
{ {
Point.Name = Name; Point.Name = Name;
Point.Description = Description; Point.Description = Description;
Point.Equipment = Equipment; Point.CreationDate = CreationDate;
Point.Images = Images; Point.Equipment = Equipment.Select(e => e.GetEquipment()).ToList();
Point.Properties = Properties; Point.Images = Images.Select(i => i.GetImage()).ToList();
Point.Properties = Properties.Select(p => p.GetProperty()).ToList();
return Point; return Point;
} }
} }
+34 -3
View File
@@ -1,6 +1,10 @@
using System.Collections.ObjectModel; using System;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using GazpromApp.Messages;
using GazpromApp.Models; using GazpromApp.Models;
namespace GazpromApp.ViewModels; namespace GazpromApp.ViewModels;
@@ -8,6 +12,8 @@ namespace GazpromApp.ViewModels;
public partial class PropertyViewModel : ViewModelBase public partial class PropertyViewModel : ViewModelBase
{ {
public ViewModelBase? Parent { get; init; }
private Property Property { get; } private Property Property { get; }
[ObservableProperty] [ObservableProperty]
@@ -16,19 +22,36 @@ public partial class PropertyViewModel : ViewModelBase
[ObservableProperty] [ObservableProperty]
private string _value; private string _value;
[ObservableProperty]
private DateTime _creationDate;
public ObservableCollection<PropertyViewModel> Properties { get; set; } public ObservableCollection<PropertyViewModel> Properties { get; set; }
// Visual and other properties // Visual and other properties
public PropertyViewModel? Parent { get; init; }
[ObservableProperty] [ObservableProperty]
private bool _isEditing; private bool _isEditing;
[RelayCommand]
private void AddProperty() => Properties.Add(new PropertyViewModel() {Parent = this});
[RelayCommand]
private void RemoveProperty() => WeakReferenceMessenger.Default.Send(new RemovePropertyMessage(this));
[RelayCommand]
private void EditProperty() => IsEditing = !IsEditing;
private void RemoveProperty(object sender, RemovePropertyMessage msg)
{
if (Properties.Contains(msg.Property))
Properties.Remove(msg.Property);
}
public Property GetProperty(Property? parent = null) public Property GetProperty(Property? parent = null)
{ {
Property.Name = Name; Property.Name = Name;
Property.Value = Value; Property.Value = Value;
Property.CreationDate = CreationDate;
Property.Parent = parent; Property.Parent = parent;
Property.Properties = Properties.Select(e => e.GetProperty(Property)).ToList(); Property.Properties = Properties.Select(e => e.GetProperty(Property)).ToList();
return Property; return Property;
@@ -38,19 +61,25 @@ public partial class PropertyViewModel : ViewModelBase
{ {
Name = "Имя свойства"; Name = "Имя свойства";
Value = "Значение свойства"; Value = "Значение свойства";
CreationDate = DateTime.Now;
Properties = []; Properties = [];
Parent = null; Parent = null;
Property = new Property(); Property = new Property();
WeakReferenceMessenger.Default.Register<RemovePropertyMessage>(this, RemoveProperty);
} }
public PropertyViewModel(Property property, PropertyViewModel? parent = null) public PropertyViewModel(Property property, PropertyViewModel? parent = null)
{ {
Name = property.Name; Name = property.Name;
Value = property.Value; Value = property.Value;
CreationDate = property.CreationDate;
Properties = new ObservableCollection<PropertyViewModel>( Properties = new ObservableCollection<PropertyViewModel>(
property.Properties.Select(e => new PropertyViewModel(e, this))); property.Properties.Select(e => new PropertyViewModel(e, this)));
Parent = property.Parent is null ? null : parent; Parent = property.Parent is null ? null : parent;
Property = property; Property = property;
WeakReferenceMessenger.Default.Register<RemovePropertyMessage>(this, RemoveProperty);
} }
public PropertyViewModel(PropertyViewModel property) public PropertyViewModel(PropertyViewModel property)
@@ -60,5 +89,7 @@ public partial class PropertyViewModel : ViewModelBase
Properties = []; Properties = [];
Parent = property; Parent = property;
Property = new Property(); Property = new Property();
WeakReferenceMessenger.Default.Register<RemovePropertyMessage>(this, RemoveProperty);
} }
} }
+42
View File
@@ -0,0 +1,42 @@
using Avalonia.Controls;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using GazpromApp.Enums;
using GazpromApp.Messages;
using GazpromApp.Models;
using GazpromApp.Views;
namespace GazpromApp.ViewModels;
public partial class SaveChangesViewModel : ViewModelBase
{
[ObservableProperty]
private bool _isSave;
[ObservableProperty]
private bool _isCancel;
[RelayCommand]
private void Cancel(Window w)
{
((SaveChangesView)w).CanClose = true;
WeakReferenceMessenger.Default.Send(new SaveChangesResult(false, true));
w.Close(this);
}
[RelayCommand]
private void Save(Window w)
{
((SaveChangesView)w).CanClose = true;
WeakReferenceMessenger.Default.Send(new SaveChangesResult(true, false));
w.Close(this);
}
[RelayCommand]
private void DontSave(Window w)
{
((SaveChangesView)w).CanClose = true;
WeakReferenceMessenger.Default.Send(new SaveChangesResult(false, false));
w.Close(this);
}
}
@@ -5,7 +5,6 @@ using System.Threading.Tasks;
using System.Web; using System.Web;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Avalonia.Platform.Storage;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
@@ -16,26 +15,15 @@ using Image = GazpromApp.Models.Image;
namespace GazpromApp.ViewModels; namespace GazpromApp.ViewModels;
public partial class EditEquipmentDialogViewModel : ViewModelBase public partial class EditEquipmentViewModel : ViewModelBase
{ {
[ObservableProperty] [ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(CompleteEditCommand))] [NotifyCanExecuteChangedFor(nameof(CompleteEditCommand))]
private string? _name; private string? _name;
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(CompleteEditCommand))]
private string? _description;
[ObservableProperty] [ObservableProperty]
private bool _isNameEditing; private bool _isNameEditing;
[ObservableProperty]
private bool _isDescriptionEditing;
public ObservableCollection<ImageViewModel> Images { get; set; }
public ObservableCollection<InspectionViewModel> Inspections { get; set; }
[RelayCommand] [RelayCommand]
private void EditName() private void EditName()
{ {
@@ -43,6 +31,13 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
IsDescriptionEditing = false; IsDescriptionEditing = false;
} }
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(CompleteEditCommand))]
private string? _description;
[ObservableProperty]
private bool _isDescriptionEditing;
[RelayCommand] [RelayCommand]
private void EditDescription() private void EditDescription()
{ {
@@ -50,20 +45,17 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
IsNameEditing = false; IsNameEditing = false;
} }
public ObservableCollection<ImageViewModel> Images { get; set; }
[RelayCommand] [RelayCommand]
private async Task AddImage(Window w) private async Task AddImage(Window w)
{ {
var files = await w.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions var files = await WeakReferenceMessenger.Default.Send(new RequestImageMessage(this));
{
AllowMultiple = true,
Title = "Выберите одну или несколько картинок",
FileTypeFilter = [FilePickerFileTypes.ImageAll]
});
foreach (var file in files) foreach (var file in files)
{ {
try try
{ {
Images.Add(new ImageViewModel(new Image()) { FileName = new Bitmap(HttpUtility.UrlDecode(file.Path.AbsolutePath) ) }); Images.Add(new ImageViewModel(new Image()) { FileName = new Bitmap(HttpUtility.UrlDecode(file.Path.AbsolutePath)), Parent = this});
} }
catch (ArgumentException) catch (ArgumentException)
{ {
@@ -76,35 +68,20 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
_ = await WeakReferenceMessenger.Default.Send(new ErrorMessage(new ErrorViewModel(error))); _ = await WeakReferenceMessenger.Default.Send(new ErrorMessage(new ErrorViewModel(error)));
} }
} }
IsImagesEmpty = Images.Count == 0;
} }
public ObservableCollection<InspectionViewModel> Inspections { get; set; }
[RelayCommand] [RelayCommand]
private static async Task ViewImage(ImageViewModel image) => _ = await WeakReferenceMessenger.Default.Send(new ViewImageMessage(image)); private void AddInspection() => Inspections.Add(new InspectionViewModel
{ Name = "Название инспекции", InspectionDate = DateTimeOffset.Now, PeriodValue = 1, PeriodType = PeriodType.Day });
private void RemoveInspection(object sender, RemoveInspectionMessage msg)
{
if (Inspections.Contains(msg.Inspection))
Inspections.Remove(msg.Inspection);
}
[RelayCommand]
private void DeleteImage(ImageViewModel image)
{
Images.Remove(image);
IsImagesEmpty = Images.Count == 0;
}
[RelayCommand]
private void AddInspection()
{
Inspections.Add(new InspectionViewModel { Name = "Название инспекции", InspectionDate = DateTimeOffset.Now, PeriodValue = 1, PeriodType = PeriodType.Day });
}
[RelayCommand]
private void EditInspection(InspectionViewModel inspection)
{
foreach (var item in Inspections)
if (item != inspection)
item.IsEditing = false;
inspection.IsEditing = !inspection.IsEditing;
}
[RelayCommand] [RelayCommand]
private void DeleteInspection(InspectionViewModel inspection) private void DeleteInspection(InspectionViewModel inspection)
{ {
@@ -114,21 +91,12 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
public ObservableCollection<PropertyViewModel> Properties { get; set; } public ObservableCollection<PropertyViewModel> Properties { get; set; }
[RelayCommand] [RelayCommand]
private void AddPropertySimple() => Properties.Add(new PropertyViewModel()); private void AddProperty() => Properties.Add(new PropertyViewModel {Parent = this});
[RelayCommand] private void RemoveProperty(object sender, RemovePropertyMessage msg)
private static void AddProperty(PropertyViewModel property) => property.Properties.Add(new PropertyViewModel(property));
[RelayCommand]
private static void EditProperty(PropertyViewModel property) => property.IsEditing = !property.IsEditing;
[RelayCommand]
private void DeleteProperty(PropertyViewModel property)
{ {
if (property.Parent is null) if (Properties.Contains(msg.Property))
Properties.Remove(property); Properties.Remove(msg.Property);
else
property.Parent?.Properties.Remove(property);
} }
private bool CanCompleteEdit() => !string.IsNullOrWhiteSpace(Name); private bool CanCompleteEdit() => !string.IsNullOrWhiteSpace(Name);
@@ -136,32 +104,24 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
[RelayCommand(CanExecute = nameof(CanCompleteEdit))] [RelayCommand(CanExecute = nameof(CanCompleteEdit))]
private void CompleteEdit() private void CompleteEdit()
{ {
IsClosed = true; _equipment.Name = Name;
var equipment = new Equipment _equipment.Description = Description;
{ _equipment.Images = Images;
Name = Name, _equipment.Inspections = Inspections;
Description = Description, _equipment.Properties = Properties;
Images = Images.Select(e => e.GetImage()).ToList(), _ = _equipment.GetEquipment();
Inspections = Inspections.Select(e => e.GetInspection()).ToList(),
Properties = Properties.Select(e => e.GetProperty()).ToList() CallUpdatePoint(_equipment);
};
WeakReferenceMessenger.Default.Send(new EditEquipmentDone(new EquipmentViewModel(equipment)));
} }
[RelayCommand] [RelayCommand]
private void CancelEdit(Window w) private void CancelEdit(Window w)
{ {
IsClosed = true; CallUpdatePoint(_equipment);
WeakReferenceMessenger.Default.Send(new EditEquipmentDone(_equipment));
} }
// Visual and other properties // Visual and other properties
[ObservableProperty]
private bool _isImagesEmpty;
[ObservableProperty]
private bool _isClosed;
private readonly EquipmentViewModel _equipment; private readonly EquipmentViewModel _equipment;
@@ -169,8 +129,23 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
public PeriodType[] AllPeriods => Enum.GetValues<PeriodType>() public PeriodType[] AllPeriods => Enum.GetValues<PeriodType>()
.Where(p => p != PeriodType.Unknown) .Where(p => p != PeriodType.Unknown)
.ToArray(); .ToArray();
private void CallUpdatePoint(ViewModelBase vm)
{
switch (vm)
{
case PointViewModel pointViewModel:
WeakReferenceMessenger.Default.Send(new EditPointMessage(pointViewModel));
break;
case EquipmentViewModel equipmentViewModel:
CallUpdatePoint(equipmentViewModel.Parent ?? throw new InvalidOperationException("Parent equipment not found in hierarchy"));
break;
default:
throw new ArgumentOutOfRangeException(nameof(vm), vm, null);
}
}
public EditEquipmentDialogViewModel() public EditEquipmentViewModel()
{ {
Name = "Testing"; Name = "Testing";
Description = "Testing"; Description = "Testing";
@@ -178,12 +153,10 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
Inspections = []; Inspections = [];
Properties = []; Properties = [];
IsImagesEmpty = true;
_equipment = new EquipmentViewModel(); _equipment = new EquipmentViewModel();
} }
public EditEquipmentDialogViewModel(EquipmentViewModel equipment) public EditEquipmentViewModel(EquipmentViewModel equipment)
{ {
Name = equipment.Name; Name = equipment.Name;
Description = equipment.Description; Description = equipment.Description;
@@ -191,8 +164,14 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
Inspections = new ObservableCollection<InspectionViewModel>(equipment.Inspections.Select(e => e)); Inspections = new ObservableCollection<InspectionViewModel>(equipment.Inspections.Select(e => e));
Properties = new ObservableCollection<PropertyViewModel>(equipment.Properties.Select(e => e)); Properties = new ObservableCollection<PropertyViewModel>(equipment.Properties.Select(e => e));
IsImagesEmpty = Images.Count == 0;
_equipment = equipment; _equipment = equipment;
WeakReferenceMessenger.Default.Register<RemovePropertyMessage>(this, RemoveProperty);
WeakReferenceMessenger.Default.Register<RemoveInspectionMessage>(this, RemoveInspection);
}
~EditEquipmentViewModel()
{
WeakReferenceMessenger.Default.UnregisterAll(this);
} }
} }
@@ -5,7 +5,6 @@ using System.Threading.Tasks;
using System.Web; using System.Web;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Avalonia.Platform.Storage;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
@@ -16,7 +15,7 @@ using Image = GazpromApp.Models.Image;
namespace GazpromApp.ViewModels; namespace GazpromApp.ViewModels;
public partial class EditPointDialogViewModel : ViewModelBase public partial class EditPointViewModel : ViewModelBase
{ {
[ObservableProperty] [ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(CompleteEditCommand))] [NotifyCanExecuteChangedFor(nameof(CompleteEditCommand))]
@@ -51,17 +50,12 @@ public partial class EditPointDialogViewModel : ViewModelBase
[RelayCommand] [RelayCommand]
private async Task AddImage(Window w) private async Task AddImage(Window w)
{ {
var files = await w.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions var files = await WeakReferenceMessenger.Default.Send(new RequestImageMessage(this));
{
AllowMultiple = true,
Title = "Выберите одну или несколько картинок",
FileTypeFilter = [FilePickerFileTypes.ImageAll]
});
foreach (var file in files) foreach (var file in files)
{ {
try try
{ {
Images.Add(new ImageViewModel(new Image()) { FileName = new Bitmap(HttpUtility.UrlDecode(file.Path.AbsolutePath) ) }); Images.Add(new ImageViewModel(new Image()) { FileName = new Bitmap(HttpUtility.UrlDecode(file.Path.AbsolutePath)), Parent = this});
} }
catch (ArgumentException) catch (ArgumentException)
{ {
@@ -74,66 +68,19 @@ public partial class EditPointDialogViewModel : ViewModelBase
_ = await WeakReferenceMessenger.Default.Send(new ErrorMessage(new ErrorViewModel(error))); _ = await WeakReferenceMessenger.Default.Send(new ErrorMessage(new ErrorViewModel(error)));
} }
} }
IsImagesEmpty = Images.Count == 0;
} }
[RelayCommand]
private void DeleteImage(ImageViewModel image)
{
Images.Remove(image);
IsImagesEmpty = Images.Count == 0;
}
[RelayCommand]
private static async Task ViewImage(ImageViewModel image) => _ = await WeakReferenceMessenger.Default.Send(new ViewImageMessage(image));
public ObservableCollection<EquipmentViewModel> Equipment { get; set; } public ObservableCollection<EquipmentViewModel> Equipment { get; set; }
[RelayCommand]
private async Task AddEquipment()
{
var equipment = await WeakReferenceMessenger.Default.Send(new NewEquipmentMessage());
if (equipment != null)
Equipment.Add(equipment);
IsEquipmentEmpty = Equipment.Count == 0;
}
[RelayCommand]
private async Task EditEquipment(EquipmentViewModel equipment)
{
var e = await WeakReferenceMessenger.Default.Send(new EditEquipmentMessage(equipment)) ?? equipment;
Equipment[Equipment.IndexOf(equipment)] = e;
}
[RelayCommand]
private void DeleteEquipment(EquipmentViewModel equipment)
{
Equipment.Remove(equipment);
IsEquipmentEmpty = Equipment.Count == 0;
}
public ObservableCollection<PropertyViewModel> Properties { get; set; } public ObservableCollection<PropertyViewModel> Properties { get; set; }
[RelayCommand] [RelayCommand]
private void AddPropertySimple() => Properties.Add(new PropertyViewModel()); private void AddProperty() => Properties.Add(new PropertyViewModel {Parent = this});
[RelayCommand] private void RemoveProperty(object sender, RemovePropertyMessage msg)
private static void AddProperty(PropertyViewModel property) => property.Properties.Add(new PropertyViewModel(property));
[RelayCommand]
private static void EditProperty(PropertyViewModel property) => property.IsEditing = !property.IsEditing;
[RelayCommand]
private void DeleteProperty(PropertyViewModel property)
{ {
if (property.Parent is null) if (Properties.Contains(msg.Property))
Properties.Remove(property); Properties.Remove(msg.Property);
else
property.Parent?.Properties.Remove(property);
} }
private bool CanCompleteEdit() => !string.IsNullOrWhiteSpace(Name); private bool CanCompleteEdit() => !string.IsNullOrWhiteSpace(Name);
@@ -141,41 +88,30 @@ public partial class EditPointDialogViewModel : ViewModelBase
[RelayCommand(CanExecute = nameof(CanCompleteEdit))] [RelayCommand(CanExecute = nameof(CanCompleteEdit))]
private void CompleteEdit() private void CompleteEdit()
{ {
IsClosed = true;
_point.Name = Name; _point.Name = Name;
_point.Description = Description; _point.Description = Description;
_point.Images = Images.Select(e => e.GetImage()).ToList(); _point.Images = Images;
_point.Equipment = Equipment.Select(e => e.GetEquipment()).ToList(); _point.Equipment = Equipment;
_point.Properties = Properties.Select(e => e.GetProperty()).ToList(); _point.Properties = Properties;
_ = _point.GetPoint(); _ = _point.GetPoint();
WeakReferenceMessenger.Default.Send(new EditPointDone(new PointViewModel(_point.GetPoint()))); WeakReferenceMessenger.Default.Send(new EditPointMessage(_point));
} }
[RelayCommand] [RelayCommand]
private void CancelEdit(Window w) private void CancelEdit(Window w)
{ {
IsClosed = true; WeakReferenceMessenger.Default.Send(new EditPointMessage(_point));
WeakReferenceMessenger.Default.Send(new EditPointDone(_point));
} }
// Visual and other properties // Visual and other properties
[ObservableProperty]
private bool _isImagesEmpty;
[ObservableProperty]
private bool _isEquipmentEmpty;
[ObservableProperty]
private bool _isClosed;
private readonly PointViewModel _point; private readonly PointViewModel _point;
public EditPointDialogViewModel() public EditPointViewModel()
{ {
Name = ""; Name = "fsdfasdfasd";
Description = ""; Description = "asfasdfasdfa";
Images = []; Images = [];
Equipment = [ Equipment = [
new EquipmentViewModel new EquipmentViewModel
@@ -245,23 +181,25 @@ public partial class EditPointDialogViewModel : ViewModelBase
} }
]; ];
IsImagesEmpty = true; _point = new PointViewModel(new Point());
IsEquipmentEmpty = true;
_point = new PointViewModel(new Point());
} }
public EditPointDialogViewModel(PointViewModel point) public EditPointViewModel(PointViewModel point)
{ {
Name = point.Name; Name = point.Name;
Description = point.Description; Description = point.Description;
Images = new ObservableCollection<ImageViewModel>(point.Images.Select(e => new ImageViewModel(e))); Images = new ObservableCollection<ImageViewModel>(point.Images);
Equipment = new ObservableCollection<EquipmentViewModel>(point.Equipment.Select(e => new EquipmentViewModel(e))); Images.ToList().ForEach(i => i.Parent = this);
Properties = new ObservableCollection<PropertyViewModel>(point.Properties.Select(e => new PropertyViewModel(e))); Equipment = new ObservableCollection<EquipmentViewModel>(point.Equipment);
Properties = new ObservableCollection<PropertyViewModel>(point.Properties);
IsImagesEmpty = Images.Count == 0;
IsEquipmentEmpty = Equipment.Count == 0;
_point = point; _point = point;
WeakReferenceMessenger.Default.Register<RemovePropertyMessage>(this, RemoveProperty);
}
~EditPointViewModel()
{
WeakReferenceMessenger.Default.UnregisterAll(this);
} }
} }
+158 -56
View File
@@ -1,7 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web; using System.Web;
@@ -21,14 +21,19 @@ public partial class MainWindowViewModel : ViewModelBase
{ {
public ObservableCollection<PointViewModel> Points { get; set; } public ObservableCollection<PointViewModel> Points { get; set; }
[ObservableProperty]
private object? _selectedItem;
[ObservableProperty]
private ViewModelBase? _selectedItemViewModel;
[RelayCommand] [RelayCommand]
private async Task AddPoint() private async Task AddPoint()
{ {
var point = await WeakReferenceMessenger.Default.Send(new NewPointMessage());
if (point == null) return;
IsLoading = true; IsLoading = true;
var point = new PointViewModel(new Point {Name = "Новый объект", Description = "Описание объекта"});
_context.Point.Add(point.GetPoint()); _context.Point.Add(point.GetPoint());
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
@@ -37,49 +42,16 @@ public partial class MainWindowViewModel : ViewModelBase
IsLoading = false; 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] [RelayCommand]
private async Task ImportPoint(Window w) private async Task ImportPoint(Window w)
{ {
Directory.CreateDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "GazpromApp"));
var files = await w.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions var files = await w.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{ {
AllowMultiple = true, AllowMultiple = true,
SuggestedStartLocation = SuggestedStartLocation =
await w.StorageProvider.TryGetFolderFromPathAsync( await w.StorageProvider.TryGetFolderFromPathAsync(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)) Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "GazpromApp"))
}); });
if (files.Count < 1) return; if (files.Count < 1) return;
@@ -92,6 +64,7 @@ public partial class MainWindowViewModel : ViewModelBase
var decoded = HttpUtility.UrlDecode(url); var decoded = HttpUtility.UrlDecode(url);
var point = DataSerialization.LoadPoint(decoded); var point = DataSerialization.LoadPoint(decoded);
point?.SetPropertyParents(); point?.SetPropertyParents();
point?.SetEquipmentParents();
if (point == null) continue; if (point == null) continue;
_context.Point.Add(point); _context.Point.Add(point);
@@ -108,33 +81,81 @@ public partial class MainWindowViewModel : ViewModelBase
[RelayCommand] [RelayCommand]
private async Task ExportPoint(Window w) private async Task ExportPoint(Window w)
{ {
Directory.CreateDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "GazpromApp"));
var folder = await w.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions var folder = await w.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{ {
AllowMultiple = false, AllowMultiple = false,
SuggestedStartLocation = SuggestedStartLocation =
await w.StorageProvider.TryGetFolderFromPathAsync( await w.StorageProvider.TryGetFolderFromPathAsync(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)) Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "GazpromApp"))
}); });
if (folder.Count != 1) return; if (folder.Count != 1) return;
foreach (var point in Points) foreach (var point in Points)
DataSerialization.SavePoint(point.GetPoint(), Path.Combine(HttpUtility.UrlDecode(folder[0].Path.AbsolutePath), point.Name + ".json") ); 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 // Visual and other properties
[ObservableProperty] private bool _isLoading = true; [ObservableProperty] private bool _isLoading = true;
private readonly AppDbContext _context; 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) if (properties.Count == 0)
return; 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 var children = await _context.Property
.Where(p => p.ParentPropertyId.HasValue && parentIds.Contains(p.ParentPropertyId.Value)) .Where(p => p.ParentPropertyId.HasValue && parentIds.Contains(p.ParentPropertyId.Value))
.AsNoTracking() .OrderBy(p => p.CreationDate)
.ToListAsync(); .ToListAsync();
if (children.Count != 0) if (children.Count != 0)
@@ -142,36 +163,85 @@ public partial class MainWindowViewModel : ViewModelBase
var childrenLookup = children.ToLookup(child => child.ParentPropertyId); var childrenLookup = children.ToLookup(child => child.ParentPropertyId);
foreach (var parent in properties.Where(parent => childrenLookup.Contains(parent.Id))) 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, loadedIds);
await LoadChildrenForProperties(children);
} }
} }
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() private async Task LoadDataAsync()
{ {
IsLoading = true; IsLoading = true;
// ReSharper disable once EntityFramework.NPlusOne.IncompleteDataQuery
var pointsFromDb = await _context.Point 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) .Include(p => p.Equipment)
.ThenInclude(e => e.Properties) .ThenInclude(e => e.Images
.OrderBy(i => i.CreationDate))
.Include(p => p.Equipment) .Include(p => p.Equipment)
.ThenInclude(e => e.Images) .ThenInclude(e => e.Inspections
.Include(p => p.Equipment) .OrderBy(i => i.CreationDate))
.ThenInclude(e => e.Inspections) .Include(p => p.Properties
.Include(p => p.Properties) .OrderBy(p => p.CreationDate))
.AsNoTracking()
.ToListAsync(); .ToListAsync();
var topLevelProperties = pointsFromDb.SelectMany(p => p.Properties) var topLevelProperties = pointsFromDb.SelectMany(p => p.Properties)
.Concat(pointsFromDb.SelectMany(p => p.Equipment).SelectMany(e => e.Properties)) .Concat(pointsFromDb.SelectMany(p => p.Equipment).SelectMany(e => e.Properties))
.ToList(); .ToList();
if (topLevelProperties.Count != 0) var topLevelEquipments = pointsFromDb.SelectMany(p => p.Equipment)
await LoadChildrenForProperties(topLevelProperties); .ToList();
if (topLevelProperties.Count != 0)
await LoadChildrenForProperties(topLevelProperties, []);
if (topLevelEquipments.Count != 0)
await LoadChildrenForEquipments(topLevelEquipments, []);
Points.Clear(); Points.Clear();
foreach (var point in pointsFromDb) foreach (var point in pointsFromDb)
Points.Add(new PointViewModel(point)); Points.Add(new PointViewModel(point));
@@ -179,16 +249,48 @@ public partial class MainWindowViewModel : ViewModelBase
IsLoading = false; 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) public MainWindowViewModel(AppDbContext context)
{ {
Points = []; Points = [];
_context = context; _context = context;
_ = LoadDataAsync(); _ = LoadDataAsync();
WeakReferenceMessenger.Default.Register<EditPointMessage>(this, EditPoint);
WeakReferenceMessenger.Default.Register<RemovePointMessage>(this, RemovePoint);
WeakReferenceMessenger.Default.Register<SelectionChangedMessage>(this, HandleSelectionChanged);
} }
public MainWindowViewModel() public MainWindowViewModel()
{ {
Points = [new PointViewModel(new Point()) { Name = "Name test", Description = "Description test" }]; Points = [new PointViewModel(new Point()) { Name = "Новый объект", Description = "Описание объекта" }];
_context = new AppDbContext(); _context = new AppDbContext();
IsLoading = false; IsLoading = false;
} }
-94
View File
@@ -1,94 +0,0 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Avalonia.Controls;
using Avalonia.Media.Imaging;
using Avalonia.Platform.Storage;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using GazpromApp.Enums;
using GazpromApp.Messages;
using GazpromApp.Models;
using Image = GazpromApp.Models.Image;
namespace GazpromApp.ViewModels;
public partial class NewEquipmentDialogViewModel : ViewModelBase
{
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(EnterEquipmentCommand))]
private string? _name;
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(EnterEquipmentCommand))]
private string? _description;
public ObservableCollection<ImageViewModel> Images { get; } = [];
[RelayCommand]
private async Task AddImage(Window w)
{
var files = await w.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
AllowMultiple = true,
Title = "Выберите одну или несколько картинок",
FileTypeFilter = [FilePickerFileTypes.ImageAll]
});
foreach (var file in files)
{
try
{
Images.Add(new ImageViewModel(new Image()) { FileName = new Bitmap(HttpUtility.UrlDecode(file.Path.AbsolutePath)) });
}
catch (ArgumentException)
{
var error = new Error
{
Title = "Ошибка обработки картинки",
Message = $"Картинка не была добавлена: \"{HttpUtility.UrlDecode(file.Name)}\"",
Severity = ErrorSeverity.Error
};
_ = await WeakReferenceMessenger.Default.Send(new ErrorMessage(new ErrorViewModel(error)));
}
}
IsImagesEmpty = Images.Count == 0;
}
[RelayCommand]
private void DeleteImage(ImageViewModel image)
{
Images.Remove(image);
IsImagesEmpty = Images.Count == 0;
}
private bool CanEnterEquipment() => !string.IsNullOrEmpty(Name);
[RelayCommand (CanExecute = nameof(CanEnterEquipment))]
private void EnterEquipment()
{
var equipment = new Equipment
{
Name = Name,
Description = Description ?? string.Empty,
Images = Images.Select(e => e.GetImage()).ToList()
};
WeakReferenceMessenger.Default.Send(new NewEquipmentDone(new EquipmentViewModel(equipment)));
}
[RelayCommand]
private static void CancelEnterEquipment(Window w)
{
w.Close();
}
// Visual and other stuff
[ObservableProperty]
private bool _isImagesEmpty;
}
-93
View File
@@ -1,93 +0,0 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Avalonia.Controls;
using Avalonia.Media.Imaging;
using Avalonia.Platform.Storage;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using GazpromApp.Enums;
using GazpromApp.Messages;
using GazpromApp.Models;
using Image = GazpromApp.Models.Image;
using Point = GazpromApp.Models.Point;
namespace GazpromApp.ViewModels;
public partial class NewPointDialogViewModel : ViewModelBase
{
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(EnterPointCommand))]
private string? _name;
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(EnterPointCommand))]
private string? _description;
public ObservableCollection<ImageViewModel> Images { get; } = [];
[RelayCommand]
private async Task AddImage(Window w)
{
var files = await w.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
AllowMultiple = true,
Title = "Выберите одну или несколько картинок",
FileTypeFilter = [FilePickerFileTypes.ImageAll]
});
foreach (var file in files)
{
try
{
Images.Add(new ImageViewModel(new Image()) { FileName = new Bitmap(HttpUtility.UrlDecode(file.Path.AbsolutePath)) });
}
catch (ArgumentException)
{
var error = new Error
{
Title = "Ошибка обработки картинки",
Message = $"Картинка не была добавлена: \"{HttpUtility.UrlDecode(file.Name)}\"",
Severity = ErrorSeverity.Error
};
_ = await WeakReferenceMessenger.Default.Send(new ErrorMessage(new ErrorViewModel(error)));
}
}
IsImagesEmpty = Images.Count == 0;
}
[RelayCommand]
private void DeleteImage(ImageViewModel image)
{
Images.Remove(image);
IsImagesEmpty = Images.Count == 0;
}
private bool CanEnterPoint() => !string.IsNullOrEmpty(Name);
[RelayCommand (CanExecute = nameof(CanEnterPoint))]
private void EnterPoint()
{
var point = new Point
{
Name = Name,
Description = Description,
Images = Images.Select(e => e.GetImage()).ToList()
};
WeakReferenceMessenger.Default.Send(new NewPointDone(new PointViewModel(point)));
}
[RelayCommand]
private static void CancelEnterPoint(Window w)
{
w.Close();
}
// Visual properties
[ObservableProperty]
private bool _isImagesEmpty = true;
}
-225
View File
@@ -1,225 +0,0 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:GazpromApp.ViewModels"
xmlns:enums="using:GazpromApp.Enums"
x:Name="Window"
mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="600"
Width="1000" Height="600"
x:Class="GazpromApp.Views.EditEquipmentDialog"
x:DataType="vm:EditEquipmentDialogViewModel"
Title="Редактирование/просмотр оборудования"
Icon="/Assets/ic_fluent_table_edit_24_filled (Custom).png"
WindowStartupLocation="CenterOwner"
Closing="Window_OnClosing"
Closed="Window_OnClosed">
<Design.DataContext>
<vm:EditEquipmentDialogViewModel/>
</Design.DataContext>
<Window.Resources>
<!-- ReSharper disable Xaml.RedundantResource -->
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="BackgroundBrush" Color="#f0f0f0"/>
<SolidColorBrush x:Key="BorderBrush" Color="#d3d3d3"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="BackgroundBrush" Color="#101010"/>
<SolidColorBrush x:Key="BorderBrush" Color="#303030"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
<!-- ReSharper restore Xaml.RedundantResource -->
<enums:PeriodConverter x:Key="PeriodConverter"/>
</Window.Resources>
<Grid RowDefinitions="70,150,*,Auto" ColumnDefinitions="*,100,220" x:Name="Root">
<TextBlock Grid.Column="0" Grid.Row="0" FontSize="28" Margin="20,4,0,4"
Text="{Binding Name}"
IsVisible="{Binding !IsNameEditing}"/>
<TextBox Grid.Column="0" Grid.Row="0" Margin="12,12,0,4"
Text="{Binding Name}"
IsVisible="{Binding IsNameEditing}"/>
<Button Grid.Column="1" Grid.Row="0" HorizontalAlignment="Center" Margin="10"
Command="{Binding EditNameCommand}">
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_edit_24_filled (Custom).png"/>
</Button>
<TextBlock Grid.Column="0" Grid.Row="1" Margin="20,4,0,4"
Text="{Binding Description}"
IsVisible="{Binding !IsDescriptionEditing}"/>
<TextBox Grid.Column="0" Grid.Row="1" Margin="12,4,0,4" AcceptsReturn="True" TextWrapping="Wrap"
Text="{Binding Description}"
IsVisible="{Binding IsDescriptionEditing}"/>
<Button Grid.Column="1" Grid.Row="1" HorizontalAlignment="Center" Margin="10"
Command="{Binding EditDescriptionCommand}">
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_edit_24_filled (Custom).png"/>
</Button>
<Panel Grid.Row="0" Grid.RowSpan="2" Grid.Column="2" HorizontalAlignment="Center">
<ScrollViewer HorizontalAlignment="Center">
<StackPanel>
<ItemsRepeater HorizontalAlignment="Center"
ItemsSource="{Binding Images}">
<ItemsRepeater.Layout>
<UniformGridLayout Orientation="Horizontal" MaximumRowsOrColumns="1"/>
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="vm:ImageViewModel">
<Border Margin="4" CornerRadius="4" Background="LightGray">
<Grid Margin="2" Width="200" Height="200" Background="LightGray"
ColumnDefinitions="*,20,4,20,8" RowDefinitions="8,20,*">
<Image Stretch="Uniform" Width="200" Height="200" Grid.RowSpan="3" Grid.ColumnSpan="5"
Source="{Binding FileName}" />
<Button Grid.Row="1" Grid.Column="1" Width="20" Height="20"
Command="{Binding #Root.((vm:EditEquipmentDialogViewModel)DataContext).ViewImageCommand}"
CommandParameter="{Binding .}">
<Image Width="16" Height="16" Source="avares://GazpromApp/Assets/ic_fluent_eye_show_24_filled (Custom) 16.png"/>
</Button>
<Button Grid.Row="1" Grid.Column="3" Width="20" Height="20"
Command="{Binding #Root.((vm:EditEquipmentDialogViewModel)DataContext).DeleteImageCommand}"
CommandParameter="{Binding .}">
<Image Width="16" Height="16" Source="avares://GazpromApp/Assets/ic_fluent_delete_24_filled (Custom) 16.png"/>
</Button>
</Grid>
</Border>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" IsVisible="{Binding !IsImagesEmpty}"
Command="{Binding AddImageCommand}"
CommandParameter="{Binding #Window}">
<Image Width="24" Source="avares://GazpromApp/Assets/ic_fluent_camera_add_24_filled (Custom).png"/>
</Button>
</StackPanel>
</ScrollViewer>
<Button HorizontalAlignment="Center" VerticalAlignment="Center"
IsVisible="{Binding IsImagesEmpty}"
Command="{Binding AddImageCommand}"
CommandParameter="{Binding #Window}">
<Image Width="24" Source="avares://GazpromApp/Assets/ic_fluent_camera_add_24_filled (Custom).png"/>
</Button>
</Panel>
<TabControl Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="2">
<TabItem Header="Тех. осмотры">
<ScrollViewer>
<StackPanel>
<ItemsRepeater HorizontalAlignment="Stretch"
ItemsSource="{Binding Inspections}">
<ItemsRepeater.Layout>
<StackLayout Orientation="Vertical" Spacing="8"/>
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="vm:InspectionViewModel">
<Border CornerRadius="4" BorderThickness="1"
Background="{DynamicResource BackgroundBrush}"
BorderBrush="{DynamicResource BorderBrush}">
<StackPanel Orientation="Vertical">
<Panel>
<TextBlock Margin="12,6,6,6" VerticalAlignment="Center"
IsVisible="{Binding !IsEditing}"
Text="{Binding Name}" FontSize="22"/>
<TextBox Height="35" Margin="12,14,84,6" FontSize="18"
IsVisible="{Binding IsEditing}"
Text="{Binding Name}"/>
<Button HorizontalAlignment="Right" Margin="0,8,20,0"
Command="{Binding #Root.((vm:EditEquipmentDialogViewModel)DataContext).EditInspectionCommand}"
CommandParameter="{Binding .}">
<Image Width="24" Source="avares://GazpromApp/Assets/ic_fluent_edit_24_filled (Custom).png"/>
</Button>
</Panel>
<Grid ColumnDefinitions="Auto, Auto, Auto, Auto, Auto, *" Margin="8">
<TextBlock Margin="10,0,0,0" Text="Дата проведения: " FontSize="18" VerticalAlignment="Center"/>
<DatePicker Grid.Column="1" VerticalAlignment="Center"
SelectedDate="{Binding InspectionDate}"/>
<TextBlock Grid.Column="2" Margin="16,0,0,0" Text="Период: " FontSize="18" VerticalAlignment="Center"/>
<NumericUpDown Grid.Column="3" AllowSpin="True" Width="120" VerticalAlignment="Center"
Value="{Binding PeriodValue}"
Minimum="0"/>
<ComboBox Grid.Column="4" Width="100" VerticalAlignment="Center" Margin="4,0,0,0"
ItemsSource="{Binding #Root.((vm:EditEquipmentDialogViewModel)DataContext).AllPeriods}"
SelectedItem="{Binding PeriodType, Mode=TwoWay}"
DisplayMemberBinding="{Binding ., Converter={StaticResource PeriodConverter}}"/>
<Button Grid.Column="5" Margin="0,0,12,0" HorizontalAlignment="Right" VerticalAlignment="Center"
Command="{Binding #Root.((vm:EditEquipmentDialogViewModel)DataContext).DeleteInspectionCommand}"
CommandParameter="{Binding .}">
<Image Width="24" Source="avares://GazpromApp/Assets/ic_fluent_delete_24_filled (Custom).png"/>
</Button>
</Grid>
</StackPanel>
</Border>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
<Button HorizontalAlignment="Center" Margin="10" Width="30" Height="30"
Command="{Binding AddInspectionCommand}">
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_add_24_filled (Custom).png"/>
</Button>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem Header="Свойства">
<ScrollViewer>
<StackPanel>
<TreeView ItemsSource="{Binding Properties}">
<TreeView.DataTemplates>
<TreeDataTemplate DataType="{x:Type vm:PropertyViewModel}"
ItemsSource="{Binding Properties}">
<Grid ColumnDefinitions="150,*,Auto,Auto,Auto">
<TextBlock Grid.Column="0" FontSize="18" VerticalAlignment="Center"
IsVisible="{Binding !IsEditing}"
Text="{Binding Name}"/>
<TextBox Grid.Column="0"
IsVisible="{Binding IsEditing}"
Text="{Binding Name}"/>
<TextBlock Grid.Column="1" FontSize="18" VerticalAlignment="Center"
IsVisible="{Binding !IsEditing}"
Text="{Binding Value}"/>
<TextBox Grid.Column="1"
IsVisible="{Binding IsEditing}"
Text="{Binding Value}"/>
<Button Grid.Column="2" Width="30" Height="30" Margin="4" VerticalAlignment="Center"
Command="{Binding #Root.((vm:EditEquipmentDialogViewModel)DataContext).AddPropertyCommand}"
CommandParameter="{Binding .}">
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_add_24_filled (Custom).png"/>
</Button>
<Button Grid.Column="3" Width="30" Height="30" Margin="4" VerticalAlignment="Center"
Command="{Binding #Root.((vm:EditEquipmentDialogViewModel)DataContext).EditPropertyCommand}"
CommandParameter="{Binding .}">
<Panel>
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_edit_24_filled (Custom).png"
IsVisible="{Binding !IsEditing}"/>
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_save_24_filled (Custom).png"
IsVisible="{Binding IsEditing}"/>
</Panel>
</Button>
<Button Grid.Column="4" Width="30" Height="30" Margin="4" VerticalAlignment="Center"
Command="{Binding #Root.((vm:EditEquipmentDialogViewModel)DataContext).DeletePropertyCommand}"
CommandParameter="{Binding .}">
<Image Height="24" Width="24" Source="avares://GazpromApp/Assets/ic_fluent_delete_24_filled (Custom).png"/>
</Button>
</Grid>
</TreeDataTemplate>
</TreeView.DataTemplates>
</TreeView>
<Button HorizontalAlignment="Center" Margin="10" Width="30" Height="30"
Command="{Binding AddPropertySimpleCommand}">
<Image Height="24" Width="24" Source="avares://GazpromApp/Assets/ic_fluent_add_24_filled (Custom).png"/>
</Button>
</StackPanel>
</ScrollViewer>
</TabItem>
</TabControl>
<Button Grid.Column="0" Grid.Row="3" Margin="8" Content="Отменить"
Command="{Binding CancelEditCommand}"
CommandParameter="{Binding #Window}"/>
<Button Grid.Column="2" Grid.Row="3" Margin="8" Content="Сохранить" HorizontalAlignment="Right"
Command="{Binding CompleteEditCommand}"/>
</Grid>
</Window>
-57
View File
@@ -1,57 +0,0 @@
using System;
using Avalonia.Controls;
using CommunityToolkit.Mvvm.Messaging;
using GazpromApp.Messages;
using GazpromApp.ViewModels;
namespace GazpromApp.Views;
public partial class EditEquipmentDialog : Window
{
public EditEquipmentDialog()
{
InitializeComponent();
if (Design.IsDesignMode)
return;
// view image
WeakReferenceMessenger.Default.Register<EditEquipmentDialog, ViewImageMessage>(this, static (w, m) =>
{
var dialog = new ImageView
{
DataContext = m.Image
};
m.Reply(dialog.ShowDialog<ImageViewModel?>(w));
});
// error handling
WeakReferenceMessenger.Default.Register<EditEquipmentDialog, ErrorMessage>(this, static (w, m) =>
{
var dialog = new ErrorView
{
DataContext = m.Error
};
m.Reply(dialog.ShowDialog<ErrorViewModel?>(w));
});
// complete editing equipment
WeakReferenceMessenger.Default.Register<EditEquipmentDialog, EditEquipmentDone>(this, static (w, m) =>
{
w.Close(m.Equipment);
});
}
private void Window_OnClosing(object? sender, WindowClosingEventArgs e)
{
if (DataContext is EditEquipmentDialogViewModel { IsClosed: false } vm)
vm.CancelEditCommand.Execute(this);
}
private void Window_OnClosed(object? sender, EventArgs e)
{
WeakReferenceMessenger.Default.Unregister<ViewImageMessage>(this);
WeakReferenceMessenger.Default.Unregister<ErrorMessage>(this);
WeakReferenceMessenger.Default.Unregister<EditEquipmentDone>(this);
}
}
+135
View File
@@ -0,0 +1,135 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:GazpromApp.ViewModels"
xmlns:views="using:GazpromApp.Views"
xmlns:icons="using:Material.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="GazpromApp.Views.EditEquipmentView"
x:DataType="vm:EditEquipmentViewModel">
<Design.DataContext>
<vm:EditEquipmentViewModel/>
</Design.DataContext>
<Grid RowDefinitions="70,150,*,Auto" ColumnDefinitions="*,100,220" x:Name="Root">
<Grid.Styles>
<Style Selector="Button.empty">
<Setter Property="IsVisible" Value="True" />
</Style>
<Style Selector="Button.not-empty">
<Setter Property="IsVisible" Value="False" />
</Style>
</Grid.Styles>
<TextBlock Grid.Column="0" Grid.Row="0" FontSize="28" Margin="20,4"
Text="{Binding Name, FallbackValue='Название'}"
IsVisible="{Binding !IsNameEditing, FallbackValue=true}"/>
<TextBox Grid.Column="0" Grid.Row="0" FontSize="28" Margin="20, 4"
Text="{Binding Name, FallbackValue='Название'}"
IsVisible="{Binding IsNameEditing, FallbackValue=false}"/>
<Button Grid.Column="1" Grid.Row="0" HorizontalAlignment="Center" Margin="10" Width="40" Height="40"
Command="{Binding EditNameCommand}">
<icons:MaterialIcon Kind="Edit" Width="24" Height="24"/>
</Button>
<TextBlock Grid.Column="0" Grid.Row="1" Margin="20,4"
Text="{Binding Description, FallbackValue='Описание'}"
IsVisible="{Binding !IsDescriptionEditing, FallbackValue=true}"/>
<TextBox Grid.Column="0" Grid.Row="1" Margin="20,4" AcceptsReturn="True" TextWrapping="Wrap"
Text="{Binding Description, FallbackValue='Название'}"
IsVisible="{Binding IsDescriptionEditing, FallbackValue=false}"/>
<Button Grid.Column="1" Grid.Row="1" HorizontalAlignment="Center" Margin="10" Width="40" Height="40"
Command="{Binding EditDescriptionCommand}">
<icons:MaterialIcon Kind="Edit" Width="24" Height="24"/>
</Button>
<Panel Grid.Row="0" Grid.RowSpan="2" Grid.Column="2" HorizontalAlignment="Center">
<ScrollViewer HorizontalAlignment="Center">
<StackPanel>
<ItemsRepeater HorizontalAlignment="Center"
ItemsSource="{Binding Images}">
<ItemsRepeater.Layout>
<UniformGridLayout Orientation="Horizontal" MaximumRowsOrColumns="1"/>
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="vm:ImageViewModel">
<Border Margin="4" CornerRadius="4" Background="LightGray">
<Grid Margin="2" Width="200" Height="200" Background="LightGray"
ColumnDefinitions="*,32,4,32,8" RowDefinitions="8,32,*">
<Image Stretch="Uniform" Width="200" Height="200" Grid.RowSpan="3" Grid.ColumnSpan="5"
Source="{Binding FileName}" />
<Button Grid.Row="1" Grid.Column="1" Width="32" Height="32"
Command="{Binding ViewImageCommand}">
<icons:MaterialIcon Kind="PrintPreview" Width="24" Height="24"/>
</Button>
<Button Grid.Row="1" Grid.Column="3" Width="32" Height="32"
Command="{Binding DeleteImageCommand}">
<icons:MaterialIcon Kind="Delete" Width="24" Height="24"/>
</Button>
</Grid>
</Border>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Width="40" Height="40"
Classes.empty="{Binding !!Images.Count}"
Classes.not-empty="{Binding !Images.Count}"
Command="{Binding AddImageCommand}">
<icons:MaterialIcon Kind="CameraPlus" Width="24" Height="24"/>
</Button>
</StackPanel>
</ScrollViewer>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Width="40" Height="40"
Classes.empty="{Binding !Images.Count}"
Classes.not-empty="{Binding !!Images.Count}"
Command="{Binding AddImageCommand}">
<icons:MaterialIcon Kind="CameraPlus" Width="24" Height="24"/>
</Button>
</Panel>
<TabControl Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3">
<TabItem Header="Свойства">
<ScrollViewer>
<StackPanel>
<TreeView ItemsSource="{Binding Properties}">
<TreeView.DataTemplates>
<TreeDataTemplate DataType="{x:Type vm:PropertyViewModel}"
ItemsSource="{Binding Properties}">
<views:PropertyView/>
</TreeDataTemplate>
</TreeView.DataTemplates>
</TreeView>
<Button HorizontalAlignment="Center" Margin="4" Width="32" Height="32"
Command="{Binding AddPropertyCommand}">
<icons:MaterialIcon Kind="Add" Width="24" Height="24"/>
</Button>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem Header="Инспекции">
<ScrollViewer>
<StackPanel>
<TreeView ItemsSource="{Binding Inspections}">
<TreeView.DataTemplates>
<TreeDataTemplate DataType="{x:Type vm:InspectionViewModel}"
ItemsSource="{Binding Inspection}">
<views:InspectionView/>
</TreeDataTemplate>
</TreeView.DataTemplates>
</TreeView>
<Button HorizontalAlignment="Center" Margin="4" Width="32" Height="32"
Command="{Binding AddInspectionCommand}">
<icons:MaterialIcon Kind="Add" Width="24" Height="24"/>
</Button>
</StackPanel>
</ScrollViewer>
</TabItem>
</TabControl>
<Button Grid.Column="0" Grid.Row="3" Margin="8" Content="Отменить" HorizontalAlignment="Left"
Command="{Binding CancelEditCommand}"/>
<Button Grid.Column="2" Grid.Row="3" Margin="8" Content="Сохранить" HorizontalAlignment="Right"
Command="{Binding CompleteEditCommand}"/>
</Grid>
</UserControl>
+13
View File
@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace GazpromApp.Views;
public partial class EditEquipmentView : UserControl
{
public EditEquipmentView()
{
InitializeComponent();
}
}
-220
View File
@@ -1,220 +0,0 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:GazpromApp.ViewModels"
x:Name="Window"
mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="600"
Width="1000" Height="600"
x:Class="GazpromApp.Views.EditPointDialog"
x:DataType="vm:EditPointDialogViewModel"
Title="Редактирование/просмотр объекта"
Icon="/Assets/ic_fluent_edit_24_filled (Custom).png"
WindowStartupLocation="CenterOwner"
Closing="Window_OnClosing"
Closed="Window_OnClosed">
<Design.DataContext>
<vm:EditPointDialogViewModel/>
</Design.DataContext>
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="BackgroundBrush" Color="#f0f0f0"/>
<SolidColorBrush x:Key="BorderBrush" Color="#d3d3d3"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<!-- ReSharper disable once Xaml.RedundantResource -->
<SolidColorBrush x:Key="BackgroundBrush" Color="#101010"/>
<!-- ReSharper disable once Xaml.RedundantResource -->
<SolidColorBrush x:Key="BorderBrush" Color="#303030"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid RowDefinitions="70,150,*,Auto" ColumnDefinitions="*,100,220" x:Name="Root">
<TextBlock Grid.Column="0" Grid.Row="0" FontSize="28" Margin="20,4,0,4"
Text="{Binding Name}"
IsVisible="{Binding !IsNameEditing}"/>
<TextBox Grid.Column="0" Grid.Row="0" Margin="12,12,0,4"
Text="{Binding Name}"
IsVisible="{Binding IsNameEditing}"/>
<Button Grid.Column="1" Grid.Row="0" HorizontalAlignment="Center" Margin="10"
Command="{Binding EditNameCommand}">
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_edit_24_filled (Custom).png"/>
</Button>
<TextBlock Grid.Column="0" Grid.Row="1" Margin="20,4,0,4"
Text="{Binding Description}"
IsVisible="{Binding !IsDescriptionEditing}"/>
<TextBox Grid.Column="0" Grid.Row="1" Margin="12,4,0,4" AcceptsReturn="True" TextWrapping="Wrap"
Text="{Binding Description}"
IsVisible="{Binding IsDescriptionEditing}"/>
<Button Grid.Column="1" Grid.Row="1" HorizontalAlignment="Center" Margin="10"
Command="{Binding EditDescriptionCommand}">
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_edit_24_filled (Custom).png"/>
</Button>
<Panel Grid.Row="0" Grid.RowSpan="2" Grid.Column="2" HorizontalAlignment="Center">
<ScrollViewer HorizontalAlignment="Center">
<StackPanel>
<ItemsRepeater HorizontalAlignment="Center"
ItemsSource="{Binding Images}">
<ItemsRepeater.Layout>
<UniformGridLayout Orientation="Horizontal" MaximumRowsOrColumns="1"/>
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="vm:ImageViewModel">
<Border Margin="4" CornerRadius="4" Background="LightGray">
<Grid Margin="2" Width="200" Height="200" Background="LightGray"
ColumnDefinitions="*,20,4,20,8" RowDefinitions="8,20,*">
<Image Stretch="Uniform" Width="200" Height="200" Grid.RowSpan="3" Grid.ColumnSpan="5"
Source="{Binding FileName}" />
<Button Grid.Row="1" Grid.Column="1" Width="20" Height="20"
Command="{Binding #Root.((vm:EditPointDialogViewModel)DataContext).ViewImageCommand}"
CommandParameter="{Binding .}">
<Image Width="16" Height="16" Source="avares://GazpromApp/Assets/ic_fluent_eye_show_24_filled (Custom) 16.png"/>
</Button>
<Button Grid.Row="1" Grid.Column="3" Width="20" Height="20"
Command="{Binding #Root.((vm:EditPointDialogViewModel)DataContext).DeleteImageCommand}"
CommandParameter="{Binding .}">
<Image Width="16" Height="16" Source="avares://GazpromApp/Assets/ic_fluent_delete_24_filled (Custom) 16.png"/>
</Button>
</Grid>
</Border>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" IsVisible="{Binding !IsImagesEmpty}"
Command="{Binding AddImageCommand}"
CommandParameter="{Binding #Window}">
<Image Width="24" Source="avares://GazpromApp/Assets/ic_fluent_camera_add_24_filled (Custom).png"/>
</Button>
</StackPanel>
</ScrollViewer>
<Button HorizontalAlignment="Center" VerticalAlignment="Center"
IsVisible="{Binding IsImagesEmpty}"
Command="{Binding AddImageCommand}"
CommandParameter="{Binding #Window}">
<Image Width="24" Source="avares://GazpromApp/Assets/ic_fluent_camera_add_24_filled (Custom).png"/>
</Button>
</Panel>
<TabControl Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="2">
<TabItem Header="Оборудование">
<ScrollViewer>
<StackPanel>
<ItemsRepeater
ItemsSource="{Binding Equipment}">
<ItemsRepeater.Layout>
<StackLayout Orientation="Vertical"/>
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="vm:EquipmentViewModel">
<Expander HorizontalAlignment="Stretch" Margin="0,4,0,4"
Background="{DynamicResource BackgroundBrush}"
BorderBrush="{DynamicResource BorderBrush}">
<Expander.Header>
<Grid Height="54" HorizontalAlignment="Stretch"
ColumnDefinitions="52, 300, *, Auto">
<Image Height="50" Width="50" Margin="0,2,2,2" HorizontalAlignment="Center" Stretch="Uniform"
Source="{Binding Images[0].FileName, FallbackValue=null}"/>
<TextBlock Grid.Column="1" FontSize="20" VerticalAlignment="Center" Margin="4,0,0,0"
Text="{Binding Name}"/>
<TextBlock Grid.Column="2" FontSize="15" TextWrapping="Wrap" VerticalAlignment="Center" HorizontalAlignment="Stretch"
Text="{Binding Description}"/>
</Grid>
</Expander.Header>
<Grid ColumnDefinitions="Auto, *, Auto, Auto">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock FontSize="18" Text="Ближайший ТО: "/>
<TextBlock FontSize="18" Text="{Binding NearestInspection}"/>
<TextBlock FontSize="18" Text="Свойств: " Margin="18, 0,0,0"/>
<TextBlock FontSize="18" Text="{Binding Properties.Count}"/>
</StackPanel>
<Button Grid.Column="2"
Command="{Binding #Root.((vm:EditPointDialogViewModel)DataContext).EditEquipmentCommand}"
CommandParameter="{Binding .}"
Margin="4,0,4,0">
<Image Source="avares://GazpromApp/Assets/ic_fluent_edit_24_filled (Custom).png"/>
</Button>
<Button Grid.Column="3"
Command="{Binding #Root.((vm:EditPointDialogViewModel)DataContext).DeleteEquipmentCommand}"
CommandParameter="{Binding .}"
Margin="4,0,4,0">
<Image Source="avares://GazpromApp/Assets/ic_fluent_delete_24_filled (Custom).png"/>
</Button>
</Grid>
</Expander>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
<Button Height="30" Width="30" HorizontalAlignment="Center" Margin="0,20,0,0"
Command="{Binding AddEquipmentCommand}">
<Image Height="24" Width="24" Source="avares://GazpromApp/Assets/ic_fluent_add_24_filled (Custom).png"/>
</Button>
</StackPanel>
</ScrollViewer>
</TabItem>
<TabItem Header="Свойства">
<ScrollViewer>
<StackPanel>
<TreeView ItemsSource="{Binding Properties}">
<TreeView.DataTemplates>
<TreeDataTemplate DataType="{x:Type vm:PropertyViewModel}"
ItemsSource="{Binding Properties}">
<Grid ColumnDefinitions="150,*,Auto,Auto,Auto">
<TextBlock Grid.Column="0" FontSize="18" VerticalAlignment="Center"
IsVisible="{Binding !IsEditing}"
Text="{Binding Name}"/>
<TextBox Grid.Column="0"
IsVisible="{Binding IsEditing}"
Text="{Binding Name}"/>
<TextBlock Grid.Column="1" FontSize="18" VerticalAlignment="Center"
IsVisible="{Binding !IsEditing}"
Text="{Binding Value}"/>
<TextBox Grid.Column="1"
IsVisible="{Binding IsEditing}"
Text="{Binding Value}"/>
<Button Grid.Column="2" Width="30" Height="30" Margin="4" VerticalAlignment="Center"
Command="{Binding #Root.((vm:EditPointDialogViewModel)DataContext).AddPropertyCommand}"
CommandParameter="{Binding .}">
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_add_24_filled (Custom).png"/>
</Button>
<Button Grid.Column="3" Width="30" Height="30" Margin="4" VerticalAlignment="Center"
Command="{Binding #Root.((vm:EditPointDialogViewModel)DataContext).EditPropertyCommand}"
CommandParameter="{Binding .}">
<Panel>
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_edit_24_filled (Custom).png"
IsVisible="{Binding !IsEditing}"/>
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_save_24_filled (Custom).png"
IsVisible="{Binding IsEditing}"/>
</Panel>
</Button>
<Button Grid.Column="4" Width="30" Height="30" Margin="4" VerticalAlignment="Center"
Command="{Binding #Root.((vm:EditPointDialogViewModel)DataContext).DeletePropertyCommand}"
CommandParameter="{Binding .}">
<Image Height="24" Width="24" Source="avares://GazpromApp/Assets/ic_fluent_delete_24_filled (Custom).png"/>
</Button>
</Grid>
</TreeDataTemplate>
</TreeView.DataTemplates>
</TreeView>
<Button HorizontalAlignment="Center" Margin="10" Width="30" Height="30"
Command="{Binding AddPropertySimpleCommand}">
<Image Height="24" Width="24" Source="avares://GazpromApp/Assets/ic_fluent_add_24_filled (Custom).png"/>
</Button>
</StackPanel>
</ScrollViewer>
</TabItem>
</TabControl>
<Button Grid.Column="0" Grid.Row="3" Margin="8" Content="Отменить"
Command="{Binding CancelEditCommand}"
CommandParameter="{Binding #Window}"/>
<Button Grid.Column="2" Grid.Row="3" Margin="8" Content="Сохранить" HorizontalAlignment="Right"
Command="{Binding CompleteEditCommand}"/>
</Grid>
</Window>
-119
View File
@@ -1,119 +0,0 @@
using System;
using Avalonia.Controls;
using CommunityToolkit.Mvvm.Messaging;
using GazpromApp.Messages;
using GazpromApp.ViewModels;
namespace GazpromApp.Views;
public partial class EditPointDialog : Window
{
public EditPointDialog()
{
InitializeComponent();
if (Design.IsDesignMode)
return;
// view image
WeakReferenceMessenger.Default.Register<EditPointDialog, ViewImageMessage>(this, static (w, m) =>
{
var dialog = new ImageView
{
DataContext = m.Image
};
m.Reply(dialog.ShowDialog<ImageViewModel?>(w));
});
// error
WeakReferenceMessenger.Default.Register<EditPointDialog, ErrorMessage>(this, static (w, m) =>
{
var dialog = new ErrorView
{
DataContext = m.Error
};
m.Reply(dialog.ShowDialog<ErrorViewModel?>(w));
});
// new equipment
WeakReferenceMessenger.Default.Register<EditPointDialog, NewEquipmentMessage>(this, (w, m) =>
{
WeakReferenceMessenger.Default.Unregister<ErrorMessage>(this);
var dialog = new NewEquipmentDialog
{
DataContext = new NewEquipmentDialogViewModel()
};
m.Reply(dialog.ShowDialog<EquipmentViewModel?>(w));
});
// edit equipment
WeakReferenceMessenger.Default.Register<EditPointDialog, EditEquipmentMessage>(this, (w, m) =>
{
WeakReferenceMessenger.Default.Unregister<ViewImageMessage>(this);
WeakReferenceMessenger.Default.Unregister<ErrorMessage>(this);
var dialog = new EditEquipmentDialog
{
DataContext = new EditEquipmentDialogViewModel(m.Equipment)
};
m.Reply(dialog.ShowDialog<EquipmentViewModel?>(w));
});
// re registering error when new equipment done
WeakReferenceMessenger.Default.Register<EditPointDialog, NewEquipmentDone>(this, (_, _) =>
{
if (!WeakReferenceMessenger.Default.IsRegistered<ErrorMessage>(this))
WeakReferenceMessenger.Default.Register<EditPointDialog, ErrorMessage>(this, static (w, m) =>
{
var dialog = new ErrorView
{
DataContext = m.Error
};
m.Reply(dialog.ShowDialog<ErrorViewModel?>(w));
});
});
// re registering view image and error view
WeakReferenceMessenger.Default.Register<EditPointDialog, EditEquipmentDone>(this, (_, _) =>
{
if (!WeakReferenceMessenger.Default.IsRegistered<ViewImageMessage>(this))
WeakReferenceMessenger.Default.Register<EditPointDialog, ViewImageMessage>(this, static (w, m) =>
{
var dialog = new ImageView
{
DataContext = m.Image
};
m.Reply(dialog.ShowDialog<ImageViewModel?>(w));
});
if (!WeakReferenceMessenger.Default.IsRegistered<ErrorMessage>(this))
WeakReferenceMessenger.Default.Register<EditPointDialog, ErrorMessage>(this, static (w, m) =>
{
var dialog = new ErrorView
{
DataContext = m.Error
};
m.Reply(dialog.ShowDialog<ErrorViewModel?>(w));
});
});
// complete editing point
WeakReferenceMessenger.Default.Register<EditPointDialog, EditPointDone>(this, static (w, m) =>
{
w.Close(m.Point);
});
}
private void Window_OnClosing(object? sender, WindowClosingEventArgs e)
{
if (DataContext is EditPointDialogViewModel { IsClosed: false } vm)
vm.CancelEditCommand.Execute(this);
}
private void Window_OnClosed(object? sender, EventArgs e)
{
WeakReferenceMessenger.Default.Unregister<ViewImageMessage>(this);
WeakReferenceMessenger.Default.Unregister<ErrorMessage>(this);
WeakReferenceMessenger.Default.Unregister<NewEquipmentMessage>(this);
WeakReferenceMessenger.Default.Unregister<EditEquipmentMessage>(this);
WeakReferenceMessenger.Default.Unregister<EditPointDone>(this);
}
}
+112
View File
@@ -0,0 +1,112 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:GazpromApp.ViewModels"
xmlns:views="using:GazpromApp.Views"
xmlns:icons="using:Material.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="500"
x:Class="GazpromApp.Views.EditPointView"
x:DataType="vm:EditPointViewModel">
<Design.DataContext>
<vm:EditPointViewModel/>
</Design.DataContext>
<Grid RowDefinitions="70,150,*,Auto" ColumnDefinitions="*,100,220" x:Name="Root">
<Grid.Styles>
<Style Selector="Button.empty">
<Setter Property="IsVisible" Value="True" />
</Style>
<Style Selector="Button.not-empty">
<Setter Property="IsVisible" Value="False" />
</Style>
</Grid.Styles>
<TextBlock Grid.Column="0" Grid.Row="0" FontSize="28" Margin="20,4"
Text="{Binding Name, FallbackValue='Название'}"
IsVisible="{Binding !IsNameEditing, FallbackValue=true}"/>
<TextBox Grid.Column="0" Grid.Row="0" FontSize="28" Margin="20, 4"
Text="{Binding Name, FallbackValue='Название'}"
IsVisible="{Binding IsNameEditing, FallbackValue=false}"/>
<Button Grid.Column="1" Grid.Row="0" HorizontalAlignment="Center" Margin="10" Width="40" Height="40"
Command="{Binding EditNameCommand}">
<icons:MaterialIcon Kind="Edit" Width="24" Height="24"/>
</Button>
<TextBlock Grid.Column="0" Grid.Row="1" Margin="20,4"
Text="{Binding Description, FallbackValue='Описание'}"
IsVisible="{Binding !IsDescriptionEditing, FallbackValue=true}"/>
<TextBox Grid.Column="0" Grid.Row="1" Margin="20,4" AcceptsReturn="True" TextWrapping="Wrap"
Text="{Binding Description, FallbackValue='Название'}"
IsVisible="{Binding IsDescriptionEditing, FallbackValue=false}"/>
<Button Grid.Column="1" Grid.Row="1" HorizontalAlignment="Center" Margin="10" Width="40" Height="40"
Command="{Binding EditDescriptionCommand}">
<icons:MaterialIcon Kind="Edit" Width="24" Height="24"/>
</Button>
<Panel Grid.Row="0" Grid.RowSpan="2" Grid.Column="2" HorizontalAlignment="Center">
<ScrollViewer HorizontalAlignment="Center">
<StackPanel>
<ItemsRepeater HorizontalAlignment="Center"
ItemsSource="{Binding Images}">
<ItemsRepeater.Layout>
<UniformGridLayout Orientation="Horizontal" MaximumRowsOrColumns="1"/>
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="vm:ImageViewModel">
<Border Margin="4" CornerRadius="4" Background="LightGray">
<Grid Margin="2" Width="200" Height="200" Background="LightGray"
ColumnDefinitions="*,32,4,32,8" RowDefinitions="8,32,*">
<Image Stretch="Uniform" Width="200" Height="200" Grid.RowSpan="3" Grid.ColumnSpan="5"
Source="{Binding FileName}" />
<Button Grid.Row="1" Grid.Column="1" Width="32" Height="32"
Command="{Binding ViewImageCommand}">
<icons:MaterialIcon Kind="PrintPreview" Width="24" Height="24"/>
</Button>
<Button Grid.Row="1" Grid.Column="3" Width="32" Height="32"
Command="{Binding DeleteImageCommand}">
<icons:MaterialIcon Kind="Delete" Width="24" Height="24"/>
</Button>
</Grid>
</Border>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Width="40" Height="40"
Classes.empty="{Binding !!Images.Count}"
Classes.not-empty="{Binding !Images.Count}"
Command="{Binding AddImageCommand}">
<icons:MaterialIcon Kind="CameraPlus" Width="24" Height="24"/>
</Button>
</StackPanel>
</ScrollViewer>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Width="40" Height="40"
Classes.empty="{Binding !Images.Count}"
Classes.not-empty="{Binding !!Images.Count}"
Command="{Binding AddImageCommand}">
<icons:MaterialIcon Kind="CameraPlus" Width="24" Height="24"/>
</Button>
</Panel>
<ScrollViewer Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3">
<StackPanel>
<TextBlock Text="Свойства:" FontSize="24" Margin="24,0"/>
<TreeView ItemsSource="{Binding Properties}">
<TreeView.DataTemplates>
<TreeDataTemplate DataType="{x:Type vm:PropertyViewModel}"
ItemsSource="{Binding Properties}">
<views:PropertyView/>
</TreeDataTemplate>
</TreeView.DataTemplates>
</TreeView>
<Button HorizontalAlignment="Center" Margin="4" Width="32" Height="32"
Command="{Binding AddPropertyCommand}">
<icons:MaterialIcon Kind="Add" Width="24" Height="24"/>
</Button>
</StackPanel>
</ScrollViewer>
<Button Grid.Column="0" Grid.Row="3" Margin="8" Content="Отменить" HorizontalAlignment="Left"
Command="{Binding CancelEditCommand}"/>
<Button Grid.Column="2" Grid.Row="3" Margin="8" Content="Сохранить" HorizontalAlignment="Right"
Command="{Binding CompleteEditCommand}"/>
</Grid>
</UserControl>
+13
View File
@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace GazpromApp.Views;
public partial class EditPointView : UserControl
{
public EditPointView()
{
InitializeComponent();
}
}
+38
View File
@@ -0,0 +1,38 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:GazpromApp.ViewModels"
xmlns:icons="using:Material.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="500"
x:Class="GazpromApp.Views.EquipmentView"
x:DataType="vm:EquipmentViewModel">
<Expander>
<Expander.Header>
<Grid ColumnDefinitions="Auto, Auto, *, Auto, Auto">
<icons:MaterialIcon Kind="Location" Margin="0,0,8,0" Width="24" Height="24"/>
<TextBlock Grid.Column="1" VerticalAlignment="Center" TextWrapping="WrapWithOverflow"
Text="{Binding Name}"/>
<Button Width="32" Grid.Column="3" Margin="0,0,8,0"
Command="{Binding AddEquipmentCommand}">
<icons:MaterialIcon Kind="Add" Width="24" Height="24"/>
</Button>
<Button Width="32" Grid.Column="4" Margin="0,0,8,0"
Command="{Binding RemoveEquipmentCommand}">
<icons:MaterialIcon Kind="Delete" Width="24" Height="24"/>
</Button>
</Grid>
</Expander.Header>
<Grid RowDefinitions="Auto,Auto,Auto" RowSpacing="4" Margin="8,4,8,2">
<TextBlock Text="{Binding Description}" />
<StackPanel Grid.Row="1" Orientation="Horizontal">
<TextBlock Text="Оборудований: "/>
<TextBlock Text="{Binding Equipments.Count}"/>
</StackPanel>
<StackPanel Grid.Row="2" Orientation="Horizontal">
<TextBlock Text="Свойств: "/>
<TextBlock Text="{Binding Properties.Count}"/>
</StackPanel>
</Grid>
</Expander>
</UserControl>
+13
View File
@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace GazpromApp.Views;
public partial class EquipmentView : UserControl
{
public EquipmentView()
{
InitializeComponent();
}
}
+55
View File
@@ -0,0 +1,55 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:GazpromApp.ViewModels"
xmlns:icons="using:Material.Icons.Avalonia"
xmlns:enums="using:GazpromApp.Enums"
mc:Ignorable="d" d:DesignWidth="930" d:DesignHeight="450"
x:Class="GazpromApp.Views.InspectionView"
x:DataType="vm:InspectionViewModel">
<Design.DataContext>
<vm:InspectionViewModel/>
</Design.DataContext>
<UserControl.Resources>
<enums:PeriodConverter x:Key="PeriodConverter"/>
</UserControl.Resources>
<Border CornerRadius="4" BorderThickness="1">
<StackPanel Orientation="Vertical">
<Grid ColumnDefinitions="*, Auto">
<TextBlock Grid.Column="0" Margin="12,6" FontSize="22" Height="50"
IsVisible="{Binding !IsEditing}"
Text="{Binding Name}"/>
<TextBox Grid.Column="0" Margin="12,6" FontSize="18" Height="50"
IsVisible="{Binding IsEditing}"
Text="{Binding Name}"/>
<Button Grid.Column="1" HorizontalAlignment="Right" Margin="12,6" Height="40" Width="40"
Command="{Binding EditInspectionCommand}">
<icons:MaterialIcon Kind="Edit" Width="24" Height="24"/>
</Button>
</Grid>
<Grid ColumnDefinitions="*, Auto">
<WrapPanel VerticalAlignment="Top">
<TextBlock Margin="10,2" Text="Дата проведения:"
FontSize="18" VerticalAlignment="Center"/>
<DatePicker FontSize="18" VerticalAlignment="Center"
SelectedDate="{Binding InspectionDate}"/>
<TextBlock Margin="10,2" Text="Период:" FontSize="18" VerticalAlignment="Center"/>
<NumericUpDown AllowSpin="True" Width="120" Margin="10,2" FontSize="18"
Value="{Binding PeriodValue}"
Minimum="0"/>
<ComboBox Width="110" VerticalAlignment="Center" Margin="10,2" FontSize="18"
ItemsSource="{Binding AllPeriods}"
SelectedItem="{Binding PeriodType, Mode=TwoWay}"
DisplayMemberBinding="{Binding .,
Converter={StaticResource PeriodConverter}}"/>
</WrapPanel>
<Button Grid.Column="1" Margin="12,6" Height="40" Width="40"
Command="{Binding RemoveInspectionCommand}">
<icons:MaterialIcon Kind="Delete" Width="24" Height="24"/>
</Button>
</Grid>
</StackPanel>
</Border>
</UserControl>
+13
View File
@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace GazpromApp.Views;
public partial class InspectionView : UserControl
{
public InspectionView()
{
InitializeComponent();
}
}
+31 -72
View File
@@ -4,43 +4,27 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:anim="https://github.com/whistyun/AnimatedImage.Avalonia" xmlns:anim="https://github.com/whistyun/AnimatedImage.Avalonia"
xmlns:vm="using:GazpromApp.ViewModels" xmlns:vm="using:GazpromApp.ViewModels"
xmlns:views="using:GazpromApp.Views"
xmlns:icons="using:Material.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="1024" d:DesignHeight="600" mc:Ignorable="d" d:DesignWidth="1024" d:DesignHeight="600"
Width="1024" Height="600"
x:Class="GazpromApp.Views.MainWindow" x:Class="GazpromApp.Views.MainWindow"
x:DataType="vm:MainWindowViewModel" x:DataType="vm:MainWindowViewModel"
x:Name="Window" x:Name="Window"
Icon="/Assets/gazpromapp.ico" Icon="/Assets/gazpromapp.ico"
Title="GazpromApp" Title="GazpromApp"
WindowStartupLocation="CenterScreen"> WindowState="Maximized"
Closing="Window_OnClosing">
<Design.DataContext> <Design.DataContext>
<!-- This only sets the DataContext for the previewer in an IDE,
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
<vm:MainWindowViewModel/> <vm:MainWindowViewModel/>
</Design.DataContext> </Design.DataContext>
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="BackgroundBrush" Color="#f0f0f0"/>
<SolidColorBrush x:Key="BorderBrush" Color="#d3d3d3"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<!-- ReSharper disable once Xaml.RedundantResource -->
<SolidColorBrush x:Key="BackgroundBrush" Color="#101010"/>
<!-- ReSharper disable once Xaml.RedundantResource -->
<SolidColorBrush x:Key="BorderBrush" Color="#303030"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Window.Resources>
<DockPanel x:Name="Root"> <DockPanel x:Name="Root">
<Menu DockPanel.Dock="Top"> <Menu DockPanel.Dock="Top">
<MenuItem Command="{Binding AddPointCommand}"> <MenuItem Command="{Binding SyncDbCommand}">
<MenuItem.Header> <MenuItem.Header>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_home_add_24_filled (Custom).png"/> <icons:MaterialIcon Kind="Sync" Width="24" Height="24"/>
<TextBlock Margin="8,0,0,0" Text="Добавить" VerticalAlignment="Center"/> <TextBlock Margin="8,0,0,0" Text="Сохранить и обновить" VerticalAlignment="Center"/>
</StackPanel> </StackPanel>
</MenuItem.Header> </MenuItem.Header>
</MenuItem> </MenuItem>
@@ -48,7 +32,7 @@
CommandParameter="{Binding #Window}"> CommandParameter="{Binding #Window}">
<MenuItem.Header> <MenuItem.Header>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_arrow_export_ltr_24_filled (Custom).png"/> <icons:MaterialIcon Kind="Upload" Width="24" Height="24"/>
<TextBlock Margin="8,0,0,0" Text="Экспорт" VerticalAlignment="Center"/> <TextBlock Margin="8,0,0,0" Text="Экспорт" VerticalAlignment="Center"/>
</StackPanel> </StackPanel>
</MenuItem.Header> </MenuItem.Header>
@@ -57,66 +41,41 @@
CommandParameter="{Binding #Window}"> CommandParameter="{Binding #Window}">
<MenuItem.Header> <MenuItem.Header>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_arrow_import_24_filled (Custom).png"/> <icons:MaterialIcon Kind="Download" Width="24" Height="24"/>
<TextBlock Margin="8,0,0,0" Text="Импорт" VerticalAlignment="Center"/> <TextBlock Margin="8,0,0,0" Text="Импорт" VerticalAlignment="Center"/>
</StackPanel> </StackPanel>
</MenuItem.Header> </MenuItem.Header>
</MenuItem> </MenuItem>
</Menu> </Menu>
<Grid DockPanel.Dock="Top" HorizontalAlignment="Stretch" <Grid DockPanel.Dock="Top" HorizontalAlignment="Stretch"
ColumnDefinitions="*,*,100"> ColumnDefinitions="*,2,2*">
<Grid.RowDefinitions> <ScrollViewer>
<RowDefinition Height="*"/>
<RowDefinition MaxHeight="50"/>
</Grid.RowDefinitions>
<ScrollViewer Grid.ColumnSpan="3">
<StackPanel Orientation="Vertical"> <StackPanel Orientation="Vertical">
<ItemsRepeater ItemsSource="{Binding Points}"> <TreeView ItemsSource="{Binding Points}"
<ItemsRepeater.Layout> SelectionChanged="TreeView_OnSelectionChanged">
<StackLayout Orientation="Vertical"/> <TreeView.DataTemplates>
</ItemsRepeater.Layout> <TreeDataTemplate DataType="{x:Type vm:PointViewModel}"
<ItemsRepeater.ItemTemplate> ItemsSource="{Binding Equipment}">
<DataTemplate DataType="vm:PointViewModel"> <views:PointView Padding="0,0,20,0"/>
<Border CornerRadius="4" BorderThickness="1" Margin="6" </TreeDataTemplate>
Background="{DynamicResource BackgroundBrush}" <TreeDataTemplate DataType="{x:Type vm:EquipmentViewModel}"
BorderBrush="{DynamicResource BorderBrush}"> ItemsSource="{Binding Equipments}">
<Grid Margin="6"> <views:EquipmentView Padding="0,0,20,0"/>
<Grid.ColumnDefinitions> </TreeDataTemplate>
<ColumnDefinition Width="Auto" MaxWidth="300"/> </TreeView.DataTemplates>
<ColumnDefinition /> </TreeView>
<ColumnDefinition Width="Auto" /> <Button Classes="Accent" Height="32" Width="32" Margin="4" HorizontalAlignment="Center"
<ColumnDefinition Width="Auto" /> Command="{Binding AddPointCommand}">
</Grid.ColumnDefinitions> <icons:MaterialIcon Kind="Add" Width="24" Height="24"/>
<TextBlock FontSize="24" Margin="4" VerticalAlignment="Center" </Button>
Grid.Column="0"
Text="{Binding Name}"/>
<TextBlock Margin="4" VerticalAlignment="Center"
Grid.Column="1"
Text="{Binding Description}"/>
<Button Grid.Column="2"
Command="{Binding #Root.((vm:MainWindowViewModel)DataContext).EditPointCommand}"
CommandParameter="{Binding .}"
Margin="4">
<Image Source="avares://GazpromApp/Assets/ic_fluent_edit_24_filled (Custom).png"/>
</Button>
<Button Grid.Column="3"
Command="{Binding #Root.((vm:MainWindowViewModel)DataContext).RemovePointCommand}"
CommandParameter="{Binding .}"
Margin="4">
<Image Source="avares://GazpromApp/Assets/ic_fluent_delete_24_filled (Custom).png"/>
</Button>
</Grid>
</Border>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</StackPanel> </StackPanel>
</ScrollViewer> </ScrollViewer>
<GridSplitter Background="#b6b6b6" Grid.Column="1" ResizeDirection="Columns"/>
<ContentControl Grid.Column="2" Content="{Binding SelectedItemViewModel}"/>
<Image Width="100" Height="100" VerticalAlignment="Center" <Image Width="100" Height="100" VerticalAlignment="Center"
IsVisible="{Binding IsLoading}" IsVisible="{Binding IsLoading}"
HorizontalAlignment="Center" HorizontalAlignment="Center"
Grid.Row="0" Grid.Column="0" Grid.Row="0" Grid.Column="0"
Grid.ColumnSpan="3" Grid.RowSpan="2"
anim:ImageBehavior.AnimatedSource="avares://GazpromApp/Assets/loading.gif"/> anim:ImageBehavior.AnimatedSource="avares://GazpromApp/Assets/loading.gif"/>
</Grid> </Grid>
</DockPanel> </DockPanel>
+71 -15
View File
@@ -1,4 +1,10 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using GazpromApp.Messages; using GazpromApp.Messages;
using GazpromApp.ViewModels; using GazpromApp.ViewModels;
@@ -7,29 +13,79 @@ namespace GazpromApp.Views;
public partial class MainWindow : Window public partial class MainWindow : Window
{ {
private bool _canClose = false;
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent();
if (Design.IsDesignMode) if (Design.IsDesignMode)
return; return;
WeakReferenceMessenger.Default.Register<MainWindow, RequestImageMessage>(this, HandleImageSelection);
WeakReferenceMessenger.Default.Register<MainWindow, ViewImageMessage>(this, HandleImageViewer);
WeakReferenceMessenger.Default.Register<MainWindow, ErrorMessage>(this, HandleErrorViewer);
WeakReferenceMessenger.Default.Register<MainWindow, SaveChangesResult>(this, HandleSave);
}
private static void HandleImageSelection(MainWindow sender, RequestImageMessage msg)
{
var files = sender.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
AllowMultiple = true,
Title = "Выберите одну или несколько картинок",
FileTypeFilter = [FilePickerFileTypes.ImageAll]
});
msg.Reply(files);
}
WeakReferenceMessenger.Default.Register<MainWindow, NewPointMessage>(this, static (w, m) => private static void HandleImageViewer(MainWindow sender, ViewImageMessage msg)
{
var dialog = new ImageView
{ {
var dialog = new NewPointDialog DataContext = msg.Image
{ };
DataContext = new NewPointDialogViewModel() msg.Reply(dialog.ShowDialog<ImageViewModel?>(sender));
}; }
m.Reply(dialog.ShowDialog<PointViewModel?>(w));
}); private static void HandleErrorViewer(MainWindow sender, ErrorMessage msg)
{
WeakReferenceMessenger.Default.Register<MainWindow, EditPointMessage>(this, static (w, m) => var dialog = new ErrorView
{ {
var dialog = new EditPointDialog DataContext = msg.Error
{ };
DataContext = new EditPointDialogViewModel(m.Point) msg.Reply(dialog.ShowDialog<ErrorViewModel?>(sender));
}; }
m.Reply(dialog.ShowDialog<PointViewModel?>(w));
}); private void TreeView_OnSelectionChanged(object? sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count > 0)
WeakReferenceMessenger.Default.Send(new SelectionChangedMessage((ViewModelBase)e.AddedItems[0]!));
}
private void HandleSave(object sender, SaveChangesResult msg)
{
if (msg.Cancel) return;
if (msg.Save)
((MainWindowViewModel)DataContext!).SyncDbCommand.Execute(null);
ForceClose();
}
private void ForceClose()
{
_canClose = true;
Close();
}
private void Window_OnClosing(object? sender, WindowClosingEventArgs e)
{
if (_canClose) return;
if (!((MainWindowViewModel)DataContext!).CanSync) return;
var dialog = new SaveChangesView
{
DataContext = new SaveChangesViewModel()
};
dialog.ShowDialog<SaveChangesViewModel?>(this);
e.Cancel = true;
} }
} }
-76
View File
@@ -1,76 +0,0 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:GazpromApp.ViewModels"
x:Name="Window"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="500"
Width="500" Height="500"
x:Class="GazpromApp.Views.NewEquipmentDialog"
x:DataType="vm:NewEquipmentDialogViewModel"
Title="Создание нового оборудования"
Icon="/Assets/ic_fluent_table_add_24_filled (Custom).png"
WindowStartupLocation="CenterOwner"
Closed="Window_OnClosed">
<Design.DataContext>
<vm:NewEquipmentDialogViewModel/>
</Design.DataContext>
<Grid Margin="12" x:Name="Root">
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="120"/>
<ColumnDefinition MinWidth="300"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="50"/>
<RowDefinition MaxHeight="100"/>
<RowDefinition MinHeight="200" Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Margin="8" Text="Название: "/>
<TextBlock Grid.Column="0" Grid.Row="1" Margin="8" Text="Описание: "/>
<TextBlock Grid.Column="0" Grid.Row="2" Margin="8" Text="Изображение: "/>
<TextBox Grid.Column="1" Grid.Row="0" Margin="8"
Text="{Binding Name}"/>
<TextBox Grid.Column="1" Grid.Row="1" Margin="8" AcceptsReturn="True" TextWrapping="Wrap"
Text="{Binding Description}"/>
<Panel Grid.Column="1" Grid.Row="2" Margin="8" IsVisible="{Binding !IsImagesEmpty}">
<ScrollViewer>
<StackPanel>
<ItemsRepeater ItemsSource="{Binding Images}" HorizontalAlignment="Center">
<ItemsRepeater.Layout>
<UniformGridLayout Orientation="Horizontal" MaximumRowsOrColumns="1"/>
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="vm:ImageViewModel">
<Border Margin="4" CornerRadius="4" Background="LightGray">
<Grid Margin="2" Width="200" Height="200" Background="LightGray"
ColumnDefinitions="*,20,8" RowDefinitions="8,20,*">
<Image Stretch="Uniform" Width="200" Height="200" Grid.RowSpan="3" Grid.ColumnSpan="3"
Source="{Binding FileName}" />
<Button Grid.Row="1" Grid.Column="1" Width="20" Height="20"
Command="{Binding #Root.((vm:NewEquipmentDialogViewModel)DataContext).DeleteImageCommand}"
CommandParameter="{Binding .}">
<Image Width="16" Height="16" Source="avares://GazpromApp/Assets/ic_fluent_delete_24_filled (Custom) 16.png"/>
</Button>
</Grid>
</Border>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
<Button HorizontalAlignment="Center" IsVisible="True"
Command="{Binding AddImageCommand}"
CommandParameter="{Binding #Window}">
<Image Width="24" Source="avares://GazpromApp/Assets/ic_fluent_camera_add_24_filled (Custom).png"/>
</Button>
</StackPanel>
</ScrollViewer>
</Panel>
<Button Grid.Column="0" Grid.Row="3" Margin="8" Content="Отменить"
Command="{Binding CancelEnterEquipmentCommand}"
CommandParameter="{Binding #Window}"/>
<Button Grid.Column="1" Grid.Row="3" Margin="8" Content="Добавить" HorizontalAlignment="Right"
Command="{Binding EnterEquipmentCommand}"/>
</Grid>
</Window>
-37
View File
@@ -1,37 +0,0 @@
using System;
using Avalonia.Controls;
using CommunityToolkit.Mvvm.Messaging;
using GazpromApp.Messages;
using GazpromApp.ViewModels;
namespace GazpromApp.Views;
public partial class NewEquipmentDialog : Window
{
public NewEquipmentDialog()
{
InitializeComponent();
// done entering new equipment
WeakReferenceMessenger.Default.Register<NewEquipmentDialog, NewEquipmentDone>(this, static (w, m) =>
{
w.Close(m.Equipment);
});
// register to work with errors
WeakReferenceMessenger.Default.Register<NewEquipmentDialog, ErrorMessage>(this, static (w, m) =>
{
var dialog = new ErrorView
{
DataContext = m.Error
};
m.Reply(dialog.ShowDialog<ErrorViewModel?>(w));
});
}
private void Window_OnClosed(object? sender, EventArgs e)
{
WeakReferenceMessenger.Default.Unregister<NewEquipmentDone>(this);
WeakReferenceMessenger.Default.Unregister<ErrorMessage>(this);
}
}
-82
View File
@@ -1,82 +0,0 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:GazpromApp.ViewModels"
x:Name="Window"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="500"
Width="500" Height="500"
x:Class="GazpromApp.Views.NewPointDialog"
x:DataType="vm:NewPointDialogViewModel"
Title="Создание нового объекта"
Icon="/Assets/ic_fluent_home_add_24_filled (Custom).png"
WindowStartupLocation="CenterOwner"
Closed="Window_OnClosed">
<Design.DataContext>
<vm:NewPointDialogViewModel/>
</Design.DataContext>
<Grid Margin="12" x:Name="Root">
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="120"/>
<ColumnDefinition MinWidth="300"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="50"/>
<RowDefinition MaxHeight="100"/>
<RowDefinition MinHeight="200" Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Margin="8" Text="Название: "/>
<TextBlock Grid.Column="0" Grid.Row="1" Margin="8" Text="Описание: "/>
<TextBlock Grid.Column="0" Grid.Row="2" Margin="8" Text="Изображение: "/>
<TextBox Grid.Column="1" Grid.Row="0" Margin="8"
Text="{Binding Name}"/>
<TextBox Grid.Column="1" Grid.Row="1" Margin="8" AcceptsReturn="True" TextWrapping="Wrap"
Text="{Binding Description}"/>
<Panel Grid.Column="1" Grid.Row="2" Margin="8" IsVisible="{Binding !IsImagesEmpty}">
<ScrollViewer>
<StackPanel>
<ItemsRepeater ItemsSource="{Binding Images}" HorizontalAlignment="Center">
<ItemsRepeater.Layout>
<UniformGridLayout Orientation="Horizontal" MaximumRowsOrColumns="1"/>
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="vm:ImageViewModel">
<Border Margin="4" CornerRadius="4" Background="LightGray">
<Grid Margin="2" Width="200" Height="200" Background="LightGray"
ColumnDefinitions="*,20,8" RowDefinitions="8,20,*">
<Image Stretch="Uniform" Width="200" Height="200" Grid.RowSpan="3" Grid.ColumnSpan="3"
Source="{Binding FileName}" />
<Button Grid.Row="1" Grid.Column="1" Width="20" Height="20"
Command="{Binding #Root.((vm:NewPointDialogViewModel)DataContext).DeleteImageCommand}"
CommandParameter="{Binding .}">
<Image Width="16" Height="16" Source="avares://GazpromApp/Assets/ic_fluent_delete_24_filled (Custom) 16.png"/>
</Button>
</Grid>
</Border>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
<Button HorizontalAlignment="Center" IsVisible="True"
Command="{Binding AddImageCommand}"
CommandParameter="{Binding #Window}">
<Image Width="24" Source="avares://GazpromApp/Assets/ic_fluent_camera_add_24_filled (Custom).png"/>
</Button>
</StackPanel>
</ScrollViewer>
</Panel>
<Panel Grid.Column="1" Grid.Row="2" Margin="8"
IsVisible="{Binding IsImagesEmpty}">
<Button HorizontalAlignment="Center" IsVisible="True"
Command="{Binding AddImageCommand}"
CommandParameter="{Binding #Window}">
<Image Width="24" Source="avares://GazpromApp/Assets/ic_fluent_camera_add_24_filled (Custom).png"/>
</Button>
</Panel>
<Button Grid.Column="0" Grid.Row="3" Margin="8" Content="Отменить"
Command="{Binding CancelEnterPointCommand}"
CommandParameter="{Binding #Window}"/>
<Button Grid.Column="1" Grid.Row="3" Margin="8" Content="Добавить" HorizontalAlignment="Right"
Command="{Binding EnterPointCommand}"/>
</Grid>
</Window>
-36
View File
@@ -1,36 +0,0 @@
using System;
using Avalonia.Controls;
using CommunityToolkit.Mvvm.Messaging;
using GazpromApp.Messages;
using GazpromApp.ViewModels;
namespace GazpromApp.Views;
public partial class NewPointDialog : Window
{
public NewPointDialog()
{
InitializeComponent();
// done entering a new point
WeakReferenceMessenger.Default.Register<NewPointDialog, NewPointDone>(this, static (w, m) =>
{
w.Close(m.Point);
});
// register to work with errors
WeakReferenceMessenger.Default.Register<NewPointDialog, ErrorMessage>(this, static (w, m) =>
{
var dialog = new ErrorView
{
DataContext = m.Error
};
m.Reply(dialog.ShowDialog<ErrorViewModel?>(w));
});
}
private void Window_OnClosed(object? sender, EventArgs e)
{
WeakReferenceMessenger.Default.Unregister<ErrorMessage>(this);
}
}
+60
View File
@@ -0,0 +1,60 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:GazpromApp.ViewModels"
xmlns:views="using:GazpromApp.Views"
xmlns:icons="using:Material.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="500"
x:Class="GazpromApp.Views.PointView"
x:DataType="vm:PointViewModel">
<Expander>
<Expander.Header>
<Grid ColumnDefinitions="Auto, Auto, *, Auto, Auto">
<icons:MaterialIcon Kind="Location" Margin="0,0,8,0" Width="24" Height="24"/>
<TextBlock Grid.Column="1" VerticalAlignment="Center" TextWrapping="WrapWithOverflow"
Text="{Binding Name}"/>
<Button Width="32" Grid.Column="3" Margin="0,0,8,0"
Command="{Binding AddEquipmentCommand}">
<icons:MaterialIcon Kind="Add" Width="24" Height="24"/>
</Button>
<Button Width="32" Grid.Column="4" Margin="0,0,8,0"
Command="{Binding RemovePointCommand}">
<icons:MaterialIcon Kind="Delete" Width="24" Height="24"/>
</Button>
</Grid>
</Expander.Header>
<Grid RowDefinitions="Auto,Auto,Auto,Auto" RowSpacing="4" Margin="8,4,8,2">
<Grid.Styles>
<Style Selector="ItemsRepeater.empty">
<Setter Property="IsVisible" Value="True" />
</Style>
<Style Selector="ItemsRepeater.not-empty">
<Setter Property="IsVisible" Value="False" />
</Style>
</Grid.Styles>
<TextBlock Text="{Binding Description}"/>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<TextBlock Text="Оборудований: "/>
<TextBlock Text="{Binding Equipment.Count}"/>
</StackPanel>
<StackPanel Grid.Row="2" Orientation="Horizontal">
<TextBlock Text="Свойств: "/>
<TextBlock Text="{Binding Properties.Count}"/>
</StackPanel>
<ItemsRepeater Grid.Row="3" Margin="4,8"
ItemsSource="{Binding Images}"
Classes.empty="{Binding !!Images.Count}"
Classes.not-empty="{Binding !Images.Count}">
<ItemsRepeater.Layout>
<StackLayout Orientation="Horizontal" Spacing="4"/>
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="vm:ImageViewModel">
<Image Width="64" Height="64" Source="{Binding FileName}"/>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</Grid>
</Expander>
</UserControl>
+14
View File
@@ -0,0 +1,14 @@
using System.Windows.Input;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace GazpromApp.Views;
public partial class PointView : UserControl
{
public PointView()
{
InitializeComponent();
}
}
+43
View File
@@ -0,0 +1,43 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:GazpromApp.ViewModels"
xmlns:icons="using:Material.Icons.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="GazpromApp.Views.PropertyView"
x:DataType="vm:PropertyViewModel">
<Grid ColumnDefinitions="150,*,Auto,Auto,Auto">
<TextBlock Grid.Column="0" FontSize="18" VerticalAlignment="Center"
IsVisible="{Binding !IsEditing}"
Text="{Binding Name}"/>
<TextBox Grid.Column="0" FontSize="18"
IsVisible="{Binding IsEditing}"
Text="{Binding Name}"/>
<TextBlock Grid.Column="1" FontSize="18" VerticalAlignment="Center"
IsVisible="{Binding !IsEditing}"
Text="{Binding Value}"/>
<TextBox Grid.Column="1"
IsVisible="{Binding IsEditing}"
Text="{Binding Value}"/>
<Button Grid.Column="2" Width="32" Height="32" Margin="4" VerticalAlignment="Center"
Command="{Binding AddPropertyCommand}">
<icons:MaterialIcon Kind="Add" Width="24" Height="24"/>
</Button>
<Button Grid.Column="3" Width="32" Height="32" Margin="4" VerticalAlignment="Center"
Command="{Binding EditPropertyCommand}">
<Panel>
<icons:MaterialIcon Kind="Edit" Width="24" Height="24"
IsVisible="{Binding !IsEditing}"/>
<icons:MaterialIcon Kind="ContentSave" Width="24" Height="24"
IsVisible="{Binding IsEditing}"/>
</Panel>
</Button>
<Button Grid.Column="4" Width="32" Height="32" Margin="4" VerticalAlignment="Center"
Command="{Binding RemovePropertyCommand}">
<icons:MaterialIcon Kind="Delete" Width="24" Height="24"/>
</Button>
</Grid>
</UserControl>
+13
View File
@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace GazpromApp.Views;
public partial class PropertyView : UserControl
{
public PropertyView()
{
InitializeComponent();
}
}
+40
View File
@@ -0,0 +1,40 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="using:GazpromApp.ViewModels"
x:Name="Window"
mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="180"
Width="400" Height="180"
x:Class="GazpromApp.Views.SaveChangesView"
x:DataType="vm:SaveChangesViewModel"
Title="Не сохраненные данные"
Icon="/Assets/ic_fluent_error_circle_24_filled (1) (Custom).png"
WindowStartupLocation="CenterOwner"
Closing="Window_OnClosing"
Closed="Window_OnClosed">
<Grid x:Name="Root" Margin="16"
ColumnDefinitions="50, *" RowDefinitions="50, *, Auto">
<Image Grid.Row="0" Grid.Column="0"
Source="avares://GazpromApp/Assets/ic_fluent_info_24_filled (Custom).png"/>
<Panel Grid.Row="0" Grid.Column="1" Grid.RowSpan="2">
<StackPanel Margin="8">
<TextBlock Text="Есть несохраненные изменения." FontSize="20" MaxLines="2" TextWrapping="Wrap"/>
<TextBlock Text="Уверены что хотите закрыть?" MaxLines="3" TextWrapping="Wrap"/>
</StackPanel>
</Panel>
<Panel Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Spacing="8">
<Button Content="Не сохранять" Background="LightCoral"
Command="{Binding DontSaveCommand}"
CommandParameter="{Binding #Window}"/>
<Button Content="Отмена"
Command="{Binding CancelCommand}"
CommandParameter="{Binding #Window}"/>
<Button Content="Сохранить"
Command="{Binding SaveCommand}"
CommandParameter="{Binding #Window}"/>
</StackPanel>
</Panel>
</Grid>
</Window>
+26
View File
@@ -0,0 +1,26 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace GazpromApp.Views;
public partial class SaveChangesView : Window
{
public bool CanClose = false;
public SaveChangesView()
{
InitializeComponent();
}
private void Window_OnClosing(object? sender, WindowClosingEventArgs e)
{
if (CanClose) return;
e.Cancel = true;
}
private void Window_OnClosed(object? sender, EventArgs e)
{
}
}
@@ -1 +1 @@
ce571eaa8794cd8018cfc316b7aa3a875ff0192541a3e5a99ac1c0b1fe0464bc cc067bc255287b1def9594eac16771691c8ab80aebe0b1c73635a5ea9772fd91
Binary file not shown.
+7 -8
View File
@@ -7,16 +7,15 @@
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
using System;
using System.Reflection; using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("GazpromApp")] [assembly: AssemblyCompany("GazpromApp")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: AssemblyConfiguration("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+d8cb1c0597162160d03e7987cc85991c880988b8")] [assembly: AssemblyInformationalVersion("1.0.0+edae732facddad296bc2957b70d69e109c8df0dc")]
[assembly: System.Reflection.AssemblyProductAttribute("GazpromApp")] [assembly: AssemblyProduct("GazpromApp")]
[assembly: System.Reflection.AssemblyTitleAttribute("GazpromApp")] [assembly: AssemblyTitle("GazpromApp")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: AssemblyVersion("1.0.0.0")]
// Generated by the MSBuild WriteCodeFragment class. // Generated by the MSBuild WriteCodeFragment class.
@@ -1 +1 @@
77f531bfc5aeafe36631b408a11c11c294e011bb2a474f23c97785d02864a447 d5e1f758b4af1a11eec5b0ef10074d2fa0359670b43f632e44e63e702c71cb03
@@ -32,10 +32,13 @@ build_property.EnableCodeStyleSeverity =
[D:/RiderProjects/GazpromApp/App.axaml] [D:/RiderProjects/GazpromApp/App.axaml]
build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml
[D:/RiderProjects/GazpromApp/Views/EditEquipmentDialog.axaml] [D:/RiderProjects/GazpromApp/Views/EditEquipmentView.axaml]
build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml
[D:/RiderProjects/GazpromApp/Views/EditPointDialog.axaml] [D:/RiderProjects/GazpromApp/Views/EditPointView.axaml]
build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml
[D:/RiderProjects/GazpromApp/Views/EquipmentView.axaml]
build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml
[D:/RiderProjects/GazpromApp/Views/ErrorView.axaml] [D:/RiderProjects/GazpromApp/Views/ErrorView.axaml]
@@ -44,11 +47,17 @@ build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml
[D:/RiderProjects/GazpromApp/Views/ImageView.axaml] [D:/RiderProjects/GazpromApp/Views/ImageView.axaml]
build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml
[D:/RiderProjects/GazpromApp/Views/InspectionView.axaml]
build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml
[D:/RiderProjects/GazpromApp/Views/MainWindow.axaml] [D:/RiderProjects/GazpromApp/Views/MainWindow.axaml]
build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml
[D:/RiderProjects/GazpromApp/Views/NewEquipmentDialog.axaml] [D:/RiderProjects/GazpromApp/Views/PointView.axaml]
build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml
[D:/RiderProjects/GazpromApp/Views/NewPointDialog.axaml] [D:/RiderProjects/GazpromApp/Views/PropertyView.axaml]
build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml
[D:/RiderProjects/GazpromApp/Views/SaveChangesView.axaml]
build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml build_metadata.AdditionalFiles.SourceItemGroup = AvaloniaXaml
Binary file not shown.
@@ -203,3 +203,9 @@ D:\RiderProjects\GazpromApp\bin\Debug\net8.0\Microsoft.IO.RecyclableMemoryStream
D:\RiderProjects\GazpromApp\bin\Debug\net8.0\Avalonia.Controls.ItemsRepeater.dll D:\RiderProjects\GazpromApp\bin\Debug\net8.0\Avalonia.Controls.ItemsRepeater.dll
D:\RiderProjects\GazpromApp\bin\Debug\net8.0\AnimatedImage.Avalonia.dll D:\RiderProjects\GazpromApp\bin\Debug\net8.0\AnimatedImage.Avalonia.dll
D:\RiderProjects\GazpromApp\bin\Debug\net8.0\AnimatedImage.dll D:\RiderProjects\GazpromApp\bin\Debug\net8.0\AnimatedImage.dll
D:\RiderProjects\GazpromApp\bin\Debug\net8.0\Material.Avalonia.dll
D:\RiderProjects\GazpromApp\bin\Debug\net8.0\Material.Colors.dll
D:\RiderProjects\GazpromApp\bin\Debug\net8.0\Material.Ripple.dll
D:\RiderProjects\GazpromApp\bin\Debug\net8.0\Material.Styles.dll
D:\RiderProjects\GazpromApp\bin\Debug\net8.0\Material.Icons.dll
D:\RiderProjects\GazpromApp\bin\Debug\net8.0\Material.Icons.Avalonia.dll
+8
View File
@@ -86,6 +86,14 @@
"target": "Package", "target": "Package",
"version": "[8.2.1, )" "version": "[8.2.1, )"
}, },
"Material.Avalonia": {
"target": "Package",
"version": "[3.12.0, )"
},
"Material.Icons.Avalonia": {
"target": "Package",
"version": "[2.4.1, )"
},
"Microsoft.EntityFrameworkCore": { "Microsoft.EntityFrameworkCore": {
"target": "Package", "target": "Package",
"version": "[9.0.6, )" "version": "[9.0.6, )"
+1 -1
View File
@@ -18,8 +18,8 @@
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore\9.0.6\buildTransitive\net8.0\Microsoft.EntityFrameworkCore.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore\9.0.6\buildTransitive\net8.0\Microsoft.EntityFrameworkCore.props')" /> <Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore\9.0.6\buildTransitive\net8.0\Microsoft.EntityFrameworkCore.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore\9.0.6\buildTransitive\net8.0\Microsoft.EntityFrameworkCore.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.codeanalysis.analyzers\3.3.4\buildTransitive\Microsoft.CodeAnalysis.Analyzers.props" Condition="Exists('$(NuGetPackageRoot)microsoft.codeanalysis.analyzers\3.3.4\buildTransitive\Microsoft.CodeAnalysis.Analyzers.props')" /> <Import Project="$(NuGetPackageRoot)microsoft.codeanalysis.analyzers\3.3.4\buildTransitive\Microsoft.CodeAnalysis.Analyzers.props" Condition="Exists('$(NuGetPackageRoot)microsoft.codeanalysis.analyzers\3.3.4\buildTransitive\Microsoft.CodeAnalysis.Analyzers.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore.design\9.0.6\build\net8.0\Microsoft.EntityFrameworkCore.Design.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore.design\9.0.6\build\net8.0\Microsoft.EntityFrameworkCore.Design.props')" /> <Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore.design\9.0.6\build\net8.0\Microsoft.EntityFrameworkCore.Design.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore.design\9.0.6\build\net8.0\Microsoft.EntityFrameworkCore.Design.props')" />
<Import Project="$(NuGetPackageRoot)harfbuzzsharp.nativeassets.webassembly\8.3.1.1\buildTransitive\netstandard1.0\HarfBuzzSharp.NativeAssets.WebAssembly.props" Condition="Exists('$(NuGetPackageRoot)harfbuzzsharp.nativeassets.webassembly\8.3.1.1\buildTransitive\netstandard1.0\HarfBuzzSharp.NativeAssets.WebAssembly.props')" />
<Import Project="$(NuGetPackageRoot)avalonia\11.3.2\buildTransitive\Avalonia.props" Condition="Exists('$(NuGetPackageRoot)avalonia\11.3.2\buildTransitive\Avalonia.props')" /> <Import Project="$(NuGetPackageRoot)avalonia\11.3.2\buildTransitive\Avalonia.props" Condition="Exists('$(NuGetPackageRoot)avalonia\11.3.2\buildTransitive\Avalonia.props')" />
<Import Project="$(NuGetPackageRoot)harfbuzzsharp.nativeassets.webassembly\8.3.1.1\buildTransitive\netstandard1.0\HarfBuzzSharp.NativeAssets.WebAssembly.props" Condition="Exists('$(NuGetPackageRoot)harfbuzzsharp.nativeassets.webassembly\8.3.1.1\buildTransitive\netstandard1.0\HarfBuzzSharp.NativeAssets.WebAssembly.props')" />
<Import Project="$(NuGetPackageRoot)avaloniaui.diagnosticssupport\2.0.4\buildTransitive\AvaloniaUI.DiagnosticsSupport.props" Condition="Exists('$(NuGetPackageRoot)avaloniaui.diagnosticssupport\2.0.4\buildTransitive\AvaloniaUI.DiagnosticsSupport.props')" /> <Import Project="$(NuGetPackageRoot)avaloniaui.diagnosticssupport\2.0.4\buildTransitive\AvaloniaUI.DiagnosticsSupport.props" Condition="Exists('$(NuGetPackageRoot)avaloniaui.diagnosticssupport\2.0.4\buildTransitive\AvaloniaUI.DiagnosticsSupport.props')" />
</ImportGroup> </ImportGroup>
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> <PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
+2 -2
View File
@@ -8,9 +8,9 @@
<Import Project="$(NuGetPackageRoot)microsoft.extensions.options\9.0.6\buildTransitive\net8.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\9.0.6\buildTransitive\net8.0\Microsoft.Extensions.Options.targets')" /> <Import Project="$(NuGetPackageRoot)microsoft.extensions.options\9.0.6\buildTransitive\net8.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\9.0.6\buildTransitive\net8.0\Microsoft.Extensions.Options.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.6\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.6\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets')" /> <Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.6\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.6\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.codeanalysis.analyzers\3.3.4\buildTransitive\Microsoft.CodeAnalysis.Analyzers.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.codeanalysis.analyzers\3.3.4\buildTransitive\Microsoft.CodeAnalysis.Analyzers.targets')" /> <Import Project="$(NuGetPackageRoot)microsoft.codeanalysis.analyzers\3.3.4\buildTransitive\Microsoft.CodeAnalysis.Analyzers.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.codeanalysis.analyzers\3.3.4\buildTransitive\Microsoft.CodeAnalysis.Analyzers.targets')" />
<Import Project="$(NuGetPackageRoot)harfbuzzsharp.nativeassets.webassembly\8.3.1.1\buildTransitive\netstandard1.0\HarfBuzzSharp.NativeAssets.WebAssembly.targets" Condition="Exists('$(NuGetPackageRoot)harfbuzzsharp.nativeassets.webassembly\8.3.1.1\buildTransitive\netstandard1.0\HarfBuzzSharp.NativeAssets.WebAssembly.targets')" />
<Import Project="$(NuGetPackageRoot)communitytoolkit.mvvm\8.2.1\buildTransitive\netstandard2.1\CommunityToolkit.Mvvm.targets" Condition="Exists('$(NuGetPackageRoot)communitytoolkit.mvvm\8.2.1\buildTransitive\netstandard2.1\CommunityToolkit.Mvvm.targets')" />
<Import Project="$(NuGetPackageRoot)avalonia.buildservices\0.0.31\buildTransitive\Avalonia.BuildServices.targets" Condition="Exists('$(NuGetPackageRoot)avalonia.buildservices\0.0.31\buildTransitive\Avalonia.BuildServices.targets')" /> <Import Project="$(NuGetPackageRoot)avalonia.buildservices\0.0.31\buildTransitive\Avalonia.BuildServices.targets" Condition="Exists('$(NuGetPackageRoot)avalonia.buildservices\0.0.31\buildTransitive\Avalonia.BuildServices.targets')" />
<Import Project="$(NuGetPackageRoot)avalonia\11.3.2\buildTransitive\Avalonia.targets" Condition="Exists('$(NuGetPackageRoot)avalonia\11.3.2\buildTransitive\Avalonia.targets')" /> <Import Project="$(NuGetPackageRoot)avalonia\11.3.2\buildTransitive\Avalonia.targets" Condition="Exists('$(NuGetPackageRoot)avalonia\11.3.2\buildTransitive\Avalonia.targets')" />
<Import Project="$(NuGetPackageRoot)harfbuzzsharp.nativeassets.webassembly\8.3.1.1\buildTransitive\netstandard1.0\HarfBuzzSharp.NativeAssets.WebAssembly.targets" Condition="Exists('$(NuGetPackageRoot)harfbuzzsharp.nativeassets.webassembly\8.3.1.1\buildTransitive\netstandard1.0\HarfBuzzSharp.NativeAssets.WebAssembly.targets')" />
<Import Project="$(NuGetPackageRoot)communitytoolkit.mvvm\8.2.1\buildTransitive\netstandard2.1\CommunityToolkit.Mvvm.targets" Condition="Exists('$(NuGetPackageRoot)communitytoolkit.mvvm\8.2.1\buildTransitive\netstandard2.1\CommunityToolkit.Mvvm.targets')" />
</ImportGroup> </ImportGroup>
</Project> </Project>
+97
View File
@@ -541,6 +541,46 @@
} }
} }
}, },
"Material.Avalonia/3.12.0": {
"type": "package",
"dependencies": {
"Avalonia": "11.1.0"
},
"compile": {
"lib/net8.0/Material.Avalonia.dll": {},
"lib/net8.0/Material.Colors.dll": {},
"lib/net8.0/Material.Ripple.dll": {},
"lib/net8.0/Material.Styles.dll": {}
},
"runtime": {
"lib/net8.0/Material.Avalonia.dll": {},
"lib/net8.0/Material.Colors.dll": {},
"lib/net8.0/Material.Ripple.dll": {},
"lib/net8.0/Material.Styles.dll": {}
}
},
"Material.Icons/2.4.1": {
"type": "package",
"compile": {
"lib/netstandard2.0/Material.Icons.dll": {}
},
"runtime": {
"lib/netstandard2.0/Material.Icons.dll": {}
}
},
"Material.Icons.Avalonia/2.4.1": {
"type": "package",
"dependencies": {
"Avalonia": "11.0.0",
"Material.Icons": "2.4.1"
},
"compile": {
"lib/netstandard2.0/Material.Icons.Avalonia.dll": {}
},
"runtime": {
"lib/netstandard2.0/Material.Icons.Avalonia.dll": {}
}
},
"MicroCom.Runtime/0.11.0": { "MicroCom.Runtime/0.11.0": {
"type": "package", "type": "package",
"compile": { "compile": {
@@ -2484,6 +2524,53 @@
"logo.png" "logo.png"
] ]
}, },
"Material.Avalonia/3.12.0": {
"sha512": "CtYyhPnP9+9UfKRGHjJGe6isxVjaM1F4cvjUHa0r7qtTskBjHNJAIJOtRMLwqD8/kl5zx1ZhS9Jtuuloqxg6Yg==",
"type": "package",
"path": "material.avalonia/3.12.0",
"files": [
".nupkg.metadata",
".signature.p7s",
"FavIcon.png",
"README.md",
"lib/net8.0/Material.Avalonia.dll",
"lib/net8.0/Material.Colors.dll",
"lib/net8.0/Material.Ripple.dll",
"lib/net8.0/Material.Styles.dll",
"lib/netstandard2.0/Material.Avalonia.dll",
"lib/netstandard2.0/Material.Colors.dll",
"lib/netstandard2.0/Material.Ripple.dll",
"lib/netstandard2.0/Material.Styles.dll",
"material.avalonia.3.12.0.nupkg.sha512",
"material.avalonia.nuspec"
]
},
"Material.Icons/2.4.1": {
"sha512": "5/8ekF4GXqpluBF+kPfv3TytBpV5Z+h4CUU5iNCDC7+A9hPQvtn08ZUjMUXtcRGxGyfScHYDqzshzTvYiPTCdA==",
"type": "package",
"path": "material.icons/2.4.1",
"files": [
".nupkg.metadata",
".signature.p7s",
"README.md",
"lib/netstandard2.0/Material.Icons.dll",
"material.icons.2.4.1.nupkg.sha512",
"material.icons.nuspec"
]
},
"Material.Icons.Avalonia/2.4.1": {
"sha512": "bJZzJCHfZDBg33ZyiSxvexMs2qMGkkv1XEgkAJkqLK9I8WNIUGLCnXcjoBrpSh2Sd2ytoD1IEjV72Zy54St3zA==",
"type": "package",
"path": "material.icons.avalonia/2.4.1",
"files": [
".nupkg.metadata",
".signature.p7s",
"README.md",
"lib/netstandard2.0/Material.Icons.Avalonia.dll",
"material.icons.avalonia.2.4.1.nupkg.sha512",
"material.icons.avalonia.nuspec"
]
},
"MicroCom.Runtime/0.11.0": { "MicroCom.Runtime/0.11.0": {
"sha512": "MEnrZ3UIiH40hjzMDsxrTyi8dtqB5ziv3iBeeU4bXsL/7NLSal9F1lZKpK+tfBRnUoDSdtcW3KufE4yhATOMCA==", "sha512": "MEnrZ3UIiH40hjzMDsxrTyi8dtqB5ziv3iBeeU4bXsL/7NLSal9F1lZKpK+tfBRnUoDSdtcW3KufE4yhATOMCA==",
"type": "package", "type": "package",
@@ -4750,6 +4837,8 @@
"Avalonia.Themes.Fluent >= 11.3.2", "Avalonia.Themes.Fluent >= 11.3.2",
"AvaloniaUI.DiagnosticsSupport >= 2.0.4", "AvaloniaUI.DiagnosticsSupport >= 2.0.4",
"CommunityToolkit.Mvvm >= 8.2.1", "CommunityToolkit.Mvvm >= 8.2.1",
"Material.Avalonia >= 3.12.0",
"Material.Icons.Avalonia >= 2.4.1",
"Microsoft.EntityFrameworkCore >= 9.0.6", "Microsoft.EntityFrameworkCore >= 9.0.6",
"Microsoft.EntityFrameworkCore.Design >= 9.0.6", "Microsoft.EntityFrameworkCore.Design >= 9.0.6",
"Microsoft.EntityFrameworkCore.Sqlite >= 9.0.6" "Microsoft.EntityFrameworkCore.Sqlite >= 9.0.6"
@@ -4841,6 +4930,14 @@
"target": "Package", "target": "Package",
"version": "[8.2.1, )" "version": "[8.2.1, )"
}, },
"Material.Avalonia": {
"target": "Package",
"version": "[3.12.0, )"
},
"Material.Icons.Avalonia": {
"target": "Package",
"version": "[2.4.1, )"
},
"Microsoft.EntityFrameworkCore": { "Microsoft.EntityFrameworkCore": {
"target": "Package", "target": "Package",
"version": "[9.0.6, )" "version": "[9.0.6, )"
+4 -1
View File
@@ -1,6 +1,6 @@
{ {
"version": 2, "version": 2,
"dgSpecHash": "tG1MV/2SQjY=", "dgSpecHash": "dxfLR4PjleQ=",
"success": true, "success": true,
"projectFilePath": "D:\\RiderProjects\\GazpromApp\\GazpromApp.csproj", "projectFilePath": "D:\\RiderProjects\\GazpromApp\\GazpromApp.csproj",
"expectedPackageFiles": [ "expectedPackageFiles": [
@@ -29,6 +29,9 @@
"C:\\Users\\retrd\\.nuget\\packages\\harfbuzzsharp.nativeassets.webassembly\\8.3.1.1\\harfbuzzsharp.nativeassets.webassembly.8.3.1.1.nupkg.sha512", "C:\\Users\\retrd\\.nuget\\packages\\harfbuzzsharp.nativeassets.webassembly\\8.3.1.1\\harfbuzzsharp.nativeassets.webassembly.8.3.1.1.nupkg.sha512",
"C:\\Users\\retrd\\.nuget\\packages\\harfbuzzsharp.nativeassets.win32\\8.3.1.1\\harfbuzzsharp.nativeassets.win32.8.3.1.1.nupkg.sha512", "C:\\Users\\retrd\\.nuget\\packages\\harfbuzzsharp.nativeassets.win32\\8.3.1.1\\harfbuzzsharp.nativeassets.win32.8.3.1.1.nupkg.sha512",
"C:\\Users\\retrd\\.nuget\\packages\\humanizer.core\\2.14.1\\humanizer.core.2.14.1.nupkg.sha512", "C:\\Users\\retrd\\.nuget\\packages\\humanizer.core\\2.14.1\\humanizer.core.2.14.1.nupkg.sha512",
"C:\\Users\\retrd\\.nuget\\packages\\material.avalonia\\3.12.0\\material.avalonia.3.12.0.nupkg.sha512",
"C:\\Users\\retrd\\.nuget\\packages\\material.icons\\2.4.1\\material.icons.2.4.1.nupkg.sha512",
"C:\\Users\\retrd\\.nuget\\packages\\material.icons.avalonia\\2.4.1\\material.icons.avalonia.2.4.1.nupkg.sha512",
"C:\\Users\\retrd\\.nuget\\packages\\microcom.runtime\\0.11.0\\microcom.runtime.0.11.0.nupkg.sha512", "C:\\Users\\retrd\\.nuget\\packages\\microcom.runtime\\0.11.0\\microcom.runtime.0.11.0.nupkg.sha512",
"C:\\Users\\retrd\\.nuget\\packages\\microsoft.bcl.asyncinterfaces\\7.0.0\\microsoft.bcl.asyncinterfaces.7.0.0.nupkg.sha512", "C:\\Users\\retrd\\.nuget\\packages\\microsoft.bcl.asyncinterfaces\\7.0.0\\microsoft.bcl.asyncinterfaces.7.0.0.nupkg.sha512",
"C:\\Users\\retrd\\.nuget\\packages\\microsoft.build.framework\\17.8.3\\microsoft.build.framework.17.8.3.nupkg.sha512", "C:\\Users\\retrd\\.nuget\\packages\\microsoft.build.framework\\17.8.3\\microsoft.build.framework.17.8.3.nupkg.sha512",
+1 -1
View File
@@ -1 +1 @@
"restore":{"projectUniqueName":"D:\\RiderProjects\\GazpromApp\\GazpromApp.csproj","projectName":"GazpromApp","projectPath":"D:\\RiderProjects\\GazpromApp\\GazpromApp.csproj","outputPath":"D:\\RiderProjects\\GazpromApp\\obj\\","projectStyle":"PackageReference","fallbackFolders":["C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"],"originalTargetFrameworks":["net8.0"],"sources":{"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\":{},"https://api.nuget.org/v3/index.json":{}},"frameworks":{"net8.0":{"targetAlias":"net8.0","projectReferences":{}}},"warningProperties":{"warnAsError":["NU1605"]},"restoreAuditProperties":{"enableAudit":"true","auditLevel":"low","auditMode":"direct"},"SdkAnalysisLevel":"9.0.300"}"frameworks":{"net8.0":{"targetAlias":"net8.0","dependencies":{"AnimatedImage.Avalonia":{"target":"Package","version":"[2.0.0, )"},"Avalonia":{"target":"Package","version":"[11.3.2, )"},"Avalonia.Controls.ItemsRepeater":{"target":"Package","version":"[11.1.5, )"},"Avalonia.Desktop":{"target":"Package","version":"[11.3.2, )"},"Avalonia.Diagnostics":{"target":"Package","version":"[11.3.2, )"},"Avalonia.Fonts.Inter":{"target":"Package","version":"[11.3.2, )"},"Avalonia.Themes.Fluent":{"target":"Package","version":"[11.3.2, )"},"AvaloniaUI.DiagnosticsSupport":{"target":"Package","version":"[2.0.4, )"},"CommunityToolkit.Mvvm":{"target":"Package","version":"[8.2.1, )"},"Microsoft.EntityFrameworkCore":{"target":"Package","version":"[9.0.6, )"},"Microsoft.EntityFrameworkCore.Design":{"include":"Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive","suppressParent":"All","target":"Package","version":"[9.0.6, )"},"Microsoft.EntityFrameworkCore.Sqlite":{"target":"Package","version":"[9.0.6, )"}},"imports":["net461","net462","net47","net471","net472","net48","net481"],"assetTargetFallback":true,"warn":true,"frameworkReferences":{"Microsoft.NETCore.App":{"privateAssets":"all"}},"runtimeIdentifierGraphPath":"C:\\Program Files\\dotnet\\sdk\\9.0.302/PortableRuntimeIdentifierGraph.json"}} "restore":{"projectUniqueName":"D:\\RiderProjects\\GazpromApp\\GazpromApp.csproj","projectName":"GazpromApp","projectPath":"D:\\RiderProjects\\GazpromApp\\GazpromApp.csproj","outputPath":"D:\\RiderProjects\\GazpromApp\\obj\\","projectStyle":"PackageReference","fallbackFolders":["C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"],"originalTargetFrameworks":["net8.0"],"sources":{"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\":{},"https://api.nuget.org/v3/index.json":{}},"frameworks":{"net8.0":{"targetAlias":"net8.0","projectReferences":{}}},"warningProperties":{"warnAsError":["NU1605"]},"restoreAuditProperties":{"enableAudit":"true","auditLevel":"low","auditMode":"direct"},"SdkAnalysisLevel":"9.0.300"}"frameworks":{"net8.0":{"targetAlias":"net8.0","dependencies":{"AnimatedImage.Avalonia":{"target":"Package","version":"[2.0.0, )"},"Avalonia":{"target":"Package","version":"[11.3.2, )"},"Avalonia.Controls.ItemsRepeater":{"target":"Package","version":"[11.1.5, )"},"Avalonia.Desktop":{"target":"Package","version":"[11.3.2, )"},"Avalonia.Diagnostics":{"target":"Package","version":"[11.3.2, )"},"Avalonia.Fonts.Inter":{"target":"Package","version":"[11.3.2, )"},"Avalonia.Themes.Fluent":{"target":"Package","version":"[11.3.2, )"},"AvaloniaUI.DiagnosticsSupport":{"target":"Package","version":"[2.0.4, )"},"CommunityToolkit.Mvvm":{"target":"Package","version":"[8.2.1, )"},"Material.Avalonia":{"target":"Package","version":"[3.12.0, )"},"Material.Icons.Avalonia":{"target":"Package","version":"[2.4.1, )"},"Microsoft.EntityFrameworkCore":{"target":"Package","version":"[9.0.6, )"},"Microsoft.EntityFrameworkCore.Design":{"include":"Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive","suppressParent":"All","target":"Package","version":"[9.0.6, )"},"Microsoft.EntityFrameworkCore.Sqlite":{"target":"Package","version":"[9.0.6, )"}},"imports":["net461","net462","net47","net471","net472","net48","net481"],"assetTargetFallback":true,"warn":true,"frameworkReferences":{"Microsoft.NETCore.App":{"privateAssets":"all"}},"runtimeIdentifierGraphPath":"C:\\Program Files\\dotnet\\sdk\\9.0.302/PortableRuntimeIdentifierGraph.json"}}
+1 -1
View File
@@ -1 +1 @@
17527364972202368 17536846459734642
+1 -1
View File
@@ -1 +1 @@
17527364972202368 17536846459734642