Improvements to themes, layouts, and CSS styling

This commit is contained in:
Shaun Walker
2019-10-16 14:28:49 -04:00
parent c029e70783
commit 05a405e036
51 changed files with 11843 additions and 777 deletions

View File

@ -1,15 +1,18 @@
@namespace Oqtane.Themes
@inherits ContainerBase
<div id="modal" class="app-admin-modal" style="display: block">
<div class="app-admin-modal-content">
<a href="@closeurl" class="app-admin-modal-close">x</a>
<div class="container">
<div class="row px-4">
<h2><ModuleTitle /></h2>
<hr style="width: 100%; color: gray; height: 1px; background-color:gray;" />
</div>
<div class="row px-4">
<div class="container">
@inject NavigationManager NavigationManager
<div class="app-admin-modal">
<div class="modal" style="display: block">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><ModuleTitle /></h5>
<button type="button" class="close" @onclick="CloseModal" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<ModuleInstance />
</div>
</div>
@ -18,11 +21,9 @@
</div>
@code {
string closeurl;
protected override void OnInitialized()
private void CloseModal()
{
closeurl = NavigateUrl();
NavigationManager.NavigateTo(NavigateUrl());
}
}

View File

@ -0,0 +1,13 @@
@namespace Oqtane.Themes.BlazorTheme
@inherits ContainerBase
<div class="container">
<div class="row px-4">
<ModuleActions /><h2><ModuleTitle /></h2>
<hr class="app-rule" />
</div>
<div class="row px-4">
<div class="container">
<ModuleInstance />
</div>
</div>
</div>

View File

