performance and user experience improvements

This commit is contained in:
Shaun Walker
2021-02-04 08:54:59 -05:00
parent 1fb58296d8
commit 531cba715e
31 changed files with 494 additions and 484 deletions

View File

@ -47,7 +47,7 @@ else
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
protected override async Task OnInitializedAsync()
protected override async Task OnParametersSetAsync()
{
try
{
@ -100,7 +100,8 @@ else
try
{
await ModuleDefinitionService.DeleteModuleDefinitionAsync(moduleDefinition.ModuleDefinitionId, moduleDefinition.SiteId);
AddModuleMessage(Localizer["Module Deleted Successfully. You Must <a href=\"{0}\">Restart</a> Your Application To Apply These Changes.", NavigateUrl("admin/system")], MessageType.Success);
AddModuleMessage(Localizer["Module Deleted Successfully"], MessageType.Success);
StateHasChanged();
}
catch (Exception ex)
{

View File

@ -10,122 +10,137 @@
@if (_initialized)
{
<table class="table table-borderless">
<tr>
<td>
<Label For="name" HelpText="Enter the site name" ResourceKey="Name">Name: </Label>
</td>
<td>
<input id="name" class="form-control" @bind="@_name" />
</td>
</tr>
<tr>
<td>
<Label For="tenant" HelpText="Enter the tenant for the site" ResourceKey="Tenant">Tenant: </Label>
</td>
<td>
<input id="tenant" class="form-control" @bind="@_tenant" readonly />
</td>
</tr>
<tr>
<td>
<Label For="alias" HelpText="Enter the alias for the server" ResourceKey="Aliases">Aliases: </Label>
</td>
<td>
<textarea id="alias" class="form-control" @bind="@_urls" rows="3"></textarea>
</td>
</tr>
<tr>
<td>
<Label For="logo" HelpText="Upload a logo for the site" ResourceKey="Logo">Logo: </Label>
</td>
<td>
<FileManager FileId="@_logofileid" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
</td>
</tr>
<tr>
<td>
<Label For="favicon" HelpText="Select Your default icon" ResourceKey="FavoriteIcon">Favicon: </Label>
</td>
<td>
<FileManager FileId="@_faviconfileid" Filter="ico" @ref="_faviconfilemanager" />
</td>
</tr>
<tr>
<td>
<Label For="defaultTheme" HelpText="Select the sites default theme" ResourceKey="DefaultTheme">Default Theme: </Label>
</td>
<td>
<select id="defaultTheme" class="form-control" @onchange="(e => ThemeChanged(e))">
<option value="-">&lt;@Localizer["Select Theme"]&gt;</option>
@foreach (var theme in _themes)
<table class="table table-borderless">
<tr>
<td>
<Label For="name" HelpText="Enter the site name" ResourceKey="Name">Name: </Label>
</td>
<td>
<input id="name" class="form-control" @bind="@_name" />
</td>
</tr>
<tr>
<td>
<Label For="tenant" HelpText="Enter the tenant for the site" ResourceKey="Tenant">Tenant: </Label>
</td>
<td>
<input id="tenant" class="form-control" @bind="@_tenant" readonly />
</td>
</tr>
<tr>
<td>
<Label For="alias" HelpText="Enter the alias for the server" ResourceKey="Aliases">Aliases: </Label>
</td>
<td>
<textarea id="alias" class="form-control" @bind="@_urls" rows="3"></textarea>
</td>
</tr>
<tr>
<td>
<Label For="logo" HelpText="Upload a logo for the site" ResourceKey="Logo">Logo: </Label>
</td>
<td>
<FileManager FileId="@_logofileid" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
</td>
</tr>
<tr>
<td>
<Label For="favicon" HelpText="Select Your default icon" ResourceKey="FavoriteIcon">Favicon: </Label>
</td>
<td>
<FileManager FileId="@_faviconfileid" Filter="ico" @ref="_faviconfilemanager" />
</td>
</tr>
<tr>
<td>
<Label For="defaultTheme" HelpText="Select the sites default theme" ResourceKey="DefaultTheme">Default Theme: </Label>
</td>
<td>
<select id="defaultTheme" class="form-control" @onchange="(e => ThemeChanged(e))">
<option value="-">&lt;@Localizer["Select Theme"]&gt;</option>
@foreach (var theme in _themes)
{
if (theme.TypeName == _themetype)
{
if (theme.TypeName == _themetype)
{
<option value="@theme.TypeName" selected>@theme.Name</option>
}
else
{
<option value="@theme.TypeName">@theme.Name</option>
}
<option value="@theme.TypeName" selected>@theme.Name</option>
}
else
{
<option value="@theme.TypeName">@theme.Name</option>
}
}
</select>
</td>
</tr>
@if (_layouts.Count > 0)
{
<tr>
<td>
<Label For="defaultLayout" HelpText="Select the sites default layout" ResourceKey="DefaultLayout">Default Layout: </Label>
</td>
<td>
<select id="defaultLayout" class="form-control" @bind="@_layouttype">
<option value="-">&lt;@Localizer["Select Layout"]&gt;</option>
@foreach (var layout in _layouts)
{
<option value="@(layout.TypeName)">@(layout.Name)</option>
}
</select>
</td>
</tr>
@if (_layouts.Count > 0)
{
<tr>
<td>
<Label For="defaultLayout" HelpText="Select the sites default layout" ResourceKey="DefaultLayout">Default Layout: </Label>
</td>
<td>
<select id="defaultLayout" class="form-control" @bind="@_layouttype">
<option value="-">&lt;@Localizer["Select Layout"]&gt;</option>
@foreach (var layout in _layouts)
{
<option value="@(layout.TypeName)">@(layout.Name)</option>
}
</select>
</td>
</tr>
}
<tr>
<td>
<Label For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
</td>
<td>
<select id="defaultContainer" class="form-control" @bind="@_containertype">
<option value="-">&lt;@Localizer["Select Container"]&gt;</option>
@foreach (var container in _containers)
{
<option value="@container.TypeName">@container.Name</option>
}
</select>
</td>
</tr>
<tr>
<td>
<Label For="allowRegister" HelpText="Do you want the users to be able to register for an account on the site" ResourceKey="AllowRegistration">Allow User Registration? </Label>
</td>
<td>
<select id="allowRegister" class="form-control" @bind="@_allowregistration">
<option value="True">@Localizer["Yes"]</option>
<option value="False">@Localizer["No"]</option>
</select>
</td>
</tr>
<tr>
<td>
<Label For="isDeleted" HelpText="Is this site deleted?" ResourceKey="IsDeleted">Is Deleted? </Label>
</td>
<td>
<select id="isDeleted" class="form-control" @bind="@_isdeleted">
<option value="True">@Localizer["Yes"]</option>
<option value="False">@Localizer["No"]</option>
</select>
</td>
</tr>
</table>
}
<tr>
<td>
<Label For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
</td>
<td>
<select id="defaultContainer" class="form-control" @bind="@_containertype">
<option value="-">&lt;@Localizer["Select Container"]&gt;</option>
@foreach (var container in _containers)
{
<option value="@container.TypeName">@container.Name</option>
}
</select>
</td>
</tr>
<tr>
<td>
<Label For="defaultAdminContainer" HelpText="Select the default admin container for the site" ResourceKey="DefaultAdminContainer">Default Admin Container: </Label>
</td>
<td>
<select id="defaultAdminContainer" class="form-control" @bind="@_admincontainertype">
<option value="-">&lt;@Localizer["Select Container"]&gt;</option>
<option value="">&lt;@Localizer["Default Admin Container"]&gt;</option>
@foreach (var container in _containers)
{
<option value="@container.TypeName">@container.Name</option>
}
</select>
</td>
</tr>
<tr>
<td>
<Label For="allowRegister" HelpText="Do you want the users to be able to register for an account on the site" ResourceKey="AllowRegistration">Allow User Registration? </Label>
</td>
<td>
<select id="allowRegister" class="form-control" @bind="@_allowregistration">
<option value="True">@Localizer["Yes"]</option>
<option value="False">@Localizer["No"]</option>
</select>
</td>
</tr>
<tr>
<td>
<Label For="isDeleted" HelpText="Is this site deleted?" ResourceKey="IsDeleted">Is Deleted? </Label>
</td>
<td>
<select id="isDeleted" class="form-control" @bind="@_isdeleted">
<option value="True">@Localizer["Yes"]</option>
<option value="False">@Localizer["No"]</option>
</select>
</td>
</tr>
</table>
<Section Name="SMTP" Heading="SMTP Settings" ResourceKey="SMTPSettings">
<table class="table table-borderless">
@ -244,6 +259,7 @@
private string _themetype = "-";
private string _layouttype = "-";
private string _containertype = "-";
private string _admincontainertype = "-";
private string _allowregistration;
private string _smtphost = string.Empty;
private string _smtpport = string.Empty;
@ -298,6 +314,7 @@
_layouttype = site.DefaultLayoutType;
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
_containertype = site.DefaultContainerType;
_admincontainertype = site.AdminContainerType;
_allowregistration = site.AllowRegistration.ToString();
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
@ -365,6 +382,7 @@
}
_layouttype = "-";
_containertype = "-";
_admincontainertype = "";
StateHasChanged();
}
catch (Exception ex)
@ -405,6 +423,7 @@
site.DefaultThemeType = _themetype;
site.DefaultLayoutType = (_layouttype == "-" ? string.Empty : _layouttype);
site.DefaultContainerType = _containertype;
site.AdminContainerType = _admincontainertype;
site.AllowRegistration = (_allowregistration == null ? true : Boolean.Parse(_allowregistration));
site.IsDeleted = (_isdeleted == null ? true : Boolean.Parse(_isdeleted));

View File

@ -78,6 +78,21 @@ else
</select>
</td>
</tr>
<tr>
<td>
<Label For="adminContainer" HelpText="Select the admin container for the site" ResourceKey="AdminContainer">Admin Container: </Label>
</td>
<td>
<select id="adminContainer" class="form-control" @bind="@_admincontainertype">
<option value="-">&lt;@Localizer["Select Container"]&gt;</option>
<option value="">&lt;@Localizer["Default Admin Container"]&gt;</option>
@foreach (var container in _containers)
{
<option value="@container.TypeName">@container.Name</option>
}
</select>
</td>
</tr>
<tr>
<td>
<Label For="siteTemplate" HelpText="Select the site template" ResourceKey="SiteTemplate">Site Template: </Label>
@ -225,6 +240,7 @@ else
private string _themetype = "-";
private string _layouttype = "-";
private string _containertype = "-";
private string _admincontainertype = "";
private string _sitetemplatetype = "-";
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
@ -278,6 +294,7 @@ else
}
_layouttype = "-";
_containertype = "-";
_admincontainertype = "";
StateHasChanged();
}
catch (Exception ex)
@ -378,6 +395,7 @@ else
config.DefaultTheme = _themetype;
config.DefaultLayout = _layouttype;
config.DefaultContainer = _containertype;
config.DefaultAdminContainer = _admincontainertype;
config.SiteTemplate = _sitetemplatetype;
ShowProgressIndicator();

