diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Index.razor b/Oqtane.Client/Modules/Admin/ModuleCreator/Index.razor index b1d72ce0..d5f98e72 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Index.razor +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Index.razor @@ -4,30 +4,52 @@ @inject IModuleDefinitionService ModuleDefinitionService @inject IModuleService ModuleService - - - - - - - - - -
- - - -
- - - -
+ + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
@code { - private string _name = string.Empty; + private string _owner = string.Empty; + private string _module = string.Empty; private string _description = string.Empty; + private string _template = string.Empty; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host; @@ -35,19 +57,19 @@ { AddModuleMessage("Please Note That Once You Select The Create Module Button The Application Must Restart In Order To Complete The Process.", MessageType.Info); } - + private async Task CreateModule() { try { - if (!string.IsNullOrEmpty(_name)) + if (!string.IsNullOrEmpty(_owner) && !string.IsNullOrEmpty(_module) && !string.IsNullOrEmpty(_template)) { - var moduleDefinition = new ModuleDefinition { Name = _name, Description = _description }; + var moduleDefinition = new ModuleDefinition { Owner = _owner.Replace(" ",""), Name = _module.Replace(" ", ""), Description = _description, Template = _template }; await ModuleDefinitionService.CreateModuleDefinitionAsync(moduleDefinition, ModuleState.ModuleId); } else { - AddModuleMessage("You Must Provide A Name For The Module", MessageType.Warning); + AddModuleMessage("You Must Provide An Owner, Module Name, And Template", MessageType.Warning); } } catch (Exception ex) diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/Edit.razor b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/Edit.razor similarity index 77% rename from Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/Edit.razor rename to Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/Edit.razor index f0fed00e..d23ab2e0 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/Edit.razor +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/Edit.razor @@ -1,10 +1,12 @@ -@namespace Oqtane.Modules.[Module]s -@using Oqtane.Services.[Module]s -@using Oqtane.Models.[Module]s @using Oqtane.Modules.Controls +@using [Owner].[Module]s.Services +@using [Owner].[Module]s.Models + +@namespace [Owner].[Module]s.Modules @inherits ModuleBase @inject NavigationManager NavigationManager -@inject I[Module]Service [Module]Service +@inject HttpClient http +@inject SiteState sitestate @@ -26,10 +28,10 @@ } @code { + public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit; + public override string Actions => "Add,Edit"; - public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Edit; } } - public override string Actions { get { return "Add,Edit"; } } - + I[Module]Service [Module]Service; int _id; string _name; string _createdby; @@ -39,9 +41,10 @@ protected override async Task OnInitializedAsync() { - if (PageState.Action == "Edit") + try { - try + [Module]Service = new [Module]Service(http, sitestate, NavigationManager); + if (PageState.Action == "Edit") { _id = Int32.Parse(PageState.QueryString["id"]); [Module] [Module] = await [Module]Service.Get[Module]Async(_id); @@ -54,11 +57,11 @@ _modifiedon = [Module].ModifiedOn; } } - catch (Exception ex) - { - await logger.LogError(ex, "Error Loading [Module] {[Module]Id} {Error}", _id, ex.Message); - AddModuleMessage("Error Loading [Module]", MessageType.Error); - } + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Loading [Module] {[Module]Id} {Error}", _id, ex.Message); + AddModuleMessage("Error Loading [Module]", MessageType.Error); } } diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/Index.razor b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/Index.razor new file mode 100644 index 00000000..b4d00775 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/Index.razor @@ -0,0 +1,101 @@ +@using [Owner].[Module]s.Services +@using [Owner].[Module]s.Models + +@namespace [Owner].[Module]s.Modules +@inherits ModuleBase +@inject NavigationManager NavigationManager +@inject HttpClient http +@inject SiteState sitestate + +@if (_[Module]s == null) +{ +

Loading...

+} +else +{ + +
+
+ @if (@_[Module]s.Count != 0) + { + +
+
[Module]s
+
+ +
+ + + @context.Name +
+
+
+ } + else + { +

No [Module]s To Display

+ } +} + +
+[Module] Module Created Successfully. Use Edit Mode To Add A [Module]. You Can Access The Files At The Following Locations:

+[RootPath]Client\
+- [Owner].[Module]s.Module.Client.csproj - client project
+- _Imports.razor - global imports for module components
+- Edit.razor - component for adding or editing content
+- Index.razor - main component for your module **the content you are reading is in this file**
+- ModuleInfo.cs - implements IModule interface to provide configuration settings for your module
+- Settings.razor - component for managing module settings
+- Services\I[Module]Service.cs - interface for defining service API methods
+- Services\[Module]Service.cs - implements service API interface methods

+[RootPath]Package\
+- [Owner].[Module]s.Module.nuspec - nuget manifest for packaging module
+- [Owner].[Module]s.Module.Package.csproj - packaging project
+- debug.cmd - copies assemblies to Oqtane bin folder when in Debug mode
+- release.cmd - creates nuget package and deploys to Oqtane wwwroot/modules folder when in Release mode

+[RootPath]Server\
+- [Owner].[Module]s.Module.Server.csproj - server project
+- Controllers\[Module]Controller.cs - API methods implemented using a REST pattern
+- Manager\[Module]Manager.cs - implements optional module interfaces for features such as import/export of content
+- Repository\I[Module]Repository.cs - interface for defining repository methods
+- Repository\[Module]Respository.cs - implements repository interface methods for data access using EF Core
+- Repository\[Module]Context.cs - provides a DB Context for data access
+- Scripts\01.00.00.sql - database schema definition

+[RootPath]Shared\
+- [Owner].[Module]s.Module.Shared.csproj - shared project
+- Models\[Module].cs - model definition