@ -3,19 +3,16 @@
<div class="sidebar">
<div align="center"><Logo /></div>
<Menu />
<Menu Orientation="Vertical" />
</div>
<div class="main">
<div class="top-row px-4">
<h1>@PageState.Page.Name</h1> <div class="ml-md-auto"><UserProfile /> <Login /> <ControlPanel /></div>
<Breadcrumbs /> <div class="ml-md-auto"><UserProfile /> <Login /> <ControlPanel /></div>
</div>
<div class="container">
<div class="row px-4">
<Pane Name="Top" />
</div>
<div class="row px-4">
<Pane Name="Bottom" />
<Pane Name="Content" />
</div>
<div class="row px-4">
<Pane Name="Admin" />
@ -24,7 +21,7 @@
</div>
@code {
public override string Panes { get { return "Top;Bottom"; } }
public override string Panes { get { return "Content"; } }
protected override async Task OnParametersSetAsync()
{

View File

@ -0,0 +1,31 @@
@namespace Oqtane.Themes.Controls
@inherits ThemeControlBase
@if (breadcrumbs != "")
{
@((MarkupString)breadcrumbs)
}
@code {
string breadcrumbs = "";
protected override void OnParametersSet()
{
breadcrumbs = "";
int? pageid = PageState.Page.PageId;
for (int i = PageState.Pages.Count - 1; i >= 0; i--)
{
Page p = PageState.Pages[i];
if (p.PageId == pageid)
{
breadcrumbs = "<li class=\"breadcrumb-item" + ((p.PageId == PageState.Page.PageId) ? " active" : "") +
"\"><a href=\"" + NavigateUrl(p.Path) + "\">" + p.Name + "</a></li>" + breadcrumbs;
pageid = p.ParentId;
}
}
if (breadcrumbs != "")
{
breadcrumbs = "<ol class=\"breadcrumb\">" + breadcrumbs + "</ol>";
}
}
}

View File

@ -9,58 +9,87 @@
@if (UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions))
{
<div id="actions" class="app-controlpanel">
<a href="javascript:void(0)" class="app-controlpanel-close" onclick="closeActions()">x</a>
<div class="app-controlpanel-content">
<ul class="nav flex-column">
<li class="nav-item px-3">
<NavLink class="btn btn-primary mx-auto" href="@NavigateUrl("admin")">Admin Dashboard</NavLink>
</li>
</ul>
<ul class="nav flex-column">
<li class="nav-item px-3">
<NavLink class="btn btn-primary mx-auto" href="@PageUrl("Add")">Add Page</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="btn btn-primary mx-auto" href="@PageUrl("Edit")">Edit Page</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="btn btn-primary mx-auto" href="@PageUrl("Delete")">Delete Page</NavLink>
</li>
</ul>
<hr style="width: 100%; color: white; height: 1px; background-color:white;" />
<div class="container">
<div class="app-controlpanel" style="@display">
<div class="card @cardclass mb-3">
<div class="card-header">
Control Panel
<button type="button" class="close" @onclick="HideControlPanel" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="card-body">
<ul class="nav flex-column">
<li class="nav-item px-3"><button type="button" class="btn btn-primary btn-block mx-auto" @onclick=@(async () => Navigate("Admin"))>Admin Dashboard</button></li>
<li class="nav-item px-3">&nbsp;</li>
<li class="nav-item px-3"><button type="button" class="btn btn-primary btn-block mx-auto" @onclick=@(async () => Navigate("Add"))>Add Page</button></li>
<li class="nav-item px-3"><button type="button" class="btn btn-primary btn-block mx-auto" @onclick=@(async () => Navigate("Edit"))>Edit Page</button></li>
<li class="nav-item px-3"><button type="button" class="btn btn-primary btn-block mx-auto" @onclick=@(async () => Navigate("Delete"))>Delete Page</button></li>
</ul>
<hr class="app-rule" />
<table class="table table-borderless">
<tr>
<td>
<label for="Module" class="control-label" style="color: white !important;">Module: </label>
<label for="Module" class="control-label">Module: </label>
</td>
<td>
@if (moduledefinitions != null)
<select class="form-control" @bind="@moduletype">
<option value="new">Add New Module</option>
<option value="existing">Add Existing Module</option>
</select>
@if (moduletype == "new")
{
<select class="form-control" @onchange="(e => CategoryChanged(e))">
<option value="-">&lt;Common Modules&gt;</option>
@foreach (var category in categories)
{
<option value="@category">@category</option>
}
</select>
<select class="form-control" @bind="@moduledefinitionname">
<option value="">&lt;Select Module&gt;</option>
@foreach (var moduledefinition in moduledefinitions)
{
if (moduledefinition.Permissions == "[]" || UserSecurity.IsAuthorized(PageState.User, "Utilize", moduledefinition.Permissions))
@if (moduledefinitions != null)
{
<select class="form-control" @onchange="(e => CategoryChanged(e))">
<option value="-">&lt;Common Modules&gt;</option>
@foreach (var category in categories)
{
<option value="@moduledefinition.ModuleDefinitionName">@moduledefinition.Name</option>
<option value="@category">@category</option>
}
</select>
<select class="form-control" @bind="@moduledefinitionname">
<option value="">&lt;Select Module&gt;</option>
@foreach (var moduledefinition in moduledefinitions)
{
if (moduledefinition.Permissions == "[]" || UserSecurity.IsAuthorized(PageState.User, "Utilize", moduledefinition.Permissions))
{
<option value="@moduledefinition.ModuleDefinitionName">@moduledefinition.Name</option>
}
}
</select>
}
}
else
{
<select class="form-control" @onchange="(e => PageChanged(e))">
<option value="-">&lt;Select Page&gt;</option>
@foreach (Page p in pages)
{
<option value="@p.PageId">@p.Name</option>
}
</select>
<select class="form-control" @bind="@moduleid">
<option value="">&lt;Select Module&gt;</option>
@foreach (Module module in modules)
{
<option value="@module.ModuleId">@module.Title</option>
}
</select>
}
</td>
</tr>
<tr>
<td>
<label for="Pane" class="control-label" style="color: white !important;">Pane: </label>
<label for="Title" class="control-label">Title: </label>
</td>
<td>
<input type="text" name="Title" class="form-control" @bind="@title" />
</td>
</tr>
<tr>
<td>
<label for="Pane" class="control-label">Pane: </label>
</td>
<td>
<select class="form-control" @bind="@pane">
@ -74,15 +103,7 @@
</tr>
<tr>
<td>
<label for="Title" class="control-label" style="color: white !important;">Title: </label>
</td>
<td>
<input type="text" name="Title" class="form-control" @bind="@title" />
</td>
</tr>
<tr>
<td>
<label for="Container" class="control-label" style="color: white !important;">Container: </label>
<label for="Container" class="control-label">Container: </label>
</td>
<td>
<select class="form-control" @bind="@containertype">
@ -94,46 +115,71 @@
</td>
</tr>
</table>
<button type="button" class="btn btn-primary mx-auto" style="width: 100%;" @onclick="@AddModule">Add Module To Page</button>
<button type="button" class="btn btn-primary btn-block mx-auto" @onclick="@AddModule">Add Module To Page</button>
@((MarkupString)@message)
</div>
</div>
</div>
@if (PageState.EditMode)
{
<button type="button" class="btn btn-outline-primary active" data-toggle="button" aria-pressed="true" autocomplete="off" @onclick="EditMode">
<button type="button" class="btn @buttonclass active" data-toggle="button" aria-pressed="true" autocomplete="off" @onclick="EditMode">
<span class="oi oi-pencil"></span>
</button>
}
else
{
<button type="button" class="btn btn-outline-primary" data-toggle="button" aria-pressed="false" autocomplete="off" @onclick="EditMode">
<button type="button" class="btn @buttonclass" data-toggle="button" aria-pressed="false" autocomplete="off" @onclick="EditMode">
<span class="oi oi-pencil"></span>
</button>
}
<span class="oi oi-menu" onclick="openActions()"></span>
<button type="button" class="btn @buttonclass" @onclick="ShowControlPanel">
<span class="oi oi-menu"></span>
</button>
}
@code {
[Parameter]
public string ButtonClass { get; set; }
[Parameter]
public string CardClass { get; set; }
string moduletype = "new";
List<string> categories = new List<string>();
List<ModuleDefinition> moduledefinitions;
List<Page> pages = new List<Page>();
string moduleid = "";
List<Module> modules = new List<Module>();
Dictionary<string, string> containers = new Dictionary<string, string>();
int pagemanagementmoduleid = -1;
string moduledefinitionname = "";
string pane = "";
string title = "";
string containertype = "";
string display = "display: none;";
string buttonclass = "btn-outline-primary";
string cardclass = "text-white bg-secondary";
string message = "";
protected override async Task OnInitializedAsync()
{
if (!string.IsNullOrEmpty(ButtonClass))
{
buttonclass = ButtonClass;
}
if (!string.IsNullOrEmpty(CardClass))
{
cardclass = CardClass;
}
if (UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions))
{
foreach(ModuleDefinition moduledefinition in PageState.ModuleDefinitions)
foreach (ModuleDefinition moduledefinition in PageState.ModuleDefinitions)
{
if (moduledefinition.Categories != "")
{
foreach(string category in moduledefinition.Categories.Split(','))
foreach (string category in moduledefinition.Categories.Split(','))
{
if (!categories.Contains(category))
{
@ -143,8 +189,15 @@
}
}
moduledefinitions = PageState.ModuleDefinitions.Where(item => item.Categories == "").ToList();
foreach(Page p in PageState.Pages)
{
if (UserSecurity.IsAuthorized(PageState.User, "View", p.Permissions))
{
pages.Add(p);
}
}
containers = ThemeService.GetContainerTypes(PageState.Themes);
containertype = containers.FirstOrDefault().Key;
containertype = PageState.Site.DefaultContainerType;
List<Module> modules = await ModuleService.GetModulesAsync(PageState.Site.SiteId, Constants.PageManagementModule);
if (modules.Count > 0)
{
@ -168,30 +221,65 @@
StateHasChanged();
}
private async Task PageChanged(ChangeEventArgs e)
{
string pageid = (string)e.Value;
if (pageid != "")
{
foreach(Module module in await ModuleService.GetModulesAsync(int.Parse(pageid)))
{
if (UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions))
{
modules.Add(module);
}
}
}
moduleid = "";
StateHasChanged();
}
private async Task AddModule()
{
if (UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions))
{
Module module = new Module();
module.SiteId = PageState.Site.SiteId;
module.ModuleDefinitionName = moduledefinitionname;
module.Permissions = PageState.Page.Permissions;
module = await ModuleService.AddModuleAsync(module);
if (moduletype == "new")
{
Module module = new Module();
module.SiteId = PageState.Site.SiteId;
module.ModuleDefinitionName = moduledefinitionname;
module.Permissions = PageState.Page.Permissions;
module = await ModuleService.AddModuleAsync(module);
moduleid = module.ModuleId.ToString();
}
PageModule pagemodule = new PageModule();
pagemodule.PageId = PageState.Page.PageId;
pagemodule.ModuleId = module.ModuleId;
pagemodule.ModuleId = int.Parse(moduleid);
if (title == "")
{
title = moduledefinitions.Where(item => item.ModuleDefinitionName == moduledefinitionname).FirstOrDefault().Name;
if (moduletype == "new")
{
pagemodule.Title = moduledefinitions.Where(item => item.ModuleDefinitionName == moduledefinitionname).FirstOrDefault().Name;
}
else
{
pagemodule.Title = modules.Where(item => item.ModuleId == int.Parse(moduleid)).FirstOrDefault().Title;
}
}
pagemodule.Title = title;
pagemodule.Pane = pane;
pagemodule.Order = int.MaxValue;
pagemodule.ContainerType = containertype;
if (pagemodule.ContainerType == PageState.Site.DefaultContainerType)
{
pagemodule.ContainerType = "";
}
await PageModuleService.AddPageModuleAsync(pagemodule);
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
message = "<br /><div class=\"alert alert-success\" role=\"alert\">Module Added To Page</div>";
NavigationManager.NavigateTo(NavigateUrl(Reload.Page));
}
}
@ -231,7 +319,37 @@
PageState.EditMode = true;
PageState.DesignMode = true;
}
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "edit=" + PageState.EditMode.ToString().ToLower(), Reload.Page));
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "edit=" + ((PageState.EditMode) ? "1" : "0"), Reload.Page));
}
}
}
private void ShowControlPanel()
{
message = "";
display = "width: 25%;";
StateHasChanged();
}
private void HideControlPanel()
{
message = "";
display = "width: 0%;";
StateHasChanged();
}
private void Navigate(string location)
{
HideControlPanel();
switch (location)
{
case "Admin":
NavigationManager.NavigateTo(NavigateUrl("admin"));
break;
case "Add":
case "Edit":
case "Delete":
NavigationManager.NavigateTo(PageUrl(location));
break;
}
}
}