View File

@ -18,14 +18,6 @@
<input id="name" class="form-control" @bind="@_name" />
</td>
</tr>
<tr>
<td>
<Label For="tenant" HelpText="Enter the tenant for the site" ResourceKey="Tenant">Tenant: </Label>
</td>
<td>
<input id="tenant" class="form-control" @bind="@_tenant" readonly />
</td>
</tr>
<tr>
<td>
<Label For="alias" HelpText="Enter the alias for the server" ResourceKey="Aliases">Aliases: </Label>
@ -86,6 +78,21 @@
</select>
</td>
</tr>
<tr>
<td>
<Label For="defaultAdminContainer" HelpText="Select the default admin container for the site" ResourceKey="DefaultAdminContainer">Default Admin Container: </Label>
</td>
<td>
<select id="defaultAdminContainer" class="form-control" @bind="@_admincontainertype">
<option value="-">&lt;@Localizer["Select Container"]&gt;</option>
<option value="">&lt;@Localizer["Default Admin Container"]&gt;</option>
@foreach (var container in _containers)
{
<option value="@container.TypeName">@container.Name</option>
}
</select>
</td>
</tr>
<tr>
<td>
<Label For="isDeleted" HelpText="Has this site been deleted?" ResourceKey="IsDeleted">Is Deleted? </Label>
@ -97,6 +104,23 @@
</select>
</td>
</tr>
<tr>
<td>
<Label For="tenant" HelpText="The tenant for the site" ResourceKey="Tenant">Tenant: </Label>
</td>
<td>
<input id="tenant" class="form-control" @bind="@_tenant" readonly />
</td>
</tr>
<tr>
<td>
<Label For="connectionstring" HelpText="The database connection string" ResourceKey="ConnectionString">Connection String: </Label>
</td>
<td>
<textarea id="connectionstring" class="form-control" @bind="@_connectionstring" rows="3" readonly></textarea>
</td>
</tr>
</table>
<br />
<button type="button" class="btn btn-success" @onclick="SaveSite">@Localizer["Save"]</button>
@ -114,13 +138,12 @@
private List<ThemeControl> _containers = new List<ThemeControl>();
private Alias _alias;
private string _name = string.Empty;
private List<Tenant> _tenantList;
private string _tenant = string.Empty;
private List<Alias> _aliasList;
private string _urls = string.Empty;
private string _themetype;
private string _layouttype;
private string _containertype;
private string _containertype = "-";
private string _admincontainertype = "-";
private string _createdby;
private DateTime _createdon;
private string _modifiedby;
@ -128,6 +151,8 @@
private string _deletedby;
private DateTime? _deletedon;
private string _isdeleted;
private string _tenant = string.Empty;
private string _connectionstring = string.Empty;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
@ -144,8 +169,6 @@
if (site != null)
{
_name = site.Name;
_tenantList = await TenantService.GetTenantsAsync();
_tenant = _tenantList.Find(item => item.TenantId == site.TenantId).Name;
foreach (Alias alias in _aliasList.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList())
{
@ -158,6 +181,7 @@
_layouttype = site.DefaultLayoutType;
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
_containertype = site.DefaultContainerType;
_admincontainertype = site.AdminContainerType;
_createdby = site.CreatedBy;
_createdon = site.CreatedOn;
_modifiedby = site.ModifiedBy;
@ -166,6 +190,14 @@
_deletedon = site.DeletedOn;
_isdeleted = site.IsDeleted.ToString();
List<Tenant> tenants = await TenantService.GetTenantsAsync();
Tenant tenant = tenants.Find(item => item.TenantId == site.TenantId);
if (tenant != null)
{
_tenant = tenant.Name;
_connectionstring = tenant.DBConnectionString;
}
_initialized = true;
}
}
@ -193,6 +225,7 @@
}
_layouttype = "-";
_containertype = "-";
_admincontainertype = "";
StateHasChanged();
}
catch (Exception ex)
@ -228,6 +261,7 @@
site.DefaultThemeType = _themetype;
site.DefaultLayoutType = _layouttype ?? string.Empty;
site.DefaultContainerType = _containertype;
site.AdminContainerType = _admincontainertype;
site.IsDeleted = (_isdeleted == null || Boolean.Parse(_isdeleted));
site = await SiteService.UpdateSiteAsync(site);

