From 0626ce017643016276f3e96a97ac625a9cb2bbf5 Mon Sep 17 00:00:00 2001 From: "HOME-LAPTOP\\kshkulev" Date: Thu, 23 Oct 2025 10:56:11 +0900 Subject: [PATCH] Update common registries page --- Hcs.WebApp/Components/Layout/MainLayout.razor | 8 + .../Components/Pages/Management/Users.razor | 4 +- .../Components/Pages/Registry/Common.razor | 141 +++++++++++++++++- Hcs.WebApp/Data/Hcs/HcsDbContext.cs | 10 ++ .../20251023014411_AddOperation.Designer.cs | 120 +++++++++++++++ .../Migrations/20251023014411_AddOperation.cs | 58 +++++++ .../Migrations/HcsDbContextModelSnapshot.cs | 139 ++++++++++------- Hcs.WebApp/Data/Hcs/Operation.cs | 27 ++++ Hcs.WebApp/Data/Hcs/Registry.cs | 4 + Hcs.WebApp/Program.cs | 2 + Hcs.WebApp/Services/OperationService.cs | 16 ++ Hcs.WebApp/Services/RegistryService.cs | 18 +++ 12 files changed, 490 insertions(+), 57 deletions(-) create mode 100644 Hcs.WebApp/Data/Hcs/Migrations/20251023014411_AddOperation.Designer.cs create mode 100644 Hcs.WebApp/Data/Hcs/Migrations/20251023014411_AddOperation.cs create mode 100644 Hcs.WebApp/Data/Hcs/Operation.cs create mode 100644 Hcs.WebApp/Services/OperationService.cs create mode 100644 Hcs.WebApp/Services/RegistryService.cs diff --git a/Hcs.WebApp/Components/Layout/MainLayout.razor b/Hcs.WebApp/Components/Layout/MainLayout.razor index ab9839d..3a84a37 100644 --- a/Hcs.WebApp/Components/Layout/MainLayout.razor +++ b/Hcs.WebApp/Components/Layout/MainLayout.razor @@ -26,6 +26,14 @@ + + + + + + + + diff --git a/Hcs.WebApp/Components/Pages/Management/Users.razor b/Hcs.WebApp/Components/Pages/Management/Users.razor index f2c978f..be7cff1 100644 --- a/Hcs.WebApp/Components/Pages/Management/Users.razor +++ b/Hcs.WebApp/Components/Pages/Management/Users.razor @@ -71,9 +71,9 @@ StateHasChanged(); var state = await AuthenticationStateProvider.GetAuthenticationStateAsync(); - if (state.User.Identity?.IsAuthenticated ?? false) + if (state.User.IsInRole(AppRole.ADMINISTRATOR_TYPE)) { - currentUserId = state.User.FindFirst(ClaimTypes.NameIdentifier).Value; + currentUserId = state.User.FindFirst(ClaimTypes.NameIdentifier)!.Value; usersWithRoles = await UsersService.GetUsersWithRole(); } diff --git a/Hcs.WebApp/Components/Pages/Registry/Common.razor b/Hcs.WebApp/Components/Pages/Registry/Common.razor index bb8d481..b8c69ce 100644 --- a/Hcs.WebApp/Components/Pages/Registry/Common.razor +++ b/Hcs.WebApp/Components/Pages/Registry/Common.razor @@ -1,5 +1,144 @@ -

Common

