DB integration added, multiple images for equipment

This commit is contained in:
retr0volkov
2025-07-15 11:14:28 +03:00 Unverified
parent 7a34fc2dbb
commit 8ddce4005f
38 changed files with 627 additions and 297 deletions
+21 -3
View File
@@ -3,13 +3,18 @@ using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core.Plugins;
using Avalonia.Markup.Xaml;
using GazpromApp.Utils;
using GazpromApp.ViewModels;
using GazpromApp.Views;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace GazpromApp;
public class App : Application
{
private static ServiceProvider? Services { get; set; }
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
@@ -17,14 +22,27 @@ public class App : Application
public override void OnFrameworkInitializationCompleted()
{
var services = new ServiceCollection();
services.AddDbContext<AppDbContext>(options =>
{
var dbPath = new AppDbContext().DbPath;
options.UseSqlite($"Data Source={dbPath}");
});
services.AddTransient<MainWindowViewModel>();
Services = services.BuildServiceProvider();
var dbContext = Services.GetRequiredService<AppDbContext>();
dbContext.Database.EnsureCreated();
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
// Avoid duplicate validations from both Avalonia and the CommunityToolkit.
// More info: https://docs.avaloniaui.net/docs/guides/development-guides/data-validation#manage-validationplugins
DisableAvaloniaDataAnnotationValidation();
desktop.MainWindow = new MainWindow
{
DataContext = new MainWindowViewModel()
DataContext = Services.GetRequiredService<MainWindowViewModel>()
};
}
+1
View File
@@ -13,6 +13,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="AnimatedImage.Avalonia" Version="2.0.0" />
<PackageReference Include="Avalonia" Version="11.3.2" />
<PackageReference Include="Avalonia.Controls.ItemsRepeater" Version="11.1.5" />
<PackageReference Include="Avalonia.Desktop" Version="11.3.2" />
+7 -6
View File
@@ -11,23 +11,24 @@ public class Equipment
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[JsonIgnore]
public int Id { get; set; }
[Required]
public string? Name { get; set; } = string.Empty;
[Required]
public string? Description { get; set; } = string.Empty;
[Required]
// Foreign keys
[Required]
[JsonIgnore]
public int PointId { get; set; }
[JsonIgnore]
public int ImageId { get; set; }
public List<int> ImageIds { get; set; } = [];
[JsonIgnore]
public List<int> InspectionIds { get; set; } = [];
// EF stuff
public Image? Image { get; set; }
// Navigation Properties
public List<Image> Images { get; set; } = [];
[JsonIgnore]
public Point? Point { get; set; }
public Point Point { get; set; } = null!;
public List<Property> Properties { get; set; } = [];
public List<Inspection> Inspections { get; set; } = [];
}
+3 -3
View File
@@ -4,7 +4,7 @@ namespace GazpromApp.Models;
public class Error
{
public string? Title { get; set; }
public string? Message { get; set; }
public ErrorSeverity Severity { get; set; }
public string? Title { get; init; }
public string? Message { get; init; }
public ErrorSeverity Severity { get; init; }
}
+12 -5
View File
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
@@ -11,11 +10,19 @@ public class Image
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[JsonIgnore]
public int Id { get; set; }
[Required]
public byte[] Bytes { get; set; } = [];
// EF stuff
// Foreign keys
[JsonIgnore]
public List<Point> Points { get; set; } = [];
public int? PointId { get; set; }
[JsonIgnore]
public List<Equipment> Equipment { get; set; } = [];
public int? EquipmentId { get; set; }
// Navigation Properties
[JsonIgnore]
public Point? Point { get; set; }
[JsonIgnore]
public Equipment? Equipment { get; set; }
}
+3 -1
View File
@@ -11,6 +11,7 @@ public class Inspection
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[JsonIgnore]
public int Id { get; set; }
[Required]
public string Name { get; set; } = string.Empty;
[Required]
@@ -20,10 +21,11 @@ public class Inspection
[Required]
public float PeriodValue { get; set; }
// Foreign keys
[JsonIgnore]
public int EquipmentId { get; set; }
// EF stuff
// Navigation Properties
[JsonIgnore]
public Equipment? Equipment { get; } = new();
}
+2 -4
View File
@@ -11,15 +11,13 @@ public class Point
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[JsonIgnore]
public int Id { get; set; }
[Required]
public string? Name { get; set; } = string.Empty;
[Required]
public string? Description { get; set; } = string.Empty;
[Required]
public double Latitude { get; set; }
[Required]
public double Longitude { get; set; }
// EF stuff
// Navigation Properties
public List<Image> Images { get; set; } = [];
public List<Equipment> Equipment { get; set; } = [];
public List<Property> Properties { get; set; } = [];
+20 -9
View File
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
@@ -12,17 +11,29 @@ public class Property
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[JsonIgnore]
public int Id { get; set; }
[JsonIgnore]
public int ParentId { get; set; }
[Required]
public string Name { get; set; } = string.Empty;
public string Value { get; set; } = string.Empty;
// EF stuff
// For self-referencing hierarchy (Property of a Property)
[JsonIgnore]
public int? ParentPropertyId { get; set; }
[JsonIgnore]
public Property? Parent { get; set; }
// For a Property of a Point
[JsonIgnore]
public int? PointId { get; set; }
[JsonIgnore]
public Point? Point { get; set; }
// For a Property of an Equipment
[JsonIgnore]
public int? EquipmentId { get; set; }
[JsonIgnore]
public Equipment? Equipment { get; set; }
// Child properties in the hierarchy
public List<Property> Properties { get; set; } = [];
[JsonIgnore]
public List<Point> Points { get; set; } = [];
[JsonIgnore]
public List<Equipment> Equipment { get; } = [];
}
+111 -28
View File
@@ -1,4 +1,5 @@
using GazpromApp.Models;
using System;
using GazpromApp.Models;
using Microsoft.EntityFrameworkCore;
namespace GazpromApp.Utils;
@@ -7,50 +8,132 @@ public class AppDbContext : DbContext
{
public DbSet<Image> Image { get; set; }
public DbSet<Equipment> Equipment { get; set; }
public DbSet<Inspection> Inspection { get; set; }
public DbSet<Property> Property { get; set; }
public DbSet<Point> Point { get; set; }
public string DbPath { get; }
public AppDbContext()
{
var path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
DbPath = System.IO.Path.Combine(path, "GazpromApp.db");
}
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
var path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
DbPath = System.IO.Path.Combine(path, "GazpromApp.db");
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseSqlite("Data Source=MainDB.db");
optionsBuilder.UseSqlite($"Data Source={DbPath}");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Images
// ==== Point RELATIONSHIPS ====
modelBuilder.Entity<Point>()
.HasMany(e => e.Images)
.WithMany(e => e.Points);
.HasMany(p => p.Equipment)
.WithOne(e => e.Point)
.HasForeignKey(e => e.PointId)
.OnDelete(DeleteBehavior.Cascade); // Deleting a Point deletes its Equipment.
modelBuilder.Entity<Equipment>()
.HasOne(e => e.Image)
.WithMany(e => e.Equipment)
.HasForeignKey(e => e.ImageId);
// Properties
modelBuilder.Entity<Point>()
.HasMany(e => e.Properties)
.WithMany(e => e.Points);
.HasMany(p => p.Images)
.WithOne(i => i.Point)
.HasForeignKey(i => i.PointId)
.OnDelete(DeleteBehavior.Cascade); // Deleting a Point deletes its Images.
modelBuilder.Entity<Equipment>()
.HasMany(e => e.Properties)
.WithMany(e => e.Equipment);
modelBuilder.Entity<Property>()
.HasMany(e => e.Properties)
.WithOne(e => e.Parent)
.HasForeignKey(e => e.ParentId);
// Equipment
modelBuilder.Entity<Equipment>()
.HasOne(e => e.Point)
.WithMany(e => e.Equipment)
.HasForeignKey(e => e.PointId);
// ==== Equipment RELATIONSHIPS ====
modelBuilder.Entity<Equipment>()
.HasMany(e => e.Inspections)
.WithOne(e => e.Equipment)
.HasForeignKey(e => e.EquipmentId);
.WithOne(i => i.Equipment)
.HasForeignKey(i => i.EquipmentId)
.OnDelete(DeleteBehavior.Cascade); // Deleting Equipment deletes its Inspections.
modelBuilder.Entity<Equipment>()
.HasMany(e => e.Images)
.WithOne(i => i.Equipment)
.HasForeignKey(i => i.EquipmentId)
.OnDelete(DeleteBehavior.Cascade); // Equipment has one Image.
// ==== PROPERTY RELATIONSHIPS ====
// Property as a child of a Point
modelBuilder.Entity<Point>()
.HasMany(p => p.Properties)
.WithOne(prop => prop.Point)
.HasForeignKey(prop => prop.PointId)
.IsRequired(false)
.OnDelete(DeleteBehavior.Cascade); // Deleting a Point deletes its Properties.
// Property as a child of an Equipment
modelBuilder.Entity<Equipment>()
.HasMany(e => e.Properties)
.WithOne(prop => prop.Equipment)
.HasForeignKey(prop => prop.EquipmentId)
.IsRequired(false)
.OnDelete(DeleteBehavior.Cascade); // Deleting Equipment deletes its Properties.
// Property as a child of another Property (self-referencing)
modelBuilder.Entity<Property>()
.HasMany(p => p.Properties)
.WithOne(p => p.Parent)
.HasForeignKey(p => p.ParentPropertyId)
.IsRequired(false)
.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);
}
}
+2 -2
View File
@@ -13,7 +13,7 @@ public static class DataSerialization
private static string LoadData(string path)
{
string text = System.IO.File.ReadAllText(path);
var text = System.IO.File.ReadAllText(path);
return text;
}
@@ -46,7 +46,7 @@ public static class Deserialization
}
catch
{
throw new ArgumentException("Ошибка расшивроки json файла");
throw new ArgumentException("Ошибка расшифровки json файла");
}
}
}
+3 -7
View File
@@ -1,20 +1,17 @@
using GazpromApp.Models;
using System.Collections.Generic;
using System.Linq;
namespace GazpromApp.Utils
{
namespace GazpromApp.Utils;
public static class PropertyParentHelper
{
public static void SetPropertyParents(this Point point)
{
// Set parents for properties in point
foreach (var prop in point.Properties)
{
SetParentsRecursively(prop);
}
// Set parents for properties in equipment
foreach (var prop in point.Equipment.SelectMany(equipment => equipment.Properties))
{
SetParentsRecursively(prop);
@@ -26,9 +23,8 @@ namespace GazpromApp.Utils
foreach (var childProp in property.Properties)
{
childProp.Parent = property;
childProp.ParentId = property.Id;
childProp.ParentPropertyId = property.Id;
SetParentsRecursively(childProp);
}
}
}
}
+13 -13
View File
@@ -9,18 +9,19 @@ namespace GazpromApp.ViewModels;
public partial class EquipmentViewModel : ViewModelBase
{
private Equipment Equipment { get; }
[ObservableProperty]
private string? _name;
[ObservableProperty]
private string? _description;
[ObservableProperty]
private ImageViewModel? _image;
public ObservableCollection<ImageViewModel> Images { get; init; } = [];
public ObservableCollection<PropertyViewModel> Properties { get; set; }
public ObservableCollection<PropertyViewModel> Properties { get; }
public ObservableCollection<InspectionViewModel> Inspections { get; set; }
public ObservableCollection<InspectionViewModel> Inspections { get; }
[ObservableProperty]
private string _nearestInspection;
@@ -29,17 +30,17 @@ public partial class EquipmentViewModel : ViewModelBase
{
Name = string.Empty;
Description = string.Empty;
Image = null;
Properties = [];
Inspections = [];
NearestInspection = "Нету инспекций";
Equipment = new Equipment();
}
public EquipmentViewModel(Equipment equipment)
{
Name = equipment.Name;
Description = equipment.Description;
Image = new ImageViewModel(equipment.Image ?? new Image());
Images = new ObservableCollection<ImageViewModel>(equipment.Images.Select(i => new ImageViewModel(i)));
Properties = new ObservableCollection<PropertyViewModel>(equipment.Properties.Select(e => new PropertyViewModel(e)));
var times = equipment.Inspections.Select(e => new InspectionViewModel(e))
@@ -57,16 +58,15 @@ public partial class EquipmentViewModel : ViewModelBase
.ToLongDateString();
if (Inspections.Count == 0) NearestInspection = "Нету инспекций";
Equipment = equipment;
}
public Equipment GetEquipment()
{
return new Equipment
{
Name = Name,
Description = Description,
Image = Image?.GetImage(),
Inspections = Inspections.Select(e => e.GetInspection()).ToList()
};
Equipment.Name = Name;
Equipment.Description = Description;
Equipment.Images = Images.Select(e => e.GetImage()).ToList();
Equipment.Inspections = Inspections.Select(e => e.GetInspection()).ToList();
return Equipment;
}
}
+17 -12
View File
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.IO;
using System.IO;
using Avalonia.Media.Imaging;
using CommunityToolkit.Mvvm.ComponentModel;
using GazpromApp.Models;
@@ -8,13 +7,19 @@ namespace GazpromApp.ViewModels;
public partial class ImageViewModel : ViewModelBase
{
private Image Image { get; }
[ObservableProperty]
private byte[]? _bytes;
// EF stuff
[ObservableProperty]
private List<Point>? _points;
private Point? _point;
[ObservableProperty]
private List<Equipment>? _equipment;
private Equipment? _equipment;
[ObservableProperty]
private Bitmap? _fileName;
@@ -22,26 +27,26 @@ public partial class ImageViewModel : ViewModelBase
{
Bytes = image.Bytes;
Equipment = image.Equipment;
Points = image.Points;
Point = image.Point;
FileName = image.Bytes is { Length: > 0 } ? new Bitmap(new MemoryStream(image.Bytes)) : null;
Image = image;
}
public ImageViewModel()
{
Bytes = null;
Equipment = null;
Points = null;
Point = null;
Image = new Image();
}
public Image GetImage()
{
var ms = new MemoryStream();
FileName?.Save(ms);
return new Image
{
Bytes = ms.ToArray(),
Equipment = Equipment ?? [],
Points = Points ?? []
};
Image.Bytes = ms.ToArray();
Image.Equipment = Equipment;
Image.Point = Point;
return Image;
}
}
+8 -7
View File
@@ -7,6 +7,7 @@ namespace GazpromApp.ViewModels;
public partial class InspectionViewModel : ViewModelBase
{
private Inspection Inspection { get; }
[ObservableProperty]
private string _name;
[ObservableProperty]
@@ -27,6 +28,7 @@ public partial class InspectionViewModel : ViewModelBase
InspectionDate = DateTimeOffset.Now;
PeriodType = 0;
PeriodValue = 1;
Inspection = new Inspection();
}
public InspectionViewModel(Inspection inspection)
@@ -35,16 +37,15 @@ public partial class InspectionViewModel : ViewModelBase
InspectionDate = inspection.InspectionDate;
PeriodType = inspection.PeriodType.ToPeriodType();
PeriodValue = inspection.PeriodValue;
Inspection = inspection;
}
public Inspection GetInspection()
{
return new Inspection
{
Name = Name,
InspectionDate = InspectionDate,
PeriodType = PeriodType.ToDescription(),
PeriodValue = PeriodValue
};
Inspection.Name = Name;
Inspection.InspectionDate = InspectionDate;
Inspection.PeriodType = PeriodType.ToDescription();
Inspection.PeriodValue = PeriodValue;
return Inspection;
}
}
+12 -11
View File
@@ -6,6 +6,8 @@ namespace GazpromApp.ViewModels;
public partial class PointViewModel : ViewModelBase
{
private Point Point { get; }
[ObservableProperty]
private string? _name;
@@ -20,14 +22,15 @@ public partial class PointViewModel : ViewModelBase
// EF stuff
[ObservableProperty]
private List<Image>? _images;
private List<Image> _images;
[ObservableProperty]
private List<Equipment>? _equipment;
private List<Equipment> _equipment;
[ObservableProperty]
private List<Property>? _properties;
private List<Property> _properties;
public PointViewModel(Point point)
{
Point = point;
Name = point.Name;
Description = point.Description;
Latitude = point.Latitude;
@@ -39,13 +42,11 @@ public partial class PointViewModel : ViewModelBase
public Point GetPoint()
{
return new Point
{
Name = Name,
Description = Description,
Equipment = Equipment ?? [],
Images = Images ?? [],
Properties = Properties ?? []
};
Point.Name = Name;
Point.Description = Description;
Point.Equipment = Equipment;
Point.Images = Images;
Point.Properties = Properties;
return Point;
}
}
+11 -10
View File
@@ -8,6 +8,8 @@ namespace GazpromApp.ViewModels;
public partial class PropertyViewModel : ViewModelBase
{
private Property Property { get; }
[ObservableProperty]
private string _name;
@@ -18,22 +20,18 @@ public partial class PropertyViewModel : ViewModelBase
// Visual and other properties
public PropertyViewModel? Parent { get; set; }
public PropertyViewModel? Parent { get; init; }
[ObservableProperty]
private bool _isEditing;
public Property GetProperty(Property? parent = null)
{
var p = new Property
{
Name = Name,
Value = Value,
Properties = [],
Parent = parent
};
p.Properties = Properties.Select(e => e.GetProperty(p)).ToList();
return p;
Property.Name = Name;
Property.Value = Value;
Property.Parent = parent;
Property.Properties = Properties.Select(e => e.GetProperty(Property)).ToList();
return Property;
}
public PropertyViewModel()
@@ -42,6 +40,7 @@ public partial class PropertyViewModel : ViewModelBase
Value = "Значение свойства";
Properties = [];
Parent = null;
Property = new Property();
}
public PropertyViewModel(Property property, PropertyViewModel? parent = null)
@@ -51,6 +50,7 @@ public partial class PropertyViewModel : ViewModelBase
Properties = new ObservableCollection<PropertyViewModel>(
property.Properties.Select(e => new PropertyViewModel(e, this)));
Parent = property.Parent is null ? null : parent;
Property = property;
}
public PropertyViewModel(PropertyViewModel property)
@@ -59,5 +59,6 @@ public partial class PropertyViewModel : ViewModelBase
Value = "Значение свойства";
Properties = [];
Parent = property;
Property = new Property();
}
}
+21 -25
View File
@@ -32,8 +32,7 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
[ObservableProperty]
private bool _isDescriptionEditing;
[ObservableProperty]
private ImageViewModel? _image;
public ObservableCollection<ImageViewModel> Images { get; set; }
public ObservableCollection<InspectionViewModel> Inspections { get; set; }
@@ -56,43 +55,39 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
{
var files = await w.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
AllowMultiple = false,
Title = "Выберите картинку",
AllowMultiple = true,
Title = "Выберите одну или несколько картинок",
FileTypeFilter = [FilePickerFileTypes.ImageAll]
});
IsImageSelected = files.Count > 0;
foreach (var file in files)
{
try
{
Image = IsImageSelected ? new ImageViewModel(new Image()) { FileName = new Bitmap(HttpUtility.UrlDecode(files[0].Path.AbsolutePath)) } : null;
Images.Add(new ImageViewModel(new Image()) { FileName = new Bitmap(HttpUtility.UrlDecode(file.Path.AbsolutePath) ) });
}
catch (ArgumentException)
{
var error = new Error
{
Title = "Ошибка обработки картинки",
Message = "Картинка не была добавлена",
Message = $"Картинка не была добавлена: \"{HttpUtility.UrlDecode(file.Name)}\"",
Severity = ErrorSeverity.Error
};
_ = await WeakReferenceMessenger.Default.Send(new ErrorMessage(new ErrorViewModel(error)));
IsImageSelected = false;
}
}
IsImagesEmpty = Images.Count == 0;
}
[RelayCommand]
private async Task ViewImage()
{
if (Image is null) return;
_ = await WeakReferenceMessenger.Default.Send(new ViewImageMessage(Image));
}
private static async Task ViewImage(ImageViewModel image) => _ = await WeakReferenceMessenger.Default.Send(new ViewImageMessage(image));
[RelayCommand]
private void DeleteImage()
private void DeleteImage(ImageViewModel image)
{
Image = null;
IsImageSelected = false;
Images.Remove(image);
IsImagesEmpty = Images.Count == 0;
}
[RelayCommand]
@@ -146,7 +141,7 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
{
Name = Name,
Description = Description,
Image = Image?.GetImage(),
Images = Images.Select(e => e.GetImage()).ToList(),
Inspections = Inspections.Select(e => e.GetInspection()).ToList(),
Properties = Properties.Select(e => e.GetProperty()).ToList()
};
@@ -163,13 +158,14 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
// Visual and other properties
[ObservableProperty]
private bool _isImageSelected;
private bool _isImagesEmpty;
[ObservableProperty]
private bool _isClosed;
private readonly EquipmentViewModel _equipment;
// ReSharper disable once MemberCanBeMadeStatic.Global
public PeriodType[] AllPeriods => Enum.GetValues<PeriodType>()
.Where(p => p != PeriodType.Unknown)
.ToArray();
@@ -178,11 +174,11 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
{
Name = "Testing";
Description = "Testing";
Image = null;
Images = [];
Inspections = [];
Properties = [];
IsImageSelected = false;
IsImagesEmpty = true;
_equipment = new EquipmentViewModel();
}
@@ -191,11 +187,11 @@ public partial class EditEquipmentDialogViewModel : ViewModelBase
{
Name = equipment.Name;
Description = equipment.Description;
Image = equipment.Image;
Images = equipment.Images;
Inspections = new ObservableCollection<InspectionViewModel>(equipment.Inspections.Select(e => e));
Properties = new ObservableCollection<PropertyViewModel>(equipment.Properties.Select(e => e));
IsImageSelected = equipment.Image is { Bytes.Length: > 0 };
IsImagesEmpty = Images.Count == 0;
_equipment = equipment;
}
+15 -14
View File
@@ -142,15 +142,14 @@ public partial class EditPointDialogViewModel : ViewModelBase
private void CompleteEdit()
{
IsClosed = true;
var point = new Point
{
Name = Name,
Description = Description,
Images = Images.Select(e => e.GetImage()).ToList(),
Equipment = Equipment.Select(e => e.GetEquipment()).ToList(),
Properties = Properties.Select(e => e.GetProperty()).ToList()
};
WeakReferenceMessenger.Default.Send(new EditPointDone(new PointViewModel(point)));
_point.Name = Name;
_point.Description = Description;
_point.Images = Images.Select(e => e.GetImage()).ToList();
_point.Equipment = Equipment.Select(e => e.GetEquipment()).ToList();
_point.Properties = Properties.Select(e => e.GetProperty()).ToList();
_ = _point.GetPoint();
WeakReferenceMessenger.Default.Send(new EditPointDone(new PointViewModel(_point.GetPoint())));
}
[RelayCommand]
@@ -182,12 +181,14 @@ public partial class EditPointDialogViewModel : ViewModelBase
new EquipmentViewModel
{
Name = "Equipment Name Very Long",
Description = "Really big description for the equipment to show the long textReally big description for the equipment to show the long textReally big description for the equipment to show the long textReally big description for the equipment to show the long text", Image = null
Description = "Really big description for the equipment to show the long textReally big description for the equipment to show the long textReally big description for the equipment to show the long textReally big description for the equipment to show the long text",
Images = []
},
new EquipmentViewModel
{
Name = "Equipment Name Very Long",
Description = "Really big description for the equipment to show the long textReally big description for the equipment to show the long textReally big description for the equipment to show the long textReally big description for the equipment to show the long text", Image = null
Description = "Really big description for the equipment to show the long textReally big description for the equipment to show the long textReally big description for the equipment to show the long textReally big description for the equipment to show the long text",
Images = []
}
];
Properties = [
@@ -254,9 +255,9 @@ public partial class EditPointDialogViewModel : ViewModelBase
{
Name = point.Name;
Description = point.Description;
Images = new ObservableCollection<ImageViewModel>((point.Images ?? []).Select(e => new ImageViewModel(e)));
Equipment = new ObservableCollection<EquipmentViewModel>((point.Equipment ?? []).Select(e => new EquipmentViewModel(e)));
Properties = new ObservableCollection<PropertyViewModel>((point.Properties ?? []).Select(e => new PropertyViewModel(e)));
Images = new ObservableCollection<ImageViewModel>(point.Images.Select(e => new ImageViewModel(e)));
Equipment = new ObservableCollection<EquipmentViewModel>(point.Equipment.Select(e => new EquipmentViewModel(e)));
Properties = new ObservableCollection<PropertyViewModel>(point.Properties.Select(e => new PropertyViewModel(e)));
IsImagesEmpty = Images.Count == 0;
IsEquipmentEmpty = Equipment.Count == 0;
+112 -12
View File
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Avalonia.Controls;
@@ -11,37 +13,62 @@ using CommunityToolkit.Mvvm.Messaging;
using GazpromApp.Messages;
using GazpromApp.Models;
using GazpromApp.Utils;
using Microsoft.EntityFrameworkCore;
namespace GazpromApp.ViewModels;
public partial class MainWindowViewModel : ViewModelBase
{
public ObservableCollection<PointViewModel> Points { get; }
public ObservableCollection<PointViewModel> Points { get; set; }
[RelayCommand]
private async Task AddPoint()
{
var point = await WeakReferenceMessenger.Default.Send(new NewPointMessage());
if (point == null) return;
IsLoading = true;
_context.Point.Add(point.GetPoint());
await _context.SaveChangesAsync();
if (point != null)
Points.Add(point);
IsLineVisible = Points.Count > 0;
IsLoading = false;
}
[RelayCommand]
private async Task EditPoint(PointViewModel point)
{
var p = await WeakReferenceMessenger.Default.Send(new EditPointMessage(point)) ?? point;
Points[Points.IndexOf(point)] = p;
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 void RemovePoint(PointViewModel point)
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);
IsLineVisible = Points.Count > 0;
IsLoading = false;
}
[RelayCommand]
@@ -54,14 +81,26 @@ public partial class MainWindowViewModel : ViewModelBase
await w.StorageProvider.TryGetFolderFromPathAsync(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments))
});
IsLoading = true;
foreach (var file in files)
{
var url = file.Path.AbsolutePath;
var decoded = HttpUtility.HtmlDecode(url);
var point = DataSerialization.LoadPoint(decoded);
point?.SetPropertyParents();
Points.Add(new PointViewModel(point ?? new Point()));
if (point == null) continue;
_context.Point.Add(point);
await _context.SaveChangesAsync();
_context.Update(point);
await _context.SaveChangesAsync();
Points.Add(new PointViewModel(point));
}
IsLoading = false;
}
[RelayCommand]
@@ -82,14 +121,75 @@ public partial class MainWindowViewModel : ViewModelBase
}
// Visual and other properties
[ObservableProperty] private bool _isLoading = true;
[ObservableProperty]
private bool _isLineVisible;
private readonly AppDbContext _context;
private async Task LoadChildrenForProperties(List<Property> properties)
{
if (properties.Count == 0)
return;
var parentIds = properties.Select(p => p.Id).ToList();
var children = await _context.Property
.Where(p => p.ParentPropertyId.HasValue && parentIds.Contains(p.ParentPropertyId.Value))
.AsNoTracking()
.ToListAsync();
if (children.Count != 0)
{
var childrenLookup = children.ToLookup(child => child.ParentPropertyId);
foreach (var parent in properties.Where(parent => childrenLookup.Contains(parent.Id)))
parent.Properties.AddRange(childrenLookup[parent.Id]);
// ReSharper disable once TailRecursiveCall
await LoadChildrenForProperties(children);
}
}
private async Task LoadDataAsync()
{
IsLoading = true;
var pointsFromDb = await _context.Point
.Include(p => p.Images)
.Include(p => p.Equipment)
.ThenInclude(e => e.Properties)
.Include(p => p.Equipment)
.ThenInclude(e => e.Images)
.Include(p => p.Equipment)
.ThenInclude(e => e.Inspections)
.Include(p => p.Properties)
.AsNoTracking()
.ToListAsync();
var topLevelProperties = pointsFromDb.SelectMany(p => p.Properties)
.Concat(pointsFromDb.SelectMany(p => p.Equipment).SelectMany(e => e.Properties))
.ToList();
if (topLevelProperties.Count != 0)
await LoadChildrenForProperties(topLevelProperties);
Points.Clear();
foreach (var point in pointsFromDb)
Points.Add(new PointViewModel(point));
IsLoading = false;
}
public MainWindowViewModel(AppDbContext context)
{
Points = [];
_context = context;
_ = LoadDataAsync();
}
public MainWindowViewModel()
{
if (Design.IsDesignMode)
Points = [new PointViewModel(new Point()) { Name = "Name test", Description = "Description test" }];
else Points = [];
_context = new AppDbContext();
IsLoading = false;
}
}
+17 -15
View File
@@ -1,4 +1,6 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Avalonia.Controls;
@@ -24,44 +26,44 @@ public partial class NewEquipmentDialogViewModel : ViewModelBase
[NotifyCanExecuteChangedFor(nameof(EnterEquipmentCommand))]
private string? _description;
[ObservableProperty]
private ImageViewModel? _image;
public ObservableCollection<ImageViewModel> Images { get; } = [];
[RelayCommand]
private async Task AddImage(Window w)
{
var files = await w.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
AllowMultiple = false,
Title = "Выберите картинку",
AllowMultiple = true,
Title = "Выберите одну или несколько картинок",
FileTypeFilter = [FilePickerFileTypes.ImageAll]
});
IsImageSelected = files.Count > 0;
foreach (var file in files)
{
try
{
Image = IsImageSelected ? new ImageViewModel(new Image()) { FileName = new Bitmap(HttpUtility.UrlDecode(files[0].Path.AbsolutePath)) } : null;
Images.Add(new ImageViewModel(new Image()) { FileName = new Bitmap(HttpUtility.UrlDecode(file.Path.AbsolutePath)) });
}
catch (ArgumentException)
{
var error = new Error
{
Title = "Ошибка обработки картинки",
Message = "Картинка не была добавлена",
Message = $"Картинка не была добавлена: \"{HttpUtility.UrlDecode(file.Name)}\"",
Severity = ErrorSeverity.Error
};
_ = await WeakReferenceMessenger.Default.Send(new ErrorMessage(new ErrorViewModel(error)));
IsImageSelected = false;
}
}
IsImagesEmpty = Images.Count == 0;
}
[RelayCommand]
private void DeleteImage()
private void DeleteImage(ImageViewModel image)
{
Image = null;
IsImageSelected = false;
Images.Remove(image);
IsImagesEmpty = Images.Count == 0;
}
private bool CanEnterEquipment() => !string.IsNullOrEmpty(Name);
@@ -73,7 +75,7 @@ public partial class NewEquipmentDialogViewModel : ViewModelBase
{
Name = Name,
Description = Description ?? string.Empty,
Image = (Image ?? new ImageViewModel()).GetImage()
Images = Images.Select(e => e.GetImage()).ToList()
};
WeakReferenceMessenger.Default.Send(new NewEquipmentDone(new EquipmentViewModel(equipment)));
@@ -88,5 +90,5 @@ public partial class NewEquipmentDialogViewModel : ViewModelBase
// Visual and other stuff
[ObservableProperty]
private bool _isImageSelected;
private bool _isImagesEmpty;
}
+34 -12
View File
@@ -57,28 +57,50 @@
<Image Width="24" Height="24" Source="avares://GazpromApp/Assets/ic_fluent_edit_24_filled (Custom).png"/>
</Button>
<Grid Grid.Row="0" Grid.RowSpan="2" Grid.Column="2"
ColumnDefinitions="*,20,4,20,8" RowDefinitions="8,20,*"
IsVisible="{Binding IsImageSelected}">
<Image Grid.ColumnSpan="5" Grid.RowSpan="3"
Source="{Binding Image.FileName, FallbackValue=null}"/>
<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 ViewImageCommand}">
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 DeleteImageCommand}">
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>
<Button Grid.Row="0" Grid.RowSpan="2" Grid.Column="2" HorizontalAlignment="Center"
IsVisible="{Binding !IsImageSelected}"
</Border>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" IsVisible="{Binding !IsImagesEmpty}"
Command="{Binding AddImageCommand}"
CommandParameter="{Binding #Window}">
<Image Width="24" Height="24"
Source="avares://GazpromApp/Assets/ic_fluent_camera_add_24_filled (Custom).png"/>
<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="Тех. осмотры">
+1 -1
View File
@@ -118,7 +118,7 @@
<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 Image.FileName, FallbackValue=null}"/>
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"
+7
View File
@@ -83,6 +83,8 @@ public partial class EditPointDialog : Window
m.Reply(dialog.ShowDialog<ImageViewModel?>(w));
});
try
{
WeakReferenceMessenger.Default.Register<EditPointDialog, ErrorMessage>(this, static (w, m) =>
{
var dialog = new ErrorView
@@ -91,6 +93,11 @@ public partial class EditPointDialog : Window
};
m.Reply(dialog.ShowDialog<ErrorViewModel?>(w));
});
}
catch (Exception)
{
// ignored
}
});
// new property
+16 -6
View File
@@ -2,9 +2,10 @@
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:anim="https://github.com/whistyun/AnimatedImage.Avalonia"
xmlns:vm="using:GazpromApp.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
Width="1436" Height="720"
mc:Ignorable="d" d:DesignWidth="1024" d:DesignHeight="600"
Width="1024" Height="600"
x:Class="GazpromApp.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
x:Name="Window"
@@ -70,8 +71,11 @@
</Grid.RowDefinitions>
<ScrollViewer Grid.ColumnSpan="3">
<StackPanel Orientation="Vertical">
<ItemsControl ItemsSource="{Binding Points}">
<ItemsControl.ItemTemplate>
<ItemsRepeater ItemsSource="{Binding Points}">
<ItemsRepeater.Layout>
<StackLayout Orientation="Vertical"/>
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="vm:PointViewModel">
<Border CornerRadius="4" BorderThickness="1" Margin="6"
Background="{DynamicResource BackgroundBrush}"
@@ -104,10 +108,16 @@
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</StackPanel>
</ScrollViewer>
<Image Width="100" Height="100" VerticalAlignment="Center"
IsVisible="{Binding IsLoading}"
HorizontalAlignment="Center"
Grid.Row="0" Grid.Column="0"
Grid.ColumnSpan="3" Grid.RowSpan="2"
anim:ImageBehavior.AnimatedSource="avares://GazpromApp/Assets/loading.gif"/>
</Grid>
</DockPanel>
</Window>
+24 -15
View File
@@ -34,29 +34,38 @@
<TextBox Grid.Column="1" Grid.Row="1" Margin="8"
Text="{Binding Description}"/>
<Grid Grid.Column="1" Grid.Row="2" Margin="2"
ColumnDefinitions="*,20,8,20,8" RowDefinitions="8,20,*"
IsVisible="True">
<Image Stretch="Uniform" Grid.RowSpan="3" Grid.ColumnSpan="3"
Source="{Binding Image.FileName, FallbackValue=null}"/>
<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"
IsVisible="{Binding IsImageSelected}"
Command="{Binding AddImageCommand}"
CommandParameter="{Binding #Window}">
<Image Width="16" Height="16" Source="avares://GazpromApp/Assets/ic_fluent_edit_24_filled (Custom) 16.png"/>
</Button>
<Button Grid.Row="1" Grid.Column="3" Width="20" Height="20"
IsVisible="{Binding IsImageSelected}"
Command="{Binding DeleteImageCommand}">
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>
<Button Grid.Row="2" Grid.Column="1" HorizontalAlignment="Center"
IsVisible="{Binding !IsImageSelected}"
</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}"
@@ -1 +1 @@
3656b818a608cac55f3434fefe51f65e8b2346fa99aecf23bebe97e8e8aa269e
6ec01d8198a7aa89515263050c4105434cbcd2354fb50cf2ffbc3673c60121f8
Binary file not shown.
+1 -1
View File
@@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("GazpromApp")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+f3e0e15f352858b0ee8bba13ece6c0dffa8c8987")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+7a34fc2dbb087fdbf1bea9de2367b1627dbfd934")]
[assembly: System.Reflection.AssemblyProductAttribute("GazpromApp")]
[assembly: System.Reflection.AssemblyTitleAttribute("GazpromApp")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
@@ -1 +1 @@
3913b1f238033a5ab96ca8fd462af0cdbfa6151f322cece9cf7cd65c0266a4e7
79ee0a1c89f7354058711501fd55995c28018c56cfa0b0de53a84dfaced70957
Binary file not shown.
@@ -201,3 +201,5 @@ D:\RiderProjects\GazpromApp\bin\Debug\net8.0\zh-Hant\Microsoft.CodeAnalysis.Work
D:\RiderProjects\GazpromApp\bin\Debug\net8.0\AvaloniaUI.DiagnosticsSupport.Avalonia.dll
D:\RiderProjects\GazpromApp\bin\Debug\net8.0\Microsoft.IO.RecyclableMemoryStream.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.dll
+4
View File
@@ -50,6 +50,10 @@
"net8.0": {
"targetAlias": "net8.0",
"dependencies": {
"AnimatedImage.Avalonia": {
"target": "Package",
"version": "[2.0.0, )"
},
"Avalonia": {
"target": "Package",
"version": "[11.3.2, )"
+51
View File
@@ -2,6 +2,28 @@
"version": 3,
"targets": {
"net8.0": {
"AnimatedImage.Avalonia/2.0.0": {
"type": "package",
"dependencies": {
"Avalonia": "11.0.0"
},
"compile": {
"lib/net6.0/AnimatedImage.Avalonia.dll": {
"related": ".xml"
},
"lib/net6.0/AnimatedImage.dll": {
"related": ".Avalonia.xml;.xml"
}
},
"runtime": {
"lib/net6.0/AnimatedImage.Avalonia.dll": {
"related": ".xml"
},
"lib/net6.0/AnimatedImage.dll": {
"related": ".Avalonia.xml;.xml"
}
}
},
"Avalonia/11.3.2": {
"type": "package",
"dependencies": {
@@ -1766,6 +1788,30 @@
}
},
"libraries": {
"AnimatedImage.Avalonia/2.0.0": {
"sha512": "Ts0lfQjbozqk1q1uoXBm/dRH8nmxTTmMunan8IBuHsIPKG1MUL+60KDmbCyurnE0rNJh24boGjhIj2Ec9W5Jbg==",
"type": "package",
"path": "animatedimage.avalonia/2.0.0",
"files": [
".nupkg.metadata",
".signature.p7s",
"AnimatedImage.Avalonia.md",
"animatedimage.avalonia.2.0.0.nupkg.sha512",
"animatedimage.avalonia.nuspec",
"lib/net462/AnimatedImage.Avalonia.dll",
"lib/net462/AnimatedImage.Avalonia.xml",
"lib/net462/AnimatedImage.dll",
"lib/net462/AnimatedImage.xml",
"lib/net6.0/AnimatedImage.Avalonia.dll",
"lib/net6.0/AnimatedImage.Avalonia.xml",
"lib/net6.0/AnimatedImage.dll",
"lib/net6.0/AnimatedImage.xml",
"lib/netcoreapp3.1/AnimatedImage.Avalonia.dll",
"lib/netcoreapp3.1/AnimatedImage.Avalonia.xml",
"lib/netcoreapp3.1/AnimatedImage.dll",
"lib/netcoreapp3.1/AnimatedImage.xml"
]
},
"Avalonia/11.3.2": {
"sha512": "3w1v4/wEpHFq6WWVNyyrne2Jyz5bdQvnK3AW36rCto42L+AtdbnO/SG2SIqJ7ObXJl+Y3LXz2XDGx9Blzqduow==",
"type": "package",
@@ -4695,6 +4741,7 @@
},
"projectFileDependencyGroups": {
"net8.0": [
"AnimatedImage.Avalonia >= 2.0.0",
"Avalonia >= 11.3.2",
"Avalonia.Controls.ItemsRepeater >= 11.1.5",
"Avalonia.Desktop >= 11.3.2",
@@ -4758,6 +4805,10 @@
"net8.0": {
"targetAlias": "net8.0",
"dependencies": {
"AnimatedImage.Avalonia": {
"target": "Package",
"version": "[2.0.0, )"
},
"Avalonia": {
"target": "Package",
"version": "[11.3.2, )"
+2 -1
View File
@@ -1,9 +1,10 @@
{
"version": 2,
"dgSpecHash": "jPpTgNZhtko=",
"dgSpecHash": "hnfkdEFJuA8=",
"success": true,
"projectFilePath": "D:\\RiderProjects\\GazpromApp\\GazpromApp.csproj",
"expectedPackageFiles": [
"C:\\Users\\retrd\\.nuget\\packages\\animatedimage.avalonia\\2.0.0\\animatedimage.avalonia.2.0.0.nupkg.sha512",
"C:\\Users\\retrd\\.nuget\\packages\\avalonia\\11.3.2\\avalonia.11.3.2.nupkg.sha512",
"C:\\Users\\retrd\\.nuget\\packages\\avalonia.angle.windows.natives\\2.1.25547.20250602\\avalonia.angle.windows.natives.2.1.25547.20250602.nupkg.sha512",
"C:\\Users\\retrd\\.nuget\\packages\\avalonia.buildservices\\0.0.31\\avalonia.buildservices.0.0.31.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.200"}"frameworks":{"net8.0":{"targetAlias":"net8.0","dependencies":{"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.204/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.200"}"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.204/PortableRuntimeIdentifierGraph.json"}}
+1 -1
View File
@@ -1 +1 @@
17518675823308854
17522225915601599
+1 -1
View File
@@ -1 +1 @@
17518675823308854
17522225915601599