diff --git a/Oqtane.Client/Modules/Admin/Login/Index.razor b/Oqtane.Client/Modules/Admin/Login/Index.razor
index b8a77ec6..06157646 100644
--- a/Oqtane.Client/Modules/Admin/Login/Index.razor
+++ b/Oqtane.Client/Modules/Admin/Login/Index.razor
@@ -89,8 +89,7 @@
if (user.IsAuthenticated)
{
authstateprovider.NotifyAuthenticationChanged();
- PageState.Reload = Constants.ReloadSite;
- NavigationManager.NavigateTo(NavigateUrl(ReturnUrl));
+ NavigationManager.NavigateTo(NavigateUrl(ReturnUrl, Reload.Site));
}
else
{
diff --git a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Add.razor b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Add.razor
index 4789f600..b9a6ea41 100644
--- a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Add.razor
+++ b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Add.razor
@@ -45,7 +45,6 @@ else
private async Task InstallFile()
{
await ModuleDefinitionService.InstallModulesAsync();
- PageState.Reload = Constants.ReloadApplication;
- NavigationManager.NavigateTo(NavigateUrl());
+ NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
}
}
diff --git a/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor b/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor
index 26c7ebfe..51869930 100644
--- a/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor
+++ b/Oqtane.Client/Modules/Admin/ModuleSettings/Index.razor
@@ -121,8 +121,7 @@
moduleType.GetMethod("UpdateSettings").Invoke(settings, null); // method must be public in settings component
}
- PageState.Reload = Constants.ReloadPage;
- NavigationManager.NavigateTo(NavigateUrl());
+ NavigationManager.NavigateTo(NavigateUrl(Reload.Page));
}
}
diff --git a/Oqtane.Client/Modules/Admin/Pages/Add.razor b/Oqtane.Client/Modules/Admin/Pages/Add.razor
index bcf77cf5..2a105bcf 100644
--- a/Oqtane.Client/Modules/Admin/Pages/Add.razor
+++ b/Oqtane.Client/Modules/Admin/Pages/Add.razor
@@ -278,8 +278,7 @@
await PageService.AddPageAsync(page);
await PageService.UpdatePageOrderAsync(page.SiteId, page.ParentId);
- PageState.Reload = Constants.ReloadSite;
- NavigationManager.NavigateTo(NavigateUrl(page.Path));
+ NavigationManager.NavigateTo(NavigateUrl(page.Path, Reload.Site));
}
catch (Exception ex)
{
diff --git a/Oqtane.Client/Modules/Admin/Pages/Delete.razor b/Oqtane.Client/Modules/Admin/Pages/Delete.razor
index 37075775..7a4fc272 100644
--- a/Oqtane.Client/Modules/Admin/Pages/Delete.razor
+++ b/Oqtane.Client/Modules/Admin/Pages/Delete.razor
@@ -179,15 +179,7 @@
try
{
await PageService.DeletePageAsync(Int32.Parse(PageState.QueryString["id"]));
- PageState.Reload = Constants.ReloadSite;
- if (PageState.Page.Name == "Page Management")
- {
- NavigationManager.NavigateTo(NavigateUrl());
- }
- else
- {
- NavigationManager.NavigateTo(NavigateUrl(""));
- }
+ NavigationManager.NavigateTo(NavigateUrl("", Reload.Site));
}
catch (Exception ex)
{
diff --git a/Oqtane.Client/Modules/Admin/Pages/Edit.razor b/Oqtane.Client/Modules/Admin/Pages/Edit.razor
index 65107ecc..80cca79d 100644
--- a/Oqtane.Client/Modules/Admin/Pages/Edit.razor
+++ b/Oqtane.Client/Modules/Admin/Pages/Edit.razor
@@ -354,8 +354,7 @@
}
}
- PageState.Reload = Constants.ReloadSite;
- NavigationManager.NavigateTo(NavigateUrl(page.Path));
+ NavigationManager.NavigateTo(NavigateUrl(page.Path, Reload.Site));
}
catch (Exception ex)
{
diff --git a/Oqtane.Client/Modules/Admin/Themes/Add.razor b/Oqtane.Client/Modules/Admin/Themes/Add.razor
new file mode 100644
index 00000000..6e9d80c5
--- /dev/null
+++ b/Oqtane.Client/Modules/Admin/Themes/Add.razor
@@ -0,0 +1,50 @@
+@using Microsoft.AspNetCore.Components.Routing
+@using Microsoft.AspNetCore.Components.Web
+@using Oqtane.Modules.Controls
+@using Oqtane.Modules
+@using Oqtane.Services
+@using Oqtane.Shared
+@namespace Oqtane.Modules.Admin.Themes
+@inherits ModuleBase
+@inject NavigationManager NavigationManager
+@inject IFileService FileService
+@inject IThemeService ThemeService
+
+
+@if (uploaded)
+{
+
+}
+else
+{
+
+}
+Cancel
+
+@code {
+ public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
+
+ bool uploaded = false;
+
+ private async Task UploadFile()
+ {
+ await FileService.UploadFilesAsync("Themes");
+ uploaded = true;
+ StateHasChanged();
+ }
+
+ private async Task InstallFile()
+ {
+ await ThemeService.InstallThemesAsync();
+ NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
+ }
+}
diff --git a/Oqtane.Client/Modules/Admin/Themes/Index.razor b/Oqtane.Client/Modules/Admin/Themes/Index.razor
index f272dba6..d1c188fb 100644
--- a/Oqtane.Client/Modules/Admin/Themes/Index.razor
+++ b/Oqtane.Client/Modules/Admin/Themes/Index.razor
@@ -2,9 +2,9 @@
@using Oqtane.Services
@using Oqtane.Models
@using Oqtane.Modules
+@using Oqtane.Modules.Controls
@namespace Oqtane.Modules.Admin.Themes
@inherits ModuleBase
-
@inject IThemeService ThemeService
@if (Themes == null)
@@ -13,6 +13,7 @@
}
else
{
+
diff --git a/Oqtane.Client/Modules/HtmlText/Edit.razor b/Oqtane.Client/Modules/HtmlText/Edit.razor
index 887bd056..aa3a20ae 100644
--- a/Oqtane.Client/Modules/HtmlText/Edit.razor
+++ b/Oqtane.Client/Modules/HtmlText/Edit.razor
@@ -80,8 +80,7 @@
htmltext.Content = content;
await htmltextservice.AddHtmlTextAsync(htmltext);
}
- PageState.Reload = Constants.ReloadPage;
- NavigationManager.NavigateTo(NavigateUrl());
+ NavigationManager.NavigateTo(NavigateUrl(Reload.Page));
}
catch (Exception ex)
{
diff --git a/Oqtane.Client/Modules/HtmlText/Services/HtmlTextService.cs b/Oqtane.Client/Modules/HtmlText/Services/HtmlTextService.cs
index d3c602c7..47244ed3 100644
--- a/Oqtane.Client/Modules/HtmlText/Services/HtmlTextService.cs
+++ b/Oqtane.Client/Modules/HtmlText/Services/HtmlTextService.cs
@@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Components;
using Oqtane.Services;
using Oqtane.Modules.HtmlText.Models;
using Oqtane.Shared;
+using System.Text.Json;
namespace Oqtane.Modules.HtmlText.Services
{
@@ -29,7 +30,17 @@ namespace Oqtane.Modules.HtmlText.Services
public async Task GetHtmlTextAsync(int ModuleId)
{
- return await http.GetJsonAsync(apiurl + "/" + ModuleId.ToString() + "?entityid=" + ModuleId.ToString());
+ HtmlTextInfo htmltext;
+ try
+ {
+ // exception handling is required because GetJsonAsync() returns an error if no content exists for the ModuleId ( https://github.com/aspnet/AspNetCore/issues/14041 )
+ htmltext = await http.GetJsonAsync(apiurl + "/" + ModuleId.ToString() + "?entityid=" + ModuleId.ToString());
+ }
+ catch
+ {
+ htmltext = null;
+ }
+ return htmltext;
}
public async Task AddHtmlTextAsync(HtmlTextInfo htmltext)
diff --git a/Oqtane.Client/Modules/ModuleBase.cs b/Oqtane.Client/Modules/ModuleBase.cs
index 6f176c38..0f2fba26 100644
--- a/Oqtane.Client/Modules/ModuleBase.cs
+++ b/Oqtane.Client/Modules/ModuleBase.cs
@@ -25,14 +25,29 @@ namespace Oqtane.Modules
return NavigateUrl(PageState.Page.Path);
}
+ public string NavigateUrl(Reload reload)
+ {
+ return NavigateUrl(PageState.Page.Path, reload);
+ }
+
public string NavigateUrl(string path)
{
- return NavigateUrl(path, "");
+ return NavigateUrl(path, "", Reload.None);
+ }
+
+ public string NavigateUrl(string path, Reload reload)
+ {
+ return NavigateUrl(path, "", reload);
}
public string NavigateUrl(string path, string parameters)
{
- return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters);
+ return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters, Reload.None);
+ }
+
+ public string NavigateUrl(string path, string parameters, Reload reload)
+ {
+ return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters, reload);
}
public string EditUrl(string action)
diff --git a/Oqtane.Client/Services/Interfaces/IThemeService.cs b/Oqtane.Client/Services/Interfaces/IThemeService.cs
index dcc6f674..8ed4db1e 100644
--- a/Oqtane.Client/Services/Interfaces/IThemeService.cs
+++ b/Oqtane.Client/Services/Interfaces/IThemeService.cs
@@ -10,5 +10,6 @@ namespace Oqtane.Services
Dictionary GetThemeTypes(List themes);
Dictionary GetPaneLayoutTypes(List themes);
Dictionary GetContainerTypes(List themes);
+ Task InstallThemesAsync();
}
}
diff --git a/Oqtane.Client/Services/ThemeService.cs b/Oqtane.Client/Services/ThemeService.cs
index 46a75c9e..670372f1 100644
--- a/Oqtane.Client/Services/ThemeService.cs
+++ b/Oqtane.Client/Services/ThemeService.cs
@@ -99,5 +99,10 @@ namespace Oqtane.Services
}
return selectableContainers;
}
+
+ public async Task InstallThemesAsync()
+ {
+ await http.GetJsonAsync>(apiurl + "/install");
+ }
}
}
diff --git a/Oqtane.Client/Shared/PageState.cs b/Oqtane.Client/Shared/PageState.cs
index 37721465..f8dfe93e 100644
--- a/Oqtane.Client/Shared/PageState.cs
+++ b/Oqtane.Client/Shared/PageState.cs
@@ -21,6 +21,5 @@ namespace Oqtane.Shared
public string Control { get; set; }
public bool EditMode { get; set; }
public bool DesignMode { get; set; }
- public int Reload { get; set; }
}
}
diff --git a/Oqtane.Client/Shared/Reload.cs b/Oqtane.Client/Shared/Reload.cs
new file mode 100644
index 00000000..18e8f448
--- /dev/null
+++ b/Oqtane.Client/Shared/Reload.cs
@@ -0,0 +1,10 @@
+namespace Oqtane.Shared
+{
+ public enum Reload
+ {
+ None,
+ Page,
+ Site,
+ Application
+ }
+}
diff --git a/Oqtane.Client/Shared/SiteRouter.razor b/Oqtane.Client/Shared/SiteRouter.razor
index e4c9d1d1..c32d15d1 100644
--- a/Oqtane.Client/Shared/SiteRouter.razor
+++ b/Oqtane.Client/Shared/SiteRouter.razor
@@ -90,16 +90,34 @@
string control = "";
bool editmode = false;
bool designmode = false;
- int reload = 0;
+ Reload reload = Reload.None;
+
+ // get Url path and querystring ( and remove anchors )
+ string path = new Uri(_absoluteUri).PathAndQuery.Substring(1);
+ if (path.IndexOf("#") != -1)
+ {
+ path = path.Substring(0, path.IndexOf("#"));
+ }
+
+ // parse querystring and remove
+ Dictionary querystring = new Dictionary();
+ if (path.IndexOf("?") != -1)
+ {
+ querystring = ParseQueryString(path);
+ path = path.Substring(0, path.IndexOf("?"));
+ }
+ if (querystring.ContainsKey("reload"))
+ {
+ reload = (Reload)int.Parse(querystring["reload"]);
+ }
if (PageState != null)
{
- reload = PageState.Reload;
editmode = PageState.EditMode;
designmode = PageState.DesignMode;
}
- if (PageState == null || reload == Constants.ReloadApplication)
+ if (PageState == null || reload == Reload.Application)
{
moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync();
themes = await ThemeService.GetThemesAsync();
@@ -119,9 +137,9 @@
{
alias = GetAlias(_absoluteUri, aliases);
SiteState.Alias = alias; // set state for services
- reload = Constants.ReloadSite;
+ reload = Reload.Site;
}
- if (PageState == null || reload <= Constants.ReloadSite)
+ if (PageState == null || reload <= Reload.Site)
{
site = await SiteService.GetSiteAsync(alias.SiteId);
}
@@ -131,7 +149,7 @@
}
if (site != null)
{
- if (PageState == null || reload >= Constants.ReloadSite)
+ if (PageState == null || reload >= Reload.Site)
{
pages = await PageService.GetPagesAsync(site.SiteId);
}
@@ -140,21 +158,6 @@
pages = PageState.Pages;
}
- // get Url path and querystring ( and remove anchors )
- string path = new Uri(_absoluteUri).PathAndQuery.Substring(1);
- if (path.IndexOf("#") != -1)
- {
- path = path.Substring(0, path.IndexOf("#"));
- }
-
- // parse querystring and remove
- Dictionary querystring = new Dictionary();
- if (path.IndexOf("?") != -1)
- {
- querystring = ParseQueryString(path);
- path = path.Substring(0, path.IndexOf("?"));
- }
-
// format path and remove alias
path = path.Replace("//", "/");
if (!path.EndsWith("/")) { path += "/"; }
@@ -185,7 +188,7 @@
// remove trailing slash so it can be used as a key for Pages
if (path.EndsWith("/")) path = path.Substring(0, path.Length - 1);
- if (PageState == null || reload >= Constants.ReloadPage)
+ if (PageState == null || reload >= Reload.Page)
{
page = pages.Where(item => item.Path == path).FirstOrDefault();
}
@@ -204,13 +207,13 @@
if (page.Path != path)
{
page = pages.Where(item => item.Path == path).FirstOrDefault();
- reload = Constants.ReloadPage;
+ reload = Reload.Page;
editmode = page.EditMode;
designmode = false;
}
user = null;
- if (PageState == null || reload >= Constants.ReloadPage)
+ if (PageState == null || reload >= Reload.Page)
{
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
if (authState.User.Identity.IsAuthenticated)
@@ -244,10 +247,10 @@
if (PageState != null && (PageState.ModuleId != pagestate.ModuleId || PageState.Control != pagestate.Control))
{
- reload = Constants.ReloadPage;
+ reload = Reload.Page;
}
- if (PageState == null || reload >= Constants.ReloadPage)
+ if (PageState == null || reload >= Reload.Page)
{
modules = await ModuleService.GetModulesAsync(page.PageId);
modules = ProcessModules(modules, moduledefinitions, pagestate.Control, page.Panes);
@@ -259,7 +262,6 @@
pagestate.Modules = modules;
pagestate.EditMode = editmode;
pagestate.DesignMode = designmode;
- pagestate.Reload = Constants.ReloadReset;
OnStateChange?.Invoke(pagestate);
}
diff --git a/Oqtane.Client/Shared/Utilities.cs b/Oqtane.Client/Shared/Utilities.cs
index b4775f6d..cd2af1d3 100644
--- a/Oqtane.Client/Shared/Utilities.cs
+++ b/Oqtane.Client/Shared/Utilities.cs
@@ -6,7 +6,7 @@ namespace Oqtane.Shared
public class Utilities
{
- public static string NavigateUrl(string alias, string path, string parameters)
+ public static string NavigateUrl(string alias, string path, string parameters, Reload reload)
{
string url = "";
if (alias != "")
@@ -25,6 +25,10 @@ namespace Oqtane.Shared
{
url += "?" + parameters;
}
+ if (reload != Reload.None)
+ {
+ url += ((string.IsNullOrEmpty(parameters)) ? "?" : "&") + "reload=" + ((int)reload).ToString();
+ }
if (!url.StartsWith("/"))
{
url = "/" + url;
@@ -34,7 +38,7 @@ namespace Oqtane.Shared
public static string EditUrl(string alias, string path, int moduleid, string action, string parameters)
{
- string url = NavigateUrl(alias, path, "");
+ string url = NavigateUrl(alias, path, "", Reload.None);
if (url == "/") url = "";
if (moduleid != -1)
{
diff --git a/Oqtane.Client/Themes/ContainerBase.cs b/Oqtane.Client/Themes/ContainerBase.cs
index 6a939f5b..d234002d 100644
--- a/Oqtane.Client/Themes/ContainerBase.cs
+++ b/Oqtane.Client/Themes/ContainerBase.cs
@@ -19,15 +19,31 @@ namespace Oqtane.Themes
return NavigateUrl(PageState.Page.Path);
}
+ public string NavigateUrl(Reload reload)
+ {
+ return NavigateUrl(PageState.Page.Path, reload);
+ }
+
public string NavigateUrl(string path)
{
- return NavigateUrl(path, "");
+ return NavigateUrl(path, "", Reload.None);
+ }
+
+ public string NavigateUrl(string path, Reload reload)
+ {
+ return NavigateUrl(path, "", reload);
}
public string NavigateUrl(string path, string parameters)
{
- return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters);
+ return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters, Reload.None);
}
+
+ public string NavigateUrl(string path, string parameters, Reload reload)
+ {
+ return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters, reload);
+ }
+
public string EditUrl(string action, string parameters)
{
return EditUrl(ModuleState.ModuleId, action, parameters);
diff --git a/Oqtane.Client/Themes/Controls/ControlPanel.razor b/Oqtane.Client/Themes/Controls/ControlPanel.razor
index 3d95a44f..0ad52951 100644
--- a/Oqtane.Client/Themes/Controls/ControlPanel.razor
+++ b/Oqtane.Client/Themes/Controls/ControlPanel.razor
@@ -164,8 +164,7 @@
await PageModuleService.AddPageModuleAsync(pagemodule);
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
- PageState.Reload = Constants.ReloadPage;
- NavigationManager.NavigateTo(NavigateUrl());
+ NavigationManager.NavigateTo(NavigateUrl(Reload.Page));
}
}
@@ -204,8 +203,7 @@
PageState.EditMode = true;
PageState.DesignMode = true;
}
- PageState.Reload = Constants.ReloadPage;
- NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "edit=" + PageState.EditMode.ToString().ToLower()));
+ NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "edit=" + PageState.EditMode.ToString().ToLower(), Reload.Page));
}
}
}
\ No newline at end of file
diff --git a/Oqtane.Client/Themes/Controls/Login.razor b/Oqtane.Client/Themes/Controls/Login.razor
index 83106017..14aa4f75 100644
--- a/Oqtane.Client/Themes/Controls/Login.razor
+++ b/Oqtane.Client/Themes/Controls/Login.razor
@@ -53,8 +53,7 @@
{
// client-side Blazor
authstateprovider.NotifyAuthenticationChanged();
- PageState.Reload = Constants.ReloadSite;
- NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "logout"));
+ NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "logout", Reload.Site));
}
}
}
diff --git a/Oqtane.Client/Themes/Controls/ModuleActions.razor b/Oqtane.Client/Themes/Controls/ModuleActions.razor
index a1f3d7d1..eb8b698e 100644
--- a/Oqtane.Client/Themes/Controls/ModuleActions.razor
+++ b/Oqtane.Client/Themes/Controls/ModuleActions.razor
@@ -65,7 +65,7 @@
{
PageModule pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
- string url = NavigateUrl();
+ string url = NavigateUrl(Reload.Page);
switch (action)
{
case "<<":
@@ -104,7 +104,6 @@
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pane);
break;
}
- PageState.Reload = Constants.ReloadPage;
NavigationManager.NavigateTo(url);
}
}
diff --git a/Oqtane.Client/Themes/ThemeBase.cs b/Oqtane.Client/Themes/ThemeBase.cs
index 2ad2956c..dd539a39 100644
--- a/Oqtane.Client/Themes/ThemeBase.cs
+++ b/Oqtane.Client/Themes/ThemeBase.cs
@@ -15,14 +15,29 @@ namespace Oqtane.Themes
return NavigateUrl(PageState.Page.Path);
}
+ public string NavigateUrl(Reload reload)
+ {
+ return NavigateUrl(PageState.Page.Path, reload);
+ }
+
public string NavigateUrl(string path)
{
- return NavigateUrl(path, "");
+ return NavigateUrl(path, "", Reload.None);
+ }
+
+ public string NavigateUrl(string path, Reload reload)
+ {
+ return NavigateUrl(path, "", reload);
}
public string NavigateUrl(string path, string parameters)
{
- return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters);
+ return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters, Reload.None);
+ }
+
+ public string NavigateUrl(string path, string parameters, Reload reload)
+ {
+ return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters, reload);
}
}
diff --git a/Oqtane.Client/Themes/ThemeObjectBase.cs b/Oqtane.Client/Themes/ThemeObjectBase.cs
index efa59f63..e5284b7f 100644
--- a/Oqtane.Client/Themes/ThemeObjectBase.cs
+++ b/Oqtane.Client/Themes/ThemeObjectBase.cs
@@ -13,14 +13,29 @@ namespace Oqtane.Themes
return NavigateUrl(PageState.Page.Path);
}
+ public string NavigateUrl(Reload reload)
+ {
+ return NavigateUrl(PageState.Page.Path, reload);
+ }
+
public string NavigateUrl(string path)
{
- return NavigateUrl(path, "");
+ return NavigateUrl(path, "", Reload.None);
+ }
+
+ public string NavigateUrl(string path, Reload reload)
+ {
+ return NavigateUrl(path, "", reload);
}
public string NavigateUrl(string path, string parameters)
{
- return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters);
+ return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters, Reload.None);
+ }
+
+ public string NavigateUrl(string path, string parameters, Reload reload)
+ {
+ return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters, reload);
}
public string EditUrl(int moduleid, string action)
diff --git a/Oqtane.Server/Controllers/ThemeController.cs b/Oqtane.Server/Controllers/ThemeController.cs
index 8cb7afe9..c8e409fb 100644
--- a/Oqtane.Server/Controllers/ThemeController.cs
+++ b/Oqtane.Server/Controllers/ThemeController.cs
@@ -2,6 +2,13 @@
using Microsoft.AspNetCore.Mvc;
using Oqtane.Repository;
using Oqtane.Models;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.Extensions.Hosting;
+using Oqtane.Shared;
+using System.IO;
+using Microsoft.AspNetCore.Hosting;
+using System.Reflection;
+using System.IO.Compression;
namespace Oqtane.Controllers
{
@@ -9,10 +16,14 @@ namespace Oqtane.Controllers
public class ThemeController : Controller
{
private readonly IThemeRepository Themes;
+ private readonly IHostApplicationLifetime HostApplicationLifetime;
+ private readonly IWebHostEnvironment environment;
- public ThemeController(IThemeRepository Themes)
+ public ThemeController(IThemeRepository Themes, IHostApplicationLifetime HostApplicationLifetime, IWebHostEnvironment environment)
{
this.Themes = Themes;
+ this.HostApplicationLifetime = HostApplicationLifetime;
+ this.environment = environment;
}
// GET: api/
@@ -21,5 +32,42 @@ namespace Oqtane.Controllers
{
return Themes.GetThemes();
}
+
+ [HttpGet("install")]
+ [Authorize(Roles = Constants.HostRole)]
+ public void InstallThemes()
+ {
+ bool install = false;
+ string themefolder = Path.Combine(environment.WebRootPath, "Themes");
+ string binfolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
+
+ // iterate through theme packages
+ foreach (string packagename in Directory.GetFiles(themefolder, "*.nupkg"))
+ {
+ // iterate through files and deploy to appropriate locations
+ using (ZipArchive archive = ZipFile.OpenRead(packagename))
+ {
+ foreach (ZipArchiveEntry entry in archive.Entries)
+ {
+ string filename = Path.GetFileName(entry.FullName);
+ switch (Path.GetExtension(filename))
+ {
+ case ".dll":
+ entry.ExtractToFile(Path.Combine(binfolder, filename));
+ break;
+ }
+ }
+ }
+ // remove theme package
+ System.IO.File.Delete(packagename);
+ install = true;
+ }
+
+ if (install)
+ {
+ // restart application
+ HostApplicationLifetime.StopApplication();
+ }
+ }
}
}
diff --git a/Oqtane.Server/Repository/ThemeRepository.cs b/Oqtane.Server/Repository/ThemeRepository.cs
index 5cac43fc..b9547e93 100644
--- a/Oqtane.Server/Repository/ThemeRepository.cs
+++ b/Oqtane.Server/Repository/ThemeRepository.cs
@@ -24,7 +24,7 @@ namespace Oqtane.Repository
// iterate through Oqtane theme assemblies
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies()
.Where(item => item.FullName.StartsWith("Oqtane.") || item.FullName.Contains(".Theme.")).ToArray();
- foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
+ foreach (Assembly assembly in assemblies)
{
Themes = LoadThemesFromAssembly(Themes, assembly);
}
diff --git a/Oqtane.Server/Scripts/00.00.00.sql b/Oqtane.Server/Scripts/00.00.00.sql
index 3c6c6b7f..153357f7 100644
--- a/Oqtane.Server/Scripts/00.00.00.sql
+++ b/Oqtane.Server/Scripts/00.00.00.sql
@@ -116,6 +116,7 @@ CREATE TABLE [dbo].[Role](
[Name] [nvarchar](256) NOT NULL,
[Description] [nvarchar](50) NOT NULL,
[IsAutoAssigned] [bit] NOT NULL,
+ [IsSystem] [bit] NOT NULL,
[CreatedBy] [nvarchar](256) NOT NULL,
[CreatedOn] [datetime] NOT NULL,
[ModifiedBy] [nvarchar](256) NOT NULL,
@@ -361,23 +362,23 @@ GO
SET IDENTITY_INSERT [dbo].[Role] ON
GO
-INSERT [dbo].[Role] ([RoleId], [SiteId], [Name], [Description], [IsAutoAssigned], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn])
-VALUES (-1, null, N'All Users', N'All Users', 0, '', getdate(), '', getdate())
+INSERT [dbo].[Role] ([RoleId], [SiteId], [Name], [Description], [IsAutoAssigned], [IsSystem], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn])
+VALUES (-1, null, N'All Users', N'All Users', 0, 1, '', getdate(), '', getdate())
GO
-INSERT [dbo].[Role] ([RoleId], [SiteId], [Name], [Description], [IsAutoAssigned], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn])
-VALUES (0, null, N'Host Users', N'Host Users', 0, '', getdate(), '', getdate())
+INSERT [dbo].[Role] ([RoleId], [SiteId], [Name], [Description], [IsAutoAssigned], [IsSystem], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn])
+VALUES (0, null, N'Host Users', N'Host Users', 0, 1, '', getdate(), '', getdate())
GO
-INSERT [dbo].[Role] ([RoleId], [SiteId], [Name], [Description], [IsAutoAssigned], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn])
-VALUES (1, 1, N'Administrators', N'Site Administrators', 0, '', getdate(), '', getdate())
+INSERT [dbo].[Role] ([RoleId], [SiteId], [Name], [Description], [IsAutoAssigned], [IsSystem], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn])
+VALUES (1, 1, N'Administrators', N'Site Administrators', 0, 1, '', getdate(), '', getdate())
GO
-INSERT [dbo].[Role] ([RoleId], [SiteId], [Name], [Description], [IsAutoAssigned], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn])
-VALUES (2, 1, N'Registered Users', N'Registered Users', 1, '', getdate(), '', getdate())
+INSERT [dbo].[Role] ([RoleId], [SiteId], [Name], [Description], [IsAutoAssigned], [IsSystem], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn])
+VALUES (2, 1, N'Registered Users', N'Registered Users', 1, 1, '', getdate(), '', getdate())
GO
-INSERT [dbo].[Role] ([RoleId], [SiteId], [Name], [Description], [IsAutoAssigned], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn])
-VALUES (3, 2, N'Administrators', N'Site Administrators', 0, '', getdate(), '', getdate())
+INSERT [dbo].[Role] ([RoleId], [SiteId], [Name], [Description], [IsAutoAssigned], [IsSystem], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn])
+VALUES (3, 2, N'Administrators', N'Site Administrators', 0, 1, '', getdate(), '', getdate())
GO
-INSERT [dbo].[Role] ([RoleId], [SiteId], [Name], [Description], [IsAutoAssigned], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn])
-VALUES (4, 2, N'Registered Users', N'Registered Users', 1, '', getdate(), '', getdate())
+INSERT [dbo].[Role] ([RoleId], [SiteId], [Name], [Description], [IsAutoAssigned], [IsSystem], [CreatedBy], [CreatedOn], [ModifiedBy], [ModifiedOn])
+VALUES (4, 2, N'Registered Users', N'Registered Users', 1, 1, '', getdate(), '', getdate())
GO
SET IDENTITY_INSERT [dbo].[Role] OFF
GO
diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs
index 9f7a77bf..8eac0f46 100644
--- a/Oqtane.Server/Startup.cs
+++ b/Oqtane.Server/Startup.cs
@@ -146,11 +146,11 @@ namespace Oqtane.Server
// get list of loaded assemblies
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
-
- // iterate through Oqtane module assemblies in /bin ( filter is narrow to optimize loading process )
string path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
DirectoryInfo folder = new DirectoryInfo(path);
List moduleassemblies = new List();
+
+ // iterate through Oqtane module assemblies in /bin ( filter is narrow to optimize loading process )
foreach (FileInfo file in folder.EnumerateFiles("*.Module.*.dll"))
{
// check if assembly is already loaded
@@ -163,6 +163,18 @@ namespace Oqtane.Server
}
}
+ // iterate through Oqtane theme assemblies in /bin ( filter is narrow to optimize loading process )
+ foreach (FileInfo file in folder.EnumerateFiles("*.Theme.*.dll"))
+ {
+ // check if assembly is already loaded
+ Assembly assembly = assemblies.Where(item => item.Location == file.FullName).FirstOrDefault();
+ if (assembly == null)
+ {
+ // load assembly ( as long as dependencies are in /bin they will load as well )
+ assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file.FullName);
+ }
+ }
+
services.AddMvc().AddModuleAssemblies(moduleassemblies).AddNewtonsoftJson();
// register singleton scoped core services
@@ -313,11 +325,11 @@ namespace Oqtane.Server
// get list of loaded assemblies
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
-
- // iterate through Oqtane module assemblies in /bin ( filter is narrow to optimize loading process )
string path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
DirectoryInfo folder = new DirectoryInfo(path);
List moduleassemblies = new List();
+
+ // iterate through Oqtane module assemblies in /bin ( filter is narrow to optimize loading process )
foreach (FileInfo file in folder.EnumerateFiles("*.Module.*.dll"))
{
// check if assembly is already loaded
@@ -330,6 +342,18 @@ namespace Oqtane.Server
}
}
+ // iterate through Oqtane theme assemblies in /bin ( filter is narrow to optimize loading process )
+ foreach (FileInfo file in folder.EnumerateFiles("*.Theme.*.dll"))
+ {
+ // check if assembly is already loaded
+ Assembly assembly = assemblies.Where(item => item.Location == file.FullName).FirstOrDefault();
+ if (assembly == null)
+ {
+ // load assembly ( as long as dependencies are in /bin they will load as well )
+ assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(file.FullName);
+ }
+ }
+
services.AddMvc().AddModuleAssemblies(moduleassemblies).AddNewtonsoftJson();
// register singleton scoped core services
@@ -399,6 +423,7 @@ namespace Oqtane.Server
}
app.UseClientSideBlazorFiles();
+ app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
diff --git a/Oqtane.Shared/Models/Alias.cs b/Oqtane.Shared/Models/Alias.cs
index f22648b8..92442601 100644
--- a/Oqtane.Shared/Models/Alias.cs
+++ b/Oqtane.Shared/Models/Alias.cs
@@ -28,6 +28,20 @@ namespace Oqtane.Models
}
}
+ [NotMapped]
+ public string BaseUrl
+ {
+ get
+ {
+ string name = Name;
+ if (name.Contains("/"))
+ {
+ name = name.Substring(0, name.IndexOf("/"));
+ }
+ return Scheme + "://" + name;
+ }
+ }
+
[NotMapped]
public string Path
{
@@ -58,7 +72,7 @@ namespace Oqtane.Models
{
get
{
- return Url + "/Tenants/" + TenantId.ToString() + "/";
+ return BaseUrl + "/Tenants/" + TenantId.ToString() + "/";
}
}
@@ -76,7 +90,7 @@ namespace Oqtane.Models
{
get
{
- return Url + "/Tenants/" + TenantId.ToString() + "/Sites/" + SiteId.ToString() + "/";
+ return BaseUrl + "/Tenants/" + TenantId.ToString() + "/Sites/" + SiteId.ToString() + "/";
}
}
}
diff --git a/Oqtane.Shared/Models/Role.cs b/Oqtane.Shared/Models/Role.cs
index 03da1f77..c9a316b5 100644
--- a/Oqtane.Shared/Models/Role.cs
+++ b/Oqtane.Shared/Models/Role.cs
@@ -9,6 +9,7 @@ namespace Oqtane.Models
public string Name { get; set; }
public string Description { get; set; }
public bool IsAutoAssigned { get; set; }
+ public bool IsSystem { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }