commit
dec6658047
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 .NET Foundation
|
||||
Copyright (c) 2018-2020 .NET Foundation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -12,9 +12,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="3.2.0-preview3.20168.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" Version="3.2.0-preview3.20168.3" PrivateAssets="all" />
|
||||
<PackageReference Include="System.Net.Http.Json" Version="3.2.0-preview3.20175.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="3.2.0-preview5.20216.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" Version="3.2.0-preview5.20216.8" PrivateAssets="all" />
|
||||
<PackageReference Include="System.Net.Http.Json" Version="3.2.0-preview5.20210.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -23,7 +23,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="3.2.0-preview3.20168.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="3.2.0-preview5.20216.8" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.2" />
|
||||
|
@ -1,14 +1,27 @@
|
||||
@namespace Oqtane.Themes.BlazorTheme
|
||||
@inherits ThemeBase
|
||||
|
||||
<div class="breadcrumbs">
|
||||
<Breadcrumbs />
|
||||
</div>
|
||||
|
||||
<div class="sidebar">
|
||||
<div align="center"><Logo /></div>
|
||||
<Menu Orientation="Vertical" />
|
||||
<nav class="navbar">
|
||||
<Logo />
|
||||
<button class="navbar-toggler" aria-expanded="false" aria-controls="navbarSupportedContent"
|
||||
aria-label="Toggle navigation" type="button" data-toggle="collapse"
|
||||
data-target="#navbarSupportedContent">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<Menu Orientation="Vertical" />
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div class="main">
|
||||
<div class="top-row px-4">
|
||||
<Breadcrumbs /> <div class="ml-md-auto"><UserProfile /> <Login /> <ControlPanel /></div>
|
||||
<div class="ml-md-auto"><UserProfile /> <Login /> <ControlPanel /></div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="row px-4">
|
||||
|
@ -1,32 +1,34 @@
|
||||
@namespace Oqtane.Themes.Controls
|
||||
@inherits ThemeControlBase
|
||||
|
||||
@if (breadcrumbs != string.Empty)
|
||||
@if (BreadCrumbPages.Any())
|
||||
{
|
||||
@((MarkupString)breadcrumbs)
|
||||
<ol class="breadcrumb">
|
||||
@foreach (var p in BreadCrumbPages)
|
||||
{
|
||||
<li class="breadcrumb-item @ActiveClass(p)">
|
||||
<a href="@NavigateUrl(p.Path)">@p.Name</a>
|
||||
</li>
|
||||
}
|
||||
</ol>
|
||||
}
|
||||
|
||||
@code {
|
||||
string breadcrumbs = string.Empty;
|
||||
|
||||
protected override void OnParametersSet()
|
||||
protected IEnumerable<Page> BreadCrumbPages => GetBreadCrumbPages().Reverse().ToList();
|
||||
|
||||
protected string ActiveClass(Page page)
|
||||
{
|
||||
breadcrumbs = string.Empty;
|
||||
int? pageid = PageState.Page.PageId;
|
||||
for (int i = PageState.Pages.Count - 1; i >= 0; i--)
|
||||
return (page.PageId == PageState.Page.PageId) ? " active" : string.Empty;
|
||||
}
|
||||
|
||||
private IEnumerable<Page> GetBreadCrumbPages()
|
||||
{
|
||||
var page = PageState.Page;
|
||||
do
|
||||
{
|
||||
var p = PageState.Pages[i];
|
||||
if (p.PageId == pageid)
|
||||
{
|
||||
breadcrumbs = "<li class=\"breadcrumb-item" + ((p.PageId == PageState.Page.PageId) ? " active" : string.Empty) +
|
||||
"\"><a href=\"" + NavigateUrl(p.Path) + "\">" + p.Name + "</a></li>" + breadcrumbs;
|
||||
pageid = p.ParentId;
|
||||
}
|
||||
}
|
||||
|
||||
if (breadcrumbs != "")
|
||||
{
|
||||
breadcrumbs = "<ol class=\"breadcrumb\">" + breadcrumbs + "</ol>";
|
||||
}
|
||||
yield return page;
|
||||
page = PageState.Pages.FirstOrDefault(p => page != null && p.PageId == page.ParentId);
|
||||
} while (page != null);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,5 @@
|
||||
@namespace Oqtane.Themes.Controls
|
||||
@inherits ThemeControlBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IUserService UserService
|
||||
@inject IJSRuntime jsRuntime
|
||||
@inject IServiceProvider ServiceProvider
|
||||
@inherits LoginBase
|
||||
|
||||
<AuthorizeView>
|
||||
<Authorizing>
|
||||
@ -16,38 +12,3 @@
|
||||
<button type="button" class="btn btn-primary" @onclick="LoginUser">Login</button>
|
||||
</NotAuthorized>
|
||||
</AuthorizeView>
|
||||
|
||||
|
||||
@code {
|
||||
private void LoginUser()
|
||||
{
|
||||
var returnurl = PageState.Alias.Path;
|
||||
if (PageState.Page.Path != "/")
|
||||
{
|
||||
returnurl += "/" + PageState.Page.Path;
|
||||
}
|
||||
|
||||
NavigationManager.NavigateTo(NavigateUrl("login", "returnurl=" + returnurl));
|
||||
}
|
||||
|
||||
private async Task LogoutUser()
|
||||
{
|
||||
await UserService.LogoutUserAsync(PageState.User);
|
||||
|
||||
if (PageState.Runtime == Runtime.Server)
|
||||
{
|
||||
// server-side Blazor
|
||||
var interop = new Interop(jsRuntime);
|
||||
string antiforgerytoken = await interop.GetElementByName("__RequestVerificationToken");
|
||||
var fields = new { __RequestVerificationToken = antiforgerytoken, returnurl = (PageState.Alias.Path + "/" + PageState.Page.Path) };
|
||||
await interop.SubmitForm("/pages/logout/", fields);
|
||||
}
|
||||
else
|
||||
{
|
||||
// client-side Blazor
|
||||
var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider));
|
||||
authstateprovider.NotifyAuthenticationChanged();
|
||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "reload"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
49
Oqtane.Client/Themes/Controls/LoginBase.cs
Normal file
49
Oqtane.Client/Themes/Controls/LoginBase.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using Oqtane.Providers;
|
||||
using Oqtane.Services;
|
||||
using Oqtane.UI;
|
||||
|
||||
namespace Oqtane.Themes.Controls
|
||||
{
|
||||
public class LoginBase : ThemeControlBase
|
||||
{
|
||||
[Inject] public NavigationManager NavigationManager {get;set;}
|
||||
[Inject]public IUserService UserService {get;set;}
|
||||
[Inject]public IJSRuntime jsRuntime {get;set;}
|
||||
[Inject]public IServiceProvider ServiceProvider {get;set;}
|
||||
|
||||
protected void LoginUser()
|
||||
{
|
||||
var returnurl = PageState.Alias.Path;
|
||||
if (PageState.Page.Path != "/")
|
||||
{
|
||||
returnurl += "/" + PageState.Page.Path;
|
||||
}
|
||||
NavigationManager.NavigateTo(NavigateUrl("login", "returnurl=" + returnurl));
|
||||
}
|
||||
|
||||
protected async Task LogoutUser()
|
||||
{
|
||||
await UserService.LogoutUserAsync(PageState.User);
|
||||
|
||||
if (PageState.Runtime == Runtime.Server)
|
||||
{
|
||||
// server-side Blazor
|
||||
var interop = new Interop(jsRuntime);
|
||||
string antiforgerytoken = await interop.GetElementByName("__RequestVerificationToken");
|
||||
var fields = new { __RequestVerificationToken = antiforgerytoken, returnurl = (PageState.Alias.Path + "/" + PageState.Page.Path) };
|
||||
await interop.SubmitForm("/pages/logout/", fields);
|
||||
}
|
||||
else
|
||||
{
|
||||
// client-side Blazor
|
||||
var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider));
|
||||
authstateprovider.NotifyAuthenticationChanged();
|
||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "reload"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -2,17 +2,20 @@
|
||||
@inherits ThemeControlBase
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
@((MarkupString)logo)
|
||||
@if (PageState.Site.LogoFileId != null)
|
||||
{
|
||||
<a href="@Href">
|
||||
<img class="img-fluid" src="@ContentUrl(PageState.Site.LogoFileId.Value)" alt="@PageState.Site.Name"/>
|
||||
</a>
|
||||
}
|
||||
|
||||
@code {
|
||||
string logo = "";
|
||||
|
||||
protected override void OnParametersSet()
|
||||
string Href
|
||||
{
|
||||
if (PageState.Site.LogoFileId != null)
|
||||
get
|
||||
{
|
||||
var uri = new Uri(NavigationManager.Uri);
|
||||
logo = "<a href=\"" + uri.Scheme + "://" + uri.Authority + "\"><img src=\"" + ContentUrl(PageState.Site.LogoFileId.Value) + "\" alt=\"" + PageState.Site.Name + "\"/></a>";
|
||||
return $"{uri.Scheme}://{uri.Authority}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,133 +1,20 @@
|
||||
@namespace Oqtane.Themes.Controls
|
||||
@inherits ThemeControlBase
|
||||
|
||||
@if (menu != string.Empty)
|
||||
@switch (Orientation)
|
||||
{
|
||||
<div class="app-menu">
|
||||
@((MarkupString)menu)
|
||||
</div>
|
||||
case "Horizontal":
|
||||
<MenuHorizontal/>
|
||||
break;
|
||||
default: // Vertical
|
||||
{
|
||||
<MenuVertical/>
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
private string menu = string.Empty;
|
||||
|
||||
@code{
|
||||
|
||||
[Parameter]
|
||||
public string Orientation { get; set; }
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
switch (Orientation)
|
||||
{
|
||||
case "Horizontal":
|
||||
CreateHorizontalMenu();
|
||||
break;
|
||||
default: // Vertical
|
||||
CreateVerticalMenu();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateVerticalMenu()
|
||||
{
|
||||
var level = -1;
|
||||
var securitylevel = int.MaxValue;
|
||||
|
||||
menu = "<ul class=\"nav flex-column\">\n";
|
||||
|
||||
foreach (Page p in PageState.Pages.Where(item => item.IsNavigation && !item.IsDeleted))
|
||||
{
|
||||
if (UserSecurity.IsAuthorized(PageState.User,PermissionNames.View, p.Permissions) && p.Level <= securitylevel)
|
||||
{
|
||||
securitylevel = int.MaxValue;
|
||||
|
||||
menu += "<li class=\"nav-item px-3\">";
|
||||
if (string.IsNullOrEmpty(p.Url))
|
||||
{
|
||||
menu += "<a href=\"" + NavigateUrl(p.Path) + "\" class=\"nav-link\" style=\"padding-left: " + ((p.Level + 1) * 15).ToString() + "px !important;\">";
|
||||
}
|
||||
else
|
||||
{
|
||||
string target = String.Empty;
|
||||
if (p.Url.StartsWith("http"))
|
||||
{
|
||||
target = " target=\"_new\"";
|
||||
}
|
||||
menu += "<a href=\"" + p.Url + "\" class=\"nav-link\" style=\"padding-left: " + ((p.Level + 1) * 15).ToString() + "px !important;\"" + target + ">";
|
||||
}
|
||||
|
||||
if (p.HasChildren)
|
||||
{
|
||||
menu += "<i class=\"oi oi-chevron-right\"></i>";
|
||||
}
|
||||
|
||||
if (p.Icon != string.Empty)
|
||||
{
|
||||
menu += "<span class=\"oi oi-" + p.Icon + "\" aria-hidden=\"true\"></span>";
|
||||
}
|
||||
|
||||
menu += p.Name;
|
||||
menu += "</a>\n";
|
||||
menu += "</li>\n";
|
||||
|
||||
level = p.Level;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (securitylevel == int.MaxValue)
|
||||
{
|
||||
securitylevel = p.Level;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
menu += "</ul>";
|
||||
}
|
||||
|
||||
private void CreateHorizontalMenu()
|
||||
{
|
||||
var url = String.Empty;
|
||||
var target = String.Empty;
|
||||
|
||||
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,PermissionNames.View, p.Permissions) && p.ParentId == PageState.Page.ParentId && p.Level == PageState.Page.Level)
|
||||
{
|
||||
if (string.IsNullOrEmpty(p.Url))
|
||||
{
|
||||
url = NavigateUrl(p.Path);
|
||||
target = String.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
url = p.Url;
|
||||
if (p.Url.StartsWith("http"))
|
||||
{
|
||||
target = " target=\"_new\"";
|
||||
}
|
||||
}
|
||||
|
||||
if (p.PageId == PageState.Page.PageId)
|
||||
{
|
||||
menu += "<li class=\"nav-item active\">" +
|
||||
"<a class=\"nav-link\" href=\"" + NavigateUrl(p.Path) + "\">" +
|
||||
((p.Icon != string.Empty) ? "<span class=\"oi oi-" + p.Icon + "\" aria-hidden=\"true\"></span> " : string.Empty) +
|
||||
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 != string.Empty) ? "<span class=\"oi oi-" + p.Icon + "\" aria-hidden=\"true\"></span> " : string.Empty) +
|
||||
p.Name + "</a></li>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
menu += "</ul>";
|
||||
menu += "</div>";
|
||||
}
|
||||
}
|
||||
|
43
Oqtane.Client/Themes/Controls/MenuBase.cs
Normal file
43
Oqtane.Client/Themes/Controls/MenuBase.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Security;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Themes.Controls
|
||||
{
|
||||
public class MenuBase : ThemeControlBase
|
||||
{
|
||||
protected IEnumerable<Page> MenuPages => GetMenuPages().ToList();
|
||||
|
||||
protected string GetTarget(Page page)
|
||||
{
|
||||
return page.Url != null && page.Url.StartsWith("http") ? "_new" : string.Empty;
|
||||
}
|
||||
|
||||
protected string GetUrl(Page page)
|
||||
{
|
||||
return string.IsNullOrEmpty(page.Url) ? NavigateUrl(page.Path) : page.Url;
|
||||
}
|
||||
|
||||
private IEnumerable<Page> GetMenuPages()
|
||||
{
|
||||
var securityLevel = int.MaxValue;
|
||||
foreach (Page p in PageState.Pages.Where(item => item.IsNavigation && !item.IsDeleted))
|
||||
{
|
||||
if (p.Level <= securityLevel && UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
|
||||
{
|
||||
securityLevel = int.MaxValue;
|
||||
yield return p;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (securityLevel == int.MaxValue)
|
||||
{
|
||||
securityLevel = p.Level;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
42
Oqtane.Client/Themes/Controls/MenuHorizontal.Razor
Normal file
42
Oqtane.Client/Themes/Controls/MenuHorizontal.Razor
Normal file
@ -0,0 +1,42 @@
|
||||
@namespace Oqtane.Themes.Controls
|
||||
@inherits MenuBase
|
||||
@if (MenuPages.Any())
|
||||
{
|
||||
<div class="app-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>
|
||||
|
||||
<div class="collapse navbar-collapse" id="Menu">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
@foreach (var p in MenuPages)
|
||||
{
|
||||
if (p.PageId == PageState.Page.PageId)
|
||||
{
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="@NavigateUrl(p.Path)">
|
||||
@if (p.Icon != string.Empty)
|
||||
{
|
||||
<span class="oi oi-@p.Icon" aria-hidden="true"></span>
|
||||
}
|
||||
@p.Name<span class="sr-only">(current)</span>
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
else
|
||||
{
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="@NavigateUrl(p.Path)">
|
||||
@if (p.Icon != string.Empty)
|
||||
{
|
||||
<span class="oi oi-@p.Icon" aria-hidden="true"></span>
|
||||
}
|
||||
@p.Name
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
}
|
27
Oqtane.Client/Themes/Controls/MenuVertical.razor
Normal file
27
Oqtane.Client/Themes/Controls/MenuVertical.razor
Normal file
@ -0,0 +1,27 @@
|
||||
@namespace Oqtane.Themes.Controls
|
||||
@inherits MenuBase
|
||||
@if (MenuPages.Any())
|
||||
{
|
||||
<div class="app-menu">
|
||||
<ul class="nav flex-column">
|
||||
@foreach (var p in MenuPages)
|
||||
{
|
||||
<li class="nav-item px-3">
|
||||
<a href="@GetUrl(p)" class="nav-link" style="padding-left:@((p.Level + 1) * 15)px !important;" target="@GetTarget(p)">
|
||||
|
||||
@if (p.HasChildren)
|
||||
{
|
||||
<i class="oi oi-chevron-right"></i>
|
||||
}
|
||||
@if (p.Icon != string.Empty)
|
||||
{
|
||||
<span class="oi oi-@p.Icon" aria-hidden="true"></span>
|
||||
}
|
||||
@p.Name
|
||||
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
@ -1,135 +1,20 @@
|
||||
@namespace Oqtane.Themes.Controls
|
||||
@inherits ContainerBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IUserService UserService
|
||||
@inject IPageModuleService PageModuleService
|
||||
@inherits ModuleActionsBase
|
||||
|
||||
@if (PageState.EditMode && !PageState.Page.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, ModuleState.Permissions))
|
||||
{
|
||||
<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)
|
||||
@foreach (var action in Actions)
|
||||
{
|
||||
if (action.Action != "")
|
||||
if (string.IsNullOrEmpty(action.Name))
|
||||
{
|
||||
<a class="dropdown-item" @onclick="(async () => await ModuleAction(action.Action))">@action.Name</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" @onclick="(async () => await ModuleAction(action))">@action.Name</a>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
private List<ActionViewModel> actions;
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, ModuleState.Permissions))
|
||||
{
|
||||
actions = new List<ActionViewModel>();
|
||||
actions.Add(new ActionViewModel { Action = "settings", Name = "Manage Settings" });
|
||||
|
||||
if (ModuleState.ModuleDefinition != null && ModuleState.ModuleDefinition.ServerManagerType != "")
|
||||
{
|
||||
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" });
|
||||
}
|
||||
|
||||
if (ModuleState.PaneModuleIndex > 0)
|
||||
{
|
||||
actions.Add(new ActionViewModel { Action = "<", Name = "Move Up" });
|
||||
}
|
||||
|
||||
if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1))
|
||||
{
|
||||
actions.Add(new ActionViewModel { Action = ">", Name = "Move Down" });
|
||||
}
|
||||
|
||||
if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1))
|
||||
{
|
||||
actions.Add(new ActionViewModel { Action = ">>", Name = "Move To Bottom" });
|
||||
}
|
||||
|
||||
foreach (string pane in PageState.Page.Panes.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
if (pane != ModuleState.Pane)
|
||||
{
|
||||
actions.Add(new ActionViewModel { Action = pane, Name = "Move To " + pane + " Pane" });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task ModuleAction(string action)
|
||||
{
|
||||
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, ModuleState.Permissions))
|
||||
{
|
||||
PageModule pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
|
||||
|
||||
string url = NavigateUrl();
|
||||
switch (action)
|
||||
{
|
||||
case "<<":
|
||||
pagemodule.Order = 0;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
break;
|
||||
case "<":
|
||||
pagemodule.Order -= 3;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
break;
|
||||
case ">":
|
||||
pagemodule.Order += 3;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
break;
|
||||
case ">>":
|
||||
pagemodule.Order = int.MaxValue;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
break;
|
||||
case "settings":
|
||||
url = EditUrl(pagemodule.ModuleId, "Settings");
|
||||
break;
|
||||
case "import":
|
||||
url = EditUrl(pagemodule.ModuleId, "Import");
|
||||
break;
|
||||
case "export":
|
||||
url = EditUrl(pagemodule.ModuleId, "Export");
|
||||
break;
|
||||
case "delete":
|
||||
pagemodule.IsDeleted = true;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
break;
|
||||
default: // move to pane
|
||||
string pane = pagemodule.Pane;
|
||||
pagemodule.Pane = action;
|
||||
pagemodule.Order = int.MaxValue; // add to bottom of pane
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pane);
|
||||
break;
|
||||
}
|
||||
NavigationManager.NavigateTo(url);
|
||||
}
|
||||
}
|
||||
|
||||
public class ActionViewModel
|
||||
{
|
||||
public string Action { set; get; }
|
||||
public string Name { set; get; }
|
||||
}
|
||||
}
|
||||
|
164
Oqtane.Client/Themes/Controls/ModuleActionsBase.cs
Normal file
164
Oqtane.Client/Themes/Controls/ModuleActionsBase.cs
Normal file
@ -0,0 +1,164 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Security;
|
||||
using Oqtane.Services;
|
||||
using Oqtane.Shared;
|
||||
|
||||
// ReSharper disable UnassignedGetOnlyAutoProperty
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
|
||||
namespace Oqtane.Themes.Controls
|
||||
{
|
||||
public class ModuleActionsBase : ContainerBase
|
||||
{
|
||||
[Inject] public NavigationManager NavigationManager { get; set; }
|
||||
[Inject] public IPageModuleService PageModuleService { get; set; }
|
||||
|
||||
protected List<ActionViewModel> Actions;
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
Actions = GetActions();
|
||||
}
|
||||
|
||||
protected virtual List<ActionViewModel> GetActions()
|
||||
{
|
||||
var actionList = new List<ActionViewModel>();
|
||||
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, ModuleState.Permissions))
|
||||
{
|
||||
actionList.Add(new ActionViewModel {Name = "Manage Settings", Action = async (u, m) => await Settings(u, m)});
|
||||
|
||||
if (ModuleState.ModuleDefinition != null && ModuleState.ModuleDefinition.ServerManagerType != "")
|
||||
{
|
||||
actionList.Add(new ActionViewModel {Name = "Import Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Import")});
|
||||
actionList.Add(new ActionViewModel {Name = "Export Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Export")});
|
||||
}
|
||||
|
||||
actionList.Add(new ActionViewModel {Name = "Delete Module", Action = async (u, m) => await DeleteModule(u, m)});
|
||||
actionList.Add(new ActionViewModel {Name = ""});
|
||||
|
||||
if (ModuleState.PaneModuleIndex > 0)
|
||||
{
|
||||
actionList.Add(new ActionViewModel {Name = "Move To Top", Action = async (s, m) => await MoveTop(s, m)});
|
||||
}
|
||||
|
||||
if (ModuleState.PaneModuleIndex > 0)
|
||||
{
|
||||
actionList.Add(new ActionViewModel {Name = "Move Up", Action = async (s, m) => await MoveUp(s, m)});
|
||||
}
|
||||
|
||||
if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1))
|
||||
{
|
||||
actionList.Add(new ActionViewModel {Name = "Move Down", Action = async (s, m) => await MoveDown(s, m)});
|
||||
}
|
||||
|
||||
if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1))
|
||||
{
|
||||
actionList.Add(new ActionViewModel {Name = "Move To Bottom", Action = async (s, m) => await MoveBottom(s, m)});
|
||||
}
|
||||
|
||||
foreach (string pane in PageState.Page.Panes.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
if (pane != ModuleState.Pane)
|
||||
{
|
||||
actionList.Add(new ActionViewModel {Name = "Move To " + pane + " Pane", Action = async (s, m) => await MoveToPane(s, pane, m)});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return actionList;
|
||||
}
|
||||
|
||||
private async Task<string> EditUrlAsync(string url, int moduleId, string import)
|
||||
{
|
||||
await Task.Yield();
|
||||
EditUrl(moduleId, import);
|
||||
return url;
|
||||
}
|
||||
|
||||
protected async Task ModuleAction(ActionViewModel action)
|
||||
{
|
||||
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, ModuleState.Permissions))
|
||||
{
|
||||
PageModule pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
|
||||
|
||||
string url = NavigateUrl();
|
||||
|
||||
if (action.Action != null)
|
||||
{
|
||||
url = await action.Action(url, pagemodule);
|
||||
}
|
||||
|
||||
NavigationManager.NavigateTo(url);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> MoveToPane(string url, string newPane, PageModule pagemodule)
|
||||
{
|
||||
string oldPane = pagemodule.Pane;
|
||||
pagemodule.Pane = newPane;
|
||||
pagemodule.Order = int.MaxValue; // add to bottom of pane
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, oldPane);
|
||||
return url;
|
||||
}
|
||||
|
||||
private async Task<string> DeleteModule(string url, PageModule pagemodule)
|
||||
{
|
||||
pagemodule.IsDeleted = true;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
return url;
|
||||
}
|
||||
|
||||
private async Task<string> Settings(string url, PageModule pagemodule)
|
||||
{
|
||||
await Task.Yield();
|
||||
url = EditUrl(pagemodule.ModuleId, "Settings");
|
||||
return url;
|
||||
}
|
||||
|
||||
private async Task<string> MoveTop(string s, PageModule pagemodule)
|
||||
{
|
||||
pagemodule.Order = 0;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
return s;
|
||||
}
|
||||
|
||||
private async Task<string> MoveBottom(string s, PageModule pagemodule)
|
||||
{
|
||||
pagemodule.Order = int.MaxValue;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
return s;
|
||||
}
|
||||
|
||||
private async Task<string> MoveUp(string s, PageModule pagemodule)
|
||||
{
|
||||
pagemodule.Order -= 3;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
return s;
|
||||
}
|
||||
|
||||
private async Task<string> MoveDown(string s, PageModule pagemodule)
|
||||
{
|
||||
pagemodule.Order += 3;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
return s;
|
||||
}
|
||||
|
||||
public class ActionViewModel
|
||||
{
|
||||
public string Name { set; get; }
|
||||
|
||||
public Func<string, PageModule, Task<string>> Action { set; get; }
|
||||
}
|
||||
}
|
||||
}
|
@ -179,31 +179,8 @@
|
||||
};
|
||||
|
||||
var installation = await InstallationService.Install(config);
|
||||
//TODO: Should be moved to Database manager
|
||||
if (installation.Success)
|
||||
{
|
||||
Site site = new Site();
|
||||
site.TenantId = -1; // will be populated on server
|
||||
site.Name = "Default Site";
|
||||
site.LogoFileId = null;
|
||||
site.FaviconFileId = null;
|
||||
site.DefaultThemeType = Constants.DefaultTheme;
|
||||
site.DefaultLayoutType = Constants.DefaultLayout;
|
||||
site.DefaultContainerType = Constants.DefaultContainer;
|
||||
site.PwaIsEnabled = false;
|
||||
site.PwaAppIconFileId = null;
|
||||
site.PwaSplashIconFileId = null;
|
||||
site.AllowRegistration = false;
|
||||
site = await SiteService.AddSiteAsync(site, null);
|
||||
|
||||
User user = new User();
|
||||
user.SiteId = site.SiteId;
|
||||
user.Username = _hostUsername;
|
||||
user.Password = _hostPassword;
|
||||
user.Email = _hostEmail;
|
||||
user.DisplayName = _hostUsername;
|
||||
user = await UserService.AddUserAsync(user);
|
||||
|
||||
NavigationManager.NavigateTo("", true);
|
||||
}
|
||||
else
|
||||
|
@ -44,6 +44,7 @@ namespace Oqtane.Controllers
|
||||
_config.Reload();
|
||||
}
|
||||
|
||||
_databaseManager.BuildDefaultSite(config.Password, config.HostEmail);
|
||||
installation.Success = true;
|
||||
return installation;
|
||||
}
|
||||
|
@ -130,10 +130,6 @@ namespace Oqtane.Controllers
|
||||
System.IO.File.Delete(file);
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Assembly Removed {Filename}", file);
|
||||
}
|
||||
|
||||
// clean up module schema versions
|
||||
_sql.ExecuteNonQuery(tenant, "DELETE FROM [dbo].[SchemaVersions] WHERE ScriptName LIKE '" + assemblyname + "%'");
|
||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Schema Versions Removed For {AssemblyName}", assemblyname);
|
||||
}
|
||||
|
||||
// remove module definition
|
||||
|
@ -315,7 +315,7 @@ namespace Oqtane.Infrastructure
|
||||
}
|
||||
}
|
||||
|
||||
private void BuildDefaultSite(string password, string email)
|
||||
public void BuildDefaultSite(string password, string email)
|
||||
{
|
||||
using (var scope = _serviceScopeFactory.CreateScope())
|
||||
{
|
||||
|
@ -1,4 +1,8 @@
|
||||
|
||||
.breadcrumbs {
|
||||
background-color: #e6e6e6;
|
||||
border-bottom: 1px solid #d6d5d5;
|
||||
}
|
||||
|
||||
.top-row {
|
||||
height: 3.5rem;
|
||||
display: flex;
|
||||
@ -12,6 +16,7 @@
|
||||
.main .top-row {
|
||||
background-color: #e6e6e6;
|
||||
border-bottom: 1px solid #d6d5d5;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
@ -22,8 +27,8 @@
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
.sidebar .navbar-brand {
|
||||
font-size: 1.1rem;
|
||||
.sidebar .navbar-toggler .navbar-toggler-icon {
|
||||
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
.sidebar .oi {
|
||||
@ -33,6 +38,10 @@
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.app-menu .nav-item {
|
||||
font-size: 0.9rem;
|
||||
padding-bottom: 0.5rem;
|
||||
@ -84,6 +93,13 @@
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.breadcrumbs {
|
||||
position: fixed;
|
||||
left: 275px;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
@ -94,7 +110,6 @@
|
||||
.main .top-row {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.main > div {
|
||||
@ -110,6 +125,10 @@
|
||||
/* Never collapse the sidebar for wide screens */
|
||||
display: block;
|
||||
}
|
||||
|
||||
.main > .container {
|
||||
margin-top: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes sk-stretchdelay {
|
||||
@ -133,3 +152,35 @@
|
||||
-webkit-transform: scaleY(1.0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.sidebar {
|
||||
margin-top: 3.5rem;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.main > .top-row.px-4 {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ml-md-auto {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.breadcrumbs {
|
||||
position: fixed;
|
||||
top: 150px;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.main > .container {
|
||||
margin-top: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ Please note that this project is governed by the **[.NET Foundation Contributor
|
||||
|
||||
**To get started with Oqtane:**
|
||||
|
||||
1. Install **[.NET Core 3.2 Preview4 SDK (v3.1.201)](https://dotnet.microsoft.com/download/dotnet-core/3.1)**.
|
||||
1. Install **[.NET Core 3.2 Preview5 SDK (v3.1.201)](https://dotnet.microsoft.com/download/dotnet-core/3.1)**.
|
||||
|
||||
2. Install the Preview edition of [Visual Studio 2019](https://visualstudio.microsoft.com/vs/preview/) (version 16.6 or higher) with the **ASP.NET and web development** workload. If you do not have a SQL Server installation available already and you wish to use LocalDB for development, you must also install the **.NET desktop development workload**.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user