Performance improvements, refactoring of multi-tenant support, split Alias and Tenant entities for cleaner separation of concerns, create an additional site during installation for demonstratng multitenancy

This commit is contained in:
Shaun Walker
2019-05-24 13:33:19 -04:00
parent 0067521cd5
commit 8deb119f36
57 changed files with 880 additions and 309 deletions

View File

@ -12,7 +12,7 @@
{
if (p.IsNavigation && UserService.IsAuthorized(PageState.User, p.ViewPermissions))
{
string url = PageState.Alias + p.Path;
string url = NavigateUrl(p.Path);
<li class="list-group-item">
<NavLink class="nav-link" href="@url" Match="NavLinkMatch.All">
<span class="oi @p.Icon" aria-hidden="true"></span> @p.Name

View File

@ -39,7 +39,7 @@
{
var interop = new Interop(jsRuntime);
await interop.SetCookie("user", user.UserId.ToString(), 7);
UriHelper.NavigateTo(PageState.Alias, true);
UriHelper.NavigateTo(NavigateUrl(""), true);
}
else
{

View File

@ -3,7 +3,6 @@
@using Oqtane.Services
@using Oqtane.Modules
@using Oqtane.Shared
@using Oqtane.Client.Modules.Controls
@inherits ModuleBase
@inject IUriHelper UriHelper
@inject IPageService PageService
@ -132,11 +131,10 @@
string viewpermissions = "All Users";
string editpermissions = "Administrators";
protected override async Task OnInitAsync()
protected override void OnInit()
{
var Themes = await ThemeService.GetThemesAsync();
themes = ThemeService.GetThemeTypes(Themes);
panelayouts = ThemeService.GetPaneLayoutTypes(Themes);
themes = ThemeService.GetThemeTypes(PageState.Themes);
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes);
}
private async Task SavePage()

View File

@ -3,7 +3,6 @@
@using Oqtane.Services
@using Oqtane.Modules
@using Oqtane.Shared
@using Oqtane.Client.Modules.Controls
@inherits ModuleBase
@inject IUriHelper UriHelper
@inject IPageService PageService
@ -133,11 +132,10 @@
string viewpermissions;
string editpermissions;
protected override async Task OnInitAsync()
protected override void OnInit()
{
List<Theme> Themes = await ThemeService.GetThemesAsync();
themes = ThemeService.GetThemeTypes(Themes);
panelayouts = ThemeService.GetPaneLayoutTypes(Themes);
themes = ThemeService.GetThemeTypes(PageState.Themes);
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes);
PageId = Int32.Parse(PageState.QueryString["id"]);
Page p = PageState.Pages.Where(item => item.PageId == PageId).FirstOrDefault();
@ -159,6 +157,6 @@
private async Task DeletePage()
{
await PageService.DeletePageAsync(Int32.Parse(PageState.QueryString["id"]));
UriHelper.NavigateTo(PageState.Alias);
UriHelper.NavigateTo(NavigateUrl("", true));
}
}

View File

@ -133,11 +133,10 @@
string viewpermissions;
string editpermissions;
protected override async Task OnInitAsync()
protected override void OnInit()
{
List<Theme> Themes = await ThemeService.GetThemesAsync();
themes = ThemeService.GetThemeTypes(Themes);
panelayouts = ThemeService.GetPaneLayoutTypes(Themes);
themes = ThemeService.GetThemeTypes(PageState.Themes);
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes);
PageId = Int32.Parse(PageState.QueryString["id"]);
Page p = PageState.Pages.Where(item => item.PageId == PageId).FirstOrDefault();

View File

@ -3,10 +3,11 @@
@using Oqtane.Client.Modules.HtmlText.Services
@using Oqtane.Shared.Modules.HtmlText.Models
@using System.Net.Http;
@using Oqtane.Client.Modules.Controls
@using Oqtane.Shared;
@inherits ModuleBase
@inject IUriHelper UriHelper
@inject HttpClient http
@inject SiteState sitestate
<form>
<table class="form-group">
@ -32,7 +33,7 @@
protected override async Task OnInitAsync()
{
HtmlTextService htmltextservice = new HtmlTextService(http, UriHelper);
HtmlTextService htmltextservice = new HtmlTextService(http, sitestate);
List<HtmlTextInfo> htmltextlist = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
if (htmltextlist != null)
{
@ -43,7 +44,7 @@
private async Task SaveContent()
{
HtmlTextService htmltextservice = new HtmlTextService(http, UriHelper);
HtmlTextService htmltextservice = new HtmlTextService(http, sitestate);
if (htmltext != null)
{
htmltext.Content = content;

View File

@ -3,9 +3,10 @@
@using Oqtane.Shared.Modules.HtmlText.Models
@using System.Net.Http;
@using Oqtane.Client.Modules.Controls
@using Oqtane.Shared;
@inherits ModuleBase
@inject HttpClient http
@inject IUriHelper UriHelper
@inject SiteState sitestate
@((MarkupString)content)
@ -16,7 +17,7 @@
protected override async Task OnInitAsync()
{
HtmlTextService htmltextservice = new HtmlTextService(http, UriHelper);
HtmlTextService htmltextservice = new HtmlTextService(http, sitestate);
List<HtmlTextInfo> htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
if (htmltext != null)
{

View File

@ -5,18 +5,24 @@ using System.Net.Http;
using Microsoft.AspNetCore.Components;
using Oqtane.Services;
using Oqtane.Shared.Modules.HtmlText.Models;
using Oqtane.Shared;
namespace Oqtane.Client.Modules.HtmlText.Services
{
public class HtmlTextService : ServiceBase, IHtmlTextService
{
private readonly HttpClient http;
private readonly string apiurl;
private readonly SiteState sitestate;
public HtmlTextService(HttpClient http, IUriHelper urihelper)
public HtmlTextService(HttpClient http, SiteState sitestate)
{
this.http = http;
apiurl = CreateApiUrl(urihelper.GetAbsoluteUri(), "HtmlText");
this.sitestate = sitestate;
}
private string apiurl
{
get { return CreateApiUrl(sitestate.Alias, "HtmlText"); }
}
public async Task<List<HtmlTextInfo>> GetHtmlTextAsync(int ModuleId)

View File

@ -20,46 +20,32 @@ namespace Oqtane.Modules
public string NavigateUrl()
{
return NavigateUrl(PageState.Page.Path, false);
return Utilities.NavigateUrl(PageState);
}
public string NavigateUrl(bool reload)
{
return NavigateUrl(PageState.Page.Path, reload);
return Utilities.NavigateUrl(PageState, reload);
}
public string NavigateUrl(string path)
{
return NavigateUrl(path, false);
return Utilities.NavigateUrl(PageState, path);
}
public string NavigateUrl(string path, bool reload)
{
string url = PageState.Alias + path;
if (reload)
{
url += "?reload=true";
}
return url;
return Utilities.NavigateUrl(PageState, path, reload);
}
public string EditUrl(string action)
{
return EditUrl(action, "");
return Utilities.EditUrl(PageState, ModuleState, action, "");
}
public string EditUrl(string action, string parameters)
{
string url = PageState.Alias + PageState.Page.Path + "?mid=" + ModuleState.ModuleId.ToString();
if (action != "")
{
url += "&ctl=" + action;
}
if (!string.IsNullOrEmpty(parameters))
{
url += "&" + parameters;
}
return url;
return Utilities.EditUrl(PageState, ModuleState, action, parameters);
}
}
}

View File

@ -0,0 +1,53 @@
using Oqtane.Models;
using System.Threading.Tasks;
using System.Net.Http;
using System.Linq;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Oqtane.Shared;
namespace Oqtane.Services
{
public class AliasService : ServiceBase, IAliasService
{
private readonly HttpClient http;
private readonly IUriHelper urihelper;
public AliasService(HttpClient http, IUriHelper urihelper)
{
this.http = http;
this.urihelper = urihelper;
}
private string apiurl
{
get { return CreateApiUrl(urihelper.GetAbsoluteUri(), "Alias"); }
}
public async Task<List<Alias>> GetAliasesAsync()
{
List<Alias> aliases = await http.GetJsonAsync<List<Alias>>(apiurl);
return aliases.OrderBy(item => item.Name).ToList();
}
public async Task<Alias> GetAliasAsync(int AliasId)
{
List<Alias> aliases = await http.GetJsonAsync<List<Alias>>(apiurl);
return aliases.Where(item => item.AliasId == AliasId).FirstOrDefault();
}
public async Task AddAliasAsync(Alias alias)
{
await http.PostJsonAsync(apiurl, alias);
}
public async Task UpdateAliasAsync(Alias alias)
{
await http.PutJsonAsync(apiurl + "/" + alias.AliasId.ToString(), alias);
}
public async Task DeleteAliasAsync(int AliasId)
{
await http.DeleteAsync(apiurl + "/" + AliasId.ToString());
}
}
}

View File

@ -0,0 +1,19 @@
using Oqtane.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Oqtane.Services
{
public interface IAliasService
{
Task<List<Alias>> GetAliasesAsync();
Task<Alias> GetAliasAsync(int AliasId);
Task AddAliasAsync(Alias alias);
Task UpdateAliasAsync(Alias alias);
Task DeleteAliasAsync(int AliasId);
}
}

View File

@ -6,54 +6,56 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using System;
using System.Reflection;
using Oqtane.Shared;
namespace Oqtane.Services
{
public class ModuleDefinitionService : ServiceBase, IModuleDefinitionService
{
private readonly HttpClient http;
private readonly string apiurl;
private readonly SiteState sitestate;
private List<ModuleDefinition> moduledefinitions;
public ModuleDefinitionService(HttpClient http, IUriHelper urihelper)
public ModuleDefinitionService(HttpClient http, SiteState sitestate)
{
this.http = http;
apiurl = CreateApiUrl(urihelper.GetAbsoluteUri(), "ModuleDefinition");
this.sitestate = sitestate;
}
private string apiurl
{
get { return CreateApiUrl(sitestate.Alias, "ModuleDefinition"); }
}
public async Task<List<ModuleDefinition>> GetModuleDefinitionsAsync()
{
if (moduledefinitions == null)
List<ModuleDefinition> moduledefinitions = await http.GetJsonAsync<List<ModuleDefinition>>(apiurl);
// get list of loaded assemblies
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (ModuleDefinition moduledefinition in moduledefinitions)
{
moduledefinitions = await http.GetJsonAsync<List<ModuleDefinition>>(apiurl);
// get list of loaded assemblies
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (ModuleDefinition moduledefinition in moduledefinitions)
if (moduledefinition.Dependencies != "")
{
if (moduledefinition.Dependencies != "")
foreach (string dependency in moduledefinition.Dependencies.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
{
foreach (string dependency in moduledefinition.Dependencies.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
string assemblyname = dependency.Replace(".dll", "");
if (assemblies.Where(item => item.FullName.StartsWith(assemblyname + ",")).FirstOrDefault() == null)
{
string assemblyname = dependency.Replace(".dll", "");
if (assemblies.Where(item => item.FullName.StartsWith(assemblyname + ",")).FirstOrDefault() == null)
{
// download assembly from server and load
var bytes = await http.GetByteArrayAsync("_framework/_bin/" + assemblyname + ".dll");
Assembly.Load(bytes);
}
// download assembly from server and load
var bytes = await http.GetByteArrayAsync("_framework/_bin/" + assemblyname + ".dll");
Assembly.Load(bytes);
}
}
if (assemblies.Where(item => item.FullName.StartsWith(moduledefinition.AssemblyName + ",")).FirstOrDefault() == null)
{
// download assembly from server and load
var bytes = await http.GetByteArrayAsync("_framework/_bin/" + moduledefinition.AssemblyName + ".dll");
Assembly.Load(bytes);
}
}
if (assemblies.Where(item => item.FullName.StartsWith(moduledefinition.AssemblyName + ",")).FirstOrDefault() == null)
{
// download assembly from server and load
var bytes = await http.GetByteArrayAsync("_framework/_bin/" + moduledefinition.AssemblyName + ".dll");
Assembly.Load(bytes);
}
}
return moduledefinitions.OrderBy(item => item.Name).ToList();
}
}

View File

@ -4,18 +4,24 @@ using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Oqtane.Shared;
namespace Oqtane.Services
{
public class ModuleService : ServiceBase, IModuleService
{
private readonly HttpClient http;
private readonly string apiurl;
private readonly SiteState sitestate;
public ModuleService(HttpClient http, IUriHelper urihelper)
public ModuleService(HttpClient http, SiteState sitestate)
{
this.http = http;
apiurl = CreateApiUrl(urihelper.GetAbsoluteUri(), "Module");
this.sitestate = sitestate;
}
private string apiurl
{
get { return CreateApiUrl(sitestate.Alias, "Module"); }
}
public async Task<List<Module>> GetModulesAsync(int PageId)

View File

@ -4,18 +4,24 @@ using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Oqtane.Shared;
namespace Oqtane.Services
{
public class PageModuleService : ServiceBase, IPageModuleService
{
private readonly HttpClient http;
private readonly string apiurl;
private readonly SiteState sitestate;
public PageModuleService(HttpClient http, IUriHelper urihelper)
public PageModuleService(HttpClient http, SiteState sitestate)
{
this.http = http;
apiurl = CreateApiUrl(urihelper.GetAbsoluteUri(), "PageModule");
this.sitestate = sitestate;
}
private string apiurl
{
get { return CreateApiUrl(sitestate.Alias, "PageModule"); }
}
public async Task<List<PageModule>> GetPageModulesAsync()

View File

@ -4,18 +4,24 @@ using System.Linq;
using System.Net.Http;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Oqtane.Shared;
namespace Oqtane.Services
{
public class PageService : ServiceBase, IPageService
{
private readonly HttpClient http;
private readonly string apiurl;
private readonly SiteState sitestate;
public PageService(HttpClient http, IUriHelper urihelper)
public PageService(HttpClient http, SiteState sitestate)
{
this.http = http;
apiurl = CreateApiUrl(urihelper.GetAbsoluteUri(), "Page");
this.sitestate = sitestate;
}
private string apiurl
{
get { return CreateApiUrl(sitestate.Alias, "Page"); }
}
public async Task<List<Page>> GetPagesAsync(int SiteId)

View File

@ -1,20 +1,24 @@
using System;
using Oqtane.Models;
using Oqtane.Shared;
namespace Oqtane.Services
{
public class ServiceBase
{
// method for alias agnostic api call
public string CreateApiUrl(string absoluteUri, string serviceName)
{
Uri uri = new Uri(absoluteUri);
string apiurl = uri.Scheme + "://" + uri.Authority + "/";
string alias = Utilities.GetAlias(absoluteUri);
if (alias != "")
{
apiurl += alias;
}
else
string apiurl = uri.Scheme + "://" + uri.Authority + "/~/api/" + serviceName;
return apiurl;
}
// method for alias specific api call
public string CreateApiUrl(Alias alias, string serviceName)
{
string apiurl = alias.Url + "/";
if (alias.Path == "")
{
apiurl += "~/";
}

View File

@ -4,18 +4,24 @@ using System.Net.Http;
using System.Linq;
using Microsoft.AspNetCore.Components;
using System.Collections.Generic;
using Oqtane.Shared;
namespace Oqtane.Services
{
public class SiteService : ServiceBase, ISiteService
{
private readonly HttpClient http;
private readonly string apiurl;
private readonly SiteState sitestate;
public SiteService(HttpClient http, IUriHelper urihelper)
public SiteService(HttpClient http, SiteState sitestate)
{
this.http = http;
apiurl = CreateApiUrl(urihelper.GetAbsoluteUri(), "Site");
this.sitestate = sitestate;
}
private string apiurl
{
get { return CreateApiUrl(sitestate.Alias, "Site"); }
}
public async Task<List<Site>> GetSitesAsync()

View File

@ -2,18 +2,24 @@
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Oqtane.Shared;
namespace Oqtane.Services
{
public class TenantService : ServiceBase, ITenantService
{
private readonly HttpClient http;
private readonly string apiurl;
private readonly SiteState sitestate;
public TenantService(HttpClient http, IUriHelper urihelper)
public TenantService(HttpClient http, SiteState sitestate)
{
this.http = http;
apiurl = CreateApiUrl(urihelper.GetAbsoluteUri(), "Tenant");
this.sitestate = sitestate;
}
private string apiurl
{
get { return CreateApiUrl(sitestate.Alias, "Tenant"); }
}
public async Task<Tenant> GetTenantAsync()

View File

@ -13,48 +13,49 @@ namespace Oqtane.Services
public class ThemeService : ServiceBase, IThemeService
{
private readonly HttpClient http;
private readonly string apiurl;
private readonly SiteState sitestate;
private List<Theme> themes;
public ThemeService(HttpClient http, IUriHelper urihelper)
public ThemeService(HttpClient http, SiteState sitestate)
{
this.http = http;
apiurl = CreateApiUrl(urihelper.GetAbsoluteUri(), "Theme");
this.sitestate = sitestate;
}
//TODO: Implement Caching or otherwise on this, and other calls within this class
private string apiurl
{
get { return CreateApiUrl(sitestate.Alias, "Theme"); }
}
public async Task<List<Theme>> GetThemesAsync()
{
if (themes == null)
List<Theme> themes = await http.GetJsonAsync<List<Theme>>(apiurl);
// get list of loaded assemblies
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Theme theme in themes)
{
themes = await http.GetJsonAsync<List<Theme>>(apiurl);
// get list of loaded assemblies
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Theme theme in themes)
if (theme.Dependencies != "")
{
if (theme.Dependencies != "")
foreach (string dependency in theme.Dependencies.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
{
foreach (string dependency in theme.Dependencies.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
string assemblyname = dependency.Replace(".dll", "");
if (assemblies.Where(item => item.FullName.StartsWith(assemblyname + ",")).FirstOrDefault() == null)
{
string assemblyname = dependency.Replace(".dll", "");
if (assemblies.Where(item => item.FullName.StartsWith(assemblyname + ",")).FirstOrDefault() == null)
{
// download assembly from server and load
var bytes = await http.GetByteArrayAsync("_framework/_bin/" + assemblyname + ".dll");
Assembly.Load(bytes);
}
// download assembly from server and load
var bytes = await http.GetByteArrayAsync("_framework/_bin/" + assemblyname + ".dll");
Assembly.Load(bytes);
}
}
if (assemblies.Where(item => item.FullName.StartsWith(theme.AssemblyName + ",")).FirstOrDefault() == null)
{
// download assembly from server and load
var bytes = await http.GetByteArrayAsync("_framework/_bin/" + theme.AssemblyName + ".dll");
Assembly.Load(bytes);
}
}
if (assemblies.Where(item => item.FullName.StartsWith(theme.AssemblyName + ",")).FirstOrDefault() == null)
{
// download assembly from server and load
var bytes = await http.GetByteArrayAsync("_framework/_bin/" + theme.AssemblyName + ".dll");
Assembly.Load(bytes);
}
}
return themes.OrderBy(item => item.Name).ToList();
}

View File

@ -12,12 +12,17 @@ namespace Oqtane.Services
public class UserService : ServiceBase, IUserService
{
private readonly HttpClient http;
private readonly string apiurl;
private readonly SiteState sitestate;
public UserService(HttpClient http, IUriHelper urihelper)
public UserService(HttpClient http, SiteState sitestate)
{
this.http = http;
apiurl = CreateApiUrl(urihelper.GetAbsoluteUri(), "User");
this.sitestate = sitestate;
}
private string apiurl
{
get { return CreateApiUrl(sitestate.Alias, "User"); }
}
public async Task<List<User>> GetUsersAsync()

View File

@ -6,7 +6,10 @@ namespace Oqtane.Shared
{
public class PageState
{
public string Alias { get; set; }
public List<ModuleDefinition> ModuleDefinitions { get; set; }
public List<Theme> Themes { get; set; }
public List<Alias> Aliases { get; set; }
public Alias Alias { get; set; }
public Site Site { get; set; }
public List<Page> Pages { get; set; }
public Page Page { get; set; }
@ -16,6 +19,5 @@ namespace Oqtane.Shared
public Dictionary<string, string> QueryString { get; set; }
public int ModuleId { get; set; }
public string Control { get; set; }
public string Mode { get; set; }
}
}

View File

@ -5,8 +5,10 @@
@using System.Collections.Generic
@using Oqtane.Shared
@using Microsoft.JSInterop
@inject SiteState SiteState
@inject IUriHelper UriHelper
@inject IJSRuntime jsRuntime
@inject IAliasService AliasService
@inject ITenantService TenantService
@inject ISiteService SiteService
@inject IPageService PageService
@ -25,12 +27,6 @@
RenderFragment DynamicComponent { get; set; }
private string _absoluteUri;
string alias;
Site site;
List<Page> pages;
Page page;
User user;
List<Module> modules;
PageState pagestate;
protected override void OnInit()
@ -63,33 +59,51 @@
private async Task Refresh()
{
List<ModuleDefinition> moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync();
List<Models.Theme> themes = await ThemeService.GetThemesAsync();
List<ModuleDefinition> moduledefinitions;
List<Models.Theme> themes;
List<Alias> aliases;
Alias alias;
Site site;
List<Page> pages;
Page page;
User user;
List<Module> modules;
bool reload = false;
if (PageState == null)
{
Tenant tenant = await TenantService.GetTenantAsync();
site = await SiteService.GetSiteAsync(tenant.SiteId);
alias = Utilities.GetAlias(_absoluteUri);
aliases = await AliasService.GetAliasesAsync();
alias = null;
}
else
{
site = PageState.Site;
aliases = PageState.Aliases;
alias = PageState.Alias;
}
if (Utilities.GetAlias(_absoluteUri) != alias)
if (alias == null || GetAlias(_absoluteUri, aliases).Name != alias.Name)
{
Tenant tenant = await TenantService.GetTenantAsync();
site = await SiteService.GetSiteAsync(tenant.SiteId);
alias = Utilities.GetAlias(_absoluteUri);
alias = GetAlias(_absoluteUri, aliases);
SiteState.Alias = alias; // set state for services
reload = true;
}
if (site != null)
if (PageState == null || reload == true)
{
moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync();
themes = await ThemeService.GetThemesAsync();
site = await SiteService.GetSiteAsync(alias.SiteId);
}
else
{
moduledefinitions = PageState.ModuleDefinitions;
themes = PageState.Themes;
site = PageState.Site;
}
if (site != null || reload == true)
{
var interop = new Interop(jsRuntime);
string userid = await interop.GetCookie("user");
user = null;
if (PageState == null || reload == true)
{
if (!string.IsNullOrEmpty(userid))
@ -120,9 +134,11 @@
}
string path = new Uri(_absoluteUri).PathAndQuery.Substring(1);
if (alias != "")
if (path.EndsWith("/")) { path = path.Substring(0, path.Length - 1); }
if (alias.Path != "")
{
path = path.Replace(alias, "");
path = path.Replace(alias.Path, "");
if (path.StartsWith("/")) { path = path.Substring(1); }
}
Dictionary<string, string> querystring = ParseQueryString(path);
@ -165,6 +181,9 @@
if (UserService.IsAuthorized(user, page.ViewPermissions))
{
pagestate = new PageState();
pagestate.ModuleDefinitions = moduledefinitions;
pagestate.Themes = themes;
pagestate.Aliases = aliases;
pagestate.Alias = alias;
pagestate.Site = site;
pagestate.Pages = pages;
@ -174,7 +193,6 @@
pagestate.QueryString = querystring;
pagestate.ModuleId = -1;
pagestate.Control = "";
pagestate.Mode = "client";
if (querystring.ContainsKey("mid"))
{
@ -309,4 +327,32 @@
return modules;
}
private Alias GetAlias(string absoluteUri, List<Alias> aliases)
{
string aliasname;
Alias alias = null;
Uri uri = new Uri(absoluteUri);
if (uri.Segments.Count() > 1)
{
// check if first path segment is an alias ( ie. a subfolder - www.domain.com/subfolder )
aliasname = uri.Authority + "/" + uri.Segments[1];
if (aliasname.EndsWith("/")) { aliasname = aliasname.Substring(0, aliasname.Length - 1); }
alias = aliases.Where(item => item.Name == aliasname).FirstOrDefault();
}
if (alias == null)
{
aliasname = uri.Authority;
alias = aliases.Where(item => item.Name == aliasname).FirstOrDefault();
}
if (alias == null && aliases.Count > 0)
{
// use first alias if Uri does not exist
alias = aliases.FirstOrDefault();
}
alias.Scheme = uri.Scheme;
return alias;
}
}

View File

@ -0,0 +1,11 @@
using Oqtane.Models;
namespace Oqtane.Shared
{
// this class is used for passing state between Blazor components and Services
public class SiteState
{
public Alias Alias { get; set; }
}
}

View File

@ -1,18 +1,52 @@
using System;
using Oqtane.Models;
namespace Oqtane.Shared
{
public class Utilities
{
public static string GetAlias(string absoluteUri)
public static string NavigateUrl(PageState pagestate)
{
string alias = "";
Uri uri = new Uri(absoluteUri);
if (uri.AbsolutePath.StartsWith("/~"))
return NavigateUrl(pagestate, pagestate.Page.Path, false);
}
public static string NavigateUrl(PageState pagestate, bool reload)
{
return NavigateUrl(pagestate, pagestate.Page.Path, reload);
}
public static string NavigateUrl(PageState pagestate, string path)
{
return NavigateUrl(pagestate, path, false);
}
public static string NavigateUrl(PageState pagestate, string path, bool reload)
{
string url = pagestate.Alias.Path + "/" + path;
if (reload)
{
alias = uri.Segments[1];
url += "?reload=true";
}
return alias;
return url;
}
public static string EditUrl(PageState pagestate, Module modulestate, string action)
{
return EditUrl(pagestate, modulestate, action, "");
}
public static string EditUrl(PageState pagestate, Module modulestate, string action, string parameters)
{
string url = pagestate.Alias.Path + "/" + pagestate.Page.Path + "?mid=" + modulestate.ModuleId.ToString();
if (action != "")
{
url += "&ctl=" + action;
}
if (!string.IsNullOrEmpty(parameters))
{
url += "&" + parameters;
}
return url;
}
public static string GetTypeNameClass(string typename)

View File

@ -1,5 +1,3 @@
#define ServerSideBlazor
using Microsoft.AspNetCore.Components.Builder;
using Microsoft.Extensions.DependencyInjection;
using System;
@ -9,6 +7,7 @@ using System.Net.Http;
using Microsoft.AspNetCore.Components;
using System.Reflection;
using Oqtane.Modules;
using Oqtane.Shared;
namespace Oqtane.Client
{
@ -28,11 +27,11 @@ namespace Oqtane.Client
#if WASM
public void ConfigureServices(IServiceCollection services)
{
// register singleton core services
services.AddSingleton<IModuleDefinitionService, ModuleDefinitionService>();
services.AddSingleton<IThemeService, ThemeService>();
// register scoped core services
services.AddScoped<SiteState>();
services.AddScoped<IModuleDefinitionService, ModuleDefinitionService>();
services.AddScoped<IThemeService, ThemeService>();
services.AddScoped<IAliasService, AliasService>();
services.AddScoped<ITenantService, TenantService>();
services.AddScoped<ISiteService, SiteService>();
services.AddScoped<IPageService, PageService>();

View File

@ -25,7 +25,7 @@
protected override void OnInit()
{
closeurl = PageState.Alias + PageState.Page.Path;
closeurl = NavigateUrl();
}
}

View File

@ -13,5 +13,35 @@ namespace Oqtane.Themes
protected Module ModuleState { get; set; }
public virtual string Name { get; set; }
public string NavigateUrl()
{
return Utilities.NavigateUrl(PageState);
}
public string NavigateUrl(bool reload)
{
return Utilities.NavigateUrl(PageState, reload);
}
public string NavigateUrl(string path)
{
return Utilities.NavigateUrl(PageState, path);
}
public string NavigateUrl(string path, bool reload)
{
return Utilities.NavigateUrl(PageState, path, reload);
}
public string EditUrl(string action)
{
return Utilities.EditUrl(PageState, ModuleState, action, "");
}
public string EditUrl(string action, string parameters)
{
return Utilities.EditUrl(PageState, ModuleState, action, parameters);
}
}
}

View File

@ -74,7 +74,7 @@
string display = "display: none";
List<ModuleDefinition> moduledefinitions;
Dictionary<string, string> containers = new Dictionary<string, string>();
int pagemanagementmoduleid;
int pagemanagementmoduleid = -1;
string moduledefinitionname;
string pane;
string title = "";
@ -82,11 +82,13 @@
protected override async Task OnInitAsync()
{
//TODO: Move this to shared component. This is used in this control Add, Edit, and Delete controls as well
moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync();
containers = ThemeService.GetContainerTypes(await ThemeService.GetThemesAsync());
moduledefinitions = PageState.ModuleDefinitions;
containers = ThemeService.GetContainerTypes(PageState.Themes);
List<Module> modules = await ModuleService.GetModulesAsync(PageState.Site.SiteId, Constants.PageManagementModule);
pagemanagementmoduleid = modules.FirstOrDefault().ModuleId;
if (modules.Count > 0)
{
pagemanagementmoduleid = modules.FirstOrDefault().ModuleId;
}
if (UserService.IsAuthorized(PageState.User, PageState.Page.EditPermissions))
{
display = "display: inline";
@ -117,23 +119,26 @@
pagemodule.Order = 0;
pagemodule.ContainerType = containertype;
await PageModuleService.AddPageModuleAsync(pagemodule);
UriHelper.NavigateTo(PageState.Alias + PageState.Page.Path + "?reload=true");
UriHelper.NavigateTo(NavigateUrl(true));
}
private string PageUrl(string action)
{
string url = "";
switch (action)
if (pagemanagementmoduleid != -1)
{
case "Add":
url = "admin/pages?mid=" + pagemanagementmoduleid.ToString() + "&ctl=" + action;
break;
case "Edit":
url = "admin/pages?mid=" + pagemanagementmoduleid.ToString() + "&ctl=" + action + "&id=" + PageState.Page.PageId.ToString();
break;
case "Delete":
url = "admin/pages?mid=" + pagemanagementmoduleid.ToString() + "&ctl=" + action + "&id=" + PageState.Page.PageId.ToString();
break;
switch (action)
{
case "Add":
url = "admin/pages?mid=" + pagemanagementmoduleid.ToString() + "&ctl=" + action;
break;
case "Edit":
url = "admin/pages?mid=" + pagemanagementmoduleid.ToString() + "&ctl=" + action + "&id=" + PageState.Page.PageId.ToString();
break;
case "Delete":
url = "admin/pages?mid=" + pagemanagementmoduleid.ToString() + "&ctl=" + action + "&id=" + PageState.Page.PageId.ToString();
break;
}
}
return url;
}

View File

@ -29,13 +29,13 @@
{
if (name == "Login")
{
UriHelper.NavigateTo(PageState.Alias + "login");
UriHelper.NavigateTo(NavigateUrl("login"));
}
else
{
var interop = new Interop(jsRuntime);
await interop.SetCookie("user", "", 7);
UriHelper.NavigateTo(PageState.Alias, true);
UriHelper.NavigateTo(NavigateUrl(""), true);
}
}
}

View File

@ -1,5 +1,5 @@
@using Oqtane.Themes
@inherits ThemeObjectBase
<a href="@PageState.Uri.Scheme://@PageState.Uri.Authority"><img src="/Sites/@PageState.Site.SiteId/@PageState.Site.Logo" /></a>
<a href="@PageState.Alias.Url"><img src="/Sites/@PageState.Site.SiteId/@PageState.Site.Logo" /></a>

View File

@ -9,7 +9,7 @@
<ul class="nav flex-column">
@if (parent != null)
{
string url = PageState.Alias + parent.Path;
string url = NavigateUrl();
<li class="nav-item px-3">
<NavLink class="nav-link" href="@parent.Path" Match="NavLinkMatch.All">
<span class="oi oi-media-skip-backward" aria-hidden="true"></span> Back
@ -20,7 +20,7 @@
{
if (p.IsNavigation && UserService.IsAuthorized(PageState.User, p.ViewPermissions))
{
string url = PageState.Alias + p.Path;
string url = NavigateUrl(p.Path);
<li class="nav-item px-3">
<NavLink class="nav-link" href="@url" Match="NavLinkMatch.All">
<span class="oi @p.Icon" aria-hidden="true"></span> @p.Name

View File

@ -1,44 +0,0 @@
@using Oqtane.Themes
@using Oqtane.Shared;
@using Microsoft.JSInterop
@inject IJSRuntime jsRuntime
@inherits ThemeObjectBase
<button type="button" class="btn btn-primary" onclick="@SetMode">
@displayMode
</button>
@functions {
string displayMode = "";
protected override async Task OnInitAsync()
{
var interop = new Interop(jsRuntime);
string value = await interop.GetCookie("blazor");
if (value == "client")
{
displayMode = "Server Mode";
}
else
{
displayMode = "Client Mode";
}
}
public async void SetMode()
{
var interop = new Interop(jsRuntime);
string mode = await interop.GetCookie("blazor");
if (mode == "client")
{
mode = "server";
}
else
{
mode = "client";
}
await interop.SetCookie("blazor", mode, 7);
}
}

View File

@ -81,7 +81,7 @@
await PageModuleService.UpdatePageModuleAsync(pagemodule);
break;
}
UriHelper.NavigateTo(PageState.Alias + path);
UriHelper.NavigateTo(NavigateUrl(path));
}
public class ActionViewModel

View File

@ -9,5 +9,26 @@ namespace Oqtane.Themes
protected PageState PageState { get; set; }
public virtual string Name { get; set; }
public virtual string Panes { get; set; }
public string NavigateUrl()
{
return Utilities.NavigateUrl(PageState);
}
public string NavigateUrl(bool reload)
{
return Utilities.NavigateUrl(PageState, reload);
}
public string NavigateUrl(string path)
{
return Utilities.NavigateUrl(PageState, path);
}
public string NavigateUrl(string path, bool reload)
{
return Utilities.NavigateUrl(PageState, path, reload);
}
}
}

View File

@ -7,5 +7,25 @@ namespace Oqtane.Themes
{
[CascadingParameter]
protected PageState PageState { get; set; }
public string NavigateUrl()
{
return Utilities.NavigateUrl(PageState);
}
public string NavigateUrl(bool reload)
{
return Utilities.NavigateUrl(PageState, reload);
}
public string NavigateUrl(string path)
{
return Utilities.NavigateUrl(PageState, path);
}
public string NavigateUrl(string path, bool reload)
{
return Utilities.NavigateUrl(PageState, path, reload);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -21,15 +21,7 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<script id="blazor"></script>
<script>
var src = "_framework/blazor.webassembly.js";
var blazor = getCookie("blazor");
if (blazor === "server") {
src = "_framework/components.server.js";
}
document.getElementById("blazor").src = src;
</script>
<script src="_framework/blazor.webassembly.js"></script>
</body>
</html>

View File

@ -1,20 +1,3 @@
/* called by index.html to check if mode is set */
function getCookie(name) {
name = name + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) === ' ') {
c = c.substring(1);
}
if (c.indexOf(name) === 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
/* Open when someone clicks on the span element */
function openActions() {
document.getElementById("actions").style.width = "25%";