View File

@ -1,16 +1,33 @@
@namespace Oqtane.Themes.Controls
@inherits ThemeControlBase
@inject IUserService UserService
@if (menu != "")
{
@((MarkupString)menu)
<div class="app-menu">
@((MarkupString)menu)
</div>
}
@code {
[Parameter]
public string Orientation { get; set; }
string menu = "";
protected override void OnParametersSet()
{
switch (Orientation)
{
case "Horizontal":
CreateHorizontalMenu();
break;
default: // Vertical
CreateVerticalMenu();
break;
}
}
private void CreateVerticalMenu()
{
int level = -1;
int securitylevel = int.MaxValue;
@ -49,4 +66,33 @@
}
menu += "</ul>";
}
private void CreateHorizontalMenu()
{
menu = "<button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#Menu\" aria-controls=\"Menu\" aria-expanded=\"false\" aria-label=\"Toggle navigation\"><span class=\"navbar-toggler-icon\"></span></button>";
menu += "<div class=\"collapse navbar-collapse\" id=\"Menu\">";
menu += "<ul class=\"navbar-nav mr-auto\">";
foreach (Page p in PageState.Pages.Where(item => item.IsNavigation && !item.IsDeleted))
{
if (UserSecurity.IsAuthorized(PageState.User, "View", p.Permissions) && p.ParentId == PageState.Page.ParentId && p.Level == PageState.Page.Level)
{
if (p.PageId == PageState.Page.PageId)
{
menu += "<li class=\"nav-item active\">" +
"<a class=\"nav-link\" href=\"" + NavigateUrl(p.Path) + "\">" +
((p.Icon != "") ? "<span class=\"oi oi-" + p.Icon + "\" aria-hidden=\"true\"></span> " : "") +
p.Name + " <span class=\"sr-only\">(current)</span></a></li>";
}
else
{
menu += "<li class=\"nav-item\">" +
"<a class=\"nav-link\" href=\"" + NavigateUrl(p.Path) + "\">" +
((p.Icon != "") ? "<span class=\"oi oi-" + p.Icon + "\" aria-hidden=\"true\"></span> " : "") +
p.Name + "</a></li>";
}
}
}
menu += "</ul>";
menu += "</div>";
}
}