+ +@code { + I[Module]Service [Module]Service; + List<[Module]> _[Module]s; + + protected override async Task OnInitializedAsync() + { + try + { + [Module]Service = new [Module]Service(http, sitestate, NavigationManager); + _[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId); + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Loading [Module] {Error}", ex.Message); + AddModuleMessage("Error Loading [Module]", MessageType.Error); + } + } + + private async Task Delete([Module] [Module]) + { + try + { + await [Module]Service.Delete[Module]Async([Module].[Module]Id); + await logger.LogInformation("[Module] Deleted {[Module]}", [Module]); + _[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId); + StateHasChanged(); + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Deleting [Module] {[Module]} {Error}", [Module], ex.Message); + AddModuleMessage("Error Deleting [Module]", MessageType.Error); + } + } +} \ No newline at end of file diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/[Module]Info.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/ModuleInfo.cs similarity index 65% rename from Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/[Module]Info.cs rename to Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/ModuleInfo.cs index 5252730e..6f6bc85c 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/[Module]Info.cs +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/ModuleInfo.cs @@ -1,7 +1,7 @@ using Oqtane.Models; using Oqtane.Modules; -namespace Oqtane.Modules.[Module]s +namespace [Owner].[Module]s.Modules { public class ModuleInfo : IModule { @@ -10,7 +10,8 @@ namespace Oqtane.Modules.[Module]s Name = "[Module]", Description = "[Module]", Version = "1.0.0", - ServerAssemblyName = "Oqtane.Server" + Dependencies = "[Owner].[Module]s.Module.Shared", + ServerAssemblyName = "[ServerAssemblyName]" }; } } diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/Services/I[Module]Service.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/Services/I[Module]Service.cs similarity index 85% rename from Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/Services/I[Module]Service.cs rename to Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/Services/I[Module]Service.cs index f481dc02..e98da06d 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/Services/I[Module]Service.cs +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/Services/I[Module]Service.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Oqtane.Models.[Module]s; +using [Owner].[Module]s.Models; -namespace Oqtane.Services.[Module]s +namespace [Owner].[Module]s.Services { public interface I[Module]Service { diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/Services/[Module]Service.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/Services/[Module]Service.cs similarity index 96% rename from Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/Services/[Module]Service.cs rename to Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/Services/[Module]Service.cs index 7935c184..4ce98e00 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/Services/[Module]Service.cs +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/Services/[Module]Service.cs @@ -3,12 +3,12 @@ using System.Linq; using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.Components; -using Oqtane.Models.[Module]s; using Oqtane.Modules; using Oqtane.Services; using Oqtane.Shared; +using [Owner].[Module]s.Models; -namespace Oqtane.Services.[Module]s +namespace [Owner].[Module]s.Services { public class [Module]Service : ServiceBase, I[Module]Service, IService { diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/Settings.razor b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/Settings.razor similarity index 92% rename from Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/Settings.razor rename to Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/Settings.razor index b657eb6a..a53dc57c 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/Settings.razor +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/Settings.razor @@ -1,4 +1,4 @@ -@namespace Oqtane.Modules.[Module]s +@namespace [Owner].[Module]s.Modules @inherits ModuleBase @inject ISettingService SettingService @@ -14,7 +14,7 @@
@code { - public override string Title { get { return "[Module] Settings"; } } + public override string Title => "[Module] Settings"; string _value; diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/[Owner].[Module]s.Module.Client.csproj b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/[Owner].[Module]s.Module.Client.csproj new file mode 100644 index 00000000..c3b58f44 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/[Owner].[Module]s.Module.Client.csproj @@ -0,0 +1,39 @@ + + + + netstandard2.1 + 3.0 + 1.0.0 + [Owner] + [Owner] + [Description] + [Owner].[Module]s.Module + [Owner] + + + + + + + + + + + + + + + ..\..\oqtane.framework\Oqtane.Client\bin\Debug\netstandard2.1\Oqtane.Client.dll + + + ..\..\oqtane.framework\Oqtane.Client\bin\Debug\netstandard2.1\Oqtane.Shared.dll + + + + + + false + false + + + diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/_Imports.razor b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/_Imports.razor new file mode 100644 index 00000000..147a5eee --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Client/_Imports.razor @@ -0,0 +1,18 @@ +@using System +@using System.Linq +@using System.Collections.Generic +@using System.Net.Http + +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using Microsoft.JSInterop + +@using Oqtane.Models +@using Oqtane.Modules +@using Oqtane.Modules.Controls +@using Oqtane.Providers +@using Oqtane.Security +@using Oqtane.Services +@using Oqtane.Shared +@using Oqtane.Themes +@using Oqtane.Themes.Controls \ No newline at end of file diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Package/[Owner].[Module]s.Module.Package.csproj b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Package/[Owner].[Module]s.Module.Package.csproj new file mode 100644 index 00000000..0689d66f --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Package/[Owner].[Module]s.Module.Package.csproj @@ -0,0 +1,19 @@ + + + + netcoreapp3.1 + false + + + + + + + + + + + + + + diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Package/[Owner].[Module]s.Module.nuspec b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Package/[Owner].[Module]s.Module.nuspec new file mode 100644 index 00000000..8598cfee --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Package/[Owner].[Module]s.Module.nuspec @@ -0,0 +1,28 @@ + + + + [Owner].[Module]s.Module + 1.0.0 + [Owner] + [Owner] + [Module]s + [Module]s + [Owner] + false + MIT + https://github.com/oqtane/oqtane.framework + https://www.oqtane.org/Portals/0/icon.jpg + oqtane module + + + + + + + + + + + + + \ No newline at end of file diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Package/debug.cmd b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Package/debug.cmd new file mode 100644 index 00000000..8b72b03b --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Package/debug.cmd @@ -0,0 +1,6 @@ +XCOPY "..\Client\bin\Debug\netstandard2.1\[Owner].[Module]s.Module.Client.dll" "..\..\oqtane.framework\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y +XCOPY "..\Client\bin\Debug\netstandard2.1\[Owner].[Module]s.Module.Client.pdb" "..\..\oqtane.framework\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y +XCOPY "..\Server\bin\Debug\netcoreapp3.1\[Owner].[Module]s.Module.Server.dll" "..\..\oqtane.framework\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y +XCOPY "..\Server\bin\Debug\netcoreapp3.1\[Owner].[Module]s.Module.Server.pdb" "..\..\oqtane.framework\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y +XCOPY "..\Shared\bin\Debug\netstandard2.1\[Owner].[Module]s.Module.Shared.dll" "..\..\oqtane.framework\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y +XCOPY "..\Shared\bin\Debug\netstandard2.1\[Owner].[Module]s.Module.Shared.pdb" "..\..\oqtane.framework\Oqtane.Server\bin\Debug\netcoreapp3.1\" /Y diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Package/release.cmd b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Package/release.cmd new file mode 100644 index 00000000..16c8ad03 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Package/release.cmd @@ -0,0 +1,2 @@ +"..\..\oqtane.framework\oqtane.package\nuget.exe" pack [Owner].[Module]s.Module.nuspec +XCOPY "*.nupkg" "..\..\oqtane.framework\Oqtane.Server\wwwroot\Modules\" /Y diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Controllers/[Module]Controller.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Controllers/[Module]Controller.cs similarity index 95% rename from Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Controllers/[Module]Controller.cs rename to Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Controllers/[Module]Controller.cs index 9fcb319e..1ff6a0ab 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Controllers/[Module]Controller.cs +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Controllers/[Module]Controller.cs @@ -1,13 +1,13 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; -using Oqtane.Models.[Module]s; -using Oqtane.Repository.[Module]s; -using Oqtane.Shared; using System.Collections.Generic; +using Oqtane.Shared; using Oqtane.Enums; using Oqtane.Infrastructure; +using [Owner].[Module]s.Models; +using [Owner].[Module]s.Repository; -namespace Oqtane.Controllers.[Module]s +namespace [Owner].[Module]s.Controllers { [Route("{site}/api/[controller]")] public class [Module]Controller : Controller diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Manager/[Module]Manager.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Manager/[Module]Manager.cs similarity index 81% rename from Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Manager/[Module]Manager.cs rename to Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Manager/[Module]Manager.cs index 8380c97d..9414847d 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Manager/[Module]Manager.cs +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Manager/[Module]Manager.cs @@ -1,10 +1,12 @@ -using Oqtane.Models.[Module]s; -using Oqtane.Repository.[Module]s; using System.Collections.Generic; using System.Linq; using System.Text.Json; +using Oqtane.Modules; +using Oqtane.Models; +using [Owner].[Module]s.Models; +using [Owner].[Module]s.Repository; -namespace Oqtane.Modules.[Module]s +namespace [Owner].[Module]s.Modules { public class [Module]Manager : IPortable { @@ -15,7 +17,7 @@ namespace Oqtane.Modules.[Module]s _[Module]s = [Module]s; } - public string ExportModule(Models.Module module) + public string ExportModule(Module module) { string content = ""; List<[Module]> [Module]s = _[Module]s.Get[Module]s(module.ModuleId).ToList(); @@ -26,7 +28,7 @@ namespace Oqtane.Modules.[Module]s return content; } - public void ImportModule(Models.Module module, string content, string version) + public void ImportModule(Module module, string content, string version) { List<[Module]> [Module]s = null; if (!string.IsNullOrEmpty(content)) diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Repository/I[Module]Repository.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Repository/I[Module]Repository.cs similarity index 82% rename from Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Repository/I[Module]Repository.cs rename to Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Repository/I[Module]Repository.cs index 7a607ad2..f38a60d5 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Repository/I[Module]Repository.cs +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Repository/I[Module]Repository.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; -using Oqtane.Models.[Module]s; +using [Owner].[Module]s.Models; -namespace Oqtane.Repository.[Module]s +namespace [Owner].[Module]s.Repository { public interface I[Module]Repository { diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Repository/[Module]Context.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Repository/[Module]Context.cs similarity index 82% rename from Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Repository/[Module]Context.cs rename to Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Repository/[Module]Context.cs index 9a438a88..2a14bbf4 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Repository/[Module]Context.cs +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Repository/[Module]Context.cs @@ -1,9 +1,10 @@ using Microsoft.EntityFrameworkCore; using Microsoft.AspNetCore.Http; -using Oqtane.Models.[Module]s; using Oqtane.Modules; +using Oqtane.Repository; +using [Owner].[Module]s.Models; -namespace Oqtane.Repository.[Module]s +namespace [Owner].[Module]s.Repository { public class [Module]Context : DBContextBase, IService { diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Repository/[Module]Repository.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Repository/[Module]Repository.cs similarity index 94% rename from Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Repository/[Module]Repository.cs rename to Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Repository/[Module]Repository.cs index c6383fce..9b83b239 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Repository/[Module]Repository.cs +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Repository/[Module]Repository.cs @@ -1,10 +1,10 @@ using Microsoft.EntityFrameworkCore; using System.Linq; using System.Collections.Generic; -using Oqtane.Models.[Module]s; using Oqtane.Modules; +using [Owner].[Module]s.Models; -namespace Oqtane.Repository.[Module]s +namespace [Owner].[Module]s.Repository { public class [Module]Repository : I[Module]Repository, IService { diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Scripts/01.00.00.sql b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Scripts/01.00.00.sql new file mode 100644 index 00000000..0e7266e6 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/Scripts/01.00.00.sql @@ -0,0 +1,26 @@ +/* +Create [Module] table +*/ + +CREATE TABLE [dbo].[[Owner][Module]]( + [[Module]Id] [int] IDENTITY(1,1) NOT NULL, + [ModuleId] [int] NOT NULL, + [Name] [nvarchar](256) NOT NULL, + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, + CONSTRAINT [PK_[Owner][Module]] PRIMARY KEY CLUSTERED + ( + [[Module]Id] ASC + ) +) +GO + +/* +Create foreign key relationships +*/ +ALTER TABLE [dbo].[[Owner][Module]] WITH CHECK ADD CONSTRAINT [FK_[Owner][Module]_Module] FOREIGN KEY([ModuleId]) +REFERENCES [dbo].Module ([ModuleId]) +ON DELETE CASCADE +GO \ No newline at end of file diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/[Owner].[Module]s.Module.Server.csproj b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/[Owner].[Module]s.Module.Server.csproj new file mode 100644 index 00000000..d92e4f75 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Server/[Owner].[Module]s.Module.Server.csproj @@ -0,0 +1,51 @@ + + + + netcoreapp3.1 + 7.3 + true + 1.0.0 + [Owner].[Module]s.Module + [Owner] + [Owner] + [Description] + [Owner] + + + + + + Library + + + + + + + + + + + + + + + + + + + + + + + + + + ..\..\oqtane.framework\Oqtane.Server\bin\Debug\netcoreapp3.1\Oqtane.Server.dll + + + ..\..\oqtane.framework\Oqtane.Server\bin\Debug\netcoreapp3.1\Oqtane.Shared.dll + + + + diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Shared/Modules/Models/[Module]/[Module].cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Shared/Models/[Module].cs similarity index 73% rename from Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Shared/Modules/Models/[Module]/[Module].cs rename to Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Shared/Models/[Module].cs index 6ebba399..5a6d7896 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Shared/Modules/Models/[Module]/[Module].cs +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Shared/Models/[Module].cs @@ -1,11 +1,12 @@ using System; -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using Oqtane.Models; -namespace Oqtane.Models.[Module]s +namespace [Owner].[Module]s.Models { + [Table("[Owner][Module]")] public class [Module] : IAuditable { - [Key] public int [Module]Id { get; set; } public int ModuleId { get; set; } public string Name { get; set; } diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Shared/[Owner].[Module]s.Module.Shared.csproj b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Shared/[Owner].[Module]s.Module.Shared.csproj new file mode 100644 index 00000000..b16ad2bd --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/Shared/[Owner].[Module]s.Module.Shared.csproj @@ -0,0 +1,28 @@ + + + + netstandard2.1 + 7.3 + 1.0.0 + [Owner].[Module].Module + [Owner] + [Owner] + [Description] + [Owner] + + + + + + + + + + + + + ..\..\oqtane.framework\Oqtane.Shared\bin\Debug\netstandard2.1\Oqtane.Shared.dll + + + + diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/[Owner].[Module]s.Module.sln b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/[Owner].[Module]s.Module.sln new file mode 100644 index 00000000..9879eac6 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/[Owner].[Module]s.Module.sln @@ -0,0 +1,52 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28621.142 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module]s.Module.Client", "Client\[Owner].[Module]s.Module.Client.csproj", "{AA8E58A1-CD09-4208-BF66-A8BB341FD669}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module]s.Module.Server", "Server\[Owner].[Module]s.Module.Server.csproj", "{04B05448-788F-433D-92C0-FED35122D45A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Module]s.Module.Shared", "Shared\[Owner].[Module]s.Module.Shared.csproj", "{18D73F73-D7BE-4388-85BA-FBD9AC96FCA2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "[Owner].[Module]s.Module.Package", "Package\[Owner].[Module]s.Module.Package.csproj", "{C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + Wasm|Any CPU = Wasm|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Release|Any CPU.Build.0 = Release|Any CPU + {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Wasm|Any CPU.ActiveCfg = Release|Any CPU + {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Wasm|Any CPU.Build.0 = Release|Any CPU + {04B05448-788F-433D-92C0-FED35122D45A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {04B05448-788F-433D-92C0-FED35122D45A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {04B05448-788F-433D-92C0-FED35122D45A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {04B05448-788F-433D-92C0-FED35122D45A}.Release|Any CPU.Build.0 = Release|Any CPU + {04B05448-788F-433D-92C0-FED35122D45A}.Wasm|Any CPU.ActiveCfg = Release|Any CPU + {04B05448-788F-433D-92C0-FED35122D45A}.Wasm|Any CPU.Build.0 = Release|Any CPU + {18D73F73-D7BE-4388-85BA-FBD9AC96FCA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {18D73F73-D7BE-4388-85BA-FBD9AC96FCA2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {18D73F73-D7BE-4388-85BA-FBD9AC96FCA2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {18D73F73-D7BE-4388-85BA-FBD9AC96FCA2}.Release|Any CPU.Build.0 = Release|Any CPU + {18D73F73-D7BE-4388-85BA-FBD9AC96FCA2}.Wasm|Any CPU.ActiveCfg = Release|Any CPU + {18D73F73-D7BE-4388-85BA-FBD9AC96FCA2}.Wasm|Any CPU.Build.0 = Release|Any CPU + {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Release|Any CPU.Build.0 = Release|Any CPU + {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Wasm|Any CPU.ActiveCfg = Debug|Any CPU + {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Wasm|Any CPU.Build.0 = Debug|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1D016F15-46FE-4726-8DFD-2E4FD4DC7668} + EndGlobalSection +EndGlobal diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/wwwroot/resources.txt b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/wwwroot/resources.txt new file mode 100644 index 00000000..2542de03 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/External/wwwroot/resources.txt @@ -0,0 +1 @@ +This is the location where static resources such as images or style sheets should be located \ No newline at end of file diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/Edit.razor b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/Edit.razor new file mode 100644 index 00000000..d23ab2e0 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/Edit.razor @@ -0,0 +1,95 @@ +@using Oqtane.Modules.Controls +@using [Owner].[Module]s.Services +@using [Owner].[Module]s.Models + +@namespace [Owner].[Module]s.Modules +@inherits ModuleBase +@inject NavigationManager NavigationManager +@inject HttpClient http +@inject SiteState sitestate + + + + + + +
+ + + +
+ +Cancel +
+
+@if (PageState.Action == "Edit") +{ + +} + +@code { + public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit; + public override string Actions => "Add,Edit"; + + I[Module]Service [Module]Service; + int _id; + string _name; + string _createdby; + DateTime _createdon; + string _modifiedby; + DateTime _modifiedon; + + protected override async Task OnInitializedAsync() + { + try + { + [Module]Service = new [Module]Service(http, sitestate, NavigationManager); + if (PageState.Action == "Edit") + { + _id = Int32.Parse(PageState.QueryString["id"]); + [Module] [Module] = await [Module]Service.Get[Module]Async(_id); + if ([Module] != null) + { + _name = [Module].Name; + _createdby = [Module].CreatedBy; + _createdon = [Module].CreatedOn; + _modifiedby = [Module].ModifiedBy; + _modifiedon = [Module].ModifiedOn; + } + } + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Loading [Module] {[Module]Id} {Error}", _id, ex.Message); + AddModuleMessage("Error Loading [Module]", MessageType.Error); + } + } + + private async Task Save() + { + try + { + if (PageState.Action == "Add") + { + [Module] [Module] = new [Module](); + [Module].ModuleId = ModuleState.ModuleId; + [Module].Name = _name; + [Module] = await [Module]Service.Add[Module]Async([Module]); + await logger.LogInformation("[Module] Added {[Module]}", [Module]); + } + else + { + [Module] [Module] = await [Module]Service.Get[Module]Async(_id); + [Module].Name = _name; + await [Module]Service.Update[Module]Async([Module]); + await logger.LogInformation("[Module] Updated {[Module]}", [Module]); + } + NavigationManager.NavigateTo(NavigateUrl()); + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Saving [Module] {Error}", ex.Message); + AddModuleMessage("Error Saving [Module]", MessageType.Error); + } + } +} diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/Index.razor b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/Index.razor similarity index 52% rename from Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/Index.razor rename to Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/Index.razor index a0f03fe2..b6080579 100644 --- a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Client/Modules/[Module]/Index.razor +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/Index.razor @@ -1,9 +1,11 @@ -@namespace Oqtane.Modules.[Module]s -@using Oqtane.Services.[Module]s -@using Oqtane.Models.[Module]s +@using [Owner].[Module]s.Services +@using [Owner].[Module]s.Models + +@namespace [Owner].[Module]s.Modules @inherits ModuleBase @inject NavigationManager NavigationManager -@inject I[Module]Service [Module]Service +@inject HttpClient http +@inject SiteState sitestate @if (_[Module]s == null) { @@ -12,44 +14,57 @@ else { -

- - -
- - - @context.Name -
-
-
+
+
+ @if (@_[Module]s.Count != 0) + { + +
+
[Module]s
+
+ +
+ + + @context.Name +
+
+
+ } + else + { +

No [Module]s To Display

+ } }
-[Module] Module Created Successfully. You Can Access The Files At The Following Locations:

-C:\Users\Shaun.Walker\Source\Repos\sbwalker\oqtane.framework\Oqtane.Client\Modules\[Module]\
-- Index.razor - main component for your module
+[Module] Module Created Successfully. Use Edit Mode To Add A [Module]. You Can Access The Files At The Following Locations:

+[RootPath]Oqtane.Client\Modules\[Module]\
- Edit.razor - component for adding or editing content
+- Index.razor - main component for your module **the content you are reading is in this file**
+- ModuleInfo.cs - implements IModule interface to provide configuration settings for your module
- Settings.razor - component for managing module settings
-- Module.cs - implements IModule interface to provide configuration settings for your module
- Services\I[Module]Service.cs - interface for defining service API methods
- Services\[Module]Service.cs - implements service API interface methods

-C:\Users\Shaun.Walker\Source\Repos\sbwalker\oqtane.framework\Oqtane.Server\Modules\[Module]\
+[RootPath]Oqtane.Server\Modules\[Module]\
- Controllers\[Module]Controller.cs - API methods implemented using a REST pattern
- Manager\[Module]Manager.cs - implements optional module interfaces for features such as import/export of content
- Repository\I[Module]Repository.cs - interface for defining repository methods
- Repository\[Module]Respository.cs - implements repository interface methods for data access using EF Core
- Repository\[Module]Context.cs - provides a DB Context for data access
- Scripts\01.00.00.sql - database schema definition

-C:\Users\Shaun.Walker\Source\Repos\sbwalker\oqtane.framework\Oqtane.Shared\Modules\Models\[Module]\
-- [Module].cs - model definition

+[RootPath]Oqtane.Shared\Modules\[Module]\
+- Models\[Module].cs - model definition

@code { + I[Module]Service [Module]Service; List<[Module]> _[Module]s; - protected override async Task OnParametersSetAsync() + protected override async Task OnInitializedAsync() { try { + [Module]Service = new [Module]Service(http, sitestate, NavigationManager); _[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId); } catch (Exception ex) @@ -65,7 +80,8 @@ C:\Users\Shaun.Walker\Source\Repos\sbwalker\oqtane.framework\Oqtane.Shared\Modul { await [Module]Service.Delete[Module]Async([Module].[Module]Id); await logger.LogInformation("[Module] Deleted {[Module]}", [Module]); - NavigationManager.NavigateTo(NavigateUrl()); + _[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId); + StateHasChanged(); } catch (Exception ex) { diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/ModuleInfo.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/ModuleInfo.cs new file mode 100644 index 00000000..6f6bc85c --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/ModuleInfo.cs @@ -0,0 +1,17 @@ +using Oqtane.Models; +using Oqtane.Modules; + +namespace [Owner].[Module]s.Modules +{ + public class ModuleInfo : IModule + { + public ModuleDefinition ModuleDefinition => new ModuleDefinition + { + Name = "[Module]", + Description = "[Module]", + Version = "1.0.0", + Dependencies = "[Owner].[Module]s.Module.Shared", + ServerAssemblyName = "[ServerAssemblyName]" + }; + } +} diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/Services/I[Module]Service.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/Services/I[Module]Service.cs new file mode 100644 index 00000000..e98da06d --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/Services/I[Module]Service.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using [Owner].[Module]s.Models; + +namespace [Owner].[Module]s.Services +{ + public interface I[Module]Service + { + Task> Get[Module]sAsync(int ModuleId); + + Task<[Module]> Get[Module]Async(int [Module]Id); + + Task<[Module]> Add[Module]Async([Module] [Module]); + + Task<[Module]> Update[Module]Async([Module] [Module]); + + Task Delete[Module]Async(int [Module]Id); + } +} diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/Services/[Module]Service.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/Services/[Module]Service.cs new file mode 100644 index 00000000..4ce98e00 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/Services/[Module]Service.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using Oqtane.Modules; +using Oqtane.Services; +using Oqtane.Shared; +using [Owner].[Module]s.Models; + +namespace [Owner].[Module]s.Services +{ + public class [Module]Service : ServiceBase, I[Module]Service, IService + { + private readonly HttpClient _http; + private readonly NavigationManager _navigationManager; + private readonly SiteState _siteState; + + public [Module]Service(HttpClient http, SiteState siteState, NavigationManager navigationManager) + { + _http = http; + _siteState = siteState; + _navigationManager = navigationManager; + } + + private string Apiurl + { + get { return CreateApiUrl(_siteState.Alias, _navigationManager.Uri, "[Module]"); } + } + + public async Task> Get[Module]sAsync(int ModuleId) + { + List<[Module]> [Module]s = await _http.GetJsonAsync>(Apiurl + "?moduleid=" + ModuleId.ToString()); + return [Module]s.OrderBy(item => item.Name).ToList(); + } + + public async Task<[Module]> Get[Module]Async(int [Module]Id) + { + return await _http.GetJsonAsync<[Module]>(Apiurl + "/" + [Module]Id.ToString()); + } + + public async Task<[Module]> Add[Module]Async([Module] [Module]) + { + return await _http.PostJsonAsync<[Module]>(Apiurl + "?entityid=" + [Module].ModuleId, [Module]); + } + + public async Task<[Module]> Update[Module]Async([Module] [Module]) + { + return await _http.PutJsonAsync<[Module]>(Apiurl + "/" + [Module].[Module]Id + "?entityid=" + [Module].ModuleId, [Module]); + } + + public async Task Delete[Module]Async(int [Module]Id) + { + await _http.DeleteAsync(Apiurl + "/" + [Module]Id.ToString()); + } + } +} diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/Settings.razor b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/Settings.razor new file mode 100644 index 00000000..a53dc57c --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Client/Modules/[Module]/Settings.razor @@ -0,0 +1,47 @@ +@namespace [Owner].[Module]s.Modules +@inherits ModuleBase +@inject ISettingService SettingService + + + + + + +
+ + + +
+ +@code { + public override string Title => "[Module] Settings"; + + string _value; + + protected override async Task OnInitializedAsync() + { + try + { + Dictionary settings = await SettingService.GetModuleSettingsAsync(ModuleState.ModuleId); + _value = SettingService.GetSetting(settings, "SettingName", ""); + } + catch (Exception ex) + { + ModuleInstance.AddModuleMessage(ex.Message, MessageType.Error); + } + } + + public async Task UpdateSettings() + { + try + { + Dictionary settings = await SettingService.GetModuleSettingsAsync(ModuleState.ModuleId); + SettingService.SetSetting(settings, "SettingName", _value); + await SettingService.UpdateModuleSettingsAsync(settings, ModuleState.ModuleId); + } + catch (Exception ex) + { + ModuleInstance.AddModuleMessage(ex.Message, MessageType.Error); + } + } +} diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Controllers/[Module]Controller.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Controllers/[Module]Controller.cs new file mode 100644 index 00000000..1ff6a0ab --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Controllers/[Module]Controller.cs @@ -0,0 +1,75 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Authorization; +using System.Collections.Generic; +using Oqtane.Shared; +using Oqtane.Enums; +using Oqtane.Infrastructure; +using [Owner].[Module]s.Models; +using [Owner].[Module]s.Repository; + +namespace [Owner].[Module]s.Controllers +{ + [Route("{site}/api/[controller]")] + public class [Module]Controller : Controller + { + private readonly I[Module]Repository _[Module]s; + private readonly ILogManager _logger; + + public [Module]Controller(I[Module]Repository [Module]s, ILogManager logger) + { + _[Module]s = [Module]s; + _logger = logger; + } + + // GET: api/?moduleid=x + [HttpGet] + [Authorize(Roles = Constants.RegisteredRole)] + public IEnumerable<[Module]> Get(string moduleid) + { + return _[Module]s.Get[Module]s(int.Parse(moduleid)); + } + + // GET api//5 + [HttpGet("{id}")] + [Authorize(Roles = Constants.RegisteredRole)] + public [Module] Get(int id) + { + return _[Module]s.Get[Module](id); + } + + // POST api/ + [HttpPost] + [Authorize(Roles = Constants.AdminRole)] + public [Module] Post([FromBody] [Module] [Module]) + { + if (ModelState.IsValid) + { + [Module] = _[Module]s.Add[Module]([Module]); + _logger.Log(LogLevel.Information, this, LogFunction.Create, "[Module] Added {[Module]}", [Module]); + } + return [Module]; + } + + // PUT api//5 + [HttpPut("{id}")] + [Authorize(Roles = Constants.AdminRole)] + public [Module] Put(int id, [FromBody] [Module] [Module]) + { + if (ModelState.IsValid) + { + [Module] = _[Module]s.Update[Module]([Module]); + _logger.Log(LogLevel.Information, this, LogFunction.Update, "[Module] Updated {[Module]}", [Module]); + } + return [Module]; + } + + // DELETE api//5 + [HttpDelete("{id}")] + [Authorize(Roles = Constants.AdminRole)] + public void Delete(int id) + { + _[Module]s.Delete[Module](id); + _logger.Log(LogLevel.Information, this, LogFunction.Delete, "[Module] Deleted {[Module]Id}", id); + } + } +} diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Manager/[Module]Manager.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Manager/[Module]Manager.cs new file mode 100644 index 00000000..9414847d --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Manager/[Module]Manager.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using Oqtane.Modules; +using Oqtane.Models; +using [Owner].[Module]s.Models; +using [Owner].[Module]s.Repository; + +namespace [Owner].[Module]s.Modules +{ + public class [Module]Manager : IPortable + { + private I[Module]Repository _[Module]s; + + public [Module]Manager(I[Module]Repository [Module]s) + { + _[Module]s = [Module]s; + } + + public string ExportModule(Module module) + { + string content = ""; + List<[Module]> [Module]s = _[Module]s.Get[Module]s(module.ModuleId).ToList(); + if ([Module]s != null) + { + content = JsonSerializer.Serialize([Module]s); + } + return content; + } + + public void ImportModule(Module module, string content, string version) + { + List<[Module]> [Module]s = null; + if (!string.IsNullOrEmpty(content)) + { + [Module]s = JsonSerializer.Deserialize>(content); + } + if ([Module]s != null) + { + foreach([Module] [Module] in [Module]s) + { + [Module] _[Module] = new [Module](); + _[Module].ModuleId = module.ModuleId; + _[Module].Name = [Module].Name; + _[Module]s.Add[Module](_[Module]); + } + } + } + } +} \ No newline at end of file diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Repository/I[Module]Repository.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Repository/I[Module]Repository.cs new file mode 100644 index 00000000..f38a60d5 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Repository/I[Module]Repository.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using [Owner].[Module]s.Models; + +namespace [Owner].[Module]s.Repository +{ + public interface I[Module]Repository + { + IEnumerable<[Module]> Get[Module]s(int ModuleId); + [Module] Get[Module](int [Module]Id); + [Module] Add[Module]([Module] [Module]); + [Module] Update[Module]([Module] [Module]); + void Delete[Module](int [Module]Id); + } +} diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Repository/[Module]Context.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Repository/[Module]Context.cs new file mode 100644 index 00000000..2a14bbf4 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Repository/[Module]Context.cs @@ -0,0 +1,18 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.AspNetCore.Http; +using Oqtane.Modules; +using Oqtane.Repository; +using [Owner].[Module]s.Models; + +namespace [Owner].[Module]s.Repository +{ + public class [Module]Context : DBContextBase, IService + { + public virtual DbSet<[Module]> [Module] { get; set; } + + public [Module]Context(ITenantResolver tenantResolver, IHttpContextAccessor accessor) : base(tenantResolver, accessor) + { + // ContextBase handles multi-tenant database connections + } + } +} diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Repository/[Module]Repository.cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Repository/[Module]Repository.cs new file mode 100644 index 00000000..9b83b239 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Repository/[Module]Repository.cs @@ -0,0 +1,49 @@ +using Microsoft.EntityFrameworkCore; +using System.Linq; +using System.Collections.Generic; +using Oqtane.Modules; +using [Owner].[Module]s.Models; + +namespace [Owner].[Module]s.Repository +{ + public class [Module]Repository : I[Module]Repository, IService + { + private readonly [Module]Context _db; + + public [Module]Repository([Module]Context context) + { + _db = context; + } + + public IEnumerable<[Module]> Get[Module]s(int ModuleId) + { + return _db.[Module].Where(item => item.ModuleId == ModuleId); + } + + public [Module] Get[Module](int [Module]Id) + { + return _db.[Module].Find([Module]Id); + } + + public [Module] Add[Module]([Module] [Module]) + { + _db.[Module].Add([Module]); + _db.SaveChanges(); + return [Module]; + } + + public [Module] Update[Module]([Module] [Module]) + { + _db.Entry([Module]).State = EntityState.Modified; + _db.SaveChanges(); + return [Module]; + } + + public void Delete[Module](int [Module]Id) + { + [Module] [Module] = _db.[Module].Find([Module]Id); + _db.[Module].Remove([Module]); + _db.SaveChanges(); + } + } +} diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Scripts/01.00.00.sql b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Scripts/01.00.00.sql new file mode 100644 index 00000000..0e7266e6 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Scripts/01.00.00.sql @@ -0,0 +1,26 @@ +/* +Create [Module] table +*/ + +CREATE TABLE [dbo].[[Owner][Module]]( + [[Module]Id] [int] IDENTITY(1,1) NOT NULL, + [ModuleId] [int] NOT NULL, + [Name] [nvarchar](256) NOT NULL, + [CreatedBy] [nvarchar](256) NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [ModifiedBy] [nvarchar](256) NOT NULL, + [ModifiedOn] [datetime] NOT NULL, + CONSTRAINT [PK_[Owner][Module]] PRIMARY KEY CLUSTERED + ( + [[Module]Id] ASC + ) +) +GO + +/* +Create foreign key relationships +*/ +ALTER TABLE [dbo].[[Owner][Module]] WITH CHECK ADD CONSTRAINT [FK_[Owner][Module]_Module] FOREIGN KEY([ModuleId]) +REFERENCES [dbo].Module ([ModuleId]) +ON DELETE CASCADE +GO \ No newline at end of file diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Scripts/Tenant.01.00.00.sql b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Scripts/Tenant.01.00.00.sql similarity index 100% rename from Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Oqtane.Server/Modules/[Module]/Scripts/Tenant.01.00.00.sql rename to Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Server/Modules/[Module]/Scripts/Tenant.01.00.00.sql diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Shared/Modules/[Module]/Models/[Module].cs b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Shared/Modules/[Module]/Models/[Module].cs new file mode 100644 index 00000000..5a6d7896 --- /dev/null +++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Templates/Internal/Oqtane.Shared/Modules/[Module]/Models/[Module].cs @@ -0,0 +1,19 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using Oqtane.Models; + +namespace [Owner].[Module]s.Models +{ + [Table("[Owner][Module]")] + public class [Module] : IAuditable + { + public int [Module]Id { get; set; } + public int ModuleId { get; set; } + public string Name { get; set; } + + public string CreatedBy { get; set; } + public DateTime CreatedOn { get; set; } + public string ModifiedBy { get; set; } + public DateTime ModifiedOn { get; set; } + } +} diff --git a/Oqtane.Client/Modules/Admin/Modules/Settings.razor b/Oqtane.Client/Modules/Admin/Modules/Settings.razor index a98d015e..aeb4406e 100644 --- a/Oqtane.Client/Modules/Admin/Modules/Settings.razor +++ b/Oqtane.Client/Modules/Admin/Modules/Settings.razor @@ -121,6 +121,10 @@ { var moduleobject = Activator.CreateInstance(_settingsModuleType); _settingstitle = (string)_settingsModuleType.GetProperty("Title").GetValue(moduleobject, null); + if (string.IsNullOrEmpty(_settingstitle)) + { + _settingstitle = "Other Settings"; + } DynamicComponent = builder => { @@ -141,7 +145,7 @@ pagemodule.PageId = int.Parse(_pageId); pagemodule.Title = _title; pagemodule.ContainerType = _containerType; - + await PageModuleService.UpdatePageModuleAsync(pagemodule); await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane); diff --git a/Oqtane.Framework.nuspec b/Oqtane.Package/Oqtane.Framework.nuspec similarity index 69% rename from Oqtane.Framework.nuspec rename to Oqtane.Package/Oqtane.Framework.nuspec index 3b82d16e..20827508 100644 --- a/Oqtane.Framework.nuspec +++ b/Oqtane.Package/Oqtane.Framework.nuspec @@ -17,9 +17,9 @@ A modular application framework for Blazor - - - - + + + + \ No newline at end of file diff --git a/Oqtane.Package/nuget.exe b/Oqtane.Package/nuget.exe new file mode 100644 index 00000000..3ae0060a Binary files /dev/null and b/Oqtane.Package/nuget.exe differ diff --git a/Oqtane.Package/pack.cmd b/Oqtane.Package/pack.cmd new file mode 100644 index 00000000..aea8d441 --- /dev/null +++ b/Oqtane.Package/pack.cmd @@ -0,0 +1,3 @@ +DEL "*.nupkg" +nuget.exe pack Oqtane.Framework.nuspec + \ No newline at end of file diff --git a/Oqtane.Server/Controllers/ModuleDefinitionController.cs b/Oqtane.Server/Controllers/ModuleDefinitionController.cs index 6ed8b830..348673e1 100644 --- a/Oqtane.Server/Controllers/ModuleDefinitionController.cs +++ b/Oqtane.Server/Controllers/ModuleDefinitionController.cs @@ -12,6 +12,7 @@ using Oqtane.Infrastructure; using Oqtane.Repository; using Oqtane.Security; using System; +using System.Runtime.InteropServices.ComTypes; // ReSharper disable StringIndexOfIsCultureSpecific.1 namespace Oqtane.Controllers @@ -147,22 +148,38 @@ namespace Oqtane.Controllers { if (ModelState.IsValid) { - string rootPath = Directory.GetParent(_environment.ContentRootPath).FullName; - string templatePath = Path.Combine(rootPath, "Oqtane.Client\\Modules\\Admin\\ModuleCreator\\Templates\\"); - ProcessTemplatesRecursively(new DirectoryInfo(templatePath), rootPath, moduleDefinition); - moduleDefinition.ModuleDefinitionName = "Oqtane.Modules." + moduleDefinition.Name + "s, Oqtane.Client"; + string templatePath = Path.Combine(Directory.GetParent(_environment.ContentRootPath).FullName, "Oqtane.Client\\Modules\\Admin\\ModuleCreator\\Templates\\" + moduleDefinition.Template + "\\"); + string rootPath; + + if (moduleDefinition.Template == "internal") + { + rootPath = Directory.GetParent(_environment.ContentRootPath).FullName + "\\"; + moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Modules, Oqtane.Client"; + moduleDefinition.ServerAssemblyName = "Oqtane.Server"; + } + else + { + rootPath = Directory.GetParent(_environment.ContentRootPath).Parent.FullName + "\\" + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Module\\"; + moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Modules, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Module.Client"; + moduleDefinition.ServerAssemblyName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Module.Server"; + } + + ProcessTemplatesRecursively(new DirectoryInfo(templatePath), rootPath, templatePath, moduleDefinition); _logger.Log(LogLevel.Information, this, LogFunction.Create, "Module Definition Created {ModuleDefinition}", moduleDefinition); + Models.Module module = _modules.GetModule(int.Parse(moduleid)); module.ModuleDefinitionName = moduleDefinition.ModuleDefinitionName; _modules.UpdateModule(module); + _installationManager.RestartApplication(); } } - private void ProcessTemplatesRecursively(DirectoryInfo current, string rootPath, ModuleDefinition moduleDefinition) + private void ProcessTemplatesRecursively(DirectoryInfo current, string rootPath, string templatePath, ModuleDefinition moduleDefinition) { // process folder - string folderPath = current.FullName.Replace("Oqtane.Client\\Modules\\Admin\\ModuleCreator\\Templates\\", ""); + string folderPath = rootPath + current.FullName.Replace(templatePath, ""); + folderPath = folderPath.Replace("[Owner]", moduleDefinition.Owner); folderPath = folderPath.Replace("[Module]", moduleDefinition.Name); if (!Directory.Exists(folderPath)) { @@ -176,19 +193,22 @@ namespace Oqtane.Controllers { // process file string filePath = Path.Combine(folderPath, file.Name); + filePath = filePath.Replace("[Owner]", moduleDefinition.Owner); filePath = filePath.Replace("[Module]", moduleDefinition.Name); string text = System.IO.File.ReadAllText(file.FullName); + text = text.Replace("[Owner]", moduleDefinition.Owner); text = text.Replace("[Module]", moduleDefinition.Name); text = text.Replace("[Description]", moduleDefinition.Description); text = text.Replace("[RootPath]", rootPath); + text = text.Replace("[ServerAssemblyName]", moduleDefinition.ServerAssemblyName); text = text.Replace("[Folder]", folderPath); text = text.Replace("[File]", Path.GetFileName(filePath)); System.IO.File.WriteAllText(filePath, text); if (Path.GetExtension(filePath) == ".sql") { - // execute script + // execute script in curent tenant foreach (string query in text.Split("GO", StringSplitOptions.RemoveEmptyEntries)) { _sql.ExecuteNonQuery(_resolver.GetTenant(), query); @@ -200,7 +220,7 @@ namespace Oqtane.Controllers foreach (DirectoryInfo folder in folders.Reverse()) { - ProcessTemplatesRecursively(folder, rootPath, moduleDefinition); + ProcessTemplatesRecursively(folder, rootPath, templatePath, moduleDefinition); } } } diff --git a/Oqtane.Server/Repository/SqlRepository.cs b/Oqtane.Server/Repository/SqlRepository.cs index c9bdf734..2952752e 100644 --- a/Oqtane.Server/Repository/SqlRepository.cs +++ b/Oqtane.Server/Repository/SqlRepository.cs @@ -15,7 +15,15 @@ namespace Oqtane.Repository using (conn) { PrepareCommand(conn, cmd, query); - int val = cmd.ExecuteNonQuery(); + int val = -1; + try + { + val = cmd.ExecuteNonQuery(); + } + catch + { + // an error occurred executing the query + } return val; } } diff --git a/Oqtane.Shared/Models/ModuleDefinition.cs b/Oqtane.Shared/Models/ModuleDefinition.cs index 33880e1f..fe39b8e6 100644 --- a/Oqtane.Shared/Models/ModuleDefinition.cs +++ b/Oqtane.Shared/Models/ModuleDefinition.cs @@ -19,6 +19,7 @@ namespace Oqtane.Models PermissionNames = ""; ServerAssemblyName = ""; ControlTypeRoutes = ""; + Template = ""; } public int ModuleDefinitionId { get; set; } @@ -54,10 +55,12 @@ namespace Oqtane.Models [NotMapped] public string ServerAssemblyName { get; set; } [NotMapped] - public string ControlTypeTemplate { get; set; } - [NotMapped] public string ControlTypeRoutes { get; set; } [NotMapped] + public string Template { get; set; } + [NotMapped] + public string ControlTypeTemplate { get; set; } + [NotMapped] public string AssemblyName { get; set; } [NotMapped] public string Permissions { get; set; } diff --git a/Oqtane.Shared/Modules/Models/HtmlText/HtmlTextInfo.cs b/Oqtane.Shared/Modules/HtmlText/Models/HtmlTextInfo.cs similarity index 100% rename from Oqtane.Shared/Modules/Models/HtmlText/HtmlTextInfo.cs rename to Oqtane.Shared/Modules/HtmlText/Models/HtmlTextInfo.cs diff --git a/Oqtane.Shared/Shared/Utilities.cs b/Oqtane.Shared/Shared/Utilities.cs index 6c2825fc..fe8e8844 100644 --- a/Oqtane.Shared/Shared/Utilities.cs +++ b/Oqtane.Shared/Shared/Utilities.cs @@ -14,53 +14,33 @@ namespace Oqtane.Shared var assemblyName = assemblyFullName.Substring(0, assemblyFullName.IndexOf(",", StringComparison.Ordinal)); return $"{type.Namespace}, {assemblyName}"; } + public static string NavigateUrl(string alias, string path, string parameters) { - string url = ""; - if (alias != "") + var uriBuilder = new UriBuilder { - url += alias + "/"; - } - if (path != "" && path != "/") - { - url += path + "/"; - } - if (url.EndsWith("/")) - { - url = url.Substring(0, url.Length - 1); - } - if (!string.IsNullOrEmpty(parameters)) - { - url += "?" + parameters; - } - if (!url.StartsWith("/")) - { - url = "/" + url; - } - return url; + Path = !string.IsNullOrEmpty(alias) + ? (!string.IsNullOrEmpty(path)) + ? $"{alias}/{path}" + : $"{alias}" + : $"{path}", + Query = parameters + }; + + return uriBuilder.Uri.PathAndQuery; } public static string EditUrl(string alias, string path, int moduleid, string action, string parameters) { - string url = NavigateUrl(alias, path, ""); - if (url == "/") url = ""; if (moduleid != -1) { - url += "/" + moduleid.ToString(); + path += $"/{moduleid}"; + if (!string.IsNullOrEmpty(action)) + { + path += $"/{action}"; + } } - if (moduleid != -1 && action != "") - { - url += "/" + action; - } - if (!string.IsNullOrEmpty(parameters)) - { - url += "?" + parameters; - } - if (!url.StartsWith("/")) - { - url = "/" + url; - } - return url; + return NavigateUrl(alias, path, parameters); } public static string ContentUrl(string alias, int fileid) diff --git a/Oqtane.Test/Oqtane.Shared.Tests/UtilitiesTests.cs b/Oqtane.Test/Oqtane.Shared.Tests/UtilitiesTests.cs new file mode 100644 index 00000000..df6a941e --- /dev/null +++ b/Oqtane.Test/Oqtane.Shared.Tests/UtilitiesTests.cs @@ -0,0 +1,31 @@ +using Oqtane.Shared; +using Xunit; + +namespace Oqtane.Test.Oqtane.Shared.Tests +{ + public class UtilitiesTests + { + [Theory] + [InlineData("contoso", "login", "returnUrl=/admin", "/contoso/login?returnUrl=/admin")] + [InlineData("contoso", "admin", "", "/contoso/admin")] + [InlineData("contoso", "", "pageId=4", "/contoso?pageId=4")] + [InlineData("contoso", "", "pageId=4&moduleId=10", "/contoso?pageId=4&moduleId=10")] + [InlineData("contoso", "", "", "/contoso")] + [InlineData("", "login", "returnUrl=/admin", "/login?returnUrl=/admin")] + [InlineData("", "admin", "", "/admin")] + [InlineData("", "", "pageId=4", "/?pageId=4")] + [InlineData("", "", "pageId=4&moduleId=10", "/?pageId=4&moduleId=10")] + [InlineData("", "", "", "/")] + public void NavigateUrlTest(string alias, string path, string parameters, string expectedUrl) + { + // Arrange + var navigatedUrl = string.Empty; + + // Act + navigatedUrl = Utilities.NavigateUrl(alias, path, parameters); + + // Assert + Assert.Equal(expectedUrl, navigatedUrl); + } + } +} diff --git a/pack.cmd b/pack.cmd deleted file mode 100644 index af7998a6..00000000 --- a/pack.cmd +++ /dev/null @@ -1,3 +0,0 @@ -DEL "*.nupkg" -C:\Nuget\nuget.exe pack Oqtane.Framework.nuspec - \ No newline at end of file