From c0ed335d8409f28607fce7a7f4ebad8bf228e2fb Mon Sep 17 00:00:00 2001 From: sbwalker Date: Mon, 9 Oct 2023 14:26:56 -0400 Subject: [PATCH] Add Rows option to Profile Management. Improve Profile validation feedback. Fix Add User so that profile Options are supported. --- .../Modules/Admin/Profiles/Edit.razor | 11 +- .../Modules/Admin/UserProfile/Index.razor | 106 +++++++++++------- Oqtane.Client/Modules/Admin/Users/Add.razor | 102 ++++++++++++----- Oqtane.Client/Modules/Admin/Users/Edit.razor | 84 +++++++++----- Oqtane.Client/Resources/SharedResources.resx | 6 + .../Tenant/04000601_AddProfileRows.cs | 29 +++++ Oqtane.Shared/Models/Profile.cs | 5 + 7 files changed, 239 insertions(+), 104 deletions(-) create mode 100644 Oqtane.Server/Migrations/Tenant/04000601_AddProfileRows.cs diff --git a/Oqtane.Client/Modules/Admin/Profiles/Edit.razor b/Oqtane.Client/Modules/Admin/Profiles/Edit.razor index 9620a396..33ec94b0 100644 --- a/Oqtane.Client/Modules/Admin/Profiles/Edit.razor +++ b/Oqtane.Client/Modules/Admin/Profiles/Edit.razor @@ -22,7 +22,7 @@
- +
@@ -43,6 +43,12 @@
+
+ +
+ +
+
@@ -101,6 +107,7 @@ private string _category = string.Empty; private string _vieworder = "0"; private string _maxlength = "0"; + private string _rows = "1"; private string _defaultvalue = string.Empty; private string _options = string.Empty; private string _validation = string.Empty; @@ -131,6 +138,7 @@ _category = profile.Category; _vieworder = profile.ViewOrder.ToString(); _maxlength = profile.MaxLength.ToString(); + _rows = profile.Rows.ToString(); _defaultvalue = profile.DefaultValue; _options = profile.Options; _validation = profile.Validation; @@ -175,6 +183,7 @@ profile.Category = _category; profile.ViewOrder = int.Parse(_vieworder); profile.MaxLength = int.Parse(_maxlength); + profile.Rows = int.Parse(_rows); profile.DefaultValue = _defaultvalue; profile.Options = _options; profile.Validation = _validation; diff --git a/Oqtane.Client/Modules/Admin/UserProfile/Index.razor b/Oqtane.Client/Modules/Admin/UserProfile/Index.razor index a10202ee..694f28aa 100644 --- a/Oqtane.Client/Modules/Admin/UserProfile/Index.razor +++ b/Oqtane.Client/Modules/Admin/UserProfile/Index.razor @@ -123,13 +123,27 @@ else } else { - @if (p.IsRequired) + @if (p.Rows == 1) { - + @if (p.IsRequired) + { + + } + else + { + + } } else { - + @if (p.IsRequired) + { + + } + else + { + + } } }
@@ -282,9 +296,11 @@ else private int folderid = -1; private int photofileid = -1; private File photo = null; + private List profiles; private Dictionary settings; private string category = string.Empty; + private string filter = "to"; private List notifications; private string notificationSummary = string.Empty; @@ -363,44 +379,47 @@ else { try { - if (username != string.Empty && email != string.Empty && ValidateProfiles()) + if (username != string.Empty && email != string.Empty) { if (_password == confirm) { - var user = PageState.User; - user.Username = username; - user.Password = _password; - user.TwoFactorRequired = bool.Parse(twofactor); - user.Email = email; - user.DisplayName = (displayname == string.Empty ? username : displayname); - user.PhotoFileId = filemanager.GetFileId(); - if (user.PhotoFileId == -1) + if (ValidateProfiles()) { - user.PhotoFileId = null; - } - if (user.PhotoFileId != null) - { - photofileid = user.PhotoFileId.Value; - photo = await FileService.GetFileAsync(photofileid); - } - else - { - photofileid = -1; - photo = null; - } + var user = PageState.User; + user.Username = username; + user.Password = _password; + user.TwoFactorRequired = bool.Parse(twofactor); + user.Email = email; + user.DisplayName = (displayname == string.Empty ? username : displayname); + user.PhotoFileId = filemanager.GetFileId(); + if (user.PhotoFileId == -1) + { + user.PhotoFileId = null; + } + if (user.PhotoFileId != null) + { + photofileid = user.PhotoFileId.Value; + photo = await FileService.GetFileAsync(photofileid); + } + else + { + photofileid = -1; + photo = null; + } - user = await UserService.UpdateUserAsync(user); - if (user != null) - { - await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId); - await logger.LogInformation("User Profile Saved"); + user = await UserService.UpdateUserAsync(user); + if (user != null) + { + await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId); + await logger.LogInformation("User Profile Saved"); - AddModuleMessage(Localizer["Success.Profile.Update"], MessageType.Success); - StateHasChanged(); - } - else - { - AddModuleMessage(Localizer["Message.Password.Complexity"], MessageType.Error); + AddModuleMessage(Localizer["Success.Profile.Update"], MessageType.Success); + StateHasChanged(); + } + else + { + AddModuleMessage(Localizer["Message.Password.Complexity"], MessageType.Error); + } } } else @@ -424,7 +443,6 @@ else private bool ValidateProfiles() { - bool valid = true; foreach (Profile profile in profiles) { if (string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)) && !string.IsNullOrEmpty(profile.DefaultValue)) @@ -433,18 +451,24 @@ else } if (!profile.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin)) { - if (valid == true && profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty))) + if (profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty))) { - valid = false; + AddModuleMessage(string.Format(SharedLocalizer["ProfileRequired"], profile.Title), MessageType.Warning); + return false; } - if (valid == true && !string.IsNullOrEmpty(profile.Validation)) + if (!string.IsNullOrEmpty(profile.Validation)) { Regex regex = new Regex(profile.Validation); - valid = regex.Match(SettingService.GetSetting(settings, profile.Name, string.Empty)).Success; + bool valid = regex.Match(SettingService.GetSetting(settings, profile.Name, string.Empty)).Success; + if (!valid) + { + AddModuleMessage(string.Format(SharedLocalizer["ProfileInvalid"], profile.Title), MessageType.Warning); + return false; + } } } } - return valid; + return true; } private void Cancel() diff --git a/Oqtane.Client/Modules/Admin/Users/Add.razor b/Oqtane.Client/Modules/Admin/Users/Add.razor index 817bf5e1..10f24ff1 100644 --- a/Oqtane.Client/Modules/Admin/Users/Add.razor +++ b/Oqtane.Client/Modules/Admin/Users/Add.razor @@ -80,18 +80,50 @@
- @if (p.IsRequired) + @if (!string.IsNullOrEmpty(p.Options)) { - + } else { - + @if (p.Rows == 1) + { + @if (p.IsRequired) + { + + } + else + { + + } + } + else + { + @if (p.IsRequired) + { + + } + else + { + + } + } }
} -
} @@ -148,31 +180,34 @@ { try { - if (_username != string.Empty && _password != string.Empty && _confirm != string.Empty && _email != string.Empty && ValidateProfiles()) + if (_username != string.Empty && _password != string.Empty && _confirm != string.Empty && _email != string.Empty) { if (_password == _confirm) { - var user = new User(); - user.SiteId = PageState.Site.SiteId; - user.Username = _username; - user.Password = _password; - user.Email = _email; - user.DisplayName = string.IsNullOrWhiteSpace(_displayname) ? _username : _displayname; - user.PhotoFileId = null; - user.SuppressNotification = !bool.Parse(_notify); - - user = await UserService.AddUserAsync(user); - - if (user != null) + if (ValidateProfiles()) { - await SettingService.UpdateUserSettingsAsync(settings, user.UserId); - await logger.LogInformation("User Created {User}", user); - NavigationManager.NavigateTo(NavigateUrl()); - } - else - { - await logger.LogError("Error Adding User {Username} {Email}", _username, _email); - AddModuleMessage(Localizer["Error.User.AddCheckPass"], MessageType.Error); + var user = new User(); + user.SiteId = PageState.Site.SiteId; + user.Username = _username; + user.Password = _password; + user.Email = _email; + user.DisplayName = string.IsNullOrWhiteSpace(_displayname) ? _username : _displayname; + user.PhotoFileId = null; + user.SuppressNotification = !bool.Parse(_notify); + + user = await UserService.AddUserAsync(user); + + if (user != null) + { + await SettingService.UpdateUserSettingsAsync(settings, user.UserId); + await logger.LogInformation("User Created {User}", user); + NavigationManager.NavigateTo(NavigateUrl()); + } + else + { + await logger.LogError("Error Adding User {Username} {Email}", _username, _email); + AddModuleMessage(Localizer["Error.User.AddCheckPass"], MessageType.Error); + } } } else @@ -194,7 +229,6 @@ private bool ValidateProfiles() { - bool valid = true; foreach (Profile profile in profiles) { if (string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)) && !string.IsNullOrEmpty(profile.DefaultValue)) @@ -203,18 +237,24 @@ } if (!profile.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin)) { - if (valid == true && profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty))) + if (profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty))) { - valid = false; + AddModuleMessage(string.Format(SharedLocalizer["ProfileRequired"], profile.Title), MessageType.Warning); + return false; } - if (valid == true && !string.IsNullOrEmpty(profile.Validation)) + if (!string.IsNullOrEmpty(profile.Validation)) { Regex regex = new Regex(profile.Validation); - valid = regex.Match(SettingService.GetSetting(settings, profile.Name, string.Empty)).Success; + bool valid = regex.Match(SettingService.GetSetting(settings, profile.Name, string.Empty)).Success; + if (!valid) + { + AddModuleMessage(string.Format(SharedLocalizer["ProfileInvalid"], profile.Title), MessageType.Warning); + return false; + } } } } - return valid; + return true; } private void ProfileChanged(ChangeEventArgs e, string SettingName) diff --git a/Oqtane.Client/Modules/Admin/Users/Edit.razor b/Oqtane.Client/Modules/Admin/Users/Edit.razor index 19fbbdd1..ea0198c9 100644 --- a/Oqtane.Client/Modules/Admin/Users/Edit.razor +++ b/Oqtane.Client/Modules/Admin/Users/Edit.razor @@ -125,13 +125,27 @@ else } else { - @if (p.IsRequired) + @if (p.Rows == 1) { - + @if (p.IsRequired) + { + + } + else + { + + } } else { - + @if (p.IsRequired) + { + + } + else + { + + } } } @@ -240,35 +254,38 @@ else { try { - if (username != string.Empty && email != string.Empty && ValidateProfiles()) + if (username != string.Empty && email != string.Empty) { if (_password == confirm) { - var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId); - user.SiteId = PageState.Site.SiteId; - user.Username = username; - user.Password = _password; - user.Email = email; - user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname; - user.PhotoFileId = null; - user.PhotoFileId = filemanager.GetFileId(); - if (user.PhotoFileId == -1) + if (ValidateProfiles()) { + var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId); + user.SiteId = PageState.Site.SiteId; + user.Username = username; + user.Password = _password; + user.Email = email; + user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname; user.PhotoFileId = null; - } + user.PhotoFileId = filemanager.GetFileId(); + if (user.PhotoFileId == -1) + { + user.PhotoFileId = null; + } - user.IsDeleted = (isdeleted == null ? true : Boolean.Parse(isdeleted)); + user.IsDeleted = (isdeleted == null ? true : Boolean.Parse(isdeleted)); - user = await UserService.UpdateUserAsync(user); - if (user != null) - { - await SettingService.UpdateUserSettingsAsync(settings, user.UserId); - await logger.LogInformation("User Saved {User}", user); - NavigationManager.NavigateTo(NavigateUrl()); - } - else - { - AddModuleMessage(Localizer["Message.Password.Complexity"], MessageType.Error); + user = await UserService.UpdateUserAsync(user); + if (user != null) + { + await SettingService.UpdateUserSettingsAsync(settings, user.UserId); + await logger.LogInformation("User Saved {User}", user); + NavigationManager.NavigateTo(NavigateUrl()); + } + else + { + AddModuleMessage(Localizer["Message.Password.Complexity"], MessageType.Error); + } } } else @@ -290,7 +307,6 @@ else private bool ValidateProfiles() { - bool valid = true; foreach (Profile profile in profiles) { if (string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)) && !string.IsNullOrEmpty(profile.DefaultValue)) @@ -299,18 +315,24 @@ else } if (!profile.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin)) { - if (valid == true && profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty))) + if (profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty))) { - valid = false; + AddModuleMessage(string.Format(SharedLocalizer["ProfileRequired"], profile.Title), MessageType.Warning); + return false; } - if (valid == true && !string.IsNullOrEmpty(profile.Validation)) + if (!string.IsNullOrEmpty(profile.Validation)) { Regex regex = new Regex(profile.Validation); - valid = regex.Match(SettingService.GetSetting(settings, profile.Name, string.Empty)).Success; + bool valid = regex.Match(SettingService.GetSetting(settings, profile.Name, string.Empty)).Success; + if (!valid) + { + AddModuleMessage(string.Format(SharedLocalizer["ProfileInvalid"], profile.Title), MessageType.Warning); + return false; + } } } } - return valid; + return true; } private void ProfileChanged(ChangeEventArgs e, string SettingName) diff --git a/Oqtane.Client/Resources/SharedResources.resx b/Oqtane.Client/Resources/SharedResources.resx index c547480a..b225811b 100644 --- a/Oqtane.Client/Resources/SharedResources.resx +++ b/Oqtane.Client/Resources/SharedResources.resx @@ -426,4 +426,10 @@ Passwords Must Have A Minimum Length Of {0} Characters, Including At Least {1} Unique Character(s), {2}{3}{4}{5} To Satisfy Password Compexity Requirements For This Site. + + {0} Is Not Valid + + + {0} Is Required + \ No newline at end of file diff --git a/Oqtane.Server/Migrations/Tenant/04000601_AddProfileRows.cs b/Oqtane.Server/Migrations/Tenant/04000601_AddProfileRows.cs new file mode 100644 index 00000000..976706ce --- /dev/null +++ b/Oqtane.Server/Migrations/Tenant/04000601_AddProfileRows.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Oqtane.Databases.Interfaces; +using Oqtane.Migrations.EntityBuilders; +using Oqtane.Repository; + +namespace Oqtane.Migrations.Tenant +{ + [DbContext(typeof(TenantDBContext))] + [Migration("Tenant.04.00.06.01")] + public class AddProfileRows : MultiDatabaseMigration + { + public AddProfileRows(IDatabase database) : base(database) + { + } + + protected override void Up(MigrationBuilder migrationBuilder) + { + var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase); + profileEntityBuilder.AddIntegerColumn("Rows", true); + profileEntityBuilder.UpdateColumn("Rows", "1"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + // not implemented + } + } +} diff --git a/Oqtane.Shared/Models/Profile.cs b/Oqtane.Shared/Models/Profile.cs index e5586a13..336cd262 100644 --- a/Oqtane.Shared/Models/Profile.cs +++ b/Oqtane.Shared/Models/Profile.cs @@ -73,5 +73,10 @@ namespace Oqtane.Models /// Optional RegExp validation expression /// public string Validation { get; set; } + + /// + /// Optional number of rows (textarea) + /// + public int Rows { get; set; } } }