@using System @using Oqtane.Services @using Oqtane.Models @using System.Linq @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 @inject IUserService UserService @inject IModuleService ModuleService @inject IModuleDefinitionService ModuleDefinitionService @inject IThemeService ThemeService @DynamicComponent @functions { [CascadingParameter] PageState PageState { get; set; } [Parameter] Action OnStateChange { get; set; } RenderFragment DynamicComponent { get; set; } private string _absoluteUri; PageState pagestate; protected override void OnInit() { _absoluteUri = UriHelper.GetAbsoluteUri(); UriHelper.OnLocationChanged += OnLocationChanged; DynamicComponent = builder => { if (pagestate != null) { builder.OpenComponent(0, Type.GetType(Constants.DefaultPage)); builder.CloseComponent(); } }; } public void Dispose() { UriHelper.OnLocationChanged -= OnLocationChanged; } protected override async Task OnParametersSetAsync() { if (PageState == null) { await Refresh(); } } private async Task Refresh() { List moduledefinitions; List themes; List aliases; Alias alias; Site site; List pages; Page page; User user; List modules; bool reload = false; if (PageState == null) { aliases = await AliasService.GetAliasesAsync(); alias = null; } else { aliases = PageState.Aliases; alias = PageState.Alias; } if (alias == null || GetAlias(_absoluteUri, aliases).Name != alias.Name) { alias = GetAlias(_absoluteUri, aliases); SiteState.Alias = alias; // set state for services reload = true; } 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)) { user = await UserService.GetUserAsync(int.Parse(userid)); } } else { user = PageState.User; } if (!string.IsNullOrEmpty(userid)) { if (user != null && user.UserId != int.Parse(userid)) { user = await UserService.GetUserAsync(int.Parse(userid)); } // this is a hack for server-side Blazor where JSInterop is not working OnInit() which means the userid is not being retrieved from the cookie on the initial render and is not being loaded into PageState if (user == null) { user = await UserService.GetUserAsync(int.Parse(userid)); } } else { user = null; } string path = new Uri(_absoluteUri).PathAndQuery.Substring(1); if (path.EndsWith("/")) { path = path.Substring(0, path.Length - 1); } if (alias.Path != "") { path = path.Replace(alias.Path, ""); if (path.StartsWith("/")) { path = path.Substring(1); } } Dictionary querystring = ParseQueryString(path); if (querystring.ContainsKey("reload")) { reload = true; } if (PageState == null || reload == true) { pages = await PageService.GetPagesAsync(site.SiteId); } else { pages = PageState.Pages; } if (path.IndexOf("?") != -1) { path = path.Substring(0, path.IndexOf("?")); } if (PageState == null || reload == true) { page = pages.Where(item => item.Path == path).FirstOrDefault(); } else { page = PageState.Page; } if (page.Path != path) { page = pages.Where(item => item.Path == path).FirstOrDefault(); reload = true; } if (page != null) { // check if user is authorized to view page 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; pagestate.Page = page; pagestate.User = user; pagestate.Uri = new Uri(_absoluteUri, UriKind.Absolute); pagestate.QueryString = querystring; pagestate.ModuleId = -1; pagestate.Control = ""; if (querystring.ContainsKey("mid")) { pagestate.ModuleId = int.Parse(querystring["mid"]); } if (querystring.ContainsKey("ctl")) { pagestate.Control = querystring["ctl"]; } if (PageState != null && (PageState.ModuleId != pagestate.ModuleId || PageState.Control != pagestate.Control)) { reload = true; } if (PageState == null || reload == true) { modules = await ModuleService.GetModulesAsync(page.PageId); modules = ProcessModules(modules, moduledefinitions, pagestate.Control, page.Panes); } else { modules = PageState.Modules; } pagestate.Modules = modules; OnStateChange?.Invoke(pagestate); } else { // user is not authorized to view page } } else { // page does not exist } } else { // site does not exist } } private async void OnLocationChanged(object sender, string AbsoluteUri) { _absoluteUri = AbsoluteUri; await LocationChanged(); } public async Task LocationChanged() { await Refresh(); } private Dictionary ParseQueryString(string path) { Dictionary querystring = new Dictionary(); if (path.IndexOf("?") != -1) { foreach (string kvp in path.Substring(path.IndexOf("?") + 1).Split('&')) { if (kvp != "") { if (kvp.Contains("=")) { string[] pair = kvp.Split('='); querystring.Add(pair[0], pair[1]); } else { querystring.Add(kvp, "true"); // default querystring when no value is provided } } } } return querystring; } private List ProcessModules(List modules, List moduledefinitions, string control, string panes) { ModuleDefinition moduledefinition; if (control == "") { control = Constants.DefaultControl; } Dictionary paneindex = new Dictionary(); foreach (Module module in modules) { // set the type based on the template and action moduledefinition = moduledefinitions.Where(item => item.ModuleDefinitionName == module.ModuleDefinitionName).FirstOrDefault(); if (moduledefinition != null) { string typename = moduledefinition.ControlTypeTemplate; if (moduledefinition.ControlTypeRoutes != "") { foreach (string route in moduledefinition.ControlTypeRoutes.Split(';')) { if (route.StartsWith(control + "=")) { typename = route.Replace(control + "=", ""); } } } module.ModuleType = typename.Replace("{Control}", control); } // ensure module's pane exists in current page and if not, assign it to the Admin pane if (!panes.Contains(module.Pane)) { module.Pane = Constants.AdminPane; } // calculate module position within pane if (paneindex.ContainsKey(module.Pane)) { paneindex[module.Pane] += 1; } else { paneindex.Add(module.Pane, 0); } module.PaneModuleIndex = paneindex[module.Pane]; } foreach (Module module in modules) { module.PaneModuleCount = paneindex[module.Pane] + 1; } return modules; } private Alias GetAlias(string absoluteUri, List 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; } }