View File

@ -6,14 +6,19 @@
@if (PageState.DesignMode && UserSecurity.IsAuthorized(PageState.User, "Edit", ModuleState.Permissions))
{
<div class="dropdown">
<button type="button" class="btn app-actions-toggle" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
@foreach (var action in actions)
{
<a class="dropdown-item" @onclick="(async () => await ModuleAction(action.Action))">@action.Name</a>
}
</div>
<a class="nav-link dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"></a>
<div class="dropdown-menu" x-placement="bottom-start" style="position: absolute; will-change: transform; top: 0px; left: 0px; transform: translate3d(0px, 37px, 0px);">
@foreach (var action in actions)
{
if (action.Action != "")
{
<a class="dropdown-item" @onclick="(async () => await ModuleAction(action.Action))">@action.Name</a>
}
else
{
<div class="dropdown-divider"></div>
}
}
</div>
}
@ -25,6 +30,14 @@
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, "Edit", ModuleState.Permissions))
{
actions = new List<ActionViewModel>();
actions.Add(new ActionViewModel { Action = "settings", Name = "Manage Settings" });
if (ModuleDefinition.ServerAssemblyName != "")
{
actions.Add(new ActionViewModel { Action = "import", Name = "Import Content" });
actions.Add(new ActionViewModel { Action = "export", Name = "Export Content" });
}
actions.Add(new ActionViewModel { Action = "delete", Name = "Delete Module" });
actions.Add(new ActionViewModel { Action = "", Name = "" });
if (ModuleState.PaneModuleIndex > 0)
{
actions.Add(new ActionViewModel { Action = "<<", Name = "Move To Top" });
@ -48,13 +61,6 @@
actions.Add(new ActionViewModel { Action = pane, Name = "Move To " + pane + " Pane" });
}
}
actions.Add(new ActionViewModel { Action = "settings", Name = "Manage Settings" });
if (ModuleDefinition.ServerAssemblyName != "")
{
actions.Add(new ActionViewModel { Action = "import", Name = "Import Content" });
actions.Add(new ActionViewModel { Action = "export", Name = "Export Content" });
}
actions.Add(new ActionViewModel { Action = "delete", Name = "Delete Module" });
}
}

