diff --git a/Oqtane.Client/Themes/ThemeBase.cs b/Oqtane.Client/Themes/ThemeBase.cs
index 68da1a70..d6f9789e 100644
--- a/Oqtane.Client/Themes/ThemeBase.cs
+++ b/Oqtane.Client/Themes/ThemeBase.cs
@@ -93,6 +93,7 @@ namespace Oqtane.Themes
// url methods
+ // navigate url
public string NavigateUrl()
{
return NavigateUrl(PageState.Page.Path);
@@ -108,31 +109,78 @@ namespace Oqtane.Themes
return NavigateUrl(PageState.Page.Path, refresh);
}
+ public string NavigateUrl(string path, string querystring)
+ {
+ return Utilities.NavigateUrl(PageState.Alias.Path, path, querystring);
+ }
+
+ public string NavigateUrl(string path, Dictionary querystring)
+ {
+ return NavigateUrl(path, Utilities.CreateQueryString(querystring));
+ }
+
public string NavigateUrl(string path, bool refresh)
{
- return Utilities.NavigateUrl(PageState.Alias.Path, path, refresh ? "refresh" : "");
+ return NavigateUrl(path, refresh ? "refresh" : "");
}
- public string NavigateUrl(string path, string parameters)
+ public string NavigateUrl(int moduleid, string action)
{
- return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters);
+ return EditUrl(moduleid, action, "");
}
+ public string NavigateUrl(int moduleid, string action, string querystring)
+ {
+ return EditUrl(PageState.Page.Path, moduleid, action, querystring);
+ }
+
+ public string NavigateUrl(int moduleid, string action, Dictionary querystring)
+ {
+ return EditUrl(PageState.Page.Path, moduleid, action, Utilities.CreateQueryString(querystring));
+ }
+
+ public string NavigateUrl(string path, int moduleId, string action)
+ {
+ return EditUrl(path, moduleId, action, "");
+ }
+
+ public string NavigateUrl(string path, int moduleid, string action, string querystring)
+ {
+ return EditUrl(path, moduleid, action, querystring);
+ }
+
+ public string NavigateUrl(string path, int moduleid, string action, Dictionary querystring)
+ {
+ return EditUrl(path, moduleid, action, querystring);
+ }
+
+ // edit url
public string EditUrl(int moduleid, string action)
{
return EditUrl(moduleid, action, "");
}
- public string EditUrl(int moduleid, string action, string parameters)
+ public string EditUrl(int moduleid, string action, string querystring)
{
- return EditUrl(PageState.Page.Path, moduleid, action, parameters);
+ return EditUrl(PageState.Page.Path, moduleid, action, querystring);
}
- public string EditUrl(string path, int moduleid, string action, string parameters)
+ public string EditUrl(int moduleid, string action, Dictionary querystring)
{
- return Utilities.EditUrl(PageState.Alias.Path, path, moduleid, action, parameters);
+ return EditUrl(PageState.Page.Path, moduleid, action, querystring);
}
+ public string EditUrl(string path, int moduleid, string action, string querystring)
+ {
+ return Utilities.EditUrl(PageState.Alias.Path, path, moduleid, action, querystring);
+ }
+
+ public string EditUrl(string path, int moduleid, string action, Dictionary querystring)
+ {
+ return EditUrl(path, moduleid, action, Utilities.CreateQueryString(querystring));
+ }
+
+ // file url
public string FileUrl(string folderpath, string filename)
{
return FileUrl(folderpath, filename, false);
@@ -152,6 +200,7 @@ namespace Oqtane.Themes
return Utilities.FileUrl(PageState.Alias, fileid, download);
}
+ // image url
public string ImageUrl(int fileid, int width, int height)
{
return ImageUrl(fileid, width, height, "");
diff --git a/Oqtane.Client/UI/Routes.razor b/Oqtane.Client/UI/Routes.razor
index fb88abcb..de6503f2 100644
--- a/Oqtane.Client/UI/Routes.razor
+++ b/Oqtane.Client/UI/Routes.razor
@@ -61,7 +61,6 @@
{
SiteState.AntiForgeryToken = AntiForgeryToken;
SiteState.AuthorizationToken = AuthorizationToken;
- SiteState.RemoteIPAddress = (_pageState != null) ? _pageState.RemoteIPAddress : "";
SiteState.Platform = Platform;
SiteState.IsPrerendering = (HttpContext != null) ? true : false;
@@ -80,6 +79,7 @@
{
_pageState = PageState;
SiteState.Alias = PageState.Alias;
+ SiteState.RemoteIPAddress = (PageState != null) ? PageState.RemoteIPAddress : "";
_installed = true;
}
}
diff --git a/Oqtane.Client/UI/SiteRouter.razor b/Oqtane.Client/UI/SiteRouter.razor
index 7c4cde03..0d5ebc1b 100644
--- a/Oqtane.Client/UI/SiteRouter.razor
+++ b/Oqtane.Client/UI/SiteRouter.razor
@@ -157,7 +157,7 @@
// verify user is authenticated for current site
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
- if (authState.User.Identity.IsAuthenticated && authState.User.Claims.Any(item => item.Type == "sitekey" && item.Value == SiteState.Alias.SiteKey))
+ if (authState.User.Identity.IsAuthenticated && authState.User.Claims.Any(item => item.Type == Constants.SiteKeyClaimType && item.Value == SiteState.Alias.SiteKey))
{
// get user
var userid = int.Parse(authState.User.Claims.First(item => item.Type == ClaimTypes.NameIdentifier).Value);
@@ -287,10 +287,10 @@
}
// load additional metadata for current page
- page = ProcessPage(page, site, user, SiteState.Alias);
+ page = ProcessPage(page, site, user, SiteState.Alias, action);
// load additional metadata for modules
- (page, modules) = ProcessModules(page, modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType, SiteState.Alias);
+ (page, modules) = ProcessModules(site, page, modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType, SiteState.Alias);
// populate page state (which acts as a client-side cache for subsequent requests)
_pagestate = new PageState
@@ -366,7 +366,7 @@
}
}
- private Page ProcessPage(Page page, Site site, User user, Alias alias)
+ private Page ProcessPage(Page page, Site site, User user, Alias alias, string action)
{
try
{
@@ -403,6 +403,16 @@
page.Resources = ManagePageResources(page.Resources, themeobject.Resources, ResourceLevel.Page, alias, "Themes", themetype.Namespace);
}
}
+ // theme settings components are dynamically loaded within the framework Page Management module
+ if (page.Path == "admin/pages" && action.ToLower() == "edit" && theme != null && !string.IsNullOrEmpty(theme.ThemeSettingsType))
+ {
+ var settingsType = Type.GetType(theme.ThemeSettingsType);
+ if (settingsType != null)
+ {
+ var objSettings = Activator.CreateInstance(settingsType) as IModuleControl;
+ page.Resources = ManagePageResources(page.Resources, objSettings.Resources, ResourceLevel.Module, alias, "Modules", settingsType.Namespace);
+ }
+ }
if (!string.IsNullOrEmpty(panes))
{
@@ -426,7 +436,7 @@
return page;
}
- private (Page Page, List Modules) ProcessModules(Page page, List modules, int moduleid, string action, string defaultcontainertype, Alias alias)
+ private (Page Page, List Modules) ProcessModules(Site site, Page page, List modules, int moduleid, string action, string defaultcontainertype, Alias alias)
{
var paneindex = new Dictionary();
@@ -494,15 +504,40 @@
module.Prerender = moduleobject.Prerender;
page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace);
+
+ // settings components are dynamically loaded within the framework Settings module
if (action.ToLower() == "settings" && module.ModuleDefinition != null)
{
- // settings components are embedded within a framework settings module
- moduletype = Type.GetType(module.ModuleDefinition.ControlTypeTemplate.Replace(Constants.ActionToken, action), false, true);
+ // module settings component
+ var settingsType = "";
+ if (!string.IsNullOrEmpty(module.ModuleDefinition.SettingsType))
+ {
+ // module settings type explicitly declared in IModule interface
+ settingsType = module.ModuleDefinition.SettingsType;
+ }
+ else
+ {
+ // legacy support - module settings type determined by convention
+ settingsType = module.ModuleDefinition.ControlTypeTemplate.Replace(Constants.ActionToken, action);
+ }
+ moduletype = Type.GetType(settingsType, false, true);
if (moduletype != null)
{
moduleobject = Activator.CreateInstance(moduletype) as IModuleControl;
page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace);
}
+
+ // container settings component
+ var theme = site.Themes.FirstOrDefault(item => item.Themes.Any(item => item.TypeName == page.ThemeType));
+ if (theme != null && !string.IsNullOrEmpty(theme.ContainerSettingsType))
+ {
+ moduletype = Type.GetType(theme.ContainerSettingsType);
+ if (moduletype != null)
+ {
+ moduleobject = Activator.CreateInstance(moduletype) as IModuleControl;
+ page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace);
+ }
+ }
}
// additional metadata needed for admin components
diff --git a/Oqtane.Client/UI/ThemeBuilder.razor b/Oqtane.Client/UI/ThemeBuilder.razor
index a563dfd8..3058f4f4 100644
--- a/Oqtane.Client/UI/ThemeBuilder.razor
+++ b/Oqtane.Client/UI/ThemeBuilder.razor
@@ -20,6 +20,13 @@
return;
}
+ // force authenticated user to provide email address (email may be missing if using external login)
+ if (PageState.User != null && PageState.User.IsAuthenticated && string.IsNullOrEmpty(PageState.User.Email) && PageState.Route.PagePath != "profile")
+ {
+ NavigationManager.NavigateTo(Utilities.NavigateUrl(PageState.Alias.Path, "profile", "returnurl=" + WebUtility.UrlEncode(PageState.Route.PathAndQuery)));
+ return;
+ }
+
// set page title
if (!string.IsNullOrEmpty(PageState.Page.Title))
{
@@ -44,7 +51,6 @@
}
// head content
- AddHeadContent(headcontent, PageState.Site.HeadContent);
if (!string.IsNullOrEmpty(PageState.Site.HeadContent))
{
headcontent = AddHeadContent(headcontent, PageState.Site.HeadContent);
@@ -66,30 +72,24 @@
{
if (!string.IsNullOrEmpty(content))
{
- if (PageState.RenderMode == RenderModes.Interactive)
+ var elements = content.Split('<', StringSplitOptions.RemoveEmptyEntries);
+ foreach (var element in elements)
{
- // remove scripts
- var index = content.IndexOf("") + 9 - index);
- index = content.IndexOf("