Merge branch 'dev' into 3805-stop-registration-redirect-without-verification

This commit is contained in:
Mostafa
2024-02-22 00:22:21 +01:00
committed by GitHub
56 changed files with 772 additions and 351 deletions

View File

@ -17,7 +17,6 @@ else
<Pager Items="@_jobs" SearchProperties="Name">
<Header>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th>@SharedLocalizer["Name"]</th>
@ -28,7 +27,6 @@ else
</Header>
<Row>
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.JobId.ToString())" ResourceKey="EditJob" /></td>
<td><ActionDialog Header="Delete Job" Message="Are You Sure You Wish To Delete This Job?" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteJob(context))" ResourceKey="DeleteJob" /></td>
<td><ActionLink Action="Log" Class="btn btn-secondary" Parameters="@($"id=" + context.JobId.ToString())" ResourceKey="JobLog" /></td>
<td>@context.Name</td>
<td>@DisplayStatus(context.IsEnabled, context.IsExecuting)</td>
@ -49,17 +47,17 @@ else
}
@code {
private List<Job> _jobs;
private List<Job> _jobs;
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
protected override async Task OnParametersSetAsync()
{
_jobs = await JobService.GetJobsAsync();
if (_jobs.Count == 0)
{
AddModuleMessage(string.Format(Localizer["Message.NoJobs"], NavigateUrl("admin/system")), MessageType.Warning);
}
protected override async Task OnInitializedAsync()
{
_jobs = await JobService.GetJobsAsync();
if (_jobs.Count == 0)
{
AddModuleMessage(string.Format(Localizer["Message.NoJobs"], NavigateUrl("admin/system")), MessageType.Warning);
}
}
private string DisplayStatus(bool isEnabled, bool isExecuting)
@ -112,22 +110,6 @@ else
return result;
}
private async Task DeleteJob(Job job)
{
try
{
await JobService.DeleteJobAsync(job.JobId);
await logger.LogInformation("Job Deleted {Job}", job);
_jobs = await JobService.GetJobsAsync();
StateHasChanged();
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Job {Job} {Error}", job, ex.Message);
AddModuleMessage(Localizer["Error.Job.Delete"], MessageType.Error);
}
}
private async Task StartJob(int jobId)
{
try

View File

@ -47,8 +47,13 @@
<button type="button" class="btn btn-primary" @onclick="Login">@SharedLocalizer["Login"]</button>
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
<br /><br />
<button type="button" class="btn btn-secondary" @onclick="Forgot">@Localizer["ForgotPassword"]</button>
}
<button type="button" class="btn btn-secondary" @onclick="Forgot">@Localizer["ForgotPassword"]</button>
@if (PageState.Site.AllowRegistration)
{
<br /><br />
<NavLink href="@NavigateUrl("register")">@Localizer["Register"]</NavLink>
}
}
</div>
</form>
}
@ -84,8 +89,6 @@
private bool _alwaysremember = false;
private string _code = string.Empty;
private string _returnUrl = string.Empty;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous;
public override List<Resource> Resources => new List<Resource>()
@ -103,11 +106,6 @@
_togglepassword = SharedLocalizer["ShowPassword"];
if (PageState.QueryString.ContainsKey("returnurl"))
{
_returnUrl = PageState.QueryString["returnurl"];
}
if (PageState.QueryString.ContainsKey("name"))
{
_username = PageState.QueryString["name"];
@ -208,12 +206,12 @@
// hybrid apps utilize an interactive login
var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider));
authstateprovider.NotifyAuthenticationChanged();
NavigationManager.NavigateTo(NavigateUrl(WebUtility.UrlDecode(_returnUrl), true));
NavigationManager.NavigateTo(NavigateUrl(PageState.ReturnUrl, true));
}
else
{
// post back to the Login page so that the cookies are set correctly
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, username = _username, password = _password, remember = _remember, returnurl = _returnUrl };
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, username = _username, password = _password, remember = _remember, returnurl = WebUtility.UrlEncode(PageState.ReturnUrl) };
string url = Utilities.TenantUrl(PageState.Alias, "/pages/login/");
await interop.SubmitForm(url, fields);
}
@ -255,7 +253,7 @@
private void Cancel()
{
NavigationManager.NavigateTo(WebUtility.UrlDecode(_returnUrl));
NavigationManager.NavigateTo(PageState.ReturnUrl);
}
private async Task Forgot()
@ -323,7 +321,7 @@
private void ExternalLogin()
{
NavigationManager.NavigateTo(Utilities.TenantUrl(PageState.Alias, "/pages/external?returnurl=" + _returnUrl), true);
NavigationManager.NavigateTo(Utilities.TenantUrl(PageState.Alias, "/pages/external?returnurl=" + WebUtility.UrlEncode(PageState.ReturnUrl)), true);
}
}

