Components based on Bootstrap4 for Sections and TabStrip to increase productivity and promote uniformity in Module UIs (#333)
* upgrade to .NET Core 3.2 Preview 3 and fixes for issues created by #314 * Components based on Bootstrap4 for Sections and TabStrip to increase productivity and promote uniformity in Module UIs
This commit is contained in:
parent
c38dff5e7c
commit
d8b15e7a4e
@ -5,80 +5,62 @@
|
||||
@inject IModuleService ModuleService
|
||||
@inject IPageService PageService
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="form-group">
|
||||
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" data-toggle="tab" href="#Pages" role="tab">
|
||||
Pages
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#Modules" role="tab">
|
||||
Modules
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
<div id="Pages" class="tab-pane fade show active" role="tabpanel">
|
||||
@if (_pages == null)
|
||||
{
|
||||
<br />
|
||||
<p>No Deleted Pages</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<Pager Items="@_pages">
|
||||
<Header>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th>Name</th>
|
||||
<th>Deleted By</th>
|
||||
<th>Deleted On</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td><button @onclick="@(() => RestorePage(context))" class="btn btn-info" title="Restore">Restore</button></td>
|
||||
<td><ActionDialog Header="Delete Page" Message="@("Are You Sure You Wish To Permanently Delete The " + context.Name + " Page?")" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeletePage(context))" /></td>
|
||||
<td>@context.Name</td>
|
||||
<td>@context.DeletedBy</td>
|
||||
<td>@context.DeletedOn</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
</div>
|
||||
<div id="Modules" class="tab-pane fade" role="tabpanel">
|
||||
@if (_modules == null)
|
||||
{
|
||||
<br />
|
||||
<p>No Deleted Modules</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<Pager Items="@_modules">
|
||||
<Header>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th>Page</th>
|
||||
<th>Module</th>
|
||||
<th>Deleted By</th>
|
||||
<th>Deleted On</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td><button @onclick="@(() => RestoreModule(context))" class="btn btn-info" title="Restore">Restore</button></td>
|
||||
<td><ActionDialog Header="Delete Module" Message="@("Are You Sure You Wish To Permanently Delete The " + context.Title + " Module?")" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" /></td>
|
||||
<td>@PageState.Pages.Find(item => item.PageId == context.PageId).Name</td>
|
||||
<td>@context.Title</td>
|
||||
<td>@context.DeletedBy</td>
|
||||
<td>@context.DeletedOn</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<TabStrip>
|
||||
<TabPanel Name="Pages">
|
||||
@if (_pages == null)
|
||||
{
|
||||
<br />
|
||||
<p>No Deleted Pages</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<Pager Items="@_pages">
|
||||
<Header>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th>Name</th>
|
||||
<th>Deleted By</th>
|
||||
<th>Deleted On</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td><button @onclick="@(() => RestorePage(context))" class="btn btn-info" title="Restore">Restore</button></td>
|
||||
<td><ActionDialog Header="Delete Page" Message="@("Are You Sure You Wish To Permanently Delete The " + context.Name + " Page?")" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeletePage(context))" /></td>
|
||||
<td>@context.Name</td>
|
||||
<td>@context.DeletedBy</td>
|
||||
<td>@context.DeletedOn</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
</TabPanel>
|
||||
<TabPanel Name="Modules">
|
||||
@if (_modules == null)
|
||||
{
|
||||
<br />
|
||||
<p>No Deleted Modules</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<Pager Items="@_modules">
|
||||
<Header>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th>Page</th>
|
||||
<th>Module</th>
|
||||
<th>Deleted By</th>
|
||||
<th>Deleted On</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td><button @onclick="@(() => RestoreModule(context))" class="btn btn-info" title="Restore">Restore</button></td>
|
||||
<td><ActionDialog Header="Delete Module" Message="@("Are You Sure You Wish To Permanently Delete The " + context.Title + " Module?")" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" /></td>
|
||||
<td>@PageState.Pages.Find(item => item.PageId == context.PageId).Name</td>
|
||||
<td>@context.Title</td>
|
||||
<td>@context.DeletedBy</td>
|
||||
<td>@context.DeletedOn</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
</TabPanel>
|
||||
</TabStrip>
|
||||
|
||||
@code {
|
||||
private List<Page> _pages;
|
||||
|
@ -123,10 +123,7 @@
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<a data-toggle="collapse" class="app-link-unstyled" href="#SMTP" aria-expanded="false" aria-controls="SMTP">
|
||||
<h5><i class="oi oi-chevron-bottom"></i> SMTP Settings</h5><hr class="app-rule" />
|
||||
</a>
|
||||
<div class="collapse" id="SMTP">
|
||||
<Section Name="SMTP" Heading="SMTP Settings">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
@ -169,12 +166,8 @@
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<a data-toggle="collapse" class="app-link-unstyled" href="#PWA" aria-expanded="false" aria-controls="PWA">
|
||||
<h5><i class="oi oi-chevron-bottom"></i> Progressive Web Application Settings</h5><hr class="app-rule" />
|
||||
</a>
|
||||
<div class="collapse" id="PWA">
|
||||
</Section>
|
||||
<Section Name="PWA" Heading="Progressive Web Application Settings">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
@ -203,9 +196,8 @@
|
||||
<FileManager FileId="@_pwasplashiconfileid.ToString()" Filter="png" @ref="_pwasplashiconfilemanager" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveSite">Save</button>
|
||||
|
@ -15,7 +15,7 @@ else
|
||||
private string _closeLabel = "</label>";
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; } // required - the title of the label
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string For { get; set; } // optional - the id of the associated input control for accessibility
|
||||
|
44
Oqtane.Client/Modules/Controls/Section.razor
Normal file
44
Oqtane.Client/Modules/Controls/Section.razor
Normal file
@ -0,0 +1,44 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
|
||||
<div class="d-flex">
|
||||
<div>
|
||||
<a data-toggle="collapse" class="app-link-unstyled" href="#@Name" aria-expanded="@_expanded" aria-controls="@Name">
|
||||
<h5>@_heading</h5>
|
||||
</a>
|
||||
</div>
|
||||
<div class="ml-auto">
|
||||
<a data-toggle="collapse" class="app-link-unstyled float-right" href="#@Name" aria-expanded="@_expanded" aria-controls="@Name">
|
||||
<i class="oi oi-chevron-bottom"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex">
|
||||
<hr class="app-rule" />
|
||||
</div>
|
||||
<div class="collapse" id="@Name">
|
||||
@ChildContent
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private string _heading = string.Empty;
|
||||
private string _expanded = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Name { get; set; } // required - the name of the section
|
||||
|
||||
[Parameter]
|
||||
public string Heading { get; set; } // optional - will default to Name if not provided
|
||||
|
||||
[Parameter]
|
||||
public string Expanded { get; set; } // optional - will default to false if not provided
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_heading = (!string.IsNullOrEmpty(Heading)) ? Heading : Name;
|
||||
_expanded = (!string.IsNullOrEmpty(Expanded)) ? Expanded : "false";
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
|
||||
<CascadingValue Value="this">
|
||||
<div>
|
||||
@foreach (TabPanel tabPanel in _tabPanels)
|
||||
{
|
||||
<button type="button"
|
||||
class="btn @GetButtonClass(tabPanel)"
|
||||
@onclick=@( () => ActivateTabPanel(tabPanel) )>
|
||||
@tabPanel.Text
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
|
||||
@code {
|
||||
private List<TabPanel> _tabPanels = new List<TabPanel>();
|
||||
|
||||
// Next line is needed so we are able to add <TabPanel> components inside
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
public TabPanel ActiveTabPanel { get; set; }
|
||||
|
||||
internal void AddTabPanel(TabPanel tabPanel)
|
||||
{
|
||||
_tabPanels.Add(tabPanel);
|
||||
if (_tabPanels.Count == 1)
|
||||
ActiveTabPanel = tabPanel;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private string GetButtonClass(TabPanel tabPanel)
|
||||
=> tabPanel == ActiveTabPanel
|
||||
? "btn-primary"
|
||||
: "btn-secondary";
|
||||
|
||||
private void ActivateTabPanel(TabPanel tabPanel)
|
||||
{
|
||||
ActiveTabPanel = tabPanel;
|
||||
}
|
||||
}
|
@ -1,27 +1,35 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
|
||||
@if (Parent.ActiveTabPanel == (TabPanel)(object)this)
|
||||
@if (Name == Parent.ActiveTab)
|
||||
{
|
||||
@ChildContent
|
||||
<div id="@Name" class="tab-pane fade show active" role="tabpanel">
|
||||
@ChildContent
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div id="@Name" class="tab-pane fade" role="tabpanel">
|
||||
@ChildContent
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[CascadingParameter]
|
||||
private TabControl Parent { get; set; }
|
||||
private TabStrip Parent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Text { get; set; }
|
||||
public string Name { get; set; } // required - name of the TabPanel
|
||||
|
||||
[Parameter]
|
||||
public string Heading { get; set; } // optional - defaults to name if not specified
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
if (Parent == null)
|
||||
throw new ArgumentNullException(nameof(Parent), "TabPanel must exist within a TabControl");
|
||||
|
||||
base.OnInitialized();
|
||||
Parent.AddTabPanel((TabPanel)(object)this);
|
||||
Parent.AddTabPanel((TabPanel)this);
|
||||
}
|
||||
}
|
||||
|
56
Oqtane.Client/Modules/Controls/TabStrip.razor
Normal file
56
Oqtane.Client/Modules/Controls/TabStrip.razor
Normal file
@ -0,0 +1,56 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
|
||||
<CascadingValue Value="this">
|
||||
<div class="container-fluid">
|
||||
<div class="form-group">
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
@foreach (TabPanel tabPanel in _tabPanels)
|
||||
{
|
||||
<li class="nav-item">
|
||||
@if (tabPanel.Name == ActiveTab)
|
||||
{
|
||||
<a class="nav-link active" data-toggle="tab" href="#@tabPanel.Name" role="tab">
|
||||
@DisplayHeading(tabPanel.Name, tabPanel.Heading)
|
||||
</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<a class="nav-link" data-toggle="tab" href="#@tabPanel.Name" role="tab">
|
||||
@DisplayHeading(tabPanel.Name, tabPanel.Heading)
|
||||
</a>
|
||||
}
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<br />
|
||||
@ChildContent
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CascadingValue>
|
||||
|
||||
@code {
|
||||
private List<TabPanel> _tabPanels = new List<TabPanel>();
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; } // contains the TabPanels
|
||||
|
||||
[Parameter]
|
||||
public string ActiveTab { get; set; } // optional - defaults to first TabPanel if not specified
|
||||
|
||||
internal void AddTabPanel(TabPanel tabPanel)
|
||||
{
|
||||
_tabPanels.Add(tabPanel);
|
||||
if (string.IsNullOrEmpty(ActiveTab))
|
||||
{
|
||||
ActiveTab = tabPanel.Name;
|
||||
}
|
||||
}
|
||||
|
||||
private string DisplayHeading(string Name, string Heading)
|
||||
{
|
||||
return (string.IsNullOrEmpty(Heading)) ? Name : Heading;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user