View File

@ -1,86 +0,0 @@
@namespace Oqtane.Modules.Admin.Tenants
@inherits ModuleBase
@inject NavigationManager NavigationManager
@inject ITenantService TenantService
@inject IStringLocalizer<Edit> Localizer
<table class="table table-borderless">
<tr>
<td>
<Label For="name" HelpText="The name of the tenant" ResourceKey="Name">Name: </Label>
</td>
<td>
@if (name == TenantNames.Master)
{
<input id="name" class="form-control" @bind="@name" readonly />
}
else
{
<input id="name" class="form-control" @bind="@name" />
}
</td>
</tr>
<tr>
<td>
<Label For="connectionstring" HelpText="The database connection string" ResourceKey="ConnectionString">Connection String: </Label>
</td>
<td>
<textarea id="connectionstring" class="form-control" @bind="@connectionstring" rows="3" readonly></textarea>
</td>
</tr>
</table>
<button type="button" class="btn btn-success" @onclick="SaveTenant">@Localizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
@code {
private int tenantid;
private string name = string.Empty;
private string connectionstring = string.Empty;
private string schema = string.Empty;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
protected override async Task OnInitializedAsync()
{
try
{
tenantid = Int32.Parse(PageState.QueryString["id"]);
var tenant = await TenantService.GetTenantAsync(tenantid);
if (tenant != null)
{
name = tenant.Name;
connectionstring = tenant.DBConnectionString;
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Loading Tenant {TenantId} {Error}", tenantid, ex.Message);
AddModuleMessage(Localizer["Error Loading Tenant"], MessageType.Error);
}
}
private async Task SaveTenant()
{
try
{
connectionstring = connectionstring.Replace("\\\\", "\\");
var tenant = await TenantService.GetTenantAsync(tenantid);
if (tenant != null)
{
tenant.Name = name;
tenant.DBConnectionString = connectionstring;
await TenantService.UpdateTenantAsync(tenant);
await logger.LogInformation("Tenant Saved {TenantId}", tenantid);
NavigationManager.NavigateTo(NavigateUrl());
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Saving Tenant {TenantId} {Error}", tenantid, ex.Message);
AddModuleMessage(Localizer["Error Saving Tenant"], MessageType.Error);
}
}
}

View File

@ -1,68 +0,0 @@
@namespace Oqtane.Modules.Admin.Tenants
@inherits ModuleBase
@inject ITenantService TenantService
@inject IAliasService AliasService
@inject IStringLocalizer<Index> Localizer
@if (tenants == null)
{
<p><em>@Localizer["Loading..."]</em></p>
}
else
{
<Pager Items="@tenants">
<Header>
<th style="width: 1px;">&nbsp;</th>
<th style="width: 1px;">&nbsp;</th>
<th>@Localizer["Name"]</th>
</Header>
<Row>
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.TenantId.ToString())" ResourceKey="EditTenant" /></td>
<td><ActionDialog Header="Delete Tenant" Message="@Localizer["Are You Sure You Wish To Delete The {0} Tenant?", context.Name]" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteTenant(context))" Disabled="@(context.Name == TenantNames.Master)" ResourceKey="DeleteTenant" /></td>
<td>@context.Name</td>
</Row>
</Pager>
}
@code {
private List<Tenant> tenants;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
protected override async Task OnParametersSetAsync()
{
tenants = await TenantService.GetTenantsAsync();
}
private async Task DeleteTenant(Tenant Tenant)
{
try
{
string message = string.Empty;
var aliases = await AliasService.GetAliasesAsync();
foreach (var alias in aliases)
{
if (alias.TenantId == Tenant.TenantId)
{
message += ", " + alias.Name;
}
}
if (string.IsNullOrEmpty(message))
{
await TenantService.DeleteTenantAsync(Tenant.TenantId);
await logger.LogInformation("Tenant Deleted {Tenant}", Tenant);
StateHasChanged();
}
else
{
AddModuleMessage(Localizer["Tenant Cannot Be Deleted Until The Following Sites Are Deleted: {0}", message.Substring(2)], MessageType.Warning);
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Deleting Tenant {Tenant} {Error}", Tenant, ex.Message);
AddModuleMessage(Localizer["Error Deleting Tenant"], MessageType.Error);
}
}
}

View File

@ -49,7 +49,7 @@ else
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
protected override async Task OnInitializedAsync()
protected override async Task OnParametersSetAsync()
{
try
{
@ -101,7 +101,8 @@ else
try
{
await ThemeService.DeleteThemeAsync(Theme.ThemeName);
AddModuleMessage(Localizer["Theme Deleted Successfully. You Must <a href=\"{0}\">Restart</a> Your Application To Apply These Changes.", NavigateUrl("admin/system")], MessageType.Success);
AddModuleMessage(Localizer["Theme Deleted Successfully"], MessageType.Success);
StateHasChanged();
}
catch (Exception ex)
{

View File

@ -3,6 +3,43 @@
@typeparam TableItem
<p>
@if (Toolbar == "Top")
{
<div class="mx-auto text-center">
@if (_endPage > 1)
{
<button class="btn btn-secondary mr-1" @onclick=@(async () => UpdateList(1))><span class="oi oi-media-step-backward" title="first" aria-hidden="true"></span></button>
}
@if (_page > _maxPages)
{
<button class="btn btn-secondary mr-1" @onclick=@(async () => SetPagerSize("back"))><span class="oi oi-media-skip-backward" title="back" aria-hidden="true"></span></button>
}
@if (_endPage > 1)
{
<button class="btn btn-secondary mr-1" @onclick=@(async () => NavigateToPage("previous"))><span class="oi oi-chevron-left" title="previous" aria-hidden="true"></span></button>
@for (int i = _startPage; i <= _endPage; i++)
{
var pager = i;
<button class="btn @((pager == _page) ? "btn-primary" : "btn-link")" @onclick=@(async () => UpdateList(pager))>
@pager
</button>
}
<button class="btn btn-secondary mr-1" @onclick=@(async () => NavigateToPage("next"))><span class="oi oi-chevron-right" title="next" aria-hidden="true"></span></button>
}
@if (_endPage < _pages)
{
<button class="btn btn-secondary mr-1" @onclick=@(async () => SetPagerSize("forward"))><span class="oi oi-media-skip-forward" title="forward" aria-hidden="true"></span></button>
}
@if (_endPage > 1)
{
<button class="btn btn-secondary mr-1" @onclick=@(async () => UpdateList(_pages))><span class="oi oi-media-step-forward" title="last" aria-hidden="true"></span></button>
}
@if (_endPage > 1)
{
<span class="btn btn-link disabled">Page @_page of @_pages</span>
}
</div>
}
@if (Format == "Table")
{
<table class="@Class">
@ -35,32 +72,43 @@
}
</div>
}
<div class="mx-auto text-center">
@if (_page > _maxPages)
{
<button class="btn btn-secondary" @onclick=@(async () => SetPagerSize("back"))><span class="oi oi-media-skip-backward" title="back" aria-hidden="true"></span></button>
}
@if (_endPage > 1)
{
<button class="btn btn-secondary" @onclick=@(async () => NavigateToPage("previous"))><span class="oi oi-chevron-left" title="previous" aria-hidden="true"></span></button>
@for (int i = _startPage; i <= _endPage; i++)
@if (Toolbar == "Bottom")
{
<div class="mx-auto text-center">
@if (_endPage > 1)
{
var pager = i;
<button class="btn @((pager == _page) ? "btn-primary" : "btn-link")" @onclick=@(async () => UpdateList(pager))>
@pager
</button>
<button class="btn btn-secondary mr-1" @onclick=@(async () => UpdateList(1))><span class="oi oi-media-step-backward" title="first" aria-hidden="true"></span></button>
}
<button class="btn btn-secondary" @onclick=@(async () => NavigateToPage("next"))><span class="oi oi-chevron-right" title="next" aria-hidden="true"></span></button>
}
@if (_endPage < _pages)
{
<button class="btn btn-secondary" @onclick=@(async () => SetPagerSize("forward"))><span class="oi oi-media-skip-forward" title="forward" aria-hidden="true"></span></button>
}
@if (_endPage > 1)
{
<span class="btn btn-link disabled">Page @_page of @_pages</span>
}
</div>
@if (_page > _maxPages)
{
<button class="btn btn-secondary mr-1" @onclick=@(async () => SetPagerSize("back"))><span class="oi oi-media-skip-backward" title="back" aria-hidden="true"></span></button>
}
@if (_endPage > 1)
{
<button class="btn btn-secondary mr-1" @onclick=@(async () => NavigateToPage("previous"))><span class="oi oi-chevron-left" title="previous" aria-hidden="true"></span></button>
@for (int i = _startPage; i <= _endPage; i++)
{
var pager = i;
<button class="btn @((pager == _page) ? "btn-primary" : "btn-link")" @onclick=@(async () => UpdateList(pager))>
@pager
</button>
}
<button class="btn btn-secondary mr-1" @onclick=@(async () => NavigateToPage("next"))><span class="oi oi-chevron-right" title="next" aria-hidden="true"></span></button>
}
@if (_endPage < _pages)
{
<button class="btn btn-secondary mr-1" @onclick=@(async () => SetPagerSize("forward"))><span class="oi oi-media-skip-forward" title="forward" aria-hidden="true"></span></button>
}
@if (_endPage > 1)
{
<button class="btn btn-secondary mr-1" @onclick=@(async () => UpdateList(_pages))><span class="oi oi-media-step-forward" title="last" aria-hidden="true"></span></button>
}
@if (_endPage > 1)
{
<span class="btn btn-link disabled">Page @_page of @_pages</span>
}
</div>
}
</p>
@code {
@ -74,6 +122,9 @@
[Parameter]
public string Format { get; set; }
[Parameter]
public string Toolbar { get; set; }
[Parameter]
public RenderFragment Header { get; set; }
@ -104,6 +155,11 @@
Format = "Table";
}
if (string.IsNullOrEmpty(Toolbar))
{
Toolbar = "Top";
}
if (string.IsNullOrEmpty(Class))
{
if (Format == "Table")