+@page "/registry/common" + +@using System.IdentityModel.Claims +@using Hcs.WebApp.Components.Dialogs +@using Hcs.WebApp.Services +@using Microsoft.AspNetCore.Authorization +@using Microsoft.AspNetCore.Identity +@using Microsoft.EntityFrameworkCore + +@attribute [Authorize] + +@inject AuthenticationStateProvider AuthenticationStateProvider +@inject OperationService OperationService +@inject RegistryService RegistryService +@inject DialogService DialogService + +Общие справочники подсистемы НСИ + + + + + + + + + + + + + + + + + + @errorMessage + + + + + + + + + + + + + + + @code { + enum CommonPageState + { + Init, + Loading, + Idle, + OperationWaiting + } + IEnumerable registries; + CommonPageState state; + string syncText = "..."; + bool hasError; + string errorMessage; + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + + if (firstRender) + { + ChangeState(CommonPageState.Init); + StateHasChanged(); + + var finalState = CommonPageState.Idle; + var state = await AuthenticationStateProvider.GetAuthenticationStateAsync(); + if (state.User.IsInRole(AppRole.ADMINISTRATOR_TYPE) || state.User.IsInRole(AppRole.OPERATOR_TYPE)) + { + var operationInProgress = await OperationService.HasActiveOperation(Operation.OperationType.Nsi_15_7_0_1_ExportAllRegistryElements); + if (operationInProgress) + { + finalState = CommonPageState.OperationWaiting; + } + else + { + registries = await RegistryService.GetAllRegistries(true); + } + } + + ChangeState(finalState); + StateHasChanged(); + } + } + + async Task SyncRegistries() + { + // TODO + } + + async Task ViewRegistry(Registry userWithRole) + { + // TODO + } + + async Task EditRegistry(Registry registry) + { + // TODO + } + + async Task SyncRegistry(Registry registry) + { + // TODO + } + + void ChangeState(CommonPageState state) + { + this.state = state; + + SetSyncText(); + } + + void SetSyncText() + { + switch (state) + { + case CommonPageState.Init: + syncText = "..."; + break; + + case CommonPageState.Loading: + case CommonPageState.Idle: + syncText = "Синхронизировать"; + break; + + case CommonPageState.OperationWaiting: + syncText = "Синхронизация в процессе"; + break; + } + } } diff --git a/Hcs.WebApp/Data/Hcs/HcsDbContext.cs b/Hcs.WebApp/Data/Hcs/HcsDbContext.cs index 14b0ceb..8ceb35e 100644 --- a/Hcs.WebApp/Data/Hcs/HcsDbContext.cs +++ b/Hcs.WebApp/Data/Hcs/HcsDbContext.cs @@ -1,4 +1,5 @@ using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Hcs.WebApp.Data.Hcs { @@ -7,5 +8,14 @@ namespace Hcs.WebApp.Data.Hcs public DbSet Registries { get; set; } public DbSet Elements { get; set; } + + public DbSet Operations { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity() + .Property(x => x.Type) + .HasConversion(new EnumToStringConverter()); + } } } diff --git a/Hcs.WebApp/Data/Hcs/Migrations/20251023014411_AddOperation.Designer.cs b/Hcs.WebApp/Data/Hcs/Migrations/20251023014411_AddOperation.Designer.cs new file mode 100644 index 0000000..81ce2eb --- /dev/null +++ b/Hcs.WebApp/Data/Hcs/Migrations/20251023014411_AddOperation.Designer.cs @@ -0,0 +1,120 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable +namespace Hcs.WebApp.Data.Hcs.Migrations +{ + [DbContext(typeof(HcsDbContext))] + [Migration("20251023014411_AddOperation")] + partial class AddOperation + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.9") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Hcs.WebApp.Data.Hcs.Operation", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("EndedAt") + .HasColumnType("datetime2"); + + b.Property("InitiatorId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("MessageGuid") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StartedAt") + .HasColumnType("datetime2"); + + b.Property("Type") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Operations"); + }); + + modelBuilder.Entity("Hcs.WebApp.Data.Hcs.Registry", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("IsCommon") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Number") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Registries"); + }); + + modelBuilder.Entity("Hcs.WebApp.Data.Hcs.RegistryElement", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Code") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("GUID") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("RegistryId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Xml") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("RegistryId"); + + b.ToTable("Elements"); + }); + + modelBuilder.Entity("Hcs.WebApp.Data.Hcs.RegistryElement", b => + { + b.HasOne("Hcs.WebApp.Data.Hcs.Registry", "Registry") + .WithMany("Elements") + .HasForeignKey("RegistryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Registry"); + }); + + modelBuilder.Entity("Hcs.WebApp.Data.Hcs.Registry", b => + { + b.Navigation("Elements"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Hcs.WebApp/Data/Hcs/Migrations/20251023014411_AddOperation.cs b/Hcs.WebApp/Data/Hcs/Migrations/20251023014411_AddOperation.cs new file mode 100644 index 0000000..a5099f6 --- /dev/null +++ b/Hcs.WebApp/Data/Hcs/Migrations/20251023014411_AddOperation.cs @@ -0,0 +1,58 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable +namespace Hcs.WebApp.Data.Hcs.Migrations +{ + /// + public partial class AddOperation : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Name", + table: "Registries", + type: "nvarchar(max)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "UpdatedAt", + table: "Registries", + type: "datetime2", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.CreateTable( + name: "Operations", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Type = table.Column(type: "nvarchar(max)", nullable: false), + InitiatorId = table.Column(type: "nvarchar(max)", nullable: false), + StartedAt = table.Column(type: "datetime2", nullable: false), + EndedAt = table.Column(type: "datetime2", nullable: true), + MessageGuid = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Operations", x => x.Id); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Operations"); + + migrationBuilder.DropColumn( + name: "Name", + table: "Registries"); + + migrationBuilder.DropColumn( + name: "UpdatedAt", + table: "Registries"); + } + } +} diff --git a/Hcs.WebApp/Data/Hcs/Migrations/HcsDbContextModelSnapshot.cs b/Hcs.WebApp/Data/Hcs/Migrations/HcsDbContextModelSnapshot.cs index e8d58a1..22104ab 100644 --- a/Hcs.WebApp/Data/Hcs/Migrations/HcsDbContextModelSnapshot.cs +++ b/Hcs.WebApp/Data/Hcs/Migrations/HcsDbContextModelSnapshot.cs @@ -1,12 +1,8 @@ // -using Hcs.WebApp.Data.Hcs; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; #nullable disable - namespace Hcs.WebApp.Data.Hcs.Migrations { [DbContext(typeof(HcsDbContext))] @@ -21,65 +17,100 @@ namespace Hcs.WebApp.Data.Hcs.Migrations SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - modelBuilder.Entity("Hcs.WebApp.Data.Hcs.Registry", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); + modelBuilder.Entity("Hcs.WebApp.Data.Hcs.Operation", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); - b.Property("IsCommon") - .HasColumnType("bit"); + b.Property("EndedAt") + .HasColumnType("datetime2"); - b.Property("Number") - .HasColumnType("int"); + b.Property("InitiatorId") + .IsRequired() + .HasColumnType("nvarchar(max)"); - b.HasKey("Id"); + b.Property("MessageGuid") + .IsRequired() + .HasColumnType("nvarchar(max)"); - b.ToTable("Registries"); - }); + b.Property("StartedAt") + .HasColumnType("datetime2"); - modelBuilder.Entity("Hcs.WebApp.Data.Hcs.RegistryElement", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); + b.Property("Type") + .IsRequired() + .HasColumnType("nvarchar(max)"); - b.Property("Code") - .IsRequired() - .HasColumnType("nvarchar(max)"); + b.HasKey("Id"); - b.Property("GUID") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("RegistryId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Xml") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("RegistryId"); - - b.ToTable("Elements"); - }); - - modelBuilder.Entity("Hcs.WebApp.Data.Hcs.RegistryElement", b => - { - b.HasOne("Hcs.WebApp.Data.Hcs.Registry", "Registry") - .WithMany("Elements") - .HasForeignKey("RegistryId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Registry"); - }); + b.ToTable("Operations"); + }); modelBuilder.Entity("Hcs.WebApp.Data.Hcs.Registry", b => - { - b.Navigation("Elements"); - }); + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("IsCommon") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Number") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Registries"); + }); + + modelBuilder.Entity("Hcs.WebApp.Data.Hcs.RegistryElement", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Code") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("GUID") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("RegistryId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Xml") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("RegistryId"); + + b.ToTable("Elements"); + }); + + modelBuilder.Entity("Hcs.WebApp.Data.Hcs.RegistryElement", b => + { + b.HasOne("Hcs.WebApp.Data.Hcs.Registry", "Registry") + .WithMany("Elements") + .HasForeignKey("RegistryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Registry"); + }); + + modelBuilder.Entity("Hcs.WebApp.Data.Hcs.Registry", b => + { + b.Navigation("Elements"); + }); #pragma warning restore 612, 618 } } diff --git a/Hcs.WebApp/Data/Hcs/Operation.cs b/Hcs.WebApp/Data/Hcs/Operation.cs new file mode 100644 index 0000000..593721f --- /dev/null +++ b/Hcs.WebApp/Data/Hcs/Operation.cs @@ -0,0 +1,27 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Hcs.WebApp.Data.Hcs +{ + public class Operation + { + public enum OperationType + { + Nsi_15_7_0_1_ExportAllRegistryElements + } + + public string Id { get; set; } + + public OperationType Type { get; set; } + + public string InitiatorId { get; set; } + + public DateTime StartedAt { get; set; } + + public DateTime? EndedAt { get; set; } + + public string MessageGuid { get; set; } + + [NotMapped] + public bool Completed => EndedAt.HasValue; + } +} diff --git a/Hcs.WebApp/Data/Hcs/Registry.cs b/Hcs.WebApp/Data/Hcs/Registry.cs index c17492e..6ba1f06 100644 --- a/Hcs.WebApp/Data/Hcs/Registry.cs +++ b/Hcs.WebApp/Data/Hcs/Registry.cs @@ -6,8 +6,12 @@ public int Number { get; set; } + public string Name { get; set; } + public bool IsCommon { get; set; } + public DateTime UpdatedAt { get; set; } + public virtual ICollection Elements { get; set; } = []; } } diff --git a/Hcs.WebApp/Program.cs b/Hcs.WebApp/Program.cs index 9b030f2..62f998a 100644 --- a/Hcs.WebApp/Program.cs +++ b/Hcs.WebApp/Program.cs @@ -57,6 +57,8 @@ builder.Services.AddTransient(); #endif builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); var activator = new RadzenComponentActivator(); activator.Override(typeof(RadzenDataGrid<>), typeof(LocalizedRadzenDataGrid<>)); diff --git a/Hcs.WebApp/Services/OperationService.cs b/Hcs.WebApp/Services/OperationService.cs new file mode 100644 index 0000000..4909036 --- /dev/null +++ b/Hcs.WebApp/Services/OperationService.cs @@ -0,0 +1,16 @@ +using Hcs.WebApp.Data.Hcs; +using Microsoft.EntityFrameworkCore; + +namespace Hcs.WebApp.Services +{ + public class OperationService(IDbContextFactory factory) + { + private readonly IDbContextFactory factory = factory; + + public async Task HasActiveOperation(Operation.OperationType type) + { + using var context = factory.CreateDbContext(); + return await context.Operations.AnyAsync(x => x.Type == type && !x.EndedAt.HasValue); + } + } +} diff --git a/Hcs.WebApp/Services/RegistryService.cs b/Hcs.WebApp/Services/RegistryService.cs new file mode 100644 index 0000000..a516fe4 --- /dev/null +++ b/Hcs.WebApp/Services/RegistryService.cs @@ -0,0 +1,18 @@ +using Hcs.WebApp.Data.Hcs; +using Microsoft.EntityFrameworkCore; + +namespace Hcs.WebApp.Services +{ + public class RegistryService(IDbContextFactory factory) + { + private readonly IDbContextFactory factory = factory; + + public async Task> GetAllRegistries(bool isCommon) + { + using var context = factory.CreateDbContext(); + return await (from registry in context.Registries + where registry.IsCommon == isCommon + select registry).ToListAsync(); + } + } +}