enhance Pager component with OnPageChanged event and implement in Visitor Management, allow PermissionGrid component to support Host role, fix unhandled exception in RichTextEditor component related to rerendering, make Quill resource declarations forward compatible, update Blazor theme to Boostrap 5.1.3, add missing RemoteIPAddress parameter in _Host app component, include logic to enable bypass of non-default alias redirection
This commit is contained in:
parent
cc9802a0d8
commit
826898e3fe
|
@ -7,7 +7,7 @@
|
||||||
@inject IStringLocalizer<Detail> Localizer
|
@inject IStringLocalizer<Detail> Localizer
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="ip" HelpText="The last recorded IP address for this visitor" ResourceKey="IP">IP Address: </Label>
|
<Label Class="col-sm-3" For="ip" HelpText="The last recorded IP address for this visitor" ResourceKey="IP">IP Address: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
|
@ -65,9 +65,9 @@
|
||||||
<input id="created" class="form-control" @bind="@_created" readonly />
|
<input id="created" class="form-control" @bind="@_created" readonly />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl(PageState.Page.Path, "type=" + PageState.QueryString["type"] + "&days=" + PageState.QueryString["days"] + "&page=" + PageState.QueryString["page"])">@SharedLocalizer["Cancel"]</NavLink>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private int _visitorId;
|
private int _visitorId;
|
||||||
|
|
|
@ -17,13 +17,13 @@ else
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<select id="type" class="form-select custom-select" @onchange="(e => TypeChanged(e))">
|
<select id="type" class="form-select custom-select" value="@_type" @onchange="(e => TypeChanged(e))">
|
||||||
<option value="false">@Localizer["AllVisitors"]</option>
|
<option value="visitors">@Localizer["AllVisitors"]</option>
|
||||||
<option value="true">@Localizer["UsersOnly"]</option>
|
<option value="users">@Localizer["UsersOnly"]</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<select id="type" class="form-select custom-select" @onchange="(e => DateChanged(e))">
|
<select id="days" class="form-select custom-select" value="@_days" @onchange="(e => DaysChanged(e))">
|
||||||
<option value="1">@Localizer["PastDay"]</option>
|
<option value="1">@Localizer["PastDay"]</option>
|
||||||
<option value="7">@Localizer["PastWeek"]</option>
|
<option value="7">@Localizer["PastWeek"]</option>
|
||||||
<option value="30">@Localizer["PastMonth"]</option>
|
<option value="30">@Localizer["PastMonth"]</option>
|
||||||
|
@ -32,7 +32,7 @@ else
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
<Pager Items="@_visitors">
|
<Pager Items="@_visitors" CurrentPage="@_page.ToString()" OnPageChange="OnPageChange">
|
||||||
<Header>
|
<Header>
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>@Localizer["IP"]</th>
|
<th>@Localizer["IP"]</th>
|
||||||
|
@ -43,7 +43,7 @@ else
|
||||||
<th>@Localizer["Created"]</th>
|
<th>@Localizer["Created"]</th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td><ActionLink Action="Detail" Parameters="@($"id=" + context.VisitorId.ToString())" ResourceKey="Details" /></td>
|
<td><ActionLink Action="Detail" Parameters="@($"id=" + context.VisitorId.ToString() + "&type=" + _type.ToString() + "&days=" + _days.ToString() + "&page=" + _page.ToString())" ResourceKey="Details" /></td>
|
||||||
<td>@context.IPAddress</td>
|
<td>@context.IPAddress</td>
|
||||||
<td>
|
<td>
|
||||||
@if (context.UserId != null)
|
@if (context.UserId != null)
|
||||||
|
@ -89,8 +89,9 @@ else
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private bool _users = false;
|
private string _type = "visitors";
|
||||||
private int _days = 1;
|
private int _days = 1;
|
||||||
|
private int _page = 1;
|
||||||
private List<Visitor> _visitors;
|
private List<Visitor> _visitors;
|
||||||
private string _tracking;
|
private string _tracking;
|
||||||
private string _filter = "";
|
private string _filter = "";
|
||||||
|
@ -100,7 +101,21 @@ else
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
|
if (PageState.QueryString.ContainsKey("type"))
|
||||||
|
{
|
||||||
|
_type = PageState.QueryString["type"];
|
||||||
|
}
|
||||||
|
if (PageState.QueryString.ContainsKey("days") && int.TryParse(PageState.QueryString["days"], out int days))
|
||||||
|
{
|
||||||
|
_days = days;
|
||||||
|
}
|
||||||
|
if (PageState.QueryString.ContainsKey("page") && int.TryParse(PageState.QueryString["page"], out int page))
|
||||||
|
{
|
||||||
|
_page = page;
|
||||||
|
}
|
||||||
|
|
||||||
await GetVisitors();
|
await GetVisitors();
|
||||||
|
|
||||||
_tracking = PageState.Site.VisitorTracking.ToString();
|
_tracking = PageState.Site.VisitorTracking.ToString();
|
||||||
_filter = SettingService.GetSetting(PageState.Site.Settings, "VisitorFilter", "");
|
_filter = SettingService.GetSetting(PageState.Site.Settings, "VisitorFilter", "");
|
||||||
_retention = SettingService.GetSetting(PageState.Site.Settings, "VisitorRetention", "30");
|
_retention = SettingService.GetSetting(PageState.Site.Settings, "VisitorRetention", "30");
|
||||||
|
@ -110,7 +125,7 @@ else
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_users = bool.Parse(e.Value.ToString());
|
_type = e.Value.ToString();
|
||||||
await GetVisitors();
|
await GetVisitors();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
@ -120,7 +135,7 @@ else
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void DateChanged(ChangeEventArgs e)
|
private async void DaysChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -137,7 +152,7 @@ else
|
||||||
private async Task GetVisitors()
|
private async Task GetVisitors()
|
||||||
{
|
{
|
||||||
_visitors = await VisitorService.GetVisitorsAsync(PageState.Site.SiteId, DateTime.UtcNow.AddDays(-_days));
|
_visitors = await VisitorService.GetVisitorsAsync(PageState.Site.SiteId, DateTime.UtcNow.AddDays(-_days));
|
||||||
if (_users)
|
if (_type == "users")
|
||||||
{
|
{
|
||||||
_visitors = _visitors.Where(item => item.UserId != null).ToList();
|
_visitors = _visitors.Where(item => item.UserId != null).ToList();
|
||||||
}
|
}
|
||||||
|
@ -164,4 +179,9 @@ else
|
||||||
AddModuleMessage(Localizer["Error.SaveSiteSettings"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.SaveSiteSettings"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnPageChange(int page)
|
||||||
|
{
|
||||||
|
_page = page;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -195,6 +195,9 @@
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Class { get; set; }
|
public string Class { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public Action<int> OnPageChange { get; set; } // optional - executes a method in the calling component when the page changes
|
||||||
|
|
||||||
private IEnumerable<TableItem> ItemList { get; set; }
|
private IEnumerable<TableItem> ItemList { get; set; }
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
protected override void OnParametersSet()
|
||||||
|
@ -268,6 +271,7 @@
|
||||||
{
|
{
|
||||||
_endPage = _pages;
|
_endPage = _pages;
|
||||||
}
|
}
|
||||||
|
OnPageChange?.Invoke(_page);
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -129,6 +129,10 @@
|
||||||
|
|
||||||
_roles = await RoleService.GetRolesAsync(ModuleState.SiteId);
|
_roles = await RoleService.GetRolesAsync(ModuleState.SiteId);
|
||||||
_roles.Insert(0, new Role { Name = RoleNames.Everyone });
|
_roles.Insert(0, new Role { Name = RoleNames.Everyone });
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
|
{
|
||||||
|
_roles.Add(new Role { Name = RoleNames.Host });
|
||||||
|
}
|
||||||
|
|
||||||
_permissions = new List<PermissionString>();
|
_permissions = new List<PermissionString>();
|
||||||
|
|
||||||
|
@ -186,9 +190,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool GetPermissionDisabled(string roleName)
|
private bool GetPermissionDisabled(string roleName)
|
||||||
=> roleName == RoleNames.Admin
|
=> (roleName == RoleNames.Admin && !UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) ? true : false;
|
||||||
? true
|
|
||||||
: false;
|
|
||||||
|
|
||||||
private async Task AddUser()
|
private async Task AddUser()
|
||||||
{
|
{
|
||||||
|
@ -253,6 +255,16 @@
|
||||||
List<string> ids = permission.Permissions.Split(';').ToList();
|
List<string> ids = permission.Permissions.Split(';').ToList();
|
||||||
ids.Remove("!" + RoleNames.Everyone); // remove deny all users
|
ids.Remove("!" + RoleNames.Everyone); // remove deny all users
|
||||||
ids.Remove("!" + RoleNames.Registered); // remove deny registered users
|
ids.Remove("!" + RoleNames.Registered); // remove deny registered users
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
|
{
|
||||||
|
ids.Remove("!" + RoleNames.Admin); // remove deny administrators
|
||||||
|
ids.Remove("!" + RoleNames.Host); // remove deny host users
|
||||||
|
if (!ids.Contains(RoleNames.Host) && !ids.Contains(RoleNames.Admin))
|
||||||
|
{
|
||||||
|
// add administrators role if host user role is not assigned
|
||||||
|
ids.Add(RoleNames.Admin);
|
||||||
|
}
|
||||||
|
}
|
||||||
permission.Permissions = string.Join(";", ids.ToArray());
|
permission.Permissions = string.Join(";", ids.ToArray());
|
||||||
_permissions[i] = permission;
|
_permissions[i] = permission;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@
|
||||||
|
|
||||||
public override List<Resource> Resources => new List<Resource>()
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
{
|
{
|
||||||
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill1.3.7.min.js" },
|
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill.min.js" },
|
||||||
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-blot-formatter.min.js" },
|
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-blot-formatter.min.js" },
|
||||||
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-interop.js" }
|
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-interop.js" }
|
||||||
};
|
};
|
||||||
|
@ -128,11 +128,11 @@
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
var interop = new RichTextEditorInterop(JSRuntime);
|
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
{
|
{
|
||||||
await base.OnAfterRenderAsync(firstRender);
|
var interop = new RichTextEditorInterop(JSRuntime);
|
||||||
|
|
||||||
|
await base.OnAfterRenderAsync(firstRender);
|
||||||
|
|
||||||
await interop.CreateEditor(
|
await interop.CreateEditor(
|
||||||
_editorElement,
|
_editorElement,
|
||||||
|
@ -146,10 +146,10 @@
|
||||||
|
|
||||||
_content = Content; // raw HTML
|
_content = Content; // raw HTML
|
||||||
|
|
||||||
}
|
|
||||||
// preserve a copy of the rich text content ( Quill sanitizes content so we need to retrieve it from the editor )
|
// preserve a copy of the rich text content ( Quill sanitizes content so we need to retrieve it from the editor )
|
||||||
_original = await interop.GetHtml(_editorElement);
|
_original = await interop.GetHtml(_editorElement);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void CloseFileManager()
|
public void CloseFileManager()
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
public override List<Resource> Resources => new List<Resource>()
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
{
|
{
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" },
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" },
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill1.3.7.bubble.css" },
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill.bubble.css" },
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill1.3.7.snow.css" }
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill.snow.css" }
|
||||||
};
|
};
|
||||||
|
|
||||||
private RichTextEditor RichTextEditorHtml;
|
private RichTextEditor RichTextEditorHtml;
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
public override List<Resource> Resources => new List<Resource>()
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
{
|
{
|
||||||
// obtained from https://cdnjs.com/libraries
|
// obtained from https://cdnjs.com/libraries
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.0.2/css/bootstrap.min.css", Integrity = "sha512-usVBAd66/NpVNfBge19gws2j6JZinnca12rAe2l+d+QkLU9fiG02O1X8Q6hepIpr/EYKZvKx/I9WsnujJuOmBA==", CrossOrigin = "anonymous" },
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/css/bootstrap.min.css", Integrity = "sha512-GQGU0fMMi238uA+a/bdWJfpUGKUkBdgfFdgBm72SUQ6BeyWjoY/ton0tEjH+OSH9iP4Dfh+7HM0I9f5eR0L/4w==", CrossOrigin = "anonymous" },
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" },
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" },
|
||||||
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/js/bootstrap.bundle.min.js", Integrity = "sha512-pax4MlgXjHEPfCwcJLQhigY7+N8rt6bVvWLFyUMuxShv170X53TRzGPmPkZmGBhk+jikR8WBM4yl7A9WMHHqvg==", CrossOrigin = "anonymous" }
|
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/js/bootstrap.bundle.min.js", Integrity = "sha512-pax4MlgXjHEPfCwcJLQhigY7+N8rt6bVvWLFyUMuxShv170X53TRzGPmPkZmGBhk+jikR8WBM4yl7A9WMHHqvg==", CrossOrigin = "anonymous" }
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@(Html.AntiForgeryToken())
|
@(Html.AntiForgeryToken())
|
||||||
<component type="typeof(Oqtane.App)" render-mode="@Model.RenderMode" param-AntiForgeryToken="@Model.AntiForgeryToken" param-Runtime="@Model.Runtime" param-RenderMode="@Model.RenderMode.ToString()" param-VisitorId="@Model.VisitorId" />
|
<component type="typeof(Oqtane.App)" render-mode="@Model.RenderMode" param-AntiForgeryToken="@Model.AntiForgeryToken" param-Runtime="@Model.Runtime" param-RenderMode="@Model.RenderMode.ToString()" param-VisitorId="@Model.VisitorId" param-RemoteIPAddress="@Model.RemoteIPAddress" />
|
||||||
|
|
||||||
<div id="blazor-error-ui">
|
<div id="blazor-error-ui">
|
||||||
<environment include="Staging,Production">
|
<environment include="Staging,Production">
|
||||||
|
|
|
@ -87,8 +87,8 @@ namespace Oqtane.Pages
|
||||||
{
|
{
|
||||||
var url = WebUtility.UrlDecode(HttpContext.Request.GetEncodedUrl());
|
var url = WebUtility.UrlDecode(HttpContext.Request.GetEncodedUrl());
|
||||||
|
|
||||||
// redirect non-default alias
|
// redirect non-default alias unless you are trying to access site settings
|
||||||
if (!alias.IsDefault)
|
if (!alias.IsDefault && !url.Contains("admin/site"))
|
||||||
{
|
{
|
||||||
var aliases = _aliases.GetAliases().Where(item => item.TenantId == alias.TenantId && item.SiteId == alias.SiteId);
|
var aliases = _aliases.GetAliases().Where(item => item.TenantId == alias.TenantId && item.SiteId == alias.SiteId);
|
||||||
if (aliases.Where(item => item.IsDefault).FirstOrDefault() != null)
|
if (aliases.Where(item => item.IsDefault).FirstOrDefault() != null)
|
||||||
|
@ -196,7 +196,7 @@ namespace Oqtane.Pages
|
||||||
private void TrackVisitor(int SiteId)
|
private void TrackVisitor(int SiteId)
|
||||||
{
|
{
|
||||||
// get request attributes
|
// get request attributes
|
||||||
string useragent = (Request.Headers[HeaderNames.UserAgent] != StringValues.Empty) ? Request.Headers[HeaderNames.UserAgent] : "";
|
string useragent = (Request.Headers[HeaderNames.UserAgent] != StringValues.Empty) ? Request.Headers[HeaderNames.UserAgent] : "(none)";
|
||||||
string language = (Request.Headers[HeaderNames.AcceptLanguage] != StringValues.Empty) ? Request.Headers[HeaderNames.AcceptLanguage] : "";
|
string language = (Request.Headers[HeaderNames.AcceptLanguage] != StringValues.Empty) ? Request.Headers[HeaderNames.AcceptLanguage] : "";
|
||||||
language = (language.Contains(",")) ? language.Substring(0, language.IndexOf(",")) : language;
|
language = (language.Contains(",")) ? language.Substring(0, language.IndexOf(",")) : language;
|
||||||
language = (language.Contains(";")) ? language.Substring(0, language.IndexOf(";")) : language;
|
language = (language.Contains(";")) ? language.Substring(0, language.IndexOf(";")) : language;
|
||||||
|
|
1173
Oqtane.Server/wwwroot/css/quill/quill.bubble.css
Normal file
1173
Oqtane.Server/wwwroot/css/quill/quill.bubble.css
Normal file
File diff suppressed because it is too large
Load Diff
1170
Oqtane.Server/wwwroot/css/quill/quill.snow.css
Normal file
1170
Oqtane.Server/wwwroot/css/quill/quill.snow.css
Normal file
File diff suppressed because it is too large
Load Diff
8
Oqtane.Server/wwwroot/js/quill.min.js
vendored
Normal file
8
Oqtane.Server/wwwroot/js/quill.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user