From 70e27da4a2272f259ed39313b7ad7b17767ad289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=90=C4=83ng=20Nguy=E1=BB=85n?= Date: Mon, 3 Nov 2025 10:29:18 +0700 Subject: [PATCH] update --- .../Config/RobotVDA5050Config.razor | 160 +++-- .../Config/RobotVDA5050Config.razor.css | 52 +- .../Pages/RobotConfigManager.razor | 4 +- .../Pages/RobotConfigManager.razor.cs | 35 +- RobotApp.Client/wwwroot/js/app.js | 1 + .../Dtos/RobotVDA5050ConfigDto.cs | 6 +- RobotApp/Components/App.razor | 1 + RobotApp/Controllers/FileController.cs | 76 +++ .../Controllers/RobotConfigsController.cs | 10 +- ...031080648_UpdateVDA5050Config1.Designer.cs | 577 ++++++++++++++++++ .../20251031080648_UpdateVDA5050Config1.cs | 22 + .../ApplicationDbContextModelSnapshot.cs | 8 +- RobotApp/Data/RobotVDA5050Config.cs | 2 +- RobotApp/robot.db | Bin 167936 -> 167936 bytes 14 files changed, 883 insertions(+), 71 deletions(-) create mode 100644 RobotApp.Client/wwwroot/js/app.js create mode 100644 RobotApp/Controllers/FileController.cs create mode 100644 RobotApp/Data/Migrations/20251031080648_UpdateVDA5050Config1.Designer.cs create mode 100644 RobotApp/Data/Migrations/20251031080648_UpdateVDA5050Config1.cs diff --git a/RobotApp.Client/Pages/Components/Config/RobotVDA5050Config.razor b/RobotApp.Client/Pages/Components/Config/RobotVDA5050Config.razor index 3844e42..2a61e9b 100644 --- a/RobotApp.Client/Pages/Components/Config/RobotVDA5050Config.razor +++ b/RobotApp.Client/Pages/Components/Config/RobotVDA5050Config.razor @@ -1,5 +1,6 @@ @implements IDisposable +
@@ -71,12 +72,27 @@
-
+
- - @if (!string.IsNullOrEmpty(CaFileName)) +
+ +
+ + + + @Model.VDA5050CA + + + +
+
+ @if (!string.IsNullOrEmpty(CaFileInfo)) { -
@CaFileName (@FormatSize(CaFileSize))
+
@CaFileInfo
} @if (!string.IsNullOrEmpty(CaFileError)) { @@ -84,12 +100,27 @@ }
-
+
- - @if (!string.IsNullOrEmpty(CertFileName)) +
+ +
+ + + + @Model.VDA5050Cer + + + +
+
+ @if (!string.IsNullOrEmpty(CertFileInfo)) { -
@CertFileName (@FormatSize(CertFileSize))
+
@CertFileInfo
} @if (!string.IsNullOrEmpty(CertFileError)) { @@ -97,12 +128,27 @@ }
-
+
- - @if (!string.IsNullOrEmpty(KeyFileName)) +
+ +
+ + + + @Model.VDA5050Key + + + +
+
+ @if (!string.IsNullOrEmpty(KeyFileInfo)) { -
@KeyFileName (@FormatSize(KeyFileSize))
+
@KeyFileInfo
} @if (!string.IsNullOrEmpty(KeyFileError)) { @@ -128,7 +174,6 @@
- @code { [Parameter] public RobotVDA5050ConfigDto Model { get; set; } = new(); @@ -136,6 +181,11 @@ [Parameter] public EventCallback ModelChanged { get; set; } + public IBrowserFile? CaFile { get; set; } + public IBrowserFile? CertFile { get; set; } + public IBrowserFile? KeyFile { get; set; } + public long MaxFileSize { get; set; } = 10 * 1024 * 1024; + private EditContext? EditContext; private bool showPassword; private string PasswordInputType => showPassword ? "text" : "password"; @@ -143,22 +193,14 @@ private enum FileSlot { Ca, Cert, Key } - private string? CaFileName; - private long CaFileSize; + private string? CaFileInfo; private string? CaFileError; - private byte[]? CaFileData; - private string? CertFileName; - private long CertFileSize; + private string? CertFileInfo; private string? CertFileError; - private byte[]? CertFileData; - private string? KeyFileName; - private long KeyFileSize; + private string? KeyFileInfo; private string? KeyFileError; - private byte[]? KeyFileData; - - private const long MaxFileSize = 10 * 1024 * 1024; // 10 MB private async Task OnFileSelected(InputFileChangeEventArgs e, FileSlot slot) { @@ -169,7 +211,7 @@ if (file.Size > MaxFileSize) { SetFileError(slot, $"File too large (max {FormatSize(MaxFileSize)})"); - SetFileInfo(slot, null, 0, null); + SetFileInfo(slot, string.Empty, 0); return; } @@ -180,30 +222,25 @@ await stream.CopyToAsync(ms); var data = ms.ToArray(); - SetFileData(slot, data, file.Name, file.Size); - ClearFileError(slot); - - // Optionally propagate change to parent via ModelChanged if required - // _ = ModelChanged.InvokeAsync(Model); + SetFileError(slot, null); + SetFileInfo(slot, file.Name, file.Size); + SetFileName(slot, file.Name); + SetBrowserFile(slot, file); + _ = ModelChanged.InvokeAsync(Model); } - catch (Exception ex) + catch { SetFileError(slot, "Failed to read file"); - Console.Error.WriteLine(ex); } } - private void SetFileData(FileSlot slot, byte[] data, string name, long size) + private void RemoveFile(FileSlot slot) { - switch (slot) - { - case FileSlot.Ca: - CaFileData = data; CaFileName = name; CaFileSize = size; break; - case FileSlot.Cert: - CertFileData = data; CertFileName = name; CertFileSize = size; break; - case FileSlot.Key: - KeyFileData = data; KeyFileName = name; KeyFileSize = size; break; - } + SetFileInfo(slot, string.Empty, 0); + SetFileError(slot, null); + SetFileName(slot, string.Empty); + + _ = ModelChanged.InvokeAsync(Model); } private void SetFileError(FileSlot slot, string? error) @@ -216,15 +253,33 @@ } } - private void ClearFileError(FileSlot slot) => SetFileError(slot, null); - - private void SetFileInfo(FileSlot slot, string? name, long size, byte[]? data) + private void SetFileInfo(FileSlot slot, string? name, long size) { switch (slot) { - case FileSlot.Ca: CaFileName = name; CaFileSize = size; CaFileData = data; break; - case FileSlot.Cert: CertFileName = name; CertFileSize = size; CertFileData = data; break; - case FileSlot.Key: KeyFileName = name; KeyFileSize = size; KeyFileData = data; break; + case FileSlot.Ca: CaFileInfo = string.IsNullOrEmpty(name) ? "" : $"{name} {FormatSize(size)}"; break; + case FileSlot.Cert: CertFileInfo = string.IsNullOrEmpty(name) ? "" : $"{name} {FormatSize(size)}"; break; + case FileSlot.Key: KeyFileInfo = string.IsNullOrEmpty(name) ? "" : $"{name} {FormatSize(size)}"; break; + } + } + + private void SetFileName(FileSlot slot, string? name) + { + switch (slot) + { + case FileSlot.Ca: Model.VDA5050CA = name; break; + case FileSlot.Cert: Model.VDA5050Cer = name; break; + case FileSlot.Key: Model.VDA5050Key = name; break; + } + } + + private void SetBrowserFile(FileSlot slot, IBrowserFile file) + { + switch (slot) + { + case FileSlot.Ca: CaFile = file; break; + case FileSlot.Cert: CertFile = file; break; + case FileSlot.Key: KeyFile = file; break; } } @@ -245,13 +300,10 @@ if (EditContext is not null) EditContext.OnFieldChanged -= EditContext_OnFieldChanged; EditContext = new EditContext(Model); EditContext.OnFieldChanged += EditContext_OnFieldChanged; + CaFileInfo = string.Empty; + CertFileInfo = string.Empty; + KeyFileInfo = string.Empty; } - CertFileName = string.Empty; - CertFileError = string.Empty; - KeyFileName = string.Empty; - KeyFileError = string.Empty; - CaFileName = string.Empty; - CaFileError = string.Empty; } private void TogglePasswordVisibility() diff --git a/RobotApp.Client/Pages/Components/Config/RobotVDA5050Config.razor.css b/RobotApp.Client/Pages/Components/Config/RobotVDA5050Config.razor.css index a0c2c3c..1cb8158 100644 --- a/RobotApp.Client/Pages/Components/Config/RobotVDA5050Config.razor.css +++ b/RobotApp.Client/Pages/Components/Config/RobotVDA5050Config.razor.css @@ -40,4 +40,54 @@ .password-toggle-btn .mdi { font-size: 1.15rem; pointer-events: none; /* let clicks hit the button, not the icon */ -} \ No newline at end of file +} + +.file-input-wrapper { + max-width: 100%; +} + +.custom-file-input-wrapper { + max-width: 100%; +} + + .custom-file-input-wrapper .form-control { + height: 38px; + padding-right: 50px; + background-color: #f8f9fa; + border: 1px solid #ced4da; + } + +.text-truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +/* === NÚT LABEL GIỐNG BUTTON THẬT === */ +.upload-btn { + cursor: pointer; + transition: all 0.2s ease; + user-select: none; + min-width: 50px; + font-size: 23px; + justify-content: center; + border-right: 1px solid silver; + border-radius: 0.25rem; +} + + /* HOVER: đổi màu nền + viền */ + .upload-btn:hover { + background-color: #e7f3ff !important; + } + + /* FOCUS: khi tab đến (accessibility) */ + .upload-btn:focus { + outline: 2px solid transparent; + box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.5) !important; + } + + /* ACTIVE: khi nhấn */ + .upload-btn:active { + transform: translateY(0); + background-color: #d0e8ff !important; + } \ No newline at end of file diff --git a/RobotApp.Client/Pages/RobotConfigManager.razor b/RobotApp.Client/Pages/RobotConfigManager.razor index aa54d06..016134f 100644 --- a/RobotApp.Client/Pages/RobotConfigManager.razor +++ b/RobotApp.Client/Pages/RobotConfigManager.razor @@ -83,7 +83,7 @@ @switch (SelectedType) { case RobotConfigType.VDA5050: - + break; case RobotConfigType.Safety: @@ -204,6 +204,8 @@ private RobotConfigType SelectedType = RobotConfigType.VDA5050; + private RobotApp.Client.Pages.Components.Config.RobotVDA5050Config RobotVDA5050ConfigRef = default!; + private int SelectedIndex = -1; private bool HasSelection => SelectedIndex >= 0; private bool IsLoading = false; diff --git a/RobotApp.Client/Pages/RobotConfigManager.razor.cs b/RobotApp.Client/Pages/RobotConfigManager.razor.cs index 812716c..e34e059 100644 --- a/RobotApp.Client/Pages/RobotConfigManager.razor.cs +++ b/RobotApp.Client/Pages/RobotConfigManager.razor.cs @@ -2,6 +2,7 @@ using RobotApp.Common.Shares; using RobotApp.Common.Shares.Dtos; using RobotApp.Common.Shares.Enums; +using System.Net.Http.Headers; using System.Net.Http.Json; using System.Xml.Schema; @@ -305,6 +306,33 @@ public partial class RobotConfigManager } } + private async Task SaveCertificates(Guid id) + { + using var content = new MultipartFormDataContent(); + + if (RobotVDA5050ConfigRef.CaFile is not null) + { + var fileContent = new StreamContent(RobotVDA5050ConfigRef.CaFile.OpenReadStream(maxAllowedSize: RobotVDA5050ConfigRef.MaxFileSize)); + content.Add(fileContent, "CaFile", RobotVDA5050ConfigRef.CaFile.Name); + } + if (RobotVDA5050ConfigRef.CertFile is not null) + { + var fileContent = new StreamContent(RobotVDA5050ConfigRef.CertFile.OpenReadStream(maxAllowedSize: RobotVDA5050ConfigRef.MaxFileSize)); + content.Add(fileContent, "CertFile", RobotVDA5050ConfigRef.CertFile.Name); + } + if (RobotVDA5050ConfigRef.KeyFile is not null) + { + var fileContent = new StreamContent(RobotVDA5050ConfigRef.KeyFile.OpenReadStream(maxAllowedSize: RobotVDA5050ConfigRef.MaxFileSize)); + content.Add(fileContent, "KeyFile", RobotVDA5050ConfigRef.KeyFile.Name); + } + + var response = await (await Http.PostAsync($"api/File/certificates/{id}", content)).Content.ReadFromJsonAsync(); + if (response is null) Snackbar.Add("Failed to update certificates", Severity.Warning); + else if (!response.IsSuccess) Snackbar.Add(response.Message ?? "Failed to update certificates config", Severity.Warning); + else return true; + return false; + } + private async Task SaveConfig() { try @@ -344,9 +372,14 @@ public partial class RobotConfigManager SelectedVda.VDA5050PublishRepeat, SelectedVda.VDA5050EnablePassword, SelectedVda.VDA5050EnableTls, + SelectedVda.VDA5050CA, + SelectedVda.VDA5050Cer, + SelectedVda.VDA5050Key, SelectedVda.Description }; - result = await (await Http.PutAsJsonAsync($"api/RobotConfigs/vda5050/{id}", updateDto)).Content.ReadFromJsonAsync(); + var saveCer = await SaveCertificates(SelectedVda.Id); + if (saveCer) result = await (await Http.PutAsJsonAsync($"api/RobotConfigs/vda5050/{id}", updateDto)).Content.ReadFromJsonAsync(); + else return; break; } diff --git a/RobotApp.Client/wwwroot/js/app.js b/RobotApp.Client/wwwroot/js/app.js new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/RobotApp.Client/wwwroot/js/app.js @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/RobotApp.Common.Shares/Dtos/RobotVDA5050ConfigDto.cs b/RobotApp.Common.Shares/Dtos/RobotVDA5050ConfigDto.cs index faa6cce..ac1ab76 100644 --- a/RobotApp.Common.Shares/Dtos/RobotVDA5050ConfigDto.cs +++ b/RobotApp.Common.Shares/Dtos/RobotVDA5050ConfigDto.cs @@ -23,7 +23,7 @@ public record RobotVDA5050ConfigDto public bool VDA5050EnableTls { get; set; } public string VDA5050CA { get; set; } public string VDA5050Cer { get; set; } - public string VDA5050_Key { get; set; } + public string VDA5050Key { get; set; } public DateTime CreatedAt { get; set; } public DateTime UpdatedAt { get; set; } public bool IsActive { get; set; } @@ -45,7 +45,7 @@ public record UpdateRobotVDA5050ConfigDto public bool VDA5050EnableTls { get; set; } public string VDA5050CA { get; set; } public string VDA5050Cer { get; set; } - public string VDA5050_Key { get; set; } + public string VDA5050Key { get; set; } public string Description { get; set; } } @@ -63,7 +63,7 @@ public record CreateRobotVDA5050ConfigDto public bool VDA5050EnableTls { get; set; } public string VDA5050CA { get; set; } public string VDA5050Cer { get; set; } - public string VDA5050_Key { get; set; } + public string VDA5050Key { get; set; } public string ConfigName { get; set; } public string Description { get; set; } } diff --git a/RobotApp/Components/App.razor b/RobotApp/Components/App.razor index d54d1b7..05a1e6a 100644 --- a/RobotApp/Components/App.razor +++ b/RobotApp/Components/App.razor @@ -41,6 +41,7 @@ + diff --git a/RobotApp/Controllers/FileController.cs b/RobotApp/Controllers/FileController.cs new file mode 100644 index 0000000..2b3d8e0 --- /dev/null +++ b/RobotApp/Controllers/FileController.cs @@ -0,0 +1,76 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using RobotApp.Common.Shares; + +namespace RobotApp.Controllers; + +[Route("api/[controller]")] +[ApiController] +[Authorize] +public class FileController(Services.Logger Logger) : ControllerBase +{ + private readonly string certificatesPath = "MqttCertificates"; + private readonly string caFilePath = "ca"; + private readonly string cerFilePath = "cer"; + private readonly string keyFilePath = "key"; + + [HttpPost] + [Route("certificates/{id:guid}")] + public async Task UpdateMqttCertificates(Guid id, [FromForm(Name = "CaFile")] IFormFile? caFile, + [FromForm(Name = "CertFile")] IFormFile? certFile, + [FromForm(Name = "KeyFile")] IFormFile? keyFile) + { + try + { + if (!Directory.Exists(certificatesPath)) Directory.CreateDirectory(certificatesPath); + + if (caFile is not null) + { + var caFolder = Path.Combine(certificatesPath, caFilePath); + if (!Directory.Exists(caFolder)) Directory.CreateDirectory(caFolder); + string caExtension = Path.GetExtension(caFile.FileName); + var caLocal = Path.Combine(caFolder, $"{id}{caExtension}"); + + if (System.IO.File.Exists($"{caLocal}.bk")) System.IO.File.Delete($"{caLocal}.bk"); + if (System.IO.File.Exists(caLocal)) System.IO.File.Move(caLocal, $"{caLocal}.bk"); + + using Stream fileStream = new FileStream(caLocal, FileMode.Create); + await caFile.OpenReadStream().CopyToAsync(fileStream); + } + + if (certFile is not null) + { + var certFolder = Path.Combine(certificatesPath, cerFilePath); + if (!Directory.Exists(certFolder)) Directory.CreateDirectory(certFolder); + string certExtension = Path.GetExtension(certFile.FileName); + var certLocal = Path.Combine(certFolder, $"{id}{certExtension}"); + + if (System.IO.File.Exists($"{certLocal}.bk")) System.IO.File.Delete($"{certLocal}.bk"); + if (System.IO.File.Exists(certLocal)) System.IO.File.Move(certLocal, $"{certLocal}.bk"); + + using Stream fileStream = new FileStream(certLocal, FileMode.Create); + await certFile.OpenReadStream().CopyToAsync(fileStream); + } + + if (keyFile is not null) + { + var keyFolder = Path.Combine(certificatesPath, keyFilePath); + if (!Directory.Exists(keyFolder)) Directory.CreateDirectory(keyFolder); + string keyExtension = Path.GetExtension(keyFile.FileName); + var keyLocal = Path.Combine(keyFolder, $"{id}{keyExtension}"); + + if (System.IO.File.Exists($"{keyLocal}.bk")) System.IO.File.Delete($"{keyLocal}.bk"); + if (System.IO.File.Exists(keyLocal)) System.IO.File.Move(keyLocal, $"{keyLocal}.bk"); + + using Stream fileStream = new FileStream(keyLocal, FileMode.Create); + await keyFile.OpenReadStream().CopyToAsync(fileStream); + } + return new(true, ""); + } + catch (Exception ex) + { + Logger.Error($"Update Mqtt Certificates is failed: {ex.Message}"); + return new(false, "An error occurred while retrieving update Mqtt Certificates."); + } + } +} diff --git a/RobotApp/Controllers/RobotConfigsController.cs b/RobotApp/Controllers/RobotConfigsController.cs index e7277aa..84fa62a 100644 --- a/RobotApp/Controllers/RobotConfigsController.cs +++ b/RobotApp/Controllers/RobotConfigsController.cs @@ -1,5 +1,4 @@ using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using RobotApp.Common.Shares; @@ -196,7 +195,7 @@ public class RobotConfigsController(Services.Logger Logg VDA5050EnableTls = config.VDA5050EnableTls, VDA5050CA = config.VDA5050CA, VDA5050Cer = config.VDA5050Cer, - VDA5050_Key = config.VDA5050_Key, + VDA5050Key = config.VDA5050Key, CreatedAt = config.CreatedAt, UpdatedAt = config.UpdatedAt, IsActive = config.IsActive, @@ -234,7 +233,7 @@ public class RobotConfigsController(Services.Logger Logg config.VDA5050EnableTls = updateDto.VDA5050EnableTls; config.VDA5050CA = updateDto.VDA5050CA; config.VDA5050Cer = updateDto.VDA5050Cer; - config.VDA5050_Key = updateDto.VDA5050_Key; + config.VDA5050Key = updateDto.VDA5050Key; config.Description = updateDto.Description ?? config.Description; config.UpdatedAt = DateTime.Now; @@ -276,7 +275,7 @@ public class RobotConfigsController(Services.Logger Logg VDA5050EnableTls = createDto.VDA5050EnableTls, VDA5050CA = createDto.VDA5050CA, VDA5050Cer = createDto.VDA5050Cer, - VDA5050_Key = createDto.VDA5050_Key, + VDA5050Key = createDto.VDA5050Key, CreatedAt = DateTime.Now, UpdatedAt = DateTime.Now, IsActive = false @@ -304,7 +303,7 @@ public class RobotConfigsController(Services.Logger Logg VDA5050EnableTls = config.VDA5050EnableTls, VDA5050CA = config.VDA5050CA, VDA5050Cer = config.VDA5050Cer, - VDA5050_Key = config.VDA5050_Key, + VDA5050Key = config.VDA5050Key, CreatedAt = config.CreatedAt, UpdatedAt = config.UpdatedAt, IsActive = config.IsActive, @@ -860,5 +859,4 @@ public class RobotConfigsController(Services.Logger Logg return new(false, "An error occurred while updating the active Safety configuration."); } } - } diff --git a/RobotApp/Data/Migrations/20251031080648_UpdateVDA5050Config1.Designer.cs b/RobotApp/Data/Migrations/20251031080648_UpdateVDA5050Config1.Designer.cs new file mode 100644 index 0000000..2b495f6 --- /dev/null +++ b/RobotApp/Data/Migrations/20251031080648_UpdateVDA5050Config1.Designer.cs @@ -0,0 +1,577 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using RobotApp.Data; + +#nullable disable + +namespace RobotApp.Data.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20251031080648_UpdateVDA5050Config1")] + partial class UpdateVDA5050Config1 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.9"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("RobotApp.Data.ApplicationRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("RobotApp.Data.ApplicationUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("RobotApp.Data.RobotConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("Id"); + + b.Property("ConfigName") + .HasMaxLength(100) + .HasColumnType("nvarchar(64)") + .HasColumnName("ConfigName"); + + b.Property("CreatedAt") + .HasColumnType("datetime2") + .HasColumnName("CreatedAt"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("ntext") + .HasColumnName("Description"); + + b.Property("Height") + .HasColumnType("float") + .HasColumnName("Height"); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnName("IsActive"); + + b.Property("Length") + .HasColumnType("float") + .HasColumnName("Length"); + + b.Property("NavigationType") + .HasColumnType("int") + .HasColumnName("NavigationType"); + + b.Property("RadiusWheel") + .HasColumnType("float") + .HasColumnName("RadiusWheel"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2") + .HasColumnName("UpdatedAt"); + + b.Property("Width") + .HasColumnType("float") + .HasColumnName("Width"); + + b.HasKey("Id"); + + b.ToTable("RobotConfig"); + }); + + modelBuilder.Entity("RobotApp.Data.RobotPlcConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("Id"); + + b.Property("ConfigName") + .HasMaxLength(100) + .HasColumnType("nvarchar(64)") + .HasColumnName("ConfigName"); + + b.Property("CreatedAt") + .HasColumnType("datetime2") + .HasColumnName("CreatedAt"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("ntext") + .HasColumnName("Description"); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnName("IsActive"); + + b.Property("PLCAddress") + .HasMaxLength(50) + .HasColumnType("nvarchar(64)") + .HasColumnName("PLCAddress"); + + b.Property("PLCPort") + .HasColumnType("int") + .HasColumnName("PLCPort"); + + b.Property("PLCUnitId") + .HasColumnType("tinyint") + .HasColumnName("PLCUnitId"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2") + .HasColumnName("UpdatedAt"); + + b.HasKey("Id"); + + b.ToTable("RobotPlcConfig"); + }); + + modelBuilder.Entity("RobotApp.Data.RobotSafetyConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("Id"); + + b.Property("ConfigName") + .HasMaxLength(100) + .HasColumnType("nvarchar(64)") + .HasColumnName("ConfigName"); + + b.Property("CreatedAt") + .HasColumnType("datetime2") + .HasColumnName("CreatedAt"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("ntext") + .HasColumnName("Description"); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnName("IsActive"); + + b.Property("SafetySpeedFast") + .HasColumnType("float") + .HasColumnName("SafetySpeedFast"); + + b.Property("SafetySpeedMedium") + .HasColumnType("float") + .HasColumnName("SafetySpeedMedium"); + + b.Property("SafetySpeedNormal") + .HasColumnType("float") + .HasColumnName("SafetySpeedNormal"); + + b.Property("SafetySpeedOptimal") + .HasColumnType("float") + .HasColumnName("SafetySpeedOptimal"); + + b.Property("SafetySpeedSlow") + .HasColumnType("float") + .HasColumnName("SafetySpeedSlow"); + + b.Property("SafetySpeedVeryFast") + .HasColumnType("float") + .HasColumnName("SafetySpeedVeryFast"); + + b.Property("SafetySpeedVerySlow") + .HasColumnType("float") + .HasColumnName("SafetySpeedVerySlow"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2") + .HasColumnName("UpdatedAt"); + + b.HasKey("Id"); + + b.ToTable("RobotSafetyConfig"); + }); + + modelBuilder.Entity("RobotApp.Data.RobotSimulationConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("Id"); + + b.Property("ConfigName") + .HasMaxLength(100) + .HasColumnType("nvarchar(64)") + .HasColumnName("ConfigName"); + + b.Property("CreatedAt") + .HasColumnType("datetime2") + .HasColumnName("CreatedAt"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("ntext") + .HasColumnName("Description"); + + b.Property("EnableSimulation") + .HasColumnType("bit") + .HasColumnName("EnableSimulation"); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnName("IsActive"); + + b.Property("SimulationAcceleration") + .HasColumnType("float") + .HasColumnName("SimulationAcceleration"); + + b.Property("SimulationDeceleration") + .HasColumnType("float") + .HasColumnName("SimulationDeceleration"); + + b.Property("SimulationMaxAngularVelocity") + .HasColumnType("float") + .HasColumnName("SimulationMaxAngularVelocity"); + + b.Property("SimulationMaxVelocity") + .HasColumnType("float") + .HasColumnName("SimulationMaxVelocity"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2") + .HasColumnName("UpdatedAt"); + + b.HasKey("Id"); + + b.ToTable("RobotSimulationConfig"); + }); + + modelBuilder.Entity("RobotApp.Data.RobotVDA5050Config", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnName("Id"); + + b.Property("ConfigName") + .HasMaxLength(100) + .HasColumnType("nvarchar(64)") + .HasColumnName("ConfigName"); + + b.Property("CreatedAt") + .HasColumnType("datetime2") + .HasColumnName("CreatedAt"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("ntext") + .HasColumnName("Description"); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnName("IsActive"); + + b.Property("SerialNumber") + .HasMaxLength(50) + .HasColumnType("nvarchar(64)") + .HasColumnName("SerialNumber"); + + b.Property("UpdatedAt") + .HasColumnType("datetime2") + .HasColumnName("UpdatedAt"); + + b.Property("VDA5050CA") + .HasColumnType("nvarchar(64)") + .HasColumnName("VDA5050_CA"); + + b.Property("VDA5050Cer") + .HasColumnType("nvarchar(64)") + .HasColumnName("VDA5050_Cer"); + + b.Property("VDA5050EnablePassword") + .HasColumnType("bit") + .HasColumnName("VDA5050_EnablePassword"); + + b.Property("VDA5050EnableTls") + .HasColumnType("bit") + .HasColumnName("VDA5050_EnableTls"); + + b.Property("VDA5050HostServer") + .HasMaxLength(100) + .HasColumnType("nvarchar(64)") + .HasColumnName("VDA5050_HostServer"); + + b.Property("VDA5050Key") + .HasColumnType("nvarchar(64)") + .HasColumnName("VDA5050_Key"); + + b.Property("VDA5050Manufacturer") + .HasMaxLength(50) + .HasColumnType("nvarchar(64)") + .HasColumnName("VDA5050_Manufacturer"); + + b.Property("VDA5050Password") + .HasMaxLength(50) + .HasColumnType("nvarchar(64)") + .HasColumnName("VDA5050_Password"); + + b.Property("VDA5050Port") + .HasColumnType("int") + .HasColumnName("VDA5050_Port"); + + b.Property("VDA5050PublishRepeat") + .HasColumnType("int") + .HasColumnName("VDA5050_PublishRepeat"); + + b.Property("VDA5050UserName") + .HasMaxLength(50) + .HasColumnType("nvarchar(64)") + .HasColumnName("VDA5050_UserName"); + + b.Property("VDA5050Version") + .HasMaxLength(20) + .HasColumnType("nvarchar(64)") + .HasColumnName("VDA5050_Version"); + + b.HasKey("Id"); + + b.ToTable("RobotVDA5050Config"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("RobotApp.Data.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("RobotApp.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("RobotApp.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("RobotApp.Data.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("RobotApp.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("RobotApp.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/RobotApp/Data/Migrations/20251031080648_UpdateVDA5050Config1.cs b/RobotApp/Data/Migrations/20251031080648_UpdateVDA5050Config1.cs new file mode 100644 index 0000000..642bbb3 --- /dev/null +++ b/RobotApp/Data/Migrations/20251031080648_UpdateVDA5050Config1.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace RobotApp.Data.Migrations +{ + /// + public partial class UpdateVDA5050Config1 : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/RobotApp/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/RobotApp/Data/Migrations/ApplicationDbContextModelSnapshot.cs index d4f4b21..39e24f0 100644 --- a/RobotApp/Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/RobotApp/Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -481,6 +481,10 @@ namespace RobotApp.Migrations .HasColumnType("nvarchar(64)") .HasColumnName("VDA5050_HostServer"); + b.Property("VDA5050Key") + .HasColumnType("nvarchar(64)") + .HasColumnName("VDA5050_Key"); + b.Property("VDA5050Manufacturer") .HasMaxLength(50) .HasColumnType("nvarchar(64)") @@ -509,10 +513,6 @@ namespace RobotApp.Migrations .HasColumnType("nvarchar(64)") .HasColumnName("VDA5050_Version"); - b.Property("VDA5050_Key") - .HasColumnType("nvarchar(64)") - .HasColumnName("VDA5050_Key"); - b.HasKey("Id"); b.ToTable("RobotVDA5050Config"); diff --git a/RobotApp/Data/RobotVDA5050Config.cs b/RobotApp/Data/RobotVDA5050Config.cs index 1cd0f5f..7cf649b 100644 --- a/RobotApp/Data/RobotVDA5050Config.cs +++ b/RobotApp/Data/RobotVDA5050Config.cs @@ -58,7 +58,7 @@ public class RobotVDA5050Config public string VDA5050Cer { get; set; } [Column("VDA5050_Key", TypeName = "nvarchar(64)")] - public string VDA5050_Key { get; set; } + public string VDA5050Key { get; set; } [Column("CreatedAt", TypeName = "datetime2")] public DateTime CreatedAt { get; set; } diff --git a/RobotApp/robot.db b/RobotApp/robot.db index a181009a0ae6794a7e1a27661e55758b90e3212e..627e3b5e8e44c132cce50ce5c544b07212327e07 100644 GIT binary patch delta 204 zcmZozz}2vTYl1Xm=|mZ4#?p-m-SXNNRt9EPrY3rpMn=Y#<`&up237_JybKHs?0okb z_%HKs;qT{9;kV%D;k&MJz|+P4SVGj0#GXIdWs0P=w}+yDRo delta 114 zcmZozz}2vTYl1Xm(L@<%#-fc0-SV2|R>nqF#+G^}mIfvkX2#kE237_JybKHsZ2UY7 z{FnK+@b~kl@LTZnY!(#w!8e&l|Azn@zcvH^P5%A-^Z6_JgZQ<9GUEI!YRrL*lLhsa Sngi|I1ML~N2ih~O4*&ps3mlmM