From 90269212142668e07d4b85be22edc709b5db2256 Mon Sep 17 00:00:00 2001 From: mostafametwally Date: Fri, 16 Feb 2024 11:54:15 +0100 Subject: [PATCH 01/15] display verification message instead of redirecting new user before email verification --- .../Modules/Admin/Register/Index.razor | 118 +++++++++--------- 1 file changed, 58 insertions(+), 60 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Register/Index.razor b/Oqtane.Client/Modules/Admin/Register/Index.razor index b7c80851..98fc932f 100644 --- a/Oqtane.Client/Modules/Admin/Register/Index.razor +++ b/Oqtane.Client/Modules/Admin/Register/Index.razor @@ -9,60 +9,63 @@ @if (PageState.Site.AllowRegistration) { - - - ... - - - - - - -
-
-
- -
- + if (!_userCreated) + { + + + ... + + + + + + + +
+
+ +
+ +
+
+
+ +
+
+ + +
+
+
+
+ +
+
+ + +
+
+
+
+ +
+ +
+
+
+ +
+ +
-
- -
-
- - -
-
-
-
- -
-
- - -
-
-
-
- -
- -
-
-
- -
- -
-
-
-
- - - - - +
+ + + + + + } } else { @@ -80,6 +83,7 @@ else private string _confirm = string.Empty; private string _email = string.Empty; private string _displayname = string.Empty; + private bool _userCreated = false; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous; @@ -121,14 +125,8 @@ else if (user != null) { await logger.LogInformation("User Created {Username} {Email}", _username, _email); - if (PageState.QueryString.ContainsKey("returnurl")) - { - NavigationManager.NavigateTo(WebUtility.UrlDecode(PageState.QueryString["returnurl"])); - } - else // legacy behavior - { - AddModuleMessage(Localizer["Info.User.AccountCreate"], MessageType.Info); - } + _userCreated = true; + AddModuleMessage(Localizer["Info.User.AccountCreate"], MessageType.Info); } else { From b68fc6187f5df74a937bab0ea17a9ec47db7dcf3 Mon Sep 17 00:00:00 2001 From: mostafametwally Date: Fri, 16 Feb 2024 22:04:12 +0100 Subject: [PATCH 02/15] localized usermanager email messages and message formatting to include site name and link #3794 --- Oqtane.Server/Managers/UserManager.cs | 71 ++++++--- .../Resources/Managers.UserManager.resx | 150 ++++++++++++++++++ 2 files changed, 200 insertions(+), 21 deletions(-) create mode 100644 Oqtane.Server/Resources/Managers.UserManager.resx diff --git a/Oqtane.Server/Managers/UserManager.cs b/Oqtane.Server/Managers/UserManager.cs index 4d273be7..20ebc948 100644 --- a/Oqtane.Server/Managers/UserManager.cs +++ b/Oqtane.Server/Managers/UserManager.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Localization; using Oqtane.Enums; using Oqtane.Infrastructure; using Oqtane.Models; @@ -29,8 +30,10 @@ namespace Oqtane.Managers private readonly ISettingRepository _settings; private readonly ISyncManager _syncManager; private readonly ILogManager _logger; + private readonly IStringLocalizer _localizer; + private readonly ISiteRepository _siteRepo; - public UserManager(IUserRepository users, IRoleRepository roles, IUserRoleRepository userRoles, UserManager identityUserManager, SignInManager identitySignInManager, ITenantManager tenantManager, INotificationRepository notifications, IFolderRepository folders, IFileRepository files, IProfileRepository profiles, ISettingRepository settings, ISyncManager syncManager, ILogManager logger) + public UserManager(IUserRepository users, IRoleRepository roles, IUserRoleRepository userRoles, UserManager identityUserManager, SignInManager identitySignInManager, ITenantManager tenantManager, INotificationRepository notifications, IFolderRepository folders, IFileRepository files, IProfileRepository profiles, ISettingRepository settings, ISyncManager syncManager, ILogManager logger, IStringLocalizer localizer, ISiteRepository siteRepo) { _users = users; _roles = roles; @@ -45,6 +48,8 @@ namespace Oqtane.Managers _settings = settings; _syncManager = syncManager; _logger = logger; + _localizer = localizer; + _siteRepo = siteRepo; } public User GetUser(int userid, int siteid) @@ -148,21 +153,33 @@ namespace Oqtane.Managers if (User != null) { + string siteName = _siteRepo.GetSite(user.SiteId).Name; if (!user.EmailConfirmed) { string token = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser); string url = alias.Protocol + alias.Name + "/login?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token); - string body = "Dear " + user.DisplayName + ",\n\nIn Order To Verify The Email Address Associated To Your User Account Please Click The Link Displayed Below:\n\n" + url + "\n\nThank You!"; - var notification = new Notification(user.SiteId, User, "User Account Verification", body); + string subject = _localizer["VerificationEmailSubject"]; + subject = subject.Replace("[SiteName]", siteName); + string body = _localizer["VerificationEmailBody"].Value; + body = body.Replace("[UserDisplayName]", user.DisplayName); + body = body.Replace("[URL]", url); + body = body.Replace("[SiteName]", siteName); + var notification = new Notification(alias.SiteId, User, subject, body); _notifications.AddNotification(notification); } else { if (!user.SuppressNotification) { - string url = alias.Protocol + alias.Name; - string body = "Dear " + user.DisplayName + ",\n\nA User Account Has Been Successfully Created For You With The Username " + user.Username + ". Please Visit " + url + " And Use The Login Option To Sign In. If You Do Not Know Your Password, Use The Forgot Password Option On The Login Page To Reset Your Account.\n\nThank You!"; - var notification = new Notification(user.SiteId, User, "User Account Notification", body); + string url = alias.Protocol + alias.Name + "/login"; + string subject = _localizer["NoVerificationEmailSubject"]; + subject = subject.Replace("[SiteName]", siteName); + string body = _localizer["NoVerificationEmailBody"].Value; + body = body.Replace("[UserDisplayName]", user.DisplayName); + body = body.Replace("[URL]", url); + body = body.Replace("[SiteName]", siteName); + body = body.Replace("[Username]", user.Username); + var notification = new Notification(alias.SiteId, User, subject, body); _notifications.AddNotification(notification); } } @@ -307,11 +324,17 @@ namespace Oqtane.Managers user.TwoFactorCode = token; user.TwoFactorExpiry = DateTime.UtcNow.AddMinutes(10); _users.UpdateUser(user); - - string body = "Dear " + user.DisplayName + ",\n\nYou requested a secure verification code to log in to your account. Please enter the secure verification code on the site:\n\n" + token + - "\n\nPlease note that the code is only valid for 10 minutes so if you are unable to take action within that time period, you should initiate a new login on the site." + - "\n\nThank You!"; - var notification = new Notification(user.SiteId, user, "User Verification Code", body); + var alias = _tenantManager.GetAlias(); + string url = alias.Protocol + alias.Name; + string siteName = _siteRepo.GetSite(alias.SiteId).Name; + string subject = _localizer["TwoFactorEmailSubject"]; + subject = subject.Replace("[SiteName]", siteName); + string body = _localizer["TwoFactorEmailBody"].Value; + body = body.Replace("[UserDisplayName]", user.DisplayName); + body = body.Replace("[URL]", url); + body = body.Replace("[SiteName]", siteName); + body = body.Replace("[Token]", token); + var notification = new Notification(alias.SiteId, user, subject, body); _notifications.AddNotification(notification); _logger.Log(LogLevel.Information, this, LogFunction.Security, "User Verification Notification Sent For {Username}", user.Username); @@ -355,10 +378,14 @@ namespace Oqtane.Managers user = _users.GetUser(user.Username); string token = await _identityUserManager.GeneratePasswordResetTokenAsync(identityuser); string url = alias.Protocol + alias.Name + "/reset?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token); - string body = "Dear " + user.DisplayName + ",\n\nYou attempted multiple times unsuccessfully to log in to your account and it is now locked out. Please wait a few minutes and then try again... or use the link below to reset your password:\n\n" + url + - "\n\nPlease note that the link is only valid for 24 hours so if you are unable to take action within that time period, you should initiate another password reset on the site." + - "\n\nThank You!"; - var notification = new Notification(user.SiteId, user, "User Lockout", body); + string siteName = _siteRepo.GetSite(alias.SiteId).Name; + string subject = _localizer["UserLockoutEmailSubject"]; + subject = subject.Replace("[SiteName]", siteName); + string body = _localizer["UserLockoutEmailBody"].Value; + body = body.Replace("[UserDisplayName]", user.DisplayName); + body = body.Replace("[URL]", url); + body = body.Replace("[SiteName]", siteName); + var notification = new Notification(alias.SiteId, user, subject, body); _notifications.AddNotification(notification); _logger.Log(LogLevel.Information, this, LogFunction.Security, "User Lockout Notification Sent For {Username}", user.Username); } @@ -404,12 +431,14 @@ namespace Oqtane.Managers user = _users.GetUser(user.Username); string token = await _identityUserManager.GeneratePasswordResetTokenAsync(identityuser); string url = alias.Protocol + alias.Name + "/reset?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token); - string body = "Dear " + user.DisplayName + ",\n\nYou recently requested to reset your password. Please use the link below to complete the process:\n\n" + url + - "\n\nPlease note that the link is only valid for 24 hours so if you are unable to take action within that time period, you should initiate another password reset on the site." + - "\n\nIf you did not request to reset your password you can safely ignore this message." + - "\n\nThank You!"; - - var notification = new Notification(_tenantManager.GetAlias().SiteId, user, "User Password Reset", body); + string siteName = _siteRepo.GetSite(alias.SiteId).Name; + string subject = _localizer["ForgotPasswordEmailSubject"]; + subject = subject.Replace("[SiteName]", siteName); + string body = _localizer["ForgotPasswordEmailBody"].Value; + body = body.Replace("[UserDisplayName]", user.DisplayName); + body = body.Replace("[URL]", url); + body = body.Replace("[SiteName]", siteName); + var notification = new Notification(_tenantManager.GetAlias().SiteId, user, subject, body); _notifications.AddNotification(notification); _logger.Log(LogLevel.Information, this, LogFunction.Security, "Password Reset Notification Sent For {Username}", user.Username); } diff --git a/Oqtane.Server/Resources/Managers.UserManager.resx b/Oqtane.Server/Resources/Managers.UserManager.resx new file mode 100644 index 00000000..66eec09c --- /dev/null +++ b/Oqtane.Server/Resources/Managers.UserManager.resx @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Dear [UserDisplayName]<br><br>You recently requested to reset your password. Please use the link below to complete the process: <b><a href="[URL]"><br><br>Click here to Reset Password</a></b><br><br>Please note that the link is only valid for 24 hours so if you are unable to take action within that time period, you should initiate another password reset on the site.<br><br>If you did not request to reset your password you can safely ignore this message.<br><br>Thank You!<br>[SiteName] team + + + Password Reset Notification Sent For [SiteName] + + + Dear [UserDisplayName],<br><br>A user account has been successfully created for you with the username <b>[Username]</b>. Please <b><a href="[URL]">click here to login</a></b>. If you do not know your password, use the forgot password option on the login page to reset your account.<br><br>Thank You!<br>[SiteName] Team + + + User Account Notification for [SiteName] + + + Dear [UserDisplayName] + ",<br><br>You requested a secure verification code to log in to your account. Please enter the secure verification code on the site:<br><br><b>[Token] </b><br><br>Please note that the code is only valid for 10 minutes so if you are unable to take action within that time period, you should initiate a new login on the [Alias].<br><br>Thank You!<br>[SiteName] Team" + + + User Verification Code for [SiteName] + + + Dear [UserDisplayName], <br><br>You attempted multiple times unsuccessfully to log in to your account and it is now locked out. Please wait a few minutes and then try again... or use the link below to reset your password:<br><br> <b><a href=[URL]>Reset Password</a></b><br><br>Please note that the link is only valid for 24 hours so if you are unable to take action within that time period, you should initiate another password reset on the site <a href="[SiteURL]">[SiteName]</a>.<br><br>Thank You!<br>[SiteName] Team + + + User Lockout Notification for [SiteName] + + + Dear [UserDisplayName],<br><br>In order to verify the email address associated to your user account, please click the link below:<br><br> <b><a href="[URL]">Click Here To Verify</a></b> <br><br>If the link is not displayed please copy and paste the following link to your browser <br><br> [URL] <br><br>Thank You!<br>[SiteName] Team + + + Email Verification for [SiteName] + + \ No newline at end of file From b08d91a21830a92e6c04efaded013b0507bcb095 Mon Sep 17 00:00:00 2001 From: mostafametwally Date: Thu, 22 Feb 2024 00:33:45 +0100 Subject: [PATCH 03/15] handle focus error on blazor web assembly when verifying email address --- Oqtane.Client/Modules/Admin/Login/Index.razor | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Oqtane.Client/Modules/Admin/Login/Index.razor b/Oqtane.Client/Modules/Admin/Login/Index.razor index f59834f8..eec57ca8 100644 --- a/Oqtane.Client/Modules/Admin/Login/Index.razor +++ b/Oqtane.Client/Modules/Admin/Login/Index.razor @@ -166,7 +166,8 @@ { if (firstRender && PageState.User == null && _allowsitelogin) { - await username.FocusAsync(); + if(!string.IsNullOrEmpty(username.Id)) + await username.FocusAsync(); } // redirect logged in user to specified page From c4d293143d0b3e58a678a5c4c098d38551081b4f Mon Sep 17 00:00:00 2001 From: Cody Date: Wed, 21 Feb 2024 21:23:27 -0800 Subject: [PATCH 04/15] Updates Bootstrap to version 5.3.2 --- Oqtane.Client/Themes/BlazorTheme/Themes/Default.razor | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Oqtane.Client/Themes/BlazorTheme/Themes/Default.razor b/Oqtane.Client/Themes/BlazorTheme/Themes/Default.razor index 92cc01d4..e19a8261 100644 --- a/Oqtane.Client/Themes/BlazorTheme/Themes/Default.razor +++ b/Oqtane.Client/Themes/BlazorTheme/Themes/Default.razor @@ -31,9 +31,9 @@ public override List Resources => new List() { // obtained from https://cdnjs.com/libraries - new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css", Integrity = "sha512-t4GWSVZO1eC8BM339Xd7Uphw5s17a86tIZIj8qRxhnKub6WoyhnrxeCIMeAqBPgdZGlCcG2PrZjMc+Wr78+5Xg==", CrossOrigin = "anonymous" }, + new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/css/bootstrap.min.css", Integrity = "sha512-b2QcS5SsA8tZodcDtGRELiGv5SaKSk1vDHDaQRda0htPYWZ6046lr3kJ5bAAQdpV2mmA/4v0wQF9MyU6/pDIAg==", CrossOrigin = "anonymous" }, new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" }, - new Resource { ResourceType = ResourceType.Script, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.bundle.min.js", Integrity = "sha512-VK2zcvntEufaimc+efOYi622VN5ZacdnufnmX7zIhCPmjhKnOi9ZDMtg1/ug5l183f19gG1/cBstPO4D8N/Img==", CrossOrigin = "anonymous" } + new Resource { ResourceType = ResourceType.Script, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/js/bootstrap.bundle.min.js", Integrity = "sha512-X/YkDZyjTf4wyc2Vy16YGCPHwAY8rZJY+POgokZjQB2mhIRFJCckEGc6YyX9eNsPfn0PzThEuNs+uaomE5CO6A==", CrossOrigin = "anonymous" } }; -} \ No newline at end of file +} From 68d9984d646c4a4aebce313b98a06595f873bb73 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Thu, 22 Feb 2024 08:00:08 -0500 Subject: [PATCH 05/15] include render mode html comment --- Oqtane.Client/UI/RenderModeBoundary.razor | 1 + 1 file changed, 1 insertion(+) diff --git a/Oqtane.Client/UI/RenderModeBoundary.razor b/Oqtane.Client/UI/RenderModeBoundary.razor index 56833e47..09479767 100644 --- a/Oqtane.Client/UI/RenderModeBoundary.razor +++ b/Oqtane.Client/UI/RenderModeBoundary.razor @@ -10,6 +10,7 @@ { @if (ModuleType != null) { + @((MarkupString)$"") @if (!string.IsNullOrEmpty(_messageContent) && _messagePosition == "top") { From 4c427116a8ac002a8480230e293cf850095ccfce Mon Sep 17 00:00:00 2001 From: Cody Date: Thu, 22 Feb 2024 07:48:58 -0800 Subject: [PATCH 06/15] Update Microsoft.AspNetCore.Authentication.OpenIdConnect To Version 8.0.2 --- Oqtane.Server/Oqtane.Server.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index c06187fe..febaa083 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -44,7 +44,7 @@ - + From eef58f4da02b9ec6562ce942a3edfe6824af9bbb Mon Sep 17 00:00:00 2001 From: sbwalker Date: Thu, 22 Feb 2024 11:01:49 -0500 Subject: [PATCH 07/15] update documentation --- Oqtane.Server/Repository/SiteRepository.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs index 7ae2d43f..9c7c55e6 100644 --- a/Oqtane.Server/Repository/SiteRepository.cs +++ b/Oqtane.Server/Repository/SiteRepository.cs @@ -107,10 +107,10 @@ namespace Oqtane.Repository { var site = GetSite(alias.SiteId); - // initialize theme Assemblies and Scripts + // initialize theme Assemblies site.Themes = _themeRepository.GetThemes().ToList(); - // initialize module Assemblies and Scripts + // initialize module Assemblies var moduleDefinitions = _moduleDefinitionRepository.GetModuleDefinitions(alias.SiteId); // execute migrations From 92719d095a700675f2b869450ec299f457321452 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Thu, 22 Feb 2024 14:21:49 -0500 Subject: [PATCH 08/15] removed AddModuleMessage from OnParametersSetAsync methods to mitigate risk of infinite loops --- Oqtane.Client/Modules/Admin/Files/Index.razor | 1 - Oqtane.Client/Modules/Admin/Logs/Index.razor | 1 - Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor | 1 - Oqtane.Client/Modules/Admin/Themes/Index.razor | 1 - Oqtane.Client/Modules/HtmlText/Index.razor | 1 - 5 files changed, 5 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Files/Index.razor b/Oqtane.Client/Modules/Admin/Files/Index.razor index 504a888f..47063d3f 100644 --- a/Oqtane.Client/Modules/Admin/Files/Index.razor +++ b/Oqtane.Client/Modules/Admin/Files/Index.razor @@ -75,7 +75,6 @@ catch (Exception ex) { await logger.LogError(ex, "Error Loading Files {Error}", ex.Message); - AddModuleMessage(Localizer["Error.File.Load"], MessageType.Error); } } diff --git a/Oqtane.Client/Modules/Admin/Logs/Index.razor b/Oqtane.Client/Modules/Admin/Logs/Index.razor index cf2f7cbc..5cc5c590 100644 --- a/Oqtane.Client/Modules/Admin/Logs/Index.razor +++ b/Oqtane.Client/Modules/Admin/Logs/Index.razor @@ -131,7 +131,6 @@ else catch (Exception ex) { await logger.LogError(ex, "Error Loading Logs {Error}", ex.Message); - AddModuleMessage(Localizer["Error.Log.Load"], MessageType.Error); } } diff --git a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor index 2d3b80a7..30211df9 100644 --- a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor +++ b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor @@ -120,7 +120,6 @@ else if (_moduleDefinitions == null) { await logger.LogError(ex, "Error Loading Modules {Error}", ex.Message); - AddModuleMessage(Localizer["Error.Module.Load"], MessageType.Error); } } } diff --git a/Oqtane.Client/Modules/Admin/Themes/Index.razor b/Oqtane.Client/Modules/Admin/Themes/Index.razor index 3a7d64ae..c9f09acc 100644 --- a/Oqtane.Client/Modules/Admin/Themes/Index.razor +++ b/Oqtane.Client/Modules/Admin/Themes/Index.razor @@ -86,7 +86,6 @@ else if (_themes == null) { await logger.LogError(ex, "Error Loading Themes {Error}", ex.Message); - AddModuleMessage(Localizer["Error.Theme.Load"], MessageType.Error); } } } diff --git a/Oqtane.Client/Modules/HtmlText/Index.razor b/Oqtane.Client/Modules/HtmlText/Index.razor index 9e8db961..f52aaf85 100644 --- a/Oqtane.Client/Modules/HtmlText/Index.razor +++ b/Oqtane.Client/Modules/HtmlText/Index.razor @@ -36,7 +36,6 @@ catch (Exception ex) { await logger.LogError(ex, "Error Loading Content {Error}", ex.Message); - AddModuleMessage(Localizer["Error.Content.Load"], MessageType.Error); } } } \ No newline at end of file From cdfae2e8cbc6fd6c2e5a66f243a61be11b55fd83 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Thu, 22 Feb 2024 16:34:52 -0500 Subject: [PATCH 09/15] modify ActionLink to use a link rather than button for disabled scenario --- Oqtane.Client/Modules/Controls/ActionLink.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Oqtane.Client/Modules/Controls/ActionLink.razor b/Oqtane.Client/Modules/Controls/ActionLink.razor index 5afcb874..a02993ca 100644 --- a/Oqtane.Client/Modules/Controls/ActionLink.razor +++ b/Oqtane.Client/Modules/Controls/ActionLink.razor @@ -8,7 +8,7 @@ { if (Disabled) { - + @((MarkupString)_iconSpan) @_text } else { From 25dacccb3b2637ec3c5464d670a76dd2ff5b7a1d Mon Sep 17 00:00:00 2001 From: sbwalker Date: Thu, 22 Feb 2024 16:40:55 -0500 Subject: [PATCH 10/15] remove Microsoft.AspNetCore.Components.WebAssembly.DevServer from default module and theme template as it is no longer needed --- .../External/Client/[Owner].Module.[Module].Client.csproj | 1 - .../External/Client/[Owner].Theme.[Theme].Client.csproj | 1 - 2 files changed, 2 deletions(-) diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Client/[Owner].Module.[Module].Client.csproj b/Oqtane.Server/wwwroot/Modules/Templates/External/Client/[Owner].Module.[Module].Client.csproj index b048bda3..b6fae0a5 100644 --- a/Oqtane.Server/wwwroot/Modules/Templates/External/Client/[Owner].Module.[Module].Client.csproj +++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Client/[Owner].Module.[Module].Client.csproj @@ -14,7 +14,6 @@ - diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/Client/[Owner].Theme.[Theme].Client.csproj b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/[Owner].Theme.[Theme].Client.csproj index 8fc597a2..0fcb6b0b 100644 --- a/Oqtane.Server/wwwroot/Themes/Templates/External/Client/[Owner].Theme.[Theme].Client.csproj +++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/[Owner].Theme.[Theme].Client.csproj @@ -13,7 +13,6 @@ - From 35f5df63e2762c776dd173cdc5293ea5f3dbec5a Mon Sep 17 00:00:00 2001 From: sbwalker Date: Fri, 23 Feb 2024 07:31:12 -0500 Subject: [PATCH 11/15] improve UX by adding data-enhance to Edit Mode button --- Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor b/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor index e8421395..3358925c 100644 --- a/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor +++ b/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor @@ -10,7 +10,7 @@ @if (_showEditMode || (PageState.Page.IsPersonalizable && PageState.User != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Registered))) { -
+ @if (PageState.EditMode) { From dcbf03c355a1493d45c3ea2557bbc479b832f18e Mon Sep 17 00:00:00 2001 From: Leigh Pointer Date: Fri, 23 Feb 2024 13:46:22 +0100 Subject: [PATCH 12/15] Added Resource Files to Theme Templates Currently the template uses the Localization Resource functionality but it will always default to the hardcoded text. Leaving it to the developer to add the resources could result in a hit and miss scenario. This PR removes the "mis" side. --- .../[Owner].Theme.[Theme]/Container.resx | 101 +++++++++++++ .../ContainerSettings.resx | 126 ++++++++++++++++ .../[Owner].Theme.[Theme]/Theme.resx | 101 +++++++++++++ .../[Owner].Theme.[Theme]/ThemeSettings.resx | 138 ++++++++++++++++++ 4 files changed, 466 insertions(+) create mode 100644 Oqtane.Server/wwwroot/Themes/Templates/External/Client/Resources/[Owner].Theme.[Theme]/Container.resx create mode 100644 Oqtane.Server/wwwroot/Themes/Templates/External/Client/Resources/[Owner].Theme.[Theme]/ContainerSettings.resx create mode 100644 Oqtane.Server/wwwroot/Themes/Templates/External/Client/Resources/[Owner].Theme.[Theme]/Theme.resx create mode 100644 Oqtane.Server/wwwroot/Themes/Templates/External/Client/Resources/[Owner].Theme.[Theme]/ThemeSettings.resx diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Resources/[Owner].Theme.[Theme]/Container.resx b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Resources/[Owner].Theme.[Theme]/Container.resx new file mode 100644 index 00000000..4fdb1b6a --- /dev/null +++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Resources/[Owner].Theme.[Theme]/Container.resx @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Resources/[Owner].Theme.[Theme]/ContainerSettings.resx b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Resources/[Owner].Theme.[Theme]/ContainerSettings.resx new file mode 100644 index 00000000..9c3b2d80 --- /dev/null +++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Resources/[Owner].Theme.[Theme]/ContainerSettings.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Specify If The Module Title Should Be Displayed + + + Display Title + + \ No newline at end of file diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Resources/[Owner].Theme.[Theme]/Theme.resx b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Resources/[Owner].Theme.[Theme]/Theme.resx new file mode 100644 index 00000000..4fdb1b6a --- /dev/null +++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Resources/[Owner].Theme.[Theme]/Theme.resx @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Resources/[Owner].Theme.[Theme]/ThemeSettings.resx b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Resources/[Owner].Theme.[Theme]/ThemeSettings.resx new file mode 100644 index 00000000..1359d4be --- /dev/null +++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Resources/[Owner].Theme.[Theme]/ThemeSettings.resx @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Specify if a Login option should be displayed. Note that this option does not prevent the login page from being accessible via a direct url. + + + Show Login? + + + Specify if a Register option should be displayed. Note that this option is also dependent on the Allow Registration option in Site Settings. + + + Show Register? + + + Specify if the settings are applicable to this page or the entire site. + + + Setting Scope: + + \ No newline at end of file From ddd39ea0c9b3d16450d01b624f3961dd85add6f8 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Fri, 23 Feb 2024 09:28:33 -0500 Subject: [PATCH 13/15] fix #3868 - static rendering support for page themes within site --- .../Controls/Theme/MenuItemsHorizontal.razor | 34 +++++++++++++++---- .../Controls/Theme/MenuItemsVertical.razor | 30 +++++++++++++--- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/Oqtane.Client/Themes/Controls/Theme/MenuItemsHorizontal.razor b/Oqtane.Client/Themes/Controls/Theme/MenuItemsHorizontal.razor index 76c254e4..dc5d901f 100644 --- a/Oqtane.Client/Themes/Controls/Theme/MenuItemsHorizontal.razor +++ b/Oqtane.Client/Themes/Controls/Theme/MenuItemsHorizontal.razor @@ -6,9 +6,20 @@