From 4d58ee2162846651fbd56625247dd15f743745ae Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Tue, 16 Apr 2024 13:46:55 -0400 Subject: [PATCH 01/77] Update README.md --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0a56d241..116e1206 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Latest Release -[5.1.0](https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0) was released on Mar 27, 2024 and is a major release providing Static Server Rendering support for Blazor in .NET 8. This release includes 263 pull requests by 6 different contributors, pushing the total number of project commits all-time to over 5100. The Oqtane framework continues to evolve at a rapid pace to meet the needs of .NET developers. +[5.1.1](https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1) was released on Apr 16, 2024 and is primarily a stabilization release, which includes a variety of improvements to the Static Server-Side Rendering support for Blazor in .NET 8. This release includes 40 pull requests by 6 different contributors, pushing the total number of project commits all-time to over 5200. The Oqtane framework continues to evolve at a rapid pace to meet the needs of .NET developers. [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Foqtane%2Foqtane.framework%2Fmaster%2Fazuredeploy.json) @@ -18,15 +18,15 @@ Please note that this project is owned by the .NET Foundation and is governed by **Using Version 5:** -- Install **[.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet/8.0)**. +- Install **[.NET 8.0.4 SDK](https://dotnet.microsoft.com/download/dotnet/8.0)**. -- Install the latest edition (v17.8 or higher) of [Visual Studio 2022](https://visualstudio.microsoft.com/downloads) with the **ASP.NET and web development** workload enabled. Oqtane works with ALL editions of Visual Studio from Community to Enterprise. If you wish to use LocalDB for development ( not a requirement as Oqtane supports SQLite, mySQL, and PostgreSQL ) you must also install the **Data storage and processing**. +- Install the latest edition (v17.9 or higher) of [Visual Studio 2022](https://visualstudio.microsoft.com/downloads) with the **ASP.NET and web development** workload enabled. Oqtane works with ALL editions of Visual Studio from Community to Enterprise. If you wish to use LocalDB for development ( not a requirement as Oqtane supports SQLite, mySQL, and PostgreSQL ) you must also install the **Data storage and processing**. - Clone the Oqtane dev branch source code to your local system. - Open the **Oqtane.sln** solution file. -- **Important:** Build the solution. +- **Important:** Rebuild the entire solution before running it. - Make sure you specify Oqtane.Server as the Startup Project @@ -63,8 +63,8 @@ Backlog (TBD) - [ ] Folder Providers - [ ] Generative AI Integration -5.1.1 (Apr 2024) -- [ ] Stabilization improvements +[5.1.1](https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1) (Apr 16, 2024) +- [x] Stabilization improvements [5.1.0](https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.0) (Mar 27, 2024) - [x] Migration to the new unified Blazor approach in .NET 8 (ie. blazor.web.js) @@ -249,6 +249,8 @@ Oqtane was created by [Shaun Walker](https://www.linkedin.com/in/shaunbrucewalke # Release Announcements +[Oqtane 5.1](https://www.oqtane.org/blog/!/75/announcing-oqtane-5-0-for-net-8) + [Oqtane 5.0](https://www.oqtane.org/blog/!/75/announcing-oqtane-5-0-for-net-8) [Oqtane 4.0](https://www.oqtane.org/blog/!/63/announcing-oqtane-4-0-for-net-7) From 976ad5fcee445d107c375f093a7ae1a4ccb327e3 Mon Sep 17 00:00:00 2001 From: Shaun Walker Date: Tue, 16 Apr 2024 13:47:24 -0400 Subject: [PATCH 02/77] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 116e1206..5cae70ad 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Latest Release -[5.1.1](https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1) was released on Apr 16, 2024 and is primarily a stabilization release, which includes a variety of improvements to the Static Server-Side Rendering support for Blazor in .NET 8. This release includes 40 pull requests by 6 different contributors, pushing the total number of project commits all-time to over 5200. The Oqtane framework continues to evolve at a rapid pace to meet the needs of .NET developers. +[5.1.1](https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1) was released on Apr 16, 2024 and is primarily a stabilization release, including a variety of improvements to the Static Server-Side Rendering support for Blazor in .NET 8. This release includes 40 pull requests by 6 different contributors, pushing the total number of project commits all-time to over 5200. The Oqtane framework continues to evolve at a rapid pace to meet the needs of .NET developers. [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Foqtane%2Foqtane.framework%2Fmaster%2Fazuredeploy.json) From 430e6163285828b8ed6561a0bb59e7916ea96514 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Thu, 18 Apr 2024 18:43:14 -0400 Subject: [PATCH 03/77] fix #4150 - remove Add Existing Module option when managing personalized pages --- .../Themes/Controls/Theme/ControlPanelInteractive.razor | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor b/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor index 5c53f36f..fe8c0128 100644 --- a/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor +++ b/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor @@ -95,7 +95,10 @@ @if (_moduleType == "new") { From 09293f7d9a1561596b580663a49f5925e662fa90 Mon Sep 17 00:00:00 2001 From: Ben Date: Sat, 20 Apr 2024 16:56:32 +0800 Subject: [PATCH 04/77] Fix #4158: insert image into correct position. --- .../Modules/Controls/RichTextEditor.razor | 20 ++++++++++--------- .../Modules/Controls/RichTextEditorInterop.cs | 16 +++++++++++++-- Oqtane.Server/wwwroot/js/quill-interop.js | 10 ++++++---- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/Oqtane.Client/Modules/Controls/RichTextEditor.razor b/Oqtane.Client/Modules/Controls/RichTextEditor.razor index ad237acb..bada030c 100644 --- a/Oqtane.Client/Modules/Controls/RichTextEditor.razor +++ b/Oqtane.Client/Modules/Controls/RichTextEditor.razor @@ -122,6 +122,7 @@ private string _message = string.Empty; private bool _contentchanged = false; + private int _editorIndex; [Parameter] public string Content { get; set; } @@ -275,18 +276,18 @@ // return original raw html content return _originalrawhtml; } - } - } + } + } - public async Task InsertRichImage() - { - _message = string.Empty; - if (_richfilemanager) - { - var file = _fileManager.GetFile(); + public async Task InsertRichImage() + { + _message = string.Empty; + if (_richfilemanager) + { + var file = _fileManager.GetFile(); if (file != null) { - await interop.InsertImage(_editorElement, file.Url, ((!string.IsNullOrEmpty(file.Description)) ? file.Description : file.Name)); + await interop.InsertImage(_editorElement, file.Url, ((!string.IsNullOrEmpty(file.Description)) ? file.Description : file.Name), _editorIndex); _richhtml = await interop.GetHtml(_editorElement); _richfilemanager = false; } @@ -297,6 +298,7 @@ } else { + _editorIndex = await interop.GetCurrentCursor(_editorElement); _richfilemanager = true; } StateHasChanged(); diff --git a/Oqtane.Client/Modules/Controls/RichTextEditorInterop.cs b/Oqtane.Client/Modules/Controls/RichTextEditorInterop.cs index 6765cad9..338f240a 100644 --- a/Oqtane.Client/Modules/Controls/RichTextEditorInterop.cs +++ b/Oqtane.Client/Modules/Controls/RichTextEditorInterop.cs @@ -105,13 +105,25 @@ namespace Oqtane.Modules.Controls } } - public Task InsertImage(ElementReference quillElement, string imageUrl, string altText) + public ValueTask GetCurrentCursor(ElementReference quillElement) + { + try + { + return _jsRuntime.InvokeAsync("Oqtane.RichTextEditor.getCurrentCursor", quillElement); + } + catch + { + return new ValueTask(Task.FromResult(0)); + } + } + + public Task InsertImage(ElementReference quillElement, string imageUrl, string altText, int editorIndex) { try { _jsRuntime.InvokeAsync( "Oqtane.RichTextEditor.insertQuillImage", - quillElement, imageUrl, altText); + quillElement, imageUrl, altText, editorIndex); return Task.CompletedTask; } catch diff --git a/Oqtane.Server/wwwroot/js/quill-interop.js b/Oqtane.Server/wwwroot/js/quill-interop.js index e5610a9e..4598d7aa 100644 --- a/Oqtane.Server/wwwroot/js/quill-interop.js +++ b/Oqtane.Server/wwwroot/js/quill-interop.js @@ -35,13 +35,15 @@ Oqtane.RichTextEditor = { enableQuillEditor: function (editorElement, mode) { editorElement.__quill.enable(mode); }, - insertQuillImage: function (quillElement, imageURL, altText) { - var Delta = Quill.import('delta'); - editorIndex = 0; - + getCurrentCursor: function (quillElement) { + var editorIndex = 0; if (quillElement.__quill.getSelection() !== null) { editorIndex = quillElement.__quill.getSelection().index; } + return editorIndex; + }, + insertQuillImage: function (quillElement, imageURL, altText, editorIndex) { + var Delta = Quill.import('delta'); return quillElement.__quill.updateContents( new Delta() From 8958b61fdd65ab25a2c6235dba9156e415303270 Mon Sep 17 00:00:00 2001 From: Ikuo Ohba Date: Sun, 21 Apr 2024 20:44:41 +0900 Subject: [PATCH 05/77] Datetime formatting issue --- Oqtane.Client/Services/VisitorService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Oqtane.Client/Services/VisitorService.cs b/Oqtane.Client/Services/VisitorService.cs index 9febe7f9..ae2e46c1 100644 --- a/Oqtane.Client/Services/VisitorService.cs +++ b/Oqtane.Client/Services/VisitorService.cs @@ -18,7 +18,7 @@ namespace Oqtane.Services public async Task> GetVisitorsAsync(int siteId, DateTime fromDate) { - List visitors = await GetJsonAsync>($"{Apiurl}?siteid={siteId}&fromdate={fromDate.ToString("dd-MMM-yyyy")}"); + List visitors = await GetJsonAsync>($"{Apiurl}?siteid={siteId}&fromdate={fromDate.ToString("yyyy-MM-dd")}"); return visitors.OrderByDescending(item => item.VisitedOn).ToList(); } From 904d39beacc4b3cd2b553250e07eadaee508cf70 Mon Sep 17 00:00:00 2001 From: Leigh Pointer Date: Mon, 22 Apr 2024 14:08:09 +0200 Subject: [PATCH 06/77] Rouge TD in table Deleted a rouge TD in the themes index table --- Oqtane.Client/Modules/Admin/Themes/Index.razor | 1 - 1 file changed, 1 deletion(-) diff --git a/Oqtane.Client/Modules/Admin/Themes/Index.razor b/Oqtane.Client/Modules/Admin/Themes/Index.razor index 3a7d64ae..4e65f693 100644 --- a/Oqtane.Client/Modules/Admin/Themes/Index.razor +++ b/Oqtane.Client/Modules/Admin/Themes/Index.razor @@ -63,7 +63,6 @@ else } - } From 7b8e7ac5c23fffd3fb0cbd573ba11acb33a42ebc Mon Sep 17 00:00:00 2001 From: Leigh Pointer Date: Mon, 22 Apr 2024 17:14:09 +0200 Subject: [PATCH 07/77] Fix for #4168 Resx entry for Module Settings Permissions tab --- Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx b/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx index 722fa2f1..b872c727 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx @@ -177,4 +177,7 @@ Expiry Date: + + Permissions + \ No newline at end of file From b5ebcc3e0770fec9aae6b9d1df767ade55731f11 Mon Sep 17 00:00:00 2001 From: Leigh Pointer Date: Mon, 22 Apr 2024 17:46:13 +0200 Subject: [PATCH 08/77] Update Index.razor --- Oqtane.Client/Modules/Admin/Pages/Index.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Oqtane.Client/Modules/Admin/Pages/Index.razor b/Oqtane.Client/Modules/Admin/Pages/Index.razor index f1b9e9b4..391c6c42 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Index.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Index.razor @@ -17,7 +17,7 @@ @SharedLocalizer["Name"] - + @(new string('-', context.Level * 2))@(context.Name) From 294f511b9a5c17918a7f0f1efe4ade2fc7f98a6c Mon Sep 17 00:00:00 2001 From: Leigh Pointer Date: Mon, 22 Apr 2024 18:27:01 +0200 Subject: [PATCH 09/77] Missing parameters #4172 #4173 --- Oqtane.Client/Modules/Admin/Profiles/Index.razor | 2 +- Oqtane.Client/Modules/Admin/Users/Index.razor | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Profiles/Index.razor b/Oqtane.Client/Modules/Admin/Profiles/Index.razor index 587fa452..6152062d 100644 --- a/Oqtane.Client/Modules/Admin/Profiles/Index.razor +++ b/Oqtane.Client/Modules/Admin/Profiles/Index.razor @@ -22,7 +22,7 @@ else @Localizer["Order"] - + @context.Name @context.Title diff --git a/Oqtane.Client/Modules/Admin/Users/Index.razor b/Oqtane.Client/Modules/Admin/Users/Index.razor index ed050ac7..a04be4c3 100644 --- a/Oqtane.Client/Modules/Admin/Users/Index.razor +++ b/Oqtane.Client/Modules/Admin/Users/Index.razor @@ -32,13 +32,13 @@ else - + - + @context.User.Username @context.User.DisplayName From ead954ddaaa5874b806fccd9396c245b7379e76a Mon Sep 17 00:00:00 2001 From: Leigh Pointer Date: Mon, 22 Apr 2024 19:18:02 +0200 Subject: [PATCH 10/77] Missing Parameters #4174 #4175 --- Oqtane.Client/Modules/Admin/Logs/Index.razor | 2 +- Oqtane.Client/Modules/Admin/Visitors/Index.razor | 2 +- Oqtane.Client/Resources/Modules/Admin/Profiles/Index.resx | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Logs/Index.razor b/Oqtane.Client/Modules/Admin/Logs/Index.razor index 6932f784..dfb0cf8d 100644 --- a/Oqtane.Client/Modules/Admin/Logs/Index.razor +++ b/Oqtane.Client/Modules/Admin/Logs/Index.razor @@ -63,7 +63,7 @@ else @Localizer["Function"] - + @context.LogDate @context.Level @context.Feature diff --git a/Oqtane.Client/Modules/Admin/Visitors/Index.razor b/Oqtane.Client/Modules/Admin/Visitors/Index.razor index 61487cf3..39b14006 100644 --- a/Oqtane.Client/Modules/Admin/Visitors/Index.razor +++ b/Oqtane.Client/Modules/Admin/Visitors/Index.razor @@ -43,7 +43,7 @@ else @Localizer["Created"] - + @context.IPAddress @if (context.UserId != null) diff --git a/Oqtane.Client/Resources/Modules/Admin/Profiles/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Profiles/Index.resx index 98f8530c..694119f3 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Profiles/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Profiles/Index.resx @@ -147,4 +147,7 @@ Title + + Detail + \ No newline at end of file From 708d473b475204cd0b4bca05bc19bf9925c963f4 Mon Sep 17 00:00:00 2001 From: Leigh Pointer Date: Mon, 22 Apr 2024 20:19:33 +0200 Subject: [PATCH 11/77] Missing Parameter #4176 --- Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor index 2d3b80a7..485f027f 100644 --- a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor +++ b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor @@ -50,7 +50,7 @@ else   - + @if (context.AssemblyName != Constants.ClientId) { From 6162244730c5e70011363e09666ec28d81470b8c Mon Sep 17 00:00:00 2001 From: sbwalker Date: Mon, 22 Apr 2024 17:09:18 -0400 Subject: [PATCH 12/77] fix #4165 - missing slash in subfolder sites --- Oqtane.Shared/Shared/Utilities.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Oqtane.Shared/Shared/Utilities.cs b/Oqtane.Shared/Shared/Utilities.cs index b9e364c3..4fc04e7f 100644 --- a/Oqtane.Shared/Shared/Utilities.cs +++ b/Oqtane.Shared/Shared/Utilities.cs @@ -44,9 +44,10 @@ namespace Oqtane.Shared string querystring = ""; string fragment = ""; + if (!string.IsNullOrEmpty(path)) path = "/" + path; + if (!string.IsNullOrEmpty(parameters)) { - // parse parameters (string urlparameters, querystring, fragment) = ParseParameters(parameters); if (!string.IsNullOrEmpty(urlparameters)) { From cfb128acb8d286777459ca5ece7f5f6d037223d7 Mon Sep 17 00:00:00 2001 From: vnetonline Date: Tue, 23 Apr 2024 15:22:02 +1000 Subject: [PATCH 13/77] [ENH] - Add Prerender IModuleControl property (similar to RenderMode) #4178 --- Oqtane.Client/Modules/ModuleBase.cs | 2 ++ Oqtane.Client/UI/ModuleInstance.razor | 2 +- Oqtane.Client/UI/RenderModeBoundary.razor | 2 +- Oqtane.Client/UI/SiteRouter.razor | 1 + Oqtane.Shared/Interfaces/IModuleControl.cs | 5 +++++ Oqtane.Shared/Models/Module.cs | 2 ++ 6 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Oqtane.Client/Modules/ModuleBase.cs b/Oqtane.Client/Modules/ModuleBase.cs index fee2d4e5..2d5410a3 100644 --- a/Oqtane.Client/Modules/ModuleBase.cs +++ b/Oqtane.Client/Modules/ModuleBase.cs @@ -52,6 +52,8 @@ namespace Oqtane.Modules public virtual string RenderMode { get { return RenderModes.Interactive; } } // interactive by default + public virtual bool Prerender { get { return true; } } // prerender at server by default + // url parameters public virtual string UrlParametersTemplate { get; set; } diff --git a/Oqtane.Client/UI/ModuleInstance.razor b/Oqtane.Client/UI/ModuleInstance.razor index 5d429954..53258cea 100644 --- a/Oqtane.Client/UI/ModuleInstance.razor +++ b/Oqtane.Client/UI/ModuleInstance.razor @@ -7,7 +7,7 @@ } else { - + } @code { diff --git a/Oqtane.Client/UI/RenderModeBoundary.razor b/Oqtane.Client/UI/RenderModeBoundary.razor index e4d6873e..d3a11055 100644 --- a/Oqtane.Client/UI/RenderModeBoundary.razor +++ b/Oqtane.Client/UI/RenderModeBoundary.razor @@ -10,7 +10,7 @@ { @if (ModuleType != null) { - @((MarkupString)$"") + @((MarkupString)$"") @DynamicComponent @if (_progressIndicator) diff --git a/Oqtane.Client/UI/SiteRouter.razor b/Oqtane.Client/UI/SiteRouter.razor index 43acc3a6..13c35b17 100644 --- a/Oqtane.Client/UI/SiteRouter.razor +++ b/Oqtane.Client/UI/SiteRouter.razor @@ -476,6 +476,7 @@ // retrieve module component resources var moduleobject = Activator.CreateInstance(moduletype) as IModuleControl; module.RenderMode = moduleobject.RenderMode; + module.Prerender = moduleobject.Prerender; page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace); if (action.ToLower() == "settings" && module.ModuleDefinition != null) diff --git a/Oqtane.Shared/Interfaces/IModuleControl.cs b/Oqtane.Shared/Interfaces/IModuleControl.cs index 1d442931..b425a311 100644 --- a/Oqtane.Shared/Interfaces/IModuleControl.cs +++ b/Oqtane.Shared/Interfaces/IModuleControl.cs @@ -35,5 +35,10 @@ namespace Oqtane.Modules /// Specifies the required render mode for the module control ie. Static,Interactive /// string RenderMode { get; } + + /// + /// Specifies the prerender mode for the moudle control ie: true or false + /// + bool Prerender { get; } } } diff --git a/Oqtane.Shared/Models/Module.cs b/Oqtane.Shared/Models/Module.cs index bae7a0ca..a875e31b 100644 --- a/Oqtane.Shared/Models/Module.cs +++ b/Oqtane.Shared/Models/Module.cs @@ -117,6 +117,8 @@ namespace Oqtane.Models public bool UseAdminContainer { get; set; } [NotMapped] public string RenderMode{ get; set; } + [NotMapped] + public bool Prerender { get; set; } #endregion From adfd0d5c183e456a271ad813b57fdab17a8723df Mon Sep 17 00:00:00 2001 From: Ikuo Ohba Date: Tue, 23 Apr 2024 21:27:13 +0900 Subject: [PATCH 14/77] Fix MicroService And Controller --- Oqtane.Client/Services/VisitorService.cs | 3 ++- Oqtane.Server/Controllers/VisitorController.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Oqtane.Client/Services/VisitorService.cs b/Oqtane.Client/Services/VisitorService.cs index ae2e46c1..b29e9c3c 100644 --- a/Oqtane.Client/Services/VisitorService.cs +++ b/Oqtane.Client/Services/VisitorService.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using Oqtane.Documentation; using Oqtane.Shared; using System; +using System.Globalization; namespace Oqtane.Services { @@ -18,7 +19,7 @@ namespace Oqtane.Services public async Task> GetVisitorsAsync(int siteId, DateTime fromDate) { - List visitors = await GetJsonAsync>($"{Apiurl}?siteid={siteId}&fromdate={fromDate.ToString("yyyy-MM-dd")}"); + List visitors = await GetJsonAsync>($"{Apiurl}?siteid={siteId}&fromdate={fromDate.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)}"); return visitors.OrderByDescending(item => item.VisitedOn).ToList(); } diff --git a/Oqtane.Server/Controllers/VisitorController.cs b/Oqtane.Server/Controllers/VisitorController.cs index 46bf8935..224aaa5f 100644 --- a/Oqtane.Server/Controllers/VisitorController.cs +++ b/Oqtane.Server/Controllers/VisitorController.cs @@ -8,6 +8,7 @@ using Oqtane.Infrastructure; using Oqtane.Repository; using System.Net; using System; +using System.Globalization; namespace Oqtane.Controllers { @@ -33,7 +34,7 @@ namespace Oqtane.Controllers int SiteId; if (int.TryParse(siteid, out SiteId) && SiteId == _alias.SiteId) { - return _visitors.GetVisitors(SiteId, DateTime.Parse(fromdate)); + return _visitors.GetVisitors(SiteId, DateTime.ParseExact(fromdate, "yyyy-MM-dd", CultureInfo.InvariantCulture)); } else { From 791cc70b094a4f01c241e91cba58edd9d4feb12b Mon Sep 17 00:00:00 2001 From: sbwalker Date: Tue, 23 Apr 2024 12:54:44 -0400 Subject: [PATCH 15/77] replace form with link in AdminContainer --- Oqtane.Client/Themes/AdminContainer.razor | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Oqtane.Client/Themes/AdminContainer.razor b/Oqtane.Client/Themes/AdminContainer.razor index 60deaa59..7aec6816 100644 --- a/Oqtane.Client/Themes/AdminContainer.razor +++ b/Oqtane.Client/Themes/AdminContainer.razor @@ -1,6 +1,5 @@ @namespace Oqtane.Themes @inherits ContainerBase -@inject NavigationManager NavigationManager
@@ -267,13 +264,13 @@ protected string _moduleId { get; private set; } = "-"; protected string _moduleType { get; private set; } = "new"; protected string _moduleDefinitionName { get; private set; } = "-"; - protected string _copyMode { get; private set; } = "-"; protected string _title { get; private set; } = ""; protected string _containerType { get; private set; } = ""; protected int _location { get; private set; } = int.MaxValue; protected string _visibility { get; private set; } = "view"; protected string _message { get; private set; } = ""; + protected string _copyModuleMessage { get; private set; } = ""; private string settingCategory = "CP-category"; private string settingPane = "CP-pane"; @@ -358,13 +355,26 @@ StateHasChanged(); } + private void ModuleIdChanged() + { + _copyModuleMessage = string.Empty; + if(_moduleId != "-") + { + var module = _modules.FirstOrDefault(item => item.ModuleId == int.Parse(_moduleId)); + if (module != null && !module.ModuleDefinition.IsPortable) + { + _copyModuleMessage = $"
{Localizer["Message.Module.NotPortable"]}
"; + } + } + } + private async Task AddModule() { if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.PermissionList)) { - if ((_moduleType == "new" && _moduleDefinitionName != "-") || (_moduleType != "new" && _moduleId != "-" && _copyMode != "-")) + if ((_moduleType == "new" && _moduleDefinitionName != "-") || (_moduleType != "new" && _moduleId != "-")) { - var newModuleId = int.Parse(_moduleId); + var newModuleId = _moduleId != "-" ? int.Parse(_moduleId) : 0; if (_moduleType == "new") { Module module = new Module(); @@ -377,7 +387,7 @@ module = await ModuleService.AddModuleAsync(module); newModuleId = module.ModuleId; } - else if(_copyMode == "copy") + else if (_moduleType == "exsiting.copy") { var module = await ModuleService.GetModuleAsync(int.Parse(_moduleId)); module.ModuleId = 0; @@ -433,8 +443,7 @@ } else { - var error = _moduleType == "new" ? Localizer["Message.Require.ModuleSelect"] : Localizer["Message.Require.ModuleAndCopyModeSelect"]; - _message = $"
{error}
"; + _message = $"
{Localizer["Message.Require.ModuleSelect"]}
"; } } else From 2e7c3167f5fdba65c6c923b091e0c84d75215d0a Mon Sep 17 00:00:00 2001 From: sbwalker Date: Mon, 29 Apr 2024 14:58:30 -0400 Subject: [PATCH 34/77] refactor #4198 - copy existing module --- .../Controls/ControlPanelInteractive.resx | 19 +--------- .../Theme/ControlPanelInteractive.razor | 37 ++++++++----------- .../HtmlText/Manager/HtmlTextManager.cs | 8 ++-- 3 files changed, 22 insertions(+), 42 deletions(-) diff --git a/Oqtane.Client/Resources/Themes/Controls/ControlPanelInteractive.resx b/Oqtane.Client/Resources/Themes/Controls/ControlPanelInteractive.resx index 6a8302d7..15c567fc 100644 --- a/Oqtane.Client/Resources/Themes/Controls/ControlPanelInteractive.resx +++ b/Oqtane.Client/Resources/Themes/Controls/ControlPanelInteractive.resx @@ -154,7 +154,7 @@ Not Authorized - You Must Select A Module. + You Must Select A Module Module Management: @@ -162,15 +162,6 @@ Select Module - - Select Copy Mode - - - Sync - - - Copy - Page Management: @@ -207,13 +198,7 @@ Top - - You Must Select A Module And The Copy Mode. - - - The Module's Content Will Not Be Synchronized. - Copy Existing Module - + \ No newline at end of file diff --git a/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor b/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor index d33b1d21..aa281da2 100644 --- a/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor +++ b/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor @@ -94,12 +94,12 @@
- @if (PageState.Page.UserId == null) { - - + + } @if (_moduleType == "new") @@ -143,21 +143,20 @@ } else { - @foreach (Page p in _pages) { } - @foreach (Module module in _modules) { } - @((MarkupString)_copyModuleMessage) }
@@ -270,7 +269,6 @@ protected int _location { get; private set; } = int.MaxValue; protected string _visibility { get; private set; } = "view"; protected string _message { get; private set; } = ""; - protected string _copyModuleMessage { get; private set; } = ""; private string settingCategory = "CP-category"; private string settingPane = "CP-pane"; @@ -341,6 +339,13 @@ StateHasChanged(); } + private void ModuleTypeChanged(ChangeEventArgs e) + { + _moduleType = (string)e.Value; + _pageId = "-"; + _moduleId = "-"; + } + private void PageChanged(ChangeEventArgs e) { _pageId = (string)e.Value; @@ -348,26 +353,14 @@ { _modules = PageState.Modules .Where(module => module.PageId == int.Parse(_pageId) && - UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.PermissionList)) + UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.PermissionList) && + (_moduleType == "add" || module.ModuleDefinition.IsPortable)) .ToList(); } _moduleId = "-"; StateHasChanged(); } - private void ModuleIdChanged() - { - _copyModuleMessage = string.Empty; - if(_moduleId != "-") - { - var module = _modules.FirstOrDefault(item => item.ModuleId == int.Parse(_moduleId)); - if (module != null && !module.ModuleDefinition.IsPortable) - { - _copyModuleMessage = $"
{Localizer["Message.Module.NotPortable"]}
"; - } - } - } - private async Task AddModule() { if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.PermissionList)) @@ -387,7 +380,7 @@ module = await ModuleService.AddModuleAsync(module); newModuleId = module.ModuleId; } - else if (_moduleType == "exsiting.copy") + else if (_moduleType == "copy") { var module = await ModuleService.GetModuleAsync(int.Parse(_moduleId)); module.ModuleId = 0; diff --git a/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs b/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs index 959f4d07..6c9293fb 100644 --- a/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs +++ b/Oqtane.Server/Modules/HtmlText/Manager/HtmlTextManager.cs @@ -7,6 +7,7 @@ using Oqtane.Repository; using Oqtane.Shared; using Oqtane.Migrations.Framework; using Oqtane.Documentation; +using System.Linq; // ReSharper disable ConvertToUsingDeclaration @@ -29,10 +30,11 @@ namespace Oqtane.Modules.HtmlText.Manager public string ExportModule(Module module) { string content = ""; - var htmlText = _htmlText.GetHtmlText(module.ModuleId); - if (htmlText != null) + var htmltexts = _htmlText.GetHtmlTexts(module.ModuleId); + if (htmltexts != null && htmltexts.Any()) { - content = WebUtility.HtmlEncode(htmlText.Content); + var htmltext = htmltexts.OrderByDescending(item => item.CreatedOn).First(); + content = WebUtility.HtmlEncode(htmltext.Content); } return content; } From 378b81b13bb1e11d565d7afe3451fbbfe15ea268 Mon Sep 17 00:00:00 2001 From: Leigh Pointer Date: Tue, 30 Apr 2024 08:17:53 +0200 Subject: [PATCH 35/77] Fix for missing parameters and Resx values Issue #4202 Issue #4203 --- Oqtane.Client/Modules/Admin/Roles/Index.razor | 4 ++-- Oqtane.Client/Modules/Admin/UrlMappings/Index.razor | 2 +- Oqtane.Client/Resources/Modules/Admin/UrlMappings/Index.resx | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Roles/Index.razor b/Oqtane.Client/Modules/Admin/Roles/Index.razor index 6b0e4610..44ffe0c3 100644 --- a/Oqtane.Client/Modules/Admin/Roles/Index.razor +++ b/Oqtane.Client/Modules/Admin/Roles/Index.razor @@ -20,9 +20,9 @@ else @SharedLocalizer["Name"] - + - + @context.Name diff --git a/Oqtane.Client/Modules/Admin/UrlMappings/Index.razor b/Oqtane.Client/Modules/Admin/UrlMappings/Index.razor index 6ed8c769..bae495fb 100644 --- a/Oqtane.Client/Modules/Admin/UrlMappings/Index.razor +++ b/Oqtane.Client/Modules/Admin/UrlMappings/Index.razor @@ -37,7 +37,7 @@ else @Localizer["Requested"] - + @context.Url diff --git a/Oqtane.Client/Resources/Modules/Admin/UrlMappings/Index.resx b/Oqtane.Client/Resources/Modules/Admin/UrlMappings/Index.resx index 4ee3cbfe..188c09e3 100644 --- a/Oqtane.Client/Resources/Modules/Admin/UrlMappings/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/UrlMappings/Index.resx @@ -159,4 +159,7 @@ Url + + Edit + \ No newline at end of file From 2b709ad0949e03c4a004e508a20da2b389919ebd Mon Sep 17 00:00:00 2001 From: iJungleboy Date: Tue, 30 Apr 2024 13:14:58 +0200 Subject: [PATCH 36/77] Update README.md, move history to docs moved release history and old announcements to the docs --- README.md | 193 +----------------------------------------------------- 1 file changed, 1 insertion(+), 192 deletions(-) diff --git a/README.md b/README.md index c4b664e9..633a3940 100644 --- a/README.md +++ b/README.md @@ -79,202 +79,11 @@ Backlog (TBD) [5.0.0](https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.0) (Nov 16, 2023) - [x] Migration to .NET 8 -[4.0.6](https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.6) ( Oct 16, 2023 ) -- [x] Stabilization improvements - -[4.0.5](https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.5) ( Sep 26, 2023 ) -- [x] Stabilization improvements - -[4.0.4](https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.4) ( Sep 25, 2023 ) -- [x] Stabilization improvements -- [x] User Import - -[4.0.3](https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.3) ( Aug 29, 2023 ) -- [x] Stabilization improvements - -[4.0.2](https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.2) ( Aug 9, 2023 ) -- [x] Stabilization improvements - -[4.0.1](https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.1) ( Jul 18, 2023 ) -- [x] Stabilization improvements - -[4.0.0](https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.0) ( Jun 26, 2023 ) -- [x] Migration to .NET 7 -- [x] Improved JavaScript, CSS, and Meta support -- [x] Optimized Client Assembly Loading -- [x] Routable Modules (ie. declarative configuration) -- [x] Site Template improvements -- [x] IEventSubscriber interface - -[3.4.3](https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.3) ( May 3, 2023 ) -- [x] Stabilization improvements - -[3.4.2](https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.2) ( Mar 29, 2023 ) -- [x] Stabilization improvements - -[3.4.1](https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.1) ( Mar 13, 2023 ) -- [x] Stabilization improvements - -[3.4.0](https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.0) ( Mar 12, 2023 ) -- [x] Permissions performance optimization -- [x] Connection string management improvements -- [x] XML site map generator -- [x] OIDC integration with User Profiles - -[3.3.1](https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.1) ( Jan 14, 2023 ) -- [x] Stabilization improvements - -[3.3.0](https://github.com/oqtane/oqtane.framework/releases/tag/v3.3.0) ( Jan 12, 2023 ) -- [x] Dynamic Authorization Policies -- [x] Entity-Level Permissions -- [x] Extended Module Permissions - -[3.2.1](https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1) ( Oct 17, 2022 ) -- [x] Stabilization improvements -- [x] Server Event System - -[3.2.0](https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.0) ( Sep 13, 2022 ) -- [x] .NET MAUI / Blazor Hybrid support -- [x] Upgrade to Bootstrap 5.2 - -[3.1.3](https://github.com/oqtane/oqtane.framework/releases/tag/v3.1.3) ( Jun 27, 2022 ) -- [x] Stabilization improvements - -[3.1.2](https://github.com/oqtane/oqtane.framework/releases/tag/v3.1.2) ( May 14, 2022 ) -- [x] Stabilization improvements - -[3.1.1](https://github.com/oqtane/oqtane.framework/releases/tag/v3.1.1) ( May 3, 2022 ) -- [x] Stabilization improvements - -[3.1.0](https://github.com/oqtane/oqtane.framework/releases/tag/v3.1.0) ( Apr 5, 2022 ) -- [x] User account lockout support -- [x] Two factor authentication support -- [x] Per-site configuration of password complexity, lockout criteria -- [x] External login support via OAuth2 / OpenID Connect -- [x] Support for Single Sign On (SSO) via OpenID Connect -- [x] External client support via Jwt tokens -- [x] Downstream API support via Jwt tokens -- [x] CSS resource hierarchy support -- [x] Site structure/content migration -- [x] Event log notifications -- [x] 404 page handling -- [x] Property change component notifications -- [x] Support for ES6 JavaScript modules - -[3.0.3](https://github.com/oqtane/oqtane.framework/releases/tag/v3.0.3) ( Feb 15, 2022 ) -- [x] Url fragment and anchor navigation support -- [x] Meta tag support in page head -- [x] Html/Text content versioning support - -[3.0.2](https://github.com/oqtane/oqtane.framework/releases/tag/v3.0.2) ( Jan 16, 2022 ) -- [x] Default alias specification, auto alias registration, redirect logic -- [x] Improvements to visitor tracking and url mapping -- [x] Scheduler enhancements for stop/start, weekly and one-time jobs -- [x] Purge job for daily housekeeping of event log and visitors -- [x] Granular security filtering for Settings - -[3.0.1](https://github.com/oqtane/oqtane.framework/releases/tag/v3.0.1) ( Dec 12, 2021 ) -- [x] Url mapping for broken links, content migration -- [x] Visitor tracking for usage insights, personalization -- [x] User experience improvements in Page and Module management - -[3.0.0](https://github.com/oqtane/oqtane.framework/releases/tag/v3.0.0) ( Nov 11, 2021 ) -- [x] Migration to .NET 6 -- [x] Blazor hosting model flexibility per site -- [x] Blazor WebAssembly prerendering support - -[2.3.1](https://github.com/oqtane/oqtane.framework/releases/tag/v2.3.1) ( Sep 27, 2021 ) -- [x] Complete UI migration to Bootstrap 5 and HTML5 form validation -- [x] Improve module/theme installation and add support for commercial extensions -- [x] Replace System.Drawing with ImageSharp -- [x] Image resizing service - -[2.2.0](https://github.com/oqtane/oqtane.framework/releases/tag/v2.2.0) ( Jul 6, 2021 ) -- [x] Bootstrap 5 Upgrade -- [x] Package Service integration -- [x] Default and Shared Resource File inclusion -- [x] Startup Error logging -- [x] API Controller Validation and Logging - -[2.1.0](https://github.com/oqtane/oqtane.framework/releases/tag/v2.1.0) ( Jun 4, 2021 ) -- [x] Cross Platform Database Support ( ie. LocalDB, SQL Server, SQLite, MySQL, PostgreSQL ) - see [#964](https://github.com/oqtane/oqtane.framework/discussions/964) -- [x] Utilize EF Core Migrations - see [#964](https://github.com/oqtane/oqtane.framework/discussions/964) -- [x] Public Content Folder support -- [x] Multi-tenant Infrastructure improvements -- [x] User Authorization optimization -- [x] Consolidation of Package Management -- [x] Blazor Server Pre-rendering -- [x] Translation Package installation support - -[2.0.2](https://github.com/oqtane/oqtane.framework/releases/tag/v2.0.2) ( Apr 19, 2021 ) -- [x] Assorted fixes and user experience improvements - -[2.0.1](https://github.com/oqtane/oqtane.framework/releases/tag/v2.0.1) ( Feb 27, 2021 ) -- [x] Complete Static Localization of Admin UI - -[2.0.0](https://github.com/oqtane/oqtane.framework/releases/tag/v2.0.0) ( Nov 11, 2020 ) -- [x] Migration to .NET 5 -- [x] Static Localization ( ie. labels, help text, etc.. ) -- [x] Improved JavaScript Reference Support -- [x] Performance Optimizations -- [x] Developer Productivity Enhancements - -[1.0.0](https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.0) ( May 19, 2020 ) -- [x] Migration to .NET Core 3.2 -- [x] Multi-Tenant ( Shared Database & Isolated Database ) -- [x] Modular Architecture -- [x] Headless API with Swagger Support -- [x] Dynamic Page Compositing Model / Site & Page Management -- [x] Authentication / User Management / Profile Management -- [x] Authorization / Roles Management / Granular Permissions -- [x] Dynamic Routing -- [x] Extensibility via Custom Modules -- [x] Extensibility via Custom Themes -- [x] Event Logging / Audit Trail -- [x] Folder / File Management -- [x] Recycle Bin -- [x] Scheduled Jobs ( Background Processing ) -- [x] Notifications / Email Delivery -- [x] Seamless Upgrade Experience -- [x] Progressive Web Application Support -- [x] JavaScript Lazy Loading -- [x] Dynamic CSS/Lazy Loading - -[POC](https://www.oqtane.org/blog/!/7/announcing-oqtane-a-modular-application-framework-for-blazor) ( May 9, 2019 ) -- [x] Initial public release on GitHub -- [x] .NET Core 3.0 +➡️ Full list and older versions can be found in the [docs roadmap](https://docs.oqtane.org/guides/roadmap/index.html) # Background Oqtane was created by [Shaun Walker](https://www.linkedin.com/in/shaunbrucewalker/) and is inspired by the DotNetNuke web application framework. Initially created as a proof of concept, Oqtane is a native Blazor application written from the ground up using modern .NET Core technology and a Single Page Application (SPA) architecture. It is a modular application framework offering a fully dynamic page compositing model, multi-site support, designer friendly themes, and extensibility via third party modules. -# Release Announcements - -[Oqtane 5.1](https://www.oqtane.org/blog/!/75/announcing-oqtane-5-0-for-net-8) - -[Oqtane 5.0](https://www.oqtane.org/blog/!/75/announcing-oqtane-5-0-for-net-8) - -[Oqtane 4.0](https://www.oqtane.org/blog/!/63/announcing-oqtane-4-0-for-net-7) - -[Oqtane 3.4](https://www.oqtane.org/blog/!/56/oqtane-3-4-0-released) - -[Oqtane 3.3](https://www.oqtane.org/blog/!/54/oqtane-3-3-0-released) - -[Oqtane 3.2](https://www.oqtane.org/blog/!/50/oqtane-3-2-for-net-maui-blazor-hybrid) - -[Oqtane 3.1](https://www.oqtane.org/blog/!/41/oqtane-3-1-released) - -[Oqtane 3.0](https://www.oqtane.org/Resources/Blog/PostId/551/announcing-oqtane-30-for-net-6) - -[Oqtane 2.2](https://www.oqtane.org/Resources/Blog/PostId/549/oqtane-22-upgrades-to-bootstrap-5) - -[Oqtane 2.1](https://www.oqtane.org/Resources/Blog/PostId/548/oqtane-21-now-supports-multiple-databases) - -[Oqtane 2.0](https://www.oqtane.org/Resources/Blog/PostId/544/announcing-oqtane-20-for-net-5) - -[Oqtane 1.0](https://www.oqtane.org/Resources/Blog/PostId/540/announcing-oqtane-10-a-modular-application-framework-for-blazor) - -[Oqtane POC](https://www.oqtane.org/Resources/Blog/PostId/520/announcing-oqtane-a-modular-application-framework-for-blazor) - # Reference Implementations [Built On Blazor!](https://builtonblazor.net) - a showcase of sites built on Blazor From 4770daa7c60a3160ef650263d390763f22fd2f2f Mon Sep 17 00:00:00 2001 From: Leigh Pointer Date: Tue, 30 Apr 2024 19:46:10 +0200 Subject: [PATCH 37/77] Fix for Issue #4210 and part #4209 This I will work on on a different Issue --- .../Modules/Admin/Modules/Settings.razor | 2 +- .../Modules/Admin/Modules/Settings.resx | 3 + .../Themes/Controls/ModuleActionsBase.resx | 150 ++++++++++++++++++ .../Controls/Container/ModuleActionsBase.cs | 17 +- 4 files changed, 164 insertions(+), 8 deletions(-) create mode 100644 Oqtane.Client/Resources/Themes/Controls/ModuleActionsBase.resx diff --git a/Oqtane.Client/Modules/Admin/Modules/Settings.razor b/Oqtane.Client/Modules/Admin/Modules/Settings.razor index 0031c729..03102dde 100644 --- a/Oqtane.Client/Modules/Admin/Modules/Settings.razor +++ b/Oqtane.Client/Modules/Admin/Modules/Settings.razor @@ -94,7 +94,7 @@
} - + @if (_permissions != null) {
diff --git a/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx b/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx index b872c727..b08997ee 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx @@ -180,4 +180,7 @@ Permissions + + Permissions + \ No newline at end of file diff --git a/Oqtane.Client/Resources/Themes/Controls/ModuleActionsBase.resx b/Oqtane.Client/Resources/Themes/Controls/ModuleActionsBase.resx new file mode 100644 index 00000000..fe72e3ea --- /dev/null +++ b/Oqtane.Client/Resources/Themes/Controls/ModuleActionsBase.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 + + + Delete Module + + + Export Content + + + Import Content + + + Manage Settings + + + Move Down + + + Move To Bottom + + + Move To Top + + + MoveUp + + + Publish Module + + + Unpublish Module + + \ No newline at end of file diff --git a/Oqtane.Client/Themes/Controls/Container/ModuleActionsBase.cs b/Oqtane.Client/Themes/Controls/Container/ModuleActionsBase.cs index 3ca24a69..54e01ef4 100644 --- a/Oqtane.Client/Themes/Controls/Container/ModuleActionsBase.cs +++ b/Oqtane.Client/Themes/Controls/Container/ModuleActionsBase.cs @@ -9,6 +9,8 @@ using Oqtane.Services; using Oqtane.Shared; using Oqtane.UI; using System.Net; +using static System.Runtime.InteropServices.JavaScript.JSType; +using Microsoft.Extensions.Localization; // ReSharper disable UnassignedGetOnlyAutoProperty // ReSharper disable MemberCanBePrivate.Global @@ -20,6 +22,7 @@ namespace Oqtane.Themes.Controls [Inject] public NavigationManager NavigationManager { get; set; } [Inject] public IPageModuleService PageModuleService { get; set; } [Inject] public IModuleService ModuleService { get; set; } + [Inject] public IStringLocalizer Localizer { get; set; } [Parameter] public PageState PageState { get; set; } [Parameter] public Module ModuleState { get; set; } @@ -37,30 +40,30 @@ namespace Oqtane.Themes.Controls if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.PermissionList)) { - actionList.Add(new ActionViewModel { Icon = Icons.Cog, Name = "Manage Settings", Action = async (u, m) => await Settings(u, m) }); + actionList.Add(new ActionViewModel { Icon = Icons.Cog, Name = Localizer["ManageSettings"], Action = async (u, m) => await Settings(u, m) }); if (UserSecurity.ContainsRole(ModuleState.PermissionList, PermissionNames.View, RoleNames.Everyone)) { - actionList.Add(new ActionViewModel { Icon = Icons.CircleX, Name = "Unpublish Module", Action = async (s, m) => await Unpublish(s, m) }); + actionList.Add(new ActionViewModel { Icon = Icons.CircleX, Name = Localizer["UnpublishModule"], Action = async (s, m) => await Unpublish(s, m) }); } else { - actionList.Add(new ActionViewModel { Icon = Icons.CircleCheck, Name = "Publish Module", Action = async (s, m) => await Publish(s, m) }); + actionList.Add(new ActionViewModel { Icon = Icons.CircleCheck, Name = Localizer["PublishModule"], Action = async (s, m) => await Publish(s, m) }); } - actionList.Add(new ActionViewModel { Icon = Icons.Trash, Name = "Delete Module", Action = async (u, m) => await DeleteModule(u, m) }); + actionList.Add(new ActionViewModel { Icon = Icons.Trash, Name = Localizer["DeleteModule"], Action = async (u, m) => await DeleteModule(u, m) }); if (ModuleState.ModuleDefinition != null && ModuleState.ModuleDefinition.IsPortable) { actionList.Add(new ActionViewModel { Name = "" }); - actionList.Add(new ActionViewModel { Icon = Icons.CloudUpload, Name = "Import Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Import") }); - actionList.Add(new ActionViewModel { Icon = Icons.CloudDownload, Name = "Export Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Export") }); + actionList.Add(new ActionViewModel { Icon = Icons.CloudUpload, Name = Localizer["ImportContent"], Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Import") }); + actionList.Add(new ActionViewModel { Icon = Icons.CloudDownload, Name = Localizer["ExportContent"], Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Export") }); } actionList.Add(new ActionViewModel { Name = "" }); if (ModuleState.PaneModuleIndex > 0) { - actionList.Add(new ActionViewModel { Icon = Icons.DataTransferUpload, Name = "Move To Top", Action = async (s, m) => await MoveTop(s, m) }); + actionList.Add(new ActionViewModel { Icon = Icons.DataTransferUpload, Name = Localizer["MoveToTop"], Action = async (s, m) => await MoveTop(s, m) }); } if (ModuleState.PaneModuleIndex > 0) From 53217b061d9f141be6f60e5bac0425cba8bf1be4 Mon Sep 17 00:00:00 2001 From: Leigh Pointer Date: Tue, 30 Apr 2024 20:07:34 +0200 Subject: [PATCH 38/77] ModuleSettings ContainerSettings #4211 ModuleSettings ContainerSettings #4211 --- .../Resources/Modules/Admin/Modules/Settings.resx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx b/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx index b872c727..3b7fc1dc 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx @@ -156,7 +156,7 @@ Module: - + Module Settings @@ -180,4 +180,10 @@ Permissions + + Container Settings + + + Module Settings + \ No newline at end of file From 4ac827b9e872833df24aabdc80683ac634cf67c9 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Tue, 30 Apr 2024 16:41:24 -0400 Subject: [PATCH 39/77] fix #4206 - validate folder name for duplicates --- Oqtane.Client/Modules/Admin/Files/Edit.razor | 11 +++++++++-- Oqtane.Client/Resources/Modules/Admin/Files/Edit.resx | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Files/Edit.razor b/Oqtane.Client/Modules/Admin/Files/Edit.razor index 05990fe4..e026b7b5 100644 --- a/Oqtane.Client/Modules/Admin/Files/Edit.razor +++ b/Oqtane.Client/Modules/Admin/Files/Edit.razor @@ -170,6 +170,7 @@ try { Folder folder; + if (_folderId != -1) { folder = await FolderService.GetFolderAsync(_folderId); @@ -179,8 +180,6 @@ folder = new Folder(); } - folder.SiteId = PageState.Site.SiteId; - if (_parentId == -1) { folder.ParentId = null; @@ -189,7 +188,15 @@ { folder.ParentId = _parentId; } + + // check for duplicate folder names + if (_folders.Any(item => item.ParentId == folder.ParentId && item.Name == _name && item.FolderId != _folderId)) + { + AddModuleMessage(Localizer["Message.Folder.Duplicate"], MessageType.Warning); + return; + } + folder.SiteId = PageState.Site.SiteId; folder.Name = _name; folder.Type = _type; folder.ImageSizes = _imagesizes; diff --git a/Oqtane.Client/Resources/Modules/Admin/Files/Edit.resx b/Oqtane.Client/Resources/Modules/Admin/Files/Edit.resx index cd3d71bb..a8d788c6 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Files/Edit.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Files/Edit.resx @@ -195,4 +195,7 @@ Folder Management + + Folder Name Specified Already Exists In Parent + \ No newline at end of file From 21e2700da509ac1002e8fcce34e23e740a6f371d Mon Sep 17 00:00:00 2001 From: Leigh Pointer Date: Wed, 1 May 2024 08:33:51 +0200 Subject: [PATCH 40/77] ModuleSettings Title Localized --- Oqtane.Client/Modules/Admin/Modules/Settings.razor | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Modules/Settings.razor b/Oqtane.Client/Modules/Admin/Modules/Settings.razor index 0031c729..9044a79c 100644 --- a/Oqtane.Client/Modules/Admin/Modules/Settings.razor +++ b/Oqtane.Client/Modules/Admin/Modules/Settings.razor @@ -128,7 +128,7 @@ @code { public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit; - public override string Title => "Module Settings"; + public override string Title => Localizer["ModuleSettings.Title"]; private ElementReference form; private bool validated = false; @@ -144,7 +144,7 @@ private PermissionGrid _permissionGrid; private Type _moduleSettingsType; private object _moduleSettings; - private string _moduleSettingsTitle = "Module Settings"; + private string _moduleSettingsTitle; private RenderFragment ModuleSettingsComponent { get; set; } private Type _containerSettingsType; private object _containerSettings; @@ -160,6 +160,7 @@ { _module = ModuleState.ModuleDefinition.Name; _title = ModuleState.Title; + _moduleSettingsTitle = Localizer["ModuleSettings.Heading"]; _pane = ModuleState.Pane; _containers = ThemeService.GetContainerControls(PageState.Site.Themes, PageState.Page.ThemeType); _containerType = ModuleState.ContainerType; From 3f742f5f8e6cfa76b657dda596958d15d0d8f956 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Wed, 1 May 2024 11:52:07 -0400 Subject: [PATCH 41/77] fix RESX file (add missing element) --- Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx | 1 + 1 file changed, 1 insertion(+) diff --git a/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx b/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx index 1763d5a2..a91aa36e 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx @@ -182,6 +182,7 @@ Permissions + Container Settings From 0de5c043bba22419c640688e500b48aa722b1e8e Mon Sep 17 00:00:00 2001 From: sbwalker Date: Wed, 1 May 2024 15:18:36 -0400 Subject: [PATCH 42/77] fix support for Site-level Scripts in Resources --- Oqtane.Client/UI/SiteRouter.razor | 2 +- Oqtane.Server/Components/App.razor | 50 +++++++++++++++--------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Oqtane.Client/UI/SiteRouter.razor b/Oqtane.Client/UI/SiteRouter.razor index ec1bc0be..9e13eeb8 100644 --- a/Oqtane.Client/UI/SiteRouter.razor +++ b/Oqtane.Client/UI/SiteRouter.razor @@ -551,7 +551,7 @@ { foreach (var resource in resources) { - if (resource.Level != ResourceLevel.Site) + if (resource.ResourceType == ResourceType.Stylesheet || resource.Level != ResourceLevel.Site) { if (resource.Url.StartsWith("~")) { diff --git a/Oqtane.Server/Components/App.razor b/Oqtane.Server/Components/App.razor index 7de887fc..541d08e4 100644 --- a/Oqtane.Server/Components/App.razor +++ b/Oqtane.Server/Components/App.razor @@ -176,15 +176,11 @@ CreateJwtToken(alias); } - // include stylesheets to prevent FOUC + // includes resources var resources = GetPageResources(alias, site, page, int.Parse(route.ModuleId, CultureInfo.InvariantCulture), route.Action); ManageStyleSheets(resources); + ManageScripts(resources, alias); - // scripts - if (_renderMode == RenderModes.Static) - { - ManageScripts(resources, alias); - } if (_renderMode == RenderModes.Interactive && _runtime == Runtimes.Server) { _reconnectScript = CreateReconnectScript(); @@ -567,13 +563,13 @@ var theme = site.Themes.FirstOrDefault(item => item.Themes.Any(item => item.TypeName == themeType)); if (theme != null) { - resources = AddResources(resources, theme.Resources, ResourceLevel.Page, alias, "Themes", Utilities.GetTypeName(theme.ThemeName)); + resources = AddResources(resources, theme.Resources, ResourceLevel.Page, alias, "Themes", Utilities.GetTypeName(theme.ThemeName), site.RenderMode); } else { // fallback to default Oqtane theme theme = site.Themes.FirstOrDefault(item => item.Themes.Any(item => item.TypeName == Constants.DefaultTheme)); - resources = AddResources(resources, theme.Resources, ResourceLevel.Page, alias, "Themes", Utilities.GetTypeName(theme.ThemeName)); + resources = AddResources(resources, theme.Resources, ResourceLevel.Page, alias, "Themes", Utilities.GetTypeName(theme.ThemeName), site.RenderMode); } var type = Type.GetType(themeType); if (type != null) @@ -581,7 +577,7 @@ var obj = Activator.CreateInstance(type) as IThemeControl; if (obj != null) { - resources = AddResources(resources, obj.Resources, ResourceLevel.Page, alias, "Themes", type.Namespace); + resources = AddResources(resources, obj.Resources, ResourceLevel.Page, alias, "Themes", type.Namespace, site.RenderMode); } } @@ -590,7 +586,7 @@ var typename = ""; if (module.ModuleDefinition != null) { - resources = AddResources(resources, module.ModuleDefinition.Resources, ResourceLevel.Module, alias, "Modules", Utilities.GetTypeName(module.ModuleDefinition.ModuleDefinitionName)); + resources = AddResources(resources, module.ModuleDefinition.Resources, ResourceLevel.Module, alias, "Modules", Utilities.GetTypeName(module.ModuleDefinition.ModuleDefinitionName), site.RenderMode); // handle default action if (action == Constants.DefaultAction && !string.IsNullOrEmpty(module.ModuleDefinition.DefaultAction)) @@ -636,7 +632,7 @@ var obj = Activator.CreateInstance(moduletype) as IModuleControl; if (obj != null) { - resources = AddResources(resources, obj.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace); + resources = AddResources(resources, obj.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace, site.RenderMode); if (action.ToLower() == "settings" && module.ModuleDefinition != null) { // settings components are embedded within a framework settings module @@ -644,7 +640,7 @@ if (moduletype != null) { obj = Activator.CreateInstance(moduletype) as IModuleControl; - resources = AddResources(resources, obj.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace); + resources = AddResources(resources, obj.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace, site.RenderMode); } } } @@ -657,32 +653,35 @@ { if (module.ModuleDefinition?.Resources != null) { - resources = AddResources(resources, module.ModuleDefinition.Resources.Where(item => item.Level == ResourceLevel.Site).ToList(), ResourceLevel.Module, alias, "Modules", Utilities.GetTypeName(module.ModuleDefinition.ModuleDefinitionName)); + resources = AddResources(resources, module.ModuleDefinition.Resources.Where(item => item.ResourceType == ResourceType.Script && item.Level == ResourceLevel.Site).ToList(), ResourceLevel.Module, alias, "Modules", Utilities.GetTypeName(module.ModuleDefinition.ModuleDefinitionName), site.RenderMode); } } return resources; } - private List AddResources(List pageresources, List resources, ResourceLevel level, Alias alias, string type, string name) + private List AddResources(List pageresources, List resources, ResourceLevel level, Alias alias, string type, string name, string rendermode) { if (resources != null) { foreach (var resource in resources) { - if (resource.Url.StartsWith("~")) + if (rendermode == RenderModes.Static || resource.ResourceType == ResourceType.Stylesheet || resource.Level == ResourceLevel.Site) { - resource.Url = resource.Url.Replace("~", "/" + type + "/" + name + "/").Replace("//", "/"); - } - if (!resource.Url.Contains("://") && alias.BaseUrl != "" && !resource.Url.StartsWith(alias.BaseUrl)) - { - resource.Url = alias.BaseUrl + resource.Url; - } + if (resource.Url.StartsWith("~")) + { + resource.Url = resource.Url.Replace("~", "/" + type + "/" + name + "/").Replace("//", "/"); + } + if (!resource.Url.Contains("://") && alias.BaseUrl != "" && !resource.Url.StartsWith(alias.BaseUrl)) + { + resource.Url = alias.BaseUrl + resource.Url; + } - // ensure resource does not exist already - if (!pageresources.Exists(item => item.Url.ToLower() == resource.Url.ToLower())) - { - pageresources.Add(resource.Clone(level, name)); + // ensure resource does not exist already + if (!pageresources.Exists(item => item.Url.ToLower() == resource.Url.ToLower())) + { + pageresources.Add(resource.Clone(level, name)); + } } } } @@ -693,6 +692,7 @@ { if (resources != null) { + // include stylesheets to prevent FOUC string batch = DateTime.UtcNow.ToString("yyyyMMddHHmmssfff"); int count = 0; foreach (var resource in resources.Where(item => item.ResourceType == ResourceType.Stylesheet)) From 4f5b33d8dfede8e95c6314ef78eab5136d81cc17 Mon Sep 17 00:00:00 2001 From: Leigh Pointer Date: Thu, 2 May 2024 09:03:26 +0200 Subject: [PATCH 43/77] Null or empty check for FormatContent Added null or empty check for the content and alias parameters at the beginning of the method. --- Oqtane.Shared/Shared/Utilities.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Oqtane.Shared/Shared/Utilities.cs b/Oqtane.Shared/Shared/Utilities.cs index 61dd5740..5498a87a 100644 --- a/Oqtane.Shared/Shared/Utilities.cs +++ b/Oqtane.Shared/Shared/Utilities.cs @@ -139,6 +139,9 @@ namespace Oqtane.Shared public static string FormatContent(string content, Alias alias, string operation) { + if (string.IsNullOrEmpty(content) || alias == null) + return content; + var aliasUrl = (alias != null && !string.IsNullOrEmpty(alias.Path)) ? "/" + alias.Path : ""; switch (operation) { From 653352bff0c90297fac201b6d9e9ac0c5dd64091 Mon Sep 17 00:00:00 2001 From: David Montesinos <90258222+mdmontesinos@users.noreply.github.com> Date: Thu, 2 May 2024 10:36:29 +0200 Subject: [PATCH 44/77] Support for IconOnly in ActionDialog open button --- .../Modules/Controls/ActionDialog.razor | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/Oqtane.Client/Modules/Controls/ActionDialog.razor b/Oqtane.Client/Modules/Controls/ActionDialog.razor index 1125d7b0..defb520d 100644 --- a/Oqtane.Client/Modules/Controls/ActionDialog.razor +++ b/Oqtane.Client/Modules/Controls/ActionDialog.razor @@ -35,11 +35,11 @@ { if (Disabled) { - + } else { - + } } } @@ -83,13 +83,13 @@ else { if (Disabled) { - + } else {
- +
} } @@ -101,6 +101,8 @@ else private bool _editmode = false; private bool _authorized = false; private string _iconSpan = string.Empty; + private string _openIconSpan = string.Empty; + private string _openText = string.Empty; [Parameter] public string Header { get; set; } // required @@ -138,6 +140,9 @@ else [Parameter] public string IconName { get; set; } // optional - specifies an icon for the link - default is no icon + [Parameter] + public bool IconOnly { get; set; } // optional - specifies only icon in opening link + [Parameter] public string Id { get; set; } // optional - specifies a unique id for the compoment - required when there are multiple component instances on a page in static rendering @@ -157,6 +162,8 @@ else { Text = Action; } + _openText = Text; + if (string.IsNullOrEmpty(Class)) { Class = "btn btn-success"; @@ -169,11 +176,17 @@ else if (!string.IsNullOrEmpty(IconName)) { + if (IconOnly) + { + _openText = string.Empty; + } + if (!IconName.Contains(" ")) { IconName = "oi oi-" + IconName; } - _iconSpan = $" "; + _openIconSpan = $"{(IconOnly ? "" : " ")}"; + _iconSpan = $" "; } Text = Localize(nameof(Text), Text); From 332e528012f321c42a0e9945503b18d9c055c71c Mon Sep 17 00:00:00 2001 From: Ikuo Ohba Date: Fri, 3 May 2024 21:18:28 +0900 Subject: [PATCH 45/77] Fix #4223 --- Oqtane.Server/Controllers/FileController.cs | 22 ++++++--------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/Oqtane.Server/Controllers/FileController.cs b/Oqtane.Server/Controllers/FileController.cs index aeeda0b2..677d922d 100644 --- a/Oqtane.Server/Controllers/FileController.cs +++ b/Oqtane.Server/Controllers/FileController.cs @@ -760,23 +760,13 @@ namespace Oqtane.Controllers { if (!Directory.Exists(folderpath)) { - string path = ""; - var separators = new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }; - string[] folders = folderpath.Split(separators, StringSplitOptions.RemoveEmptyEntries); - foreach (string folder in folders) + try { - path = Utilities.PathCombine(path, folder, Path.DirectorySeparatorChar.ToString()); - if (!Directory.Exists(path)) - { - try - { - Directory.CreateDirectory(path); - } - catch (Exception ex) - { - _logger.Log(LogLevel.Error, this, LogFunction.Create, ex, "Unable To Create Folder {Folder}", path); - } - } + Directory.CreateDirectory(folderpath); + } + catch (Exception ex) + { + _logger.Log(LogLevel.Error, this, LogFunction.Create, ex, "Unable To Create Folder {Folder}", folderpath); } } } From 021d7e5efcc4a76aca2a6b4ea3495d8f0840ced5 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Fri, 3 May 2024 13:37:10 -0400 Subject: [PATCH 46/77] fix #4221 - exception in Module Management when a module has been uninstalled (credit @marceloatoledo) --- Oqtane.Client/Modules/Admin/ModuleDefinitions/Edit.razor | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Edit.razor b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Edit.razor index 1e0c427c..0081e3e8 100644 --- a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Edit.razor +++ b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Edit.razor @@ -306,10 +306,9 @@ _languages = _languages.OrderBy(item => item.Name).ToList(); } - // Group modules by PageId - // Get distinct PageIds where modules are present + // get distinct pages where module exists var distinctPageIds = PageState.Modules - .Where(md => md.ModuleDefinition.ModuleDefinitionId == _moduleDefinitionId && md.IsDeleted == false) + .Where(md => md.ModuleDefinition?.ModuleDefinitionId == _moduleDefinitionId && md.IsDeleted == false) .Select(md => md.PageId) .Distinct(); From d047d26dbf43f958350d07a39a095d72a9201ee8 Mon Sep 17 00:00:00 2001 From: Ikuo Ohba Date: Sun, 5 May 2024 12:12:40 +0900 Subject: [PATCH 47/77] Reverted and fixed the source code. --- Oqtane.Server/Controllers/FileController.cs | 22 +++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/Oqtane.Server/Controllers/FileController.cs b/Oqtane.Server/Controllers/FileController.cs index 677d922d..4f5bcb2f 100644 --- a/Oqtane.Server/Controllers/FileController.cs +++ b/Oqtane.Server/Controllers/FileController.cs @@ -760,13 +760,23 @@ namespace Oqtane.Controllers { if (!Directory.Exists(folderpath)) { - try + string path = folderpath.StartsWith(Path.DirectorySeparatorChar) ? Path.DirectorySeparatorChar.ToString() : string.Empty; + var separators = new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }; + string[] folders = folderpath.Split(separators, StringSplitOptions.RemoveEmptyEntries); + foreach (string folder in folders) { - Directory.CreateDirectory(folderpath); - } - catch (Exception ex) - { - _logger.Log(LogLevel.Error, this, LogFunction.Create, ex, "Unable To Create Folder {Folder}", folderpath); + path = Utilities.PathCombine(path, folder, Path.DirectorySeparatorChar.ToString()); + if (!Directory.Exists(path)) + { + try + { + Directory.CreateDirectory(path); + } + catch (Exception ex) + { + _logger.Log(LogLevel.Error, this, LogFunction.Create, ex, "Unable To Create Folder {Folder}", path); + } + } } } } From a7952a4633a5e30a66de5cad00a319b54c9bd518 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Mon, 6 May 2024 15:56:05 -0400 Subject: [PATCH 48/77] add shadow-none to page links in pager --- Oqtane.Client/Modules/Controls/Pager.razor | 72 +++++++++++----------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/Oqtane.Client/Modules/Controls/Pager.razor b/Oqtane.Client/Modules/Controls/Pager.razor index a37166ec..8e643f17 100644 --- a/Oqtane.Client/Modules/Controls/Pager.razor +++ b/Oqtane.Client/Modules/Controls/Pager.razor @@ -23,16 +23,16 @@ { } @@ -86,16 +86,16 @@ { } @@ -202,16 +202,16 @@ { } @@ -250,16 +250,16 @@ { } From f7895823cbb289fff4bb48d9f8b5e42fb19f1494 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Tue, 7 May 2024 13:48:58 -0400 Subject: [PATCH 49/77] fix #4235 - add space above Logout button in Control Panel --- .../Themes/Controls/Theme/ControlPanelInteractive.razor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor b/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor index aa281da2..ab76f0bc 100644 --- a/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor +++ b/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor @@ -216,7 +216,7 @@
- +
From bf4052b550a3aa507306992249a9e84c07cf5d1a Mon Sep 17 00:00:00 2001 From: sbwalker Date: Wed, 8 May 2024 14:42:39 -0400 Subject: [PATCH 50/77] require AntiForgery on Static Rendered components --- .../Extensions/ComponentEndpointRouteBuilderExtensions.cs | 2 ++ Oqtane.Server/Startup.cs | 1 + 2 files changed, 3 insertions(+) diff --git a/Oqtane.Server/Extensions/ComponentEndpointRouteBuilderExtensions.cs b/Oqtane.Server/Extensions/ComponentEndpointRouteBuilderExtensions.cs index b464e81d..77731577 100644 --- a/Oqtane.Server/Extensions/ComponentEndpointRouteBuilderExtensions.cs +++ b/Oqtane.Server/Extensions/ComponentEndpointRouteBuilderExtensions.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Routing; using System; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Antiforgery; namespace OqtaneSSR.Extensions { @@ -23,6 +24,7 @@ namespace OqtaneSSR.Extensions { routeEndpointBuilder.Metadata.Add(new RootComponentMetadata(typeof(App))); routeEndpointBuilder.Metadata.Add(new ComponentTypeMetadata(typeof(App))); + routeEndpointBuilder.Metadata.Add(new RequireAntiforgeryTokenAttribute()); }); } } diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index 0a83d275..d4bf0161 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -216,6 +216,7 @@ namespace Oqtane app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); + app.UseAntiforgery(); if (_useSwagger) { From 2ae120c87889622e0c7510b2a207e489a32fa3a8 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Thu, 9 May 2024 14:42:54 -0400 Subject: [PATCH 51/77] add support for Auto Prerendering --- Oqtane.Client/Modules/Admin/Site/Index.razor | 2 +- Oqtane.Client/Modules/ModuleBase.cs | 2 +- .../Resources/Modules/Admin/Site/Index.resx | 2 +- Oqtane.Client/Resources/SharedResources.resx | 3 ++ .../Controls/Container/ModuleActions.razor | 2 +- .../Themes/Controls/Theme/ControlPanel.razor | 2 +- Oqtane.Client/UI/ModuleInstance.razor | 34 +++++++++++++++---- Oqtane.Client/UI/RenderModeBoundary.razor | 1 - Oqtane.Server/Components/App.razor | 2 +- 9 files changed, 37 insertions(+), 13 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Site/Index.razor b/Oqtane.Client/Modules/Admin/Site/Index.razor index 56df0b3e..633760e7 100644 --- a/Oqtane.Client/Modules/Admin/Site/Index.razor +++ b/Oqtane.Client/Modules/Admin/Site/Index.razor @@ -340,7 +340,7 @@
diff --git a/Oqtane.Client/Modules/ModuleBase.cs b/Oqtane.Client/Modules/ModuleBase.cs index 46fd01db..4c5bb670 100644 --- a/Oqtane.Client/Modules/ModuleBase.cs +++ b/Oqtane.Client/Modules/ModuleBase.cs @@ -52,7 +52,7 @@ namespace Oqtane.Modules public virtual string RenderMode { get { return RenderModes.Interactive; } } // interactive by default - public virtual bool? Prerender { get { return null; } } // prerender at server by default + public virtual bool? Prerender { get { return null; } } // allows the Site Prerender property to be overridden // url parameters public virtual string UrlParametersTemplate { get; set; } diff --git a/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx index 4617bd91..a6b10f64 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx @@ -277,7 +277,7 @@ UI Component Settings - Specifies if interactive components should prerender their output + Specifies if interactive components should prerender their output. The default is Auto which determines if a component should be prerendered at runtime based on the environment. Prerender? diff --git a/Oqtane.Client/Resources/SharedResources.resx b/Oqtane.Client/Resources/SharedResources.resx index dd4bc841..fd26490e 100644 --- a/Oqtane.Client/Resources/SharedResources.resx +++ b/Oqtane.Client/Resources/SharedResources.resx @@ -453,4 +453,7 @@ Static + + Auto + \ No newline at end of file diff --git a/Oqtane.Client/Themes/Controls/Container/ModuleActions.razor b/Oqtane.Client/Themes/Controls/Container/ModuleActions.razor index 749519a6..d2c7f6a1 100644 --- a/Oqtane.Client/Themes/Controls/Container/ModuleActions.razor +++ b/Oqtane.Client/Themes/Controls/Container/ModuleActions.razor @@ -10,6 +10,6 @@ } else { - + } } diff --git a/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor b/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor index 119f7690..c453117b 100644 --- a/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor +++ b/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor @@ -36,7 +36,7 @@ } else { - + } } diff --git a/Oqtane.Client/UI/ModuleInstance.razor b/Oqtane.Client/UI/ModuleInstance.razor index 37dd6d20..f501523d 100644 --- a/Oqtane.Client/UI/ModuleInstance.razor +++ b/Oqtane.Client/UI/ModuleInstance.razor @@ -1,13 +1,17 @@ @namespace Oqtane.UI @inject SiteState SiteState -@if (PageState.RenderMode == RenderModes.Interactive || ModuleState.RenderMode == RenderModes.Static) +@if (_comment != null) { - -} -else -{ - + @((MarkupString)_comment) + @if (PageState.RenderMode == RenderModes.Interactive || ModuleState.RenderMode == RenderModes.Static) + { + + } + else + { + + } } @code { @@ -20,6 +24,24 @@ else [CascadingParameter] private Module ModuleState { get; set; } + private bool _prerender; + private string _comment; + + protected override void OnParametersSet() + { + _prerender = ModuleState.Prerender ?? (PageState.Site.Prerender && PageState.User == null); + _comment = ""; + } + [Obsolete("AddModuleMessage is deprecated. Use AddModuleMessage in ModuleBase instead.", false)] public void AddModuleMessage(string message, MessageType type) diff --git a/Oqtane.Client/UI/RenderModeBoundary.razor b/Oqtane.Client/UI/RenderModeBoundary.razor index 2d9c8e07..b1f56793 100644 --- a/Oqtane.Client/UI/RenderModeBoundary.razor +++ b/Oqtane.Client/UI/RenderModeBoundary.razor @@ -10,7 +10,6 @@ { @if (ModuleType != null) { - @((MarkupString)$"") @DynamicComponent @if (_progressIndicator) diff --git a/Oqtane.Server/Components/App.razor b/Oqtane.Server/Components/App.razor index 541d08e4..61aad936 100644 --- a/Oqtane.Server/Components/App.razor +++ b/Oqtane.Server/Components/App.razor @@ -139,7 +139,7 @@ { _renderMode = site.RenderMode; _runtime = site.Runtime; - _prerender = site.Prerender; + _prerender = site.Prerender && !Context.User.Identity.IsAuthenticated; Route route = new Route(url, alias.Path); var page = site.Pages.FirstOrDefault(item => item.Path.Equals(route.PagePath, StringComparison.OrdinalIgnoreCase)); From c597b293b8ab04552661cfb86cb940d882b6ac93 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Thu, 9 May 2024 15:08:52 -0400 Subject: [PATCH 52/77] modify prerendering UI options --- Oqtane.Client/Modules/Admin/Site/Index.razor | 4 ++-- Oqtane.Client/Resources/Modules/Admin/Site/Index.resx | 2 +- Oqtane.Client/Resources/SharedResources.resx | 6 ++++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Site/Index.razor b/Oqtane.Client/Modules/Admin/Site/Index.razor index 633760e7..4b77c534 100644 --- a/Oqtane.Client/Modules/Admin/Site/Index.razor +++ b/Oqtane.Client/Modules/Admin/Site/Index.razor @@ -337,11 +337,11 @@
- +
diff --git a/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx index a6b10f64..45f3d029 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx @@ -280,7 +280,7 @@ Specifies if interactive components should prerender their output. The default is Auto which determines if a component should be prerendered at runtime based on the environment.
- Prerender? + Prerendering: The default render mode for the site diff --git a/Oqtane.Client/Resources/SharedResources.resx b/Oqtane.Client/Resources/SharedResources.resx index fd26490e..a07d7295 100644 --- a/Oqtane.Client/Resources/SharedResources.resx +++ b/Oqtane.Client/Resources/SharedResources.resx @@ -456,4 +456,10 @@ Auto + + Disabled + + + Enabled + \ No newline at end of file From d57c1e7ff0b7ac848fb3867be03c8c51ab31efb6 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Fri, 10 May 2024 16:28:19 -0400 Subject: [PATCH 53/77] revert prerender changes and change default --- Oqtane.Client/Modules/Admin/Site/Index.razor | 25 ++++++++++++++++--- .../Resources/Modules/Admin/Site/Index.resx | 4 +-- Oqtane.Client/Resources/SharedResources.resx | 3 --- Oqtane.Client/UI/ModuleInstance.razor | 2 +- Oqtane.Server/Components/App.razor | 2 +- .../Infrastructure/DatabaseManager.cs | 8 +++--- 6 files changed, 30 insertions(+), 14 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Site/Index.razor b/Oqtane.Client/Modules/Admin/Site/Index.razor index 4b77c534..a5626a5d 100644 --- a/Oqtane.Client/Modules/Admin/Site/Index.razor +++ b/Oqtane.Client/Modules/Admin/Site/Index.razor @@ -319,7 +319,7 @@
- @@ -337,11 +337,11 @@
- +
@@ -572,6 +572,23 @@ } } + private void RenderModeChanged(ChangeEventArgs e) + { + _rendermode = (string)e.Value; + switch (_rendermode) + { + case RenderModes.Interactive: + _prerender = "True"; + break; + case RenderModes.Static: + _prerender = "False"; + break; + case RenderModes.Headless: + _prerender = "False"; + break; + } + } + private async Task SaveSite() { validated = true; diff --git a/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx index 45f3d029..babf23e0 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx @@ -277,10 +277,10 @@ UI Component Settings
- Specifies if interactive components should prerender their output. The default is Auto which determines if a component should be prerendered at runtime based on the environment. + Specifies if interactive components should prerender their output on the server - Prerendering: + Prerender: The default render mode for the site diff --git a/Oqtane.Client/Resources/SharedResources.resx b/Oqtane.Client/Resources/SharedResources.resx index a07d7295..4161d868 100644 --- a/Oqtane.Client/Resources/SharedResources.resx +++ b/Oqtane.Client/Resources/SharedResources.resx @@ -453,9 +453,6 @@ Static - - Auto - Disabled diff --git a/Oqtane.Client/UI/ModuleInstance.razor b/Oqtane.Client/UI/ModuleInstance.razor index f501523d..8dfec04b 100644 --- a/Oqtane.Client/UI/ModuleInstance.razor +++ b/Oqtane.Client/UI/ModuleInstance.razor @@ -29,7 +29,7 @@ protected override void OnParametersSet() { - _prerender = ModuleState.Prerender ?? (PageState.Site.Prerender && PageState.User == null); + _prerender = ModuleState.Prerender ?? PageState.Site.Prerender; _comment = " Exe - 5.1.1 + 5.1.2 Oqtane Shaun Walker .NET Foundation @@ -14,7 +14,7 @@ .NET Foundation https://www.oqtane.org https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE - https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1 + https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.2 https://github.com/oqtane/oqtane.framework Git Oqtane.Maui @@ -31,7 +31,7 @@ 0E29FC31-1B83-48ED-B6E0-9F3C67B775D4 - 5.1.1 + 5.1.2 1 14.2 diff --git a/Oqtane.Package/Oqtane.Client.nuspec b/Oqtane.Package/Oqtane.Client.nuspec index 49cf9bd5..4b9d0a44 100644 --- a/Oqtane.Package/Oqtane.Client.nuspec +++ b/Oqtane.Package/Oqtane.Client.nuspec @@ -2,7 +2,7 @@ Oqtane.Client - 5.1.1 + 5.1.2 Shaun Walker .NET Foundation Oqtane Framework @@ -12,7 +12,7 @@ false MIT https://github.com/oqtane/oqtane.framework - https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1 + https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.2 icon.png oqtane diff --git a/Oqtane.Package/Oqtane.Framework.nuspec b/Oqtane.Package/Oqtane.Framework.nuspec index cfaef73d..d81c1693 100644 --- a/Oqtane.Package/Oqtane.Framework.nuspec +++ b/Oqtane.Package/Oqtane.Framework.nuspec @@ -2,7 +2,7 @@ Oqtane.Framework - 5.1.1 + 5.1.2 Shaun Walker .NET Foundation Oqtane Framework @@ -11,8 +11,8 @@ .NET Foundation false MIT - https://github.com/oqtane/oqtane.framework/releases/download/v5.1.1/Oqtane.Framework.5.1.1.Upgrade.zip - https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1 + https://github.com/oqtane/oqtane.framework/releases/download/v5.1.2/Oqtane.Framework.5.1.2.Upgrade.zip + https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.2 icon.png oqtane framework diff --git a/Oqtane.Package/Oqtane.Server.nuspec b/Oqtane.Package/Oqtane.Server.nuspec index 93c2942e..7a489cfb 100644 --- a/Oqtane.Package/Oqtane.Server.nuspec +++ b/Oqtane.Package/Oqtane.Server.nuspec @@ -2,7 +2,7 @@ Oqtane.Server - 5.1.1 + 5.1.2 Shaun Walker .NET Foundation Oqtane Framework @@ -12,7 +12,7 @@ false MIT https://github.com/oqtane/oqtane.framework - https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1 + https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.2 icon.png oqtane diff --git a/Oqtane.Package/Oqtane.Shared.nuspec b/Oqtane.Package/Oqtane.Shared.nuspec index ac34a811..ab1deb4d 100644 --- a/Oqtane.Package/Oqtane.Shared.nuspec +++ b/Oqtane.Package/Oqtane.Shared.nuspec @@ -2,7 +2,7 @@ Oqtane.Shared - 5.1.1 + 5.1.2 Shaun Walker .NET Foundation Oqtane Framework @@ -12,7 +12,7 @@ false MIT https://github.com/oqtane/oqtane.framework - https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1 + https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.2 icon.png oqtane diff --git a/Oqtane.Package/Oqtane.Updater.nuspec b/Oqtane.Package/Oqtane.Updater.nuspec index fe7d85bd..2c51fc0e 100644 --- a/Oqtane.Package/Oqtane.Updater.nuspec +++ b/Oqtane.Package/Oqtane.Updater.nuspec @@ -2,7 +2,7 @@ Oqtane.Updater - 5.1.1 + 5.1.2 Shaun Walker .NET Foundation Oqtane Framework @@ -12,7 +12,7 @@ false MIT https://github.com/oqtane/oqtane.framework - https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1 + https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.2 icon.png oqtane diff --git a/Oqtane.Package/install.ps1 b/Oqtane.Package/install.ps1 index ed93995d..57e2d394 100644 --- a/Oqtane.Package/install.ps1 +++ b/Oqtane.Package/install.ps1 @@ -1 +1 @@ -Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.1.1.Install.zip" -Force \ No newline at end of file +Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.1.2.Install.zip" -Force \ No newline at end of file diff --git a/Oqtane.Package/upgrade.ps1 b/Oqtane.Package/upgrade.ps1 index c5c23da0..0c0d2f56 100644 --- a/Oqtane.Package/upgrade.ps1 +++ b/Oqtane.Package/upgrade.ps1 @@ -1 +1 @@ -Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.1.1.Upgrade.zip" -Force \ No newline at end of file +Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.1.2.Upgrade.zip" -Force \ No newline at end of file diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index 7fe28c3d..3357bee6 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -3,7 +3,7 @@ net8.0 Debug;Release - 5.1.1 + 5.1.2 Oqtane Shaun Walker .NET Foundation @@ -11,7 +11,7 @@ .NET Foundation https://www.oqtane.org https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE - https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1 + https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.2 https://github.com/oqtane/oqtane.framework Git Oqtane diff --git a/Oqtane.Shared/Oqtane.Shared.csproj b/Oqtane.Shared/Oqtane.Shared.csproj index 3d8d4a78..6ef82a5b 100644 --- a/Oqtane.Shared/Oqtane.Shared.csproj +++ b/Oqtane.Shared/Oqtane.Shared.csproj @@ -3,7 +3,7 @@ net8.0 Debug;Release - 5.1.1 + 5.1.2 Oqtane Shaun Walker .NET Foundation @@ -11,7 +11,7 @@ .NET Foundation https://www.oqtane.org https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE - https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1 + https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.2 https://github.com/oqtane/oqtane.framework Git Oqtane diff --git a/Oqtane.Shared/Shared/Constants.cs b/Oqtane.Shared/Shared/Constants.cs index a7d1173e..b2b8c837 100644 --- a/Oqtane.Shared/Shared/Constants.cs +++ b/Oqtane.Shared/Shared/Constants.cs @@ -4,8 +4,8 @@ namespace Oqtane.Shared { public class Constants { - public static readonly string Version = "5.1.1"; - public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3,3.1.4,3.2.0,3.2.1,3.3.0,3.3.1,3.4.0,3.4.1,3.4.2,3.4.3,4.0.0,4.0.1,4.0.2,4.0.3,4.0.4,4.0.5,4.0.6,5.0.0,5.0.1,5.0.2,5.0.3,5.1.0,5.1.1"; + public static readonly string Version = "5.1.2"; + public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3,3.1.4,3.2.0,3.2.1,3.3.0,3.3.1,3.4.0,3.4.1,3.4.2,3.4.3,4.0.0,4.0.1,4.0.2,4.0.3,4.0.4,4.0.5,4.0.6,5.0.0,5.0.1,5.0.2,5.0.3,5.1.0,5.1.1,5.1.2"; public const string PackageId = "Oqtane.Framework"; public const string ClientId = "Oqtane.Client"; public const string UpdaterPackageId = "Oqtane.Updater"; diff --git a/Oqtane.Updater/Oqtane.Updater.csproj b/Oqtane.Updater/Oqtane.Updater.csproj index 4554897c..c9b31857 100644 --- a/Oqtane.Updater/Oqtane.Updater.csproj +++ b/Oqtane.Updater/Oqtane.Updater.csproj @@ -3,7 +3,7 @@ net8.0 Exe - 5.1.1 + 5.1.2 Oqtane Shaun Walker .NET Foundation @@ -11,7 +11,7 @@ .NET Foundation https://www.oqtane.org https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE - https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.1 + https://github.com/oqtane/oqtane.framework/releases/tag/v5.1.2 https://github.com/oqtane/oqtane.framework Git Oqtane From 5169ed494c230400aaa6a61ced92a2ead1416c7d Mon Sep 17 00:00:00 2001 From: sbwalker Date: Mon, 20 May 2024 16:54:11 -0400 Subject: [PATCH 71/77] upgrade to .NET 8.0.5 --- Oqtane.Client/Oqtane.Client.csproj | 6 +++--- .../Oqtane.Database.PostgreSQL.csproj | 4 ++-- .../Oqtane.Database.SqlServer.csproj | 2 +- .../Oqtane.Database.Sqlite.csproj | 2 +- Oqtane.Maui/Oqtane.Maui.csproj | 12 ++++++------ Oqtane.Server/Oqtane.Server.csproj | 16 ++++++++-------- Oqtane.Shared/Oqtane.Shared.csproj | 4 ++-- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Oqtane.Client/Oqtane.Client.csproj b/Oqtane.Client/Oqtane.Client.csproj index a600f3b9..884b79a0 100644 --- a/Oqtane.Client/Oqtane.Client.csproj +++ b/Oqtane.Client/Oqtane.Client.csproj @@ -22,9 +22,9 @@ - - - + + + diff --git a/Oqtane.Database.PostgreSQL/Oqtane.Database.PostgreSQL.csproj b/Oqtane.Database.PostgreSQL/Oqtane.Database.PostgreSQL.csproj index 06090744..04093e5a 100644 --- a/Oqtane.Database.PostgreSQL/Oqtane.Database.PostgreSQL.csproj +++ b/Oqtane.Database.PostgreSQL/Oqtane.Database.PostgreSQL.csproj @@ -34,8 +34,8 @@ - - + + diff --git a/Oqtane.Database.SqlServer/Oqtane.Database.SqlServer.csproj b/Oqtane.Database.SqlServer/Oqtane.Database.SqlServer.csproj index 3ce0dfa6..f742b253 100644 --- a/Oqtane.Database.SqlServer/Oqtane.Database.SqlServer.csproj +++ b/Oqtane.Database.SqlServer/Oqtane.Database.SqlServer.csproj @@ -33,7 +33,7 @@ - + diff --git a/Oqtane.Database.Sqlite/Oqtane.Database.Sqlite.csproj b/Oqtane.Database.Sqlite/Oqtane.Database.Sqlite.csproj index 4a8f9de0..80e4e18d 100644 --- a/Oqtane.Database.Sqlite/Oqtane.Database.Sqlite.csproj +++ b/Oqtane.Database.Sqlite/Oqtane.Database.Sqlite.csproj @@ -33,7 +33,7 @@ - + diff --git a/Oqtane.Maui/Oqtane.Maui.csproj b/Oqtane.Maui/Oqtane.Maui.csproj index 0181f307..a7a79ea3 100644 --- a/Oqtane.Maui/Oqtane.Maui.csproj +++ b/Oqtane.Maui/Oqtane.Maui.csproj @@ -65,15 +65,15 @@ - - + + - + - - - + + + diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj index 3357bee6..f661e715 100644 --- a/Oqtane.Server/Oqtane.Server.csproj +++ b/Oqtane.Server/Oqtane.Server.csproj @@ -33,19 +33,19 @@ - - + + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - - - + + + diff --git a/Oqtane.Shared/Oqtane.Shared.csproj b/Oqtane.Shared/Oqtane.Shared.csproj index 6ef82a5b..f16dcd9c 100644 --- a/Oqtane.Shared/Oqtane.Shared.csproj +++ b/Oqtane.Shared/Oqtane.Shared.csproj @@ -19,8 +19,8 @@ - - + + From 6c4e1d1c414cea5308bfb86955ca4f6d42b67dc0 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Mon, 20 May 2024 16:59:44 -0400 Subject: [PATCH 72/77] update theme and module templates to .NET SDK 8.0.5 --- .../External/Client/[Owner].Module.[Module].Client.csproj | 6 +++--- .../External/Server/[Owner].Module.[Module].Server.csproj | 8 ++++---- .../External/Client/[Owner].Theme.[Theme].Client.csproj | 6 +++--- 3 files changed, 10 insertions(+), 10 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 285cf9b7..8088f6cf 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 @@ -13,9 +13,9 @@ - - - + + + diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/[Owner].Module.[Module].Server.csproj b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/[Owner].Module.[Module].Server.csproj index d80b6abd..1bdfa524 100644 --- a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/[Owner].Module.[Module].Server.csproj +++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/[Owner].Module.[Module].Server.csproj @@ -19,10 +19,10 @@ - - - - + + + + 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 e143330b..4a10f700 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 @@ -12,9 +12,9 @@ - - - + + + From 0988a92d8a648e861a29b57b2f3238c6a18e28d3 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Mon, 20 May 2024 22:12:01 -0400 Subject: [PATCH 73/77] changed terminology from Library to Headless --- .../Themes/Controls/Theme/ControlPanelInteractive.razor | 2 +- Oqtane.Server/Repository/ModuleDefinitionRepository.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor b/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor index 5f9b1b7c..e2319d4c 100644 --- a/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor +++ b/Oqtane.Client/Themes/Controls/Theme/ControlPanelInteractive.razor @@ -296,7 +296,7 @@ _containerType = PageState.Site.DefaultContainerType; _allModuleDefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId); _moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(_category)).ToList(); - _categories = _allModuleDefinitions.SelectMany(m => m.Categories.Split(',', StringSplitOptions.RemoveEmptyEntries)).Distinct().Where(item => item != "Library").ToList(); + _categories = _allModuleDefinitions.SelectMany(m => m.Categories.Split(',', StringSplitOptions.RemoveEmptyEntries)).Distinct().Where(item => item != "Headless").ToList(); } } diff --git a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs index 124897e3..f20c3d13 100644 --- a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs +++ b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs @@ -406,7 +406,7 @@ namespace Oqtane.Repository moduledefinition = moduleobject.ModuleDefinition; moduledefinition.ModuleDefinitionName = moduletype.Namespace + ", " + moduletype.Assembly.GetName().Name; moduledefinition.AssemblyName = assembly.GetName().Name; - moduledefinition.Categories = "Library"; + moduledefinition.Categories = "Headless"; moduledefinition.PermissionList = new List { new Permission(PermissionNames.Utilize, RoleNames.Host, true) From af0a64965657cbb8bf17911772e84c7c9f4850ee Mon Sep 17 00:00:00 2001 From: sbwalker Date: Tue, 21 May 2024 11:06:42 -0400 Subject: [PATCH 74/77] fix #4279 - remove Theme Settings tab from Add Page UI --- Oqtane.Client/Modules/Admin/Pages/Add.razor | 33 --------------------- 1 file changed, 33 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Pages/Add.razor b/Oqtane.Client/Modules/Admin/Pages/Add.razor index 1c3bcadc..b4bc912e 100644 --- a/Oqtane.Client/Modules/Admin/Pages/Add.razor +++ b/Oqtane.Client/Modules/Admin/Pages/Add.razor @@ -198,12 +198,6 @@
- @if (_themeSettingsType != null) - { - - @_themeSettingsComponent - - }
@@ -238,9 +232,6 @@ private string _bodycontent; private string _permissions = null; private PermissionGrid _permissionGrid; - private Type _themeSettingsType; - private object _themeSettings; - private RenderFragment _themeSettingsComponent { get; set; } private bool _refresh = false; protected Page _parent = null; protected Dictionary _icons; @@ -281,7 +272,6 @@ } _effectivedate = Utilities.UtcAsLocalDate(PageState.Page.EffectiveDate); _expirydate = Utilities.UtcAsLocalDate(PageState.Page.ExpiryDate); - ThemeSettings(); _initialized = true; } else @@ -324,7 +314,6 @@ _themetype = (string)e.Value; _containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype); _containertype = _containers.First().TypeName; - ThemeSettings(); StateHasChanged(); // if theme chosen is different than default site theme, display warning message to user @@ -334,28 +323,6 @@ } } - private void ThemeSettings() - { - _themeSettingsType = null; - _themeSettingsComponent = null; - var theme = PageState.Site.Themes.FirstOrDefault(item => item.Themes.Any(themecontrol => themecontrol.TypeName.Equals(_themetype))); - if (theme != null && !string.IsNullOrEmpty(theme.ThemeSettingsType)) - { - _themeSettingsType = Type.GetType(theme.ThemeSettingsType); - if (_themeSettingsType != null) - { - _themeSettingsComponent = builder => - { - builder.OpenComponent(0, _themeSettingsType); - builder.AddAttribute(1, "RenderModeBoundary", RenderModeBoundary); - builder.AddComponentReferenceCapture(2, inst => { _themeSettings = Convert.ChangeType(inst, _themeSettingsType); }); - builder.CloseComponent(); - }; - } - _refresh = true; - } - } - private async Task SavePage() { validated = true; From e30037c4d11716a70e912119a7c6f078c9b2a549 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Thu, 23 May 2024 09:44:42 -0400 Subject: [PATCH 75/77] add ability to specify session duration for visitor tracking --- .../Modules/Admin/Visitors/Index.razor | 19 +++- .../Modules/Admin/Visitors/Index.resx | 8 +- Oqtane.Server/Components/App.razor | 97 +++++++++++-------- 3 files changed, 79 insertions(+), 45 deletions(-) diff --git a/Oqtane.Client/Modules/Admin/Visitors/Index.razor b/Oqtane.Client/Modules/Admin/Visitors/Index.razor index 39b14006..ea5510c0 100644 --- a/Oqtane.Client/Modules/Admin/Visitors/Index.razor +++ b/Oqtane.Client/Modules/Admin/Visitors/Index.razor @@ -69,14 +69,20 @@ else -
+
+ +
+ +
+
+
- +
@@ -103,7 +109,8 @@ else private int _page = 1; private List _visitors; private string _tracking; - private string _filter = ""; + private int _duration = 5; + private string _filter = ""; private int _retention = 30; private string _correlation = "true"; @@ -128,7 +135,8 @@ else _tracking = PageState.Site.VisitorTracking.ToString(); var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); - _filter = SettingService.GetSetting(settings, "VisitorFilter", Constants.DefaultVisitorFilter); + _duration = int.Parse(SettingService.GetSetting(settings, "VisitorDuration", "5")); + _filter = SettingService.GetSetting(settings, "VisitorFilter", Constants.DefaultVisitorFilter); _retention = int.Parse(SettingService.GetSetting(settings, "VisitorRetention", "30")); _correlation = SettingService.GetSetting(settings, "VisitorCorrelation", "true"); } @@ -179,7 +187,8 @@ else await SiteService.UpdateSiteAsync(site); var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); - settings = SettingService.SetSetting(settings, "VisitorFilter", _filter, true); + settings = SettingService.SetSetting(settings, "VisitorDuration", _duration.ToString(), true); + settings = SettingService.SetSetting(settings, "VisitorFilter", _filter, true); settings = SettingService.SetSetting(settings, "VisitorRetention", _retention.ToString(), true); settings = SettingService.SetSetting(settings, "VisitorCorrelation", _correlation, true); await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId); diff --git a/Oqtane.Client/Resources/Modules/Admin/Visitors/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Visitors/Index.resx index 28bc46d1..37599ccb 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Visitors/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Visitors/Index.resx @@ -184,7 +184,7 @@ Number of days of visitor activity to retain - Retention (Days): + Retention: Indicate if new visitors to this site should be correlated based on their IP Address @@ -192,4 +192,10 @@ Correlate Visitors? + + The duration of a browsing session considered to be a distinct visit (in minutes) + + + Session Duration: + \ No newline at end of file diff --git a/Oqtane.Server/Components/App.razor b/Oqtane.Server/Components/App.razor index 86b2eb40..2ace2726 100644 --- a/Oqtane.Server/Components/App.razor +++ b/Oqtane.Server/Components/App.razor @@ -324,14 +324,26 @@ int? userid = Context.User.UserId(); userid = (userid == -1) ? null : userid; - // check if cookie already exists + // get cookie value + var visitorCookieName = Constants.VisitorCookiePrefix + SiteId.ToString(); + var visitorCookieValue = Context.Request.Cookies[visitorCookieName]; + DateTime expiry = DateTime.MinValue; + if (visitorCookieValue.Contains("|")) + { + var values = visitorCookieValue.Split('|'); + int.TryParse(values[0], out _visitorId); + DateTime.TryParse(values[1], out expiry); + } + else // legacy cookie format + { + int.TryParse(visitorCookieValue, out _visitorId); + } + bool setcookie = false; Visitor visitor = null; - bool addcookie = false; - var VisitorCookie = Constants.VisitorCookiePrefix + SiteId.ToString(); - if (!int.TryParse(Context.Request.Cookies[VisitorCookie], out _visitorId)) + + if (_visitorId <= 0) { // if enabled use IP Address correlation - _visitorId = -1; var correlate = bool.Parse(settings.GetValue("VisitorCorrelation", "true")); if (correlate) { @@ -339,12 +351,12 @@ if (visitor != null) { _visitorId = visitor.VisitorId; - addcookie = true; + setcookie = true; } } } - if (_visitorId == -1) + if (_visitorId <= 0) { // create new visitor visitor = new Visitor(); @@ -360,52 +372,59 @@ visitor.VisitedOn = DateTime.UtcNow; visitor = VisitorRepository.AddVisitor(visitor); _visitorId = visitor.VisitorId; - addcookie = true; + setcookie = true; } else { - if (visitor == null) + // check expiry + if (DateTime.UtcNow > expiry) { - // get visitor if it was not previously loaded - visitor = VisitorRepository.GetVisitor(_visitorId); - } - if (visitor != null) - { - // update visitor - visitor.IPAddress = _remoteIPAddress; - visitor.UserAgent = useragent; - visitor.Language = language; - visitor.Url = url; - if (!string.IsNullOrEmpty(referrer)) + if (visitor == null) { - visitor.Referrer = referrer; + // get visitor if not previously loaded + visitor = VisitorRepository.GetVisitor(_visitorId); } - if (userid != null) + if (visitor != null) { - visitor.UserId = userid; + // update visitor + visitor.IPAddress = _remoteIPAddress; + visitor.UserAgent = useragent; + visitor.Language = language; + visitor.Url = url; + if (!string.IsNullOrEmpty(referrer)) + { + visitor.Referrer = referrer; + } + if (userid != null) + { + visitor.UserId = userid; + } + visitor.Visits += 1; + visitor.VisitedOn = DateTime.UtcNow; + VisitorRepository.UpdateVisitor(visitor); + setcookie = true; + } + else + { + // remove cookie if visitor does not exist + Context.Response.Cookies.Delete(visitorCookieName); } - visitor.Visits += 1; - visitor.VisitedOn = DateTime.UtcNow; - VisitorRepository.UpdateVisitor(visitor); - } - else - { - // remove cookie if VisitorId does not exist - Context.Response.Cookies.Delete(VisitorCookie); } } - // append cookie - if (addcookie) + // set cookie + if (setcookie) { + expiry = DateTime.UtcNow.AddMinutes(int.Parse(settings.GetValue("VisitorDuration", "5"))); + Context.Response.Cookies.Append( - VisitorCookie, - _visitorId.ToString(), + visitorCookieName, + $"{_visitorId}|{expiry}", new CookieOptions() - { - Expires = DateTimeOffset.UtcNow.AddYears(1), - IsEssential = true - } + { + Expires = DateTimeOffset.UtcNow.AddYears(10), + IsEssential = true + } ); } } From dfe530a76416caa6d19f03b4cb9d0f0ec958e227 Mon Sep 17 00:00:00 2001 From: sbwalker Date: Fri, 24 May 2024 22:51:34 -0400 Subject: [PATCH 76/77] fix issues when importing SiteTemplates --- Oqtane.Server/Components/App.razor | 2 +- Oqtane.Server/Repository/SiteRepository.cs | 54 ++++++++++++++-------- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/Oqtane.Server/Components/App.razor b/Oqtane.Server/Components/App.razor index 2ace2726..c32e1f97 100644 --- a/Oqtane.Server/Components/App.razor +++ b/Oqtane.Server/Components/App.razor @@ -328,7 +328,7 @@ var visitorCookieName = Constants.VisitorCookiePrefix + SiteId.ToString(); var visitorCookieValue = Context.Request.Cookies[visitorCookieName]; DateTime expiry = DateTime.MinValue; - if (visitorCookieValue.Contains("|")) + if (visitorCookieValue != null && visitorCookieValue.Contains("|")) { var values = visitorCookieValue.Split('|'); int.TryParse(values[0], out _visitorId); diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs index 59f5db3c..39dd43f2 100644 --- a/Oqtane.Server/Repository/SiteRepository.cs +++ b/Oqtane.Server/Repository/SiteRepository.cs @@ -165,22 +165,23 @@ namespace Oqtane.Repository if (!serverstate.IsInitialized) { var site = GetSite(alias.SiteId); - - // initialize theme Assemblies - site.Themes = _themeRepository.GetThemes().ToList(); - - // initialize module Assemblies - var moduleDefinitions = _moduleDefinitionRepository.GetModuleDefinitions(alias.SiteId); - - // execute migrations - var version = ProcessSiteMigrations(alias, site); - version = ProcessPageTemplates(alias, site, moduleDefinitions, version); - if (site.Version != version) + if (site != null) { - site.Version = version; - UpdateSite(site); - } + // initialize theme Assemblies + site.Themes = _themeRepository.GetThemes().ToList(); + // initialize module Assemblies + var moduleDefinitions = _moduleDefinitionRepository.GetModuleDefinitions(alias.SiteId); + + // execute migrations + var version = ProcessSiteMigrations(alias, site); + version = ProcessPageTemplates(alias, site, moduleDefinitions, version); + if (site.Version != version) + { + site.Version = version; + UpdateSite(site); + } + } serverstate.IsInitialized = true; } } @@ -411,7 +412,7 @@ namespace Oqtane.Repository } else { - parent = pages.FirstOrDefault(item => item.Path.ToLower() == pageTemplate.Parent.ToLower()); + parent = pages.FirstOrDefault(item => item.Path.ToLower() == ((pageTemplate.Parent == "/") ? "" : pageTemplate.Parent.ToLower())); } page.ParentId = (parent != null) ? parent.PageId : null; page.Path = page.Path.ToLower(); @@ -487,7 +488,21 @@ namespace Oqtane.Repository pageModule.Order = (pageTemplateModule.Order == 0) ? 1 : pageTemplateModule.Order; pageModule.ContainerType = pageTemplateModule.ContainerType; pageModule.IsDeleted = pageTemplateModule.IsDeleted; - pageModule.Module.PermissionList = pageTemplateModule.PermissionList; + pageModule.Module.PermissionList = new List(); + foreach (var permission in pageTemplateModule.PermissionList) + { + pageModule.Module.PermissionList.Add(new Permission + { + SiteId = permission.SiteId, + EntityName = permission.EntityName, + EntityId = permission.EntityId, + PermissionName = permission.PermissionName, + RoleName = permission.RoleName, + UserId = permission.UserId, + IsAuthorized = permission.IsAuthorized + }); + } + //pageModule.Module.PermissionList = pageTemplateModule.PermissionList; pageModule.Module.AllPages = false; pageModule.Module.IsDeleted = false; try @@ -539,8 +554,11 @@ namespace Oqtane.Repository try { var module = _moduleRepository.GetModule(pageModule.ModuleId); - var moduleobject = ActivatorUtilities.CreateInstance(_serviceProvider, moduletype); - ((IPortable)moduleobject).ImportModule(module, pageTemplateModule.Content, moduleDefinition.Version); + if (module != null) + { + var moduleobject = ActivatorUtilities.CreateInstance(_serviceProvider, moduletype); + ((IPortable)moduleobject).ImportModule(module, pageTemplateModule.Content, moduleDefinition.Version); + } } catch (Exception ex) { From 9a7a53405124c2ac000cc8b33e0f194ffc16e58d Mon Sep 17 00:00:00 2001 From: sbwalker Date: Tue, 28 May 2024 07:55:45 -0400 Subject: [PATCH 77/77] introduce Clone method in Permission model --- Oqtane.Server/Repository/SiteRepository.cs | 12 +----------- Oqtane.Shared/Models/Permission.cs | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs index 39dd43f2..3328461b 100644 --- a/Oqtane.Server/Repository/SiteRepository.cs +++ b/Oqtane.Server/Repository/SiteRepository.cs @@ -491,18 +491,8 @@ namespace Oqtane.Repository pageModule.Module.PermissionList = new List(); foreach (var permission in pageTemplateModule.PermissionList) { - pageModule.Module.PermissionList.Add(new Permission - { - SiteId = permission.SiteId, - EntityName = permission.EntityName, - EntityId = permission.EntityId, - PermissionName = permission.PermissionName, - RoleName = permission.RoleName, - UserId = permission.UserId, - IsAuthorized = permission.IsAuthorized - }); + pageModule.Module.PermissionList.Add(permission.Clone(permission)); } - //pageModule.Module.PermissionList = pageTemplateModule.PermissionList; pageModule.Module.AllPages = false; pageModule.Module.IsDeleted = false; try diff --git a/Oqtane.Shared/Models/Permission.cs b/Oqtane.Shared/Models/Permission.cs index 8d411252..1448e039 100644 --- a/Oqtane.Shared/Models/Permission.cs +++ b/Oqtane.Shared/Models/Permission.cs @@ -101,6 +101,20 @@ namespace Oqtane.Models IsAuthorized = isAuthorized; } + public Permission Clone(Permission permission) + { + return new Permission + { + SiteId = permission.SiteId, + EntityName = permission.EntityName, + EntityId = permission.EntityId, + PermissionName = permission.PermissionName, + RoleName = permission.RoleName, + UserId = permission.UserId, + IsAuthorized = permission.IsAuthorized + }; + } + [Obsolete("The Role property is deprecated", false)] [NotMapped] [JsonIgnore] // exclude from API payload