commit
27c6700f9d
@ -1,7 +1,4 @@
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@using Oqtane.Shared
|
||||
@using Oqtane.Services
|
||||
@inject IInstallationService InstallationService
|
||||
@inject IInstallationService InstallationService
|
||||
|
||||
@if (Initialized)
|
||||
{
|
||||
|
@ -1,37 +1,31 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Models;
|
||||
@using Oqtane.Security
|
||||
@namespace Oqtane.Modules.Admin.Dashboard
|
||||
@namespace Oqtane.Modules.Admin.Dashboard
|
||||
@inherits ModuleBase
|
||||
@inject IPageService PageService
|
||||
@inject IUserService UserService
|
||||
|
||||
<ul class="list-group">
|
||||
<div class="row">
|
||||
@foreach (var p in pages)
|
||||
{
|
||||
if (UserSecurity.IsAuthorized(PageState.User, "View", p.Permissions))
|
||||
{
|
||||
string url = NavigateUrl(p.Path);
|
||||
<li class="list-group-item">
|
||||
<div class="col-md-2 mx-auto text-center">
|
||||
<NavLink class="nav-link" href="@url" Match="NavLinkMatch.All">
|
||||
<span class="oi @p.Icon" aria-hidden="true"></span> @p.Name
|
||||
<h2><span class="oi oi-@p.Icon" aria-hidden="true"></span></h2>@p.Name
|
||||
</NavLink>
|
||||
</li>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
List<Page> pages;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
// display list of pages which are children of current page
|
||||
pages = PageState.Pages.Where(item => item.ParentId == PageState.Page.PageId).ToList();
|
||||
Page admin = PageState.Pages.Where(item => item.Path == "admin").FirstOrDefault();
|
||||
pages = PageState.Pages.Where(item => item.ParentId == admin.PageId).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
56
Oqtane.Client/Modules/Admin/Files/Add.razor
Normal file
56
Oqtane.Client/Modules/Admin/Files/Add.razor
Normal file
@ -0,0 +1,56 @@
|
||||
@namespace Oqtane.Modules.Admin.Files
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IFileService FileService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Files: </label>
|
||||
</td>
|
||||
<td>
|
||||
<FileUpload Multiple="true" @ref="fileupload"></FileUpload>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-primary" @onclick="UploadFile">Upload</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
FileUpload fileupload;
|
||||
|
||||
private async Task UploadFile()
|
||||
{
|
||||
string[] files = await fileupload.GetFiles();
|
||||
if (files.Length > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
ShowProgressIndicator();
|
||||
|
||||
string result = await FileService.UploadFilesAsync(PageState.Site.SiteRootPath, files, "");
|
||||
if (result == "")
|
||||
{
|
||||
await logger.LogInformation("Files Uploaded Successfully");
|
||||
AddModuleMessage("Files Uploaded Successfully", MessageType.Success);
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogError("Upload Failed For {Files}", result.Replace(",",", "));
|
||||
AddModuleMessage("Upload Failed For " + result.Replace(",",", ") + ". This Could Be Due To A Network Error Or Because A File Type Is Restricted.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Upload Failed {Error}", ex.Message);
|
||||
AddModuleMessage("Upload Failed. " + ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage("You Must Select Some Files To Upload", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
61
Oqtane.Client/Modules/Admin/Files/Index.razor
Normal file
61
Oqtane.Client/Modules/Admin/Files/Index.razor
Normal file
@ -0,0 +1,61 @@
|
||||
@namespace Oqtane.Modules.Admin.Files
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IFileService FileService
|
||||
|
||||
@if (Files == null)
|
||||
{
|
||||
<p><em>Loading...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ActionLink Action="Add" Text="Add Files" />
|
||||
|
||||
<Pager Items="@Files">
|
||||
<Header>
|
||||
<th> </th>
|
||||
<th>Name</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td><ActionDialog Header="Delete File" Message="@("Are You Sure You Wish To Delete " + context + "?")" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteFile(context))" /></td>
|
||||
<td><a href="@(uri.Scheme + "://" + uri.Authority + "/" + PageState.Site.SiteRootPath + context)" target="_new">@context</a></td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
List<string> Files;
|
||||
Uri uri;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
Files = await FileService.GetFilesAsync(PageState.Site.SiteRootPath);
|
||||
uri = new Uri(NavigationManager.Uri);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Files {Error}", ex.Message);
|
||||
AddModuleMessage("Error Loading Files", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteFile(string filename)
|
||||
{
|
||||
try
|
||||
{
|
||||
await FileService.DeleteFileAsync(PageState.Site.SiteRootPath, filename);
|
||||
Files = await FileService.GetFilesAsync(PageState.Site.SiteRootPath);
|
||||
await logger.LogInformation("File Deleted {File}", filename);
|
||||
AddModuleMessage("File " + filename + " Deleted", MessageType.Success);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Deleting File {File} {Error}", filename, ex.Message);
|
||||
AddModuleMessage("Error Deleting File " + filename, MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +1,4 @@
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Oqtane.Modules
|
||||
@using Microsoft.JSInterop
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Providers
|
||||
@using Oqtane.Shared
|
||||
@namespace Oqtane.Modules.Admin.Login
|
||||
@namespace Oqtane.Modules.Admin.Login
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IJSRuntime jsRuntime
|
||||
@ -23,7 +14,6 @@
|
||||
</Authorized>
|
||||
<NotAuthorized>
|
||||
<div class="container">
|
||||
@((MarkupString)Message)
|
||||
<div class="form-group">
|
||||
<label for="Username" class="control-label">Username: </label>
|
||||
<input type="text" name="Username" class="form-control" placeholder="Username" @bind="@Username" />
|
||||
@ -47,7 +37,6 @@
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Anonymous; } }
|
||||
|
||||
public string Message { get; set; } = "";
|
||||
public string Username { get; set; } = "";
|
||||
public string Password { get; set; } = "";
|
||||
public bool Remember { get; set; } = false;
|
||||
@ -67,6 +56,7 @@
|
||||
user = await UserService.LoginUserAsync(user, false, false);
|
||||
if (user.IsAuthenticated)
|
||||
{
|
||||
await logger.LogInformation("Login Successful For Username {Username}", Username);
|
||||
// complete the login on the server so that the cookies are set correctly on SignalR
|
||||
var interop = new Interop(jsRuntime);
|
||||
string antiforgerytoken = await interop.GetElementByName("__RequestVerificationToken");
|
||||
@ -75,7 +65,8 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
Message = "<div class=\"alert alert-danger\" role=\"alert\">Login Failed. Please Remember That Passwords Are Case Sensitive.</div>";
|
||||
await logger.LogInformation("Login Failed For Username {Username}", Username);
|
||||
AddModuleMessage("Login Failed. Please Remember That Passwords Are Case Sensitive.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -88,13 +79,14 @@
|
||||
user = await UserService.LoginUserAsync(user, true, Remember);
|
||||
if (user.IsAuthenticated)
|
||||
{
|
||||
await logger.LogInformation("Login Successful For Username {Username}", Username);
|
||||
authstateprovider.NotifyAuthenticationChanged();
|
||||
PageState.Reload = Constants.ReloadSite;
|
||||
NavigationManager.NavigateTo(NavigateUrl(ReturnUrl));
|
||||
NavigationManager.NavigateTo(NavigateUrl(ReturnUrl, Reload.Site));
|
||||
}
|
||||
else
|
||||
{
|
||||
Message = "<div class=\"alert alert-danger\" role=\"alert\">Login Failed. Please Remember That Passwords Are Case Sensitive.</div>";
|
||||
await logger.LogInformation("Login Failed For Username {Username}", Username);
|
||||
AddModuleMessage("Login Failed. Please Remember That Passwords Are Case Sensitive.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
207
Oqtane.Client/Modules/Admin/Logs/Detail.razor
Normal file
207
Oqtane.Client/Modules/Admin/Logs/Detail.razor
Normal file
@ -0,0 +1,207 @@
|
||||
@namespace Oqtane.Modules.Admin.Logs
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ILogService LogService
|
||||
@inject IPageService PageService
|
||||
@inject IPageModuleService PageModuleService
|
||||
@inject IUserService UserService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Date/Time: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@logdate" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Level: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@level" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Feature: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@feature" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Function: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@function" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Category: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@category" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
@if (pagename != "")
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Page: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@pagename" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@if (moduletitle != "")
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Module: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@moduletitle" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@if (username != "")
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">User: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@username" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Url: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@url" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Template: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@template" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Message: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@message" rows="5" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
@if (!string.IsNullOrEmpty(exception))
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Exception: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@exception" rows="5" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Properties: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@properties" rows="5" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">Server: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@server" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
int logid;
|
||||
string logdate = "";
|
||||
string level = "";
|
||||
string feature = "";
|
||||
string function = "";
|
||||
string category = "";
|
||||
string pagename = "";
|
||||
string moduletitle = "";
|
||||
string username = "";
|
||||
string url = "";
|
||||
string template = "";
|
||||
string message = "";
|
||||
string exception = "";
|
||||
string properties = "";
|
||||
string server = "";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
logid = Int32.Parse(PageState.QueryString["id"]);
|
||||
Log log = await LogService.GetLogAsync(logid);
|
||||
if (log != null)
|
||||
{
|
||||
logdate = log.LogDate.ToString();
|
||||
level = log.Level;
|
||||
feature = log.Feature;
|
||||
function = log.Function;
|
||||
category = log.Category;
|
||||
if (log.PageId != null)
|
||||
{
|
||||
Page page = await PageService.GetPageAsync(log.PageId.Value);
|
||||
if (page != null)
|
||||
{
|
||||
pagename = page.Name;
|
||||
}
|
||||
}
|
||||
if (log.PageId != null && log.ModuleId != null)
|
||||
{
|
||||
PageModule pagemodule = await PageModuleService.GetPageModuleAsync(log.PageId.Value, log.ModuleId.Value);
|
||||
if (pagemodule != null)
|
||||
{
|
||||
moduletitle = pagemodule.Title;
|
||||
}
|
||||
}
|
||||
if (log.UserId != null)
|
||||
{
|
||||
User user = await UserService.GetUserAsync(log.UserId.Value, PageState.Site.SiteId);
|
||||
if (user != null)
|
||||
{
|
||||
username = user.Username;
|
||||
}
|
||||
}
|
||||
url = log.Url;
|
||||
template = log.MessageTemplate;
|
||||
message = log.Message;
|
||||
exception = log.Exception;
|
||||
properties = log.Properties;
|
||||
server = log.Server;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Log {LogId} {Error}", logid, ex.Message);
|
||||
AddModuleMessage("Error Loading Log", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
162
Oqtane.Client/Modules/Admin/Logs/Index.razor
Normal file
162
Oqtane.Client/Modules/Admin/Logs/Index.razor
Normal file
@ -0,0 +1,162 @@
|
||||
@namespace Oqtane.Modules.Admin.Logs
|
||||
@inherits ModuleBase
|
||||
@inject ILogService LogService
|
||||
|
||||
@if (Logs == null)
|
||||
{
|
||||
<p><em>Loading...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="form-group">
|
||||
<label>Level: </label>
|
||||
<select class="form-control" @onchange="(e => LevelChanged(e))">
|
||||
<option value="-"><All Levels></option>
|
||||
<option value="Trace">Trace</option>
|
||||
<option value="Debug">Debug</option>
|
||||
<option value="Information">Information</option>
|
||||
<option value="Warning">Warning</option>
|
||||
<option value="Error">Error</option>
|
||||
<option value="Critical">Critical</option>
|
||||
</select>
|
||||
<label>Function: </label>
|
||||
<select class="form-control" @onchange="(e => FunctionChanged(e))">
|
||||
<option value="-"><All Functions></option>
|
||||
<option value="Create">Create</option>
|
||||
<option value="Read">Read</option>
|
||||
<option value="Update">Update</option>
|
||||
<option value="Delete">Delete</option>
|
||||
<option value="Security">Security</option>
|
||||
<option value="Other">Other</option>
|
||||
</select>
|
||||
<label>Rows: </label>
|
||||
<select class="form-control" @onchange="(e => RowsChanged(e))">
|
||||
<option value="10">10</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
</div>
|
||||
@if (Logs.Any())
|
||||
{
|
||||
<Pager Items="@Logs">
|
||||
<Header>
|
||||
<th> </th>
|
||||
<th>Date</th>
|
||||
<th>Level</th>
|
||||
<th>Feature</th>
|
||||
<th>Function</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td class="@GetClass(context.Function)"><ActionLink Action="Detail" Parameters="@($"id=" + context.LogId.ToString())" /></td>
|
||||
<td class="@GetClass(context.Function)">@context.LogDate</td>
|
||||
<td class="@GetClass(context.Function)">@context.Level</td>
|
||||
<td class="@GetClass(context.Function)">@context.Feature</td>
|
||||
<td class="@GetClass(context.Function)">@context.Function</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p><em>No Logs Match The Criteria Specified</em></p>
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
string level = "-";
|
||||
string function = "-";
|
||||
string rows = "10";
|
||||
List<Log> Logs;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
await GetLogs();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Logs {Error}", ex.Message);
|
||||
AddModuleMessage("Error Loading Logs", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async void LevelChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
level = (string)e.Value;
|
||||
await GetLogs();
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Logs {Error}", ex.Message);
|
||||
AddModuleMessage("Error Loading Logs", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async void FunctionChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
function = (string)e.Value;
|
||||
await GetLogs();
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Logs {Error}", ex.Message);
|
||||
AddModuleMessage("Error Loading Logs", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async void RowsChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
rows = (string)e.Value;
|
||||
await GetLogs();
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Logs {Error}", ex.Message);
|
||||
AddModuleMessage("Error Loading Logs", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task GetLogs()
|
||||
{
|
||||
Logs = await LogService.GetLogsAsync(PageState.Site.SiteId, ((level == "-") ? "" : level), ((function == "-") ? "" : function), int.Parse(rows));
|
||||
}
|
||||
|
||||
private string GetClass(string function)
|
||||
{
|
||||
string classname = "";
|
||||
switch (function)
|
||||
{
|
||||
case "Create":
|
||||
classname = "table-primary";
|
||||
break;
|
||||
case "Read":
|
||||
classname = "table-secondary";
|
||||
break;
|
||||
case "Update":
|
||||
classname = "table-success";
|
||||
break;
|
||||
case "Delete":
|
||||
classname = "table-danger";
|
||||
break;
|
||||
case "Security":
|
||||
classname = "table-warning";
|
||||
break;
|
||||
default:
|
||||
classname = "";
|
||||
break;
|
||||
}
|
||||
return classname;
|
||||
}
|
||||
}
|
@ -1,14 +1,9 @@
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Modules.Controls
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Shared
|
||||
@namespace Oqtane.Modules.Admin.ModuleDefinitions
|
||||
@namespace Oqtane.Modules.Admin.ModuleDefinitions
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IFileService FileService
|
||||
@inject IModuleDefinitionService ModuleDefinitionService
|
||||
@inject IPackageService PackageService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
@ -16,36 +11,136 @@
|
||||
<label for="Name" class="control-label">Module: </label>
|
||||
</td>
|
||||
<td>
|
||||
<FileUpload Filter=".nupkg"></FileUpload>
|
||||
<FileUpload Filter=".nupkg" @ref="fileupload"></FileUpload>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-primary" @onclick="UploadFile">Upload Module</button>
|
||||
|
||||
@if (packages != null)
|
||||
{
|
||||
<hr class="app-rule" />
|
||||
<div class="mx-auto text-center"><h2>Available Modules</h2></div>
|
||||
|
||||
<Pager Items="@packages">
|
||||
<Header>
|
||||
<th>Name</th>
|
||||
<th>Version</th>
|
||||
<th></th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td>@context.Name</td>
|
||||
<td>@context.Version</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-primary" @onclick=@(async () => await DownloadModule(context.PackageId, context.Version))>Download Module</button>
|
||||
</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
|
||||
@if (uploaded)
|
||||
{
|
||||
<button type="button" class="btn btn-success" @onclick="InstallFile">Install</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn btn-success" @onclick="UploadFile">Upload</button>
|
||||
<button type="button" class="btn btn-success" @onclick="InstallModules">Install</button>
|
||||
}
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||
|
||||
bool uploaded = false;
|
||||
List<Package> packages;
|
||||
FileUpload fileupload;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
List<ModuleDefinition> moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
|
||||
packages = await PackageService.GetPackagesAsync("module");
|
||||
foreach(Package package in packages.ToArray())
|
||||
{
|
||||
if (moduledefinitions.Exists(item => Utilities.GetTypeName(item.ModuleDefinitionName) == package.PackageId))
|
||||
{
|
||||
packages.Remove(package);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Packages {Error}", ex.Message);
|
||||
AddModuleMessage("Error Loading Packages", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UploadFile()
|
||||
{
|
||||
await FileService.UploadFilesAsync("Modules");
|
||||
uploaded = true;
|
||||
StateHasChanged();
|
||||
string[] files = await fileupload.GetFiles();
|
||||
if (files.Length > 0)
|
||||
{
|
||||
if (files[0].Contains(".Module."))
|
||||
{
|
||||
try
|
||||
{
|
||||
string result = await FileService.UploadFilesAsync("Modules", files, "");
|
||||
if (result == "")
|
||||
{
|
||||
await logger.LogInformation("Module Uploaded Successfully {Package}", files[0]);
|
||||
AddModuleMessage("Module Uploaded Successfully. Click Install To Complete Installation.", MessageType.Success);
|
||||
uploaded = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogError("Module Upload Failed For {Package}", files[0]);
|
||||
AddModuleMessage("Module Upload Failed For " + result.Replace(",",", ") + ". This Could Be Due To A Network Error Or Because A File Type Is Restricted.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Module Upload Failed For {Package} {Error}", files[0], ex.Message);
|
||||
AddModuleMessage("Module Upload Failed.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogError("Invalid Module Package {Package}", files[0]);
|
||||
AddModuleMessage("Invalid Module Package", MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage("You Must Select A Module To Upload", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task InstallFile()
|
||||
private async Task InstallModules()
|
||||
{
|
||||
await ModuleDefinitionService.InstallModulesAsync();
|
||||
PageState.Reload = Constants.ReloadApplication;
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
try
|
||||
{
|
||||
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Installating Module");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DownloadModule(string moduledefinitionname, string version)
|
||||
{
|
||||
try
|
||||
{
|
||||
await PackageService.DownloadPackageAsync(moduledefinitionname, version, "Modules");
|
||||
await logger.LogInformation("Module {ModuleDefinitionName} {Version} Downloaded Successfully", moduledefinitionname, version);
|
||||
AddModuleMessage("Module Downloaded Successfully. Click Install To Complete Installation.", MessageType.Success);
|
||||
uploaded = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Downloading Module {ModuleDefinitionName} {Version}", moduledefinitionname, version);
|
||||
AddModuleMessage("Error Downloading Module", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
82
Oqtane.Client/Modules/Admin/ModuleDefinitions/Edit.razor
Normal file
82
Oqtane.Client/Modules/Admin/ModuleDefinitions/Edit.razor
Normal file
@ -0,0 +1,82 @@
|
||||
@namespace Oqtane.Modules.Admin.ModuleDefinitions
|
||||
@inherits ModuleBase
|
||||
@inject IModuleDefinitionService ModuleDefinitionService
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Name: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Permissions: </label>
|
||||
</td>
|
||||
<td>
|
||||
<PermissionGrid EntityName="ModuleDefinition" PermissionNames="Utilize" Permissions="@permissions" @ref="permissiongrid" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveModuleDefinition">Save</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
int ModuleDefinitionId;
|
||||
string name;
|
||||
string permissions;
|
||||
string createdby;
|
||||
DateTime createdon;
|
||||
string modifiedby;
|
||||
DateTime modifiedon;
|
||||
|
||||
PermissionGrid permissiongrid;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
ModuleDefinitionId = Int32.Parse(PageState.QueryString["id"]);
|
||||
ModuleDefinition moduledefinition = PageState.ModuleDefinitions.Where(item => item.ModuleDefinitionId == ModuleDefinitionId).FirstOrDefault();
|
||||
if (moduledefinition != null)
|
||||
{
|
||||
name = moduledefinition.Name;
|
||||
permissions = moduledefinition.Permissions;
|
||||
createdby = moduledefinition.CreatedBy;
|
||||
createdon = moduledefinition.CreatedOn;
|
||||
modifiedby = moduledefinition.ModifiedBy;
|
||||
modifiedon = moduledefinition.ModifiedOn;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading ModuleDefinition {ModuleDefinitionId} {Error}", ModuleDefinitionId, ex.Message);
|
||||
AddModuleMessage("Error Loading Module", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveModuleDefinition()
|
||||
{
|
||||
try
|
||||
{
|
||||
ModuleDefinition moduledefinition = PageState.ModuleDefinitions.Where(item => item.ModuleDefinitionId == ModuleDefinitionId).FirstOrDefault();
|
||||
moduledefinition.Permissions = permissiongrid.GetPermissions();
|
||||
await ModuleDefinitionService.UpdateModuleDefinitionAsync(moduledefinition);
|
||||
await logger.LogInformation("ModuleDefinition Saved {ModuleDefinition}", moduledefinition);
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Site));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving ModuleDefinition {ModuleDefinitionId} {Error}", ModuleDefinitionId, ex.Message);
|
||||
AddModuleMessage("Error Saving Module", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,8 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Modules.Controls
|
||||
@namespace Oqtane.Modules.Admin.ModuleDefinitions
|
||||
@namespace Oqtane.Modules.Admin.ModuleDefinitions
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IModuleDefinitionService ModuleDefinitionService
|
||||
@inject IPackageService PackageService
|
||||
|
||||
@if (moduledefinitions == null)
|
||||
{
|
||||
@ -14,30 +11,94 @@
|
||||
else
|
||||
{
|
||||
<ActionLink Action="Add" Text="Install Module" />
|
||||
<table class="table table-borderless">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var moduledefinition in moduledefinitions)
|
||||
{
|
||||
<tr>
|
||||
<td>@moduledefinition.Name</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<Pager Items="@moduledefinitions">
|
||||
<Header>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th>Name</th>
|
||||
<th>Version</th>
|
||||
<th> </th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.ModuleDefinitionId.ToString())" /></td>
|
||||
<td>
|
||||
@if (context.AssemblyName != "Oqtane.Client")
|
||||
{
|
||||
<ActionDialog Header="Delete Module" Message="@("Are You Sure You Wish To Delete The " + context.Name + " Module?")" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" />
|
||||
}
|
||||
</td>
|
||||
<td>@context.Name</td>
|
||||
<td>@context.Version</td>
|
||||
<td>
|
||||
@if (UpgradeAvailable(context.ModuleDefinitionName, context.Version))
|
||||
{
|
||||
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadModule(context.ModuleDefinitionName, context.Version))>Upgrade</button>
|
||||
}
|
||||
</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||
|
||||
List<ModuleDefinition> moduledefinitions;
|
||||
List<Package> packages;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync();
|
||||
try
|
||||
{
|
||||
moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
|
||||
packages = await PackageService.GetPackagesAsync("module");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Modules {Error}", ex.Message);
|
||||
AddModuleMessage("Error Loading Modules", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private bool UpgradeAvailable(string moduledefinitionname, string version)
|
||||
{
|
||||
bool upgradeavailable = false;
|
||||
Package package = packages.Where(item => item.PackageId == Utilities.GetTypeName(moduledefinitionname)).FirstOrDefault();
|
||||
if (package != null)
|
||||
{
|
||||
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0);
|
||||
}
|
||||
return upgradeavailable;
|
||||
}
|
||||
|
||||
private async Task DownloadModule(string moduledefinitionname, string version)
|
||||
{
|
||||
try
|
||||
{
|
||||
await PackageService.DownloadPackageAsync(moduledefinitionname, version, "Modules");
|
||||
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
|
||||
await logger.LogInformation("Module Downloaded {ModuleDefinitionName} {Version}", moduledefinitionname, version);
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Downloading Module {ModuleDefinitionName} {Version} {Error}", moduledefinitionname, version, ex.Message);
|
||||
AddModuleMessage("Error Downloading Module", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteModule(ModuleDefinition ModuleDefinition)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ModuleDefinitionService.DeleteModuleDefinitionAsync(ModuleDefinition.ModuleDefinitionId, ModuleDefinition.SiteId);
|
||||
await logger.LogInformation("Module Deleted {ModuleDefinition}", ModuleDefinition);
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Deleting Module {ModuleDefinition} {Error}", ModuleDefinition, ex.Message);
|
||||
AddModuleMessage("Error Deleting Module", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
32
Oqtane.Client/Modules/Admin/Modules/Export.razor
Normal file
32
Oqtane.Client/Modules/Admin/Modules/Export.razor
Normal file
@ -0,0 +1,32 @@
|
||||
@namespace Oqtane.Modules.Admin.Modules
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IModuleService ModuleService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Title" class="control-label">Content: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@content" rows="5" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="ExportModule">Export</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
public override string Title { get { return "Export Module"; } }
|
||||
|
||||
string content = "";
|
||||
|
||||
private async Task ExportModule()
|
||||
{
|
||||
content = await ModuleService.ExportModuleAsync(ModuleState.ModuleId);
|
||||
}
|
||||
}
|
49
Oqtane.Client/Modules/Admin/Modules/Import.razor
Normal file
49
Oqtane.Client/Modules/Admin/Modules/Import.razor
Normal file
@ -0,0 +1,49 @@
|
||||
@namespace Oqtane.Modules.Admin.Modules
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IModuleService ModuleService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Title" class="control-label">Content: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@content" rows="5" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="ImportModule">Import</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
public override string Title { get { return "Import Module"; } }
|
||||
|
||||
string content = "";
|
||||
|
||||
|
||||
private async Task ImportModule()
|
||||
{
|
||||
if (content != "")
|
||||
{
|
||||
try
|
||||
{
|
||||
await ModuleService.ImportModuleAsync(ModuleState.ModuleId, content);
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Page));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Importing Module {ModuleId} {Error}", ModuleState.ModuleId, ex.Message);
|
||||
AddModuleMessage("Error Importing Module", MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage("You Must Enter Some Content To Import", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,4 @@
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Shared
|
||||
@using Oqtane.Security
|
||||
@using Oqtane.Modules.Controls
|
||||
@namespace Oqtane.Modules.Admin.ModuleSettings
|
||||
@namespace Oqtane.Modules.Admin.Modules
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IThemeService ThemeService
|
||||
@ -14,7 +6,7 @@
|
||||
@inject IPageModuleService PageModuleService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Title" class="control-label">Title: </label>
|
||||
@ -23,8 +15,6 @@
|
||||
<input type="text" name="Title" class="form-control" @bind="@title" />
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Container" class="control-label">Container: </label>
|
||||
@ -44,7 +34,7 @@
|
||||
<label for="Name" class="control-label">Permissions: </label>
|
||||
</td>
|
||||
<td>
|
||||
<PermissionGrid EntityName="Module" Permissions="@permissions" @ref="permissiongrid" />
|
||||
<PermissionGrid EntityName="Module" PermissionNames="@permissionnames" Permissions="@permissions" @ref="permissiongrid" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -76,6 +66,7 @@
|
||||
Dictionary<string, string> containers = new Dictionary<string, string>();
|
||||
string title;
|
||||
string containertype;
|
||||
string permissionnames = "";
|
||||
string permissions;
|
||||
string pageid;
|
||||
|
||||
@ -90,6 +81,7 @@
|
||||
containers = ThemeService.GetContainerTypes(await ThemeService.GetThemesAsync());
|
||||
containertype = ModuleState.ContainerType;
|
||||
permissions = ModuleState.Permissions;
|
||||
permissionnames = PageState.ModuleDefinitions.Find(item => item.ModuleDefinitionName == ModuleState.ModuleDefinitionName).PermissionNames;
|
||||
pageid = ModuleState.PageId.ToString();
|
||||
|
||||
DynamicComponent = builder =>
|
||||
@ -111,9 +103,11 @@
|
||||
await ModuleService.UpdateModuleAsync(module);
|
||||
|
||||
PageModule pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
|
||||
pagemodule.PageId = int.Parse(pageid);
|
||||
pagemodule.Title = title;
|
||||
pagemodule.ContainerType = containertype;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
|
||||
Type moduleType = Type.GetType(ModuleState.ModuleType);
|
||||
if (moduleType != null)
|
||||
@ -121,8 +115,7 @@
|
||||
moduleType.GetMethod("UpdateSettings").Invoke(settings, null); // method must be public in settings component
|
||||
}
|
||||
|
||||
PageState.Reload = Constants.ReloadPage;
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Page));
|
||||
}
|
||||
|
||||
}
|
@ -1,151 +1,150 @@
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Modules.Controls
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Shared
|
||||
@using Oqtane.Security
|
||||
@namespace Oqtane.Modules.Admin.Pages
|
||||
@namespace Oqtane.Modules.Admin.Pages
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IPageService PageService
|
||||
@inject IThemeService ThemeService
|
||||
|
||||
<ModuleMessage Message="@message" />
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Name: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Path: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@path" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Parent: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @onchange="(e => ParentChanged(e))">
|
||||
<option value=""><Site Root></option>
|
||||
@foreach (Page page in pages)
|
||||
{
|
||||
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Insert: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@insert">
|
||||
<option value="<<">At Beginning</option>
|
||||
@if (children != null && children.Count > 0)
|
||||
{
|
||||
<option value="<">Before</option>
|
||||
<option value=">">After</option>
|
||||
}
|
||||
<option value=">>" selected>At End</option>
|
||||
</select>
|
||||
@if (children != null && children.Count > 0 && (insert == "<" || insert == ">"))
|
||||
{
|
||||
<select class="form-control" @bind="@childid">
|
||||
<option value="-1"><Select Page></option>
|
||||
@foreach (Page page in children)
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Name: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Path: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@path" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Parent: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @onchange="(e => ParentChanged(e))">
|
||||
<option value="-1"><Site Root></option>
|
||||
@foreach (Page page in pages)
|
||||
{
|
||||
<option value="@(page.PageId)">@(page.Name)</option>
|
||||
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
||||
}
|
||||
</select>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Navigation? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@isnavigation">
|
||||
<option value="True">Yes</option>
|
||||
<option value="False">No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Edit Mode? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@editmode">
|
||||
<option value="True">Yes</option>
|
||||
<option value="False">No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Theme: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@themetype">
|
||||
<option value=""><Select Theme></option>
|
||||
@foreach (KeyValuePair<string, string> item in themes)
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Insert: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@insert">
|
||||
<option value="<<">At Beginning</option>
|
||||
@if (children != null && children.Count > 0)
|
||||
{
|
||||
<option value="<">Before</option>
|
||||
<option value=">">After</option>
|
||||
}
|
||||
<option value=">>">At End</option>
|
||||
</select>
|
||||
@if (children != null && children.Count > 0 && (insert == "<" || insert == ">"))
|
||||
{
|
||||
<option value="@item.Key">@item.Value</option>
|
||||
<select class="form-control" @bind="@childid">
|
||||
<option value="-1"><Select Page></option>
|
||||
@foreach (Page page in children)
|
||||
{
|
||||
<option value="@(page.PageId)">@(page.Name)</option>
|
||||
}
|
||||
</select>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Layout: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@layouttype">
|
||||
<option value=""><Select Layout></option>
|
||||
@foreach (KeyValuePair<string, string> panelayout in panelayouts)
|
||||
{
|
||||
<option value="@panelayout.Key">@panelayout.Value</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Icon: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@icon" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Permissions: </label>
|
||||
</td>
|
||||
<td>
|
||||
<PermissionGrid EntityName="Page" Permissions="@permissions" @ref="permissiongrid" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Navigation? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@isnavigation">
|
||||
<option value="True">Yes</option>
|
||||
<option value="False">No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Personalizable? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@ispersonalizable">
|
||||
<option value="True">Yes</option>
|
||||
<option value="False">No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Default Mode? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@mode">
|
||||
<option value="view">View Mode</option>
|
||||
<option value="edit">Edit Mode</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Theme: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @onchange="(e => ThemeChanged(e))">
|
||||
<option value=""><Select Theme></option>
|
||||
@foreach (KeyValuePair<string, string> item in themes)
|
||||
{
|
||||
<option value="@item.Key">@item.Value</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Layout: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@layouttype">
|
||||
<option value=""><Select Layout></option>
|
||||
@foreach (KeyValuePair<string, string> panelayout in panelayouts)
|
||||
{
|
||||
<option value="@panelayout.Key">@panelayout.Value</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Icon: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@icon" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Permissions: </label>
|
||||
</td>
|
||||
<td>
|
||||
<PermissionGrid EntityName="Page" Permissions="@permissions" @ref="permissiongrid" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SavePage">Save</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
string message = "";
|
||||
|
||||
Dictionary<string, string> themes = new Dictionary<string, string>();
|
||||
Dictionary<string, string> panelayouts = new Dictionary<string, string>();
|
||||
|
||||
@ -157,7 +156,8 @@
|
||||
List<Page> children;
|
||||
int childid = -1;
|
||||
string isnavigation = "True";
|
||||
string editmode = "False";
|
||||
string ispersonalizable = "False";
|
||||
string mode = "view";
|
||||
string themetype = "";
|
||||
string layouttype = "";
|
||||
string icon = "";
|
||||
@ -165,7 +165,7 @@
|
||||
|
||||
PermissionGrid permissiongrid;
|
||||
|
||||
protected override void OnInitialized()
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -173,7 +173,10 @@
|
||||
children = PageState.Pages.Where(item => item.ParentId == null).ToList();
|
||||
|
||||
themes = ThemeService.GetThemeTypes(PageState.Themes);
|
||||
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes);
|
||||
themetype = PageState.Site.DefaultThemeType;
|
||||
|
||||
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes, themetype);
|
||||
layouttype = PageState.Site.DefaultLayoutType;
|
||||
|
||||
List<PermissionString> permissionstrings = new List<PermissionString>();
|
||||
permissionstrings.Add(new PermissionString { PermissionName = "View", Permissions = Constants.AdminRole });
|
||||
@ -182,16 +185,17 @@
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
message = ex.Message;
|
||||
await logger.LogError(ex, "Error Initializing Page {Error}", ex.Message);
|
||||
AddModuleMessage("Error Initializing Page", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void ParentChanged(ChangeEventArgs e)
|
||||
private async void ParentChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
parentid = (string)e.Value;
|
||||
if (string.IsNullOrEmpty(parentid))
|
||||
if (parentid == "-1")
|
||||
{
|
||||
children = PageState.Pages.Where(item => item.ParentId == null).ToList();
|
||||
}
|
||||
@ -203,87 +207,121 @@
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
message = ex.Message;
|
||||
await logger.LogError(ex, "Error Loading Child Pages For Parent {PageId} {Error}", parentid, ex.Message);
|
||||
AddModuleMessage("Error Loading Child Pages For Parent", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async void ThemeChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
themetype = (string)e.Value;
|
||||
if (themetype != "")
|
||||
{
|
||||
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes, themetype);
|
||||
}
|
||||
else
|
||||
{
|
||||
panelayouts = new Dictionary<string, string>();
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Pane Layouts For Theme {ThemeType} {Error}", themetype, ex.Message);
|
||||
AddModuleMessage("Error Loading Pane Layouts For Theme", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SavePage()
|
||||
{
|
||||
Page page = null;
|
||||
try
|
||||
{
|
||||
Page page = new Page();
|
||||
page.SiteId = PageState.Page.SiteId;
|
||||
page.Name = name;
|
||||
if (path == "")
|
||||
if (name != "" && !string.IsNullOrEmpty(themetype) && (panelayouts.Count == 0 || !string.IsNullOrEmpty(layouttype)))
|
||||
{
|
||||
path = name;
|
||||
}
|
||||
if (path.Contains("/"))
|
||||
{
|
||||
path = path.Substring(path.LastIndexOf("/") + 1);
|
||||
}
|
||||
if (string.IsNullOrEmpty(parentid))
|
||||
{
|
||||
page.ParentId = null;
|
||||
page.Path = Utilities.GetFriendlyUrl(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
page.ParentId = Int32.Parse(parentid);
|
||||
Page parent = PageState.Pages.Where(item => item.PageId == page.ParentId).FirstOrDefault();
|
||||
if (parent.Path == "")
|
||||
page = new Page();
|
||||
page.SiteId = PageState.Page.SiteId;
|
||||
page.Name = name;
|
||||
if (path == "")
|
||||
{
|
||||
page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(path);
|
||||
path = name;
|
||||
}
|
||||
if (path.Contains("/"))
|
||||
{
|
||||
path = path.Substring(path.LastIndexOf("/") + 1);
|
||||
}
|
||||
if (string.IsNullOrEmpty(parentid))
|
||||
{
|
||||
page.ParentId = null;
|
||||
page.Path = Utilities.GetFriendlyUrl(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(path);
|
||||
page.ParentId = Int32.Parse(parentid);
|
||||
Page parent = PageState.Pages.Where(item => item.PageId == page.ParentId).FirstOrDefault();
|
||||
if (parent.Path == "")
|
||||
{
|
||||
page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
Page child;
|
||||
switch (insert)
|
||||
{
|
||||
case "<<":
|
||||
page.Order = 0;
|
||||
break;
|
||||
case "<":
|
||||
child = PageState.Pages.Where(item => item.PageId == childid).FirstOrDefault();
|
||||
page.Order = child.Order - 1;
|
||||
break;
|
||||
case ">":
|
||||
child = PageState.Pages.Where(item => item.PageId == childid).FirstOrDefault();
|
||||
page.Order = child.Order + 1;
|
||||
break;
|
||||
case ">>":
|
||||
page.Order = int.MaxValue;
|
||||
break;
|
||||
}
|
||||
page.IsNavigation = (isnavigation == null ? true : Boolean.Parse(isnavigation));
|
||||
page.EditMode = (editmode == null ? true : Boolean.Parse(editmode));
|
||||
page.ThemeType = themetype;
|
||||
page.LayoutType = (layouttype == null ? "" : layouttype);
|
||||
page.Icon = (icon == null ? "" : icon);
|
||||
Type type;
|
||||
if (!string.IsNullOrEmpty(layouttype))
|
||||
{
|
||||
type = Type.GetType(layouttype);
|
||||
Page child;
|
||||
switch (insert)
|
||||
{
|
||||
case "<<":
|
||||
page.Order = 0;
|
||||
break;
|
||||
case "<":
|
||||
child = PageState.Pages.Where(item => item.PageId == childid).FirstOrDefault();
|
||||
page.Order = child.Order - 1;
|
||||
break;
|
||||
case ">":
|
||||
child = PageState.Pages.Where(item => item.PageId == childid).FirstOrDefault();
|
||||
page.Order = child.Order + 1;
|
||||
break;
|
||||
case ">>":
|
||||
page.Order = int.MaxValue;
|
||||
break;
|
||||
}
|
||||
page.IsNavigation = (isnavigation == null ? true : Boolean.Parse(isnavigation));
|
||||
page.EditMode = (mode == "edit" ? true : false);
|
||||
page.ThemeType = themetype;
|
||||
page.LayoutType = (layouttype == null ? "" : layouttype);
|
||||
page.Icon = (icon == null ? "" : icon);
|
||||
page.Permissions = permissiongrid.GetPermissions();
|
||||
|
||||
if (page.ThemeType == PageState.Site.DefaultThemeType)
|
||||
{
|
||||
page.ThemeType = "";
|
||||
}
|
||||
if (page.LayoutType == PageState.Site.DefaultLayoutType)
|
||||
{
|
||||
page.LayoutType = "";
|
||||
}
|
||||
page.IsPersonalizable = (ispersonalizable == null ? false : Boolean.Parse(ispersonalizable));
|
||||
page.UserId = null;
|
||||
|
||||
await PageService.AddPageAsync(page);
|
||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId);
|
||||
|
||||
await logger.LogInformation("Page Added {Page}", page);
|
||||
NavigationManager.NavigateTo(NavigateUrl(page.Path, Reload.Site));
|
||||
}
|
||||
else
|
||||
{
|
||||
type = Type.GetType(themetype);
|
||||
AddModuleMessage("You Must Provide Page Name And Theme", MessageType.Warning);
|
||||
}
|
||||
System.Reflection.PropertyInfo property = type.GetProperty("Panes");
|
||||
page.Panes = (string)property.GetValue(Activator.CreateInstance(type), null);
|
||||
page.Permissions = permissiongrid.GetPermissions();
|
||||
await PageService.AddPageAsync(page);
|
||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.ParentId);
|
||||
|
||||
PageState.Reload = Constants.ReloadSite;
|
||||
NavigationManager.NavigateTo(NavigateUrl(page.Path));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
message = ex.Message;
|
||||
await logger.LogError(ex, "Error Saving Page {Page} {Error}", page, ex.Message);
|
||||
AddModuleMessage("Error Saving Page", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,197 +0,0 @@
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Modules.Controls
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Shared
|
||||
@using Oqtane.Security
|
||||
@namespace Oqtane.Modules.Admin.Pages
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IPageService PageService
|
||||
@inject IThemeService ThemeService
|
||||
|
||||
<ModuleMessage Message="@message" />
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Name: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@name" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Path: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@path" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Parent: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@parentid" readonly>
|
||||
<option value=""><Select Parent></option>
|
||||
@foreach (Page p in PageState.Pages)
|
||||
{
|
||||
<option value="@p.PageId">@p.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Navigation? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@isnavigation" readonly>
|
||||
<option value="True">Yes</option>
|
||||
<option value="False">No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Edit Mode? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@editmode" readonly>
|
||||
<option value="True">Yes</option>
|
||||
<option value="False">No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Theme: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@themetype" readonly>
|
||||
<option value=""><Select Theme></option>
|
||||
@foreach (KeyValuePair<string, string> item in themes)
|
||||
{
|
||||
<option value="@item.Key">@item.Value</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Layout: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@layouttype" readonly>
|
||||
<option value=""><Select Layout></option>
|
||||
@foreach (KeyValuePair<string, string> panelayout in panelayouts)
|
||||
{
|
||||
<option value="@panelayout.Key">@panelayout.Value</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Icon: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@icon" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Permissions: </label>
|
||||
</td>
|
||||
<td>
|
||||
<PermissionGrid EntityName="Page" Permissions="@permissions" @ref="permissiongrid" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-danger" @onclick="DeletePage">Delete</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
string message = "";
|
||||
|
||||
Dictionary<string, string> themes = new Dictionary<string, string>();
|
||||
Dictionary<string, string> panelayouts = new Dictionary<string, string>();
|
||||
|
||||
int PageId;
|
||||
string name;
|
||||
string path;
|
||||
string parentid = "";
|
||||
string isnavigation;
|
||||
string editmode;
|
||||
string themetype;
|
||||
string layouttype;
|
||||
string icon;
|
||||
string permissions;
|
||||
string createdby;
|
||||
DateTime createdon;
|
||||
string modifiedby;
|
||||
DateTime modifiedon;
|
||||
|
||||
PermissionGrid permissiongrid;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
try
|
||||
{
|
||||
themes = ThemeService.GetThemeTypes(PageState.Themes);
|
||||
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes);
|
||||
|
||||
PageId = Int32.Parse(PageState.QueryString["id"]);
|
||||
Page page = PageState.Pages.Where(item => item.PageId == PageId).FirstOrDefault();
|
||||
if (page != null)
|
||||
{
|
||||
name = page.Name;
|
||||
path = page.Path;
|
||||
isnavigation = page.IsNavigation.ToString();
|
||||
editmode = page.EditMode.ToString();
|
||||
themetype = page.ThemeType;
|
||||
layouttype = page.LayoutType;
|
||||
icon = page.Icon;
|
||||
permissions = page.Permissions;
|
||||
createdby = page.CreatedBy;
|
||||
createdon = page.CreatedOn;
|
||||
modifiedby = page.ModifiedBy;
|
||||
modifiedon = page.ModifiedOn;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
message = ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeletePage()
|
||||
{
|
||||
try
|
||||
{
|
||||
await PageService.DeletePageAsync(Int32.Parse(PageState.QueryString["id"]));
|
||||
PageState.Reload = Constants.ReloadSite;
|
||||
if (PageState.Page.Name == "Page Management")
|
||||
{
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
else
|
||||
{
|
||||
NavigationManager.NavigateTo(NavigateUrl(""));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
message = ex.Message;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +1,9 @@
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Modules.Controls
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Shared
|
||||
@using Oqtane.Security
|
||||
@namespace Oqtane.Modules.Admin.Pages
|
||||
@namespace Oqtane.Modules.Admin.Pages
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IPageService PageService
|
||||
@inject IThemeService ThemeService
|
||||
|
||||
<ModuleMessage Message="@message" />
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
@ -37,7 +27,7 @@
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @onchange="(e => ParentChanged(e))">
|
||||
<option value=""><Site Root></option>
|
||||
<option value="-1"><Site Root></option>
|
||||
@foreach (Page page in pages)
|
||||
{
|
||||
if (page.PageId.ToString() == parentid)
|
||||
@ -60,7 +50,7 @@
|
||||
<select class="form-control" @bind="@insert">
|
||||
@if (parentid == currentparentid)
|
||||
{
|
||||
<option value=""><Maintain Current Location></option>
|
||||
<option value="="><Maintain Current Location></option>
|
||||
}
|
||||
<option value="<<">To Beginning</option>
|
||||
@if (children != null && children.Count > 0)
|
||||
@ -68,7 +58,7 @@
|
||||
<option value="<">Before</option>
|
||||
<option value=">">After</option>
|
||||
}
|
||||
<option value=">>" selected>To End</option>
|
||||
<option value=">>">To End</option>
|
||||
</select>
|
||||
@if (children != null && children.Count > 0 && (insert == "<" || insert == ">"))
|
||||
{
|
||||
@ -95,25 +85,43 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Edit Mode? </label>
|
||||
<label for="Name" class="control-label">Personalizable? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@editmode">
|
||||
<select class="form-control" @bind="@ispersonalizable">
|
||||
<option value="True">Yes</option>
|
||||
<option value="False">No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Default Mode? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@mode">
|
||||
<option value="view">View Mode</option>
|
||||
<option value="edit">Edit Mode</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Theme: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@themetype">
|
||||
<select class="form-control" @onchange="(e => ThemeChanged(e))">
|
||||
<option value=""><Select Theme></option>
|
||||
@foreach (KeyValuePair<string, string> item in themes)
|
||||
{
|
||||
<option value="@item.Key">@item.Value</option>
|
||||
if (item.Key == themetype)
|
||||
{
|
||||
<option value="@item.Key" selected>@item.Value</option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="@item.Key">@item.Value</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
@ -153,13 +161,11 @@
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
|
||||
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon" DeletedBy="@deletedby" DeletedOn="@deletedon"></AuditInfo>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
string message = "";
|
||||
|
||||
Dictionary<string, string> themes = new Dictionary<string, string>();
|
||||
Dictionary<string, string> panelayouts = new Dictionary<string, string>();
|
||||
|
||||
@ -169,11 +175,12 @@
|
||||
string path;
|
||||
string currentparentid;
|
||||
string parentid;
|
||||
string insert = "";
|
||||
string insert = "=";
|
||||
List<Page> children;
|
||||
int childid = -1;
|
||||
string isnavigation;
|
||||
string editmode;
|
||||
string ispersonalizable;
|
||||
string mode;
|
||||
string themetype;
|
||||
string layouttype;
|
||||
string icon;
|
||||
@ -182,10 +189,12 @@
|
||||
DateTime createdon;
|
||||
string modifiedby;
|
||||
DateTime modifiedon;
|
||||
string deletedby;
|
||||
DateTime? deletedon;
|
||||
|
||||
PermissionGrid permissiongrid;
|
||||
|
||||
protected override void OnInitialized()
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -193,7 +202,6 @@
|
||||
children = PageState.Pages.Where(item => item.ParentId == null).ToList();
|
||||
|
||||
themes = ThemeService.GetThemeTypes(PageState.Themes);
|
||||
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes);
|
||||
|
||||
PageId = Int32.Parse(PageState.QueryString["id"]);
|
||||
Page page = PageState.Pages.Where(item => item.PageId == PageId).FirstOrDefault();
|
||||
@ -215,8 +223,10 @@
|
||||
}
|
||||
currentparentid = parentid;
|
||||
isnavigation = page.IsNavigation.ToString();
|
||||
editmode = page.EditMode.ToString();
|
||||
ispersonalizable = page.IsPersonalizable.ToString();
|
||||
mode = (page.EditMode) ? "edit" : "view";
|
||||
themetype = page.ThemeType;
|
||||
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes, themetype);
|
||||
layouttype = page.LayoutType;
|
||||
icon = page.Icon;
|
||||
permissions = page.Permissions;
|
||||
@ -224,20 +234,23 @@
|
||||
createdon = page.CreatedOn;
|
||||
modifiedby = page.ModifiedBy;
|
||||
modifiedon = page.ModifiedOn;
|
||||
deletedby = page.DeletedBy;
|
||||
deletedon = page.DeletedOn;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
message = ex.Message;
|
||||
await logger.LogError(ex, "Error Loading Page {PageId} {Error}", PageId, ex.Message);
|
||||
AddModuleMessage("Error Loading Page", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void ParentChanged(ChangeEventArgs e)
|
||||
private async void ParentChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
parentid = (string)e.Value;
|
||||
if (string.IsNullOrEmpty(parentid))
|
||||
if (parentid == "-1")
|
||||
{
|
||||
children = PageState.Pages.Where(item => item.ParentId == null).ToList();
|
||||
}
|
||||
@ -247,7 +260,7 @@
|
||||
}
|
||||
if (parentid == currentparentid)
|
||||
{
|
||||
insert = "";
|
||||
insert = "=";
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -257,109 +270,142 @@
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
message = ex.Message;
|
||||
await logger.LogError(ex, "Error Loading Child Pages For Parent {PageId} {Error}", parentid, ex.Message);
|
||||
AddModuleMessage("Error Loading Child Pages For Parent", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async void ThemeChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
themetype = (string)e.Value;
|
||||
if (themetype != "")
|
||||
{
|
||||
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes, themetype);
|
||||
}
|
||||
else
|
||||
{
|
||||
panelayouts = new Dictionary<string, string>();
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Pane Layouts For Theme {ThemeType} {Error}", themetype, ex.Message);
|
||||
AddModuleMessage("Error Loading Pane Layouts For Theme", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SavePage()
|
||||
{
|
||||
Page page = null;
|
||||
try
|
||||
{
|
||||
Page page = PageState.Pages.Where(item => item.PageId == PageId).FirstOrDefault();
|
||||
string currentpath = page.Path;
|
||||
if (name != "" && !string.IsNullOrEmpty(themetype) && (panelayouts.Count == 0 || !string.IsNullOrEmpty(layouttype)))
|
||||
{
|
||||
page = PageState.Pages.Where(item => item.PageId == PageId).FirstOrDefault();
|
||||
string currentpath = page.Path;
|
||||
|
||||
page.Name = name;
|
||||
if (path == "")
|
||||
{
|
||||
path = name;
|
||||
}
|
||||
if (path.Contains("/"))
|
||||
{
|
||||
path = path.Substring(path.LastIndexOf("/") + 1);
|
||||
}
|
||||
if (string.IsNullOrEmpty(parentid))
|
||||
{
|
||||
page.ParentId = null;
|
||||
page.Path = Utilities.GetFriendlyUrl(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
page.ParentId = Int32.Parse(parentid);
|
||||
Page parent = PageState.Pages.Where(item => item.PageId == page.ParentId).FirstOrDefault();
|
||||
if (parent.Path == "")
|
||||
page.Name = name;
|
||||
if (path == "" && name.ToLower() != "home")
|
||||
{
|
||||
page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(path);
|
||||
path = name;
|
||||
}
|
||||
if (path.Contains("/"))
|
||||
{
|
||||
path = path.Substring(path.LastIndexOf("/") + 1);
|
||||
}
|
||||
if (string.IsNullOrEmpty(parentid))
|
||||
{
|
||||
page.ParentId = null;
|
||||
page.Path = Utilities.GetFriendlyUrl(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(path);
|
||||
page.ParentId = Int32.Parse(parentid);
|
||||
Page parent = PageState.Pages.Where(item => item.PageId == page.ParentId).FirstOrDefault();
|
||||
if (parent.Path == "")
|
||||
{
|
||||
page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (insert != "")
|
||||
{
|
||||
Page child;
|
||||
switch (insert)
|
||||
if (insert != "=")
|
||||
{
|
||||
case "<<":
|
||||
page.Order = 0;
|
||||
break;
|
||||
case "<":
|
||||
child = PageState.Pages.Where(item => item.PageId == childid).FirstOrDefault();
|
||||
page.Order = child.Order - 1;
|
||||
break;
|
||||
case ">":
|
||||
child = PageState.Pages.Where(item => item.PageId == childid).FirstOrDefault();
|
||||
page.Order = child.Order + 1;
|
||||
break;
|
||||
case ">>":
|
||||
page.Order = int.MaxValue;
|
||||
break;
|
||||
Page child;
|
||||
switch (insert)
|
||||
{
|
||||
case "<<":
|
||||
page.Order = 0;
|
||||
break;
|
||||
case "<":
|
||||
child = PageState.Pages.Where(item => item.PageId == childid).FirstOrDefault();
|
||||
page.Order = child.Order - 1;
|
||||
break;
|
||||
case ">":
|
||||
child = PageState.Pages.Where(item => item.PageId == childid).FirstOrDefault();
|
||||
page.Order = child.Order + 1;
|
||||
break;
|
||||
case ">>":
|
||||
page.Order = int.MaxValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
page.IsNavigation = (isnavigation == null ? true : Boolean.Parse(isnavigation));
|
||||
page.EditMode = (editmode == null ? true : Boolean.Parse(editmode));
|
||||
page.ThemeType = themetype;
|
||||
page.LayoutType = (layouttype == null ? "" : layouttype);
|
||||
page.Icon = (icon == null ? "" : icon);
|
||||
Type type;
|
||||
if (!string.IsNullOrEmpty(layouttype))
|
||||
{
|
||||
type = Type.GetType(layouttype);
|
||||
page.IsNavigation = (isnavigation == null ? true : Boolean.Parse(isnavigation));
|
||||
page.EditMode = (mode == "edit" ? true : false);
|
||||
page.ThemeType = themetype;
|
||||
page.LayoutType = (layouttype == null ? "" : layouttype);
|
||||
page.Icon = (icon == null ? "" : icon);
|
||||
page.Permissions = permissiongrid.GetPermissions();
|
||||
|
||||
if (page.ThemeType == PageState.Site.DefaultThemeType)
|
||||
{
|
||||
page.ThemeType = "";
|
||||
}
|
||||
if (page.LayoutType == PageState.Site.DefaultLayoutType)
|
||||
{
|
||||
page.LayoutType = "";
|
||||
}
|
||||
page.IsPersonalizable = (ispersonalizable == null ? false : Boolean.Parse(ispersonalizable));
|
||||
page.UserId = null;
|
||||
|
||||
await PageService.UpdatePageAsync(page);
|
||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId);
|
||||
if (currentparentid == "")
|
||||
{
|
||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, int.Parse(currentparentid));
|
||||
}
|
||||
|
||||
// update child paths
|
||||
if (parentid != currentparentid)
|
||||
{
|
||||
foreach (Page p in PageState.Pages.Where(item => item.Path.StartsWith(currentpath)))
|
||||
{
|
||||
p.Path = p.Path.Replace(currentpath, page.Path);
|
||||
await PageService.UpdatePageAsync(p);
|
||||
}
|
||||
}
|
||||
|
||||
await logger.LogInformation("Page Saved {Page}", page);
|
||||
NavigationManager.NavigateTo(NavigateUrl(page.Path, Reload.Site));
|
||||
}
|
||||
else
|
||||
{
|
||||
type = Type.GetType(themetype);
|
||||
AddModuleMessage("You Must Provide Page Name And Theme", MessageType.Warning);
|
||||
}
|
||||
System.Reflection.PropertyInfo property = type.GetProperty("Panes");
|
||||
page.Panes = (string)property.GetValue(Activator.CreateInstance(type), null);
|
||||
page.Permissions = permissiongrid.GetPermissions();
|
||||
await PageService.UpdatePageAsync(page);
|
||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.ParentId);
|
||||
if (currentparentid == "")
|
||||
{
|
||||
await PageService.UpdatePageOrderAsync(page.SiteId, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
await PageService.UpdatePageOrderAsync(page.SiteId, int.Parse(currentparentid));
|
||||
}
|
||||
|
||||
// update child paths
|
||||
if (parentid != currentparentid)
|
||||
{
|
||||
foreach (Page p in PageState.Pages.Where(item => item.Path.StartsWith(currentpath)))
|
||||
{
|
||||
p.Path = p.Path.Replace(currentpath, page.Path);
|
||||
await PageService.UpdatePageAsync(p);
|
||||
}
|
||||
}
|
||||
|
||||
PageState.Reload = Constants.ReloadSite;
|
||||
NavigationManager.NavigateTo(NavigateUrl(page.Path));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
message = ex.Message;
|
||||
await logger.LogError(ex, "Error Saving Page {Page} {Error}", page, ex.Message);
|
||||
AddModuleMessage("Error Saving Page", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,37 +1,42 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Modules.Controls
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Shared
|
||||
@namespace Oqtane.Modules.Admin.Pages
|
||||
@namespace Oqtane.Modules.Admin.Pages
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IPageService PageService
|
||||
|
||||
@if (PageState.Pages != null)
|
||||
{
|
||||
<ActionLink Action="Add" Text="Add Page" />
|
||||
<table class="table table-borderless">
|
||||
<thead>
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th>Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (Page page in PageState.Pages)
|
||||
{
|
||||
<tr>
|
||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + page.PageId.ToString())" /></td>
|
||||
<td><ActionLink Action="Delete" Parameters="@($"id=" + page.PageId.ToString())" Class="btn btn-danger" /></td>
|
||||
<td>@(new string('-', page.Level * 2))@(page.Name)</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<Pager Items="@PageState.Pages.Where(item => !item.IsDeleted)">
|
||||
<Header>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th>Name</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.PageId.ToString())" /></td>
|
||||
<td><ActionDialog Header="Delete Page" Message="@("Are You Sure You Wish To Delete The " + context.Name + " Page?")" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeletePage(context))" /></td>
|
||||
<td>@(new string('-', context.Level * 2))@(context.Name)</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
private async Task DeletePage(Page Page)
|
||||
{
|
||||
try
|
||||
{
|
||||
Page.IsDeleted = true;
|
||||
await PageService.UpdatePageAsync(Page);
|
||||
await logger.LogInformation("Page Deleted {Page}", Page);
|
||||
NavigationManager.NavigateTo(NavigateUrl("admin/pages", Reload.Site));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Deleting Page {Page} {Error}", Page, ex.Message);
|
||||
AddModuleMessage("Error Deleting Page", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
165
Oqtane.Client/Modules/Admin/Profiles/Edit.razor
Normal file
165
Oqtane.Client/Modules/Admin/Profiles/Edit.razor
Normal file
@ -0,0 +1,165 @@
|
||||
@namespace Oqtane.Modules.Admin.Profiles
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IProfileService ProfileService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Name: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Title: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@title" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Description: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@description" rows="5" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Category: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@category" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Order: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@vieworder" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Length: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@maxlength" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Default Value: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@defaultvalue" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Required? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@isrequired">
|
||||
<option value="True">Yes</option>
|
||||
<option value="False">No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Private? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@isprivate">
|
||||
<option value="True">Yes</option>
|
||||
<option value="False">No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveProfile">Save</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
public override string Actions { get { return "Add,Edit"; } }
|
||||
|
||||
int profileid = -1;
|
||||
string name = "";
|
||||
string title = "";
|
||||
string description = "";
|
||||
string category = "";
|
||||
string vieworder = "0";
|
||||
string maxlength = "0";
|
||||
string defaultvalue = "";
|
||||
string isrequired = "False";
|
||||
string isprivate = "False";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (PageState.QueryString.ContainsKey("id"))
|
||||
{
|
||||
profileid = Int32.Parse(PageState.QueryString["id"]);
|
||||
Profile profile = await ProfileService.GetProfileAsync(profileid);
|
||||
if (profile != null)
|
||||
{
|
||||
name = profile.Name;
|
||||
title = profile.Title;
|
||||
description = profile.Description;
|
||||
category = profile.Category;
|
||||
vieworder = profile.ViewOrder.ToString();
|
||||
maxlength = profile.MaxLength.ToString();
|
||||
defaultvalue = profile.DefaultValue;
|
||||
isrequired = profile.IsRequired.ToString();
|
||||
isprivate = profile.IsPrivate.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Profile {ProfileId} {Error}", profileid, ex.Message);
|
||||
AddModuleMessage("Error Loading Profile", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveProfile()
|
||||
{
|
||||
try
|
||||
{
|
||||
Profile profile;
|
||||
if (profileid != -1)
|
||||
{
|
||||
profile = await ProfileService.GetProfileAsync(profileid);
|
||||
}
|
||||
else
|
||||
{
|
||||
profile = new Profile();
|
||||
}
|
||||
profile.Name = name;
|
||||
profile.Title = title;
|
||||
profile.Description = description;
|
||||
profile.Category = category;
|
||||
profile.ViewOrder = int.Parse(vieworder);
|
||||
profile.MaxLength = int.Parse(maxlength);
|
||||
profile.DefaultValue = defaultvalue;
|
||||
profile.IsRequired = (isrequired == null ? false : Boolean.Parse(isrequired));
|
||||
profile.IsPrivate = (isprivate == null ? false : Boolean.Parse(isprivate));
|
||||
profile = await ProfileService.UpdateProfileAsync(profile);
|
||||
await logger.LogInformation("Profile Saved {Profile}", profile);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving Profile {ProfleId} {Error}", profileid, ex.Message);
|
||||
AddModuleMessage("Error Saving Profile", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
51
Oqtane.Client/Modules/Admin/Profiles/Index.razor
Normal file
51
Oqtane.Client/Modules/Admin/Profiles/Index.razor
Normal file
@ -0,0 +1,51 @@
|
||||
@namespace Oqtane.Modules.Admin.Profiles
|
||||
@inherits ModuleBase
|
||||
@inject IProfileService ProfileService
|
||||
|
||||
@if (Profiles == null)
|
||||
{
|
||||
<p><em>Loading...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ActionLink Action="Add" Security="SecurityAccessLevel.Admin" Text="Add Profile" />
|
||||
|
||||
<Pager Items="@Profiles">
|
||||
<Header>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th>Name</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.ProfileId.ToString())" /></td>
|
||||
<td><ActionDialog Header="Delete Profile" Message="@("Are You Sure You Wish To Delete " + context.Name + "?")" Action="Delete" Class="btn btn-danger" OnClick="@(async () => await DeleteProfile(context.ProfileId))" /></td>
|
||||
<td>@context.Name</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
List<Profile> Profiles;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
Profiles = await ProfileService.GetProfilesAsync(PageState.Site.SiteId);
|
||||
}
|
||||
|
||||
private async Task DeleteProfile(int ProfileId)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ProfileService.DeleteProfileAsync(ProfileId);
|
||||
await logger.LogInformation("Profile Deleted {ProfileId}", ProfileId);
|
||||
AddModuleMessage("Profile Deleted", MessageType.Success);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Deleting Profile {ProfileId} {Error}", ProfileId, ex.Message);
|
||||
AddModuleMessage("Error Deleting Profile", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
174
Oqtane.Client/Modules/Admin/RecycleBin/Index.razor
Normal file
174
Oqtane.Client/Modules/Admin/RecycleBin/Index.razor
Normal file
@ -0,0 +1,174 @@
|
||||
@namespace Oqtane.Modules.Admin.RecycleBin
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IPageModuleService PageModuleService
|
||||
@inject IModuleService ModuleService
|
||||
@inject IPageService PageService
|
||||
|
||||
<TabControl>
|
||||
<TabPanel Text="Pages">
|
||||
@if (pages.Count == 0)
|
||||
{
|
||||
<br/>
|
||||
<p>No Deleted Pages</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<Pager Items="@pages">
|
||||
<Header>
|
||||
<th>Name</th>
|
||||
<th>Deleted By</th>
|
||||
<th>Deleted On</th>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td>@context.Name</td>
|
||||
<td>@context.DeletedBy</td>
|
||||
<td>@context.DeletedOn</td>
|
||||
<td><button @onclick="@(() => RestorePage(context))" class="btn btn-info" title="Restore">Restore</button></td>
|
||||
<td><button @onclick="@(() => DeletePage(context.PageId))" class="btn btn-danger">Delete</button></td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
</TabPanel>
|
||||
<TabPanel Text="Modules">
|
||||
@if (pageModules.Count == 0)
|
||||
{
|
||||
<br/>
|
||||
<p>No Deleted Modules</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<Pager Items="@pageModules">
|
||||
<Header>
|
||||
<th>Page</th>
|
||||
<th>Module</th>
|
||||
<th>Deleted By</th>
|
||||
<th>Deleted On</th>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td>@PageState.Pages.Find(item => item.PageId == context.PageId).Name</td>
|
||||
<td>@context.Title</td>
|
||||
<td>@context.DeletedBy</td>
|
||||
<td>@context.DeletedOn</td>
|
||||
<td><button @onclick="@(() => RestorePageModule(context))" class="btn btn-info" title="Restore">Restore</button></td>
|
||||
<td><button @onclick="@(() => DeletePageModule(context.PageModuleId, context.ModuleId))" class="btn btn-danger">Delete</button></td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
</TabPanel>
|
||||
</TabControl>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
List<Page> pages { get; set; }
|
||||
List<PageModule> pageModules { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
pages = new List<Page>();
|
||||
pageModules = new List<PageModule>();
|
||||
await LoadEntities();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Deleted Pages Or Modules {Error}", ex.Message);
|
||||
AddModuleMessage("Error Loading Deleted Pages Or Modules", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
pages = PageState.Pages.Where(item => item.IsDeleted).ToList();
|
||||
}
|
||||
|
||||
private async Task LoadEntities()
|
||||
{
|
||||
pageModules.Clear();
|
||||
foreach (var module in PageState.Modules.Where(item => item.IsDeleted))
|
||||
{
|
||||
var pageModule = await PageModuleService.GetPageModuleAsync(module.PageModuleId);
|
||||
pageModules.Add(pageModule);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RestorePage(Page Page)
|
||||
{
|
||||
try
|
||||
{
|
||||
Page.IsDeleted = false;
|
||||
await PageService.UpdatePageAsync(Page);
|
||||
await logger.LogInformation("Page Restored {Page}", Page);
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Site));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Restoring Deleted Page {Page} {Error}", Page, ex.Message);
|
||||
AddModuleMessage("Error Restoring Deleted Page", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeletePage(int PageId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var deletedPageModules = PageState.Modules.Where(item => item.PageId == PageId);
|
||||
await PageService.DeletePageAsync(PageId);
|
||||
foreach (var module in deletedPageModules)
|
||||
{
|
||||
await ModuleService.DeleteModuleAsync(module.ModuleId);
|
||||
}
|
||||
await logger.LogInformation("Page Permanently Deleted {PageId}", PageId);
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Site));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Permanently Deleting Page {PageId} {Error}", PageId, ex.Message);
|
||||
AddModuleMessage(ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RestorePageModule(PageModule PageModule)
|
||||
{
|
||||
try
|
||||
{
|
||||
PageModule.IsDeleted = false;
|
||||
await PageModuleService.UpdatePageModuleAsync(PageModule);
|
||||
await LoadEntities();
|
||||
await logger.LogInformation("Page Module Restored {PageModule}", PageModule);
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Site));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Restoring Deleted Page Module {PageModule} {Error}", PageModule, ex.Message);
|
||||
AddModuleMessage("Error Restoring Deleted Page Module", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeletePageModule(int PageModuleId, int ModuleId)
|
||||
{
|
||||
try
|
||||
{
|
||||
await PageModuleService.DeletePageModuleAsync(PageModuleId);
|
||||
if (PageState.Modules.Count(item => item.ModuleId == ModuleId) == 1)
|
||||
{
|
||||
await ModuleService.DeleteModuleAsync(ModuleId);
|
||||
}
|
||||
PageState.Modules.RemoveAt(PageState.Modules.FindIndex(item => item.ModuleId == ModuleId));
|
||||
await LoadEntities();
|
||||
await logger.LogInformation("Page Module Permanently Deleted {PageModuleId}", PageModuleId);
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Site));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Permanently Deleting Page Module {PageModuleId} {Error}", PageModuleId, ex.Message);
|
||||
AddModuleMessage("Error Permanently Deleting Page Module", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +1,20 @@
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Services
|
||||
@namespace Oqtane.Modules.Admin.Register
|
||||
@namespace Oqtane.Modules.Admin.Register
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IUserService UserService
|
||||
|
||||
<div class="container">
|
||||
<div class="form-group">
|
||||
<label for="Username" class="control-label">Email: </label>
|
||||
<input type="text" name="Username" class="form-control" placeholder="Username" @bind="@Email" />
|
||||
<label for="Username" class="control-label">Username: </label>
|
||||
<input type="text" class="form-control" placeholder="Username" @bind="@Username" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="Password" class="control-label">Password: </label>
|
||||
<input type="password" name="Password" class="form-control" placeholder="Password" @bind="@Password" />
|
||||
<input type="password" class="form-control" placeholder="Password" @bind="@Password" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="Username" class="control-label">Email: </label>
|
||||
<input type="text" class="form-control" placeholder="Username" @bind="@Email" />
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary" @onclick="RegisterUser">Register</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">Cancel</button>
|
||||
@ -24,24 +23,49 @@
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Anonymous; } }
|
||||
|
||||
public string Email { get; set; } = "";
|
||||
public string Password { get; set; } = "";
|
||||
string Username = "";
|
||||
string Password = "";
|
||||
string Email = "";
|
||||
|
||||
private async Task RegisterUser()
|
||||
{
|
||||
User user = new User();
|
||||
user.SiteId = PageState.Site.SiteId;
|
||||
user.Username = Email;
|
||||
user.DisplayName = Email;
|
||||
user.Email = Email;
|
||||
user.IsHost = false;
|
||||
user.Password = Password;
|
||||
await UserService.AddUserAsync(user);
|
||||
NavigationManager.NavigateTo("");
|
||||
try
|
||||
{
|
||||
if (Username != "" && Password != "" && Email != "")
|
||||
{
|
||||
User user = new User();
|
||||
user.SiteId = PageState.Site.SiteId;
|
||||
user.Username = Username;
|
||||
user.DisplayName = Username;
|
||||
user.Email = Email;
|
||||
user.Password = Password;
|
||||
user = await UserService.AddUserAsync(user);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
await logger.LogInformation("User Created {Username} {Email}", Username, Email);
|
||||
NavigationManager.NavigateTo(NavigateUrl(""));
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogError("Error Adding User {Username} {Email}", Username, Email);
|
||||
AddModuleMessage("Error Adding User. Please Ensure Password Meets Complexity Requirements And Username Is Not Already In Use.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage("You Must Provide A Username, Password, and Email Address", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Adding User {Username} {Email} {Error}", Username, Email, ex.Message);
|
||||
AddModuleMessage("Error Adding User", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void Cancel()
|
||||
{
|
||||
NavigationManager.NavigateTo(NavigateUrl("")); // navigate to home
|
||||
NavigationManager.NavigateTo(NavigateUrl(""));
|
||||
}
|
||||
}
|
||||
|
79
Oqtane.Client/Modules/Admin/Roles/Add.razor
Normal file
79
Oqtane.Client/Modules/Admin/Roles/Add.razor
Normal file
@ -0,0 +1,79 @@
|
||||
@namespace Oqtane.Modules.Admin.Roles
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IRoleService RoleService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Name: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Description: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@description" rows="5" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Auto Assigned? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@isautoassigned">
|
||||
<option value="True">Yes</option>
|
||||
<option value="False">No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">System Role? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@issystem">
|
||||
<option value="True">Yes</option>
|
||||
<option value="False">No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveRole">Save</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
string name = "";
|
||||
string description = "";
|
||||
string isautoassigned = "False";
|
||||
string issystem = "False";
|
||||
|
||||
private async Task SaveRole()
|
||||
{
|
||||
try
|
||||
{
|
||||
Role role = new Role();
|
||||
role.SiteId = PageState.Page.SiteId;
|
||||
role.Name = name;
|
||||
role.Description = description;
|
||||
role.IsAutoAssigned = (isautoassigned == null ? false : Boolean.Parse(isautoassigned));
|
||||
role.IsSystem = (issystem == null ? false : Boolean.Parse(issystem));
|
||||
role = await RoleService.AddRoleAsync(role);
|
||||
await logger.LogInformation("Role Added {Role}", role);
|
||||
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Adding Role", ex.Message);
|
||||
AddModuleMessage(ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
98
Oqtane.Client/Modules/Admin/Roles/Edit.razor
Normal file
98
Oqtane.Client/Modules/Admin/Roles/Edit.razor
Normal file
@ -0,0 +1,98 @@
|
||||
@namespace Oqtane.Modules.Admin.Roles
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IRoleService RoleService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Name: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Description: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@description" rows="5" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Auto Assigned? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@isautoassigned">
|
||||
<option value="True">Yes</option>
|
||||
<option value="False">No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">System Role? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@issystem">
|
||||
<option value="True">Yes</option>
|
||||
<option value="False">No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveRole">Save</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
int roleid;
|
||||
string name = "";
|
||||
string description = "";
|
||||
string isautoassigned = "False";
|
||||
string issystem = "False";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
roleid = Int32.Parse(PageState.QueryString["id"]);
|
||||
Role role = await RoleService.GetRoleAsync(roleid);
|
||||
if (role != null)
|
||||
{
|
||||
name = role.Name;
|
||||
description = role.Description;
|
||||
isautoassigned = role.IsAutoAssigned.ToString();
|
||||
issystem = role.IsSystem.ToString();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Role {RoleId} {Error}", roleid, ex.Message);
|
||||
AddModuleMessage("Error Loading Role", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveRole()
|
||||
{
|
||||
try
|
||||
{
|
||||
Role role = await RoleService.GetRoleAsync(roleid);
|
||||
role.Name = name;
|
||||
role.Description = description;
|
||||
role.IsAutoAssigned = (isautoassigned == null ? false : Boolean.Parse(isautoassigned));
|
||||
role.IsSystem = (issystem == null ? false : Boolean.Parse(issystem));
|
||||
role = await RoleService.UpdateRoleAsync(role);
|
||||
await logger.LogInformation("Role Saved {Role}", role);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving Role {RoleId} {Error}", roleid, ex.Message);
|
||||
AddModuleMessage("Error Saving Role", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,4 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Modules.Controls
|
||||
@namespace Oqtane.Modules.Admin.Roles
|
||||
@namespace Oqtane.Modules.Admin.Roles
|
||||
@inherits ModuleBase
|
||||
@inject IRoleService RoleService
|
||||
|
||||
@ -13,21 +8,20 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var Role in Roles)
|
||||
{
|
||||
<tr>
|
||||
<td>@Role.Name</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<ActionLink Action="Add" Text="Add Role" />
|
||||
|
||||
<Pager Items="@Roles">
|
||||
<Header>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th>Name</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.RoleId.ToString())" /></td>
|
||||
<td><ActionDialog Header="Delete Role" Message="@("Are You Sure You Wish To Delete The " + context.Name + " Role?")" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteRole(context))" /></td>
|
||||
<td>@context.Name</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
|
||||
@code {
|
||||
@ -35,8 +29,23 @@ else
|
||||
|
||||
List<Role> Roles;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
Roles = await RoleService.GetRolesAsync(PageState.Site.SiteId);
|
||||
}
|
||||
|
||||
private async Task DeleteRole(Role Role)
|
||||
{
|
||||
try
|
||||
{
|
||||
await RoleService.DeleteRoleAsync(Role.RoleId);
|
||||
await logger.LogInformation("Role Deleted {Role}", Role);
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Deleting Role {Role} {Error}", Role, ex.Message);
|
||||
AddModuleMessage("Error Deleting Role", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +1,11 @@
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Shared
|
||||
@using Oqtane.Security
|
||||
@namespace Oqtane.Modules.Admin.Sites
|
||||
@namespace Oqtane.Modules.Admin.Sites
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ITenantService TenantService
|
||||
@inject IAliasService AliasService
|
||||
@inject ISiteService SiteService
|
||||
@inject IPageService PageService
|
||||
@inject IThemeService ThemeService
|
||||
@inject IUserService UserService
|
||||
|
||||
@if (tenants == null)
|
||||
{
|
||||
@ -19,46 +13,107 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Tenant: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @onchange="(e => TenantChanged(e))">
|
||||
<option value="-1"><Select Tenant></option>
|
||||
@foreach (Tenant tenant in tenants)
|
||||
{
|
||||
<option value="@tenant.TenantId">@tenant.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Name: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Aliases: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@urls" rows="3" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Logo: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@logo" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Default Theme: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @onchange="(e => ThemeChanged(e))">
|
||||
<option value=""><Select Theme></option>
|
||||
@foreach (KeyValuePair<string, string> item in themes)
|
||||
{
|
||||
<option value="@item.Key">@item.Value</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Default Layout: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@layouttype">
|
||||
<option value=""><Select Layout></option>
|
||||
@foreach (KeyValuePair<string, string> panelayout in panelayouts)
|
||||
{
|
||||
<option value="@panelayout.Key">@panelayout.Value</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Default Container: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@containertype">
|
||||
<option value=""><Select Container></option>
|
||||
@foreach (KeyValuePair<string, string>container in containers)
|
||||
{
|
||||
<option value="@container.Key">@container.Value</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
@if (!isinitialized)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Tenant: </label>
|
||||
<label for="Name" class="control-label">Host Username:</label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@tenantid">
|
||||
<option value=""><Select Tenant></option>
|
||||
@foreach (Tenant tenant in tenants)
|
||||
{
|
||||
<option value="@tenant.TenantId">@tenant.Name</option>
|
||||
}
|
||||
</select>
|
||||
<input class="form-control" @bind="@username" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Name: </label>
|
||||
<label for="Name" class="control-label">Host Password:</label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@name" />
|
||||
<input type="password" class="form-control" @bind="@password" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Alias: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@url" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Logo: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@logo" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
}
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveSite">Save</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
}
|
||||
@ -66,54 +121,152 @@ else
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||
|
||||
Dictionary<string, string> themes = new Dictionary<string, string>();
|
||||
Dictionary<string, string> panelayouts = new Dictionary<string, string>();
|
||||
Dictionary<string, string> containers = new Dictionary<string, string>();
|
||||
|
||||
List<Tenant> tenants;
|
||||
string tenantid = "";
|
||||
string tenantid = "-1";
|
||||
string name = "";
|
||||
string url = "";
|
||||
string urls = "";
|
||||
string logo = "";
|
||||
string themetype = "";
|
||||
string layouttype = "";
|
||||
string containertype = "";
|
||||
bool isinitialized = true;
|
||||
string username = "";
|
||||
string password = "";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
tenants = await TenantService.GetTenantsAsync();
|
||||
urls = PageState.Alias.Name;
|
||||
themes = ThemeService.GetThemeTypes(PageState.Themes);
|
||||
containers = ThemeService.GetContainerTypes(PageState.Themes);
|
||||
username = PageState.User.Username;
|
||||
}
|
||||
|
||||
private async void TenantChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
tenantid = (string)e.Value;
|
||||
if (tenantid != "-1")
|
||||
{
|
||||
Tenant tenant = tenants.Where(item => item.TenantId == int.Parse(tenantid)).FirstOrDefault();
|
||||
if (tenant != null)
|
||||
{
|
||||
isinitialized = tenant.IsInitialized;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Tenant {TenantId} {Error}", tenantid, ex.Message);
|
||||
AddModuleMessage("Error Loading Tenant", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async void ThemeChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
themetype = (string)e.Value;
|
||||
if (themetype != "")
|
||||
{
|
||||
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes, themetype);
|
||||
}
|
||||
else
|
||||
{
|
||||
panelayouts = new Dictionary<string, string>();
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Pane Layouts For Theme {ThemeType} {Error}", themetype, ex.Message);
|
||||
AddModuleMessage("Error Loading Pane Layouts For Theme", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveSite()
|
||||
{
|
||||
Site site = new Site();
|
||||
site.Name = name;
|
||||
site.Logo = (logo == null ? "" : logo);
|
||||
await SiteService.AddSiteAsync(site);
|
||||
List<Site> sites = await SiteService.GetSitesAsync();
|
||||
site = sites.Where(item => item.Name == name).FirstOrDefault();
|
||||
if (tenantid != "-1" && name != "" && urls != "" && !string.IsNullOrEmpty(themetype) && (panelayouts.Count == 0 || !string.IsNullOrEmpty(layouttype)) && !string.IsNullOrEmpty(containertype))
|
||||
{
|
||||
bool isvalid = true;
|
||||
|
||||
Alias alias = new Alias();
|
||||
alias.Name = url;
|
||||
alias.TenantId = int.Parse(tenantid);
|
||||
alias.SiteId = site.SiteId;
|
||||
await AliasService.AddAliasAsync(alias);
|
||||
if (!isinitialized)
|
||||
{
|
||||
User user = new User();
|
||||
user.SiteId = PageState.Site.SiteId;
|
||||
user.Username = username;
|
||||
user.Password = password;
|
||||
user = await UserService.LoginUserAsync(user, false, false);
|
||||
isvalid = user.IsAuthenticated;
|
||||
}
|
||||
|
||||
// need to add a home page and admin pages
|
||||
Page p = new Page();
|
||||
p.SiteId = site.SiteId;
|
||||
p.ParentId = null;
|
||||
p.Name = "Home";
|
||||
p.Path = "";
|
||||
p.Order = 1;
|
||||
p.IsNavigation = true;
|
||||
p.ThemeType = PageState.Site.DefaultThemeType;
|
||||
p.LayoutType = "";
|
||||
p.Icon = "";
|
||||
Type type = Type.GetType(p.ThemeType);
|
||||
System.Reflection.PropertyInfo property = type.GetProperty("Panes");
|
||||
p.Panes = (string)property.GetValue(Activator.CreateInstance(type), null);
|
||||
if (isvalid)
|
||||
{
|
||||
List<Alias> aliases = new List<Alias>();
|
||||
urls = urls.Replace("\n", ",");
|
||||
foreach (string name in urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
Alias alias = new Alias();
|
||||
alias.Name = name;
|
||||
alias.TenantId = int.Parse(tenantid);
|
||||
alias.SiteId = -1;
|
||||
alias = await AliasService.AddAliasAsync(alias);
|
||||
aliases.Add(alias);
|
||||
}
|
||||
|
||||
List<PermissionString> permissionstrings = new List<PermissionString>();
|
||||
permissionstrings.Add(new PermissionString { PermissionName = "View", Permissions = Constants.AllUsersRole });
|
||||
permissionstrings.Add(new PermissionString { PermissionName = "Edit", Permissions = Constants.AdminRole });
|
||||
p.Permissions = UserSecurity.SetPermissionStrings(permissionstrings);
|
||||
Site site = new Site();
|
||||
site.TenantId = int.Parse(tenantid);
|
||||
site.Name = name;
|
||||
site.Logo = (logo == null ? "" : logo);
|
||||
site.DefaultThemeType = themetype;
|
||||
site.DefaultLayoutType = (layouttype == null ? "" : layouttype);
|
||||
site.DefaultContainerType = containertype;
|
||||
site = await SiteService.AddSiteAsync(site, aliases[0]);
|
||||
|
||||
await PageService.AddPageAsync(p);
|
||||
foreach(Alias alias in aliases)
|
||||
{
|
||||
alias.SiteId = site.SiteId;
|
||||
await AliasService.UpdateAliasAsync(alias);
|
||||
}
|
||||
|
||||
if (!isinitialized)
|
||||
{
|
||||
User user = new User();
|
||||
user.SiteId = site.SiteId;
|
||||
user.Username = username;
|
||||
user.Password = password;
|
||||
user.Email = PageState.User.Email;
|
||||
user.DisplayName = PageState.User.DisplayName;
|
||||
user = await UserService.AddUserAsync(user, aliases[0]);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
Tenant tenant = tenants.Where(item => item.TenantId == int.Parse(tenantid)).FirstOrDefault();
|
||||
tenant.IsInitialized = true;
|
||||
await TenantService.UpdateTenantAsync(tenant);
|
||||
}
|
||||
}
|
||||
await logger.LogInformation("Site Created {Site}", site);
|
||||
|
||||
Uri uri = new Uri(NavigationManager.Uri);
|
||||
NavigationManager.NavigateTo(uri.Scheme + "://" + aliases[0].Name, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogError("Invalid Password Entered For Host {Username}", username);
|
||||
AddModuleMessage("Invalid Host Password", MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage("You Must Provide A Tenant, Site Name, Alias, And Default Theme/Container", MessageType.Warning);
|
||||
}
|
||||
|
||||
NavigationManager.NavigateTo(url, true);
|
||||
}
|
||||
}
|
||||
|
248
Oqtane.Client/Modules/Admin/Sites/Edit.razor
Normal file
248
Oqtane.Client/Modules/Admin/Sites/Edit.razor
Normal file
@ -0,0 +1,248 @@
|
||||
@namespace Oqtane.Modules.Admin.Sites
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ISiteService SiteService
|
||||
@inject IAliasService AliasService
|
||||
@inject IThemeService ThemeService
|
||||
|
||||
@if (themes == null)
|
||||
{
|
||||
<p><em>Loading...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Name: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Aliases: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@urls" rows="3" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Logo: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@logo" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Default Theme: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @onchange="(e => ThemeChanged(e))">
|
||||
<option value=""><Select Theme></option>
|
||||
@foreach (KeyValuePair<string, string> item in themes)
|
||||
{
|
||||
if (item.Key == themetype)
|
||||
{
|
||||
<option value="@item.Key" selected>@item.Value</option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="@item.Key">@item.Value</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Default Layout: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@layouttype">
|
||||
<option value=""><Select Layout></option>
|
||||
@foreach (KeyValuePair<string, string> panelayout in panelayouts)
|
||||
{
|
||||
<option value="@panelayout.Key">@panelayout.Value</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Default Container: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@containertype">
|
||||
<option value=""><Select Container></option>
|
||||
@foreach (KeyValuePair<string, string> container in containers)
|
||||
{
|
||||
<option value="@container.Key">@container.Value</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Is Deleted? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@isdeleted">
|
||||
<option value="True">Yes</option>
|
||||
<option value="False">No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveSite">Save</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon" DeletedBy="@deletedby" DeletedOn="@deletedon"></AuditInfo>
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||
|
||||
Dictionary<string, string> themes = new Dictionary<string, string>();
|
||||
Dictionary<string, string> panelayouts = new Dictionary<string, string>();
|
||||
Dictionary<string, string> containers = new Dictionary<string, string>();
|
||||
|
||||
Alias Alias;
|
||||
int siteid;
|
||||
string name = "";
|
||||
List<Alias> aliases;
|
||||
string urls = "";
|
||||
string logo = "";
|
||||
string themetype;
|
||||
string layouttype;
|
||||
string containertype;
|
||||
|
||||
string createdby;
|
||||
DateTime createdon;
|
||||
string modifiedby;
|
||||
DateTime modifiedon;
|
||||
string deletedby;
|
||||
DateTime? deletedon;
|
||||
string isdeleted;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
themes = ThemeService.GetThemeTypes(PageState.Themes);
|
||||
containers = ThemeService.GetContainerTypes(PageState.Themes);
|
||||
Alias = PageState.Aliases.Where(item => item.AliasId == Int32.Parse(PageState.QueryString["id"])).FirstOrDefault();
|
||||
|
||||
siteid = Alias.SiteId;
|
||||
Site site = await SiteService.GetSiteAsync(siteid, Alias);
|
||||
if (site != null)
|
||||
{
|
||||
name = site.Name;
|
||||
aliases = PageState.Aliases.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList();
|
||||
foreach (Alias alias in aliases)
|
||||
{
|
||||
urls += alias.Name + "\n";
|
||||
}
|
||||
logo = site.Logo;
|
||||
themetype = site.DefaultThemeType;
|
||||
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes, themetype);
|
||||
layouttype = site.DefaultLayoutType;
|
||||
containertype = site.DefaultContainerType;
|
||||
|
||||
createdby = site.CreatedBy;
|
||||
createdon = site.CreatedOn;
|
||||
modifiedby = site.ModifiedBy;
|
||||
modifiedon = site.ModifiedOn;
|
||||
deletedby = site.DeletedBy;
|
||||
deletedon = site.DeletedOn;
|
||||
isdeleted = site.IsDeleted.ToString();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Site {SiteId} {Error}", siteid, ex.Message);
|
||||
AddModuleMessage(ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async void ThemeChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
themetype = (string)e.Value;
|
||||
if (themetype != "")
|
||||
{
|
||||
panelayouts = ThemeService.GetPaneLayoutTypes(PageState.Themes, themetype);
|
||||
}
|
||||
else
|
||||
{
|
||||
panelayouts = new Dictionary<string, string>();
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Pane Layouts For Theme {ThemeType} {Error}", themetype, ex.Message);
|
||||
AddModuleMessage("Error Loading Pane Layouts For Theme", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveSite()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (name != "" && urls != "" && !string.IsNullOrEmpty(themetype) && (panelayouts.Count == 0 || !string.IsNullOrEmpty(layouttype)) && !string.IsNullOrEmpty(containertype))
|
||||
{
|
||||
Site site = await SiteService.GetSiteAsync(siteid, Alias);
|
||||
if (site != null)
|
||||
{
|
||||
site.Name = name;
|
||||
site.Logo = (logo == null ? "" : logo);
|
||||
site.DefaultThemeType = themetype;
|
||||
site.DefaultLayoutType = (layouttype == null ? "" : layouttype);
|
||||
site.DefaultContainerType = containertype;
|
||||
site.IsDeleted = (isdeleted == null ? true : Boolean.Parse(isdeleted));
|
||||
|
||||
site = await SiteService.UpdateSiteAsync(site, Alias);
|
||||
|
||||
urls = urls.Replace("\n", ",");
|
||||
string[] names = urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
foreach (Alias alias in aliases)
|
||||
{
|
||||
if (!names.Contains(alias.Name))
|
||||
{
|
||||
await AliasService.DeleteAliasAsync(alias.AliasId);
|
||||
}
|
||||
}
|
||||
foreach (string name in names)
|
||||
{
|
||||
if (!aliases.Exists(item => item.Name == name))
|
||||
{
|
||||
Alias alias = new Alias();
|
||||
alias.Name = name;
|
||||
alias.TenantId = site.TenantId;
|
||||
alias.SiteId = site.SiteId;
|
||||
await AliasService.AddAliasAsync(alias);
|
||||
}
|
||||
}
|
||||
await logger.LogInformation("Site Saved {Site}", site);
|
||||
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Site));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage("You Must Provide A Site Name, Alias, And Default Theme/Container", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving Site {SiteId} {Error}", siteid, ex.Message);
|
||||
AddModuleMessage("Error Saving Site", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,7 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Modules.Controls
|
||||
@namespace Oqtane.Modules.Admin.Sites
|
||||
@namespace Oqtane.Modules.Admin.Sites
|
||||
@inherits ModuleBase
|
||||
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IAliasService AliasService
|
||||
@inject ISiteService SiteService
|
||||
|
||||
@if (sites == null)
|
||||
@ -14,31 +10,55 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var site in sites)
|
||||
{
|
||||
<tr>
|
||||
<td>@site.Name</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<ActionLink Action="Add" Text="Add Site" />
|
||||
|
||||
<Pager Items="@sites">
|
||||
<Header>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th>Name</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.AliasId.ToString())" /></td>
|
||||
<td><ActionDialog Header="Delete Site" Message="@("Are You Sure You Wish To Delete The " + context.Name + " Site?")" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteSite(context))" /></td>
|
||||
<td><a href="@(scheme + context.Name)">@context.Name</a></td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||
|
||||
List<Site> sites;
|
||||
List<Alias> sites;
|
||||
string scheme;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
sites = await SiteService.GetSitesAsync();
|
||||
Uri uri = new Uri(NavigationManager.Uri);
|
||||
scheme = uri.Scheme + "://";
|
||||
|
||||
sites = new List<Alias>();
|
||||
foreach (Alias alias in PageState.Aliases.OrderBy(item => item.Name))
|
||||
{
|
||||
if (!sites.Exists(item => item.TenantId == alias.TenantId && item.SiteId == alias.SiteId))
|
||||
{
|
||||
sites.Add(alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteSite(Alias Alias)
|
||||
{
|
||||
try
|
||||
{
|
||||
await SiteService.DeleteSiteAsync(Alias.SiteId, Alias);
|
||||
await logger.LogInformation("Sited Deleted {Alias}", Alias);
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Deleting Site {Error}", ex.Message);
|
||||
AddModuleMessage("Error Deleting Site", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
82
Oqtane.Client/Modules/Admin/Tenants/Add.razor
Normal file
82
Oqtane.Client/Modules/Admin/Tenants/Add.razor
Normal file
@ -0,0 +1,82 @@
|
||||
@namespace Oqtane.Modules.Admin.Tenants
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ITenantService TenantService
|
||||
@inject IInstallationService InstallationService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Name: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Connection String: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@connectionstring" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Schema: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@schema" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveTenant">Save</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||
|
||||
string name = "";
|
||||
string connectionstring = "";
|
||||
string schema = "";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
List<Tenant> tenants = await TenantService.GetTenantsAsync();
|
||||
connectionstring = tenants.FirstOrDefault().DBConnectionString;
|
||||
schema = tenants.FirstOrDefault().DBSchema;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Tenants {Error}", ex.Message);
|
||||
AddModuleMessage("Error Loading Tenants", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveTenant()
|
||||
{
|
||||
ShowProgressIndicator();
|
||||
|
||||
connectionstring = connectionstring.Replace("\\\\", "\\");
|
||||
GenericResponse response = await InstallationService.Install(connectionstring);
|
||||
if (response.Success)
|
||||
{
|
||||
Tenant tenant = new Tenant();
|
||||
tenant.Name = name;
|
||||
tenant.DBConnectionString = connectionstring;
|
||||
tenant.DBSchema = schema;
|
||||
tenant.IsInitialized = false;
|
||||
await TenantService.AddTenantAsync(tenant);
|
||||
await logger.LogInformation("Tenant Created {Tenant}", tenant);
|
||||
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogError("Error Creating Tenant {Error}", response.Message);
|
||||
AddModuleMessage(response.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
86
Oqtane.Client/Modules/Admin/Tenants/Edit.razor
Normal file
86
Oqtane.Client/Modules/Admin/Tenants/Edit.razor
Normal file
@ -0,0 +1,86 @@
|
||||
@namespace Oqtane.Modules.Admin.Tenants
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ITenantService TenantService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Name: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Connection String: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@connectionstring" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Schema: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@schema" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveTenant">Save</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||
|
||||
int tenantid;
|
||||
string name = "";
|
||||
string connectionstring = "";
|
||||
string schema = "";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
tenantid = Int32.Parse(PageState.QueryString["id"]);
|
||||
Tenant tenant = await TenantService.GetTenantAsync(tenantid);
|
||||
if (tenant != null)
|
||||
{
|
||||
name = tenant.Name;
|
||||
connectionstring = tenant.DBConnectionString;
|
||||
schema = tenant.DBSchema;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Tenant {TenantId} {Error}", tenantid, ex.Message);
|
||||
AddModuleMessage("Error Loading Tenant", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveTenant()
|
||||
{
|
||||
try
|
||||
{
|
||||
connectionstring = connectionstring.Replace("\\\\", "\\");
|
||||
Tenant tenant = await TenantService.GetTenantAsync(tenantid);
|
||||
if (tenant != null)
|
||||
{
|
||||
tenant.Name = name;
|
||||
tenant.DBConnectionString = connectionstring;
|
||||
tenant.DBSchema = schema;
|
||||
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("Error Saving Tenant", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
52
Oqtane.Client/Modules/Admin/Tenants/Index.razor
Normal file
52
Oqtane.Client/Modules/Admin/Tenants/Index.razor
Normal file
@ -0,0 +1,52 @@
|
||||
@namespace Oqtane.Modules.Admin.Tenants
|
||||
@inherits ModuleBase
|
||||
@inject ITenantService TenantService
|
||||
|
||||
@if (tenants == null)
|
||||
{
|
||||
<p><em>Loading...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ActionLink Action="Add" Text="Add Tenant" />
|
||||
|
||||
<Pager Items="@tenants">
|
||||
<Header>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th>Name</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.TenantId.ToString())" /></td>
|
||||
<td><ActionDialog Header="Delete Tenant" Message="@("Are You Sure You Wish To Delete The " + context.Name + " Tenant?")" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteTenant(context))" /></td>
|
||||
<td>@context.Name</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||
|
||||
List<Tenant> tenants;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
tenants = await TenantService.GetTenantsAsync();
|
||||
}
|
||||
|
||||
private async Task DeleteTenant(Tenant Tenant)
|
||||
{
|
||||
try
|
||||
{
|
||||
await TenantService.DeleteTenantAsync(Tenant.TenantId);
|
||||
await logger.LogInformation("Tenant Deleted {Tenant}", Tenant);
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Deleting Tenant {Tenant} {Error}", Tenant, ex.Message);
|
||||
AddModuleMessage("Error Deleting Tenant", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
121
Oqtane.Client/Modules/Admin/Themes/Add.razor
Normal file
121
Oqtane.Client/Modules/Admin/Themes/Add.razor
Normal file
@ -0,0 +1,121 @@
|
||||
@namespace Oqtane.Modules.Admin.Themes
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IFileService FileService
|
||||
@inject IThemeService ThemeService
|
||||
@inject IPackageService PackageService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Theme: </label>
|
||||
</td>
|
||||
<td>
|
||||
<FileUpload Filter=".nupkg" @ref="fileupload"></FileUpload>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-primary" @onclick="UploadTheme">Upload Theme</button>
|
||||
|
||||
@if (packages != null)
|
||||
{
|
||||
<hr class="app-rule" />
|
||||
<div class="mx-auto text-center"><h2>Available Themes</h2></div>
|
||||
|
||||
<Pager Items="@packages">
|
||||
<Header>
|
||||
<th>Name</th>
|
||||
<th>Version</th>
|
||||
<th></th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td>@context.Name</td>
|
||||
<td>@context.Version</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-primary" @onclick=@(async () => await DownloadTheme(context.PackageId, context.Version))>Download Theme</button>
|
||||
</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
|
||||
@if (uploaded)
|
||||
{
|
||||
<button type="button" class="btn btn-success" @onclick="InstallThemes">Install</button>
|
||||
}
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||
|
||||
bool uploaded = false;
|
||||
List<Package> packages;
|
||||
FileUpload fileupload;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
List<Theme> themes = await ThemeService.GetThemesAsync();
|
||||
packages = await PackageService.GetPackagesAsync("theme");
|
||||
foreach(Package package in packages.ToArray())
|
||||
{
|
||||
if (themes.Exists(item => Utilities.GetTypeName(item.ThemeName) == package.PackageId))
|
||||
{
|
||||
packages.Remove(package);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UploadTheme()
|
||||
{
|
||||
string[] files = await fileupload.GetFiles();
|
||||
if (files.Length > 0)
|
||||
{
|
||||
if (files[0].Contains(".Theme."))
|
||||
{
|
||||
try
|
||||
{
|
||||
string result = await FileService.UploadFilesAsync("Themes", files, "");
|
||||
if (result == "")
|
||||
{
|
||||
await logger.LogInformation("Theme Uploaded {Package}", files[0]);
|
||||
AddModuleMessage("Theme Uploaded Successfully. Click Install To Complete Installation.", MessageType.Success);
|
||||
uploaded = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogInformation("Theme Upload Failed For {Package}", result.Replace(",",", "));
|
||||
AddModuleMessage("Upload Failed For " + result.Replace(",",", ") + ". This Could Be Due To A Network Error Or Because A File Type Is Restricted.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Theme Upload Failed {Package} {Error}", files[0], ex.Message);
|
||||
AddModuleMessage("Theme Upload Failed", MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogError("Invalid Theme Package {Package}", files[0]);
|
||||
AddModuleMessage("Invalid Theme Package", MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage("You Must Select A Theme To Upload", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task InstallThemes()
|
||||
{
|
||||
await ThemeService.InstallThemesAsync();
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
|
||||
}
|
||||
|
||||
private async Task DownloadTheme(string packageid, string version)
|
||||
{
|
||||
await PackageService.DownloadPackageAsync(packageid, version, "Themes");
|
||||
AddModuleMessage("Theme Downloaded Successfully. Click Install To Complete Installation.", MessageType.Success);
|
||||
uploaded = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
@ -1,42 +1,78 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Modules
|
||||
@namespace Oqtane.Modules.Admin.Themes
|
||||
@namespace Oqtane.Modules.Admin.Themes
|
||||
@inherits ModuleBase
|
||||
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IThemeService ThemeService
|
||||
@inject IPackageService PackageService
|
||||
|
||||
@if (Themes == null)
|
||||
@if (themes == null)
|
||||
{
|
||||
<p><em>Loading...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var theme in Themes)
|
||||
{
|
||||
<tr>
|
||||
<td>@theme.Name</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<ActionLink Action="Add" Text="Install Theme" />
|
||||
|
||||
<Pager Items="@themes">
|
||||
<Header>
|
||||
<th> </th>
|
||||
<th>Name</th>
|
||||
<th>Version</th>
|
||||
<th> </th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td>
|
||||
@if (context.AssemblyName != "Oqtane.Client")
|
||||
{
|
||||
<ActionDialog Header="Delete Theme" Message="@("Are You Sure You Wish To Delete The " + context.Name + " Theme?")" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteTheme(context))" />
|
||||
}
|
||||
</td>
|
||||
<td>@context.Name</td>
|
||||
<td>@context.Version</td>
|
||||
<td>
|
||||
@if (UpgradeAvailable(context.ThemeName, context.Version))
|
||||
{
|
||||
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadTheme(context.ThemeName, context.Version))>Upgrade</button>
|
||||
}
|
||||
</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||
|
||||
List<Theme> Themes;
|
||||
List<Theme> themes;
|
||||
List<Package> packages;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
Themes = await ThemeService.GetThemesAsync();
|
||||
themes = await ThemeService.GetThemesAsync();
|
||||
packages = await PackageService.GetPackagesAsync("module");
|
||||
}
|
||||
|
||||
private bool UpgradeAvailable(string themename, string version)
|
||||
{
|
||||
bool upgradeavailable = false;
|
||||
Package package = packages.Where(item => item.PackageId == Utilities.GetTypeName(themename)).FirstOrDefault();
|
||||
if (package != null)
|
||||
{
|
||||
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0);
|
||||
}
|
||||
return upgradeavailable;
|
||||
}
|
||||
|
||||
private async Task DownloadTheme(string themename, string version)
|
||||
{
|
||||
await PackageService.DownloadPackageAsync(themename, version, "Themes");
|
||||
await logger.LogInformation("Theme Downloaded {ThemeName} {Version}", themename, version);
|
||||
await ThemeService.InstallThemesAsync();
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
|
||||
}
|
||||
|
||||
private async Task DeleteTheme(Theme Theme)
|
||||
{
|
||||
await ThemeService.DeleteThemeAsync(Theme.ThemeName);
|
||||
await logger.LogInformation("Theme Deleted {Theme}", Theme);
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
|
||||
}
|
||||
}
|
109
Oqtane.Client/Modules/Admin/Upgrade/Index.razor
Normal file
109
Oqtane.Client/Modules/Admin/Upgrade/Index.razor
Normal file
@ -0,0 +1,109 @@
|
||||
@namespace Oqtane.Modules.Admin.Upgrade
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IFileService FileService
|
||||
@inject IPackageService PackageService
|
||||
@inject IInstallationService InstallationService
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Framework: </label>
|
||||
</td>
|
||||
<td>
|
||||
<FileUpload Filter=".nupkg" @ref="fileupload"></FileUpload>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@if (uploaded)
|
||||
{
|
||||
<button type="button" class="btn btn-success" @onclick="Upgrade">Upgrade</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn btn-primary" @onclick="UploadFile">Upload</button>
|
||||
}
|
||||
|
||||
@if (upgradeavailable)
|
||||
{
|
||||
<hr class="app-rule" />
|
||||
<div class="mx-auto text-center"><h2>Upgrade Available</h2></div>
|
||||
|
||||
<button type="button" class="btn btn-success" @onclick=@(async () => await Download(Constants.PackageId, Constants.Version))>Upgrade Framework</button>
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Host; } }
|
||||
|
||||
bool uploaded = false;
|
||||
bool upgradeavailable = false;
|
||||
FileUpload fileupload;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
List<Package> packages = await PackageService.GetPackagesAsync("framework");
|
||||
Package package = packages.FirstOrDefault();
|
||||
if (package != null)
|
||||
{
|
||||
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(Constants.Version)) > 0);
|
||||
}
|
||||
if (!upgradeavailable)
|
||||
{
|
||||
AddModuleMessage("Framework Is Up To Date", MessageType.Info);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UploadFile()
|
||||
{
|
||||
string[] files = await fileupload.GetFiles();
|
||||
if (files.Length > 0)
|
||||
{
|
||||
if (files[0].Contains(".Framework."))
|
||||
{
|
||||
try
|
||||
{
|
||||
string result = await FileService.UploadFilesAsync("Framework", files, "");
|
||||
if (result == "")
|
||||
{
|
||||
await logger.LogInformation("Framework Uploaded {Package}", files[0]);
|
||||
AddModuleMessage("Framework Uploaded Successfully. Click Upgrade To Complete Installation.", MessageType.Success);
|
||||
uploaded = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogInformation("Framework Upload Failed For {Package}", result.Replace(",",", "));
|
||||
AddModuleMessage("Upload Failed For " + result.Replace(",",", ") + ". This Could Be Due To A Network Error Or Because A File Type Is Restricted.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Framework Upload Failed {Package} {Error}", files[0], ex.Message);
|
||||
AddModuleMessage("Framework Upload Failed. " + ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogError("Invalid Framework Package {Package}", files[0]);
|
||||
AddModuleMessage("Invalid Framework Package", MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage("You Must Select A Framework Package To Upload", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Upgrade()
|
||||
{
|
||||
await InstallationService.Upgrade();
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
|
||||
}
|
||||
|
||||
private async Task Download(string packageid, string version)
|
||||
{
|
||||
await PackageService.DownloadPackageAsync(packageid, version, "Framework");
|
||||
await InstallationService.Upgrade();
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Application));
|
||||
}
|
||||
}
|
@ -1,27 +1,27 @@
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Modules.Controls
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Services
|
||||
@namespace Oqtane.Modules.Admin.Profile
|
||||
@namespace Oqtane.Modules.Admin.UserProfile
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IUserService UserService
|
||||
@inject IProfileService ProfileService
|
||||
@inject ISettingService SettingService
|
||||
|
||||
<ModuleMessage Message="@message" />
|
||||
|
||||
@if (PageState.User != null && profiles != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Name: </label>
|
||||
<label for="Name" class="control-label">Username: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@displayname" />
|
||||
<input class="form-control" @bind="@username" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Password: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="password" class="form-control" @bind="@password" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -32,6 +32,14 @@
|
||||
<input class="form-control" @bind="@email" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Full Name: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@displayname" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@foreach (Profile profile in profiles)
|
||||
{
|
||||
@ -64,9 +72,10 @@
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.View; } }
|
||||
|
||||
string message = "";
|
||||
string displayname = "";
|
||||
string username = "";
|
||||
string password = "";
|
||||
string email = "";
|
||||
string displayname = "";
|
||||
List<Profile> profiles;
|
||||
Dictionary<string, string> settings;
|
||||
string category = "";
|
||||
@ -77,19 +86,21 @@
|
||||
{
|
||||
if (PageState.User != null)
|
||||
{
|
||||
displayname = PageState.User.DisplayName;
|
||||
username = PageState.User.Username;
|
||||
email = PageState.User.Email;
|
||||
displayname = PageState.User.DisplayName;
|
||||
profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
|
||||
settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
||||
}
|
||||
else
|
||||
{
|
||||
message = "Current User Is Not Logged In";
|
||||
AddModuleMessage("Current User Is Not Logged In", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
message = ex.Message;
|
||||
await logger.LogError(ex, "Error Loading User Profile {Error}", ex.Message);
|
||||
AddModuleMessage("Error Loading User Profile", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,16 +114,20 @@
|
||||
try
|
||||
{
|
||||
User user = PageState.User;
|
||||
user.DisplayName = displayname;
|
||||
user.Username = username;
|
||||
user.Password = password;
|
||||
user.Email = email;
|
||||
user.DisplayName = displayname;
|
||||
await UserService.UpdateUserAsync(user);
|
||||
await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
|
||||
await logger.LogInformation("User Profile Saved");
|
||||
|
||||
NavigationManager.NavigateTo("");
|
||||
NavigationManager.NavigateTo(NavigateUrl(""));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
message = ex.Message;
|
||||
await logger.LogError(ex, "Error Saving User Profile {Error}", ex.Message);
|
||||
AddModuleMessage("Error Saving User Profile", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
133
Oqtane.Client/Modules/Admin/Users/Add.razor
Normal file
133
Oqtane.Client/Modules/Admin/Users/Add.razor
Normal file
@ -0,0 +1,133 @@
|
||||
@namespace Oqtane.Modules.Admin.Users
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IUserService UserService
|
||||
@inject IProfileService ProfileService
|
||||
@inject ISettingService SettingService
|
||||
|
||||
@if (profiles != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Username: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@username" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Password: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="password" class="form-control" @bind="@password" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Email: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@email" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Full Name: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@displayname" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@foreach (Profile profile in profiles)
|
||||
{
|
||||
var p = profile;
|
||||
if (p.Category != category)
|
||||
{
|
||||
<tr>
|
||||
<th colspan="2" style="text-align: center;">
|
||||
@p.Category
|
||||
</th>
|
||||
</tr>
|
||||
category = p.Category;
|
||||
}
|
||||
<tr>
|
||||
<td>
|
||||
<label for="@p.Name" class="control-label">@p.Title: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" maxlength="@p.MaxLength" placeholder="@p.Description" @onchange="(e => ProfileChanged(e, p.Name))" />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
<button type="button" class="btn btn-primary" @onclick="SaveUser">Save</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
string username = "";
|
||||
string password = "";
|
||||
string email = "";
|
||||
string displayname = "";
|
||||
List<Profile> profiles;
|
||||
Dictionary<string, string> settings;
|
||||
string category = "";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
|
||||
settings = new Dictionary<string, string>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading User Profile {Error}", ex.Message);
|
||||
AddModuleMessage("Error Loading User Profile", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveUser()
|
||||
{
|
||||
try
|
||||
{
|
||||
User user = new User();
|
||||
user.SiteId = PageState.Site.SiteId;
|
||||
user.Username = username;
|
||||
user.Password = password;
|
||||
user.Email = email;
|
||||
user.DisplayName = string.IsNullOrWhiteSpace(user.DisplayName) ? user.Username : user.DisplayName;
|
||||
|
||||
user = await UserService.AddUserAsync(user);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
await SettingService.UpdateUserSettingsAsync(settings, user.UserId);
|
||||
await logger.LogInformation("User Created {User}", user);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogError("Error Adding User {Username} {Email}", username, email);
|
||||
AddModuleMessage("Error Adding User. Please Ensure Password Meets Complexity Requirements And Username Is Not Already In Use.", MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Adding User {Username} {Email} {Error}", username, email, ex.Message);
|
||||
AddModuleMessage("Error Adding User", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProfileChanged(ChangeEventArgs e, string SettingName)
|
||||
{
|
||||
string value = (string)e.Value;
|
||||
settings = SettingService.SetSetting(settings, SettingName, value);
|
||||
}
|
||||
|
||||
}
|
169
Oqtane.Client/Modules/Admin/Users/Edit.razor
Normal file
169
Oqtane.Client/Modules/Admin/Users/Edit.razor
Normal file
@ -0,0 +1,169 @@
|
||||
@namespace Oqtane.Modules.Admin.Users
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IUserService UserService
|
||||
@inject IProfileService ProfileService
|
||||
@inject ISettingService SettingService
|
||||
|
||||
@if (profiles != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Username: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@username" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Password: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="password" class="form-control" @bind="@password" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Email: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@email" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Full Name: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@displayname" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@foreach (Profile profile in profiles)
|
||||
{
|
||||
var p = profile;
|
||||
if (p.Category != category)
|
||||
{
|
||||
<tr>
|
||||
<th colspan="2" style="text-align: center;">
|
||||
@p.Category
|
||||
</th>
|
||||
</tr>
|
||||
category = p.Category;
|
||||
}
|
||||
<tr>
|
||||
<td>
|
||||
<label for="@p.Name" class="control-label">@p.Title: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" placeholder="@p.Description" @onchange="(e => ProfileChanged(e, p.Name))" />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Is Deleted? </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@isdeleted">
|
||||
<option value="True">Yes</option>
|
||||
<option value="False">No</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-primary" @onclick="SaveUser">Save</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon" DeletedBy="@deletedby" DeletedOn="@deletedon"></AuditInfo>
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
int userid;
|
||||
string username = "";
|
||||
string password = "";
|
||||
string email = "";
|
||||
string displayname = "";
|
||||
List<Profile> profiles;
|
||||
Dictionary<string, string> settings;
|
||||
string category = "";
|
||||
string createdby;
|
||||
DateTime createdon;
|
||||
string modifiedby;
|
||||
DateTime modifiedon;
|
||||
string deletedby;
|
||||
DateTime? deletedon;
|
||||
string isdeleted;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
profiles = await ProfileService.GetProfilesAsync(PageState.Site.SiteId);
|
||||
|
||||
userid = Int32.Parse(PageState.QueryString["id"]);
|
||||
User user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
||||
if (user != null)
|
||||
{
|
||||
username = user.Username;
|
||||
email = user.Email;
|
||||
displayname = user.DisplayName;
|
||||
settings = await SettingService.GetUserSettingsAsync(user.UserId);
|
||||
createdby = user.CreatedBy;
|
||||
createdon = user.CreatedOn;
|
||||
modifiedby = user.ModifiedBy;
|
||||
modifiedon = user.ModifiedOn;
|
||||
deletedby = user.DeletedBy;
|
||||
deletedon = user.DeletedOn;
|
||||
isdeleted = user.IsDeleted.ToString();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading User {UserId} {Error}", userid, ex.Message);
|
||||
AddModuleMessage("Error Loading User", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetProfileValue(string SettingName, string DefaultValue)
|
||||
{
|
||||
return SettingService.GetSetting(settings, SettingName, DefaultValue);
|
||||
}
|
||||
|
||||
private async Task SaveUser()
|
||||
{
|
||||
try
|
||||
{
|
||||
User user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
||||
user.SiteId = PageState.Site.SiteId;
|
||||
user.Username = username;
|
||||
user.Password = password;
|
||||
user.Email = email;
|
||||
user.DisplayName = string.IsNullOrWhiteSpace(user.DisplayName) ? user.Username : user.DisplayName;
|
||||
user.IsDeleted = (isdeleted == null ? true : Boolean.Parse(isdeleted));
|
||||
|
||||
user = await UserService.UpdateUserAsync(user);
|
||||
await SettingService.UpdateUserSettingsAsync(settings, user.UserId);
|
||||
await logger.LogInformation("User Saved {User}", user);
|
||||
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving User {Username} {Email} {Error}", username, email, ex.Message);
|
||||
AddModuleMessage("Error Saving User", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProfileChanged(ChangeEventArgs e, string SettingName)
|
||||
{
|
||||
string value = (string)e.Value;
|
||||
settings = SettingService.SetSetting(settings, SettingName, value);
|
||||
}
|
||||
|
||||
}
|
@ -1,43 +1,59 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Modules.Controls
|
||||
@namespace Oqtane.Modules.Admin.Users
|
||||
@namespace Oqtane.Modules.Admin.Users
|
||||
@inherits ModuleBase
|
||||
|
||||
@inject IUserRoleService UserRoleService
|
||||
@inject IUserService UserService
|
||||
|
||||
@if (Users == null)
|
||||
@if (userroles == null)
|
||||
{
|
||||
<p><em>Loading...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var User in Users)
|
||||
{
|
||||
<tr>
|
||||
<td>@User.Username</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<ActionLink Action="Add" Text="Add User" />
|
||||
|
||||
<Pager Items="@userroles">
|
||||
<Header>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
<th>Name</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.UserId.ToString())" /></td>
|
||||
<td><ActionDialog Header="Delete User" Message="@("Are You Sure You Wish To Delete " + context.User.DisplayName + "?")" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteUser(context))" /></td>
|
||||
<td><ActionLink Action="Roles" Parameters="@($"id=" + context.UserId.ToString())" /></td>
|
||||
<td>@context.User.DisplayName</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
List<User> Users;
|
||||
List<UserRole> userroles;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
Users = await UserService.GetUsersAsync(PageState.Site.SiteId);
|
||||
userroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId);
|
||||
userroles = userroles.Where(item => item.Role.Name == Constants.RegisteredRole).ToList();
|
||||
}
|
||||
|
||||
private async Task DeleteUser(UserRole UserRole)
|
||||
{
|
||||
try
|
||||
{
|
||||
User user = await UserService.GetUserAsync(UserRole.UserId, PageState.Site.SiteId);
|
||||
if (user != null)
|
||||
{
|
||||
await UserService.DeleteUserAsync(user.UserId);
|
||||
await logger.LogInformation("User Deleted {User}", UserRole.User);
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Deleting User {User} {Error}", UserRole.User, ex.Message);
|
||||
AddModuleMessage(ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
187
Oqtane.Client/Modules/Admin/Users/Roles.razor
Normal file
187
Oqtane.Client/Modules/Admin/Users/Roles.razor
Normal file
@ -0,0 +1,187 @@
|
||||
@namespace Oqtane.Modules.Admin.Users
|
||||
@inherits ModuleBase
|
||||
@inject IRoleService RoleService
|
||||
@inject IUserRoleService UserRoleService
|
||||
|
||||
@if (userroles == null)
|
||||
{
|
||||
<p><em>Loading...</em></p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Role: </label>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" @bind="@roleid">
|
||||
<option value="-1"><Select Role></option>
|
||||
@foreach (Role role in roles)
|
||||
{
|
||||
<option value="@(role.RoleId)">@role.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Effective Date: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@effectivedate" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Expiry Date: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input class="form-control" @bind="@expirydate" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveUserRole">Save</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||
|
||||
<hr class="app-rule" />
|
||||
<p align="center">
|
||||
<Pager Items="@userroles">
|
||||
<Header>
|
||||
<th>Role</th>
|
||||
<th> </th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td>@context.Role.Name</td>
|
||||
<td>
|
||||
@if (!context.Role.IsSystem)
|
||||
{
|
||||
<button type="button" class="btn btn-danger" @onclick=@(async () => await DeleteUserRole(context.UserRoleId))>Delete</button>
|
||||
}
|
||||
</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
</p>
|
||||
}
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Admin; } }
|
||||
|
||||
int userid;
|
||||
List<Role> roles;
|
||||
int roleid = -1;
|
||||
string effectivedate = "";
|
||||
string expirydate = "";
|
||||
List<UserRole> userroles;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
userid = Int32.Parse(PageState.QueryString["id"]);
|
||||
roles = await RoleService.GetRolesAsync(PageState.Site.SiteId);
|
||||
await GetUserRoles();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Roles {Error}", ex.Message);
|
||||
AddModuleMessage("Error Loading Roles", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task GetUserRoles()
|
||||
{
|
||||
try
|
||||
{
|
||||
userroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId);
|
||||
userroles = userroles.Where(item => item.UserId == userid).ToList();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading User Roles {UserId} {Error}", userid, ex.Message);
|
||||
AddModuleMessage("Error Loading User Roles", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveUserRole()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (roleid != -1)
|
||||
{
|
||||
UserRole userrole = userroles.Where(item => item.UserId == userid && item.RoleId == roleid).FirstOrDefault();
|
||||
if (userrole != null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(effectivedate))
|
||||
{
|
||||
userrole.EffectiveDate = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
userrole.EffectiveDate = DateTime.Parse(effectivedate);
|
||||
}
|
||||
if (string.IsNullOrEmpty(expirydate))
|
||||
{
|
||||
userrole.ExpiryDate = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
userrole.ExpiryDate = DateTime.Parse(expirydate);
|
||||
}
|
||||
await UserRoleService.UpdateUserRoleAsync(userrole);
|
||||
}
|
||||
else
|
||||
{
|
||||
userrole = new UserRole();
|
||||
userrole.UserId = userid;
|
||||
userrole.RoleId = roleid;
|
||||
if (string.IsNullOrEmpty(effectivedate))
|
||||
{
|
||||
userrole.EffectiveDate = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
userrole.EffectiveDate = DateTime.Parse(effectivedate);
|
||||
}
|
||||
if (string.IsNullOrEmpty(expirydate))
|
||||
{
|
||||
userrole.ExpiryDate = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
userrole.ExpiryDate = DateTime.Parse(expirydate);
|
||||
}
|
||||
await UserRoleService.AddUserRoleAsync(userrole);
|
||||
}
|
||||
await GetUserRoles();
|
||||
await logger.LogInformation("User Assigned To Role {UserRole}", userrole);
|
||||
AddModuleMessage("User Assigned To Role", MessageType.Success);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage("You Must Select A Role", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving User Roles {UserId} {Error}", userid, ex.Message);
|
||||
AddModuleMessage("Error Saving User Roles", MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteUserRole(int UserRoleId)
|
||||
{
|
||||
try
|
||||
{
|
||||
await UserRoleService.DeleteUserRoleAsync(UserRoleId);
|
||||
await GetUserRoles();
|
||||
await logger.LogInformation("User Removed From Role {UserRoleId}", UserRoleId);
|
||||
AddModuleMessage("User Removed From Role", MessageType.Success);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Removing User From Role {UserRoleId} {Error}", UserRoleId, ex.Message);
|
||||
AddModuleMessage("Error Removing User From Role", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
130
Oqtane.Client/Modules/Controls/ActionDialog.razor
Normal file
130
Oqtane.Client/Modules/Controls/ActionDialog.razor
Normal file
@ -0,0 +1,130 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
|
||||
@if (visible)
|
||||
{
|
||||
<div class="app-admin-modal">
|
||||
<div class="modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@Header</h5>
|
||||
<button type="button" class="close" @onclick="DisplayModal" aria-label="Close">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>@Message</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="@Class" @onclick="Confirm">@Action</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="DisplayModal">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (authorized)
|
||||
{
|
||||
<button class="@Class" @onclick="DisplayModal">@Text</button>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string Header { get; set; } // required
|
||||
|
||||
[Parameter]
|
||||
public string Message { get; set; } // required
|
||||
|
||||
[Parameter]
|
||||
public string Action { get; set; } // defaults to Ok if not specified
|
||||
|
||||
[Parameter]
|
||||
public SecurityAccessLevel? Security { get; set; } // optional - can be used to explicitly specify SecurityAccessLevel
|
||||
|
||||
[Parameter]
|
||||
public string Text { get; set; } // optional - defaults to Action if not specified
|
||||
|
||||
[Parameter]
|
||||
public string Class { get; set; } // optional
|
||||
|
||||
[Parameter]
|
||||
public Action OnClick { get; set; } // required - executes a method in the calling component
|
||||
|
||||
bool visible = false;
|
||||
bool authorized = false;
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
if (string.IsNullOrEmpty(Action))
|
||||
{
|
||||
Action = "Ok";
|
||||
}
|
||||
if (string.IsNullOrEmpty(Text))
|
||||
{
|
||||
Text = Action;
|
||||
}
|
||||
if (string.IsNullOrEmpty(Class))
|
||||
{
|
||||
Class = "btn btn-success";
|
||||
}
|
||||
authorized = IsAuthorized();
|
||||
}
|
||||
|
||||
private bool IsAuthorized()
|
||||
{
|
||||
bool authorized = false;
|
||||
if (PageState.EditMode)
|
||||
{
|
||||
SecurityAccessLevel security = SecurityAccessLevel.Host;
|
||||
if (Security == null)
|
||||
{
|
||||
string typename = ModuleState.ModuleType.Replace(Utilities.GetTypeNameLastSegment(ModuleState.ModuleType, 0) + ",", Action + ",");
|
||||
Type moduleType = Type.GetType(typename);
|
||||
if (moduleType != null)
|
||||
{
|
||||
var moduleobject = Activator.CreateInstance(moduleType);
|
||||
security = (SecurityAccessLevel)moduleType.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
security = SecurityAccessLevel.Anonymous; // occurs when an action does not have a corresponding module control
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
security = Security.Value;
|
||||
}
|
||||
switch (security)
|
||||
{
|
||||
case SecurityAccessLevel.Anonymous:
|
||||
authorized = true;
|
||||
break;
|
||||
case SecurityAccessLevel.View:
|
||||
authorized = UserSecurity.IsAuthorized(PageState.User, "View", ModuleState.Permissions);
|
||||
break;
|
||||
case SecurityAccessLevel.Edit:
|
||||
authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", ModuleState.Permissions);
|
||||
break;
|
||||
case SecurityAccessLevel.Admin:
|
||||
authorized = UserSecurity.IsAuthorized(PageState.User, Constants.AdminRole);
|
||||
break;
|
||||
case SecurityAccessLevel.Host:
|
||||
authorized = UserSecurity.IsAuthorized(PageState.User, Constants.HostRole);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return authorized;
|
||||
}
|
||||
|
||||
private void DisplayModal()
|
||||
{
|
||||
visible = !visible;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void Confirm()
|
||||
{
|
||||
DisplayModal();
|
||||
OnClick();
|
||||
}
|
||||
}
|
@ -1,10 +1,4 @@
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Shared
|
||||
@using Oqtane.Security
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
@inject IUserService UserService
|
||||
|
||||
@ -15,16 +9,19 @@
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string Action { get; set; }
|
||||
public string Action { get; set; } // required
|
||||
|
||||
[Parameter]
|
||||
public string Text { get; set; } // optional
|
||||
public SecurityAccessLevel? Security { get; set; } // optional - can be used to explicitly specify SecurityAccessLevel
|
||||
|
||||
[Parameter]
|
||||
public string Parameters { get; set; } // optional
|
||||
public string Text { get; set; } // optional - defaults to Action if not specified
|
||||
|
||||
[Parameter]
|
||||
public string Class { get; set; } // optional
|
||||
public string Parameters { get; set; } // optional - querystring parameter should be in the form of "id=x&name=y"
|
||||
|
||||
[Parameter]
|
||||
public string Class { get; set; } // optional - defaults to primary if not specified
|
||||
|
||||
[Parameter]
|
||||
public string Style { get; set; } // optional
|
||||
@ -39,12 +36,12 @@
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
text = Action;
|
||||
if (!String.IsNullOrEmpty(Text))
|
||||
if (!string.IsNullOrEmpty(Text))
|
||||
{
|
||||
text = Text;
|
||||
}
|
||||
|
||||
if (!String.IsNullOrEmpty(Parameters))
|
||||
if (!string.IsNullOrEmpty(Parameters))
|
||||
{
|
||||
parameters = Parameters;
|
||||
}
|
||||
@ -60,34 +57,53 @@
|
||||
}
|
||||
|
||||
url = EditUrl(Action, parameters);
|
||||
authorized = IsAuthorized();
|
||||
}
|
||||
|
||||
private bool IsAuthorized()
|
||||
{
|
||||
bool authorized = false;
|
||||
if (PageState.EditMode)
|
||||
{
|
||||
string typename = ModuleState.ModuleType.Replace(Utilities.GetTypeNameClass(ModuleState.ModuleType) + ",", Action + ",");
|
||||
Type moduleType = Type.GetType(typename);
|
||||
if (moduleType != null)
|
||||
SecurityAccessLevel security = SecurityAccessLevel.Host;
|
||||
if (Security == null)
|
||||
{
|
||||
var moduleobject = Activator.CreateInstance(moduleType);
|
||||
SecurityAccessLevel SecurityAccessLevel = (SecurityAccessLevel)moduleType.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null);
|
||||
switch (SecurityAccessLevel)
|
||||
string typename = ModuleState.ModuleType.Replace(Utilities.GetTypeNameLastSegment(ModuleState.ModuleType, 0) + ",", Action + ",");
|
||||
Type moduleType = Type.GetType(typename);
|
||||
if (moduleType != null)
|
||||
{
|
||||
case SecurityAccessLevel.Anonymous:
|
||||
authorized = true;
|
||||
break;
|
||||
case SecurityAccessLevel.View:
|
||||
authorized = UserSecurity.IsAuthorized(PageState.User, "View", ModuleState.Permissions);
|
||||
break;
|
||||
case SecurityAccessLevel.Edit:
|
||||
authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", ModuleState.Permissions);
|
||||
break;
|
||||
case SecurityAccessLevel.Admin:
|
||||
authorized = UserSecurity.IsAuthorized(PageState.User, Constants.AdminRole);
|
||||
break;
|
||||
case SecurityAccessLevel.Host:
|
||||
authorized = UserSecurity.IsAuthorized(PageState.User, Constants.HostRole);
|
||||
break;
|
||||
var moduleobject = Activator.CreateInstance(moduleType);
|
||||
security = (SecurityAccessLevel)moduleType.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
security = SecurityAccessLevel.Anonymous; // occurs when an action does not have a corresponding module control
|
||||
Class = "btn btn-warning"; // alert developer of missing module comtrol
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
security = Security.Value;
|
||||
}
|
||||
switch (security)
|
||||
{
|
||||
case SecurityAccessLevel.Anonymous:
|
||||
authorized = true;
|
||||
break;
|
||||
case SecurityAccessLevel.View:
|
||||
authorized = UserSecurity.IsAuthorized(PageState.User, "View", ModuleState.Permissions);
|
||||
break;
|
||||
case SecurityAccessLevel.Edit:
|
||||
authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", ModuleState.Permissions);
|
||||
break;
|
||||
case SecurityAccessLevel.Admin:
|
||||
authorized = UserSecurity.IsAuthorized(PageState.User, Constants.AdminRole);
|
||||
break;
|
||||
case SecurityAccessLevel.Host:
|
||||
authorized = UserSecurity.IsAuthorized(PageState.User, Constants.HostRole);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return authorized;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
@using Oqtane.Modules
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
|
||||
@if (text != "")
|
||||
@ -20,6 +18,15 @@
|
||||
|
||||
[Parameter]
|
||||
public DateTime ModifiedOn { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string DeletedBy { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public DateTime? DeletedOn { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool IsDeleted { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Style { get; set; }
|
||||
@ -56,5 +63,19 @@
|
||||
}
|
||||
text += "</p>";
|
||||
}
|
||||
|
||||
if (!String.IsNullOrEmpty(DeletedBy) || DeletedOn.HasValue)
|
||||
{
|
||||
text += "<p style=\"" + Style + "\">Deleted ";
|
||||
if (!String.IsNullOrEmpty(DeletedBy))
|
||||
{
|
||||
text += " by <b>" + DeletedBy + "</b>";
|
||||
}
|
||||
if (DeletedOn != null)
|
||||
{
|
||||
text += " on <b>" + DeletedOn.Value.ToString("MMM dd yyyy HH:mm:ss") + "</b>";
|
||||
}
|
||||
text += "</p>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inject IJSRuntime jsRuntime
|
||||
|
||||
@if (multiple)
|
||||
{
|
||||
<input type="file" id="@fileid" name="file" accept="@filter" multiple />
|
||||
<input type="file" id="@fileid" name="file" accept="@filter" value="@files" multiple />
|
||||
}
|
||||
else
|
||||
{
|
||||
<input type="file" id="@fileid" name="file" accept="@filter" />
|
||||
<input type="file" id="@fileid" name="file" accept="@filter" value="@files" />
|
||||
}
|
||||
<span id="@progressinfoid"></span> <progress id="@progressbarid" style="visibility: hidden;"></progress>
|
||||
|
||||
@ -25,6 +25,7 @@ else
|
||||
string progressinfoid = "";
|
||||
string progressbarid = "";
|
||||
string filter = "*";
|
||||
string files = "";
|
||||
bool multiple = false;
|
||||
|
||||
protected override void OnInitialized()
|
||||
@ -43,4 +44,11 @@ else
|
||||
multiple = bool.Parse(Multiple);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string[]> GetFiles()
|
||||
{
|
||||
var interop = new Interop(jsRuntime);
|
||||
string[] files = await interop.GetFiles(fileid);
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,9 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Modules
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
|
||||
@if (Message != "")
|
||||
@if (!string.IsNullOrEmpty(message))
|
||||
{
|
||||
<div class="@type">@Message</div>
|
||||
<br />
|
||||
<div class="@classname" role="alert">@message</div>
|
||||
<br />
|
||||
}
|
||||
|
||||
@ -17,24 +14,40 @@
|
||||
[Parameter]
|
||||
public MessageType Type { get; set; }
|
||||
|
||||
string type = "alert alert-danger";
|
||||
string message = "";
|
||||
string classname = "alert alert-danger";
|
||||
|
||||
protected override void OnInitialized()
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
switch (Type)
|
||||
message = Message;
|
||||
classname = GetMessageType(Type);
|
||||
}
|
||||
|
||||
public void SetModuleMessage(string message, MessageType type)
|
||||
{
|
||||
this.message = message;
|
||||
classname = GetMessageType(type);
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private string GetMessageType(MessageType type)
|
||||
{
|
||||
string classname = "";
|
||||
switch (type)
|
||||
{
|
||||
case MessageType.Success:
|
||||
type = "alert alert-success";
|
||||
classname = "alert alert-success";
|
||||
break;
|
||||
case MessageType.Info:
|
||||
type = "alert alert-info";
|
||||
classname = "alert alert-info";
|
||||
break;
|
||||
case MessageType.Warning:
|
||||
type = "alert alert-warning";
|
||||
classname = "alert alert-warning";
|
||||
break;
|
||||
case MessageType.Error:
|
||||
type = "alert alert-danger";
|
||||
classname = "alert alert-danger";
|
||||
break;
|
||||
}
|
||||
return classname;
|
||||
}
|
||||
}
|
||||
|
195
Oqtane.Client/Modules/Controls/Pager.razor
Normal file
195
Oqtane.Client/Modules/Controls/Pager.razor
Normal file
@ -0,0 +1,195 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
@typeparam TableItem
|
||||
|
||||
<p>
|
||||
@if(Format == "Table")
|
||||
{
|
||||
<table class="@Class">
|
||||
<thead>
|
||||
<tr>@Header</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in ItemList)
|
||||
{
|
||||
<tr>@Row(item)</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
@if(Format == "Grid")
|
||||
{
|
||||
<div class="@Class">
|
||||
<div class="row">@Header</div>
|
||||
@foreach (var item in ItemList)
|
||||
{
|
||||
<div class="row">@Row(item)</div>
|
||||
}
|
||||
</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++)
|
||||
{
|
||||
var pager = i;
|
||||
<button class="btn @((pager == Page) ? "btn-primary" : "btn-link")" @onclick=@(async () => UpdateList(pager))>
|
||||
@pager
|
||||
</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>
|
||||
</p>
|
||||
|
||||
@code {
|
||||
int Pages = 0;
|
||||
int Page = 1;
|
||||
int MaxItems;
|
||||
int MaxPages;
|
||||
int StartPage;
|
||||
int EndPage;
|
||||
|
||||
[Parameter]
|
||||
public string Format { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment Header { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment<TableItem> Row { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public IEnumerable<TableItem> Items { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string PageSize { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string DisplayPages { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Class { get; set; }
|
||||
|
||||
IEnumerable<TableItem> ItemList { get; set; }
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
if (string.IsNullOrEmpty(Format))
|
||||
{
|
||||
Format = "Table";
|
||||
}
|
||||
if (string.IsNullOrEmpty(Class))
|
||||
{
|
||||
if (Format == "Table")
|
||||
{
|
||||
Class = "table table-borderless";
|
||||
}
|
||||
else
|
||||
{
|
||||
Class = "container";
|
||||
}
|
||||
}
|
||||
if (string.IsNullOrEmpty(PageSize))
|
||||
{
|
||||
MaxItems = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
MaxItems = int.Parse(PageSize);
|
||||
}
|
||||
if (string.IsNullOrEmpty(DisplayPages))
|
||||
{
|
||||
MaxPages = 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
MaxPages = int.Parse(DisplayPages);
|
||||
}
|
||||
|
||||
if (Items != null)
|
||||
{
|
||||
ItemList = Items.Skip((Page - 1) * MaxItems).Take(MaxItems);
|
||||
Pages = (int)Math.Ceiling(Items.Count() / (decimal)MaxItems);
|
||||
}
|
||||
|
||||
SetPagerSize("forward");
|
||||
}
|
||||
|
||||
public void UpdateList(int CurrentPage)
|
||||
{
|
||||
ItemList = Items.Skip((CurrentPage - 1) * MaxItems).Take(MaxItems);
|
||||
Page = CurrentPage;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
public void SetPagerSize(string direction)
|
||||
{
|
||||
if (direction == "forward")
|
||||
{
|
||||
if (EndPage + 1 < Pages)
|
||||
{
|
||||
StartPage = EndPage + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
StartPage = 1;
|
||||
}
|
||||
|
||||
if (EndPage + MaxPages < Pages)
|
||||
{
|
||||
EndPage = StartPage + MaxPages - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
EndPage = Pages;
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
else if (direction == "back")
|
||||
{
|
||||
EndPage = StartPage - 1;
|
||||
StartPage = StartPage - MaxPages;
|
||||
}
|
||||
}
|
||||
|
||||
public void NavigateToPage(string direction)
|
||||
{
|
||||
if (direction == "next")
|
||||
{
|
||||
if (Page < Pages)
|
||||
{
|
||||
if (Page == EndPage)
|
||||
{
|
||||
SetPagerSize("forward");
|
||||
}
|
||||
Page += 1;
|
||||
}
|
||||
}
|
||||
else if (direction == "previous")
|
||||
{
|
||||
if (Page > 1)
|
||||
{
|
||||
if (Page == StartPage)
|
||||
{
|
||||
SetPagerSize("back");
|
||||
}
|
||||
Page -= 1;
|
||||
}
|
||||
}
|
||||
UpdateList(Page);
|
||||
}
|
||||
}
|
@ -1,10 +1,4 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Security
|
||||
@using Oqtane.Shared
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
@inject IRoleService RoleService
|
||||
@inject IUserService UserService
|
||||
@ -83,6 +77,9 @@
|
||||
[Parameter]
|
||||
public string EntityName { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string PermissionNames { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Permissions { get; set; }
|
||||
|
||||
@ -95,11 +92,14 @@
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
permissionnames = PageState.ModuleDefinitions.Find(item => item.ModuleDefinitionName == ModuleState.ModuleDefinitionName).Permissions;
|
||||
if (string.IsNullOrEmpty(permissionnames))
|
||||
if (string.IsNullOrEmpty(PermissionNames))
|
||||
{
|
||||
permissionnames = "View,Edit";
|
||||
}
|
||||
else
|
||||
{
|
||||
permissionnames = PermissionNames;
|
||||
}
|
||||
roles = await RoleService.GetRolesAsync(ModuleState.SiteId);
|
||||
roles.Insert(0, new Role { Name = Constants.AllUsersRole });
|
||||
|
||||
|
43
Oqtane.Client/Modules/Controls/TabControl.razor
Normal file
43
Oqtane.Client/Modules/Controls/TabControl.razor
Normal file
@ -0,0 +1,43 @@
|
||||
@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 {
|
||||
// Next line is needed so we are able to add <TabPanel> components inside
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
public TabPanel ActiveTabPanel { get; set; }
|
||||
List<TabPanel> TabPanels = new List<TabPanel>();
|
||||
|
||||
internal void AddTabPanel(TabPanel tabPanel)
|
||||
{
|
||||
TabPanels.Add(tabPanel);
|
||||
if (TabPanels.Count == 1)
|
||||
ActiveTabPanel = tabPanel;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
string GetButtonClass(TabPanel tabPanel)
|
||||
{
|
||||
return tabPanel == ActiveTabPanel ? "btn-primary" : "btn-secondary";
|
||||
}
|
||||
|
||||
void ActivateTabPanel(TabPanel tabPanel)
|
||||
{
|
||||
ActiveTabPanel = tabPanel;
|
||||
}
|
||||
}
|
27
Oqtane.Client/Modules/Controls/TabPanel.razor
Normal file
27
Oqtane.Client/Modules/Controls/TabPanel.razor
Normal file
@ -0,0 +1,27 @@
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@inherits ModuleBase
|
||||
|
||||
@if (Parent.ActiveTabPanel == (TabPanel)(object)this)
|
||||
{
|
||||
@ChildContent
|
||||
}
|
||||
|
||||
@code {
|
||||
[CascadingParameter]
|
||||
private TabControl Parent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Text { get; set; }
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@namespace Oqtane.Modules.Controls
|
||||
@namespace Oqtane.Modules.Controls
|
||||
|
||||
<img src="@src" title="@title" disabled=@Disabled @onclick="SetValue" />
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Modules
|
||||
@namespace Oqtane.Modules.Counter
|
||||
@inherits ModuleBase
|
||||
Current count: @currentCount
|
||||
|
@ -1,5 +1,4 @@
|
||||
using Oqtane.Modules;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Oqtane.Modules.Counter
|
||||
{
|
||||
|
@ -1,26 +1,18 @@
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Modules.Controls
|
||||
@using Oqtane.Modules.HtmlText.Services
|
||||
@using Oqtane.Modules.HtmlText.Services
|
||||
@using Oqtane.Modules.HtmlText.Models
|
||||
@using System.Net.Http;
|
||||
@using Oqtane.Shared;
|
||||
@namespace Oqtane.Modules.HtmlText
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject HttpClient http
|
||||
@inject SiteState sitestate
|
||||
|
||||
<ModuleMessage Message="@message" />
|
||||
|
||||
<table class="form-group">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Name" class="control-label">Content: </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@content" rows="5" style="width:400px;" />
|
||||
<textarea class="form-control" @bind="@content" rows="5" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -34,7 +26,6 @@
|
||||
public override SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.Edit; } }
|
||||
public override string Title { get { return "Edit Html/Text"; } }
|
||||
|
||||
string message = "";
|
||||
string content;
|
||||
string createdby;
|
||||
DateTime createdon;
|
||||
@ -58,7 +49,8 @@
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
message = ex.Message;
|
||||
await logger.LogError(ex, "An Error Occurred Loading Html/Text Content. " + ex.Message);
|
||||
AddModuleMessage(ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,12 +72,13 @@
|
||||
htmltext.Content = content;
|
||||
await htmltextservice.AddHtmlTextAsync(htmltext);
|
||||
}
|
||||
PageState.Reload = Constants.ReloadPage;
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
await logger.LogInformation("Html/Text Content Saved {HtmlText}", htmltext);
|
||||
NavigationManager.NavigateTo(NavigateUrl(Reload.Page));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
message = ex.Message;
|
||||
await logger.LogError(ex, "Error Saving Content {Error}", ex.Message);
|
||||
AddModuleMessage("Error Saving Content", MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,18 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Modules.HtmlText.Services
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Modules.HtmlText.Services
|
||||
@using Oqtane.Modules.HtmlText.Models
|
||||
@using System.Net.Http;
|
||||
@using Oqtane.Modules.Controls
|
||||
@using Oqtane.Shared;
|
||||
@namespace Oqtane.Modules.HtmlText
|
||||
@inherits ModuleBase
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject HttpClient http
|
||||
@inject SiteState sitestate
|
||||
|
||||
<ModuleMessage Message="@message" />
|
||||
|
||||
@((MarkupString)content)
|
||||
|
||||
<br />
|
||||
<ActionLink Action="Edit" />
|
||||
<br />
|
||||
<br />
|
||||
<br /><br />
|
||||
|
||||
@code {
|
||||
string message = "";
|
||||
string content;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
@ -37,7 +28,7 @@
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
message = ex.Message;
|
||||
AddModuleMessage(ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
using Oqtane.Modules;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Oqtane.Modules.HtmlText
|
||||
{
|
||||
public class Module : IModule
|
||||
public class ModuleInfo : IModule
|
||||
{
|
||||
public Dictionary<string, string> Properties
|
||||
{
|
||||
@ -13,7 +12,8 @@ namespace Oqtane.Modules.HtmlText
|
||||
{
|
||||
{ "Name", "HtmlText" },
|
||||
{ "Description", "Renders HTML or Text" },
|
||||
{ "Version", "1.0.0" }
|
||||
{ "Version", "1.0.0" },
|
||||
{ "ServerAssemblyName", "Oqtane.Server" }
|
||||
};
|
||||
return properties;
|
||||
}
|
@ -1,11 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Oqtane.Services;
|
||||
using Oqtane.Modules.HtmlText.Models;
|
||||
using Oqtane.Shared;
|
||||
using Oqtane.Models;
|
||||
|
||||
namespace Oqtane.Modules.HtmlText.Services
|
||||
{
|
||||
@ -29,7 +28,17 @@ namespace Oqtane.Modules.HtmlText.Services
|
||||
|
||||
public async Task<HtmlTextInfo> GetHtmlTextAsync(int ModuleId)
|
||||
{
|
||||
return await http.GetJsonAsync<HtmlTextInfo>(apiurl + "/" + ModuleId.ToString() + "?entityid=" + ModuleId.ToString());
|
||||
HtmlTextInfo htmltext;
|
||||
try
|
||||
{
|
||||
// exception handling is required because GetJsonAsync() returns an error if no content exists for the ModuleId ( https://github.com/aspnet/AspNetCore/issues/14041 )
|
||||
htmltext = await http.GetJsonAsync<HtmlTextInfo>(apiurl + "/" + ModuleId.ToString() + "?entityid=" + ModuleId.ToString());
|
||||
}
|
||||
catch
|
||||
{
|
||||
htmltext = null;
|
||||
}
|
||||
return htmltext;
|
||||
}
|
||||
|
||||
public async Task AddHtmlTextAsync(HtmlTextInfo htmltext)
|
||||
@ -46,5 +55,6 @@ namespace Oqtane.Modules.HtmlText.Services
|
||||
{
|
||||
await http.DeleteAsync(apiurl + "/" + ModuleId.ToString() + "?entityid=" + ModuleId.ToString());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace Oqtane.Modules
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Modules
|
||||
{
|
||||
public interface IModuleControl
|
||||
{
|
||||
|
@ -1,17 +1,43 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Oqtane.Shared;
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using Oqtane.Services;
|
||||
using System;
|
||||
|
||||
namespace Oqtane.Modules
|
||||
{
|
||||
public class ModuleBase : ComponentBase, IModuleControl
|
||||
{
|
||||
public Logger logger { get; set; }
|
||||
|
||||
public ModuleBase()
|
||||
{
|
||||
this.logger = new Logger(this);
|
||||
}
|
||||
|
||||
[Inject]
|
||||
protected ILogService LoggingService { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
protected PageState PageState { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
protected Module ModuleState { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
protected ModuleInstance ModuleInstance { get; set; }
|
||||
|
||||
protected ModuleDefinition ModuleDefinition
|
||||
{
|
||||
get
|
||||
{
|
||||
return PageState.ModuleDefinitions.Where(item => item.ModuleDefinitionName == ModuleState.ModuleDefinitionName).FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
||||
// optional interface properties
|
||||
public virtual SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.View; } set { } } // default security
|
||||
|
||||
public virtual string Title { get { return ""; } }
|
||||
@ -20,19 +46,42 @@ namespace Oqtane.Modules
|
||||
|
||||
public virtual bool UseAdminContainer { get { return true; } }
|
||||
|
||||
// path method
|
||||
|
||||
public string ModulePath()
|
||||
{
|
||||
return "Modules/" + this.GetType().Namespace + "/";
|
||||
}
|
||||
|
||||
// url methods
|
||||
public string NavigateUrl()
|
||||
{
|
||||
return NavigateUrl(PageState.Page.Path);
|
||||
}
|
||||
|
||||
public string NavigateUrl(Reload reload)
|
||||
{
|
||||
return NavigateUrl(PageState.Page.Path, reload);
|
||||
}
|
||||
|
||||
public string NavigateUrl(string path)
|
||||
{
|
||||
return NavigateUrl(path, "");
|
||||
return NavigateUrl(path, "", Reload.None);
|
||||
}
|
||||
|
||||
public string NavigateUrl(string path, Reload reload)
|
||||
{
|
||||
return NavigateUrl(path, "", reload);
|
||||
}
|
||||
|
||||
public string NavigateUrl(string path, string parameters)
|
||||
{
|
||||
return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters);
|
||||
return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters, Reload.None);
|
||||
}
|
||||
|
||||
public string NavigateUrl(string path, string parameters, Reload reload)
|
||||
{
|
||||
return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters, reload);
|
||||
}
|
||||
|
||||
public string EditUrl(string action)
|
||||
@ -59,5 +108,126 @@ namespace Oqtane.Modules
|
||||
{
|
||||
return Utilities.EditUrl(PageState.Alias.Path, path, moduleid, action, parameters);
|
||||
}
|
||||
|
||||
// user feedback methods
|
||||
public void AddModuleMessage(string message, MessageType type)
|
||||
{
|
||||
ModuleInstance.AddModuleMessage(message, type);
|
||||
}
|
||||
|
||||
public void ShowProgressIndicator()
|
||||
{
|
||||
ModuleInstance.ShowProgressIndicator();
|
||||
}
|
||||
|
||||
public void HideProgressIndicator()
|
||||
{
|
||||
ModuleInstance.HideProgressIndicator();
|
||||
}
|
||||
|
||||
// logging methods
|
||||
public async Task Log(LogLevel level, Exception exception, string message, params object[] args)
|
||||
{
|
||||
int PageId = PageState.Page.PageId;
|
||||
int ModuleId = ModuleState.ModuleId;
|
||||
int? UserId = null;
|
||||
if (PageState.User != null)
|
||||
{
|
||||
UserId = PageState.User.UserId;
|
||||
}
|
||||
string category = this.GetType().AssemblyQualifiedName;
|
||||
string feature = Utilities.GetTypeNameLastSegment(category, 1);
|
||||
LogFunction function;
|
||||
switch (PageState.Action)
|
||||
{
|
||||
case "Add":
|
||||
function = LogFunction.Create;
|
||||
break;
|
||||
case "Edit":
|
||||
function = LogFunction.Update;
|
||||
break;
|
||||
case "Delete":
|
||||
function = LogFunction.Delete;
|
||||
break;
|
||||
default:
|
||||
function = LogFunction.Read;
|
||||
break;
|
||||
}
|
||||
if (feature == "Login")
|
||||
{
|
||||
function = LogFunction.Security;
|
||||
}
|
||||
await LoggingService.Log(PageId, ModuleId, UserId, category, feature, function, level, exception, message, args);
|
||||
}
|
||||
|
||||
public class Logger
|
||||
{
|
||||
private ModuleBase modulebase;
|
||||
|
||||
public Logger(ModuleBase modulebase)
|
||||
{
|
||||
this.modulebase = modulebase;
|
||||
}
|
||||
|
||||
public async Task LogTrace(string message, params object[] args)
|
||||
{
|
||||
await modulebase.Log(LogLevel.Trace, null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogTrace(Exception exception, string message, params object[] args)
|
||||
{
|
||||
await modulebase.Log(LogLevel.Trace, exception, message, args);
|
||||
}
|
||||
|
||||
public async Task LogDebug(string message, params object[] args)
|
||||
{
|
||||
await modulebase.Log(LogLevel.Debug, null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogDebug(Exception exception, string message, params object[] args)
|
||||
{
|
||||
await modulebase.Log(LogLevel.Debug, exception, message, args);
|
||||
}
|
||||
|
||||
public async Task LogInformation(string message, params object[] args)
|
||||
{
|
||||
await modulebase.Log(LogLevel.Information, null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogInformation(Exception exception, string message, params object[] args)
|
||||
{
|
||||
await modulebase.Log(LogLevel.Information, exception, message, args);
|
||||
}
|
||||
|
||||
public async Task LogWarning(string message, params object[] args)
|
||||
{
|
||||
await modulebase.Log(LogLevel.Warning, null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogWarning(Exception exception, string message, params object[] args)
|
||||
{
|
||||
await modulebase.Log(LogLevel.Warning, exception, message, args);
|
||||
}
|
||||
|
||||
public async Task LogError(string message, params object[] args)
|
||||
{
|
||||
await modulebase.Log(LogLevel.Error, null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogError(Exception exception, string message, params object[] args)
|
||||
{
|
||||
await modulebase.Log(LogLevel.Error, exception, message, args);
|
||||
}
|
||||
|
||||
public async Task LogCritical(string message, params object[] args)
|
||||
{
|
||||
await modulebase.Log(LogLevel.Critical, null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogCritical(Exception exception, string message, params object[] args)
|
||||
{
|
||||
await modulebase.Log(LogLevel.Critical, exception, message, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Modules.Weather.Services
|
||||
@namespace Oqtane.Modules.Weather
|
||||
@inherits ModuleBase
|
||||
|
@ -1,5 +1,4 @@
|
||||
using Oqtane.Modules;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Oqtane.Modules.Weather
|
||||
{
|
||||
|
@ -3,6 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<BlazorLinkOnBuild>false</BlazorLinkOnBuild>
|
||||
<RestoreAdditionalProjectSources>
|
||||
https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json;
|
||||
https://dotnet.myget.org/F/blazor-dev/api/v3/index.json;
|
||||
@ -27,10 +28,10 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Blazor" Version="3.0.0-preview9.19424.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="3.0.0-preview9.19424.4" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Blazor.HttpClient" Version="3.0.0-preview9.19424.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="3.0.0-preview9.19424.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Blazor" Version="3.0.0-preview9.19465.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="3.0.0-preview9.19465.2" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Blazor.HttpClient" Version="3.0.0-preview9.19465.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="3.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -1,4 +1,7 @@
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using Oqtane.Shared;
|
||||
@ -7,12 +10,14 @@ namespace Oqtane.Services
|
||||
{
|
||||
public class FileService : ServiceBase, IFileService
|
||||
{
|
||||
private readonly HttpClient http;
|
||||
private readonly SiteState sitestate;
|
||||
private readonly NavigationManager NavigationManager;
|
||||
private readonly IJSRuntime jsRuntime;
|
||||
|
||||
public FileService(SiteState sitestate, NavigationManager NavigationManager, IJSRuntime jsRuntime)
|
||||
public FileService(HttpClient http, SiteState sitestate, NavigationManager NavigationManager, IJSRuntime jsRuntime)
|
||||
{
|
||||
this.http = http;
|
||||
this.sitestate = sitestate;
|
||||
this.NavigationManager = NavigationManager;
|
||||
this.jsRuntime = jsRuntime;
|
||||
@ -23,15 +28,52 @@ namespace Oqtane.Services
|
||||
get { return CreateApiUrl(sitestate.Alias, NavigationManager.Uri, "File"); }
|
||||
}
|
||||
|
||||
public async Task UploadFilesAsync(string Folder)
|
||||
public async Task<List<string>> GetFilesAsync(string Folder)
|
||||
{
|
||||
await UploadFilesAsync(Folder, "");
|
||||
return await http.GetJsonAsync<List<string>>(apiurl + "?folder=" + Folder);
|
||||
}
|
||||
|
||||
public async Task UploadFilesAsync(string Folder, string FileUploadName)
|
||||
public async Task<string> UploadFilesAsync(string Folder, string[] Files, string FileUploadName)
|
||||
{
|
||||
string result = "";
|
||||
|
||||
var interop = new Interop(jsRuntime);
|
||||
await interop.UploadFiles(apiurl + "/upload", Folder, FileUploadName);
|
||||
|
||||
// uploading files is asynchronous so we need to wait for the upload to complete
|
||||
bool success = false;
|
||||
int attempts = 0;
|
||||
while (attempts < 5 && success == false)
|
||||
{
|
||||
Thread.Sleep(2000); // wait 2 seconds
|
||||
result = "";
|
||||
|
||||
List<string> files = await GetFilesAsync(Folder);
|
||||
if (files.Count > 0)
|
||||
{
|
||||
success = true;
|
||||
foreach (string file in Files)
|
||||
{
|
||||
if (!files.Contains(file))
|
||||
{
|
||||
success = false;
|
||||
result += file + ",";
|
||||
}
|
||||
}
|
||||
}
|
||||
attempts += 1;
|
||||
}
|
||||
if (!success)
|
||||
{
|
||||
result = result.Substring(0, result.Length - 1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task DeleteFileAsync(string Folder, string File)
|
||||
{
|
||||
await http.DeleteAsync(apiurl + "?folder=" + Folder + "&file=" + File);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,5 +35,10 @@ namespace Oqtane.Services
|
||||
{
|
||||
return await http.PostJsonAsync<GenericResponse>(apiurl, connectionstring);
|
||||
}
|
||||
|
||||
public async Task<GenericResponse> Upgrade()
|
||||
{
|
||||
return await http.GetJsonAsync<GenericResponse>(apiurl + "/upgrade");
|
||||
}
|
||||
}
|
||||
}
|
@ -6,7 +6,8 @@ namespace Oqtane.Services
|
||||
{
|
||||
public interface IFileService
|
||||
{
|
||||
Task UploadFilesAsync(string Folder);
|
||||
Task UploadFilesAsync(string Folder, string FileUploadName);
|
||||
Task<List<string>> GetFilesAsync(string Folder);
|
||||
Task<string> UploadFilesAsync(string Folder, string[] Files, string FileUploadName);
|
||||
Task DeleteFileAsync(string Folder, string File);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Services
|
||||
@ -8,5 +7,6 @@ namespace Oqtane.Services
|
||||
{
|
||||
Task<GenericResponse> IsInstalled();
|
||||
Task<GenericResponse> Install(string connectionstring);
|
||||
Task<GenericResponse> Upgrade();
|
||||
}
|
||||
}
|
||||
|
15
Oqtane.Client/Services/Interfaces/ILogService.cs
Normal file
15
Oqtane.Client/Services/Interfaces/ILogService.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Shared;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
public interface ILogService
|
||||
{
|
||||
Task<List<Log>> GetLogsAsync(int SiteId, string Level, string Function, int Rows);
|
||||
Task<Log> GetLogAsync(int LogId);
|
||||
Task Log(int? PageId, int? ModuleId, int? UserId, string category, string feature, LogFunction function, LogLevel level, Exception exception, string message, params object[] args);
|
||||
}
|
||||
}
|
@ -6,7 +6,9 @@ namespace Oqtane.Services
|
||||
{
|
||||
public interface IModuleDefinitionService
|
||||
{
|
||||
Task<List<ModuleDefinition>> GetModuleDefinitionsAsync();
|
||||
Task InstallModulesAsync();
|
||||
}
|
||||
Task<List<ModuleDefinition>> GetModuleDefinitionsAsync(int SiteId);
|
||||
Task UpdateModuleDefinitionAsync(ModuleDefinition ModuleDefinition);
|
||||
Task InstallModuleDefinitionsAsync();
|
||||
Task DeleteModuleDefinitionAsync(int ModuleDefinitionId, int SiteId);
|
||||
}
|
||||
}
|
||||
|
@ -6,11 +6,12 @@ namespace Oqtane.Services
|
||||
{
|
||||
public interface IModuleService
|
||||
{
|
||||
Task<List<Module>> GetModulesAsync(int PageId);
|
||||
Task<List<Module>> GetModulesAsync(int SiteId, string ModuleDefinitionName);
|
||||
Task<List<Module>> GetModulesAsync(int SiteId);
|
||||
Task<Module> GetModuleAsync(int ModuleId);
|
||||
Task<Module> AddModuleAsync(Module Module);
|
||||
Task<Module> UpdateModuleAsync(Module Module);
|
||||
Task DeleteModuleAsync(int ModuleId);
|
||||
Task<bool> ImportModuleAsync(int ModuleId, string Content);
|
||||
Task<string> ExportModuleAsync(int ModuleId);
|
||||
}
|
||||
}
|
||||
|
12
Oqtane.Client/Services/Interfaces/IPackageService.cs
Normal file
12
Oqtane.Client/Services/Interfaces/IPackageService.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
public interface IPackageService
|
||||
{
|
||||
Task<List<Package>> GetPackagesAsync(string Tag);
|
||||
Task DownloadPackageAsync(string PackageId, string Version, string Folder);
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ namespace Oqtane.Services
|
||||
{
|
||||
Task<List<PageModule>> GetPageModulesAsync();
|
||||
Task<PageModule> GetPageModuleAsync(int PageModuleId);
|
||||
Task<PageModule> GetPageModuleAsync(int PageId, int ModuleId);
|
||||
Task<PageModule> AddPageModuleAsync(PageModule PageModule);
|
||||
Task<PageModule> UpdatePageModuleAsync(PageModule PageModule);
|
||||
Task UpdatePageModuleOrderAsync(int PageId, string Pane);
|
||||
|
@ -8,9 +8,10 @@ namespace Oqtane.Services
|
||||
{
|
||||
Task<List<Page>> GetPagesAsync(int SiteId);
|
||||
Task<Page> GetPageAsync(int PageId);
|
||||
Task<Page> GetPageAsync(int PageId, int UserId);
|
||||
Task<Page> AddPageAsync(Page Page);
|
||||
Task<Page> UpdatePageAsync(Page Page);
|
||||
Task UpdatePageOrderAsync(int SiteId, int? ParentId);
|
||||
Task UpdatePageOrderAsync(int SiteId, int PageId, int? ParentId);
|
||||
Task DeletePageAsync(int PageId);
|
||||
}
|
||||
}
|
||||
|
19
Oqtane.Client/Services/Interfaces/IScheduleLogService.cs
Normal file
19
Oqtane.Client/Services/Interfaces/IScheduleLogService.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
public interface IScheduleLogService
|
||||
{
|
||||
Task<List<ScheduleLog>> GetScheduleLogsAsync();
|
||||
|
||||
Task<ScheduleLog> GetScheduleLogAsync(int ScheduleLogId);
|
||||
|
||||
Task<ScheduleLog> AddScheduleLogAsync(ScheduleLog ScheduleLog);
|
||||
|
||||
Task<ScheduleLog> UpdateScheduleLogAsync(ScheduleLog ScheduleLog);
|
||||
|
||||
Task DeleteScheduleLogAsync(int ScheduleLogId);
|
||||
}
|
||||
}
|
19
Oqtane.Client/Services/Interfaces/IScheduleService.cs
Normal file
19
Oqtane.Client/Services/Interfaces/IScheduleService.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
public interface IScheduleService
|
||||
{
|
||||
Task<List<Schedule>> GetSchedulesAsync();
|
||||
|
||||
Task<Schedule> GetScheduleAsync(int ScheduleId);
|
||||
|
||||
Task<Schedule> AddScheduleAsync(Schedule Schedule);
|
||||
|
||||
Task<Schedule> UpdateScheduleAsync(Schedule Schedule);
|
||||
|
||||
Task DeleteScheduleAsync(int ScheduleId);
|
||||
}
|
||||
}
|
@ -7,13 +7,18 @@ namespace Oqtane.Services
|
||||
public interface ISiteService
|
||||
{
|
||||
Task<List<Site>> GetSitesAsync();
|
||||
Task<List<Site>> GetSitesAsync(Alias Alias);
|
||||
|
||||
Task<Site> GetSiteAsync(int SiteId);
|
||||
Task<Site> GetSiteAsync(int SiteId, Alias Alias);
|
||||
|
||||
Task<Site> AddSiteAsync(Site Site);
|
||||
Task<Site> AddSiteAsync(Site Site, Alias Alias);
|
||||
|
||||
Task<Site> UpdateSiteAsync(Site Site);
|
||||
Task<Site> UpdateSiteAsync(Site Site, Alias Alias);
|
||||
|
||||
Task DeleteSiteAsync(int SiteId);
|
||||
Task DeleteSiteAsync(int SiteId, Alias Alias);
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,12 @@ namespace Oqtane.Services
|
||||
{
|
||||
Task<List<Tenant>> GetTenantsAsync();
|
||||
|
||||
Task<Tenant> GetTenantAsync();
|
||||
Task<Tenant> GetTenantAsync(int TenantId);
|
||||
|
||||
Task<Tenant> AddTenantAsync(Tenant Tenant);
|
||||
|
||||
Task<Tenant> UpdateTenantAsync(Tenant Tenant);
|
||||
|
||||
Task DeleteTenantAsync(int TenantId);
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,10 @@ namespace Oqtane.Services
|
||||
public interface IThemeService
|
||||
{
|
||||
Task<List<Theme>> GetThemesAsync();
|
||||
Dictionary<string, string> GetThemeTypes(List<Theme> themes);
|
||||
Dictionary<string, string> GetPaneLayoutTypes(List<Theme> themes);
|
||||
Dictionary<string, string> GetContainerTypes(List<Theme> themes);
|
||||
Dictionary<string, string> GetThemeTypes(List<Theme> Themes);
|
||||
Dictionary<string, string> GetPaneLayoutTypes(List<Theme> Themes, string ThemeName);
|
||||
Dictionary<string, string> GetContainerTypes(List<Theme> Themes);
|
||||
Task InstallThemesAsync();
|
||||
Task DeleteThemeAsync(string ThemeName);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ namespace Oqtane.Services
|
||||
public interface IUserRoleService
|
||||
{
|
||||
Task<List<UserRole>> GetUserRolesAsync();
|
||||
Task<List<UserRole>> GetUserRolesAsync(int UserId);
|
||||
Task<List<UserRole>> GetUserRolesAsync(int SiteId);
|
||||
Task<UserRole> GetUserRoleAsync(int UserRoleId);
|
||||
Task<UserRole> AddUserRoleAsync(UserRole UserRole);
|
||||
Task<UserRole> UpdateUserRoleAsync(UserRole UserRole);
|
||||
|
@ -6,7 +6,7 @@ namespace Oqtane.Services
|
||||
{
|
||||
public interface IUserService
|
||||
{
|
||||
Task<List<User>> GetUsersAsync(int SiteId);
|
||||
Task<List<User>> GetUsersAsync();
|
||||
|
||||
Task<User> GetUserAsync(int UserId, int SiteId);
|
||||
|
||||
@ -14,12 +14,14 @@ namespace Oqtane.Services
|
||||
|
||||
Task<User> AddUserAsync(User User);
|
||||
|
||||
Task<User> AddUserAsync(User User, Alias alias);
|
||||
|
||||
Task<User> UpdateUserAsync(User User);
|
||||
|
||||
Task DeleteUserAsync(int UserId);
|
||||
|
||||
Task<User> LoginUserAsync(User User, bool SetCookie, bool IsPersistent);
|
||||
|
||||
Task LogoutUserAsync();
|
||||
Task LogoutUserAsync(User User);
|
||||
}
|
||||
}
|
||||
|
62
Oqtane.Client/Services/LogService.cs
Normal file
62
Oqtane.Client/Services/LogService.cs
Normal file
@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
public class LogService : ServiceBase, ILogService
|
||||
{
|
||||
private readonly HttpClient http;
|
||||
private readonly SiteState sitestate;
|
||||
private readonly NavigationManager NavigationManager;
|
||||
|
||||
public LogService(HttpClient http, SiteState sitestate, NavigationManager NavigationManager)
|
||||
{
|
||||
this.http = http;
|
||||
this.sitestate = sitestate;
|
||||
this.NavigationManager = NavigationManager;
|
||||
}
|
||||
|
||||
private string apiurl
|
||||
{
|
||||
get { return CreateApiUrl(sitestate.Alias, NavigationManager.Uri, "Log"); }
|
||||
}
|
||||
|
||||
public async Task<List<Log>> GetLogsAsync(int SiteId, string Level, string Function, int Rows)
|
||||
{
|
||||
return await http.GetJsonAsync<List<Log>>(apiurl + "?siteid=" + SiteId.ToString() + "&level=" + Level + "&function=" + Function + "&rows=" + Rows.ToString());
|
||||
}
|
||||
|
||||
public async Task<Log> GetLogAsync(int LogId)
|
||||
{
|
||||
return await http.GetJsonAsync<Log>(apiurl + "/" + LogId.ToString());
|
||||
}
|
||||
|
||||
public async Task Log(int? PageId, int? ModuleId, int? UserId, string category, string feature, LogFunction function, LogLevel level, Exception exception, string message, params object[] args)
|
||||
{
|
||||
Log log = new Log();
|
||||
log.SiteId = sitestate.Alias.SiteId;
|
||||
log.PageId = PageId;
|
||||
log.ModuleId = ModuleId;
|
||||
log.UserId = UserId;
|
||||
log.Url = NavigationManager.Uri;
|
||||
log.Category = category;
|
||||
log.Feature = feature;
|
||||
log.Function = Enum.GetName(typeof(LogFunction), function);
|
||||
log.Level = Enum.GetName(typeof(LogLevel), level);
|
||||
if (exception != null)
|
||||
{
|
||||
log.Exception = JsonSerializer.Serialize(exception);
|
||||
}
|
||||
log.Message = message;
|
||||
log.MessageTemplate = "";
|
||||
log.Properties = JsonSerializer.Serialize(args);
|
||||
await http.PostJsonAsync(apiurl, log);
|
||||
}
|
||||
}
|
||||
}
|
@ -28,10 +28,10 @@ namespace Oqtane.Services
|
||||
get { return CreateApiUrl(sitestate.Alias, NavigationManager.Uri, "ModuleDefinition"); }
|
||||
}
|
||||
|
||||
public async Task<List<ModuleDefinition>> GetModuleDefinitionsAsync()
|
||||
public async Task<List<ModuleDefinition>> GetModuleDefinitionsAsync(int SiteId)
|
||||
{
|
||||
// get list of modules from the server
|
||||
List<ModuleDefinition> moduledefinitions = await http.GetJsonAsync<List<ModuleDefinition>>(apiurl);
|
||||
List<ModuleDefinition> moduledefinitions = await http.GetJsonAsync<List<ModuleDefinition>>(apiurl + "?siteid=" + SiteId.ToString());
|
||||
|
||||
// get list of loaded assemblies on the client ( in the client-side hosting module the browser client has its own app domain )
|
||||
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
@ -47,7 +47,7 @@ namespace Oqtane.Services
|
||||
if (assemblies.Where(item => item.FullName.StartsWith(assemblyname + ",")).FirstOrDefault() == null)
|
||||
{
|
||||
// download assembly from server and load
|
||||
var bytes = await http.GetByteArrayAsync("_framework/_bin/" + assemblyname + ".dll");
|
||||
var bytes = await http.GetByteArrayAsync(apiurl + "/" + assemblyname + ".dll");
|
||||
Assembly.Load(bytes);
|
||||
}
|
||||
}
|
||||
@ -56,7 +56,7 @@ namespace Oqtane.Services
|
||||
if (assemblies.Where(item => item.FullName.StartsWith(moduledefinition.AssemblyName + ",")).FirstOrDefault() == null)
|
||||
{
|
||||
// download assembly from server and load
|
||||
var bytes = await http.GetByteArrayAsync("_framework/_bin/" + moduledefinition.AssemblyName + ".dll");
|
||||
var bytes = await http.GetByteArrayAsync(apiurl + "/" + moduledefinition.AssemblyName + ".dll");
|
||||
Assembly.Load(bytes);
|
||||
}
|
||||
}
|
||||
@ -64,9 +64,19 @@ namespace Oqtane.Services
|
||||
return moduledefinitions.OrderBy(item => item.Name).ToList();
|
||||
}
|
||||
|
||||
public async Task InstallModulesAsync()
|
||||
public async Task UpdateModuleDefinitionAsync(ModuleDefinition ModuleDefinition)
|
||||
{
|
||||
await http.PutJsonAsync(apiurl + "/" + ModuleDefinition.ModuleDefinitionId.ToString(), ModuleDefinition);
|
||||
}
|
||||
|
||||
public async Task InstallModuleDefinitionsAsync()
|
||||
{
|
||||
await http.GetJsonAsync<List<string>>(apiurl + "/install");
|
||||
}
|
||||
|
||||
public async Task DeleteModuleDefinitionAsync(int ModuleDefinitionId, int SiteId)
|
||||
{
|
||||
await http.DeleteAsync(apiurl + "/" + ModuleDefinitionId.ToString() + "?siteid=" + SiteId.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,21 +26,15 @@ namespace Oqtane.Services
|
||||
get { return CreateApiUrl(sitestate.Alias, NavigationManager.Uri, "Module"); }
|
||||
}
|
||||
|
||||
public async Task<List<Module>> GetModulesAsync(int PageId)
|
||||
public async Task<List<Module>> GetModulesAsync(int SiteId)
|
||||
{
|
||||
List<Module> modules = await http.GetJsonAsync<List<Module>>(apiurl + "?pageid=" + PageId.ToString());
|
||||
List<Module> modules = await http.GetJsonAsync<List<Module>>(apiurl + "?siteid=" + SiteId.ToString());
|
||||
modules = modules
|
||||
.OrderBy(item => item.Order)
|
||||
.ToList();
|
||||
return modules;
|
||||
}
|
||||
|
||||
public async Task<List<Module>> GetModulesAsync(int SiteId, string ModuleDefinitionName)
|
||||
{
|
||||
List<Module> modules = await http.GetJsonAsync<List<Module>>(apiurl + "?siteid=" + SiteId.ToString() + "&moduledefinitionname=" + ModuleDefinitionName);
|
||||
return modules.ToList();
|
||||
}
|
||||
|
||||
public async Task<Module> GetModuleAsync(int ModuleId)
|
||||
{
|
||||
return await http.GetJsonAsync<Module>(apiurl + "/" + ModuleId.ToString());
|
||||
@ -60,5 +54,15 @@ namespace Oqtane.Services
|
||||
{
|
||||
await http.DeleteAsync(apiurl + "/" + ModuleId.ToString());
|
||||
}
|
||||
|
||||
public async Task<bool> ImportModuleAsync(int ModuleId, string Content)
|
||||
{
|
||||
return await http.PostJsonAsync<bool>(apiurl + "/import?moduleid=" + ModuleId, Content);
|
||||
}
|
||||
|
||||
public async Task<string> ExportModuleAsync(int ModuleId)
|
||||
{
|
||||
return await http.GetStringAsync(apiurl + "/export?moduleid=" + ModuleId.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
40
Oqtane.Client/Services/PackageService.cs
Normal file
40
Oqtane.Client/Services/PackageService.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Oqtane.Shared;
|
||||
using System.Linq;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
public class PackageService : ServiceBase, IPackageService
|
||||
{
|
||||
private readonly HttpClient http;
|
||||
private readonly SiteState sitestate;
|
||||
private readonly NavigationManager NavigationManager;
|
||||
|
||||
public PackageService(HttpClient http, SiteState sitestate, NavigationManager NavigationManager)
|
||||
{
|
||||
this.http = http;
|
||||
this.sitestate = sitestate;
|
||||
this.NavigationManager = NavigationManager;
|
||||
}
|
||||
|
||||
private string apiurl
|
||||
{
|
||||
get { return CreateApiUrl(sitestate.Alias, NavigationManager.Uri, "Package"); }
|
||||
}
|
||||
|
||||
public async Task<List<Package>> GetPackagesAsync(string Tag)
|
||||
{
|
||||
List<Package> packages = await http.GetJsonAsync<List<Package>>(apiurl + "?tag=" + Tag);
|
||||
return packages.OrderByDescending(item => item.Downloads).ToList();
|
||||
}
|
||||
|
||||
public async Task DownloadPackageAsync(string PackageId, string Version, string Folder)
|
||||
{
|
||||
await http.PostJsonAsync(apiurl + "?packageid=" + PackageId + "&version=" + Version + "&folder=" + Folder, null);
|
||||
}
|
||||
}
|
||||
}
|
@ -36,6 +36,11 @@ namespace Oqtane.Services
|
||||
return await http.GetJsonAsync<PageModule>(apiurl + "/" + PageModuleId.ToString());
|
||||
}
|
||||
|
||||
public async Task<PageModule> GetPageModuleAsync(int PageId, int ModuleId)
|
||||
{
|
||||
return await http.GetJsonAsync<PageModule>(apiurl + "/" + PageId.ToString() + "/" + ModuleId.ToString());
|
||||
}
|
||||
|
||||
public async Task<PageModule> AddPageModuleAsync(PageModule PageModule)
|
||||
{
|
||||
return await http.PostJsonAsync<PageModule>(apiurl, PageModule);
|
||||
|
@ -39,6 +39,11 @@ namespace Oqtane.Services
|
||||
return await http.GetJsonAsync<Page>(apiurl + "/" + PageId.ToString());
|
||||
}
|
||||
|
||||
public async Task<Page> GetPageAsync(int PageId, int UserId)
|
||||
{
|
||||
return await http.GetJsonAsync<Page>(apiurl + "/" + PageId.ToString() + "?userid=" + UserId.ToString());
|
||||
}
|
||||
|
||||
public async Task<Page> AddPageAsync(Page Page)
|
||||
{
|
||||
return await http.PostJsonAsync<Page>(apiurl, Page);
|
||||
@ -49,9 +54,9 @@ namespace Oqtane.Services
|
||||
return await http.PutJsonAsync<Page>(apiurl + "/" + Page.PageId.ToString(), Page);
|
||||
}
|
||||
|
||||
public async Task UpdatePageOrderAsync(int SiteId, int? ParentId)
|
||||
public async Task UpdatePageOrderAsync(int SiteId, int PageId, int? ParentId)
|
||||
{
|
||||
await http.PutJsonAsync(apiurl + "/?siteid=" + SiteId.ToString() + "&parentid=" + ((ParentId == null) ? "" : ParentId.ToString()), null);
|
||||
await http.PutJsonAsync(apiurl + "/?siteid=" + SiteId.ToString() + "&pageid=" + PageId.ToString() + "&parentid=" + ((ParentId == null) ? "" : ParentId.ToString()), null);
|
||||
}
|
||||
|
||||
public async Task DeletePageAsync(int PageId)
|
||||
|
54
Oqtane.Client/Services/ScheduleLogService.cs
Normal file
54
Oqtane.Client/Services/ScheduleLogService.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Collections.Generic;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
public class ScheduleLogService : ServiceBase, IScheduleLogService
|
||||
{
|
||||
private readonly HttpClient http;
|
||||
private readonly SiteState sitestate;
|
||||
private readonly NavigationManager NavigationManager;
|
||||
|
||||
public ScheduleLogService(HttpClient http, SiteState sitestate, NavigationManager NavigationManager)
|
||||
{
|
||||
this.http = http;
|
||||
this.sitestate = sitestate;
|
||||
this.NavigationManager = NavigationManager;
|
||||
}
|
||||
|
||||
private string apiurl
|
||||
{
|
||||
get { return CreateApiUrl(sitestate.Alias, NavigationManager.Uri, "ScheduleLog"); }
|
||||
}
|
||||
|
||||
public async Task<List<ScheduleLog>> GetScheduleLogsAsync()
|
||||
{
|
||||
List<ScheduleLog> schedulelogs = await http.GetJsonAsync<List<ScheduleLog>>(apiurl);
|
||||
return schedulelogs.OrderBy(item => item.StartDate).ToList();
|
||||
}
|
||||
|
||||
public async Task<ScheduleLog> GetScheduleLogAsync(int ScheduleLogId)
|
||||
{
|
||||
return await http.GetJsonAsync<ScheduleLog>(apiurl + "/" + ScheduleLogId.ToString());
|
||||
}
|
||||
|
||||
public async Task<ScheduleLog> AddScheduleLogAsync(ScheduleLog schedulelog)
|
||||
{
|
||||
return await http.PostJsonAsync<ScheduleLog>(apiurl, schedulelog);
|
||||
}
|
||||
|
||||
public async Task<ScheduleLog> UpdateScheduleLogAsync(ScheduleLog schedulelog)
|
||||
{
|
||||
return await http.PutJsonAsync<ScheduleLog>(apiurl + "/" + schedulelog.ScheduleLogId.ToString(), schedulelog);
|
||||
}
|
||||
public async Task DeleteScheduleLogAsync(int ScheduleLogId)
|
||||
{
|
||||
await http.DeleteAsync(apiurl + "/" + ScheduleLogId.ToString());
|
||||
}
|
||||
}
|
||||
}
|
54
Oqtane.Client/Services/ScheduleService.cs
Normal file
54
Oqtane.Client/Services/ScheduleService.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Collections.Generic;
|
||||
using Oqtane.Shared;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
public class ScheduleService : ServiceBase, IScheduleService
|
||||
{
|
||||
private readonly HttpClient http;
|
||||
private readonly SiteState sitestate;
|
||||
private readonly NavigationManager NavigationManager;
|
||||
|
||||
public ScheduleService(HttpClient http, SiteState sitestate, NavigationManager NavigationManager)
|
||||
{
|
||||
this.http = http;
|
||||
this.sitestate = sitestate;
|
||||
this.NavigationManager = NavigationManager;
|
||||
}
|
||||
|
||||
private string apiurl
|
||||
{
|
||||
get { return CreateApiUrl(sitestate.Alias, NavigationManager.Uri, "Schedule"); }
|
||||
}
|
||||
|
||||
public async Task<List<Schedule>> GetSchedulesAsync()
|
||||
{
|
||||
List<Schedule> schedules = await http.GetJsonAsync<List<Schedule>>(apiurl);
|
||||
return schedules.OrderBy(item => item.Name).ToList();
|
||||
}
|
||||
|
||||
public async Task<Schedule> GetScheduleAsync(int ScheduleId)
|
||||
{
|
||||
return await http.GetJsonAsync<Schedule>(apiurl + "/" + ScheduleId.ToString());
|
||||
}
|
||||
|
||||
public async Task<Schedule> AddScheduleAsync(Schedule schedule)
|
||||
{
|
||||
return await http.PostJsonAsync<Schedule>(apiurl, schedule);
|
||||
}
|
||||
|
||||
public async Task<Schedule> UpdateScheduleAsync(Schedule schedule)
|
||||
{
|
||||
return await http.PutJsonAsync<Schedule>(apiurl + "/" + schedule.ScheduleId.ToString(), schedule);
|
||||
}
|
||||
public async Task DeleteScheduleAsync(int ScheduleId)
|
||||
{
|
||||
await http.DeleteAsync(apiurl + "/" + ScheduleId.ToString());
|
||||
}
|
||||
}
|
||||
}
|
@ -10,11 +10,13 @@ namespace Oqtane.Services
|
||||
|
||||
public static string CreateApiUrl(Alias alias, string absoluteUri, string serviceName)
|
||||
{
|
||||
string apiurl = "";
|
||||
Uri uri = new Uri(absoluteUri);
|
||||
|
||||
string apiurl;
|
||||
if (alias != null)
|
||||
{
|
||||
// build a url which passes the alias that may include a subfolder for multi-tenancy
|
||||
apiurl = alias.Url + "/";
|
||||
apiurl = uri.Scheme + "://" + alias.Name + "/";
|
||||
if (alias.Path == "")
|
||||
{
|
||||
apiurl += "~/";
|
||||
@ -23,7 +25,6 @@ namespace Oqtane.Services
|
||||
else
|
||||
{
|
||||
// build a url which ignores any subfolder for multi-tenancy
|
||||
Uri uri = new Uri(absoluteUri);
|
||||
apiurl = uri.Scheme + "://" + uri.Authority + "/~/";
|
||||
}
|
||||
apiurl += "api/" + serviceName;
|
||||
|
@ -31,24 +31,47 @@ namespace Oqtane.Services
|
||||
List<Site> sites = await http.GetJsonAsync<List<Site>>(apiurl);
|
||||
return sites.OrderBy(item => item.Name).ToList();
|
||||
}
|
||||
public async Task<List<Site>> GetSitesAsync(Alias Alias)
|
||||
{
|
||||
List<Site> sites = await http.GetJsonAsync<List<Site>>(CreateApiUrl(Alias, NavigationManager.Uri, "Site"));
|
||||
return sites.OrderBy(item => item.Name).ToList();
|
||||
}
|
||||
|
||||
public async Task<Site> GetSiteAsync(int SiteId)
|
||||
{
|
||||
return await http.GetJsonAsync<Site>(apiurl + "/" + SiteId.ToString());
|
||||
}
|
||||
public async Task<Site> GetSiteAsync(int SiteId, Alias Alias)
|
||||
{
|
||||
return await http.GetJsonAsync<Site>(CreateApiUrl(Alias, NavigationManager.Uri, "Site") + "/" + SiteId.ToString());
|
||||
}
|
||||
|
||||
public async Task<Site> AddSiteAsync(Site Site)
|
||||
{
|
||||
return await http.PostJsonAsync<Site>(apiurl, Site);
|
||||
}
|
||||
|
||||
public async Task<Site> AddSiteAsync(Site Site, Alias Alias)
|
||||
{
|
||||
return await http.PostJsonAsync<Site>(CreateApiUrl(Alias, NavigationManager.Uri, "Site"), Site);
|
||||
}
|
||||
|
||||
public async Task<Site> UpdateSiteAsync(Site Site)
|
||||
{
|
||||
return await http.PutJsonAsync<Site>(apiurl + "/" + Site.SiteId.ToString(), Site);
|
||||
}
|
||||
public async Task<Site> UpdateSiteAsync(Site Site, Alias Alias)
|
||||
{
|
||||
return await http.PutJsonAsync<Site>(CreateApiUrl(Alias, NavigationManager.Uri, "Site") + "/" + Site.SiteId.ToString(), Site);
|
||||
}
|
||||
|
||||
public async Task DeleteSiteAsync(int SiteId)
|
||||
{
|
||||
await http.DeleteAsync(apiurl + "/" + SiteId.ToString());
|
||||
}
|
||||
public async Task DeleteSiteAsync(int SiteId, Alias Alias)
|
||||
{
|
||||
await http.DeleteAsync(CreateApiUrl(Alias, NavigationManager.Uri, "Site") + "/" + SiteId.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,9 +32,24 @@ namespace Oqtane.Services
|
||||
return tenants.OrderBy(item => item.Name).ToList();
|
||||
}
|
||||
|
||||
public async Task<Tenant> GetTenantAsync()
|
||||
public async Task<Tenant> GetTenantAsync(int TenantId)
|
||||
{
|
||||
return await http.GetJsonAsync<Tenant>(apiurl);
|
||||
return await http.GetJsonAsync<Tenant>(apiurl + "/" + TenantId.ToString());
|
||||
}
|
||||
|
||||
public async Task<Tenant> AddTenantAsync(Tenant Tenant)
|
||||
{
|
||||
return await http.PostJsonAsync<Tenant>(apiurl, Tenant);
|
||||
}
|
||||
|
||||
public async Task<Tenant> UpdateTenantAsync(Tenant Tenant)
|
||||
{
|
||||
return await http.PutJsonAsync<Tenant>(apiurl + "/" + Tenant.TenantId.ToString(), Tenant);
|
||||
}
|
||||
|
||||
public async Task DeleteTenantAsync(int TenantId)
|
||||
{
|
||||
await http.DeleteAsync(apiurl + "/" + TenantId.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ namespace Oqtane.Services
|
||||
if (assemblies.Where(item => item.FullName.StartsWith(assemblyname + ",")).FirstOrDefault() == null)
|
||||
{
|
||||
// download assembly from server and load
|
||||
var bytes = await http.GetByteArrayAsync("_framework/_bin/" + assemblyname + ".dll");
|
||||
var bytes = await http.GetByteArrayAsync(apiurl + "/" + assemblyname + ".dll");
|
||||
Assembly.Load(bytes);
|
||||
}
|
||||
}
|
||||
@ -53,7 +53,7 @@ namespace Oqtane.Services
|
||||
if (assemblies.Where(item => item.FullName.StartsWith(theme.AssemblyName + ",")).FirstOrDefault() == null)
|
||||
{
|
||||
// download assembly from server and load
|
||||
var bytes = await http.GetByteArrayAsync("_framework/_bin/" + theme.AssemblyName + ".dll");
|
||||
var bytes = await http.GetByteArrayAsync(apiurl + "/" + theme.AssemblyName + ".dll");
|
||||
Assembly.Load(bytes);
|
||||
}
|
||||
}
|
||||
@ -61,43 +61,56 @@ namespace Oqtane.Services
|
||||
return themes.OrderBy(item => item.Name).ToList();
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetThemeTypes(List<Theme> themes)
|
||||
public Dictionary<string, string> GetThemeTypes(List<Theme> Themes)
|
||||
{
|
||||
var selectableThemes = new Dictionary<string, string>();
|
||||
foreach (Theme theme in themes)
|
||||
foreach (Theme theme in Themes)
|
||||
{
|
||||
foreach (string themecontrol in theme.ThemeControls.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
selectableThemes.Add(themecontrol, theme.Name + " - " + Utilities.GetTypeNameClass(themecontrol));
|
||||
selectableThemes.Add(themecontrol, theme.Name + " - " + Utilities.GetTypeNameLastSegment(themecontrol, 0));
|
||||
}
|
||||
}
|
||||
return selectableThemes;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetPaneLayoutTypes(List<Theme> themes)
|
||||
public Dictionary<string, string> GetPaneLayoutTypes(List<Theme> Themes, string ThemeName)
|
||||
{
|
||||
var selectablePaneLayouts = new Dictionary<string, string>();
|
||||
foreach (Theme theme in themes)
|
||||
{
|
||||
foreach (string panelayout in theme.PaneLayouts.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
foreach (Theme theme in Themes)
|
||||
{
|
||||
if (ThemeName.StartsWith(theme.ThemeName))
|
||||
{
|
||||
selectablePaneLayouts.Add(panelayout, theme.Name + " - " + @Utilities.GetTypeNameClass(panelayout));
|
||||
foreach (string panelayout in theme.PaneLayouts.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
selectablePaneLayouts.Add(panelayout, theme.Name + " - " + @Utilities.GetTypeNameLastSegment(panelayout, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
return selectablePaneLayouts;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetContainerTypes(List<Theme> themes)
|
||||
public Dictionary<string, string> GetContainerTypes(List<Theme> Themes)
|
||||
{
|
||||
var selectableContainers = new Dictionary<string, string>();
|
||||
foreach (Theme theme in themes)
|
||||
foreach (Theme theme in Themes)
|
||||
{
|
||||
foreach (string container in theme.ContainerControls.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
selectableContainers.Add(container, theme.Name + " - " + @Utilities.GetTypeNameClass(container));
|
||||
selectableContainers.Add(container, theme.Name + " - " + @Utilities.GetTypeNameLastSegment(container, 0));
|
||||
}
|
||||
}
|
||||
return selectableContainers;
|
||||
}
|
||||
|
||||
public async Task InstallThemesAsync()
|
||||
{
|
||||
await http.GetJsonAsync<List<string>>(apiurl + "/install");
|
||||
}
|
||||
|
||||
public async Task DeleteThemeAsync(string ThemeName)
|
||||
{
|
||||
await http.DeleteAsync(apiurl + "/" + ThemeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,9 +31,9 @@ namespace Oqtane.Services
|
||||
return await http.GetJsonAsync<List<UserRole>>(apiurl);
|
||||
}
|
||||
|
||||
public async Task<List<UserRole>> GetUserRolesAsync(int UserId)
|
||||
public async Task<List<UserRole>> GetUserRolesAsync(int SiteId)
|
||||
{
|
||||
return await http.GetJsonAsync<List<UserRole>>(apiurl + "?userid=" + UserId.ToString());
|
||||
return await http.GetJsonAsync<List<UserRole>>(apiurl + "?siteid=" + SiteId.ToString());
|
||||
}
|
||||
|
||||
public async Task<UserRole> GetUserRoleAsync(int UserRoleId)
|
||||
|
@ -27,9 +27,9 @@ namespace Oqtane.Services
|
||||
get { return CreateApiUrl(sitestate.Alias, NavigationManager.Uri, "User"); }
|
||||
}
|
||||
|
||||
public async Task<List<User>> GetUsersAsync(int SiteId)
|
||||
public async Task<List<User>> GetUsersAsync()
|
||||
{
|
||||
List<User> users = await http.GetJsonAsync<List<User>>(apiurl + "?siteid=" + SiteId.ToString());
|
||||
List<User> users = await http.GetJsonAsync<List<User>>(apiurl);
|
||||
return users.OrderBy(item => item.DisplayName).ToList();
|
||||
}
|
||||
|
||||
@ -45,7 +45,26 @@ namespace Oqtane.Services
|
||||
|
||||
public async Task<User> AddUserAsync(User User)
|
||||
{
|
||||
return await http.PostJsonAsync<User>(apiurl, User);
|
||||
try
|
||||
{
|
||||
return await http.PostJsonAsync<User>(apiurl, User);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<User> AddUserAsync(User User, Alias Alias)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await http.PostJsonAsync<User>(CreateApiUrl(Alias, NavigationManager.Uri, "User"), User);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<User> UpdateUserAsync(User User)
|
||||
@ -59,13 +78,13 @@ namespace Oqtane.Services
|
||||
|
||||
public async Task<User> LoginUserAsync(User User, bool SetCookie, bool IsPersistent)
|
||||
{
|
||||
return await http.PostJsonAsync<User>(apiurl + "/login?setcookie=" + SetCookie.ToString() + "&persistent =" + IsPersistent.ToString(), User);
|
||||
return await http.PostJsonAsync<User>(apiurl + "/login?setcookie=" + SetCookie.ToString() + "&persistent=" + IsPersistent.ToString(), User);
|
||||
}
|
||||
|
||||
public async Task LogoutUserAsync()
|
||||
public async Task LogoutUserAsync(User User)
|
||||
{
|
||||
// best practices recommend post is preferrable to get for logout
|
||||
await http.PostJsonAsync(apiurl + "/logout", null);
|
||||
await http.PostJsonAsync(apiurl + "/logout", User);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,4 @@
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Shared
|
||||
@using Oqtane.Modules
|
||||
@namespace Oqtane.Shared
|
||||
@namespace Oqtane.Shared
|
||||
|
||||
<CascadingValue Value="@ModuleState">
|
||||
@DynamicComponent
|
||||
@ -22,7 +19,7 @@
|
||||
{
|
||||
ModuleState = Module; // passed in from Pane component
|
||||
string container = ModuleState.ContainerType;
|
||||
if (PageState.ModuleId != -1 && PageState.Control != "" && ModuleState.UseAdminContainer)
|
||||
if (PageState.ModuleId != -1 && PageState.Action != "" && ModuleState.UseAdminContainer)
|
||||
{
|
||||
container = Constants.DefaultAdminContainer;
|
||||
}
|
||||
@ -38,7 +35,7 @@
|
||||
else
|
||||
{
|
||||
// container does not exist with type specified
|
||||
builder.OpenComponent(0, Type.GetType(Constants.ModuleMessageControl));
|
||||
builder.OpenComponent(0, Type.GetType(Constants.ModuleMessageComponent));
|
||||
builder.AddAttribute(1, "Message", "Error Loading Module Container " + container);
|
||||
builder.CloseComponent();
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Shared
|
||||
@namespace Oqtane.Shared
|
||||
@namespace Oqtane.Shared
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IInstallationService InstallationService
|
||||
@inject ISiteService SiteService
|
||||
@inject IUserService UserService
|
||||
|
||||
<div class="container">
|
||||
@ -13,7 +10,7 @@
|
||||
<img src="oqtane.png" />
|
||||
</div>
|
||||
</div>
|
||||
<hr style="width: 100%; color: gray; height: 1px; background-color:gray;" />
|
||||
<hr class="app-rule" />
|
||||
<h2 class="text-center">Database Configuration</h2>
|
||||
<div class="row">
|
||||
<div class="mx-auto text-center">
|
||||
@ -35,7 +32,7 @@
|
||||
<label for="Title" class="control-label" style="font-weight: bold">Server: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="ServerName" class="form-control" @bind="@ServerName" />
|
||||
<input type="text" class="form-control" @bind="@ServerName" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -43,7 +40,7 @@
|
||||
<label for="Title" class="control-label" style="font-weight: bold">Database: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="DatabaseName" class="form-control" @bind="@DatabaseName" />
|
||||
<input type="text" class="form-control" @bind="@DatabaseName" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -62,7 +59,7 @@
|
||||
<label for="Title" class="control-label" style="font-weight: bold">Username: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="Username" class="form-control" @bind="@Username" />
|
||||
<input type="text" class="form-control" @bind="@Username" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="@IntegratedSecurityDisplay">
|
||||
@ -70,14 +67,14 @@
|
||||
<label for="Title" class="control-label" style="font-weight: bold">Password: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="password" id="Password" class="form-control" @bind="@Password" />
|
||||
<input type="password" class="form-control" @bind="@Password" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<hr style="width: 100%; color: gray; height: 1px; background-color:gray;" />
|
||||
<hr class="app-rule" />
|
||||
<h2 class="text-center">Application Administrator</h2>
|
||||
<div class="row">
|
||||
<div class="mx-auto text-center">
|
||||
@ -85,10 +82,10 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Title" class="control-label" style="font-weight: bold">Email: </label>
|
||||
<label for="Title" class="control-label" style="font-weight: bold">Username: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="Email" class="form-control" @bind="@Email" />
|
||||
<input type="text" class="form-control" @bind="@HostUsername" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -96,7 +93,15 @@
|
||||
<label for="Title" class="control-label" style="font-weight: bold">Password: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="password" id="Email" class="form-control" @bind="@HostPassword" />
|
||||
<input type="password" class="form-control" @bind="@HostPassword" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="Title" class="control-label" style="font-weight: bold">Email: </label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" class="form-control" @bind="@HostEmail" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@ -108,7 +113,7 @@
|
||||
<button type="button" class="btn btn-success" @onclick="Install">Install Now</button><br /><br />
|
||||
@((MarkupString)@Message)
|
||||
</div>
|
||||
<div class="loading" style="@LoadingDisplay"></div>
|
||||
<div class="app-progress-indicator" style="@LoadingDisplay"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -118,18 +123,19 @@
|
||||
private string DatabaseName = "Oqtane-" + DateTime.Now.ToString("yyyyMMddHHmm");
|
||||
private string Username = "";
|
||||
private string Password = "";
|
||||
private string Email = "";
|
||||
private string HostUsername = "host";
|
||||
private string HostPassword = "";
|
||||
private string HostEmail = "";
|
||||
private string Message = "";
|
||||
|
||||
private string IntegratedSecurityDisplay = "display:none;";
|
||||
private string LoadingDisplay = "display:none;";
|
||||
private string IntegratedSecurityDisplay = "display: none;";
|
||||
private string LoadingDisplay = "display: none;";
|
||||
|
||||
private void SetIntegratedSecurity(ChangeEventArgs e)
|
||||
{
|
||||
if (Convert.ToBoolean(e.Value))
|
||||
{
|
||||
IntegratedSecurityDisplay = "display:none;";
|
||||
IntegratedSecurityDisplay = "display: none;";
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -139,7 +145,7 @@
|
||||
|
||||
private async Task Install()
|
||||
{
|
||||
if (HostPassword.Length >= 6)
|
||||
if (HostUsername != "" & HostPassword.Length >= 6 & HostEmail != "")
|
||||
{
|
||||
LoadingDisplay = "";
|
||||
StateHasChanged();
|
||||
@ -152,7 +158,7 @@
|
||||
else
|
||||
{
|
||||
connectionstring = "Data Source=" + ServerName + ";Initial Catalog=" + DatabaseName + ";";
|
||||
if (IntegratedSecurityDisplay == "display:none;")
|
||||
if (IntegratedSecurityDisplay == "display: none;")
|
||||
{
|
||||
connectionstring += "Integrated Security=SSPI;";
|
||||
}
|
||||
@ -165,13 +171,21 @@
|
||||
GenericResponse response = await InstallationService.Install(connectionstring);
|
||||
if (response.Success)
|
||||
{
|
||||
Site site = new Site();
|
||||
site.TenantId = -1; // will be populated on server
|
||||
site.Name = "Default Site";
|
||||
site.Logo = "oqtane.png";
|
||||
site.DefaultThemeType = Constants.DefaultTheme;
|
||||
site.DefaultLayoutType = Constants.DefaultLayout;
|
||||
site.DefaultContainerType = Constants.DefaultContainer;
|
||||
site = await SiteService.AddSiteAsync(site);
|
||||
|
||||
User user = new User();
|
||||
user.SiteId = 1;
|
||||
user.Username = Email;
|
||||
user.DisplayName = Email;
|
||||
user.Email = Email;
|
||||
user.IsHost = true;
|
||||
user.SiteId = site.SiteId;
|
||||
user.Username = HostUsername;
|
||||
user.Password = HostPassword;
|
||||
user.Email = HostEmail;
|
||||
user.DisplayName = HostUsername;
|
||||
user = await UserService.AddUserAsync(user);
|
||||
|
||||
NavigationManager.NavigateTo("", true);
|
||||
@ -179,12 +193,12 @@
|
||||
else
|
||||
{
|
||||
Message = "<div class=\"alert alert-danger\" role=\"alert\">" + response.Message + "</div>";
|
||||
LoadingDisplay = "display:none;";
|
||||
LoadingDisplay = "display: none;";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Message = "<div class=\"alert alert-danger\" role=\"alert\">Password Must Be 6 Characters Or Greater</div>";
|
||||
Message = "<div class=\"alert alert-danger\" role=\"alert\">Username And Email Must Be Provided And Password Must Be Greater Than 5 Characters</div>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,13 +42,13 @@ namespace Oqtane.Shared
|
||||
}
|
||||
}
|
||||
|
||||
public Task AddCSS(string filename)
|
||||
public Task IncludeCSS(string id, string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
jsRuntime.InvokeAsync<string>(
|
||||
"interop.addCSS",
|
||||
filename);
|
||||
"interop.includeCSS",
|
||||
id, url);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
catch
|
||||
@ -86,6 +86,20 @@ namespace Oqtane.Shared
|
||||
}
|
||||
}
|
||||
|
||||
public ValueTask<string[]> GetFiles(string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
return jsRuntime.InvokeAsync<string[]>(
|
||||
"interop.getFiles",
|
||||
name);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new ValueTask<string[]>(Task.FromResult(new string[0]));
|
||||
}
|
||||
}
|
||||
|
||||
public Task UploadFiles(string posturl, string folder, string name)
|
||||
{
|
||||
try
|
||||
|
@ -1,9 +1,14 @@
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Shared
|
||||
@using Oqtane.Modules
|
||||
@namespace Oqtane.Shared
|
||||
@namespace Oqtane.Shared
|
||||
|
||||
@DynamicComponent
|
||||
<ModuleMessage Message="@message" Type="MessageType.Error" />
|
||||
<CascadingValue Value="this">
|
||||
<ModuleMessage @ref="modulemessage" />
|
||||
@DynamicComponent
|
||||
</CascadingValue>
|
||||
@if (progressindicator)
|
||||
{
|
||||
<div class="app-progress-indicator"></div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[CascadingParameter]
|
||||
@ -12,17 +17,24 @@
|
||||
[CascadingParameter]
|
||||
private Module ModuleState { get; set; }
|
||||
|
||||
private ModuleMessage modulemessage { get; set; }
|
||||
string message;
|
||||
|
||||
RenderFragment DynamicComponent { get; set; }
|
||||
|
||||
bool progressindicator = false;
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
DynamicComponent = builder =>
|
||||
{
|
||||
string typename = ModuleState.ModuleType;
|
||||
if (PageState.Control == "Settings") // module settings are a core component
|
||||
{
|
||||
typename = Constants.DefaultSettingsControl;
|
||||
// check for core module actions component
|
||||
if (Constants.DefaultModuleActions.Contains(PageState.Action))
|
||||
{
|
||||
typename = Constants.DefaultModuleActionsTemplate.Replace(Constants.ActionToken, PageState.Action);
|
||||
}
|
||||
|
||||
Type moduleType = null;
|
||||
if (typename != null)
|
||||
{
|
||||
@ -35,11 +47,28 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
// module does not exist with typename specified
|
||||
builder.OpenComponent(0, Type.GetType(Constants.ModuleMessageControl));
|
||||
builder.AddAttribute(1, "Message", "Error Loading Component For Module " + ModuleState.ModuleDefinitionName);
|
||||
builder.CloseComponent();
|
||||
// module does not exist with typename specified
|
||||
message = "Module Does Not Have A Component Named " + Utilities.GetTypeNameLastSegment(typename, 0) + ".razor";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void AddModuleMessage(string message, MessageType type)
|
||||
{
|
||||
progressindicator = false;
|
||||
StateHasChanged();
|
||||
modulemessage.SetModuleMessage(message, type);
|
||||
}
|
||||
|
||||
public void ShowProgressIndicator()
|
||||
{
|
||||
progressindicator = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
public void HideProgressIndicator()
|
||||
{
|
||||
progressindicator = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
@ -18,9 +18,8 @@ namespace Oqtane.Shared
|
||||
public Uri Uri { get; set; }
|
||||
public Dictionary<string, string> QueryString { get; set; }
|
||||
public int ModuleId { get; set; }
|
||||
public string Control { get; set; }
|
||||
public string Action { get; set; }
|
||||
public bool EditMode { get; set; }
|
||||
public bool DesignMode { get; set; }
|
||||
public int Reload { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,4 @@
|
||||
@using System
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Modules
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Shared
|
||||
@using Oqtane.Security
|
||||
@using System.Linq
|
||||
@namespace Oqtane.Shared
|
||||
@namespace Oqtane.Shared
|
||||
@inject IUserService UserService
|
||||
@inject IModuleService ModuleService
|
||||
@inject IModuleDefinitionService ModuleDefinitionService
|
||||
@ -34,8 +27,8 @@
|
||||
{
|
||||
if (PageState.DesignMode && UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions) && Name != Constants.AdminPane)
|
||||
{
|
||||
paneadminborder = "pane-admin-border";
|
||||
panetitle = "<div class=\"pane-admin-title\">" + Name + " Pane</div>";
|
||||
paneadminborder = "app-pane-admin-border";
|
||||
panetitle = "<div class=\"app-pane-admin-title\">" + Name + " Pane</div>";
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -45,23 +38,24 @@
|
||||
|
||||
DynamicComponent = builder =>
|
||||
{
|
||||
if (PageState.ModuleId != -1 && PageState.Control != "")
|
||||
if (PageState.ModuleId != -1 && PageState.Action != "")
|
||||
{
|
||||
if (Name == Constants.AdminPane)
|
||||
if (Name.ToLower() == Constants.AdminPane.ToLower())
|
||||
{
|
||||
Module module = PageState.Modules.Where(item => item.ModuleId == PageState.ModuleId).FirstOrDefault();
|
||||
if (module != null)
|
||||
{
|
||||
string typename = module.ModuleType;
|
||||
if (PageState.Control == "Settings")
|
||||
// check for core module actions component
|
||||
if (Constants.DefaultModuleActions.Contains(PageState.Action))
|
||||
{
|
||||
typename = Constants.DefaultSettingsControl;
|
||||
typename = Constants.DefaultModuleActionsTemplate.Replace(Constants.ActionToken, PageState.Action);
|
||||
}
|
||||
Type moduleType = Type.GetType(typename);
|
||||
if (moduleType != null)
|
||||
{
|
||||
bool authorized = false;
|
||||
if (PageState.Control == "Settings")
|
||||
if (Constants.DefaultModuleActions.Contains(PageState.Action))
|
||||
{
|
||||
authorized = UserSecurity.IsAuthorized(PageState.User, "Edit", PageState.Page.Permissions);
|
||||
}
|
||||
@ -89,19 +83,19 @@
|
||||
}
|
||||
if (authorized)
|
||||
{
|
||||
if (PageState.Control != "Settings" && module.ControlTitle != "")
|
||||
if (!Constants.DefaultModuleActions.Contains(PageState.Action) && module.ControlTitle != "")
|
||||
{
|
||||
module.Title = module.ControlTitle;
|
||||
}
|
||||
builder.OpenComponent(0, Type.GetType(Constants.DefaultContainer));
|
||||
builder.OpenComponent(0, Type.GetType(Constants.ContainerComponent));
|
||||
builder.AddAttribute(1, "Module", module);
|
||||
builder.CloseComponent();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// module control does not exist with name specified
|
||||
}
|
||||
// module control does not exist with name specified
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -110,12 +104,12 @@
|
||||
if (PageState.ModuleId != -1)
|
||||
{
|
||||
Module module = PageState.Modules.Where(item => item.ModuleId == PageState.ModuleId).FirstOrDefault();
|
||||
if (module != null && module.Pane == Name)
|
||||
if (module != null && module.Pane.ToLower() == Name.ToLower())
|
||||
{
|
||||
// check if user is authorized to view module
|
||||
if (UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions))
|
||||
// check if user is authorized to view module
|
||||
if (UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions))
|
||||
{
|
||||
builder.OpenComponent(0, Type.GetType(Constants.DefaultContainer));
|
||||
builder.OpenComponent(0, Type.GetType(Constants.ContainerComponent));
|
||||
builder.AddAttribute(1, "Module", module);
|
||||
builder.CloseComponent();
|
||||
}
|
||||
@ -123,12 +117,12 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (Module module in PageState.Modules.Where(item => item.Pane == Name).OrderBy(x => x.Order).ToArray())
|
||||
foreach (Module module in PageState.Modules.Where(item => item.PageId == PageState.Page.PageId && item.Pane.ToLower() == Name.ToLower() && !item.IsDeleted).OrderBy(x => x.Order).ToArray())
|
||||
{
|
||||
// check if user is authorized to view module
|
||||
if (UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions))
|
||||
// check if user is authorized to view module
|
||||
if (UserSecurity.IsAuthorized(PageState.User, "View", module.Permissions))
|
||||
{
|
||||
builder.OpenComponent(0, Type.GetType(Constants.DefaultContainer));
|
||||
builder.OpenComponent(0, Type.GetType(Constants.ContainerComponent));
|
||||
builder.AddAttribute(1, "Module", module);
|
||||
builder.SetKey(module.PageModuleId);
|
||||
builder.CloseComponent();
|
||||
|
@ -1,6 +1,4 @@
|
||||
@using System
|
||||
@using Oqtane.Shared
|
||||
@namespace Oqtane.Shared
|
||||
@namespace Oqtane.Shared
|
||||
|
||||
@DynamicComponent
|
||||
|
||||
@ -22,8 +20,8 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
// layout does not exist with type specified
|
||||
}
|
||||
// layout does not exist with type specified
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,14 +1,4 @@
|
||||
@using System
|
||||
@using Oqtane.Services
|
||||
@using Oqtane.Models
|
||||
@using Oqtane.Modules
|
||||
@using System.Linq
|
||||
@using System.Collections.Generic
|
||||
@using Oqtane.Shared
|
||||
@using Oqtane.Security
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@namespace Oqtane.Shared
|
||||
@namespace Oqtane.Shared
|
||||
@inject AuthenticationStateProvider AuthenticationStateProvider
|
||||
@inject SiteState SiteState
|
||||
@inject NavigationManager NavigationManager
|
||||
@ -48,7 +38,7 @@
|
||||
{
|
||||
if (PageState != null)
|
||||
{
|
||||
builder.OpenComponent(0, Type.GetType(Constants.DefaultPage));
|
||||
builder.OpenComponent(0, Type.GetType(Constants.PageComponent));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
};
|
||||
@ -87,28 +77,44 @@
|
||||
User user;
|
||||
List<Module> modules;
|
||||
int moduleid = -1;
|
||||
string control = "";
|
||||
string action = "";
|
||||
bool editmode = false;
|
||||
bool designmode = false;
|
||||
int reload = 0;
|
||||
Reload reload = Reload.None;
|
||||
|
||||
// get Url path and querystring ( and remove anchors )
|
||||
string path = new Uri(_absoluteUri).PathAndQuery.Substring(1);
|
||||
if (path.IndexOf("#") != -1)
|
||||
{
|
||||
path = path.Substring(0, path.IndexOf("#"));
|
||||
}
|
||||
|
||||
// parse querystring and remove
|
||||
Dictionary<string, string> querystring = new Dictionary<string, string>();
|
||||
if (path.IndexOf("?") != -1)
|
||||
{
|
||||
querystring = ParseQueryString(path);
|
||||
path = path.Substring(0, path.IndexOf("?"));
|
||||
}
|
||||
if (querystring.ContainsKey("reload"))
|
||||
{
|
||||
reload = (Reload)int.Parse(querystring["reload"]);
|
||||
}
|
||||
|
||||
if (PageState != null)
|
||||
{
|
||||
reload = PageState.Reload;
|
||||
editmode = PageState.EditMode;
|
||||
designmode = PageState.DesignMode;
|
||||
}
|
||||
|
||||
if (PageState == null || reload == Constants.ReloadApplication)
|
||||
if (PageState == null || reload == Reload.Application)
|
||||
{
|
||||
moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync();
|
||||
themes = await ThemeService.GetThemesAsync();
|
||||
aliases = await AliasService.GetAliasesAsync();
|
||||
alias = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
moduledefinitions = PageState.ModuleDefinitions;
|
||||
themes = PageState.Themes;
|
||||
aliases = PageState.Aliases;
|
||||
alias = PageState.Alias;
|
||||
@ -119,9 +125,9 @@
|
||||
{
|
||||
alias = GetAlias(_absoluteUri, aliases);
|
||||
SiteState.Alias = alias; // set state for services
|
||||
reload = Constants.ReloadSite;
|
||||
reload = Reload.Site;
|
||||
}
|
||||
if (PageState == null || reload <= Constants.ReloadSite)
|
||||
if (PageState == null || reload <= Reload.Site)
|
||||
{
|
||||
site = await SiteService.GetSiteAsync(alias.SiteId);
|
||||
}
|
||||
@ -131,30 +137,17 @@
|
||||
}
|
||||
if (site != null)
|
||||
{
|
||||
if (PageState == null || reload >= Constants.ReloadSite)
|
||||
if (PageState == null || reload >= Reload.Site)
|
||||
{
|
||||
moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(site.SiteId);
|
||||
pages = await PageService.GetPagesAsync(site.SiteId);
|
||||
}
|
||||
else
|
||||
{
|
||||
moduledefinitions = PageState.ModuleDefinitions;
|
||||
pages = PageState.Pages;
|
||||
}
|
||||
|
||||
// get Url path and querystring ( and remove anchors )
|
||||
string path = new Uri(_absoluteUri).PathAndQuery.Substring(1);
|
||||
if (path.IndexOf("#") != -1)
|
||||
{
|
||||
path = path.Substring(0, path.IndexOf("#"));
|
||||
}
|
||||
|
||||
// parse querystring and remove
|
||||
Dictionary<string, string> querystring = new Dictionary<string, string>();
|
||||
if (path.IndexOf("?") != -1)
|
||||
{
|
||||
querystring = ParseQueryString(path);
|
||||
path = path.Substring(0, path.IndexOf("?"));
|
||||
}
|
||||
|
||||
// format path and remove alias
|
||||
path = path.Replace("//", "/");
|
||||
if (!path.EndsWith("/")) { path += "/"; }
|
||||
@ -166,18 +159,18 @@
|
||||
// extract admin route elements from path
|
||||
string[] segments = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
int result;
|
||||
// check if path has moduleid and control specification ie. page/moduleid/control/
|
||||
if (segments.Length >= 2 && int.TryParse(segments[segments.Length - 2], out result))
|
||||
{
|
||||
// path has moduleid and control specification ie. page/moduleid/control/
|
||||
control = segments[segments.Length - 1];
|
||||
action = segments[segments.Length - 1];
|
||||
moduleid = result;
|
||||
path = path.Replace(moduleid.ToString() + "/" + control + "/", "");
|
||||
path = path.Replace(moduleid.ToString() + "/" + action + "/", "");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (segments.Length >= 2 && int.TryParse(segments[segments.Length - 2], out result))
|
||||
// check if path has only moduleid specification ie. page/moduleid/
|
||||
if (segments.Length >= 1 && int.TryParse(segments[segments.Length - 1], out result))
|
||||
{
|
||||
// path has only moduleid specification ie. page/moduleid/
|
||||
moduleid = result;
|
||||
path = path.Replace(moduleid.ToString() + "/", "");
|
||||
}
|
||||
@ -185,7 +178,7 @@
|
||||
// remove trailing slash so it can be used as a key for Pages
|
||||
if (path.EndsWith("/")) path = path.Substring(0, path.Length - 1);
|
||||
|
||||
if (PageState == null || reload >= Constants.ReloadPage)
|
||||
if (PageState == null || reload >= Reload.Page)
|
||||
{
|
||||
page = pages.Where(item => item.Path == path).FirstOrDefault();
|
||||
}
|
||||
@ -204,13 +197,13 @@
|
||||
if (page.Path != path)
|
||||
{
|
||||
page = pages.Where(item => item.Path == path).FirstOrDefault();
|
||||
reload = Constants.ReloadPage;
|
||||
reload = Reload.Page;
|
||||
editmode = page.EditMode;
|
||||
designmode = false;
|
||||
}
|
||||
|
||||
user = null;
|
||||
if (PageState == null || reload >= Constants.ReloadPage)
|
||||
if (PageState == null || reload >= Reload.Page)
|
||||
{
|
||||
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
||||
if (authState.User.Identity.IsAuthenticated)
|
||||
@ -228,6 +221,8 @@
|
||||
// check if user is authorized to view page
|
||||
if (UserSecurity.IsAuthorized(user, "View", page.Permissions))
|
||||
{
|
||||
page = await ProcessPage(page, site, user);
|
||||
|
||||
pagestate = new PageState();
|
||||
pagestate.ModuleDefinitions = moduledefinitions;
|
||||
pagestate.Themes = themes;
|
||||
@ -240,17 +235,17 @@
|
||||
pagestate.Uri = new Uri(_absoluteUri, UriKind.Absolute);
|
||||
pagestate.QueryString = querystring;
|
||||
pagestate.ModuleId = moduleid;
|
||||
pagestate.Control = control;
|
||||
pagestate.Action = action;
|
||||
|
||||
if (PageState != null && (PageState.ModuleId != pagestate.ModuleId || PageState.Control != pagestate.Control))
|
||||
if (PageState != null && (PageState.ModuleId != pagestate.ModuleId || PageState.Action != pagestate.Action))
|
||||
{
|
||||
reload = Constants.ReloadPage;
|
||||
reload = Reload.Page;
|
||||
}
|
||||
|
||||
if (PageState == null || reload >= Constants.ReloadPage)
|
||||
if (PageState == null || reload >= Reload.Page)
|
||||
{
|
||||
modules = await ModuleService.GetModulesAsync(page.PageId);
|
||||
modules = ProcessModules(modules, moduledefinitions, pagestate.Control, page.Panes);
|
||||
modules = await ModuleService.GetModulesAsync(site.SiteId);
|
||||
modules = ProcessModules(modules, moduledefinitions, page.PageId, pagestate.ModuleId, pagestate.Action, page.Panes, site.DefaultContainerType);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -259,18 +254,22 @@
|
||||
pagestate.Modules = modules;
|
||||
pagestate.EditMode = editmode;
|
||||
pagestate.DesignMode = designmode;
|
||||
pagestate.Reload = Constants.ReloadReset;
|
||||
|
||||
OnStateChange?.Invoke(pagestate);
|
||||
}
|
||||
else
|
||||
{
|
||||
// user is not authorized to view page
|
||||
if (path != "")
|
||||
{
|
||||
NavigationManager.NavigateTo("");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// page does not exist
|
||||
NavigationManager.NavigateTo("");
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -319,15 +318,43 @@
|
||||
return querystring;
|
||||
}
|
||||
|
||||
private List<Module> ProcessModules(List<Module> modules, List<ModuleDefinition> moduledefinitions, string control, string panes)
|
||||
private async Task<Page> ProcessPage(Page page, Site site, User user)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (page.IsPersonalizable && user != null)
|
||||
{
|
||||
// load the personalized page
|
||||
page = await PageService.GetPageAsync(page.PageId, user.UserId);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(page.ThemeType))
|
||||
{
|
||||
page.ThemeType = site.DefaultThemeType;
|
||||
page.LayoutType = site.DefaultLayoutType;
|
||||
}
|
||||
Type type;
|
||||
if (!string.IsNullOrEmpty(page.LayoutType))
|
||||
{
|
||||
type = Type.GetType(page.LayoutType);
|
||||
}
|
||||
else
|
||||
{
|
||||
type = Type.GetType(page.ThemeType);
|
||||
}
|
||||
System.Reflection.PropertyInfo property = type.GetProperty("Panes");
|
||||
page.Panes = (string)property.GetValue(Activator.CreateInstance(type), null);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// error loading theme or layout
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
private List<Module> ProcessModules(List<Module> modules, List<ModuleDefinition> moduledefinitions, int pageid, int moduleid, string control, string panes, string defaultcontainertype)
|
||||
{
|
||||
ModuleDefinition moduledefinition;
|
||||
|
||||
if (control == "")
|
||||
{
|
||||
control = Constants.DefaultControl;
|
||||
}
|
||||
|
||||
Dictionary<string, int> paneindex = new Dictionary<string, int>();
|
||||
foreach (Module module in modules)
|
||||
{
|
||||
@ -336,56 +363,80 @@
|
||||
if (moduledefinition != null)
|
||||
{
|
||||
string typename = moduledefinition.ControlTypeTemplate;
|
||||
if (moduledefinition.ControlTypeRoutes != "")
|
||||
if (module.ModuleId == moduleid && control != "")
|
||||
{
|
||||
foreach (string route in moduledefinition.ControlTypeRoutes.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
// check if the module defines custom routes
|
||||
if (moduledefinition.ControlTypeRoutes != "")
|
||||
{
|
||||
if (route.StartsWith(control + "="))
|
||||
foreach (string route in moduledefinition.ControlTypeRoutes.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
typename = route.Replace(control + "=", "");
|
||||
if (route.StartsWith(control + "="))
|
||||
{
|
||||
typename = route.Replace(control + "=", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
module.ModuleType = typename.Replace(Constants.ActionToken, control);
|
||||
|
||||
// admin controls need to load additional metadata from the IModuleControl interface
|
||||
if (moduleid == module.ModuleId)
|
||||
{
|
||||
typename = module.ModuleType;
|
||||
// check for core module actions component
|
||||
if (Constants.DefaultModuleActions.Contains(control))
|
||||
{
|
||||
typename = Constants.DefaultModuleActionsTemplate.Replace(Constants.ActionToken, control);
|
||||
}
|
||||
Type moduletype = Type.GetType(typename);
|
||||
if (moduletype != null)
|
||||
{
|
||||
var moduleobject = Activator.CreateInstance(moduletype);
|
||||
module.SecurityAccessLevel = (SecurityAccessLevel)moduletype.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null);
|
||||
module.ControlTitle = (string)moduletype.GetProperty("Title").GetValue(moduleobject);
|
||||
module.Actions = (string)moduletype.GetProperty("Actions").GetValue(moduleobject);
|
||||
module.UseAdminContainer = (bool)moduletype.GetProperty("UseAdminContainer").GetValue(moduleobject);
|
||||
}
|
||||
}
|
||||
}
|
||||
module.ModuleType = typename.Replace("{Control}", control);
|
||||
|
||||
// get IModuleControl properties
|
||||
typename = module.ModuleType;
|
||||
if (control == "Settings")
|
||||
else
|
||||
{
|
||||
typename = Constants.DefaultSettingsControl;
|
||||
module.ModuleType = typename.Replace(Constants.ActionToken, Constants.DefaultAction);
|
||||
}
|
||||
Type moduletype = Type.GetType(typename);
|
||||
if (moduletype != null)
|
||||
|
||||
}
|
||||
|
||||
if (module.PageId == pageid)
|
||||
{
|
||||
// ensure module's pane exists in current page and if not, assign it to the Admin pane
|
||||
if (!panes.ToLower().Contains(module.Pane.ToLower()))
|
||||
{
|
||||
var moduleobject = Activator.CreateInstance(moduletype);
|
||||
module.SecurityAccessLevel = (SecurityAccessLevel)moduletype.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null);
|
||||
module.ControlTitle = (string)moduletype.GetProperty("Title").GetValue(moduleobject);
|
||||
module.Actions = (string)moduletype.GetProperty("Actions").GetValue(moduleobject);
|
||||
module.UseAdminContainer = (bool)moduletype.GetProperty("UseAdminContainer").GetValue(moduleobject);
|
||||
module.Pane = Constants.AdminPane;
|
||||
}
|
||||
|
||||
// calculate module position within pane
|
||||
if (paneindex.ContainsKey(module.Pane))
|
||||
{
|
||||
paneindex[module.Pane] += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
paneindex.Add(module.Pane, 0);
|
||||
}
|
||||
module.PaneModuleIndex = paneindex[module.Pane];
|
||||
}
|
||||
|
||||
// ensure module's pane exists in current page and if not, assign it to the Admin pane
|
||||
if (!panes.Contains(module.Pane))
|
||||
if (string.IsNullOrEmpty(module.ContainerType))
|
||||
{
|
||||
module.Pane = Constants.AdminPane;
|
||||
module.ContainerType = defaultcontainertype;
|
||||
}
|
||||
|
||||
// calculate module position within pane
|
||||
if (paneindex.ContainsKey(module.Pane))
|
||||
{
|
||||
paneindex[module.Pane] += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
paneindex.Add(module.Pane, 0);
|
||||
}
|
||||
module.PaneModuleIndex = paneindex[module.Pane];
|
||||
}
|
||||
|
||||
foreach (Module module in modules)
|
||||
{
|
||||
module.PaneModuleCount = paneindex[module.Pane] + 1;
|
||||
if (module.PageId == pageid)
|
||||
{
|
||||
module.PaneModuleCount = paneindex[module.Pane] + 1;
|
||||
}
|
||||
}
|
||||
return modules;
|
||||
}
|
||||
@ -414,7 +465,6 @@
|
||||
// use first alias if Uri does not exist
|
||||
alias = aliases.FirstOrDefault();
|
||||
}
|
||||
alias.Scheme = uri.Scheme;
|
||||
return alias;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
@using Oqtane.Shared
|
||||
@using Oqtane.Modules
|
||||
@namespace Oqtane.Shared
|
||||
@namespace Oqtane.Shared
|
||||
@inject IJSRuntime jsRuntime
|
||||
|
||||
@DynamicComponent
|
||||
|
||||
@ -21,8 +20,8 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
// theme does not exist with type specified
|
||||
builder.OpenComponent(0, Type.GetType(Constants.ModuleMessageControl));
|
||||
// theme does not exist with type specified
|
||||
builder.OpenComponent(0, Type.GetType(Constants.ModuleMessageComponent));
|
||||
builder.AddAttribute(1, "Message", "Error Loading Page Theme " + PageState.Page.ThemeType);
|
||||
builder.CloseComponent();
|
||||
}
|
||||
|
@ -52,6 +52,10 @@ namespace Oqtane.Client
|
||||
services.AddScoped<IUserRoleService, UserRoleService>();
|
||||
services.AddScoped<ISettingService, SettingService>();
|
||||
services.AddScoped<IFileService, FileService>();
|
||||
services.AddScoped<IPackageService, PackageService>();
|
||||
services.AddScoped<ILogService, LogService>();
|
||||
services.AddScoped<IScheduleService, ScheduleService>();
|
||||
services.AddScoped<IScheduleLogService, ScheduleLogService>();
|
||||
|
||||
// dynamically register module contexts and repository services
|
||||
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user