View File

@ -201,7 +201,7 @@
@if (_themeSettingsType != null)
{
<TabPanel Name="ThemeSettings" Heading=@Localizer["Theme.Heading"] ResourceKey="ThemeSettings">
@ThemeSettingsComponent
@_themeSettingsComponent
</TabPanel>
}
</TabStrip>
@ -240,7 +240,7 @@
private PermissionGrid _permissionGrid;
private Type _themeSettingsType;
private object _themeSettings;
private RenderFragment ThemeSettingsComponent { get; set; }
private RenderFragment _themeSettingsComponent { get; set; }
private bool _refresh = false;
protected Page _parent = null;
protected Dictionary<string, string> _icons;
@ -337,13 +337,14 @@
private void ThemeSettings()
{
_themeSettingsType = null;
_themeSettingsComponent = null;
var theme = PageState.Site.Themes.FirstOrDefault(item => item.Themes.Any(themecontrol => themecontrol.TypeName.Equals(_themetype)));
if (theme != null && !string.IsNullOrEmpty(theme.ThemeSettingsType))
{
_themeSettingsType = Type.GetType(theme.ThemeSettingsType);
if (_themeSettingsType != null)
{
ThemeSettingsComponent = builder =>
_themeSettingsComponent = builder =>
{
builder.OpenComponent(0, _themeSettingsType);
builder.AddComponentReferenceCapture(1, inst => { _themeSettings = Convert.ChangeType(inst, _themeSettingsType); });

View File

@ -234,7 +234,7 @@
@if (_themeSettingsType != null)
{
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
@ThemeSettingsComponent
@_themeSettingsComponent
</TabPanel>
<br />
}
@ -278,7 +278,7 @@
@if (_themeSettingsType != null)
{
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
@ThemeSettingsComponent
@_themeSettingsComponent
</TabPanel>
<br />
}
@ -317,7 +317,7 @@
private string _containertype = "-";
private Type _themeSettingsType;
private object _themeSettings;
private RenderFragment ThemeSettingsComponent { get; set; }
private RenderFragment _themeSettingsComponent { get; set; }
private string _headcontent;
private string _bodycontent;
private List<Permission> _permissions = null;
@ -467,7 +467,7 @@
_containertype = _containers.First().TypeName;
ThemeSettings();
StateHasChanged();
// if theme chosen is different than default site theme, display warning message to user
if (ThemeService.GetTheme(PageState.Site.Themes, _themetype)?.ThemeName != ThemeService.GetTheme(PageState.Site.Themes, PageState.Site.DefaultThemeType)?.ThemeName)
{
@ -478,13 +478,14 @@
private void ThemeSettings()
{
_themeSettingsType = null;
_themeSettingsComponent = null;
var theme = PageState.Site.Themes.FirstOrDefault(item => item.Themes.Any(themecontrol => themecontrol.TypeName.Equals(_themetype)));
if (theme != null && !string.IsNullOrEmpty(theme.ThemeSettingsType))
{
_themeSettingsType = Type.GetType(theme.ThemeSettingsType);
if (_themeSettingsType != null)
{
ThemeSettingsComponent = builder =>
_themeSettingsComponent = builder =>
{
builder.OpenComponent(0, _themeSettingsType);
builder.AddComponentReferenceCapture(1, inst => { _themeSettings = Convert.ChangeType(inst, _themeSettingsType); });
@ -630,11 +631,11 @@
await logger.LogInformation("Page Saved {Page}", _page);
if (!string.IsNullOrEmpty(PageState.ReturnUrl))
{
NavigationManager.NavigateTo(PageState.ReturnUrl);
NavigationManager.NavigateTo(PageState.ReturnUrl, true);
}
else
{
NavigationManager.NavigateTo(NavigateUrl());
NavigationManager.NavigateTo(NavigateUrl(), true);
}
}
else

View File

@ -62,6 +62,11 @@
<br />
<button type="button" class="btn btn-primary" @onclick="Register">@Localizer["Register"]</button>
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
@if (_allowsitelogin)
{
<br /><br />
<NavLink href="@NavigateUrl("login")">@Localizer["Login"]</NavLink>
}
</form>
</NotAuthorized>
</AuthorizeView>
@ -84,12 +89,14 @@ else
private string _email = string.Empty;
private string _displayname = string.Empty;
private bool _userCreated = false;
private bool _allowsitelogin = true;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous;
protected override async Task OnInitializedAsync()
{
_passwordrequirements = await UserService.GetPasswordRequirementsAsync(PageState.Site.SiteId);
_passwordrequirements = await UserService.GetPasswordRequirementsAsync(PageState.Site.SiteId);
_allowsitelogin = bool.Parse(SettingService.GetSetting(PageState.Site.Settings, "LoginOptions:AllowSiteLogin", "true"));
}
protected override void OnParametersSet()
@ -158,7 +165,7 @@ else
private void Cancel()
{
NavigationManager.NavigateTo(NavigateUrl(string.Empty));
NavigationManager.NavigateTo(PageState.ReturnUrl);
}
private void TogglePassword()

View File

@ -579,9 +579,6 @@
var site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
if (site != null)
{
bool refresh = false;
bool reload = false;
site.Name = _name;
site.HomePageId = (_homepageid != "-" ? int.Parse(_homepageid) : null);
site.IsDeleted = (_isdeleted == null ? true : Boolean.Parse(_isdeleted));
@ -595,7 +592,6 @@
if (logofileid != _logofileid)
{
_logofileid = logofileid;
refresh = true; // needs to be refreshed on client
}
}
int? faviconFieldId = _faviconfilemanager.GetFileId();
@ -603,17 +599,14 @@
if (site.FaviconFileId != faviconFieldId)
{
site.FaviconFileId = faviconFieldId;
reload = true; // needs to be reloaded on server
}
if (site.DefaultThemeType != _themetype)
{
site.DefaultThemeType = _themetype;
refresh = true; // needs to be refreshed on client
}
if (site.DefaultContainerType != _containertype)
{
site.DefaultContainerType = _containertype;
refresh = true; // needs to be refreshed on client
}
site.AdminContainerType = _admincontainertype;
@ -621,33 +614,28 @@
if (site.HeadContent != _headcontent)
{
site.HeadContent = _headcontent;
reload = true;
}
if (site.BodyContent != _bodycontent)
{
site.BodyContent = _bodycontent;
reload = true;
}
// PWA
if (site.PwaIsEnabled.ToString() != _pwaisenabled)
{
site.PwaIsEnabled = Boolean.Parse(_pwaisenabled);
reload = true; // needs to be reloaded on server
}
int? pwaappiconfileid = _pwaappiconfilemanager.GetFileId();
if (pwaappiconfileid == -1) pwaappiconfileid = null;
if (site.PwaAppIconFileId != pwaappiconfileid)
{
site.PwaAppIconFileId = pwaappiconfileid;
reload = true; // needs to be reloaded on server
}
int? pwasplashiconfileid = _pwasplashiconfilemanager.GetFileId();
if (pwasplashiconfileid == -1) pwasplashiconfileid = null;
if (site.PwaSplashIconFileId != pwasplashiconfileid)
{
site.PwaSplashIconFileId = pwasplashiconfileid;
reload = true; // needs to be reloaded on server
}
// hosting model
@ -659,7 +647,6 @@
site.Runtime = _runtime;
site.Prerender = bool.Parse(_prerender);
site.Hybrid = bool.Parse(_hybrid);
reload = true; // needs to be reloaded on serve
}
}
@ -686,15 +673,7 @@
await logger.LogInformation("Site Settings Saved {Site}", site);
if (refresh || reload)
{
NavigationManager.NavigateTo(NavigateUrl(true), reload); // refresh/reload
}
else
{
AddModuleMessage(Localizer["Success.Settings.SaveSite"], MessageType.Success);
await ScrollToPageTop();
}
NavigationManager.NavigateTo(NavigateUrl(), true); // reload
}
}
else

View File

@ -483,9 +483,9 @@
await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
await logger.LogInformation("User Profile Saved");
if (PageState.QueryString.ContainsKey("returnurl"))
if (!string.IsNullOrEmpty(PageState.ReturnUrl))
{
NavigationManager.NavigateTo(WebUtility.UrlDecode(PageState.QueryString["returnurl"]));
NavigationManager.NavigateTo(PageState.ReturnUrl);
}
else // legacy behavior
{
@ -551,7 +551,7 @@
private void Cancel()
{
NavigationManager.NavigateTo(NavigateUrl(string.Empty));
NavigationManager.NavigateTo(PageState.ReturnUrl);
}
private void ProfileChanged(ChangeEventArgs e, string SettingName)

View File

@ -6,20 +6,24 @@
{
<div class="@_classname alert-dismissible fade show mb-3" role="alert">
@((MarkupString)_message)
@if (Type == MessageType.Error && PageState != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
@if (PageState != null)
{
@((MarkupString)"&nbsp;&nbsp;")<NavLink href="@NavigateUrl("admin/log")">View Details</NavLink>
@if (Type == MessageType.Error && UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
{
<NavLink class="ms-2" href="@NavigateUrl("admin/log")">View Details</NavLink>
}
<form method="post" @onsubmit="DismissModal" @formname="@_formname" data-enhance>
<input type="hidden" name="__RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<button type="submit" class="btn-close" aria-label="Close"></button>
</form>
}
<form method="post" @onsubmit="DismissModal" @formname="@($"ModuleMessageForm{ModuleState.PageModuleId}")" data-enhance>
<input type="hidden" name="__RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
<button type="submit" class="btn-close" aria-label="Close"></button>
</form>
</div>
}
@code {
private string _message = string.Empty;
private string _classname = string.Empty;
private string _formname = "ModuleMessageForm";
[Parameter]
public string Message { get; set; }
@ -27,6 +31,14 @@
[Parameter]
public MessageType Type { get; set; }
protected override void OnInitialized()
{
if (ModuleState != null)
{
_formname += ModuleState.PageModuleId.ToString();
}
}
protected override void OnParametersSet()
{
_message = Message;

View File

@ -10,7 +10,6 @@ using System.Collections.Generic;
using Microsoft.JSInterop;
using System.Linq;
using System.Dynamic;
using System.Net.Http.Headers;
namespace Oqtane.Modules
{
@ -90,7 +89,7 @@ namespace Oqtane.Modules
resources = Resources.Where(item => item.ResourceType == ResourceType.Script).ToList();
}
}
if (resources != null &&resources.Any())
if (resources != null && resources.Any())
{
var interop = new Interop(JSRuntime);
var scripts = new List<object>();

View File

@ -144,18 +144,9 @@
<data name="Month" xml:space="preserve">
<value>Month(s)</value>
</data>
<data name="Error.Job.Delete" xml:space="preserve">
<value>Error Deleting Job</value>
</data>
<data name="ViewJobs.Text" xml:space="preserve">
<value>View Logs</value>
</data>
<data name="DeleteJob.Header" xml:space="preserve">
<value>Delete Job</value>
</data>
<data name="DeleteJob.Message" xml:space="preserve">
<value>Are You Sure You Wish To Delete This Job?</value>
</data>
<data name="Frequency" xml:space="preserve">
<value>Frequency</value>
</data>
@ -165,9 +156,6 @@
<data name="Stop" xml:space="preserve">
<value>Stop</value>
</data>
<data name="DeleteJob.Text" xml:space="preserve">
<value>Delete</value>
</data>
<data name="EditJob.Text" xml:space="preserve">
<value>Edit</value>
</data>

View File

@ -228,4 +228,7 @@
<data name="ExternalLoginStatus.ReviewClaims" xml:space="preserve">
<value>The Review Claims Option Was Enabled In External Login Settings. Please Visit The Event Log To View The Claims Returned By The Provider.</value>
</data>
<data name="Register" xml:space="preserve">
<value>Register as new user?</value>
</data>
</root>

View File

@ -177,4 +177,7 @@
<data name="Username.Text" xml:space="preserve">
<value>Username:</value>
</data>
<data name="Login" xml:space="preserve">
<value>Already have account? Login now.</value>
</data>
</root>

View File

@ -1,5 +1,4 @@
using Oqtane.Models;
using Oqtane.UI;
using System.Collections.Generic;
using System.Threading.Tasks;

View File

@ -10,7 +10,7 @@ namespace Oqtane.Services
public interface IPageService
{
/// <summary>
/// Retuns a list of pages
/// Returns a list of pages
/// </summary>
/// <param name="siteId"></param>
/// <returns></returns>

View File

@ -3,11 +3,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using System;
using System.Reflection;
using Oqtane.Documentation;
using Oqtane.Shared;
using Oqtane.UI;
namespace Oqtane.Services
{

View File

@ -52,7 +52,7 @@ namespace Oqtane.Themes.Controls
else
{
// use existing value
loginurl = "?returnurl=" + PageState.QueryString["returnurl"];
loginurl += "?returnurl=" + PageState.QueryString["returnurl"];
}
// set logout url

View File

@ -31,7 +31,16 @@
protected override void OnParametersSet()
{
_returnurl = WebUtility.UrlEncode(PageState.Route.PathAndQuery);
if (!PageState.QueryString.ContainsKey("returnurl"))
{
// remember current url
_returnurl += WebUtility.UrlEncode(PageState.Route.PathAndQuery);
}
else
{
// use existing value
_returnurl += PageState.QueryString["returnurl"];
}
}
}

View File

@ -16,9 +16,9 @@ namespace Oqtane.Themes.OqtaneTheme
ContainerSettingsType = "Oqtane.Themes.OqtaneTheme.ContainerSettings, Oqtane.Client",
Resources = new List<Resource>()
{
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.0/cyborg/bootstrap.min.css", Integrity = "sha512-jwIqEv8o/kTBMJVtbNCBrDqhBojl0YSUam+EFpLjVOC86Ci6t4ZciTnIkelFNOik+dEQVymKGcQLiaJZNAfWRg==", CrossOrigin = "anonymous" },
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.2/cyborg/bootstrap.min.css", Integrity = "sha512-RfNxVfFNFgqk9MXO4TCKXYXn9hgc+keHCg3xFFGbnp2q7Cifda+YYzMTDHwsQtNx4DuqIMgfvZead7XOtB9CDQ==", CrossOrigin = "anonymous" },
new Resource { ResourceType = ResourceType.Stylesheet, Url = "~/Theme.css" },
new Resource { ResourceType = ResourceType.Script, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.bundle.min.js", Integrity = "sha512-VK2zcvntEufaimc+efOYi622VN5ZacdnufnmX7zIhCPmjhKnOi9ZDMtg1/ug5l183f19gG1/cBstPO4D8N/Img==", CrossOrigin = "anonymous" }
new Resource { ResourceType = ResourceType.Script, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.2/js/bootstrap.bundle.min.js", Integrity = "sha512-X/YkDZyjTf4wyc2Vy16YGCPHwAY8rZJY+POgokZjQB2mhIRFJCckEGc6YyX9eNsPfn0PzThEuNs+uaomE5CO6A==", CrossOrigin = "anonymous" }
}
};
}

View File

@ -3,6 +3,8 @@
@using Oqtane.Shared
@inject SiteState SiteState
@implements IDisposable
@* the following StreamRendering attribute is required - if it is removed the framework will not render the content in static rendering *@
@attribute [StreamRendering]
@if (!string.IsNullOrEmpty(_title))
{
@ -17,6 +19,12 @@
private string _title = "";
private string _content = "";
[Parameter]
public string RenderMode { get; set; }
[Parameter]
public string Runtime { get; set; }
protected override void OnInitialized()
{
((INotifyPropertyChanged)SiteState.Properties).PropertyChanged += PropertyChanged;
@ -47,7 +55,7 @@
private string RemoveScripts(string headcontent)
{
if (!string.IsNullOrEmpty(headcontent))
if (!string.IsNullOrEmpty(headcontent) && RenderMode == RenderModes.Interactive)
{
var index = headcontent.IndexOf("<script");
while (index >= 0)

View File

@ -17,7 +17,7 @@ namespace Oqtane.UI
case Runtimes.Auto:
return new InteractiveAutoRenderMode(prerender: prerender);
}
return new InteractiveServerRenderMode(prerender: prerender); // default to interactiver server
return new InteractiveServerRenderMode(prerender: prerender);
}
}
}

View File

@ -1,18 +1,18 @@
@namespace Oqtane.UI
@inject SiteState SiteState
@if (PageState.RenderMode == RenderModes.Interactive || ModuleState.RenderMode == RenderModes.Static)
@if (PageState.RenderMode == RenderModes.Interactive || ModuleState.RenderMode == RenderModes.Interactive)
{
<RenderModeBoundary ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" />
<StreamRenderingDisabled ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" />
}
else
{
<RenderModeBoundary ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" @rendermode="@InteractiveRenderMode.GetInteractiveRenderMode(PageState.Site.Runtime, PageState.Site.Prerender)" />
<StreamRenderingEnabled ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" />
}
@code {
// this component is on the static side of the render mode boundary
// it passes state as serializable parameters across the boundary so that the state can be used by downstream interactive components
// it passes state as serializable parameters across the boundary
[CascadingParameter]
protected PageState PageState { get; set; }
@ -20,7 +20,8 @@ else
[CascadingParameter]
private Module ModuleState { get; set; }
[Obsolete("AddModuleMessage is deprecated. Use ModuleBase.AddModuleMessage instead.", false)]
[Obsolete("AddModuleMessage is deprecated. Use AddModuleMessage in ModuleBase instead.", false)]
public void AddModuleMessage(string message, MessageType type)
{
}
@ -30,12 +31,12 @@ else
{
}
[Obsolete("ShowProgressIndicator is deprecated. Use ModuleBase.ShowProgressIndicator instead.", false)]
[Obsolete("ShowProgressIndicator is deprecated. Use ShowProgressIndicator in ModuleBase instead.", false)]
public void ShowProgressIndicator()
{
}
[Obsolete("HideProgressIndicator is deprecated. Use ModuleBase.HideProgressIndicator instead.", false)]
[Obsolete("HideProgressIndicator is deprecated. Use HideProgressIndicator in ModuleBase instead.", false)]
public void HideProgressIndicator()
{
}

View File

@ -67,7 +67,7 @@ else
// pane matches current pane
if (Name.ToLower() == pane.ToLower())
{
if (module.ModuleId == PageState.ModuleId && PageState.Action != Constants.DefaultAction)
if (PageState.ModuleId == module.ModuleId && PageState.Action != Constants.DefaultAction)
{
var moduleType = Type.GetType(module.ModuleType);
if (moduleType != null)

View File

@ -4,12 +4,12 @@
@inject ILogService LoggingService
@inherits ErrorBoundary
@if (CurrentException is null)
{
@if (ModuleType != null)
{
<CascadingValue Value="@PageState">
<CascadingValue Value="@ModuleState">
<CascadingValue Value="@PageState">
<CascadingValue Value="@ModuleState">
@if (CurrentException is null)
{
@if (ModuleType != null)
{
@if (!string.IsNullOrEmpty(_messageContent) && _messagePosition == "top")
{
<ModuleMessage Message="@_messageContent" Type="@_messageType" />
@ -23,19 +23,22 @@
{
<ModuleMessage Message="@_messageContent" Type="@_messageType" />
}
</CascadingValue>
</CascadingValue>
}
}
else
{
@if (!string.IsNullOrEmpty(_error))
{
<ModuleMessage Message="@_error" Type="@MessageType.Error" />
}
}
}
}
else
{
@if (!string.IsNullOrEmpty(_error))
{
<ModuleMessage Message="@_error" Type="@MessageType.Error" />
}
}
</CascadingValue>
</CascadingValue>
@code {
// this component is on the interactive side of the render mode boundary
// it receives state as serializable parameters so that the state can be made available to downstream components
private Type ModuleType { get; set; }
RenderFragment DynamicComponent { get; set; }

View File

@ -3,7 +3,8 @@
@inject IInstallationService InstallationService
@inject IJSRuntime JSRuntime
@inject SiteState SiteState
@attribute [StreamRendering]
@* the following StreamRendering attribute is required - if it is removed the framework will not render the content in static rendering *@
@attribute [StreamRendering]
@if (_initialized)
{

View File

@ -50,7 +50,7 @@
DynamicComponent = builder =>
{
if (PageState != null)
if (PageState != null && !PageState.Refresh)
{
builder.OpenComponent(0, typeof(ThemeBuilder));
builder.CloseComponent();
@ -101,8 +101,8 @@
_error = "";
Route route = new Route(_absoluteUri, SiteState.Alias.Path);
int moduleid = (int.TryParse(route.ModuleId, out moduleid)) ? moduleid : -1;
var action = (!string.IsNullOrEmpty(route.Action)) ? route.Action : Constants.DefaultAction;
int moduleid = int.Parse(route.ModuleId);
var action = route.Action;
var querystring = Utilities.ParseQueryString(route.Query);
var returnurl = "";
@ -567,9 +567,19 @@
// ensure resource does not exist already
if (!pageresources.Exists(item => item.Url.ToLower() == resource.Url.ToLower()))
{
resource.Level = level;
resource.Namespace = name;
pageresources.Add(resource);
pageresources.Add(new Resource
{
ResourceType = resource.ResourceType,
Url = resource.Url,
Integrity = resource.Integrity,
CrossOrigin = resource.CrossOrigin,
Bundle = resource.Bundle,
Location = resource.Location,
ES6Module = resource.ES6Module,
Content = resource.Content,
Level = level,
Namespace = name
});
}
}
}

View File

@ -0,0 +1,21 @@
@attribute [StreamRendering(false)]
@if (PageState.RenderMode == RenderModes.Interactive || ModuleState.RenderMode == RenderModes.Static)
{
<RenderModeBoundary ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" />
}
else
{
<RenderModeBoundary ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" @rendermode="@InteractiveRenderMode.GetInteractiveRenderMode(PageState.Site.Runtime, PageState.Site.Prerender)" />
}
@code {
[Parameter]
public SiteState SiteState { get; set; }
[Parameter]
public PageState PageState { get; set; }
[Parameter]
public Module ModuleState { get; set; }
}

View File

@ -0,0 +1,21 @@
@attribute [StreamRendering(true)]
@if (PageState.RenderMode == RenderModes.Interactive || ModuleState.RenderMode == RenderModes.Static)
{
<RenderModeBoundary ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" />
}
else
{
<RenderModeBoundary ModuleState="@ModuleState" PageState="@PageState" SiteState="@SiteState" @rendermode="@InteractiveRenderMode.GetInteractiveRenderMode(PageState.Site.Runtime, PageState.Site.Prerender)" />
}
@code {
[Parameter]
public SiteState SiteState { get; set; }
[Parameter]
public PageState PageState { get; set; }
[Parameter]
public Module ModuleState { get; set; }
}

View File

@ -53,30 +53,6 @@
{
headcontent = AddHeadContent(headcontent, PageState.Page.HeadContent);
}
if (PageState.RenderMode == RenderModes.Static)
{
string batch = DateTime.UtcNow.ToString("yyyyMMddHHmmssfff");
int count = 0;
foreach (Resource resource in PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Stylesheet && item.Level == ResourceLevel.Module))
{
// if (resource.Url.StartsWith("~"))
// {
// resource.Url = resource.Url.Replace("~", "/Themes/" + Utilities.GetTypeName(name) + "/").Replace("//", "/");
// }
if (!resource.Url.Contains("://") && PageState.Alias.BaseUrl != "" && !resource.Url.StartsWith(PageState.Alias.BaseUrl))
{
resource.Url = PageState.Alias.BaseUrl + resource.Url;
}
if (!headcontent.Contains(resource.Url, StringComparison.OrdinalIgnoreCase))
{
count++;
string id = "id=\"app-stylesheet-" + resource.Level.ToString().ToLower() + "-" + batch + "-" + count.ToString("00") + "\" ";
headcontent += "<link " + id + "rel=\"stylesheet\" href=\"" + resource.Url + "\"" + (!string.IsNullOrEmpty(resource.Integrity) ? " integrity=\"" + resource.Integrity + "\"" : "") + (!string.IsNullOrEmpty(resource.CrossOrigin) ? " crossorigin=\"" + resource.CrossOrigin + "\"" : "") + " type=\"text/css\"/>" + Environment.NewLine;
}
}
}
SiteState.Properties.HeadContent = headcontent;
DynamicComponent = builder =>
@ -96,7 +72,7 @@
while (index >= 0)
{
var element = content.Substring(index, content.IndexOf(">", index) - index + 1);
if (!string.IsNullOrEmpty(element) && !element.ToLower().StartsWith("<script") && !element.ToLower().StartsWith("</script"))
if (!string.IsNullOrEmpty(element) && (PageState.RenderMode == RenderModes.Static || (!element.ToLower().StartsWith("<script") && !element.ToLower().StartsWith("</script"))))
{
if (!headcontent.Contains(element))
{
@ -168,6 +144,7 @@
string integrity = "";
string crossorigin = "";
string type = "";
var dataAttributes = new Dictionary<string, string>();
foreach (var attribute in attributes)
{
if (attribute.Contains("="))
@ -190,6 +167,12 @@
case "type":
type = value[1];
break;
default:
if(!string.IsNullOrWhiteSpace(value[0]) && value[0].StartsWith("data-"))
{
dataAttributes.Add(value[0], value[1]);
}
break;
}
}
}
@ -197,7 +180,7 @@
if (!string.IsNullOrEmpty(src))
{
src = (src.Contains("://")) ? src : PageState.Alias.BaseUrl + src;
scripts.Add(new { href = src, bundle = "", integrity = integrity, crossorigin = crossorigin, es6module = (type == "module"), location = location.ToString().ToLower() });
scripts.Add(new { href = src, bundle = "", integrity = integrity, crossorigin = crossorigin, es6module = (type == "module"), location = location.ToString().ToLower(), dataAttributes = dataAttributes });
}
else
{
@ -217,4 +200,67 @@
await interop.IncludeScripts(scripts.ToArray());
}
}
private string ManageStyleSheets(List<Resource> resources, Alias alias)
{
var stylesheets = "";
if (resources != null)
{
string batch = DateTime.UtcNow.ToString("yyyyMMddHHmmssfff");
int count = 0;
foreach (var resource in resources.Where(item => item.ResourceType == ResourceType.Stylesheet))
{
if (resource.Url.StartsWith("~"))
{
resource.Url = resource.Url.Replace("~", "/Themes/" + Utilities.GetTypeName(resource.Namespace) + "/").Replace("//", "/");
}
if (!resource.Url.Contains("://") && alias.BaseUrl != "" && !resource.Url.StartsWith(alias.BaseUrl))
{
resource.Url = alias.BaseUrl + resource.Url;
}
if (!stylesheets.Contains(resource.Url, StringComparison.OrdinalIgnoreCase))
{
count++;
string id = "id=\"app-stylesheet-" + ResourceLevel.Page.ToString().ToLower() + "-" + batch + "-" + count.ToString("00") + "\" ";
stylesheets += "<link " + id + "rel=\"stylesheet\" href=\"" + resource.Url + "\"" + (!string.IsNullOrEmpty(resource.Integrity) ? " integrity=\"" + resource.Integrity + "\"" : "") + (!string.IsNullOrEmpty(resource.CrossOrigin) ? " crossorigin=\"" + resource.CrossOrigin + "\"" : "") + " type=\"text/css\"/>" + Environment.NewLine;
}
}
}
return stylesheets;
}
private string ManageScripts(List<Resource> resources, Alias alias)
{
var scripts = "";
if (resources != null)
{
foreach (var resource in resources.Where(item => item.ResourceType == ResourceType.Script && item.Location == ResourceLocation.Head))
{
var script = CreateScript(resource, alias);
if (!scripts.Contains(script, StringComparison.OrdinalIgnoreCase))
{
scripts += script + Environment.NewLine;
}
}
}
return scripts;
}
private string CreateScript(Resource resource, Alias alias)
{
if (!string.IsNullOrEmpty(resource.Url))
{
var url = (resource.Url.Contains("://")) ? resource.Url : alias.BaseUrl + resource.Url;
return "<script src=\"" + url + "\"" +
((!string.IsNullOrEmpty(resource.Integrity)) ? " integrity=\"" + resource.Integrity + "\"" : "") +
((!string.IsNullOrEmpty(resource.CrossOrigin)) ? " crossorigin=\"" + resource.CrossOrigin + "\"" : "") +
"></script>";
}
else
{
// inline script
return "<script>" + resource.Content + "</script>";
}
}
}