View File

@ -1,7 +1,7 @@
@namespace Oqtane.Themes.Controls
@inherits ContainerBase
@title
@((MarkupString)title)
@code {
string title = "";

View File

@ -2,6 +2,7 @@
{
public interface ILayoutControl
{
string Panes { get; } // identifies all panes in a theme ( delimited by ";" )
}
}

View File

@ -3,7 +3,7 @@
<div class="container">
<div class="row px-4">
<ModuleActions /><h2><ModuleTitle /></h2>
<hr style="width: 100%; color: gray; height: 1px; background-color:gray;" />
<hr class="app-rule" />
</div>
<div class="row px-4">
<div class="container">

View File

@ -1,33 +1,23 @@
@namespace Oqtane.Themes.OqtaneTheme
@inherits ThemeBase
<div class="sidebar">
<div align="center"><Logo /></div>
<Menu />
</div>
<div class="main">
<div class="top-row px-4">
<h1>@PageState.Page.Name</h1> <div class="ml-md-auto"><UserProfile /> <Login /> <ControlPanel /></div>
</div>
<main role="main">
<nav class="navbar navbar-expand-md navbar-dark bg-primary fixed-top">
<Logo /><Menu Orientation="Horizontal" /><div class="ml-md-auto"><UserProfile /> <Login /> <ControlPanel ButtonClass="btn-outline-secondary" CardClass="bg-light" /></div>
</nav>
<div class="container">
<div class="row px-4">
<Pane Name="Top" />
</div>
<div class="row px-4">
<Pane Name="Bottom" />
</div>
<PaneLayout />
<div class="row px-4">
<Pane Name="Admin" />
</div>
</div>
</div>
</main>
@code {
public override string Panes { get { return "Left;Right"; } }
public override string Panes { get { return ""; } }
protected override async Task OnParametersSetAsync()
{
await IncludeCSS("Theme.css");
}
}
}

