diff --git a/Oqtane.Client/UI/SiteRouter.razor b/Oqtane.Client/UI/SiteRouter.razor index a384fc58..3d058032 100644 --- a/Oqtane.Client/UI/SiteRouter.razor +++ b/Oqtane.Client/UI/SiteRouter.razor @@ -1,4 +1,6 @@ -@namespace Oqtane.UI +@using System.Diagnostics.CodeAnalysis +@using System.Runtime.InteropServices +@namespace Oqtane.UI @inject AuthenticationStateProvider AuthenticationStateProvider @inject SiteState SiteState @inject NavigationManager NavigationManager @@ -11,9 +13,6 @@ @inject IModuleService ModuleService @inject IModuleDefinitionService ModuleDefinitionService @inject ILogService LogService -@using System.Diagnostics.CodeAnalysis -@using Oqtane.Enums -@using System.Runtime.InteropServices @implements IHandleAfterRender @DynamicComponent @@ -89,7 +88,7 @@ // get path var path = uri.LocalPath.Substring(1); - // parse querystring + // parse querystring var querystring = ParseQueryString(uri.Query); // the reload parameter is used during user login/logout @@ -237,7 +236,7 @@ } // check if user is authorized to view page - if (UserSecurity.IsAuthorized(user,PermissionNames.View, page.Permissions)) + if (UserSecurity.IsAuthorized(user, PermissionNames.View, page.Permissions)) { page = await ProcessPage(page, site, user); diff --git a/Oqtane.Client/_Imports.razor b/Oqtane.Client/_Imports.razor index 22d11669..3dce6c30 100644 --- a/Oqtane.Client/_Imports.razor +++ b/Oqtane.Client/_Imports.razor @@ -17,4 +17,5 @@ @using Oqtane.Shared @using Oqtane.Themes @using Oqtane.Themes.Controls -@using Oqtane.UI \ No newline at end of file +@using Oqtane.UI +@using Oqtane.Enums diff --git a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs index 9e717e37..8ec43e6e 100644 --- a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs +++ b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs @@ -197,11 +197,8 @@ namespace Oqtane.Repository || Attribute.IsDefined(modulecontroltype, typeof(OqtaneIgnoreAttribute)) ) continue; - string[] typename = modulecontroltype.AssemblyQualifiedName?.Split(',').Select(item => item.Trim()).ToArray(); - string[] segments = typename[0].Split('.'); - Array.Resize(ref segments, segments.Length - 1); - string moduleType = string.Join(".", segments); - string qualifiedModuleType = moduleType + ", " + typename[1]; + string moduleNamespace = modulecontroltype.Namespace; + string qualifiedModuleType = moduleNamespace + ", " + modulecontroltype.Assembly.GetName().Name; int index = moduledefinitions.FindIndex(item => item.ModuleDefinitionName == qualifiedModuleType); if (index == -1) @@ -210,7 +207,7 @@ namespace Oqtane.Repository Type moduletype = assembly .GetTypes() .Where(item => item.Namespace != null) - .Where(item => item.Namespace.StartsWith(moduleType)) + .Where(item => item.Namespace.StartsWith(moduleNamespace)) .FirstOrDefault(item => item.GetInterfaces().Contains(typeof(IModule))); if (moduletype != null) { @@ -223,8 +220,8 @@ namespace Oqtane.Repository // set default property values moduledefinition = new ModuleDefinition { - Name = moduleType.Substring(moduleType.LastIndexOf(".") + 1), - Description = "Manage " + moduleType.Substring(moduleType.LastIndexOf(".") + 1), + Name = moduleNamespace.Substring(moduleNamespace.LastIndexOf(".") + 1), + Description = "Manage " + moduleNamespace.Substring(moduleNamespace.LastIndexOf(".") + 1), Categories = ((qualifiedModuleType.StartsWith("Oqtane.Modules.Admin.")) ? "Admin" : "") }; } @@ -232,7 +229,7 @@ namespace Oqtane.Repository // set internal properties moduledefinition.ModuleDefinitionName = qualifiedModuleType; moduledefinition.Version = ""; // will be populated from database - moduledefinition.ControlTypeTemplate = moduleType + "." + Constants.ActionToken + ", " + typename[1]; + moduledefinition.ControlTypeTemplate = moduleNamespace + "." + Constants.ActionToken + ", " + modulecontroltype.Assembly.GetName().Name; moduledefinition.AssemblyName = assembly.GetName().Name; if (string.IsNullOrEmpty(moduledefinition.Categories)) @@ -269,7 +266,7 @@ namespace Oqtane.Repository { foreach (string action in actions.Split(',')) { - moduledefinition.ControlTypeRoutes += (action + "=" + modulecontroltype.FullName + ", " + typename[1] + ";"); + moduledefinition.ControlTypeRoutes += (action + "=" + modulecontroltype.FullName + ", " + modulecontroltype.Assembly.GetName().Name + ";"); } } diff --git a/Oqtane.Server/Repository/ThemeRepository.cs b/Oqtane.Server/Repository/ThemeRepository.cs index 9885fe83..6b0a5e45 100644 --- a/Oqtane.Server/Repository/ThemeRepository.cs +++ b/Oqtane.Server/Repository/ThemeRepository.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using Oqtane.Models; +using Oqtane.Shared; using Oqtane.Themes; namespace Oqtane.Repository @@ -46,76 +47,77 @@ namespace Oqtane.Repository Type[] themeControlTypes = assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(IThemeControl))).ToArray(); foreach (Type themeControlType in themeControlTypes) { - if (themeControlType.Name != "ThemeBase") + // Check if type should be ignored + if (themeControlType.Name == "ThemeBase" + || themeControlType.IsGenericType + || Attribute.IsDefined(themeControlType, typeof(OqtaneIgnoreAttribute)) + ) continue; + + string themeNamespace = themeControlType.Namespace; + string qualifiedModuleType = themeNamespace + ", " + themeControlType.Assembly.GetName().Name; + + int index = themes.FindIndex(item => item.ThemeName == themeNamespace); + if (index == -1) { - string[] typename = themeControlType.AssemblyQualifiedName.Split(',').Select(item => item.Trim()).ToList().ToArray(); - string[] segments = typename[0].Split('.'); - Array.Resize(ref segments, segments.Length - 1); - string @namespace = string.Join(".", segments); - - int index = themes.FindIndex(item => item.ThemeName == @namespace); - if (index == -1) - { - // determine if this theme implements ITheme - Type themetype = assembly.GetTypes() - .Where(item => item.Namespace != null) - .Where(item => item.Namespace.StartsWith(@namespace)) - .Where(item => item.GetInterfaces().Contains(typeof(ITheme))).FirstOrDefault(); - if (themetype != null) - { - var themeobject = Activator.CreateInstance(themetype); - theme = (Theme)themetype.GetProperty("Theme").GetValue(themeobject); - } - else - { - theme = new Theme - { - Name = themeControlType.Name, - Version = new Version(1, 0, 0).ToString() - }; - } - // set internal properties - theme.ThemeName = @namespace; - theme.ThemeControls = ""; - theme.PaneLayouts = ""; - theme.ContainerControls = ""; - theme.AssemblyName = assembly.FullName.Split(",")[0]; - themes.Add(theme); - index = themes.FindIndex(item => item.ThemeName == @namespace); - } - theme = themes[index]; - theme.ThemeControls += (themeControlType.FullName + ", " + typename[1] + ";"); - - // layouts - Type[] layouttypes = assembly.GetTypes() + // determine if this theme implements ITheme + Type themetype = assembly.GetTypes() .Where(item => item.Namespace != null) - .Where(item => item.Namespace.StartsWith(@namespace)) - .Where(item => item.GetInterfaces().Contains(typeof(ILayoutControl))).ToArray(); - foreach (Type layouttype in layouttypes) + .Where(item => item.Namespace.StartsWith(themeNamespace)) + .Where(item => item.GetInterfaces().Contains(typeof(ITheme))).FirstOrDefault(); + if (themetype != null) { - string panelayout = layouttype.FullName + ", " + typename[1] + ";"; - if (!theme.PaneLayouts.Contains(panelayout)) - { - theme.PaneLayouts += panelayout; - } + var themeobject = Activator.CreateInstance(themetype); + theme = (Theme)themetype.GetProperty("Theme").GetValue(themeobject); } - - // containers - Type[] containertypes = assembly.GetTypes() - .Where(item => item.Namespace != null) - .Where(item => item.Namespace.StartsWith(@namespace)) - .Where(item => item.GetInterfaces().Contains(typeof(IContainerControl))).ToArray(); - foreach (Type containertype in containertypes) + else { - string container = containertype.FullName + ", " + typename[1] + ";"; - if (!theme.ContainerControls.Contains(container)) + theme = new Theme { - theme.ContainerControls += container; - } + Name = themeControlType.Name, + Version = new Version(1, 0, 0).ToString() + }; } - - themes[index] = theme; + // set internal properties + theme.ThemeName = themeNamespace; + theme.ThemeControls = ""; + theme.PaneLayouts = ""; + theme.ContainerControls = ""; + theme.AssemblyName = assembly.FullName.Split(",")[0]; + themes.Add(theme); + index = themes.FindIndex(item => item.ThemeName == themeNamespace); } + theme = themes[index]; + theme.ThemeControls += (themeControlType.FullName + ", " + themeControlType.Assembly.GetName().Name + ";"); + + // layouts + Type[] layouttypes = assembly.GetTypes() + .Where(item => item.Namespace != null) + .Where(item => item.Namespace.StartsWith(themeNamespace)) + .Where(item => item.GetInterfaces().Contains(typeof(ILayoutControl))).ToArray(); + foreach (Type layouttype in layouttypes) + { + string panelayout = layouttype.FullName + ", " + themeControlType.Assembly.GetName().Name + ";"; + if (!theme.PaneLayouts.Contains(panelayout)) + { + theme.PaneLayouts += panelayout; + } + } + + // containers + Type[] containertypes = assembly.GetTypes() + .Where(item => item.Namespace != null) + .Where(item => item.Namespace.StartsWith(themeNamespace)) + .Where(item => item.GetInterfaces().Contains(typeof(IContainerControl))).ToArray(); + foreach (Type containertype in containertypes) + { + string container = containertype.FullName + ", " + themeControlType.Assembly.GetName().Name + ";"; + if (!theme.ContainerControls.Contains(container)) + { + theme.ContainerControls += container; + } + } + + themes[index] = theme; } return themes; } diff --git a/Oqtane.Server/wwwroot/Themes/Oqtane.Themes.BlazorTheme/Theme.css b/Oqtane.Server/wwwroot/Themes/Oqtane.Themes.BlazorTheme/Theme.css index c69fc61d..9089259d 100644 --- a/Oqtane.Server/wwwroot/Themes/Oqtane.Themes.BlazorTheme/Theme.css +++ b/Oqtane.Server/wwwroot/Themes/Oqtane.Themes.BlazorTheme/Theme.css @@ -83,6 +83,7 @@ .navbar-toggler { background-color: rgba(255, 255, 255, 0.1); + margin-left: auto; } @media (max-width: 767.98px) { diff --git a/Oqtane.Server/wwwroot/Themes/Oqtane.Themes.OqtaneTheme/Theme.css b/Oqtane.Server/wwwroot/Themes/Oqtane.Themes.OqtaneTheme/Theme.css index 0b093b3f..56bbf2dd 100644 --- a/Oqtane.Server/wwwroot/Themes/Oqtane.Themes.OqtaneTheme/Theme.css +++ b/Oqtane.Server/wwwroot/Themes/Oqtane.Themes.OqtaneTheme/Theme.css @@ -4,6 +4,13 @@ body { padding-top: 7rem; } +.controls { + z-index: 2000; + padding-top: 15px; + padding-bottom: 15px; + margin-right: 10px; +} + .app-menu .nav-item { font-size: 0.9rem; padding-bottom: 0.5rem; @@ -33,3 +40,35 @@ body { vertical-align: text-top; top: -2px; } + +.navbar-toggler { + background-color: rgba(255, 255, 255, 0.1); + margin-left: auto; +} + +@media (max-width: 767px) { + .navbar { + position: fixed; + top: 60px; + width: 100%; + } + + .controls { + height: 60px; + top: 15px; + position: fixed; + top: 0px; + width: 100%; + background-color: rgb(0, 0, 0); + } + + .controls-group { + float: right; + margin-right: 25px; + } + + .container { + position: relative; + top: 30px; + } +} \ No newline at end of file