diff --git a/Oqtane.Client/Shared/SiteRouter.razor b/Oqtane.Client/Shared/SiteRouter.razor index 09f7740e..65d15f27 100644 --- a/Oqtane.Client/Shared/SiteRouter.razor +++ b/Oqtane.Client/Shared/SiteRouter.razor @@ -8,6 +8,8 @@ @using Microsoft.AspNetCore.Components.Routing @inject SiteState SiteState @inject IUriHelper UriHelper +@inject INavigationInterception NavigationInterception +@inject IComponentContext ComponentContext @inject IJSRuntime jsRuntime @inject IAliasService AliasService @inject ITenantService TenantService @@ -17,342 +19,350 @@ @inject IModuleService ModuleService @inject IModuleDefinitionService ModuleDefinitionService @inject IThemeService ThemeService +@implements IHandleAfterRender @DynamicComponent @code { - [CascadingParameter] PageState PageState { get; set; } +[CascadingParameter] PageState PageState { get; set; } - [Parameter] Action OnStateChange { get; set; } +[Parameter] Action OnStateChange { get; set; } - RenderFragment DynamicComponent { get; set; } - private string _absoluteUri; - PageState pagestate; +PageState pagestate; +RenderFragment DynamicComponent { get; set; } - protected override void OnInit() +string _absoluteUri; +bool _navigationInterceptionEnabled; + +protected override void OnInit() +{ + _absoluteUri = UriHelper.GetAbsoluteUri(); + UriHelper.OnLocationChanged += OnLocationChanged; + + DynamicComponent = builder => { - _absoluteUri = UriHelper.GetAbsoluteUri(); - UriHelper.OnLocationChanged += OnLocationChanged; - - DynamicComponent = builder => + if (pagestate != null) { - 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(); + builder.OpenComponent(0, Type.GetType(Constants.DefaultPage)); + builder.CloseComponent(); } - } + }; +} - private async Task Refresh() - { - List moduledefinitions; - List themes; - List aliases; - Alias alias; - Site site; - List pages; - Page page; - User user; - List modules; +public void Dispose() +{ + UriHelper.OnLocationChanged -= OnLocationChanged; +} - 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, LocationChangedEventArgs args) - { - _absoluteUri = args.Location; - await LocationChanged(); - } - - public async Task LocationChanged() +protected override async Task OnParametersSetAsync() +{ + if (PageState == null) { await Refresh(); } +} - private Dictionary ParseQueryString(string path) +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) { - Dictionary querystring = new Dictionary(); + 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) { - 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; + path = path.Substring(0, path.IndexOf("?")); } - Dictionary paneindex = new Dictionary(); - foreach (Module module in modules) + if (PageState == null || reload == true) { - // set the type based on the template and action - moduledefinition = moduledefinitions.Where(item => item.ModuleDefinitionName == module.ModuleDefinitionName).FirstOrDefault(); - if (moduledefinition != null) + 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)) { - string typename = moduledefinition.ControlTypeTemplate; - if (moduledefinition.ControlTypeRoutes != "") + 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")) { - foreach (string route in moduledefinition.ControlTypeRoutes.Split(';')) - { - if (route.StartsWith(control + "=")) - { - typename = route.Replace(control + "=", ""); - } - } + 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; } - 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; - } + 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; - // calculate module position within pane - if (paneindex.ContainsKey(module.Pane)) - { - paneindex[module.Pane] += 1; + OnStateChange?.Invoke(pagestate); } else { - paneindex.Add(module.Pane, 0); + // user is not authorized to view page } - module.PaneModuleIndex = paneindex[module.Pane]; } - - foreach (Module module in modules) + else { - module.PaneModuleCount = paneindex[module.Pane] + 1; + // page does not exist } - return modules; } - - private Alias GetAlias(string absoluteUri, List aliases) + else { - - 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; + // site does not exist } +} + +private async void OnLocationChanged(object sender, LocationChangedEventArgs args) +{ + _absoluteUri = args.Location; + await Refresh(); +} + +Task IHandleAfterRender.OnAfterRenderAsync() +{ + if (!_navigationInterceptionEnabled && ComponentContext.IsConnected) + { + _navigationInterceptionEnabled = true; + return NavigationInterception.EnableNavigationInterceptionAsync(); + } + return Task.CompletedTask; +} + +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; +} } \ No newline at end of file