View File

@ -1,15 +0,0 @@
@namespace Oqtane.Themes.OqtaneTheme
@inherits LayoutBase
<div class="row px-4">
<div class="col-sm">
<Pane Name="Left" />
</div>
<div class="col-sm">
<Pane Name="Right" />
</div>
</div>
@code {
public override string Panes { get { return "Left;Right"; } }
}

View File

@ -1,26 +0,0 @@
@namespace Oqtane.Themes.OqtaneTheme
@inherits ThemeBase
<div class="sidebar">
<div align="center"><Logo /></div>
<Menu />
</div>
<div class="main">
<div class="top-row px-4">
<h1>@PageState.Page.Name</h1> <div class="ml-md-auto"><UserProfile /> <Login /> <ControlPanel /></div>
</div>
<div class="container">
<PaneLayout />
<div class="row px-4">
<Pane Name="Admin" />
</div>
</div>
</div>
@code {
protected override async Task OnParametersSetAsync()
{
await IncludeCSS("Theme.css");
}
}

View File

@ -0,0 +1,18 @@
@namespace Oqtane.Themes.OqtaneTheme
@inherits LayoutBase
<div class="row px-4">
<Pane Name="Top" />
</div>
<div class="row px-4">
<div class="col-sm"><Pane Name="Left" /></div>
<div class="col-sm"><Pane Name="Content" /></div>
<div class="col-sm"><Pane Name="Right" /></div>
</div>
<div class="row px-4">
<Pane Name="Bottom" />
</div>
@code {
public override string Panes { get { return "Top;Left;Content;Right;Bottom"; } }
}

View File

@ -0,0 +1,10 @@
@namespace Oqtane.Themes.OqtaneTheme
@inherits LayoutBase
<div class="row px-4">
<Pane Name="Content" />
</div>
@code {
public override string Panes { get { return "Content"; } }
}

View File

@ -1,13 +0,0 @@
@namespace Oqtane.Themes.OqtaneTheme
@inherits LayoutBase
<div class="row px-4">
<Pane Name="Top" />
</div>
<div class="row px-4">
<Pane Name="Bottom" />
</div>
@code {
public override string Panes { get { return "Top;Bottom"; } }
}