Compare commits
281 Commits
v0.9.1-bet
...
v1.0.1
Author | SHA1 | Date | |
---|---|---|---|
9ea5da525b | |||
fa15a5e44b | |||
35d037bbf4 | |||
e8387103f1 | |||
16965fd027 | |||
f81ef89c61 | |||
6034a161e7 | |||
ff23865711 | |||
3ac4116a84 | |||
65df0549fd | |||
04ffb079ea | |||
99d99ca6ad | |||
0659fc53b7 | |||
2febd81b4a | |||
0f814bfefe | |||
120066fce1 | |||
f4ca525bb5 | |||
5dced08f7a | |||
882412b8ff | |||
563345638a | |||
20b83c8809 | |||
7d89670930 | |||
40571bfb6e | |||
5a7a47ef27 | |||
ee5553ad8a | |||
ab8a1e7324 | |||
9e633d2d6d | |||
975e7217a5 | |||
95053d8671 | |||
61498862b5 | |||
a57e25d3d3 | |||
7cd18b1fe1 | |||
0636227284 | |||
d4d12b6f41 | |||
7c24bae753 | |||
06480d9a7e | |||
71b3b695fc | |||
db6d5d2b64 | |||
7d7e8e9e66 | |||
354382a580 | |||
288cad3d3f | |||
597a935cac | |||
1e4b2404c4 | |||
048d8f1b87 | |||
ec416a7fef | |||
c8630d7b05 | |||
42696eacbd | |||
b668a5d0ae | |||
4285603563 | |||
1c0d24ac25 | |||
4e6b4a20ef | |||
ea89cc1a64 | |||
79622819aa | |||
88e3a9adc3 | |||
f0c95c46c9 | |||
1a0e8f7e19 | |||
b5d4f8b176 | |||
8053cc0af6 | |||
134f21e29c | |||
a67330dbbb | |||
06820b9b63 | |||
f5d47a0308 | |||
937ae32a9e | |||
5124dea72c | |||
2ceeb25d0e | |||
e2732d83bd | |||
3e56e9cc04 | |||
836c4505b9 | |||
ef5ae77060 | |||
86b7fe193f | |||
3503f20255 | |||
51b69e05fb | |||
095a95a3a9 | |||
8d17153686 | |||
6efbeeb2b4 | |||
af1aab5b8d | |||
f854b948ce | |||
7b9cd39cb7 | |||
6f6f2b77d7 | |||
ed2822ac7c | |||
41348b285d | |||
5b0da056b4 | |||
2d079bdc06 | |||
aed71fbf96 | |||
4ebdf5721c | |||
99cad13890 | |||
4edb3f32f0 | |||
01a3b7ed95 | |||
c79199357e | |||
e24c6fc235 | |||
cdc4de432a | |||
5544d2bed3 | |||
aa4b00c900 | |||
c4f1d37421 | |||
c6b22d660b | |||
ec11587b28 | |||
1b7ca45d4a | |||
01491b063d | |||
4142cc63e7 | |||
20dc749d05 | |||
4144be5323 | |||
27a3ac8d1c | |||
f45cb8b069 | |||
0cc325ee95 | |||
7d21cfefc1 | |||
652d46f64a | |||
be4813d9c0 | |||
fe92d3d74f | |||
833ea9461a | |||
47a917a3df | |||
cb484665ca | |||
64b0c2f128 | |||
6402723d2a | |||
b1a007491f | |||
17ef268594 | |||
58d97dd731 | |||
ee3a4d1624 | |||
f9035f8fdf | |||
3a5b6954e3 | |||
1794d54a3f | |||
7d251b20cc | |||
0f09df13b5 | |||
73763f1623 | |||
1b2c7772ef | |||
3b2583a1bd | |||
f7470e3c5b | |||
19f8b3d429 | |||
fd249a7734 | |||
d5f3b7513d | |||
2a3b7caa9f | |||
612a820dac | |||
e80f42f1d9 | |||
8b5004c628 | |||
151e37c470 | |||
e935451d93 | |||
b0af00aa47 | |||
cbbac26881 | |||
f2230dd530 | |||
963148c639 | |||
215e52e42e | |||
945d7870c0 | |||
cc40733cff | |||
795f591da2 | |||
4cab49e022 | |||
3b685fe571 | |||
97df673609 | |||
cbcec0481a | |||
2f272ef4b6 | |||
a4ed06f2fc | |||
3339690e2a | |||
e4b37c17d8 | |||
f1f07f45c6 | |||
068803615b | |||
ddbb08ea75 | |||
6ac2b64d7d | |||
93497eb776 | |||
e1b0dbcdf7 | |||
c2ddd248e4 | |||
a4ec456205 | |||
23764d1ae4 | |||
f77a8a964f | |||
c089b90659 | |||
32cd34b090 | |||
d8fca5de20 | |||
2f8a15fb89 | |||
1495a5c017 | |||
61b1b710db | |||
24579dc4d0 | |||
066ef44773 | |||
1355233b92 | |||
dc55c5b3ec | |||
ed3f07ff61 | |||
028485b653 | |||
b43d191536 | |||
43dfad38c9 | |||
6f1e930474 | |||
1d52de53a6 | |||
3aec68d9fa | |||
4dc24f4c78 | |||
a73e088abc | |||
b61446a50a | |||
31773abb01 | |||
85c491224d | |||
19fb3120d3 | |||
35b26c7525 | |||
4154bd0988 | |||
52b2c876a4 | |||
b7eeda7562 | |||
b59e2533ea | |||
a8ec5e1265 | |||
61ff097f51 | |||
b82f69b8b0 | |||
263b045c75 | |||
a160597f6f | |||
f0fe6551dd | |||
09b17e142e | |||
b8ce634f85 | |||
1532eb7586 | |||
9b65cd0e07 | |||
b4596cb624 | |||
5e23448618 | |||
96c2a59551 | |||
6ae019336d | |||
0c236682b9 | |||
9b74262c76 | |||
a13208e65d | |||
f8ab886750 | |||
84b011224e | |||
c426302242 | |||
814e2100b2 | |||
54d4447d23 | |||
93942d7cdd | |||
0afd7d9ca4 | |||
3a19ced2d1 | |||
d5811a20e9 | |||
1b2600c6c4 | |||
f9cdc6d70c | |||
fbdf21320b | |||
96f5668a3b | |||
13adebb36c | |||
8a1e83ff7f | |||
e698ea4d36 | |||
f5ce00ae7d | |||
3cbb6e3e6e | |||
9394e77fd5 | |||
ac03afb146 | |||
51c27ae0e5 | |||
0ea4c4d723 | |||
b3dee737b4 | |||
24ca9f4ded | |||
9850e249fc | |||
5e04cb18a4 | |||
39641804f1 | |||
edc356292d | |||
78f4af6b70 | |||
e98b8801f3 | |||
caabac3e74 | |||
422f360807 | |||
6e28fa47a2 | |||
b4f3c4ae56 | |||
bafe2c6666 | |||
5eec442442 | |||
def12489e6 | |||
82429c2545 | |||
aa97dd4d0d | |||
cba5865e81 | |||
8afe8e7474 | |||
a9630e715b | |||
6824b3f1b5 | |||
1cca18c4d2 | |||
a886ae12cc | |||
560c995564 | |||
69a5077eda | |||
3efd39c74f | |||
bbcb054f7a | |||
88cf30f7c6 | |||
4c188b782d | |||
196e3d5865 | |||
6fd0efbb73 | |||
9eec0fd86b | |||
ad70128747 | |||
ee55b4e3cf | |||
53f454e370 | |||
f05c7d79e3 | |||
598b433cd2 | |||
6ac4ba4617 | |||
f4710f90c0 | |||
6f3fe8d933 | |||
da73d519d7 | |||
7f157582cc | |||
4d7ec16f36 | |||
7c814a67b3 | |||
c83496d814 | |||
83d47376cc | |||
a1449fb2dd | |||
2362faaee1 | |||
71f79bd90b | |||
7ca1f92f52 | |||
c30ee60433 | |||
e627e14233 | |||
4a6b12b6f9 |
@ -1,4 +1,5 @@
|
|||||||
@namespace Oqtane.Modules.Admin.Files
|
@namespace Oqtane.Modules.Admin.Files
|
||||||
|
@using System.IO
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IFileService FileService
|
@inject IFileService FileService
|
||||||
@ -12,7 +13,7 @@
|
|||||||
<Label For="upload" HelpText="Upload the file you want">Upload: </Label>
|
<Label For="upload" HelpText="Upload the file you want">Upload: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<FileManager UploadMultiple="true" ShowFiles="false" FolderId="@_folderId.ToString()" />
|
<FileManager UploadMultiple="true" ShowFiles="false" FolderId="@_folderId" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@ -70,19 +71,33 @@
|
|||||||
|
|
||||||
private async Task Download()
|
private async Task Download()
|
||||||
{
|
{
|
||||||
try
|
if (url == string.Empty || _folderId == -1)
|
||||||
{
|
{
|
||||||
if (url != string.Empty && _folderId != -1)
|
AddModuleMessage("You Must Enter A Url And Select A Folder", MessageType.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var filename = url.Substring(url.LastIndexOf("/", StringComparison.Ordinal) + 1);
|
||||||
|
|
||||||
|
if (!Constants.UploadableFiles.Split(',')
|
||||||
|
.Contains(Path.GetExtension(filename).ToLower().Replace(".", "")))
|
||||||
|
{
|
||||||
|
AddModuleMessage("File Could Not Be Downloaded From Url Due To Its File Extension", MessageType.Warning);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filename.IsPathOrFileValid())
|
||||||
|
{
|
||||||
|
AddModuleMessage("You Must Enter A Url With A Valid File Name", MessageType.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
await FileService.UploadFileAsync(url, _folderId);
|
await FileService.UploadFileAsync(url, _folderId);
|
||||||
await logger.LogInformation("File Downloaded Successfully From Url {Url}", url);
|
await logger.LogInformation("File Downloaded Successfully From Url {Url}", url);
|
||||||
AddModuleMessage("File Downloaded Successfully From Url", MessageType.Success);
|
AddModuleMessage("File Downloaded Successfully From Url", MessageType.Success);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
AddModuleMessage("You Must Enter A Url And Select A Folder", MessageType.Warning);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Downloading File From Url {Url} {Error}", url, ex.Message);
|
await logger.LogError(ex, "Error Downloading File From Url {Url} {Error}", url, ex.Message);
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label for="name" HelpText="Enter the file name">Name: </Label>
|
<Label for="name" HelpText="Enter the folder name">Name: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input id="name" class="form-control" @bind="@_name" />
|
<input id="name" class="form-control" @bind="@_name" />
|
||||||
@ -112,9 +112,19 @@
|
|||||||
|
|
||||||
private async Task SaveFolder()
|
private async Task SaveFolder()
|
||||||
{
|
{
|
||||||
try
|
if (_name == string.Empty || _parentId == -1)
|
||||||
{
|
{
|
||||||
if (_name != string.Empty && _parentId != -1)
|
AddModuleMessage("Folders Must Have A Parent And A Name", MessageType.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_name.IsPathOrFileValid())
|
||||||
|
{
|
||||||
|
AddModuleMessage("Folder Name Not Valid.", MessageType.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
Folder folder;
|
Folder folder;
|
||||||
if (_folderId != -1)
|
if (_folderId != -1)
|
||||||
@ -150,13 +160,15 @@
|
|||||||
folder = await FolderService.AddFolderAsync(folder);
|
folder = await FolderService.AddFolderAsync(folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (folder != null)
|
||||||
|
{
|
||||||
await FolderService.UpdateFolderOrderAsync(folder.SiteId, folder.FolderId, folder.ParentId);
|
await FolderService.UpdateFolderOrderAsync(folder.SiteId, folder.FolderId, folder.ParentId);
|
||||||
await logger.LogInformation("Folder Saved {Folder}", folder);
|
await logger.LogInformation("Folder Saved {Folder}", folder);
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddModuleMessage("Folders Must Have A Parent And A Name", MessageType.Warning);
|
AddModuleMessage("An Error Was Encountered Saving The Folder", MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
</table>
|
</table>
|
||||||
<Pager Items="@_files">
|
<Pager Items="@_files">
|
||||||
<Header>
|
<Header>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Modified</th>
|
<th>Modified</th>
|
||||||
<th>Type</th>
|
<th>Type</th>
|
||||||
|
@ -15,14 +15,14 @@ else
|
|||||||
|
|
||||||
<Pager Items="@_jobs">
|
<Pager Items="@_jobs">
|
||||||
<Header>
|
<Header>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Status</th>
|
<th>Status</th>
|
||||||
<th>Frequency</th>
|
<th>Frequency</th>
|
||||||
<th>Next Execution</th>
|
<th>Next Execution</th>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.JobId.ToString())" /></td>
|
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.JobId.ToString())" /></td>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
@namespace Oqtane.Modules.Admin.Login
|
@namespace Oqtane.Modules.Admin.Login
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IJSRuntime JsRuntime
|
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@inject IServiceProvider ServiceProvider
|
@inject IServiceProvider ServiceProvider
|
||||||
|
|
||||||
@ -96,7 +95,7 @@
|
|||||||
{
|
{
|
||||||
await logger.LogInformation("Login Successful For Username {Username}", _username);
|
await logger.LogInformation("Login Successful For Username {Username}", _username);
|
||||||
// complete the login on the server so that the cookies are set correctly on SignalR
|
// complete the login on the server so that the cookies are set correctly on SignalR
|
||||||
var interop = new Interop(JsRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
string antiforgerytoken = await interop.GetElementByName("__RequestVerificationToken");
|
string antiforgerytoken = await interop.GetElementByName("__RequestVerificationToken");
|
||||||
var fields = new { __RequestVerificationToken = antiforgerytoken, username = _username, password = _password, remember = _remember, returnurl = _returnUrl };
|
var fields = new { __RequestVerificationToken = antiforgerytoken, username = _username, password = _password, remember = _remember, returnurl = _returnUrl };
|
||||||
await interop.SubmitForm($"/{PageState.Alias.AliasId}/pages/login/", fields);
|
await interop.SubmitForm($"/{PageState.Alias.AliasId}/pages/login/", fields);
|
||||||
|
@ -49,7 +49,7 @@ else
|
|||||||
{
|
{
|
||||||
<Pager Items="@_logs">
|
<Pager Items="@_logs">
|
||||||
<Header>
|
<Header>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>Date</th>
|
<th>Date</th>
|
||||||
<th>Level</th>
|
<th>Level</th>
|
||||||
<th>Feature</th>
|
<th>Feature</th>
|
||||||
|
@ -3,8 +3,9 @@
|
|||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IModuleDefinitionService ModuleDefinitionService
|
@inject IModuleDefinitionService ModuleDefinitionService
|
||||||
@inject IModuleService ModuleService
|
@inject IModuleService ModuleService
|
||||||
|
@inject ISystemService SystemService
|
||||||
|
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="owner" HelpText="Enter the name of the organization who is developing this module. It should not contain spaces or punctuation.">Owner Name: </Label>
|
<Label For="owner" HelpText="Enter the name of the organization who is developing this module. It should not contain spaces or punctuation.">Owner Name: </Label>
|
||||||
@ -34,14 +35,25 @@
|
|||||||
<Label For="template" HelpText="Select a module template. Internal modules are created inside of the Oqtane solution. External modules are created outside of the Oqtane solution.">Template: </Label>
|
<Label For="template" HelpText="Select a module template. Internal modules are created inside of the Oqtane solution. External modules are created outside of the Oqtane solution.">Template: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="template" class="form-control" @bind="@_template">
|
<select id="template" class="form-control" @onchange="(e => TemplateChanged(e))">
|
||||||
<option value=""><Select Template></option>
|
<option value="-"><Select Template></option>
|
||||||
<option value="internal">Internal</option>
|
<option value="internal">Internal</option>
|
||||||
<option value="external">External</option>
|
<option value="external">External</option>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
@if (!string.IsNullOrEmpty(_location))
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="location" HelpText="Location where the module will be created">Location: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="module" class="form-control" @bind="@_location" readonly />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</table>
|
||||||
|
|
||||||
<button type="button" class="btn btn-success" @onclick="CreateModule">Create Module</button>
|
<button type="button" class="btn btn-success" @onclick="CreateModule">Create Module</button>
|
||||||
|
|
||||||
@ -49,7 +61,8 @@
|
|||||||
private string _owner = string.Empty;
|
private string _owner = string.Empty;
|
||||||
private string _module = string.Empty;
|
private string _module = string.Empty;
|
||||||
private string _description = string.Empty;
|
private string _description = string.Empty;
|
||||||
private string _template = string.Empty;
|
private string _template = "-";
|
||||||
|
private string _location = string.Empty;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
@ -62,9 +75,9 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(_owner) && !string.IsNullOrEmpty(_module) && !string.IsNullOrEmpty(_template))
|
if (!string.IsNullOrEmpty(_owner) && !string.IsNullOrEmpty(_module) && _template != "-")
|
||||||
{
|
{
|
||||||
var moduleDefinition = new ModuleDefinition { Owner = _owner.Replace(" ",""), Name = _module.Replace(" ", ""), Description = _description, Template = _template };
|
var moduleDefinition = new ModuleDefinition { Owner = _owner.Replace(" ", ""), Name = _module.Replace(" ", ""), Description = _description, Template = _template };
|
||||||
await ModuleDefinitionService.CreateModuleDefinitionAsync(moduleDefinition, ModuleState.ModuleId);
|
await ModuleDefinitionService.CreateModuleDefinitionAsync(moduleDefinition, ModuleState.ModuleId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -77,4 +90,35 @@
|
|||||||
await logger.LogError(ex, "Error Creating Module");
|
await logger.LogError(ex, "Error Creating Module");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void TemplateChanged(ChangeEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_location = string.Empty;
|
||||||
|
_template = (string)e.Value;
|
||||||
|
if (_template != "-")
|
||||||
|
{
|
||||||
|
Dictionary<string, string> systeminfo = await SystemService.GetSystemInfoAsync();
|
||||||
|
if (systeminfo != null)
|
||||||
|
{
|
||||||
|
string[] path = systeminfo["serverpath"].Split('\\');
|
||||||
|
if (_template == "internal")
|
||||||
|
{
|
||||||
|
_location = string.Join("\\", path, 0, path.Length - 1) + "\\Oqtane.Client\\Modules\\" + _owner + "." + _module + "s";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_location = string.Join("\\", path, 0, path.Length - 2) + "\\" + _owner + "." + _module + "s";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Getting System Info {Error}", ex.Message);
|
||||||
|
AddModuleMessage("Error Getting System Info", MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
<Header>
|
<Header>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Version</th>
|
<th>Version</th>
|
||||||
<th></th>
|
<th style="width: 1px"></th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td>@context.Name</td>
|
<td>@context.Name</td>
|
||||||
@ -35,7 +35,7 @@
|
|||||||
<Label HelpText="Upload one or more module packages. Once they are uploaded click Install to complete the installation.">Module: </Label>
|
<Label HelpText="Upload one or more module packages. Once they are uploaded click Install to complete the installation.">Module: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<FileManager Filter="nupkg" ShowFiles="false" Folder="Modules" UploadMultiple="True" />
|
<FileManager Filter="nupkg" ShowFiles="false" Folder="Modules" UploadMultiple="true" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@ -77,8 +77,10 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
ShowProgressIndicator();
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
await interop.RedirectBrowser(NavigateUrl(), 3);
|
||||||
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
|
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -14,11 +14,11 @@ else
|
|||||||
|
|
||||||
<Pager Items="@_moduleDefinitions">
|
<Pager Items="@_moduleDefinitions">
|
||||||
<Header>
|
<Header>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Version</th>
|
<th>Version</th>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.ModuleDefinitionId.ToString())" /></td>
|
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.ModuleDefinitionId.ToString())" /></td>
|
||||||
@ -54,21 +54,27 @@ else
|
|||||||
_packages = await PackageService.GetPackagesAsync("module");
|
_packages = await PackageService.GetPackagesAsync("module");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (_moduleDefinitions == null)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Loading Modules {Error}", ex.Message);
|
await logger.LogError(ex, "Error Loading Modules {Error}", ex.Message);
|
||||||
AddModuleMessage("Error Loading Modules", MessageType.Error);
|
AddModuleMessage("Error Loading Modules", MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private bool UpgradeAvailable(string moduledefinitionname, string version)
|
private bool UpgradeAvailable(string moduledefinitionname, string version)
|
||||||
{
|
{
|
||||||
var upgradeavailable = false;
|
var upgradeavailable = false;
|
||||||
|
if (_packages != null)
|
||||||
|
{
|
||||||
var package = _packages.Where(item => item.PackageId == Utilities.GetTypeName(moduledefinitionname)).FirstOrDefault();
|
var package = _packages.Where(item => item.PackageId == Utilities.GetTypeName(moduledefinitionname)).FirstOrDefault();
|
||||||
if (package != null)
|
if (package != null)
|
||||||
{
|
{
|
||||||
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0);
|
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
return upgradeavailable;
|
return upgradeavailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,9 +83,11 @@ else
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(moduledefinitionname, version, "Modules");
|
await PackageService.DownloadPackageAsync(moduledefinitionname, version, "Modules");
|
||||||
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
|
|
||||||
await logger.LogInformation("Module Downloaded {ModuleDefinitionName} {Version}", moduledefinitionname, version);
|
await logger.LogInformation("Module Downloaded {ModuleDefinitionName} {Version}", moduledefinitionname, version);
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
ShowProgressIndicator();
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
await interop.RedirectBrowser(NavigateUrl(), 3);
|
||||||
|
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -92,9 +100,10 @@ else
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
ShowProgressIndicator();
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
await interop.RedirectBrowser(NavigateUrl(), 3);
|
||||||
await ModuleDefinitionService.DeleteModuleDefinitionAsync(moduleDefinition.ModuleDefinitionId, moduleDefinition.SiteId);
|
await ModuleDefinitionService.DeleteModuleDefinitionAsync(moduleDefinition.ModuleDefinitionId, moduleDefinition.SiteId);
|
||||||
await logger.LogInformation("Module Deleted {ModuleDefinition}", moduleDefinition);
|
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -24,10 +24,10 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="container" class="form-control" @bind="@_containerType">
|
<select id="container" class="form-control" @bind="@_containerType">
|
||||||
<option value=""><Select Container></option>
|
<option value="-"><Inherit From Page Or Site></option>
|
||||||
@foreach (KeyValuePair<string, string> container in _containers)
|
@foreach (var container in _containers)
|
||||||
{
|
{
|
||||||
<option value="@container.Key">@container.Value</option>
|
<option value="@container.TypeName">@container.Name</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
@ -63,7 +63,7 @@
|
|||||||
}
|
}
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel Name="Permissions">
|
<TabPanel Name="Permissions">
|
||||||
@if (_containers != null)
|
@if (_permissions != null)
|
||||||
{
|
{
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
@ -85,12 +85,12 @@
|
|||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private Dictionary<string, string> _containers;
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
private string _title;
|
private string _title;
|
||||||
private string _containerType;
|
private string _containerType;
|
||||||
private string _allPages = "false";
|
private string _allPages = "false";
|
||||||
private string _permissionNames = "";
|
private string _permissionNames = "";
|
||||||
private string _permissions;
|
private string _permissions = null;
|
||||||
private string _pageId;
|
private string _pageId;
|
||||||
private PermissionGrid _permissionGrid;
|
private PermissionGrid _permissionGrid;
|
||||||
private Type _settingsModuleType;
|
private Type _settingsModuleType;
|
||||||
@ -105,8 +105,16 @@
|
|||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
_title = ModuleState.Title;
|
_title = ModuleState.Title;
|
||||||
_containers = ThemeService.GetContainerTypes(await ThemeService.GetThemesAsync());
|
_containers = ThemeService.GetContainerControls(await ThemeService.GetThemesAsync(), PageState.Page.ThemeType);
|
||||||
_containerType = ModuleState.ContainerType;
|
_containerType = ModuleState.ContainerType;
|
||||||
|
if (!string.IsNullOrEmpty(PageState.Page.DefaultContainerType) && _containerType == PageState.Page.DefaultContainerType)
|
||||||
|
{
|
||||||
|
_containerType = "-";
|
||||||
|
}
|
||||||
|
if (_containerType == PageState.Site.DefaultContainerType)
|
||||||
|
{
|
||||||
|
_containerType = "-";
|
||||||
|
}
|
||||||
_allPages = ModuleState.AllPages.ToString();
|
_allPages = ModuleState.AllPages.ToString();
|
||||||
_permissions = ModuleState.Permissions;
|
_permissions = ModuleState.Permissions;
|
||||||
_permissionNames = ModuleState.ModuleDefinition.PermissionNames;
|
_permissionNames = ModuleState.ModuleDefinition.PermissionNames;
|
||||||
@ -115,8 +123,8 @@
|
|||||||
_settingsModuleType = Type.GetType(ModuleState.ModuleType);
|
_settingsModuleType = Type.GetType(ModuleState.ModuleType);
|
||||||
if (_settingsModuleType != null)
|
if (_settingsModuleType != null)
|
||||||
{
|
{
|
||||||
var moduleobject = Activator.CreateInstance(_settingsModuleType);
|
var moduleobject = Activator.CreateInstance(_settingsModuleType) as IModuleControl;
|
||||||
_settingstitle = (string)_settingsModuleType.GetProperty("Title").GetValue(moduleobject, null);
|
_settingstitle = moduleobject.Title;
|
||||||
if (string.IsNullOrEmpty(_settingstitle))
|
if (string.IsNullOrEmpty(_settingstitle))
|
||||||
{
|
{
|
||||||
_settingstitle = "Other Settings";
|
_settingstitle = "Other Settings";
|
||||||
@ -136,7 +144,15 @@
|
|||||||
var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
|
var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
|
||||||
pagemodule.PageId = int.Parse(_pageId);
|
pagemodule.PageId = int.Parse(_pageId);
|
||||||
pagemodule.Title = _title;
|
pagemodule.Title = _title;
|
||||||
pagemodule.ContainerType = _containerType;
|
pagemodule.ContainerType = (_containerType != "-") ? _containerType : string.Empty;
|
||||||
|
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Page.DefaultContainerType)
|
||||||
|
{
|
||||||
|
pagemodule.ContainerType = string.Empty;
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Site.DefaultContainerType)
|
||||||
|
{
|
||||||
|
pagemodule.ContainerType = string.Empty;
|
||||||
|
}
|
||||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||||
|
|
||||||
|
@ -101,42 +101,59 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="Theme" class="form-control" @onchange="(e => ThemeChanged(e))">
|
<select id="Theme" class="form-control" @onchange="(e => ThemeChanged(e))">
|
||||||
<option value="-"><Select Theme></option>
|
<option value="-"><Inherit From Site></option>
|
||||||
@foreach (KeyValuePair<string, string> item in _themes)
|
@foreach (var theme in _themes)
|
||||||
{
|
{
|
||||||
if (item.Key == _themetype)
|
if (theme.TypeName == _themetype)
|
||||||
{
|
{
|
||||||
<option value="@item.Key" selected>@item.Value</option>
|
<option value="@theme.TypeName" selected>@theme.Name</option>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<option value="@item.Key">@item.Value</option>
|
<option value="@theme.TypeName">@theme.Name</option>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@if (_layouts.Count > 0)
|
||||||
|
{
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="Layout" HelpText="Select a layout for the page (if the selected theme supports it)">Layout: </Label>
|
<Label For="Layout" HelpText="Select a layout for the page (if the selected theme supports it)">Layout: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="Layout" class="form-control" @bind="@_layouttype">
|
<select id="Layout" class="form-control" @bind="@_layouttype">
|
||||||
<option value="-"><Select Layout></option>
|
<option value="-"><Inherit From Site></option>
|
||||||
@foreach (KeyValuePair<string, string> panelayout in _panelayouts)
|
@foreach (var layout in _layouts)
|
||||||
{
|
{
|
||||||
if (panelayout.Key == _layouttype)
|
if (layout.TypeName == _layouttype)
|
||||||
{
|
{
|
||||||
<option value="@panelayout.Key" selected>@panelayout.Value</option>
|
<option value="@(layout.TypeName)" selected>@(layout.Name)</option>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<option value="@panelayout.Key">@panelayout.Value</option>
|
<option value="@(layout.TypeName)">@(layout.Name)</option>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="defaultContainer" HelpText="Select the default container for the page">Default Container: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select id="defaultContainer" class="form-control" @bind="@_containertype">
|
||||||
|
<option value="-"><Inherit From Site></option>
|
||||||
|
@foreach (var container in _containers)
|
||||||
|
{
|
||||||
|
<option value="@container.TypeName">@container.Name</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="Icon" HelpText="Optionally provide an icon for this page which will be displayed in the site navigation">Icon: </Label>
|
<Label For="Icon" HelpText="Optionally provide an icon for this page which will be displayed in the site navigation">Icon: </Label>
|
||||||
@ -185,9 +202,10 @@
|
|||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private Dictionary<string, string> _themes;
|
|
||||||
private Dictionary<string, string> _panelayouts;
|
|
||||||
private List<Theme> _themeList;
|
private List<Theme> _themeList;
|
||||||
|
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||||
|
private List<ThemeControl> _layouts = new List<ThemeControl>();
|
||||||
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
private List<Page> _pageList;
|
private List<Page> _pageList;
|
||||||
private string _name;
|
private string _name;
|
||||||
private string _title;
|
private string _title;
|
||||||
@ -202,6 +220,7 @@
|
|||||||
private string _mode = "view";
|
private string _mode = "view";
|
||||||
private string _themetype = "-";
|
private string _themetype = "-";
|
||||||
private string _layouttype = "-";
|
private string _layouttype = "-";
|
||||||
|
private string _containertype = "-";
|
||||||
private string _icon = string.Empty;
|
private string _icon = string.Empty;
|
||||||
private string _permissions = string.Empty;
|
private string _permissions = string.Empty;
|
||||||
private PermissionGrid _permissionGrid;
|
private PermissionGrid _permissionGrid;
|
||||||
@ -216,12 +235,7 @@
|
|||||||
_pageList = PageState.Pages;
|
_pageList = PageState.Pages;
|
||||||
_children = PageState.Pages.Where(item => item.ParentId == null).ToList();
|
_children = PageState.Pages.Where(item => item.ParentId == null).ToList();
|
||||||
|
|
||||||
_themetype = PageState.Site.DefaultThemeType;
|
_themes = ThemeService.GetThemeControls(_themeList);
|
||||||
_layouttype = PageState.Site.DefaultLayoutType;
|
|
||||||
|
|
||||||
_themes = ThemeService.GetThemeTypes(_themeList);
|
|
||||||
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
|
|
||||||
|
|
||||||
_permissions = string.Empty;
|
_permissions = string.Empty;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -273,12 +287,16 @@
|
|||||||
_themetype = (string)e.Value;
|
_themetype = (string)e.Value;
|
||||||
if (_themetype != "-")
|
if (_themetype != "-")
|
||||||
{
|
{
|
||||||
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
|
_layouts = ThemeService.GetLayoutControls(_themeList, _themetype);
|
||||||
|
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_panelayouts = new Dictionary<string, string>();
|
_layouts = new List<ThemeControl>();
|
||||||
|
_containers = new List<ThemeControl>();
|
||||||
}
|
}
|
||||||
|
_layouttype = "-";
|
||||||
|
_containertype = "-";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -293,7 +311,7 @@
|
|||||||
Page page = null;
|
Page page = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (_name != string.Empty && !string.IsNullOrEmpty(_themetype) && (_panelayouts.Count == 0 || !string.IsNullOrEmpty(_layouttype)))
|
if (_name != string.Empty && !string.IsNullOrEmpty(_themetype) && (_layouts.Count == 0 || !string.IsNullOrEmpty(_layouttype)))
|
||||||
{
|
{
|
||||||
page = new Page();
|
page = new Page();
|
||||||
page.SiteId = PageState.Page.SiteId;
|
page.SiteId = PageState.Page.SiteId;
|
||||||
@ -351,16 +369,20 @@
|
|||||||
page.Url = _url;
|
page.Url = _url;
|
||||||
page.EditMode = (_mode == "edit" ? true : false);
|
page.EditMode = (_mode == "edit" ? true : false);
|
||||||
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
||||||
page.LayoutType = (_layouttype != "-") ? _layouttype : string.Empty;
|
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
|
||||||
if (page.ThemeType == PageState.Site.DefaultThemeType)
|
|
||||||
{
|
{
|
||||||
page.ThemeType = string.Empty;
|
page.ThemeType = string.Empty;
|
||||||
}
|
}
|
||||||
|
page.LayoutType = (_layouttype != "-") ? _layouttype : string.Empty;
|
||||||
if (page.LayoutType == PageState.Site.DefaultLayoutType)
|
if (!string.IsNullOrEmpty(page.LayoutType) && page.LayoutType == PageState.Site.DefaultLayoutType)
|
||||||
{
|
{
|
||||||
page.LayoutType = string.Empty;
|
page.LayoutType = string.Empty;
|
||||||
}
|
}
|
||||||
|
page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
|
||||||
|
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
|
||||||
|
{
|
||||||
|
page.DefaultContainerType = string.Empty;
|
||||||
|
}
|
||||||
page.Icon = (_icon == null ? string.Empty : _icon);
|
page.Icon = (_icon == null ? string.Empty : _icon);
|
||||||
page.Permissions = _permissionGrid.GetPermissions();
|
page.Permissions = _permissionGrid.GetPermissions();
|
||||||
page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable));
|
page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable));
|
||||||
|
@ -112,42 +112,59 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="Theme" class="form-control" @onchange="(e => ThemeChanged(e))">
|
<select id="Theme" class="form-control" @onchange="(e => ThemeChanged(e))">
|
||||||
<option value="-"><Select Theme></option>
|
<option value="-"><Inherit From Site></option>
|
||||||
@foreach (KeyValuePair<string, string> item in _themes)
|
@foreach (var theme in _themes)
|
||||||
{
|
{
|
||||||
if (item.Key == _themetype)
|
if (theme.TypeName == _themetype)
|
||||||
{
|
{
|
||||||
<option value="@item.Key" selected>@item.Value</option>
|
<option value="@theme.TypeName" selected>@theme.Name</option>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<option value="@item.Key">@item.Value</option>
|
<option value="@theme.TypeName">@theme.Name</option>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@if (_layouts.Count > 0)
|
||||||
|
{
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="Layout" HelpText="Select a layout for the page (if the selected theme supports it)">Layout: </Label>
|
<Label For="Layout" HelpText="Select a layout for the page (if the selected theme supports it)">Layout: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="Layout" class="form-control" @bind="@_layouttype">
|
<select id="Layout" class="form-control" @bind="@_layouttype">
|
||||||
<option value="-"><Select Layout></option>
|
<option value="-"><Inherit From Site></option>
|
||||||
@foreach (KeyValuePair<string, string> panelayout in _panelayouts)
|
@foreach (var layout in _layouts)
|
||||||
{
|
{
|
||||||
if (panelayout.Key == _layouttype)
|
if (layout.TypeName == _layouttype)
|
||||||
{
|
{
|
||||||
<option value="@panelayout.Key" selected>@panelayout.Value</option>
|
<option value="@(layout.TypeName)" selected>@(layout.Name)</option>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<option value="@panelayout.Key">@panelayout.Value</option>
|
<option value="@(layout.TypeName)">@(layout.Name)</option>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="defaultContainer" HelpText="Select the default container for the page">Default Container: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select id="defaultContainer" class="form-control" @bind="@_containertype">
|
||||||
|
<option value="-"><Inherit From Site></option>
|
||||||
|
@foreach (var container in _containers)
|
||||||
|
{
|
||||||
|
<option value="@container.TypeName">@container.Name</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="Icon" HelpText="Optionally provide an icon for this page which will be displayed in the site navigation">Icon: </Label>
|
<Label For="Icon" HelpText="Optionally provide an icon for this page which will be displayed in the site navigation">Icon: </Label>
|
||||||
@ -185,6 +202,8 @@
|
|||||||
}
|
}
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel Name="Permissions">
|
<TabPanel Name="Permissions">
|
||||||
|
@if (_permissions != null)
|
||||||
|
{
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
@ -192,15 +211,17 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
}
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</TabStrip>
|
</TabStrip>
|
||||||
<button type="button" class="btn btn-success" @onclick="SavePage">Save</button>
|
<button type="button" class="btn btn-success" @onclick="SavePage">Save</button>
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private Dictionary<string, string> _themes;
|
|
||||||
private Dictionary<string, string> _panelayouts;
|
|
||||||
private List<Theme> _themeList;
|
private List<Theme> _themeList;
|
||||||
|
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||||
|
private List<ThemeControl> _layouts = new List<ThemeControl>();
|
||||||
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
private List<Page> _pageList;
|
private List<Page> _pageList;
|
||||||
private int _pageId;
|
private int _pageId;
|
||||||
private string _name;
|
private string _name;
|
||||||
@ -217,8 +238,9 @@
|
|||||||
private string _mode;
|
private string _mode;
|
||||||
private string _themetype = "-";
|
private string _themetype = "-";
|
||||||
private string _layouttype = "-";
|
private string _layouttype = "-";
|
||||||
|
private string _containertype = "-";
|
||||||
private string _icon;
|
private string _icon;
|
||||||
private string _permissions;
|
private string _permissions = null;
|
||||||
private string _createdby;
|
private string _createdby;
|
||||||
private DateTime _createdon;
|
private DateTime _createdon;
|
||||||
private string _modifiedby;
|
private string _modifiedby;
|
||||||
@ -236,11 +258,11 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_themeList = await ThemeService.GetThemesAsync();
|
|
||||||
_pageList = PageState.Pages;
|
_pageList = PageState.Pages;
|
||||||
_children = PageState.Pages.Where(item => item.ParentId == null).ToList();
|
_children = PageState.Pages.Where(item => item.ParentId == null).ToList();
|
||||||
|
|
||||||
_themes = ThemeService.GetThemeTypes(_themeList);
|
_themeList = await ThemeService.GetThemesAsync();
|
||||||
|
_themes = ThemeService.GetThemeControls(_themeList);
|
||||||
|
|
||||||
_pageId = Int32.Parse(PageState.QueryString["id"]);
|
_pageId = Int32.Parse(PageState.QueryString["id"]);
|
||||||
var page = PageState.Pages.FirstOrDefault(item => item.PageId == _pageId);
|
var page = PageState.Pages.FirstOrDefault(item => item.PageId == _pageId);
|
||||||
@ -270,16 +292,22 @@
|
|||||||
_ispersonalizable = page.IsPersonalizable.ToString();
|
_ispersonalizable = page.IsPersonalizable.ToString();
|
||||||
_mode = (page.EditMode) ? "edit" : "view";
|
_mode = (page.EditMode) ? "edit" : "view";
|
||||||
_themetype = page.ThemeType;
|
_themetype = page.ThemeType;
|
||||||
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
|
|
||||||
_layouttype = page.LayoutType;
|
|
||||||
if (_themetype == PageState.Site.DefaultThemeType)
|
if (_themetype == PageState.Site.DefaultThemeType)
|
||||||
{
|
{
|
||||||
_themetype = "-";
|
_themetype = "-";
|
||||||
}
|
}
|
||||||
|
_layouts = ThemeService.GetLayoutControls(_themeList, page.ThemeType);
|
||||||
|
_layouttype = page.LayoutType;
|
||||||
if (_layouttype == PageState.Site.DefaultLayoutType)
|
if (_layouttype == PageState.Site.DefaultLayoutType)
|
||||||
{
|
{
|
||||||
_layouttype = "-";
|
_layouttype = "-";
|
||||||
}
|
}
|
||||||
|
_containers = ThemeService.GetContainerControls(_themeList, page.ThemeType);
|
||||||
|
_containertype = page.DefaultContainerType;
|
||||||
|
if (string.IsNullOrEmpty(_containertype))
|
||||||
|
{
|
||||||
|
_containertype = "-";
|
||||||
|
}
|
||||||
_icon = page.Icon;
|
_icon = page.Icon;
|
||||||
_permissions = page.Permissions;
|
_permissions = page.Permissions;
|
||||||
_createdby = page.CreatedBy;
|
_createdby = page.CreatedBy;
|
||||||
@ -347,12 +375,16 @@
|
|||||||
_themetype = (string)e.Value;
|
_themetype = (string)e.Value;
|
||||||
if (_themetype != "-")
|
if (_themetype != "-")
|
||||||
{
|
{
|
||||||
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
|
_layouts = ThemeService.GetLayoutControls(_themeList, _themetype);
|
||||||
|
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_panelayouts = new Dictionary<string, string>();
|
_layouts = new List<ThemeControl>();
|
||||||
|
_containers = new List<ThemeControl>();
|
||||||
}
|
}
|
||||||
|
_layouttype = "-";
|
||||||
|
_containertype = "-";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -426,15 +458,20 @@
|
|||||||
page.Url = _url;
|
page.Url = _url;
|
||||||
page.EditMode = (_mode == "edit");
|
page.EditMode = (_mode == "edit");
|
||||||
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
||||||
page.LayoutType = (_layouttype != "-") ? _layouttype : string.Empty;
|
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
|
||||||
if (page.ThemeType == PageState.Site.DefaultThemeType)
|
|
||||||
{
|
{
|
||||||
page.ThemeType = string.Empty;
|
page.ThemeType = string.Empty;
|
||||||
}
|
}
|
||||||
if (page.LayoutType == PageState.Site.DefaultLayoutType)
|
page.LayoutType = (_layouttype != "-") ? _layouttype : string.Empty;
|
||||||
|
if (!string.IsNullOrEmpty(page.LayoutType) && page.LayoutType == PageState.Site.DefaultLayoutType)
|
||||||
{
|
{
|
||||||
page.LayoutType = string.Empty;
|
page.LayoutType = string.Empty;
|
||||||
}
|
}
|
||||||
|
page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
|
||||||
|
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
|
||||||
|
{
|
||||||
|
page.DefaultContainerType = string.Empty;
|
||||||
|
}
|
||||||
page.Icon = _icon ?? string.Empty;
|
page.Icon = _icon ?? string.Empty;
|
||||||
page.Permissions = _permissionGrid.GetPermissions();
|
page.Permissions = _permissionGrid.GetPermissions();
|
||||||
page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable));
|
page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable));
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
<Pager Items="@PageState.Pages.Where(item => !item.IsDeleted)">
|
<Pager Items="@PageState.Pages.Where(item => !item.IsDeleted)">
|
||||||
<Header>
|
<Header>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
|
@ -12,8 +12,8 @@ else
|
|||||||
|
|
||||||
<Pager Items="@_profiles">
|
<Pager Items="@_profiles">
|
||||||
<Header>
|
<Header>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
{
|
{
|
||||||
<Pager Items="@_pages">
|
<Pager Items="@_pages">
|
||||||
<Header>
|
<Header>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Deleted By</th>
|
<th>Deleted By</th>
|
||||||
<th>Deleted On</th>
|
<th>Deleted On</th>
|
||||||
@ -42,8 +42,8 @@
|
|||||||
{
|
{
|
||||||
<Pager Items="@_modules">
|
<Pager Items="@_modules">
|
||||||
<Header>
|
<Header>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>Page</th>
|
<th>Page</th>
|
||||||
<th>Module</th>
|
<th>Module</th>
|
||||||
<th>Deleted By</th>
|
<th>Deleted By</th>
|
||||||
|
@ -12,9 +12,9 @@ else
|
|||||||
|
|
||||||
<Pager Items="@_roles">
|
<Pager Items="@_roles">
|
||||||
<Header>
|
<Header>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
<Label For="logo" HelpText="Upload a logo for the site">Logo: </Label>
|
<Label For="logo" HelpText="Upload a logo for the site">Logo: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<FileManager FileId="@_logofileid.ToString()" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
|
<FileManager FileId="@_logofileid" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -47,7 +47,7 @@
|
|||||||
<Label For="favicon" HelpText="Select Your default icon">Favicon: </Label>
|
<Label For="favicon" HelpText="Select Your default icon">Favicon: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<FileManager FileId="@_faviconfileid.ToString()" Filter="ico" @ref="_faviconfilemanager" />
|
<FileManager FileId="@_faviconfileid" Filter="ico" @ref="_faviconfilemanager" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -56,45 +56,48 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="defaultTheme" class="form-control" @onchange="(e => ThemeChanged(e))">
|
<select id="defaultTheme" class="form-control" @onchange="(e => ThemeChanged(e))">
|
||||||
<option value=""><Select Theme></option>
|
<option value="-"><Select Theme></option>
|
||||||
@foreach (KeyValuePair<string, string> item in _themes)
|
@foreach (var theme in _themes)
|
||||||
{
|
{
|
||||||
if (item.Key == _themetype)
|
if (theme.TypeName == _themetype)
|
||||||
{
|
{
|
||||||
<option value="@item.Key" selected>@item.Value</option>
|
<option value="@theme.TypeName" selected>@theme.Name</option>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<option value="@item.Key">@item.Value</option>
|
<option value="@theme.TypeName">@theme.Name</option>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@if (_layouts.Count > 0)
|
||||||
|
{
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="defaultLayout" HelpText="Select the sites default layout">Default Layout: </Label>
|
<Label For="defaultLayout" HelpText="Select the sites default layout">Default Layout: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="defaultLayout" class="form-control" @bind="@_layouttype">
|
<select id="defaultLayout" class="form-control" @bind="@_layouttype">
|
||||||
<option value=""><Select Layout></option>
|
<option value="-"><Select Layout></option>
|
||||||
@foreach (KeyValuePair<string, string> panelayout in _panelayouts)
|
@foreach (var layout in _layouts)
|
||||||
{
|
{
|
||||||
<option value="@panelayout.Key">@panelayout.Value</option>
|
<option value="@(layout.TypeName)">@(layout.Name)</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="defaultContainer" HelpText="Select the default container for the site">Default Container: </Label>
|
<Label For="defaultContainer" HelpText="Select the default container for the site">Default Container: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="defaultContainer" class="form-control" @bind="@_containertype">
|
<select id="defaultContainer" class="form-control" @bind="@_containertype">
|
||||||
<option value=""><Select Container></option>
|
<option value="-"><Select Container></option>
|
||||||
@foreach (KeyValuePair<string, string> container in _containers)
|
@foreach (var container in _containers)
|
||||||
{
|
{
|
||||||
<option value="@container.Key">@container.Value</option>
|
<option value="@container.TypeName">@container.Name</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
@ -185,7 +188,7 @@
|
|||||||
<Label For="appIcon" HelpText="Include an application icon for your PWA. It should be a PNG which is 192 X 192 pixels in dimension.">App Icon: </Label>
|
<Label For="appIcon" HelpText="Include an application icon for your PWA. It should be a PNG which is 192 X 192 pixels in dimension.">App Icon: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<FileManager FileId="@_pwaappiconfileid.ToString()" Filter="png" @ref="_pwaappiconfilemanager" />
|
<FileManager FileId="@_pwaappiconfileid" Filter="png" @ref="_pwaappiconfilemanager" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -193,7 +196,7 @@
|
|||||||
<Label For="splashIcon" HelpText="Include a splash icon for your PWA. It should be a PNG which is 512 X 512 pixels in dimension.">Splash Icon: </Label>
|
<Label For="splashIcon" HelpText="Include a splash icon for your PWA. It should be a PNG which is 512 X 512 pixels in dimension.">Splash Icon: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<FileManager FileId="@_pwasplashiconfileid.ToString()" Filter="png" @ref="_pwasplashiconfilemanager" />
|
<FileManager FileId="@_pwasplashiconfileid" Filter="png" @ref="_pwasplashiconfilemanager" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@ -208,10 +211,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private Dictionary<string, string> _themes;
|
|
||||||
private Dictionary<string, string> _panelayouts;
|
|
||||||
private Dictionary<string, string> _containers;
|
|
||||||
private List<Theme> _themeList;
|
private List<Theme> _themeList;
|
||||||
|
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||||
|
private List<ThemeControl> _layouts = new List<ThemeControl>();
|
||||||
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
private string _name = string.Empty;
|
private string _name = string.Empty;
|
||||||
private List<Tenant> _tenantList;
|
private List<Tenant> _tenantList;
|
||||||
private string _tenant = string.Empty;
|
private string _tenant = string.Empty;
|
||||||
@ -221,9 +224,9 @@
|
|||||||
private FileManager _logofilemanager;
|
private FileManager _logofilemanager;
|
||||||
private int _faviconfileid = -1;
|
private int _faviconfileid = -1;
|
||||||
private FileManager _faviconfilemanager;
|
private FileManager _faviconfilemanager;
|
||||||
private string _themetype;
|
private string _themetype = "-";
|
||||||
private string _layouttype;
|
private string _layouttype = "-";
|
||||||
private string _containertype;
|
private string _containertype = "-";
|
||||||
private string _allowregistration;
|
private string _allowregistration;
|
||||||
private string _smtphost = string.Empty;
|
private string _smtphost = string.Empty;
|
||||||
private string _smtpport = string.Empty;
|
private string _smtpport = string.Empty;
|
||||||
@ -271,9 +274,11 @@
|
|||||||
_faviconfileid = site.FaviconFileId.Value;
|
_faviconfileid = site.FaviconFileId.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_themes = ThemeService.GetThemeControls(_themeList);
|
||||||
_themetype = site.DefaultThemeType;
|
_themetype = site.DefaultThemeType;
|
||||||
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
|
_layouts = ThemeService.GetLayoutControls(_themeList, _themetype);
|
||||||
_layouttype = site.DefaultLayoutType;
|
_layouttype = site.DefaultLayoutType;
|
||||||
|
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
||||||
_containertype = site.DefaultContainerType;
|
_containertype = site.DefaultContainerType;
|
||||||
_allowregistration = site.AllowRegistration.ToString();
|
_allowregistration = site.AllowRegistration.ToString();
|
||||||
|
|
||||||
@ -314,9 +319,6 @@
|
|||||||
_deletedon = site.DeletedOn;
|
_deletedon = site.DeletedOn;
|
||||||
_isdeleted = site.IsDeleted.ToString();
|
_isdeleted = site.IsDeleted.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
_themes = ThemeService.GetThemeTypes(_themeList);
|
|
||||||
_containers = ThemeService.GetContainerTypes(_themeList);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -330,14 +332,18 @@
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_themetype = (string)e.Value;
|
_themetype = (string)e.Value;
|
||||||
if (_themetype != string.Empty)
|
if (_themetype != "-")
|
||||||
{
|
{
|
||||||
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
|
_layouts = ThemeService.GetLayoutControls(_themeList, _themetype);
|
||||||
|
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_panelayouts = new Dictionary<string, string>();
|
_layouts = new List<ThemeControl>();
|
||||||
|
_containers = new List<ThemeControl>();
|
||||||
}
|
}
|
||||||
|
_layouttype = "-";
|
||||||
|
_containertype = "-";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -351,7 +357,7 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (_name != string.Empty && _urls != string.Empty && !string.IsNullOrEmpty(_themetype) && (_panelayouts.Count == 0 || !string.IsNullOrEmpty(_layouttype)) && !string.IsNullOrEmpty(_containertype))
|
if (_name != string.Empty && _urls != string.Empty && _themetype != "-" && (_layouts.Count == 0 || _layouttype != "-") && _containertype != "-")
|
||||||
{
|
{
|
||||||
var unique = true;
|
var unique = true;
|
||||||
foreach (string name in _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
foreach (string name in _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
@ -376,7 +382,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
site.DefaultThemeType = _themetype;
|
site.DefaultThemeType = _themetype;
|
||||||
site.DefaultLayoutType = (_layouttype == null ? string.Empty : _layouttype);
|
site.DefaultLayoutType = (_layouttype == "-" ? string.Empty : _layouttype);
|
||||||
site.DefaultContainerType = _containertype;
|
site.DefaultContainerType = _containertype;
|
||||||
site.AllowRegistration = (_allowregistration == null ? true : Boolean.Parse(_allowregistration));
|
site.AllowRegistration = (_allowregistration == null ? true : Boolean.Parse(_allowregistration));
|
||||||
site.IsDeleted = (_isdeleted == null ? true : Boolean.Parse(_isdeleted));
|
site.IsDeleted = (_isdeleted == null ? true : Boolean.Parse(_isdeleted));
|
||||||
|
@ -38,38 +38,41 @@ else
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="defaultTheme" class="form-control" @onchange="(e => ThemeChanged(e))">
|
<select id="defaultTheme" class="form-control" @onchange="(e => ThemeChanged(e))">
|
||||||
<option value=""><Select Theme></option>
|
<option value="-"><Select Theme></option>
|
||||||
@foreach (KeyValuePair<string, string> item in _themes)
|
@foreach (var theme in _themes)
|
||||||
{
|
{
|
||||||
<option value="@item.Key">@item.Value</option>
|
<option value="@theme.TypeName">@theme.Name</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@if (_layouts.Count > 0)
|
||||||
|
{
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="defaultLayout" HelpText="Select the default layout for the site">Default Layout: </Label>
|
<Label For="defaultLayout" HelpText="Select the default layout for the site">Default Layout: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="defaultLayout" class="form-control" @bind="@_layouttype">
|
<select id="defaultLayout" class="form-control" @bind="@_layouttype">
|
||||||
<option value=""><Select Layout></option>
|
<option value="-"><Select Layout></option>
|
||||||
@foreach (KeyValuePair<string, string> panelayout in _panelayouts)
|
@foreach (var layout in _layouts)
|
||||||
{
|
{
|
||||||
<option value="@panelayout.Key">@panelayout.Value</option>
|
<option value="@(layout.TypeName)">@(layout.Name)</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="defaultContainer" HelpText="Select the default container for the site">Default Container: </Label>
|
<Label For="defaultContainer" HelpText="Select the default container for the site">Default Container: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="defaultContainer" class="form-control" @bind="@_containertype">
|
<select id="defaultContainer" class="form-control" @bind="@_containertype">
|
||||||
<option value=""><Select Container></option>
|
<option value="-"><Select Container></option>
|
||||||
@foreach (KeyValuePair<string, string> container in _containers)
|
@foreach (var container in _containers)
|
||||||
{
|
{
|
||||||
<option value="@container.Key">@container.Value</option>
|
<option value="@container.TypeName">@container.Name</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
@ -80,7 +83,7 @@ else
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="siteTemplate" class="form-control" @bind="@_sitetemplatetype">
|
<select id="siteTemplate" class="form-control" @bind="@_sitetemplatetype">
|
||||||
<option value=""><Select Site Template></option>
|
<option value="-"><Select Site Template></option>
|
||||||
@foreach (SiteTemplate siteTemplate in _siteTemplates)
|
@foreach (SiteTemplate siteTemplate in _siteTemplates)
|
||||||
{
|
{
|
||||||
<option value="@siteTemplate.TypeName">@siteTemplate.Name</option>
|
<option value="@siteTemplate.TypeName">@siteTemplate.Name</option>
|
||||||
@ -198,11 +201,11 @@ else
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private Dictionary<string, string> _themes = new Dictionary<string, string>();
|
|
||||||
private Dictionary<string, string> _panelayouts = new Dictionary<string, string>();
|
|
||||||
private Dictionary<string, string> _containers = new Dictionary<string, string>();
|
|
||||||
private List<SiteTemplate> _siteTemplates;
|
|
||||||
private List<Theme> _themeList;
|
private List<Theme> _themeList;
|
||||||
|
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||||
|
private List<ThemeControl> _layouts = new List<ThemeControl>();
|
||||||
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
|
private List<SiteTemplate> _siteTemplates;
|
||||||
private List<Tenant> _tenants;
|
private List<Tenant> _tenants;
|
||||||
private string _tenantid = "-";
|
private string _tenantid = "-";
|
||||||
|
|
||||||
@ -218,20 +221,19 @@ else
|
|||||||
|
|
||||||
private string _name = string.Empty;
|
private string _name = string.Empty;
|
||||||
private string _urls = string.Empty;
|
private string _urls = string.Empty;
|
||||||
private string _themetype = string.Empty;
|
private string _themetype = "-";
|
||||||
private string _layouttype = string.Empty;
|
private string _layouttype = "-";
|
||||||
private string _containertype = string.Empty;
|
private string _containertype = "-";
|
||||||
private string _sitetemplatetype = string.Empty;
|
private string _sitetemplatetype = "-";
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
_themeList = await ThemeService.GetThemesAsync();
|
|
||||||
_tenants = await TenantService.GetTenantsAsync();
|
_tenants = await TenantService.GetTenantsAsync();
|
||||||
_urls = PageState.Alias.Name;
|
_urls = PageState.Alias.Name;
|
||||||
_themes = ThemeService.GetThemeTypes(_themeList);
|
_themeList = await ThemeService.GetThemesAsync();
|
||||||
_containers = ThemeService.GetContainerTypes(_themeList);
|
_themes = ThemeService.GetThemeControls(_themeList);
|
||||||
_siteTemplates = await SiteTemplateService.GetSiteTemplatesAsync();
|
_siteTemplates = await SiteTemplateService.GetSiteTemplatesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,15 +265,18 @@ else
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_themetype = (string)e.Value;
|
_themetype = (string)e.Value;
|
||||||
if (_themetype != string.Empty)
|
if (_themetype != "-")
|
||||||
{
|
{
|
||||||
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
|
_layouts = ThemeService.GetLayoutControls(_themeList, _themetype);
|
||||||
|
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_panelayouts = new Dictionary<string, string>();
|
_layouts = new List<ThemeControl>();
|
||||||
|
_containers = new List<ThemeControl>();
|
||||||
}
|
}
|
||||||
|
_layouttype = "-";
|
||||||
|
_containertype = "-";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -283,7 +288,7 @@ else
|
|||||||
|
|
||||||
private async Task SaveSite()
|
private async Task SaveSite()
|
||||||
{
|
{
|
||||||
if (_tenantid != "-" && _name != string.Empty && _urls != string.Empty && !string.IsNullOrEmpty(_themetype) && (_panelayouts.Count == 0 || !string.IsNullOrEmpty(_layouttype)) && !string.IsNullOrEmpty(_containertype) && !string.IsNullOrEmpty(_sitetemplatetype))
|
if (_tenantid != "-" && _name != string.Empty && _urls != string.Empty && _themetype != "-" && (_layouts.Count == 0 || _layouttype != "-") && _containertype != "-" && _sitetemplatetype != "-")
|
||||||
{
|
{
|
||||||
var duplicates = new List<string>();
|
var duplicates = new List<string>();
|
||||||
var aliases = await AliasService.GetAliasesAsync();
|
var aliases = await AliasService.GetAliasesAsync();
|
||||||
|
@ -39,45 +39,48 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="defaultTheme" class="form-control" @onchange="(e => ThemeChanged(e))">
|
<select id="defaultTheme" class="form-control" @onchange="(e => ThemeChanged(e))">
|
||||||
<option value=""><Select Theme></option>
|
<option value="-"><Select Theme></option>
|
||||||
@foreach (KeyValuePair<string, string> item in _themes)
|
@foreach (var theme in _themes)
|
||||||
{
|
{
|
||||||
if (item.Key == _themetype)
|
if (theme.TypeName == _themetype)
|
||||||
{
|
{
|
||||||
<option value="@item.Key" selected>@item.Value</option>
|
<option value="@theme.TypeName" selected>@theme.Name</option>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<option value="@item.Key">@item.Value</option>
|
<option value="@theme.TypeName">@theme.Name</option>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@if (_layouts.Count > 0)
|
||||||
|
{
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="defaultLayout" HelpText="Select the default layout for the site">Default Layout: </Label>
|
<Label For="defaultLayout" HelpText="Select the default layout for the site">Default Layout: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="defaultLayout" class="form-control" @bind="@_layouttype">
|
<select id="defaultLayout" class="form-control" @bind="@_layouttype">
|
||||||
<option value=""><Select Layout></option>
|
<option value="-"><Select Layout></option>
|
||||||
@foreach (KeyValuePair<string, string> panelayout in _panelayouts)
|
@foreach (var layout in _layouts)
|
||||||
{
|
{
|
||||||
<option value="@panelayout.Key">@panelayout.Value</option>
|
<option value="@(layout.TypeName)">@(layout.Name)</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="defaultContainer" HelpText="Select the default container for the site">Default Container: </Label>
|
<Label For="defaultContainer" HelpText="Select the default container for the site">Default Container: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="defaultIdea" class="form-control" @bind="@_containertype">
|
<select id="defaultIdea" class="form-control" @bind="@_containertype">
|
||||||
<option value=""><Select Container></option>
|
<option value="-"><Select Container></option>
|
||||||
@foreach (KeyValuePair<string, string> container in _containers)
|
@foreach (var container in _containers)
|
||||||
{
|
{
|
||||||
<option value="@container.Key">@container.Value</option>
|
<option value="@container.TypeName">@container.Name</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
@ -103,11 +106,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private Dictionary<string, string> _themes;
|
|
||||||
private Dictionary<string, string> _panelayouts;
|
|
||||||
private Dictionary<string, string> _containers;
|
|
||||||
private Alias _alias;
|
|
||||||
private List<Theme> _themeList;
|
private List<Theme> _themeList;
|
||||||
|
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||||
|
private List<ThemeControl> _layouts = new List<ThemeControl>();
|
||||||
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
|
private Alias _alias;
|
||||||
private string _name = string.Empty;
|
private string _name = string.Empty;
|
||||||
private List<Tenant> _tenantList;
|
private List<Tenant> _tenantList;
|
||||||
private string _tenant = string.Empty;
|
private string _tenant = string.Empty;
|
||||||
@ -147,9 +150,11 @@
|
|||||||
_urls += alias.Name + "\n";
|
_urls += alias.Name + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_themes = ThemeService.GetThemeControls(_themeList);
|
||||||
_themetype = site.DefaultThemeType;
|
_themetype = site.DefaultThemeType;
|
||||||
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
|
_layouts = ThemeService.GetLayoutControls(_themeList, _themetype);
|
||||||
_layouttype = site.DefaultLayoutType;
|
_layouttype = site.DefaultLayoutType;
|
||||||
|
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
||||||
_containertype = site.DefaultContainerType;
|
_containertype = site.DefaultContainerType;
|
||||||
_createdby = site.CreatedBy;
|
_createdby = site.CreatedBy;
|
||||||
_createdon = site.CreatedOn;
|
_createdon = site.CreatedOn;
|
||||||
@ -159,9 +164,6 @@
|
|||||||
_deletedon = site.DeletedOn;
|
_deletedon = site.DeletedOn;
|
||||||
_isdeleted = site.IsDeleted.ToString();
|
_isdeleted = site.IsDeleted.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
_themes = ThemeService.GetThemeTypes(_themeList);
|
|
||||||
_containers = ThemeService.GetContainerTypes(_themeList);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -175,15 +177,18 @@
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_themetype = (string)e.Value;
|
_themetype = (string)e.Value;
|
||||||
if (_themetype != string.Empty)
|
if (_themetype != "-")
|
||||||
{
|
{
|
||||||
_panelayouts = ThemeService.GetPaneLayoutTypes(_themeList, _themetype);
|
_layouts = ThemeService.GetLayoutControls(_themeList, _themetype);
|
||||||
|
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_panelayouts = new Dictionary<string, string>();
|
_layouts = new List<ThemeControl>();
|
||||||
|
_containers = new List<ThemeControl>();
|
||||||
}
|
}
|
||||||
|
_layouttype = "-";
|
||||||
|
_containertype = "-";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -197,7 +202,7 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (_name != string.Empty && _urls != string.Empty && !string.IsNullOrEmpty(_themetype) && (_panelayouts.Count == 0 || !string.IsNullOrEmpty(_layouttype)) && !string.IsNullOrEmpty(_containertype))
|
if (_name != string.Empty && _urls != string.Empty && _themetype != "-" && (_layouts.Count == 0 || _layouttype != "-") && _containertype != "-")
|
||||||
{
|
{
|
||||||
var unique = true;
|
var unique = true;
|
||||||
foreach (string name in _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
foreach (string name in _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
@ -14,8 +14,8 @@ else
|
|||||||
|
|
||||||
<Pager Items="@_sites">
|
<Pager Items="@_sites">
|
||||||
<Header>
|
<Header>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<Label For="version" HelpText="Framework Version">Framework Version: </Label>
|
<Label For="version" HelpText="Framework Version">Framework Version: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input id="version" class="form-control" @bind="@_version" disabled />
|
<input id="version" class="form-control" @bind="@_version" readonly />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -16,7 +16,7 @@
|
|||||||
<Label For="runtime" HelpText="Blazor Runtime (Server or WebAssembly)">Blazor Runtime: </Label>
|
<Label For="runtime" HelpText="Blazor Runtime (Server or WebAssembly)">Blazor Runtime: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input id="runtime" class="form-control" @bind="@_runtime" disabled />
|
<input id="runtime" class="form-control" @bind="@_runtime" readonly />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -24,7 +24,7 @@
|
|||||||
<Label For="clrversion" HelpText="Common Language Runtime Version">CLR Version: </Label>
|
<Label For="clrversion" HelpText="Common Language Runtime Version">CLR Version: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input id="clrversion" class="form-control" @bind="@_clrversion" disabled />
|
<input id="clrversion" class="form-control" @bind="@_clrversion" readonly />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -32,7 +32,7 @@
|
|||||||
<Label For="osversion" HelpText="Operating System Version">OS Version: </Label>
|
<Label For="osversion" HelpText="Operating System Version">OS Version: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input id="osversion" class="form-control" @bind="@_osversion" disabled />
|
<input id="osversion" class="form-control" @bind="@_osversion" readonly />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -40,7 +40,7 @@
|
|||||||
<Label For="serverpath" HelpText="Server Path">Server Path: </Label>
|
<Label For="serverpath" HelpText="Server Path">Server Path: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input id="serverpath" class="form-control" @bind="@_serverpath" disabled />
|
<input id="serverpath" class="form-control" @bind="@_serverpath" readonly />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -48,7 +48,7 @@
|
|||||||
<Label For="servertime" HelpText="Server Time">Server Time: </Label>
|
<Label For="servertime" HelpText="Server Time">Server Time: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input id="servertime" class="form-control" @bind="@_servertime" disabled />
|
<input id="servertime" class="form-control" @bind="@_servertime" readonly />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
@ -11,8 +11,8 @@ else
|
|||||||
{
|
{
|
||||||
<Pager Items="@tenants">
|
<Pager Items="@tenants">
|
||||||
<Header>
|
<Header>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
@if (_packages != null)
|
@if (_packages != null)
|
||||||
{
|
{
|
||||||
<TabStrip>
|
<TabStrip>
|
||||||
@if (_packages.Count > 0)
|
@if (_packages.Count > 0)
|
||||||
{
|
{
|
||||||
<TabPanel Name="Download">
|
<TabPanel Name="Download">
|
||||||
@ -16,7 +16,7 @@
|
|||||||
<Header>
|
<Header>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Version</th>
|
<th>Version</th>
|
||||||
<th></th>
|
<th style="width: 1px;"></th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td>@context.Name</td>
|
<td>@context.Name</td>
|
||||||
@ -35,15 +35,15 @@
|
|||||||
<Label HelpText="Upload one or more theme packages. Once they are uploaded click Install to complete the installation.">Theme: </Label>
|
<Label HelpText="Upload one or more theme packages. Once they are uploaded click Install to complete the installation.">Theme: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<FileManager Filter="nupkg" ShowFiles="false" Folder="Themes" UploadMultiple="True" />
|
<FileManager Filter="nupkg" ShowFiles="false" Folder="Themes" UploadMultiple="@true" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</TabStrip>
|
</TabStrip>
|
||||||
|
|
||||||
<button type="button" class="btn btn-success" @onclick="InstallThemes">Install</button>
|
<button type="button" class="btn btn-success" @onclick="InstallThemes">Install</button>
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
@ -77,8 +77,10 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
ShowProgressIndicator();
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
await interop.RedirectBrowser(NavigateUrl(), 3);
|
||||||
await ThemeService.InstallThemesAsync();
|
await ThemeService.InstallThemesAsync();
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -101,4 +103,4 @@
|
|||||||
AddModuleMessage("Error Downloading Theme", MessageType.Error);
|
AddModuleMessage("Error Downloading Theme", MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
@namespace Oqtane.Modules.Admin.Themes
|
@namespace Oqtane.Modules.Admin.Themes
|
||||||
|
@using System.Net
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IThemeService ThemeService
|
@inject IThemeService ThemeService
|
||||||
@inject IPackageService PackageService
|
@inject IPackageService PackageService
|
||||||
|
|
||||||
@if (themes == null)
|
@if (_themes == null)
|
||||||
{
|
{
|
||||||
<p><em>Loading...</em></p>
|
<p><em>Loading...</em></p>
|
||||||
}
|
}
|
||||||
@ -12,14 +13,16 @@ else
|
|||||||
{
|
{
|
||||||
<ActionLink Action="Add" Text="Install Theme" />
|
<ActionLink Action="Add" Text="Install Theme" />
|
||||||
|
|
||||||
<Pager Items="@themes">
|
<Pager Items="@_themes">
|
||||||
<Header>
|
<Header>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>Name</th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>Version</th>
|
<th scope="col">Name</th>
|
||||||
|
<th scope="col">Version</th>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
|
<td><ActionLink Action="View" Parameters="@($"name=" + WebUtility.UrlEncode(context.ThemeName))" /></td>
|
||||||
<td>
|
<td>
|
||||||
@if (context.AssemblyName != "Oqtane.Client")
|
@if (context.AssemblyName != "Oqtane.Client")
|
||||||
{
|
{
|
||||||
@ -34,46 +37,79 @@ else
|
|||||||
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadTheme(context.ThemeName, context.Version))>Upgrade</button>
|
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadTheme(context.ThemeName, context.Version))>Upgrade</button>
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
|
<td></td>
|
||||||
</Row>
|
</Row>
|
||||||
</Pager>
|
</Pager>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<Theme> themes;
|
private List<Theme> _themes;
|
||||||
private List<Package> packages;
|
private List<Package> _packages;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
themes = await ThemeService.GetThemesAsync();
|
try
|
||||||
packages = await PackageService.GetPackagesAsync("module");
|
{
|
||||||
|
_themes = await ThemeService.GetThemesAsync();
|
||||||
|
_packages = await PackageService.GetPackagesAsync("theme");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (_themes == null)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Loading Themes {Error}", ex.Message);
|
||||||
|
AddModuleMessage("Error Loading Themes", MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool UpgradeAvailable(string themename, string version)
|
private bool UpgradeAvailable(string themename, string version)
|
||||||
{
|
{
|
||||||
var upgradeavailable = false;
|
var upgradeavailable = false;
|
||||||
var package = packages.Where(item => item.PackageId == Utilities.GetTypeName(themename)).FirstOrDefault();
|
if (_packages != null)
|
||||||
|
{
|
||||||
|
var package = _packages.Where(item => item.PackageId == Utilities.GetTypeName(themename)).FirstOrDefault();
|
||||||
if (package != null)
|
if (package != null)
|
||||||
{
|
{
|
||||||
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0);
|
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return upgradeavailable;
|
return upgradeavailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DownloadTheme(string themename, string version)
|
private async Task DownloadTheme(string themename, string version)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(themename, version, "Themes");
|
await PackageService.DownloadPackageAsync(themename, version, "Themes");
|
||||||
await logger.LogInformation("Theme Downloaded {ThemeName} {Version}", themename, version);
|
await logger.LogInformation("Theme Downloaded {ThemeName} {Version}", themename, version);
|
||||||
|
ShowProgressIndicator();
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
await interop.RedirectBrowser(NavigateUrl(), 3);
|
||||||
await ThemeService.InstallThemesAsync();
|
await ThemeService.InstallThemesAsync();
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Downloading Theme {ThemeName} {Version} {Error}", themename, version, ex.Message);
|
||||||
|
AddModuleMessage("Error Downloading Theme", MessageType.Error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DeleteTheme(Theme Theme)
|
private async Task DeleteTheme(Theme Theme)
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ShowProgressIndicator();
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
await interop.RedirectBrowser(NavigateUrl(), 3);
|
||||||
await ThemeService.DeleteThemeAsync(Theme.ThemeName);
|
await ThemeService.DeleteThemeAsync(Theme.ThemeName);
|
||||||
await logger.LogInformation("Theme Deleted {Theme}", Theme);
|
}
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Deleting Theme {Theme} {Error}", Theme, ex.Message);
|
||||||
|
AddModuleMessage("Error Deleting Theme", MessageType.Error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
101
Oqtane.Client/Modules/Admin/Themes/View.razor
Normal file
101
Oqtane.Client/Modules/Admin/Themes/View.razor
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
@namespace Oqtane.Modules.Admin.Themes
|
||||||
|
@using System.Net
|
||||||
|
@inherits ModuleBase
|
||||||
|
@inject IThemeService ThemeService
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
|
<table class="table table-borderless">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="name" HelpText="The name of the theme">Name: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="name" class="form-control" @bind="@_name" disabled />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="themename" HelpText="The internal name of the module">Internal Name: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="themename" class="form-control" @bind="@_themeName" disabled />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="version" HelpText="The version of the thene">Version: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="version" class="form-control" @bind="@_version" disabled />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="owner" HelpText="The owner or creator of the theme">Owner: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="owner" class="form-control" @bind="@_owner" disabled />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="url" HelpText="The reference url of the theme">Reference Url: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="url" class="form-control" @bind="@_url" disabled />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="contact" HelpText="The contact for the theme">Contact: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="contact" class="form-control" @bind="@_contact" disabled />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="license" HelpText="The license of the theme">License: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<textarea id="license" class="form-control" @bind="@_license" rows="5" disabled></textarea>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private string _themeName = "";
|
||||||
|
private string _name;
|
||||||
|
private string _version;
|
||||||
|
private string _owner = "";
|
||||||
|
private string _url = "";
|
||||||
|
private string _contact = "";
|
||||||
|
private string _license = "";
|
||||||
|
|
||||||
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_themeName = WebUtility.UrlDecode(PageState.QueryString["name"]);
|
||||||
|
var themes = await ThemeService.GetThemesAsync();
|
||||||
|
var theme = themes.FirstOrDefault(item => item.ThemeName == _themeName);
|
||||||
|
if (theme != null)
|
||||||
|
{
|
||||||
|
_name = theme.Name;
|
||||||
|
_version = theme.Version;
|
||||||
|
_owner = theme.Owner;
|
||||||
|
_url = theme.Url;
|
||||||
|
_contact = theme.Contact;
|
||||||
|
_license = theme.License;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Loading Theme {ThemeName} {Error}", _themeName, ex.Message);
|
||||||
|
AddModuleMessage("Error Loading Theme", MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
@if (_package != null)
|
@if (_package != null)
|
||||||
{
|
{
|
||||||
<TabStrip>
|
<TabStrip>
|
||||||
<TabPanel Name="Download">
|
<TabPanel Name="Download">
|
||||||
@if (_upgradeavailable)
|
@if (_upgradeavailable)
|
||||||
{
|
{
|
||||||
@ -26,13 +26,13 @@
|
|||||||
<Label HelpText="Upload a framework package and select Install to complete the installation">Framework: </Label>
|
<Label HelpText="Upload a framework package and select Install to complete the installation">Framework: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<FileManager Filter="nupkg" ShowFiles="false" Folder="Framework" />
|
<FileManager Filter="nupkg" Folder="Framework" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<button type="button" class="btn btn-success" @onclick="Upgrade">Install</button>
|
<button type="button" class="btn btn-success" @onclick="Upgrade">Install</button>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</TabStrip>
|
</TabStrip>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
@ -42,8 +42,12 @@
|
|||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
List<Package> packages = await PackageService.GetPackagesAsync("framework");
|
List<Package> packages = await PackageService.GetPackagesAsync("framework");
|
||||||
|
if (packages != null)
|
||||||
|
{
|
||||||
_package = packages.FirstOrDefault();
|
_package = packages.FirstOrDefault();
|
||||||
if (_package != null)
|
if (_package != null)
|
||||||
{
|
{
|
||||||
@ -54,17 +58,43 @@
|
|||||||
_package = new Package { Name = Constants.PackageId, Version = Constants.Version };
|
_package = new Package { Name = Constants.PackageId, Version = Constants.Version };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// can be caused by no network connection
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task Upgrade()
|
private async Task Upgrade()
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ShowProgressIndicator();
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
await interop.RedirectBrowser(NavigateUrl(), 3);
|
||||||
await InstallationService.Upgrade();
|
await InstallationService.Upgrade();
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Executing Upgrade {Error}", ex.Message);
|
||||||
|
AddModuleMessage("Error Executing Upgrade", MessageType.Error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Download(string packageid, string version)
|
private async Task Download(string packageid, string version)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(packageid, version, "Framework");
|
await PackageService.DownloadPackageAsync(packageid, version, "Framework");
|
||||||
|
ShowProgressIndicator();
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
await interop.RedirectBrowser(NavigateUrl(), 3);
|
||||||
await InstallationService.Upgrade();
|
await InstallationService.Upgrade();
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Downloading Framework {Error}", ex.Message);
|
||||||
|
AddModuleMessage("Error Downloading Framework", MessageType.Error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@namespace Oqtane.Modules.Admin.UserProfile
|
@namespace Oqtane.Modules.Admin.UserProfile
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IUserRoleService UserRoleService
|
@inject IUserService UserService
|
||||||
@inject INotificationService NotificationService
|
@inject INotificationService NotificationService
|
||||||
|
|
||||||
@if (PageState.User != null)
|
@if (PageState.User != null)
|
||||||
@ -9,19 +9,10 @@
|
|||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="to" HelpText="Select the user it is going to">To: </Label>
|
<Label For="to" HelpText="Enter the username you wish to send a message to">To: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="to" class="form-control" @bind="@userid">
|
<input id="to" class="form-control" @bind="@username" />
|
||||||
<option value="-1"><Select User></option>
|
|
||||||
@if (userroles != null)
|
|
||||||
{
|
|
||||||
foreach (UserRole userrole in userroles)
|
|
||||||
{
|
|
||||||
<option value="@userrole.UserId">@userrole.User.DisplayName</option>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -46,8 +37,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<UserRole> userroles;
|
private string username = "";
|
||||||
private string userid = "-1";
|
|
||||||
private string subject = "";
|
private string subject = "";
|
||||||
private string body = "";
|
private string body = "";
|
||||||
|
|
||||||
@ -55,42 +45,37 @@
|
|||||||
|
|
||||||
public override string Title => "Send Notification";
|
public override string Title => "Send Notification";
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
userroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId);
|
|
||||||
userroles = userroles.Where(item => item.Role.Name == Constants.RegisteredRole || item.Role.Name == Constants.HostRole)
|
|
||||||
.OrderBy(item => item.User.DisplayName).ToList();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Loading Users {Error}", ex.Message);
|
|
||||||
AddModuleMessage("Error Loading Users", MessageType.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Send()
|
private async Task Send()
|
||||||
{
|
{
|
||||||
var notification = new Notification();
|
var notification = new Notification();
|
||||||
try
|
try
|
||||||
|
{
|
||||||
|
var user = await UserService.GetUserAsync(username, PageState.Site.SiteId);
|
||||||
|
if (user != null)
|
||||||
{
|
{
|
||||||
notification.SiteId = PageState.Site.SiteId;
|
notification.SiteId = PageState.Site.SiteId;
|
||||||
notification.FromUserId = PageState.User.UserId;
|
notification.FromUserId = PageState.User.UserId;
|
||||||
notification.ToUserId = int.Parse(userid);
|
notification.FromDisplayName = PageState.User.DisplayName;
|
||||||
notification.ToEmail = "";
|
notification.FromEmail = PageState.User.Email;
|
||||||
|
notification.ToUserId = user.UserId;
|
||||||
|
notification.ToDisplayName = user.DisplayName;
|
||||||
|
notification.ToEmail = user.Email;
|
||||||
notification.Subject = subject;
|
notification.Subject = subject;
|
||||||
notification.Body = body;
|
notification.Body = body;
|
||||||
notification.ParentId = null;
|
notification.ParentId = null;
|
||||||
notification.CreatedOn = DateTime.UtcNow;
|
notification.CreatedOn = DateTime.UtcNow;
|
||||||
notification.IsDelivered = false;
|
notification.IsDelivered = false;
|
||||||
notification.DeliveredOn = null;
|
notification.DeliveredOn = null;
|
||||||
|
notification.SendOn = DateTime.UtcNow;
|
||||||
notification = await NotificationService.AddNotificationAsync(notification);
|
notification = await NotificationService.AddNotificationAsync(notification);
|
||||||
|
|
||||||
await logger.LogInformation("Notification Created {Notification}", notification);
|
await logger.LogInformation("Notification Created {Notification}", notification);
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddModuleMessage("User Does Not Exist. Please Verify That The Username Provided Is Correct.", MessageType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Adding Notification {Notification} {Error}", notification, ex.Message);
|
await logger.LogError(ex, "Error Adding Notification {Notification} {Error}", notification, ex.Message);
|
||||||
|
@ -32,7 +32,7 @@ else
|
|||||||
<label for="Name" class="control-label">Password: </label>
|
<label for="Name" class="control-label">Password: </label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="password" class="form-control" @bind="@password" />
|
<input type="password" class="form-control" @bind="@password" autocomplete="new-password" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -40,7 +40,7 @@ else
|
|||||||
<label for="Name" class="control-label">Confirm Password: </label>
|
<label for="Name" class="control-label">Confirm Password: </label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="password" class="form-control" @bind="@confirm" />
|
<input type="password" class="form-control" @bind="@confirm" autocomplete="new-password" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -64,7 +64,7 @@ else
|
|||||||
<label for="Name" class="control-label">Photo: </label>
|
<label for="Name" class="control-label">Photo: </label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<FileManager FileId="@photofileid.ToString()" @ref="filemanager" />
|
<FileManager FileId="@photofileid" @ref="filemanager" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@ -73,7 +73,7 @@ else
|
|||||||
}
|
}
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel Name="Profile">
|
<TabPanel Name="Profile">
|
||||||
@if (profiles != null)
|
@if (profiles != null && settings != null)
|
||||||
{
|
{
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
@foreach (Profile profile in profiles)
|
@foreach (Profile profile in profiles)
|
||||||
@ -111,8 +111,8 @@ else
|
|||||||
{
|
{
|
||||||
<Pager Items="@notifications">
|
<Pager Items="@notifications">
|
||||||
<Header>
|
<Header>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>From</th>
|
<th>From</th>
|
||||||
<th>Subject</th>
|
<th>Subject</th>
|
||||||
<th>Received</th>
|
<th>Received</th>
|
||||||
@ -120,13 +120,22 @@ else
|
|||||||
<Row>
|
<Row>
|
||||||
<td><ActionLink Action="View" Parameters="@($"id=" + context.NotificationId.ToString())" Security="SecurityAccessLevel.View" EditMode="false" /></td>
|
<td><ActionLink Action="View" Parameters="@($"id=" + context.NotificationId.ToString())" Security="SecurityAccessLevel.View" EditMode="false" /></td>
|
||||||
<td><ActionDialog Header="Delete Notification" Message="@("Are You Sure You Wish To Delete This Notification?")" Action="Delete" Security="SecurityAccessLevel.View" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" EditMode="false" /></td>
|
<td><ActionDialog Header="Delete Notification" Message="@("Are You Sure You Wish To Delete This Notification?")" Action="Delete" Security="SecurityAccessLevel.View" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" EditMode="false" /></td>
|
||||||
<td>@(context.FromUser == null ? "System" : context.FromUser.DisplayName)</td>
|
<td>@context.FromDisplayName</td>
|
||||||
<td>@context.Subject</td>
|
<td>@context.Subject</td>
|
||||||
<td>@context.CreatedOn</td>
|
<td>@context.CreatedOn</td>
|
||||||
</Row>
|
</Row>
|
||||||
<Detail>
|
<Detail>
|
||||||
<td colspan="2"></td>
|
<td colspan="2"></td>
|
||||||
<td colspan="3">@(context.Body.Length > 100 ? context.Body.Substring(0, 100) : context.Body)</td>
|
<td colspan="3">
|
||||||
|
@{
|
||||||
|
string input = "___";
|
||||||
|
if (context.Body.Contains(input)){
|
||||||
|
context.Body = context.Body.Split(input)[0];
|
||||||
|
context.Body = context.Body.Replace("\n", "");
|
||||||
|
context.Body = context.Body.Replace("\r", "");
|
||||||
|
} }
|
||||||
|
@(context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body)
|
||||||
|
</td>
|
||||||
</Detail>
|
</Detail>
|
||||||
</Pager>
|
</Pager>
|
||||||
}
|
}
|
||||||
@ -143,13 +152,22 @@ else
|
|||||||
<Row>
|
<Row>
|
||||||
<td><ActionLink Action="View" Parameters="@($"id=" + context.NotificationId.ToString())" Security="SecurityAccessLevel.View" EditMode="false" /></td>
|
<td><ActionLink Action="View" Parameters="@($"id=" + context.NotificationId.ToString())" Security="SecurityAccessLevel.View" EditMode="false" /></td>
|
||||||
<td><ActionDialog Header="Delete Notification" Message="@("Are You Sure You Wish To Delete This Notification?")" Action="Delete" Security="SecurityAccessLevel.View" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" EditMode="false" /></td>
|
<td><ActionDialog Header="Delete Notification" Message="@("Are You Sure You Wish To Delete This Notification?")" Action="Delete" Security="SecurityAccessLevel.View" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" EditMode="false" /></td>
|
||||||
<td>@(context.ToUser == null ? context.ToEmail : context.ToUser.DisplayName)</td>
|
<td>@context.ToDisplayName</td>
|
||||||
<td>@context.Subject</td>
|
<td>@context.Subject</td>
|
||||||
<td>@context.CreatedOn</td>
|
<td>@context.CreatedOn</td>
|
||||||
</Row>
|
</Row>
|
||||||
<Detail>
|
<Detail>
|
||||||
<td colspan="2"></td>
|
<td colspan="2"></td>
|
||||||
<td colspan="3">@(context.Body.Length > 100 ? context.Body.Substring(0, 100) : context.Body)</td>
|
<td colspan="3">
|
||||||
|
@{
|
||||||
|
string input = "___";
|
||||||
|
if (context.Body.Contains(input)){
|
||||||
|
context.Body = context.Body.Split(input)[0];
|
||||||
|
context.Body = context.Body.Replace("\n", "");
|
||||||
|
context.Body = context.Body.Replace("\r", "");
|
||||||
|
} }
|
||||||
|
@(context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body)
|
||||||
|
</td>
|
||||||
</Detail>
|
</Detail>
|
||||||
</Pager>
|
</Pager>
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@namespace Oqtane.Modules.Admin.UserProfile
|
@namespace Oqtane.Modules.Admin.UserProfile
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IUserRoleService UserRoleService
|
@inject IUserService UserService
|
||||||
@inject INotificationService NotificationService
|
@inject INotificationService NotificationService
|
||||||
|
|
||||||
@if (PageState.User != null)
|
@if (PageState.User != null)
|
||||||
@ -11,26 +11,35 @@
|
|||||||
<td>
|
<td>
|
||||||
<label class="control-label">@title: </label>
|
<label class="control-label">@title: </label>
|
||||||
</td>
|
</td>
|
||||||
|
@if (title == "From")
|
||||||
|
{
|
||||||
<td>
|
<td>
|
||||||
<select class="form-control" readonly @bind="userid">
|
<input class="form-control" @bind="@username" readonly />
|
||||||
<option value="-1"><System></option>
|
|
||||||
@if (userroles != null)
|
|
||||||
{
|
|
||||||
foreach (UserRole userrole in userroles)
|
|
||||||
{
|
|
||||||
<option value="@userrole.UserId">@userrole.User.DisplayName</option>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</td>
|
</td>
|
||||||
|
}
|
||||||
|
@if (title == "To")
|
||||||
|
{
|
||||||
|
<td>
|
||||||
|
<input class="form-control" @bind="@username" />
|
||||||
|
</td>
|
||||||
|
}
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<label class="control-label">Subject: </label>
|
<label class="control-label">Subject: </label>
|
||||||
</td>
|
</td>
|
||||||
|
@if (title == "From")
|
||||||
|
{
|
||||||
|
<td>
|
||||||
|
<input class="form-control" @bind="@subject" readonly />
|
||||||
|
</td>
|
||||||
|
}
|
||||||
|
@if (title == "To")
|
||||||
|
{
|
||||||
<td>
|
<td>
|
||||||
<input class="form-control" @bind="@subject" />
|
<input class="form-control" @bind="@subject" />
|
||||||
</td>
|
</td>
|
||||||
|
}
|
||||||
</tr>
|
</tr>
|
||||||
@if (title == "From")
|
@if (title == "From")
|
||||||
{
|
{
|
||||||
@ -39,10 +48,23 @@
|
|||||||
<label class="control-label">Date: </label>
|
<label class="control-label">Date: </label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input class="form-control" @bind="@createdon" />
|
<input class="form-control" @bind="@createdon" readonly />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
}
|
}
|
||||||
|
@if (title == "From")
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label class="control-label">Message: </label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<textarea class="form-control" @bind="@body" rows="5" readonly />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
@if (title == "To")
|
||||||
|
{
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<label class="control-label">Message: </label>
|
<label class="control-label">Message: </label>
|
||||||
@ -51,29 +73,35 @@
|
|||||||
<textarea class="form-control" @bind="@body" rows="5" />
|
<textarea class="form-control" @bind="@body" rows="5" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
}
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
@if (reply != string.Empty)
|
@if (reply != string.Empty)
|
||||||
{
|
{
|
||||||
<button type="button" class="btn btn-primary" @onclick="Send">Send</button>
|
<button type="button" class="btn btn-primary" @onclick="Send">Send</button> }
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (title == "From")
|
if (title == "From")
|
||||||
{
|
{
|
||||||
<button type="button" class="btn btn-primary" @onclick="Reply">Reply</button>
|
<button type="button" class="btn btn-primary" @onclick="Reply">Reply</button>}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<p>@reply</p>
|
@if (title == "To")
|
||||||
}
|
{
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label">Original Message </label>
|
||||||
|
<textarea class="form-control" @bind="@reply" rows="5" readonly />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private int notificationid;
|
private int notificationid;
|
||||||
private string title = string.Empty;
|
private string title = string.Empty;
|
||||||
private List<UserRole> userroles;
|
private string username = "";
|
||||||
private string userid = "-1";
|
|
||||||
private string subject = string.Empty;
|
private string subject = string.Empty;
|
||||||
private string createdon = string.Empty;
|
private string createdon = string.Empty;
|
||||||
private string body = string.Empty;
|
private string body = string.Empty;
|
||||||
@ -86,20 +114,17 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
userroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId);
|
|
||||||
userroles = userroles.Where(item => item.Role.Name == Constants.RegisteredRole || item.Role.Name == Constants.HostRole)
|
|
||||||
.OrderBy(item => item.User.DisplayName).ToList();
|
|
||||||
|
|
||||||
notificationid = Int32.Parse(PageState.QueryString["id"]);
|
notificationid = Int32.Parse(PageState.QueryString["id"]);
|
||||||
Notification notification = await NotificationService.GetNotificationAsync(notificationid);
|
Notification notification = await NotificationService.GetNotificationAsync(notificationid);
|
||||||
if (notification != null)
|
if (notification != null)
|
||||||
{
|
{
|
||||||
|
int userid = -1;
|
||||||
if (notification.ToUserId == PageState.User.UserId)
|
if (notification.ToUserId == PageState.User.UserId)
|
||||||
{
|
{
|
||||||
title = "From";
|
title = "From";
|
||||||
if (notification.FromUserId != null)
|
if (notification.FromUserId != null)
|
||||||
{
|
{
|
||||||
userid = notification.FromUserId.ToString();
|
userid = notification.FromUserId.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -107,10 +132,21 @@
|
|||||||
title = "To";
|
title = "To";
|
||||||
if (notification.ToUserId != null)
|
if (notification.ToUserId != null)
|
||||||
{
|
{
|
||||||
userid = notification.ToUserId.ToString();
|
userid = notification.ToUserId.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (userid != -1)
|
||||||
|
{
|
||||||
|
var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
username = user.Username;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (username == "")
|
||||||
|
{
|
||||||
|
username = "System";
|
||||||
|
}
|
||||||
subject = notification.Subject;
|
subject = notification.Subject;
|
||||||
createdon = notification.CreatedOn.ToString();
|
createdon = notification.CreatedOn.ToString();
|
||||||
body = notification.Body;
|
body = notification.Body;
|
||||||
@ -126,37 +162,51 @@
|
|||||||
private void Reply()
|
private void Reply()
|
||||||
{
|
{
|
||||||
title = "To";
|
title = "To";
|
||||||
|
if (!subject.Contains("RE:"))
|
||||||
|
{
|
||||||
subject = "RE: " + subject;
|
subject = "RE: " + subject;
|
||||||
|
}
|
||||||
reply = body;
|
reply = body;
|
||||||
|
body = "\n\n____________________________________________\nSent: " + createdon + "\nSubject: " + subject + "\n\n" + body;
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Send()
|
private async Task Send()
|
||||||
{
|
{
|
||||||
var notification = new Notification();
|
var notification = new Notification();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var user = await UserService.GetUserAsync(username, PageState.Site.SiteId);
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
notification.SiteId = PageState.Site.SiteId;
|
notification.SiteId = PageState.Site.SiteId;
|
||||||
notification.FromUserId = PageState.User.UserId;
|
notification.FromUserId = PageState.User.UserId;
|
||||||
notification.ToUserId = int.Parse(userid);
|
notification.FromDisplayName = PageState.User.DisplayName;
|
||||||
notification.ToEmail = string.Empty;
|
notification.FromEmail = PageState.User.Email;
|
||||||
|
notification.ToUserId = user.UserId;
|
||||||
|
notification.ToDisplayName = user.DisplayName;
|
||||||
|
notification.ToEmail = user.Email;
|
||||||
notification.Subject = subject;
|
notification.Subject = subject;
|
||||||
notification.Body = body;
|
notification.Body = body;
|
||||||
notification.ParentId = notificationid;
|
notification.ParentId = notificationid;
|
||||||
notification.CreatedOn = DateTime.UtcNow;
|
notification.CreatedOn = DateTime.UtcNow;
|
||||||
notification.IsDelivered = false;
|
notification.IsDelivered = false;
|
||||||
notification.DeliveredOn = null;
|
notification.DeliveredOn = null;
|
||||||
|
notification.SendOn = DateTime.UtcNow;
|
||||||
try
|
|
||||||
{
|
|
||||||
notification = await NotificationService.AddNotificationAsync(notification);
|
notification = await NotificationService.AddNotificationAsync(notification);
|
||||||
|
|
||||||
await logger.LogInformation("Notification Created {Notification}", notification);
|
await logger.LogInformation("Notification Created {Notification}", notification);
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddModuleMessage("User Does Not Exist. Please Verify That The Username Provided Is Correct.", MessageType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Adding Notification {Notification} {Error}", notification, ex.Message);
|
await logger.LogError(ex, "Error Adding Notification {Notification} {Error}", notification, ex.Message);
|
||||||
AddModuleMessage("Error Adding Notification", MessageType.Error);
|
AddModuleMessage("Error Adding Notification", MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ else
|
|||||||
<label class="control-label">Photo: </label>
|
<label class="control-label">Photo: </label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<FileManager FileId="@photofileid.ToString()" @ref="filemanager" />
|
<FileManager FileId="@photofileid" @ref="filemanager" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -2,40 +2,79 @@
|
|||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject IUserRoleService UserRoleService
|
@inject IUserRoleService UserRoleService
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
|
@inject ISettingService SettingService
|
||||||
|
|
||||||
@if (userroles == null)
|
@if (userroles == null)
|
||||||
{
|
{
|
||||||
<p><em>Loading...</em></p>
|
<p>
|
||||||
|
<em>Loading...</em>
|
||||||
|
</p>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<ActionLink Action="Add" Text="Add User" />
|
<ActionLink Action="Add" Text="Add User"/>
|
||||||
|
|
||||||
|
<div class="d-flex p-1">
|
||||||
|
<input class="form-control mr-4" @bind="@_search"/><button class="btn btn-outline-primary ml-1" @onclick="OnSearch">Search</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Pager Items="@userroles">
|
<Pager Items="@userroles">
|
||||||
<Header>
|
<Header>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.UserId.ToString())" /></td>
|
<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>
|
<ActionLink Action="Edit" Parameters="@($"id=" + context.UserId.ToString())"/>
|
||||||
<td><ActionLink Action="Roles" Parameters="@($"id=" + context.UserId.ToString())" /></td>
|
</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>
|
<td>@context.User.DisplayName</td>
|
||||||
</Row>
|
</Row>
|
||||||
</Pager>
|
</Pager>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
private List<UserRole> allroles;
|
||||||
private List<UserRole> userroles;
|
private List<UserRole> userroles;
|
||||||
|
private string _search;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
userroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId);
|
allroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId);
|
||||||
userroles = userroles.Where(item => item.Role.Name == Constants.RegisteredRole).ToList();
|
await LoadSettingsAsync();
|
||||||
|
userroles = Search(_search);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<UserRole> Search(string search)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_search))
|
||||||
|
{
|
||||||
|
return allroles.Where(item => item.Role.Name == Constants.RegisteredRole).ToList();
|
||||||
|
}
|
||||||
|
return allroles
|
||||||
|
.Where(item => item.Role.Name == Constants.RegisteredRole &&
|
||||||
|
(
|
||||||
|
item.User.Username.Contains(search, StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
item.User.Email.Contains(search, StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
item.User.DisplayName.Contains(search, StringComparison.OrdinalIgnoreCase)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnSearch()
|
||||||
|
{
|
||||||
|
userroles = Search(_search);
|
||||||
|
await UpdateSettingsAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DeleteUser(UserRole UserRole)
|
private async Task DeleteUser(UserRole UserRole)
|
||||||
@ -56,4 +95,20 @@ else
|
|||||||
AddModuleMessage(ex.Message, MessageType.Error);
|
AddModuleMessage(ex.Message, MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string settingSearch = "AU-search";
|
||||||
|
|
||||||
|
private async Task LoadSettingsAsync()
|
||||||
|
{
|
||||||
|
Dictionary<string, string> settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
||||||
|
_search = SettingService.GetSetting(settings, settingSearch, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdateSettingsAsync()
|
||||||
|
{
|
||||||
|
Dictionary<string, string> settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
||||||
|
SettingService.SetSetting(settings, settingSearch, _search);
|
||||||
|
await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -109,8 +109,8 @@
|
|||||||
Type moduleType = Type.GetType(typename);
|
Type moduleType = Type.GetType(typename);
|
||||||
if (moduleType != null)
|
if (moduleType != null)
|
||||||
{
|
{
|
||||||
var moduleobject = Activator.CreateInstance(moduleType);
|
var moduleobject = Activator.CreateInstance(moduleType) as IModuleControl;
|
||||||
security = (SecurityAccessLevel)moduleType.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null);
|
security = moduleobject.SecurityAccessLevel;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -52,6 +52,9 @@
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string IconName { get; set; } // optional - specifies an icon for the link - default is no icon
|
public string IconName { get; set; } // optional - specifies an icon for the link - default is no icon
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public bool IconOnly { get; set; } // optional - specifies only icon in link
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
protected override void OnParametersSet()
|
||||||
{
|
{
|
||||||
_text = Action;
|
_text = Action;
|
||||||
@ -60,6 +63,11 @@
|
|||||||
_text = Text;
|
_text = Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IconOnly && !string.IsNullOrEmpty(IconName))
|
||||||
|
{
|
||||||
|
_text = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Parameters))
|
if (!string.IsNullOrEmpty(Parameters))
|
||||||
{
|
{
|
||||||
_parameters = Parameters;
|
_parameters = Parameters;
|
||||||
@ -82,7 +90,8 @@
|
|||||||
|
|
||||||
if (!string.IsNullOrEmpty(IconName))
|
if (!string.IsNullOrEmpty(IconName))
|
||||||
{
|
{
|
||||||
_iconSpan = $"<span class=\"oi oi-{IconName}\"></span> ";
|
_iconSpan = $"<span class=\"oi oi-{IconName}\"></span>{(IconOnly?"":" ")}";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_url = EditUrl(Action, _parameters);
|
_url = EditUrl(Action, _parameters);
|
||||||
@ -101,8 +110,8 @@
|
|||||||
var moduleType = Type.GetType(typename);
|
var moduleType = Type.GetType(typename);
|
||||||
if (moduleType != null)
|
if (moduleType != null)
|
||||||
{
|
{
|
||||||
var moduleobject = Activator.CreateInstance(moduleType);
|
var moduleobject = Activator.CreateInstance(moduleType) as IModuleControl;
|
||||||
security = (SecurityAccessLevel)moduleType.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null);
|
security = moduleobject.SecurityAccessLevel;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
@namespace Oqtane.Modules.Controls
|
@namespace Oqtane.Modules.Controls
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
|
|
||||||
@attribute [OqtaneIgnore]
|
@attribute [OqtaneIgnore]
|
||||||
@inject IFolderService FolderService
|
@inject IFolderService FolderService
|
||||||
@inject IFileService FileService
|
@inject IFileService FileService
|
||||||
@inject IJSRuntime JsRuntime
|
|
||||||
|
|
||||||
@if (_folders != null)
|
@if (_folders != null)
|
||||||
{
|
{
|
||||||
<div id="@Id" class="container-fluid px-0">
|
<div id="@Id" class="container-fluid px-0">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
|
@if (ShowFolders || FolderId <= 0)
|
||||||
|
{
|
||||||
<div>
|
<div>
|
||||||
<select class="form-control" @onchange="(e => FolderChanged(e))">
|
<select class="form-control" @onchange="(e => FolderChanged(e))">
|
||||||
@if (string.IsNullOrEmpty(Folder))
|
@if (string.IsNullOrEmpty(Folder))
|
||||||
@ -18,7 +20,7 @@
|
|||||||
}
|
}
|
||||||
@foreach (Folder folder in _folders)
|
@foreach (Folder folder in _folders)
|
||||||
{
|
{
|
||||||
if (folder.FolderId == _folderid)
|
if (folder.FolderId == FolderId)
|
||||||
{
|
{
|
||||||
<option value="@(folder.FolderId)" selected>@(new string('-', folder.Level * 2))@(folder.Name)</option>
|
<option value="@(folder.FolderId)" selected>@(new string('-', folder.Level * 2))@(folder.Name)</option>
|
||||||
}
|
}
|
||||||
@ -29,14 +31,15 @@
|
|||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@if (_showfiles)
|
}
|
||||||
|
@if (ShowFiles)
|
||||||
{
|
{
|
||||||
<div>
|
<div>
|
||||||
<select class="form-control" @onchange="(e => FileChanged(e))">
|
<select class="form-control" @onchange="(e => FileChanged(e))">
|
||||||
<option value="-1"><Select File></option>
|
<option value="-1"><Select File></option>
|
||||||
@foreach (File file in _files)
|
@foreach (File file in _files)
|
||||||
{
|
{
|
||||||
if (file.FileId == _fileid)
|
if (file.FileId == FileId)
|
||||||
{
|
{
|
||||||
<option value="@(file.FileId)" selected>@(file.Name)</option>
|
<option value="@(file.FileId)" selected>@(file.Name)</option>
|
||||||
}
|
}
|
||||||
@ -48,16 +51,16 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@if (_haseditpermission)
|
@if (ShowUpload && _haseditpermission)
|
||||||
{
|
{
|
||||||
<div>
|
<div>
|
||||||
@if (_uploadmultiple)
|
@if (UploadMultiple)
|
||||||
{
|
{
|
||||||
<input type="file" id="@_fileinputid" name="file" accept="@_filter" multiple />
|
<input type="file" id="@_fileinputid" name="file" accept="@_filter" multiple/>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<input type="file" id="@_fileinputid" name="file" accept="@_filter" />
|
<input type="file" id="@_fileinputid" name="file" accept="@_filter"/>
|
||||||
}
|
}
|
||||||
<span id="@_progressinfoid"></span><progress id="@_progressbarid" style="width: 150px; visibility: hidden;"></progress>
|
<span id="@_progressinfoid"></span><progress id="@_progressbarid" style="width: 150px; visibility: hidden;"></progress>
|
||||||
<span class="float-right">
|
<span class="float-right">
|
||||||
@ -68,13 +71,13 @@
|
|||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@((MarkupString)_message)
|
|
||||||
}
|
}
|
||||||
|
@((MarkupString) _message)
|
||||||
</div>
|
</div>
|
||||||
@if (_image != string.Empty)
|
@if (_image != string.Empty)
|
||||||
{
|
{
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
@((MarkupString)_image)
|
@((MarkupString) _image)
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@ -84,15 +87,12 @@
|
|||||||
@code {
|
@code {
|
||||||
private string _id;
|
private string _id;
|
||||||
private List<Folder> _folders;
|
private List<Folder> _folders;
|
||||||
private int _folderid = -1;
|
|
||||||
private List<File> _files = new List<File>();
|
private List<File> _files = new List<File>();
|
||||||
private int _fileid = -1;
|
|
||||||
private bool _showfiles = true;
|
private bool _showfiles = true;
|
||||||
private string _fileinputid = string.Empty;
|
private string _fileinputid = string.Empty;
|
||||||
private string _progressinfoid = string.Empty;
|
private string _progressinfoid = string.Empty;
|
||||||
private string _progressbarid = string.Empty;
|
private string _progressbarid = string.Empty;
|
||||||
private string _filter = "*";
|
private string _filter = "*";
|
||||||
private bool _uploadmultiple = false;
|
|
||||||
private bool _haseditpermission = false;
|
private bool _haseditpermission = false;
|
||||||
private string _message = string.Empty;
|
private string _message = string.Empty;
|
||||||
private string _image = string.Empty;
|
private string _image = string.Empty;
|
||||||
@ -105,19 +105,25 @@
|
|||||||
public string Folder { get; set; } // optional - for setting a specific folder by default
|
public string Folder { get; set; } // optional - for setting a specific folder by default
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string FolderId { get; set; } // optional - for setting a specific folderid by default
|
public int FolderId { get; set; } = -1; // optional - for setting a specific folderid by default
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string ShowFiles { get; set; } // optional - for indicating whether a list of files should be displayed - default is true
|
public bool ShowFiles { get; set; } = true; // optional - for indicating whether a list of files should be displayed - default is true
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string FileId { get; set; } // optional - for setting a specific file by default
|
public bool ShowUpload { get; set; } = true; // optional - for indicating whether a Upload controls should be displayed - default is true
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public bool ShowFolders { get; set; } = true; // optional - for indicating whether a list of folders should be displayed - default is true
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public int FileId { get; set; } = -1; // optional - for setting a specific file by default
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Filter { get; set; } // optional - comma delimited list of file types that can be selected or uploaded ie. "jpg,gif"
|
public string Filter { get; set; } // optional - comma delimited list of file types that can be selected or uploaded ie. "jpg,gif"
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string UploadMultiple { get; set; } // optional - enable multiple file uploads - default false
|
public bool UploadMultiple { get; set; } = false; // optional - enable multiple file uploads - default false
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
@ -129,42 +135,30 @@
|
|||||||
if (!string.IsNullOrEmpty(Folder))
|
if (!string.IsNullOrEmpty(Folder))
|
||||||
{
|
{
|
||||||
_folders = new List<Folder> {new Folder {FolderId = -1, Name = Folder}};
|
_folders = new List<Folder> {new Folder {FolderId = -1, Name = Folder}};
|
||||||
_folderid = -1;
|
FolderId = -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_folders = await FolderService.GetFoldersAsync(ModuleState.SiteId);
|
_folders = await FolderService.GetFoldersAsync(ModuleState.SiteId);
|
||||||
if (!string.IsNullOrEmpty(FolderId))
|
|
||||||
{
|
|
||||||
_folderid = int.Parse(FolderId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(FileId))
|
if (FileId != -1)
|
||||||
{
|
{
|
||||||
_fileid = int.Parse(FileId);
|
File file = await FileService.GetFileAsync(FileId);
|
||||||
if (_fileid != -1)
|
|
||||||
{
|
|
||||||
File file = await FileService.GetFileAsync(int.Parse(FileId));
|
|
||||||
if (file != null)
|
if (file != null)
|
||||||
{
|
{
|
||||||
_folderid = file.FolderId;
|
FolderId = file.FolderId;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_fileid = -1; // file does not exist
|
FileId = -1; // file does not exist
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await SetImage();
|
await SetImage();
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(ShowFiles))
|
|
||||||
{
|
|
||||||
_showfiles = bool.Parse(ShowFiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Filter))
|
if (!string.IsNullOrEmpty(Filter))
|
||||||
{
|
{
|
||||||
_filter = "." + Filter.Replace(",",",.");
|
_filter = "." + Filter.Replace(",", ",.");
|
||||||
}
|
}
|
||||||
|
|
||||||
await GetFiles();
|
await GetFiles();
|
||||||
@ -174,11 +168,6 @@
|
|||||||
_fileinputid = _guid + "FileInput";
|
_fileinputid = _guid + "FileInput";
|
||||||
_progressinfoid = _guid + "ProgressInfo";
|
_progressinfoid = _guid + "ProgressInfo";
|
||||||
_progressbarid = _guid + "ProgressBar";
|
_progressbarid = _guid + "ProgressBar";
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(UploadMultiple))
|
|
||||||
{
|
|
||||||
_uploadmultiple = bool.Parse(UploadMultiple);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task GetFiles()
|
private async Task GetFiles()
|
||||||
@ -191,11 +180,11 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Folder folder = _folders.FirstOrDefault(item => item.FolderId == _folderid);
|
Folder folder = _folders.FirstOrDefault(item => item.FolderId == FolderId);
|
||||||
if (folder != null)
|
if (folder != null)
|
||||||
{
|
{
|
||||||
_haseditpermission = UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, folder.Permissions);
|
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, folder.Permissions);
|
||||||
_files = await FileService.GetFilesAsync(_folderid);
|
_files = await FileService.GetFilesAsync(FolderId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -222,9 +211,9 @@
|
|||||||
_message = string.Empty;
|
_message = string.Empty;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_folderid = int.Parse((string)e.Value);
|
FolderId = int.Parse((string) e.Value);
|
||||||
await GetFiles();
|
await GetFiles();
|
||||||
_fileid = -1;
|
FileId = -1;
|
||||||
_image = string.Empty;
|
_image = string.Empty;
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
@ -238,7 +227,7 @@
|
|||||||
private async Task FileChanged(ChangeEventArgs e)
|
private async Task FileChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
_message = string.Empty;
|
_message = string.Empty;
|
||||||
_fileid = int.Parse((string)e.Value);
|
FileId = int.Parse((string) e.Value);
|
||||||
|
|
||||||
await SetImage();
|
await SetImage();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
@ -247,19 +236,19 @@
|
|||||||
private async Task SetImage()
|
private async Task SetImage()
|
||||||
{
|
{
|
||||||
_image = string.Empty;
|
_image = string.Empty;
|
||||||
if (_fileid != -1)
|
if (FileId != -1)
|
||||||
{
|
{
|
||||||
File file = await FileService.GetFileAsync(_fileid);
|
File file = await FileService.GetFileAsync(FileId);
|
||||||
if (file != null && file.ImageHeight != 0 && file.ImageWidth != 0)
|
if (file != null && file.ImageHeight != 0 && file.ImageWidth != 0)
|
||||||
{
|
{
|
||||||
var maxwidth = 200;
|
var maxwidth = 200;
|
||||||
var maxheight = 200;
|
var maxheight = 200;
|
||||||
|
|
||||||
var ratioX = (double)maxwidth / (double)file.ImageWidth;
|
var ratioX = (double) maxwidth / (double) file.ImageWidth;
|
||||||
var ratioY = (double)maxheight / (double)file.ImageHeight;
|
var ratioY = (double) maxheight / (double) file.ImageHeight;
|
||||||
var ratio = ratioX < ratioY ? ratioX : ratioY;
|
var ratio = ratioX < ratioY ? ratioX : ratioY;
|
||||||
|
|
||||||
_image = "<img src=\"" + ContentUrl(_fileid) + "\" alt=\"" + file.Name +
|
_image = "<img src=\"" + ContentUrl(FileId) + "\" alt=\"" + file.Name +
|
||||||
"\" width=\"" + Convert.ToInt32(file.ImageWidth * ratio).ToString() +
|
"\" width=\"" + Convert.ToInt32(file.ImageWidth * ratio).ToString() +
|
||||||
"\" height=\"" + Convert.ToInt32(file.ImageHeight * ratio).ToString() + "\" />";
|
"\" height=\"" + Convert.ToInt32(file.ImageHeight * ratio).ToString() + "\" />";
|
||||||
}
|
}
|
||||||
@ -268,7 +257,7 @@
|
|||||||
|
|
||||||
private async Task UploadFile()
|
private async Task UploadFile()
|
||||||
{
|
{
|
||||||
var interop = new Interop(JsRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
var upload = await interop.GetFiles(_fileinputid);
|
var upload = await interop.GetFiles(_fileinputid);
|
||||||
if (upload.Length > 0)
|
if (upload.Length > 0)
|
||||||
{
|
{
|
||||||
@ -281,7 +270,7 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = await FileService.UploadFilesAsync(_folderid, upload, _guid);
|
result = await FileService.UploadFilesAsync(FolderId, upload, _guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == string.Empty)
|
if (result == string.Empty)
|
||||||
@ -295,7 +284,7 @@
|
|||||||
var file = _files.Where(item => item.Name == upload[0]).FirstOrDefault();
|
var file = _files.Where(item => item.Name == upload[0]).FirstOrDefault();
|
||||||
if (file != null)
|
if (file != null)
|
||||||
{
|
{
|
||||||
_fileid = file.FileId;
|
FileId = file.FileId;
|
||||||
await SetImage();
|
await SetImage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -325,21 +314,21 @@
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await FileService.DeleteFileAsync(_fileid);
|
await FileService.DeleteFileAsync(FileId);
|
||||||
await logger.LogInformation("File Deleted {File}", _fileid);
|
await logger.LogInformation("File Deleted {File}", FileId);
|
||||||
_message = "<br /><div class=\"alert alert-success\" role=\"alert\">File Deleted</div>";
|
_message = "<br /><div class=\"alert alert-success\" role=\"alert\">File Deleted</div>";
|
||||||
await GetFiles();
|
await GetFiles();
|
||||||
_fileid = -1;
|
FileId = -1;
|
||||||
await SetImage();
|
await SetImage();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Deleting File {File} {Error}", _fileid, ex.Message);
|
await logger.LogError(ex, "Error Deleting File {File} {Error}", FileId, ex.Message);
|
||||||
_message = "<br /><div class=\"alert alert-danger\" role=\"alert\">Error Deleting File</div>";
|
_message = "<br /><div class=\"alert alert-danger\" role=\"alert\">Error Deleting File</div>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetFileId() => _fileid;
|
public int GetFileId() => FileId;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,10 +10,10 @@
|
|||||||
<table class="table" style="width: 50%; min-width: 250px;">
|
<table class="table" style="width: 50%; min-width: 250px;">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Role</th>
|
<th scope="col">Role</th>
|
||||||
@foreach (PermissionString permission in _permissions)
|
@foreach (PermissionString permission in _permissions)
|
||||||
{
|
{
|
||||||
<th style="text-align: center;">@permission.PermissionName</th>
|
<th style="text-align: center; width: 1px;">@permission.PermissionName</th>
|
||||||
}
|
}
|
||||||
</tr>
|
</tr>
|
||||||
@foreach (Role role in _roles)
|
@foreach (Role role in _roles)
|
||||||
@ -36,10 +36,10 @@
|
|||||||
<table class="table" style="width: 50%; min-width: 250px;">
|
<table class="table" style="width: 50%; min-width: 250px;">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>User</th>
|
<th scope="col">User</th>
|
||||||
@foreach (PermissionString permission in _permissions)
|
@foreach (PermissionString permission in _permissions)
|
||||||
{
|
{
|
||||||
<th style="text-align: center;">@permission.PermissionName</th>
|
<th style="text-align: center; width: 1px;">@permission.PermissionName</th>
|
||||||
}
|
}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -48,11 +48,11 @@
|
|||||||
{
|
{
|
||||||
string userid = "[" + user.UserId.ToString() + "]";
|
string userid = "[" + user.UserId.ToString() + "]";
|
||||||
<tr>
|
<tr>
|
||||||
<td>@user.DisplayName</td>
|
<td >@user.DisplayName</td>
|
||||||
@foreach (PermissionString permission in _permissions)
|
@foreach (PermissionString permission in _permissions)
|
||||||
{
|
{
|
||||||
var p = permission;
|
var p = permission;
|
||||||
<td style="text-align: center;">
|
<td style="text-align: center; width: 1px;">
|
||||||
<TriStateCheckBox Value=@GetPermissionValue(p.Permissions, userid) Disabled=false OnChange="@(e => PermissionChanged(e, p.PermissionName, userid))" />
|
<TriStateCheckBox Value=@GetPermissionValue(p.Permissions, userid) Disabled=false OnChange="@(e => PermissionChanged(e, p.PermissionName, userid))" />
|
||||||
</td>
|
</td>
|
||||||
}
|
}
|
||||||
@ -64,9 +64,10 @@
|
|||||||
<table class="table" style="width: 50%; min-width: 250px;">
|
<table class="table" style="width: 50%; min-width: 250px;">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: right;"><label for="Username" class="control-label">User: </label></td>
|
<td class="input-group">
|
||||||
<td><input type="text" name="Username" class="form-control" placeholder="Enter Username" @bind="@_username" /></td>
|
<input type="text" name="Username" class="form-control" placeholder="Enter Username" @bind="@_username" />
|
||||||
<td style="text-align: left;"><button type="button" class="btn btn-primary" @onclick="AddUser">Add</button></td>
|
<button type="button" class="btn btn-primary" @onclick="AddUser">Add</button>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
@namespace Oqtane.Modules.Controls
|
@namespace Oqtane.Modules.Controls
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@attribute [OqtaneIgnore]
|
@attribute [OqtaneIgnore]
|
||||||
@inject IJSRuntime JsRuntime
|
|
||||||
|
|
||||||
<div class="row" style="margin-bottom: 50px;">
|
<div class="row" style="margin-bottom: 50px;">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
@ -108,6 +107,13 @@
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string DebugLevel { get; set; } = "info";
|
public string DebugLevel { get; set; } = "info";
|
||||||
|
|
||||||
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
|
{
|
||||||
|
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill1.3.6.min.js" },
|
||||||
|
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-blot-formatter.min.js" },
|
||||||
|
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-interop.js" }
|
||||||
|
};
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
_content = Content; // raw HTML
|
_content = Content; // raw HTML
|
||||||
@ -117,8 +123,11 @@
|
|||||||
{
|
{
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
{
|
{
|
||||||
await RichTextEditorInterop.CreateEditor(
|
await base.OnAfterRenderAsync(firstRender);
|
||||||
JsRuntime,
|
|
||||||
|
var interop = new RichTextEditorInterop(JSRuntime);
|
||||||
|
|
||||||
|
await interop.CreateEditor(
|
||||||
_editorElement,
|
_editorElement,
|
||||||
_toolBar,
|
_toolBar,
|
||||||
ReadOnly,
|
ReadOnly,
|
||||||
@ -126,14 +135,10 @@
|
|||||||
Theme,
|
Theme,
|
||||||
DebugLevel);
|
DebugLevel);
|
||||||
|
|
||||||
await RichTextEditorInterop.LoadEditorContent(
|
await interop.LoadEditorContent(_editorElement, Content);
|
||||||
JsRuntime,
|
|
||||||
_editorElement, Content);
|
|
||||||
|
|
||||||
// preserve a copy of the rich text content ( Quill sanitizes content so we need to retrieve it from the editor )
|
// preserve a copy of the rich text content ( Quill sanitizes content so we need to retrieve it from the editor )
|
||||||
_original = await RichTextEditorInterop.GetHtml(
|
_original = await interop.GetHtml(_editorElement);
|
||||||
JsRuntime,
|
|
||||||
_editorElement);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,25 +151,22 @@
|
|||||||
|
|
||||||
public async Task RefreshRichText()
|
public async Task RefreshRichText()
|
||||||
{
|
{
|
||||||
await RichTextEditorInterop.LoadEditorContent(
|
var interop = new RichTextEditorInterop(JSRuntime);
|
||||||
JsRuntime,
|
await interop.LoadEditorContent(_editorElement, _content);
|
||||||
_editorElement, _content);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RefreshRawHtml()
|
public async Task RefreshRawHtml()
|
||||||
{
|
{
|
||||||
_content = await RichTextEditorInterop.GetHtml(
|
var interop = new RichTextEditorInterop(JSRuntime);
|
||||||
JsRuntime,
|
_content = await interop.GetHtml(_editorElement);
|
||||||
_editorElement);
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetHtml()
|
public async Task<string> GetHtml()
|
||||||
{
|
{
|
||||||
// get rich text content
|
// get rich text content
|
||||||
string content = await RichTextEditorInterop.GetHtml(
|
var interop = new RichTextEditorInterop(JSRuntime);
|
||||||
JsRuntime,
|
string content = await interop.GetHtml(_editorElement);
|
||||||
_editorElement);
|
|
||||||
|
|
||||||
if (_original != content)
|
if (_original != content)
|
||||||
{
|
{
|
||||||
@ -185,9 +187,8 @@
|
|||||||
var fileid = _fileManager.GetFileId();
|
var fileid = _fileManager.GetFileId();
|
||||||
if (fileid != -1)
|
if (fileid != -1)
|
||||||
{
|
{
|
||||||
await RichTextEditorInterop.InsertImage(
|
var interop = new RichTextEditorInterop(JSRuntime);
|
||||||
JsRuntime,
|
await interop.InsertImage(_editorElement, ContentUrl(fileid));
|
||||||
_editorElement, ContentUrl(fileid));
|
|
||||||
_filemanagervisible = false;
|
_filemanagervisible = false;
|
||||||
_message = string.Empty;
|
_message = string.Empty;
|
||||||
}
|
}
|
||||||
@ -207,22 +208,19 @@
|
|||||||
// other rich text editor methods which can be used by developers
|
// other rich text editor methods which can be used by developers
|
||||||
public async Task<string> GetText()
|
public async Task<string> GetText()
|
||||||
{
|
{
|
||||||
return await RichTextEditorInterop.GetText(
|
var interop = new RichTextEditorInterop(JSRuntime);
|
||||||
JsRuntime,
|
return await interop.GetText(_editorElement);
|
||||||
_editorElement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetContent()
|
public async Task<string> GetContent()
|
||||||
{
|
{
|
||||||
return await RichTextEditorInterop.GetContent(
|
var interop = new RichTextEditorInterop(JSRuntime);
|
||||||
JsRuntime,
|
return await interop.GetContent(_editorElement);
|
||||||
_editorElement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task EnableEditor(bool mode)
|
public async Task EnableEditor(bool mode)
|
||||||
{
|
{
|
||||||
await RichTextEditorInterop.EnableEditor(
|
var interop = new RichTextEditorInterop(JSRuntime);
|
||||||
JsRuntime,
|
await interop.EnableEditor(_editorElement, mode);
|
||||||
_editorElement, mode);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,16 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Oqtane.Modules.Controls
|
namespace Oqtane.Modules.Controls
|
||||||
{
|
{
|
||||||
public static class RichTextEditorInterop
|
public class RichTextEditorInterop
|
||||||
{
|
{
|
||||||
internal static ValueTask<object> CreateEditor(
|
private readonly IJSRuntime _jsRuntime;
|
||||||
IJSRuntime jsRuntime,
|
|
||||||
|
public RichTextEditorInterop(IJSRuntime jsRuntime)
|
||||||
|
{
|
||||||
|
_jsRuntime = jsRuntime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task CreateEditor(
|
||||||
ElementReference quillElement,
|
ElementReference quillElement,
|
||||||
ElementReference toolbar,
|
ElementReference toolbar,
|
||||||
bool readOnly,
|
bool readOnly,
|
||||||
@ -15,66 +21,103 @@ namespace Oqtane.Modules.Controls
|
|||||||
string theme,
|
string theme,
|
||||||
string debugLevel)
|
string debugLevel)
|
||||||
{
|
{
|
||||||
return jsRuntime.InvokeAsync<object>(
|
try
|
||||||
"interop.createQuill",
|
{
|
||||||
quillElement, toolbar, readOnly,
|
await _jsRuntime.InvokeAsync<object>(
|
||||||
placeholder, theme, debugLevel);
|
"Oqtane.RichTextEditor.createQuill",
|
||||||
|
quillElement, toolbar, readOnly, placeholder, theme, debugLevel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// handle exception
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static ValueTask<string> GetText(
|
public ValueTask<string> GetText(ElementReference quillElement)
|
||||||
IJSRuntime jsRuntime,
|
|
||||||
ElementReference quillElement)
|
|
||||||
{
|
{
|
||||||
return jsRuntime.InvokeAsync<string>(
|
try
|
||||||
"interop.getQuillText",
|
{
|
||||||
|
return _jsRuntime.InvokeAsync<string>(
|
||||||
|
"Oqtane.RichTextEditor.getQuillText",
|
||||||
quillElement);
|
quillElement);
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
internal static ValueTask<string> GetHtml(
|
|
||||||
IJSRuntime jsRuntime,
|
|
||||||
ElementReference quillElement)
|
|
||||||
{
|
{
|
||||||
return jsRuntime.InvokeAsync<string>(
|
return new ValueTask<string>(Task.FromResult(string.Empty));
|
||||||
"interop.getQuillHTML",
|
}
|
||||||
quillElement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static ValueTask<string> GetContent(
|
public ValueTask<string> GetHtml(ElementReference quillElement)
|
||||||
IJSRuntime jsRuntime,
|
|
||||||
ElementReference quillElement)
|
|
||||||
{
|
{
|
||||||
return jsRuntime.InvokeAsync<string>(
|
try
|
||||||
"interop.getQuillContent",
|
{
|
||||||
|
return _jsRuntime.InvokeAsync<string>(
|
||||||
|
"Oqtane.RichTextEditor.getQuillHTML",
|
||||||
quillElement);
|
quillElement);
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
internal static ValueTask<object> LoadEditorContent(
|
|
||||||
IJSRuntime jsRuntime,
|
|
||||||
ElementReference quillElement,
|
|
||||||
string content)
|
|
||||||
{
|
{
|
||||||
return jsRuntime.InvokeAsync<object>(
|
return new ValueTask<string>(Task.FromResult(string.Empty));
|
||||||
"interop.loadQuillContent",
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueTask<string> GetContent(ElementReference quillElement)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return _jsRuntime.InvokeAsync<string>(
|
||||||
|
"Oqtane.RichTextEditor.getQuillContent",
|
||||||
|
quillElement);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return new ValueTask<string>(Task.FromResult(string.Empty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task LoadEditorContent(ElementReference quillElement, string content)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_jsRuntime.InvokeAsync<object>(
|
||||||
|
"Oqtane.RichTextEditor.loadQuillContent",
|
||||||
quillElement, content);
|
quillElement, content);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static ValueTask<object> EnableEditor(
|
public Task EnableEditor(ElementReference quillElement, bool mode)
|
||||||
IJSRuntime jsRuntime,
|
|
||||||
ElementReference quillElement,
|
|
||||||
bool mode)
|
|
||||||
{
|
{
|
||||||
return jsRuntime.InvokeAsync<object>(
|
try
|
||||||
"interop.enableQuillEditor", quillElement, mode);
|
{
|
||||||
|
_jsRuntime.InvokeAsync<object>(
|
||||||
|
"Oqtane.RichTextEditor.enableQuillEditor", quillElement, mode);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static ValueTask<object> InsertImage(
|
public Task InsertImage(ElementReference quillElement, string imageUrl)
|
||||||
IJSRuntime jsRuntime,
|
|
||||||
ElementReference quillElement,
|
|
||||||
string imageUrl)
|
|
||||||
{
|
{
|
||||||
return jsRuntime.InvokeAsync<object>(
|
try
|
||||||
"interop.insertQuillImage",
|
{
|
||||||
|
_jsRuntime.InvokeAsync<object>(
|
||||||
|
"Oqtane.RichTextEditor.insertQuillImage",
|
||||||
quillElement, imageUrl);
|
quillElement, imageUrl);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,12 @@
|
|||||||
|
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<div>
|
<div>
|
||||||
<a data-toggle="collapse" class="app-link-unstyled" href="#@Name" aria-expanded="@_expanded" aria-controls="@Name">
|
<a data-toggle="collapse" class="app-link-unstyled" href="#@Name" aria-expanded="@_expanded" aria-controls="@Name" @onclick:preventDefault="true">
|
||||||
<h5>@_heading</h5>
|
<h5>@_heading</h5>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-auto">
|
<div class="ml-auto">
|
||||||
<a data-toggle="collapse" class="app-link-unstyled float-right" href="#@Name" aria-expanded="@_expanded" aria-controls="@Name">
|
<a data-toggle="collapse" class="app-link-unstyled float-right" href="#@Name" aria-expanded="@_expanded" aria-controls="@Name" @onclick:preventDefault="true">
|
||||||
<i class="oi oi-chevron-bottom"></i>
|
<i class="oi oi-chevron-bottom"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,13 +11,13 @@
|
|||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
@if (tabPanel.Name == ActiveTab)
|
@if (tabPanel.Name == ActiveTab)
|
||||||
{
|
{
|
||||||
<a class="nav-link active" data-toggle="tab" href="#@tabPanel.Name" role="tab">
|
<a class="nav-link active" data-toggle="tab" href="#@tabPanel.Name" role="tab" @onclick:preventDefault="true">
|
||||||
@DisplayHeading(tabPanel.Name, tabPanel.Heading)
|
@DisplayHeading(tabPanel.Name, tabPanel.Heading)
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<a class="nav-link" data-toggle="tab" href="#@tabPanel.Name" role="tab">
|
<a class="nav-link" data-toggle="tab" href="#@tabPanel.Name" role="tab" @onclick:preventDefault="true">
|
||||||
@DisplayHeading(tabPanel.Name, tabPanel.Heading)
|
@DisplayHeading(tabPanel.Name, tabPanel.Heading)
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,8 @@
|
|||||||
@using Oqtane.Modules.Controls
|
@using Oqtane.Modules.Controls
|
||||||
@namespace Oqtane.Modules.HtmlText
|
@namespace Oqtane.Modules.HtmlText
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
|
@inject IHtmlTextService HtmlTextService
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject HttpClient http
|
|
||||||
@inject SiteState sitestate
|
|
||||||
|
|
||||||
@if (_content != null)
|
@if (_content != null)
|
||||||
{
|
{
|
||||||
@ -14,12 +13,24 @@
|
|||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">Cancel</NavLink>
|
||||||
@if (!string.IsNullOrEmpty(_content))
|
@if (!string.IsNullOrEmpty(_content))
|
||||||
{
|
{
|
||||||
<br /><br />
|
<br />
|
||||||
|
<br />
|
||||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
|
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||||
|
|
||||||
|
public override string Title => "Edit Html/Text";
|
||||||
|
|
||||||
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
|
{
|
||||||
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" },
|
||||||
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill1.3.6.bubble.css" },
|
||||||
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill1.3.6.snow.css" }
|
||||||
|
};
|
||||||
|
|
||||||
private RichTextEditor RichTextEditorHtml;
|
private RichTextEditor RichTextEditorHtml;
|
||||||
private string _content = null;
|
private string _content = null;
|
||||||
private string _createdby;
|
private string _createdby;
|
||||||
@ -27,16 +38,11 @@
|
|||||||
private string _modifiedby;
|
private string _modifiedby;
|
||||||
private DateTime _modifiedon;
|
private DateTime _modifiedon;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
|
||||||
|
|
||||||
public override string Title => "Edit Html/Text";
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var htmltextservice = new HtmlTextService(http, sitestate);
|
var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId);
|
||||||
var htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
|
|
||||||
if (htmltext != null)
|
if (htmltext != null)
|
||||||
{
|
{
|
||||||
_content = htmltext.Content;
|
_content = htmltext.Content;
|
||||||
@ -65,19 +71,18 @@
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var htmltextservice = new HtmlTextService(http, sitestate);
|
var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId);
|
||||||
var htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
|
|
||||||
if (htmltext != null)
|
if (htmltext != null)
|
||||||
{
|
{
|
||||||
htmltext.Content = content;
|
htmltext.Content = content;
|
||||||
await htmltextservice.UpdateHtmlTextAsync(htmltext);
|
await HtmlTextService.UpdateHtmlTextAsync(htmltext);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
htmltext = new HtmlTextInfo();
|
htmltext = new HtmlTextInfo();
|
||||||
htmltext.ModuleId = ModuleState.ModuleId;
|
htmltext.ModuleId = ModuleState.ModuleId;
|
||||||
htmltext.Content = content;
|
htmltext.Content = content;
|
||||||
await htmltextservice.AddHtmlTextAsync(htmltext);
|
await HtmlTextService.AddHtmlTextAsync(htmltext);
|
||||||
}
|
}
|
||||||
|
|
||||||
await logger.LogInformation("Html/Text Content Saved {HtmlText}", htmltext);
|
await logger.LogInformation("Html/Text Content Saved {HtmlText}", htmltext);
|
||||||
|
@ -1,32 +1,28 @@
|
|||||||
@using Oqtane.Modules.HtmlText.Services
|
@using Oqtane.Modules.HtmlText.Services
|
||||||
@using Oqtane.Modules.HtmlText.Models
|
|
||||||
@namespace Oqtane.Modules.HtmlText
|
@namespace Oqtane.Modules.HtmlText
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject NavigationManager NavigationManager
|
@inject IHtmlTextService HtmlTextService
|
||||||
@inject HttpClient http
|
|
||||||
@inject SiteState sitestate
|
|
||||||
|
|
||||||
@((MarkupString)content)
|
@((MarkupString)content)
|
||||||
|
|
||||||
@if (PageState.EditMode)
|
@if (PageState.EditMode)
|
||||||
{
|
{
|
||||||
<br />
|
<br /><ActionLink Action="Edit" /><br /><br />
|
||||||
}
|
|
||||||
<ActionLink Action="Edit" />
|
|
||||||
@if (PageState.EditMode)
|
|
||||||
{
|
|
||||||
<br /><br />
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
|
{
|
||||||
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
|
||||||
|
};
|
||||||
|
|
||||||
private string content = "";
|
private string content = "";
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var htmltextservice = new HtmlTextService(http, sitestate);
|
var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId);
|
||||||
var htmltext = await htmltextservice.GetHtmlTextAsync(ModuleState.ModuleId);
|
|
||||||
if (htmltext != null)
|
if (htmltext != null)
|
||||||
{
|
{
|
||||||
content = htmltext.Content;
|
content = htmltext.Content;
|
||||||
|
@ -8,7 +8,7 @@ using Oqtane.Shared;
|
|||||||
|
|
||||||
namespace Oqtane.Modules.HtmlText.Services
|
namespace Oqtane.Modules.HtmlText.Services
|
||||||
{
|
{
|
||||||
public class HtmlTextService : ServiceBase, IHtmlTextService
|
public class HtmlTextService : ServiceBase, IHtmlTextService, IService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
|
@ -6,10 +6,13 @@ using Oqtane.Services;
|
|||||||
using System;
|
using System;
|
||||||
using Oqtane.Enums;
|
using Oqtane.Enums;
|
||||||
using Oqtane.UI;
|
using Oqtane.UI;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.JSInterop;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Oqtane.Modules
|
namespace Oqtane.Modules
|
||||||
{
|
{
|
||||||
public class ModuleBase : ComponentBase, IModuleControl
|
public abstract class ModuleBase : ComponentBase, IModuleControl
|
||||||
{
|
{
|
||||||
private Logger _logger;
|
private Logger _logger;
|
||||||
|
|
||||||
@ -18,6 +21,9 @@ namespace Oqtane.Modules
|
|||||||
[Inject]
|
[Inject]
|
||||||
protected ILogService LoggingService { get; set; }
|
protected ILogService LoggingService { get; set; }
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
protected IJSRuntime JSRuntime { get; set; }
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
protected PageState PageState { get; set; }
|
protected PageState PageState { get; set; }
|
||||||
|
|
||||||
@ -27,7 +33,6 @@ namespace Oqtane.Modules
|
|||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
protected ModuleInstance ModuleInstance { get; set; }
|
protected ModuleInstance ModuleInstance { get; set; }
|
||||||
|
|
||||||
|
|
||||||
// optional interface properties
|
// optional interface properties
|
||||||
public virtual SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.View; } set { } } // default security
|
public virtual SecurityAccessLevel SecurityAccessLevel { get { return SecurityAccessLevel.View; } set { } } // default security
|
||||||
|
|
||||||
@ -37,6 +42,27 @@ namespace Oqtane.Modules
|
|||||||
|
|
||||||
public virtual bool UseAdminContainer { get { return true; } }
|
public virtual bool UseAdminContainer { get { return true; } }
|
||||||
|
|
||||||
|
public virtual List<Resource> Resources { get; set; }
|
||||||
|
|
||||||
|
// base lifecycle method for handling JSInterop script registration
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
if (Resources != null && Resources.Exists(item => item.ResourceType == ResourceType.Script))
|
||||||
|
{
|
||||||
|
var scripts = new List<object>();
|
||||||
|
foreach (Resource resource in Resources.Where(item => item.ResourceType == ResourceType.Script))
|
||||||
|
{
|
||||||
|
scripts.Add(new { href = resource.Url, bundle = resource.Bundle ?? "", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "" });
|
||||||
|
}
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
await interop.IncludeScripts(scripts.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// path method
|
// path method
|
||||||
|
|
||||||
public string ModulePath()
|
public string ModulePath()
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<LangVersion>7.3</LangVersion>
|
<LangVersion>7.3</LangVersion>
|
||||||
<RazorLangVersion>3.0</RazorLangVersion>
|
<RazorLangVersion>3.0</RazorLangVersion>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
<Version>0.9.1</Version>
|
<Version>1.0.1</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
@ -15,8 +15,9 @@
|
|||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://github.com/oqtane</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<PackageReleaseNotes>Not for production use.</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</PackageReleaseNotes>
|
||||||
<RootNamespace>Oqtane</RootNamespace>
|
<RootNamespace>Oqtane</RootNamespace>
|
||||||
|
<IsPackable>true</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -27,14 +28,14 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="3.2.0-rc1.20223.4" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="3.2.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" Version="3.2.0-rc1.20223.4" PrivateAssets="all" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" Version="3.2.0" PrivateAssets="all" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="3.1.2" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="3.2.0" PrivateAssets="all" />
|
||||||
<PackageReference Include="System.Net.Http.Json" Version="3.2.0-rc1.20217.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="3.1.4" />
|
||||||
|
<PackageReference Include="System.Net.Http.Json" Version="3.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Oqtane.Shared\Oqtane.Shared.csproj" />
|
<ProjectReference Include="..\Oqtane.Shared\Oqtane.Shared.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -4,12 +4,16 @@ using System.Threading.Tasks;
|
|||||||
using Oqtane.Services;
|
using Oqtane.Services;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Json;
|
||||||
using Oqtane.Modules;
|
using Oqtane.Modules;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
using Oqtane.Providers;
|
using Oqtane.Providers;
|
||||||
using Microsoft.AspNetCore.Components.Authorization;
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace Oqtane.Client
|
namespace Oqtane.Client
|
||||||
{
|
{
|
||||||
@ -19,10 +23,9 @@ namespace Oqtane.Client
|
|||||||
{
|
{
|
||||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||||
builder.RootComponents.Add<App>("app");
|
builder.RootComponents.Add<App>("app");
|
||||||
|
HttpClient httpClient = new HttpClient {BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)};
|
||||||
|
|
||||||
builder.Services.AddSingleton(
|
builder.Services.AddSingleton(httpClient);
|
||||||
new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }
|
|
||||||
);
|
|
||||||
builder.Services.AddOptions();
|
builder.Services.AddOptions();
|
||||||
|
|
||||||
// register auth services
|
// register auth services
|
||||||
@ -57,14 +60,16 @@ namespace Oqtane.Client
|
|||||||
builder.Services.AddScoped<ISqlService, SqlService>();
|
builder.Services.AddScoped<ISqlService, SqlService>();
|
||||||
builder.Services.AddScoped<ISystemService, SystemService>();
|
builder.Services.AddScoped<ISystemService, SystemService>();
|
||||||
|
|
||||||
|
await LoadClientAssemblies(httpClient);
|
||||||
|
|
||||||
// dynamically register module contexts and repository services
|
// dynamically register module contexts and repository services
|
||||||
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||||
foreach (Assembly assembly in assemblies)
|
foreach (Assembly assembly in assemblies)
|
||||||
{
|
{
|
||||||
Type[] implementationtypes = assembly.GetTypes()
|
var implementationTypes = assembly.GetTypes()
|
||||||
.Where(item => item.GetInterfaces().Contains(typeof(IService)))
|
.Where(item => item.GetInterfaces().Contains(typeof(IService)));
|
||||||
.ToArray();
|
|
||||||
foreach (Type implementationtype in implementationtypes)
|
foreach (Type implementationtype in implementationTypes)
|
||||||
{
|
{
|
||||||
Type servicetype = Type.GetType(implementationtype.AssemblyQualifiedName.Replace(implementationtype.Name, "I" + implementationtype.Name));
|
Type servicetype = Type.GetType(implementationtype.AssemblyQualifiedName.Replace(implementationtype.Name, "I" + implementationtype.Name));
|
||||||
if (servicetype != null)
|
if (servicetype != null)
|
||||||
@ -76,9 +81,62 @@ namespace Oqtane.Client
|
|||||||
builder.Services.AddScoped(implementationtype, implementationtype); // no interface defined for service
|
builder.Services.AddScoped(implementationtype, implementationtype); // no interface defined for service
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assembly.GetInstances<IClientStartup>()
|
||||||
|
.ToList()
|
||||||
|
.ForEach(x => x.ConfigureServices(builder.Services));
|
||||||
}
|
}
|
||||||
|
|
||||||
await builder.Build().RunAsync();
|
await builder.Build().RunAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async Task LoadClientAssemblies(HttpClient http)
|
||||||
|
{
|
||||||
|
// get list of loaded assemblies on the client
|
||||||
|
var assemblies = AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetName().Name).ToList();
|
||||||
|
|
||||||
|
// get assemblies from server and load into client app domain
|
||||||
|
var zip = await http.GetByteArrayAsync($"/~/api/Installation/load");
|
||||||
|
|
||||||
|
// asemblies and debug symbols are packaged in a zip file
|
||||||
|
using (ZipArchive archive = new ZipArchive(new MemoryStream(zip)))
|
||||||
|
{
|
||||||
|
Dictionary<string, byte[]> dlls = new Dictionary<string, byte[]>();
|
||||||
|
Dictionary<string, byte[]> pdbs = new Dictionary<string, byte[]>();
|
||||||
|
|
||||||
|
foreach (ZipArchiveEntry entry in archive.Entries)
|
||||||
|
{
|
||||||
|
if (!assemblies.Contains(Path.GetFileNameWithoutExtension(entry.Name)))
|
||||||
|
{
|
||||||
|
using (var memoryStream = new MemoryStream())
|
||||||
|
{
|
||||||
|
entry.Open().CopyTo(memoryStream);
|
||||||
|
byte[] file = memoryStream.ToArray();
|
||||||
|
switch (Path.GetExtension(entry.Name))
|
||||||
|
{
|
||||||
|
case ".dll":
|
||||||
|
dlls.Add(entry.Name, file);
|
||||||
|
break;
|
||||||
|
case ".pdb":
|
||||||
|
pdbs.Add(entry.Name, file);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var item in dlls)
|
||||||
|
{
|
||||||
|
if (pdbs.ContainsKey(item.Key))
|
||||||
|
{
|
||||||
|
Assembly.Load(item.Value, pdbs[item.Key]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assembly.Load(item.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,16 +5,21 @@ using System.Linq;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System;
|
using System;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
public class AliasService : ServiceBase, IAliasService
|
public class AliasService : ServiceBase, IAliasService
|
||||||
{
|
{
|
||||||
|
|
||||||
public AliasService(HttpClient http) :base(http) { }
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Alias");
|
public AliasService(HttpClient http, SiteState siteState) : base(http)
|
||||||
|
{
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Apiurl => CreateApiUrl(_siteState.Alias, "Alias");
|
||||||
|
|
||||||
public async Task<List<Alias>> GetAliasesAsync()
|
public async Task<List<Alias>> GetAliasesAsync()
|
||||||
{
|
{
|
||||||
|
@ -12,7 +12,6 @@ namespace Oqtane.Services
|
|||||||
Task UpdateModuleDefinitionAsync(ModuleDefinition moduleDefinition);
|
Task UpdateModuleDefinitionAsync(ModuleDefinition moduleDefinition);
|
||||||
Task InstallModuleDefinitionsAsync();
|
Task InstallModuleDefinitionsAsync();
|
||||||
Task DeleteModuleDefinitionAsync(int moduleDefinitionId, int siteId);
|
Task DeleteModuleDefinitionAsync(int moduleDefinitionId, int siteId);
|
||||||
Task LoadModuleDefinitionsAsync(int siteId, Runtime runtime);
|
|
||||||
Task CreateModuleDefinitionAsync(ModuleDefinition moduleDefinition, int moduleId);
|
Task CreateModuleDefinitionAsync(ModuleDefinition moduleDefinition, int moduleId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,9 @@ namespace Oqtane.Services
|
|||||||
public interface IThemeService
|
public interface IThemeService
|
||||||
{
|
{
|
||||||
Task<List<Theme>> GetThemesAsync();
|
Task<List<Theme>> GetThemesAsync();
|
||||||
Dictionary<string, string> GetThemeTypes(List<Theme> themes);
|
List<ThemeControl> GetThemeControls(List<Theme> themes);
|
||||||
Dictionary<string, string> GetPaneLayoutTypes(List<Theme> themes, string themeName);
|
List<ThemeControl> GetLayoutControls(List<Theme> themes, string themeName);
|
||||||
Dictionary<string, string> GetContainerTypes(List<Theme> themes);
|
List<ThemeControl> GetContainerControls(List<Theme> themes, string themeName);
|
||||||
Task InstallThemesAsync();
|
Task InstallThemesAsync();
|
||||||
Task DeleteThemeAsync(string themeName);
|
Task DeleteThemeAsync(string themeName);
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,20 @@ using System.Threading.Tasks;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
public class JobLogService : ServiceBase, IJobLogService
|
public class JobLogService : ServiceBase, IJobLogService
|
||||||
{
|
{
|
||||||
public JobLogService(HttpClient http) :base(http) { }
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("JobLog");
|
public JobLogService(HttpClient http, SiteState siteState) : base(http)
|
||||||
|
{
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Apiurl => CreateApiUrl(_siteState.Alias, "JobLog");
|
||||||
|
|
||||||
public async Task<List<JobLog>> GetJobLogsAsync()
|
public async Task<List<JobLog>> GetJobLogsAsync()
|
||||||
{
|
{
|
||||||
|
@ -3,14 +3,20 @@ using System.Threading.Tasks;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
public class JobService : ServiceBase, IJobService
|
public class JobService : ServiceBase, IJobService
|
||||||
{
|
{
|
||||||
public JobService(HttpClient http) : base(http) { }
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Job");
|
public JobService(HttpClient http, SiteState siteState) : base(http)
|
||||||
|
{
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Apiurl => CreateApiUrl(_siteState.Alias, "Job");
|
||||||
|
|
||||||
public async Task<List<Job>> GetJobsAsync()
|
public async Task<List<Job>> GetJobsAsync()
|
||||||
{
|
{
|
||||||
|
@ -49,46 +49,9 @@ namespace Oqtane.Services
|
|||||||
await DeleteAsync($"{Apiurl}/{moduleDefinitionId}?siteid={siteId}");
|
await DeleteAsync($"{Apiurl}/{moduleDefinitionId}?siteid={siteId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task LoadModuleDefinitionsAsync(int siteId, Runtime runtime)
|
|
||||||
{
|
|
||||||
// get list of modules from the server
|
|
||||||
List<ModuleDefinition> moduledefinitions = await GetModuleDefinitionsAsync(siteId);
|
|
||||||
|
|
||||||
// download assemblies to browser when running client-side Blazor
|
|
||||||
if (runtime == Runtime.WebAssembly)
|
|
||||||
{
|
|
||||||
// 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();
|
|
||||||
|
|
||||||
foreach (ModuleDefinition moduledefinition in moduledefinitions)
|
|
||||||
{
|
|
||||||
// if a module has dependencies, check if they are loaded
|
|
||||||
if (moduledefinition.Dependencies != "")
|
|
||||||
{
|
|
||||||
foreach (string dependency in moduledefinition.Dependencies.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
|
||||||
{
|
|
||||||
string assemblyname = dependency.Replace(".dll", "");
|
|
||||||
if (assemblies.Where(item => item.FullName.StartsWith(assemblyname + ",")).FirstOrDefault() == null)
|
|
||||||
{
|
|
||||||
// download assembly from server and load
|
|
||||||
var bytes = await _http.GetByteArrayAsync($"{Apiurl}/load/{assemblyname}.dll");
|
|
||||||
Assembly.Load(bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// check if the module assembly is loaded
|
|
||||||
if (assemblies.Where(item => item.FullName.StartsWith(moduledefinition.AssemblyName + ",")).FirstOrDefault() == null)
|
|
||||||
{
|
|
||||||
// download assembly from server and load
|
|
||||||
var bytes = await _http.GetByteArrayAsync($"{Apiurl}/load/{moduledefinition.AssemblyName}.dll");
|
|
||||||
Assembly.Load(bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public async Task CreateModuleDefinitionAsync(ModuleDefinition moduleDefinition, int moduleId)
|
public async Task CreateModuleDefinitionAsync(ModuleDefinition moduleDefinition, int moduleId)
|
||||||
{
|
{
|
||||||
await PostJsonAsync($"{Apiurl}?moduleid={moduleId.ToString()}", moduleDefinition);
|
await PostJsonAsync($"{Apiurl}?moduleid={moduleId}", moduleDefinition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,13 +135,13 @@ namespace Oqtane.Services
|
|||||||
//TODO Missing content JSON validation
|
//TODO Missing content JSON validation
|
||||||
}
|
}
|
||||||
|
|
||||||
// create an API Url which is tenant agnostic ( for use with entities in the MasterDB )
|
// create an API Url which is tenant agnostic ( for use during installation )
|
||||||
public string CreateApiUrl(string serviceName)
|
public string CreateApiUrl(string serviceName)
|
||||||
{
|
{
|
||||||
return CreateApiUrl(null, serviceName);
|
return CreateApiUrl(null, serviceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create an API Url which is tenant aware ( for use with entities in the TenantDB )
|
// create an API Url which is tenant aware ( for use with repositories )
|
||||||
public string CreateApiUrl(Alias alias, string serviceName)
|
public string CreateApiUrl(Alias alias, string serviceName)
|
||||||
{
|
{
|
||||||
string apiurl = "/";
|
string apiurl = "/";
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Oqtane.Models;
|
using System;
|
||||||
|
using Oqtane.Models;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -106,7 +107,7 @@ namespace Oqtane.Services
|
|||||||
|
|
||||||
foreach (KeyValuePair<string, string> kvp in settings)
|
foreach (KeyValuePair<string, string> kvp in settings)
|
||||||
{
|
{
|
||||||
Setting setting = settingsList.FirstOrDefault(item => item.SettingName == kvp.Key);
|
Setting setting = settingsList.FirstOrDefault(item => item.SettingName.Equals(kvp.Key,StringComparison.OrdinalIgnoreCase));
|
||||||
if (setting == null)
|
if (setting == null)
|
||||||
{
|
{
|
||||||
setting = new Setting();
|
setting = new Setting();
|
||||||
@ -152,7 +153,7 @@ namespace Oqtane.Services
|
|||||||
public string GetSetting(Dictionary<string, string> settings, string settingName, string defaultValue)
|
public string GetSetting(Dictionary<string, string> settings, string settingName, string defaultValue)
|
||||||
{
|
{
|
||||||
string value = defaultValue;
|
string value = defaultValue;
|
||||||
if (settings.ContainsKey(settingName))
|
if (settings != null && settings.ContainsKey(settingName))
|
||||||
{
|
{
|
||||||
value = settings[settingName];
|
value = settings[settingName];
|
||||||
}
|
}
|
||||||
@ -161,6 +162,10 @@ namespace Oqtane.Services
|
|||||||
|
|
||||||
public Dictionary<string, string> SetSetting(Dictionary<string, string> settings, string settingName, string settingValue)
|
public Dictionary<string, string> SetSetting(Dictionary<string, string> settings, string settingName, string settingValue)
|
||||||
{
|
{
|
||||||
|
if (settings == null)
|
||||||
|
{
|
||||||
|
settings = new Dictionary<string, string>();
|
||||||
|
}
|
||||||
if (settings.ContainsKey(settingName))
|
if (settings.ContainsKey(settingName))
|
||||||
{
|
{
|
||||||
settings[settingName] = settingValue;
|
settings[settingName] = settingValue;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Shared;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -6,9 +7,14 @@ namespace Oqtane.Services
|
|||||||
{
|
{
|
||||||
public class SqlService : ServiceBase, ISqlService
|
public class SqlService : ServiceBase, ISqlService
|
||||||
{
|
{
|
||||||
public SqlService(HttpClient http) : base(http) { }
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Sql");
|
public SqlService(HttpClient http, SiteState siteState) : base(http)
|
||||||
|
{
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Apiurl => CreateApiUrl(_siteState.Alias, "Sql");
|
||||||
|
|
||||||
public async Task<SqlQuery> ExecuteQueryAsync(SqlQuery sqlquery)
|
public async Task<SqlQuery> ExecuteQueryAsync(SqlQuery sqlquery)
|
||||||
{
|
{
|
||||||
|
@ -3,14 +3,20 @@ using System.Net.Http;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
public class TenantService : ServiceBase, ITenantService
|
public class TenantService : ServiceBase, ITenantService
|
||||||
{
|
{
|
||||||
public TenantService(HttpClient http) : base(http) { }
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Tenant");
|
public TenantService(HttpClient http, SiteState siteState) : base(http)
|
||||||
|
{
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Apiurl => CreateApiUrl(_siteState.Alias, "Tenant");
|
||||||
|
|
||||||
public async Task<List<Tenant>> GetTenantsAsync()
|
public async Task<List<Tenant>> GetTenantsAsync()
|
||||||
{
|
{
|
||||||
|
@ -1,108 +1,54 @@
|
|||||||
using Oqtane.Models;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Reflection;
|
using Oqtane.Models;
|
||||||
using System;
|
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
public class ThemeService : ServiceBase, IThemeService
|
public class ThemeService : ServiceBase, IThemeService
|
||||||
{
|
{
|
||||||
private readonly HttpClient _http;
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
public ThemeService(HttpClient http) : base(http)
|
public ThemeService(HttpClient http, SiteState siteState) : base(http)
|
||||||
{
|
{
|
||||||
_http = http;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Theme");
|
private string ApiUrl => CreateApiUrl(_siteState.Alias, "Theme");
|
||||||
|
|
||||||
public async Task<List<Theme>> GetThemesAsync()
|
public async Task<List<Theme>> GetThemesAsync()
|
||||||
{
|
{
|
||||||
List<Theme> themes = await GetJsonAsync<List<Theme>>(Apiurl);
|
List<Theme> themes = await GetJsonAsync<List<Theme>>(ApiUrl);
|
||||||
|
|
||||||
// get list of loaded assemblies
|
|
||||||
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
|
||||||
|
|
||||||
foreach (Theme theme in themes)
|
|
||||||
{
|
|
||||||
if (theme.Dependencies != "")
|
|
||||||
{
|
|
||||||
foreach (string dependency in theme.Dependencies.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
|
||||||
{
|
|
||||||
string assemblyname = dependency.Replace(".dll", "");
|
|
||||||
if (assemblies.Where(item => item.FullName.StartsWith(assemblyname + ",")).FirstOrDefault() == null)
|
|
||||||
{
|
|
||||||
// download assembly from server and load
|
|
||||||
var bytes = await _http.GetByteArrayAsync($"{Apiurl}/load/{assemblyname}.dll");
|
|
||||||
Assembly.Load(bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (assemblies.Where(item => item.FullName.StartsWith(theme.AssemblyName + ",")).FirstOrDefault() == null)
|
|
||||||
{
|
|
||||||
// download assembly from server and load
|
|
||||||
var bytes = await _http.GetByteArrayAsync($"{Apiurl}/load/{theme.AssemblyName}.dll");
|
|
||||||
Assembly.Load(bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return themes.OrderBy(item => item.Name).ToList();
|
return themes.OrderBy(item => item.Name).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<string, string> GetThemeTypes(List<Theme> themes)
|
public List<ThemeControl> GetThemeControls(List<Theme> themes)
|
||||||
{
|
{
|
||||||
var selectableThemes = new Dictionary<string, string>();
|
return themes.SelectMany(item => item.Themes).ToList();
|
||||||
foreach (Theme theme in themes)
|
|
||||||
{
|
|
||||||
foreach (string themecontrol in theme.ThemeControls.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
|
||||||
{
|
|
||||||
selectableThemes.Add(themecontrol, theme.Name + " - " + Utilities.GetTypeNameLastSegment(themecontrol, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return selectableThemes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<string, string> GetPaneLayoutTypes(List<Theme> themes, string themeName)
|
public List<ThemeControl> GetLayoutControls(List<Theme> themes, string themeName)
|
||||||
{
|
{
|
||||||
var selectablePaneLayouts = new Dictionary<string, string>();
|
return themes.Where(item => Utilities.GetTypeName(themeName).StartsWith(Utilities.GetTypeName(item.ThemeName)))
|
||||||
foreach (Theme theme in themes)
|
.SelectMany(item => item.Layouts).ToList();
|
||||||
{
|
|
||||||
if (themeName.StartsWith(theme.ThemeName))
|
|
||||||
{
|
|
||||||
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 List<ThemeControl> GetContainerControls(List<Theme> themes, string themeName)
|
||||||
{
|
{
|
||||||
var selectableContainers = new Dictionary<string, string>();
|
return themes.Where(item => Utilities.GetTypeName(themeName).StartsWith(Utilities.GetTypeName(item.ThemeName)))
|
||||||
foreach (Theme theme in themes)
|
.SelectMany(item => item.Containers).ToList();
|
||||||
{
|
|
||||||
foreach (string container in theme.ContainerControls.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
|
||||||
{
|
|
||||||
selectableContainers.Add(container, theme.Name + " - " + @Utilities.GetTypeNameLastSegment(container, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return selectableContainers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InstallThemesAsync()
|
public async Task InstallThemesAsync()
|
||||||
{
|
{
|
||||||
await GetJsonAsync<List<string>>($"{Apiurl}/install");
|
await GetJsonAsync<List<string>>($"{ApiUrl}/install");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteThemeAsync(string themeName)
|
public async Task DeleteThemeAsync(string themeName)
|
||||||
{
|
{
|
||||||
await DeleteAsync($"{Apiurl}/{themeName}");
|
await DeleteAsync($"{ApiUrl}/{themeName}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,9 +28,13 @@
|
|||||||
@code {
|
@code {
|
||||||
public override string Panes => "Content";
|
public override string Panes => "Content";
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
{
|
{
|
||||||
await IncludeCSS("Theme.css");
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css", Integrity = "sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk", CrossOrigin = "anonymous" },
|
||||||
}
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" },
|
||||||
|
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://code.jquery.com/jquery-3.5.1.slim.min.js", Integrity = "sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj", CrossOrigin = "anonymous" },
|
||||||
|
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js", Integrity = "sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo", CrossOrigin = "anonymous" },
|
||||||
|
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js", Integrity = "sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI", CrossOrigin = "anonymous" }
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -1,63 +1,12 @@
|
|||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.JSInterop;
|
|
||||||
using Oqtane.Shared;
|
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.UI;
|
|
||||||
|
|
||||||
namespace Oqtane.Themes
|
namespace Oqtane.Themes
|
||||||
{
|
{
|
||||||
public class ContainerBase : ComponentBase, IContainerControl
|
public abstract class ContainerBase : ThemeBase, IContainerControl
|
||||||
{
|
{
|
||||||
[Inject]
|
|
||||||
protected IJSRuntime JSRuntime { get; set; }
|
|
||||||
|
|
||||||
[CascadingParameter]
|
|
||||||
protected PageState PageState { get; set; }
|
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
protected Module ModuleState { get; set; }
|
protected Module ModuleState { get; set; }
|
||||||
|
|
||||||
public virtual string Name { get; set; }
|
|
||||||
|
|
||||||
public string ThemePath()
|
|
||||||
{
|
|
||||||
return "Themes/" + GetType().Namespace + "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
public string NavigateUrl()
|
|
||||||
{
|
|
||||||
return NavigateUrl(PageState.Page.Path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string NavigateUrl(string path)
|
|
||||||
{
|
|
||||||
return NavigateUrl(path, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public string NavigateUrl(string path, string parameters)
|
|
||||||
{
|
|
||||||
return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string EditUrl(string action, string parameters)
|
|
||||||
{
|
|
||||||
return EditUrl(ModuleState.ModuleId, action, parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string EditUrl(int moduleid, string action)
|
|
||||||
{
|
|
||||||
return EditUrl(moduleid, action, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public string EditUrl(int moduleid, string action, string parameters)
|
|
||||||
{
|
|
||||||
return EditUrl(PageState.Page.Path, moduleid, action, parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string EditUrl(string path, int moduleid, string action, string parameters)
|
|
||||||
{
|
|
||||||
return Utilities.EditUrl(PageState.Alias.Path, path, moduleid, action, parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
@namespace Oqtane.Themes.Controls
|
@namespace Oqtane.Themes.Controls
|
||||||
@inherits ThemeControlBase
|
@inherits ThemeControlBase
|
||||||
@attribute [OqtaneIgnore]
|
|
||||||
|
|
||||||
@if (BreadCrumbPages.Any())
|
@if (BreadCrumbPages.Any())
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
@namespace Oqtane.Themes.Controls
|
@namespace Oqtane.Themes.Controls
|
||||||
@inherits ThemeControlBase
|
@inherits ThemeControlBase
|
||||||
@attribute [OqtaneIgnore]
|
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@inject IModuleDefinitionService ModuleDefinitionService
|
@inject IModuleDefinitionService ModuleDefinitionService
|
||||||
@ -9,8 +8,9 @@
|
|||||||
@inject IPageService PageService
|
@inject IPageService PageService
|
||||||
@inject IPageModuleService PageModuleService
|
@inject IPageModuleService PageModuleService
|
||||||
@inject ILogService logger
|
@inject ILogService logger
|
||||||
|
@inject ISettingService SettingService
|
||||||
|
|
||||||
@if (_moduleDefinitions != null && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, PageState.Page.Permissions))
|
@if (_moduleDefinitions != null && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
||||||
{
|
{
|
||||||
<div class="app-controlpanel" style="@_display">
|
<div class="app-controlpanel" style="@_display">
|
||||||
|
|
||||||
@ -49,6 +49,21 @@
|
|||||||
<button class="btn btn-danger btn-block mx-auto" @onclick="ConfirmDelete">Delete</button>
|
<button class="btn btn-danger btn-block mx-auto" @onclick="ConfirmDelete">Delete</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<br />
|
||||||
|
<div class="row">
|
||||||
|
@if (UserSecurity.GetPermissionStrings(PageState.Page.Permissions).FirstOrDefault(item => item.PermissionName == PermissionNames.View).Permissions.Split(';').Contains(Constants.AllUsersRole))
|
||||||
|
{
|
||||||
|
<div class="col">
|
||||||
|
<button type="button" class="btn btn-primary btn-block mx-auto" @onclick=@(async () => Publish("unpublish"))>Unpublish Page</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="col">
|
||||||
|
<button type="button" class="btn btn-primary btn-block mx-auto" @onclick=@(async () => Publish("publish"))>Publish Page</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (_deleteConfirmation)
|
@if (_deleteConfirmation)
|
||||||
@ -78,18 +93,18 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-center">
|
<div class="col text-center">
|
||||||
<label for="Module" class="control-label">Module Management: </label>
|
<label for="Module" class="control-label">Module Management: </label>
|
||||||
<select class="form-control" @bind="@_moduleType">
|
<select class="form-control" @bind="@ModuleType">
|
||||||
<option value="new">Add New Module</option>
|
<option value="new">Add New Module</option>
|
||||||
<option value="existing">Add Existing Module</option>
|
<option value="existing">Add Existing Module</option>
|
||||||
</select>
|
</select>
|
||||||
@if (_moduleType == "new")
|
@if (ModuleType == "new")
|
||||||
{
|
{
|
||||||
@if (_moduleDefinitions != null)
|
@if (_moduleDefinitions != null)
|
||||||
{
|
{
|
||||||
<select class="form-control" @onchange="(e => CategoryChanged(e))">
|
<select class="form-control" @onchange="(e => CategoryChanged(e))">
|
||||||
@foreach (var category in _categories)
|
@foreach (var category in _categories)
|
||||||
{
|
{
|
||||||
if (category == _category)
|
if (category == Category)
|
||||||
{
|
{
|
||||||
<option value="@category" selected>@category Modules</option>
|
<option value="@category" selected>@category Modules</option>
|
||||||
}
|
}
|
||||||
@ -100,7 +115,7 @@
|
|||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
<select class="form-control" @onchange="(e => ModuleChanged(e))">
|
<select class="form-control" @onchange="(e => ModuleChanged(e))">
|
||||||
@if (_moduleDefinitionName == "-")
|
@if (ModuleDefinitionName == "-")
|
||||||
{
|
{
|
||||||
<option value="-" selected><Select Module></option>
|
<option value="-" selected><Select Module></option>
|
||||||
}
|
}
|
||||||
@ -116,7 +131,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
@((MarkupString)@_description)
|
@((MarkupString) Description)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -128,7 +143,7 @@
|
|||||||
<option value="@p.PageId">@p.Name</option>
|
<option value="@p.PageId">@p.Name</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
<select class="form-control" @bind="@_moduleId">
|
<select class="form-control" @bind="@ModuleId">
|
||||||
<option value="-"><Select Module></option>
|
<option value="-"><Select Module></option>
|
||||||
@foreach (Module module in _modules)
|
@foreach (Module module in _modules)
|
||||||
{
|
{
|
||||||
@ -141,28 +156,30 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-center">
|
<div class="col text-center">
|
||||||
<label for="Title" class="control-label">Title: </label>
|
<label for="Title" class="control-label">Title: </label>
|
||||||
<input type="text" name="Title" class="form-control" @bind="@_title" />
|
<input type="text" name="Title" class="form-control" @bind="@Title" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@if (_pane.Length > 1)
|
||||||
|
{
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-center">
|
<div class="col text-center">
|
||||||
<label for="Pane" class="control-label">Pane: </label>
|
<label for="Pane" class="control-label">Pane: </label>
|
||||||
<select class="form-control" @bind="@_pane">
|
<select class="form-control" @bind="@Pane">
|
||||||
<option value=""><Select Pane></option>
|
@foreach (string pane in PageState.Page.Panes)
|
||||||
@foreach (string pane in PageState.Page.Panes.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
|
||||||
{
|
{
|
||||||
<option value="@pane">@pane Pane</option>
|
<option value="@pane">@pane Pane</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-center">
|
<div class="col text-center">
|
||||||
<label for="Container" class="control-label">Container: </label>
|
<label for="Container" class="control-label">Container: </label>
|
||||||
<select class="form-control" @bind="@_containerType">
|
<select class="form-control" @bind="@ContainerType">
|
||||||
@foreach (KeyValuePair<string, string> container in _containers)
|
@foreach (var container in _containers)
|
||||||
{
|
{
|
||||||
<option value="@container.Key">@container.Value</option>
|
<option value="@container.TypeName">@container.Name</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@ -171,13 +188,13 @@
|
|||||||
<br />
|
<br />
|
||||||
|
|
||||||
<button type="button" class="btn btn-primary btn-block mx-auto" @onclick="@AddModule">Add Module To Page</button>
|
<button type="button" class="btn btn-primary btn-block mx-auto" @onclick="@AddModule">Add Module To Page</button>
|
||||||
@((MarkupString) _message)
|
@((MarkupString) Message)
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, PageState.Page.Permissions) || (PageState.Page.IsPersonalizable && PageState.User != null))
|
@if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions) || (PageState.Page.IsPersonalizable && PageState.User != null))
|
||||||
{
|
{
|
||||||
@if (PageState.Page.EditMode)
|
@if (PageState.Page.EditMode)
|
||||||
{
|
{
|
||||||
@ -202,192 +219,179 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, PageState.Page.Permissions))
|
@if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
||||||
{
|
{
|
||||||
<button type="button" class="btn @ButtonClass" @onclick="ShowControlPanel">
|
<button type="button" class="btn @ButtonClass" @onclick="ShowControlPanel">
|
||||||
<span class="oi oi-cog"></span>
|
<span class="oi oi-cog"></span>
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code{
|
||||||
|
|
||||||
private bool _deleteConfirmation = false;
|
private bool _deleteConfirmation = false;
|
||||||
private string _moduleType = "new";
|
|
||||||
private List<string> _categories = new List<string>();
|
private List<string> _categories = new List<string>();
|
||||||
private List<ModuleDefinition> _allModuleDefinitions;
|
private List<ModuleDefinition> _allModuleDefinitions;
|
||||||
private List<ModuleDefinition> _moduleDefinitions;
|
private List<ModuleDefinition> _moduleDefinitions;
|
||||||
private List<Page> _pages = new List<Page>();
|
private List<Page> _pages = new List<Page>();
|
||||||
private string _pageId = "-";
|
|
||||||
private string _moduleId = "-";
|
|
||||||
private List<Module> _modules = new List<Module>();
|
private List<Module> _modules = new List<Module>();
|
||||||
private Dictionary<string, string> _containers = new Dictionary<string, string>();
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
private string _moduleDefinitionName = "-";
|
|
||||||
private string _category = "Common";
|
|
||||||
private string _description = "";
|
|
||||||
private string _pane = "";
|
|
||||||
private string _title = "";
|
|
||||||
private string _containerType = "";
|
|
||||||
private string _display = "display: none;";
|
private string _display = "display: none;";
|
||||||
private string _message = "";
|
private string _category = "Common";
|
||||||
|
|
||||||
[Parameter]
|
protected string PageId { get; private set; } = "-";
|
||||||
public string ButtonClass { get; set; }
|
protected string ModuleId { get; private set; } = "-";
|
||||||
|
protected string ModuleType { get; private set; } = "new";
|
||||||
|
protected string ModuleDefinitionName { get; private set; } = "-";
|
||||||
|
|
||||||
[Parameter]
|
protected string Category
|
||||||
public string CardClass { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string HeaderClass { get; set; }
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public string BodyClass { get; set; }
|
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(ButtonClass))
|
get => _category;
|
||||||
|
private set
|
||||||
{
|
{
|
||||||
ButtonClass = "btn-outline-secondary";
|
if (_category != value)
|
||||||
|
{
|
||||||
|
_category = value;
|
||||||
|
_moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(Category)).ToList();
|
||||||
|
ModuleDefinitionName = "-";
|
||||||
|
Description = "";
|
||||||
|
StateHasChanged();
|
||||||
|
_ = UpdateSettingsAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(CardClass))
|
protected string Pane
|
||||||
{
|
{
|
||||||
CardClass = "card border-secondary mb-3";
|
get => _pane;
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
if (_pane != value)
|
||||||
|
{
|
||||||
|
_pane = value;
|
||||||
|
_ = UpdateSettingsAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(HeaderClass))
|
|
||||||
{
|
|
||||||
HeaderClass = "card-header";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(BodyClass))
|
protected string Description { get; private set; } = "";
|
||||||
{
|
|
||||||
BodyClass = "card-body";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, PageState.Page.Permissions))
|
protected string Title { get; private set; } = "";
|
||||||
|
protected string ContainerType { get; private set; } = "";
|
||||||
|
protected string Message { get; private set; } = "";
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string ButtonClass { get; set; } = "btn-outline-secondary";
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string CardClass { get; set; } = "card border-secondary mb-3";
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string HeaderClass { get; set; } = "card-header";
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string BodyClass { get; set; } = "card-body";
|
||||||
|
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
||||||
{
|
{
|
||||||
_pages?.Clear();
|
_pages?.Clear();
|
||||||
|
|
||||||
foreach (Page p in PageState.Pages)
|
foreach (Page p in PageState.Pages)
|
||||||
{
|
{
|
||||||
if (UserSecurity.IsAuthorized(PageState.User,PermissionNames.View, p.Permissions))
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
|
||||||
{
|
{
|
||||||
_pages.Add(p);
|
_pages.Add(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
await LoadSettingsAsync();
|
||||||
|
|
||||||
var panes = PageState.Page.Panes.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
_pane = panes.Count() == 1 ? panes.SingleOrDefault() : "";
|
|
||||||
var themes = await ThemeService.GetThemesAsync();
|
var themes = await ThemeService.GetThemesAsync();
|
||||||
_containers = ThemeService.GetContainerTypes(themes);
|
_containers = ThemeService.GetContainerControls(themes, PageState.Page.ThemeType);
|
||||||
_containerType = PageState.Site.DefaultContainerType;
|
ContainerType = PageState.Site.DefaultContainerType;
|
||||||
|
|
||||||
_allModuleDefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
|
_allModuleDefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
|
||||||
|
_moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(Category)).ToList();
|
||||||
_categories = new List<string>();
|
_categories = _allModuleDefinitions.SelectMany(m => m.Categories.Split(',')).Distinct().ToList();
|
||||||
foreach (ModuleDefinition moduledefinition in _allModuleDefinitions)
|
|
||||||
{
|
|
||||||
if (moduledefinition.Categories != "")
|
|
||||||
{
|
|
||||||
foreach (string category in moduledefinition.Categories.Split(','))
|
|
||||||
{
|
|
||||||
if (!_categories.Contains(category))
|
|
||||||
{
|
|
||||||
_categories.Add(category);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_category = "Common";
|
|
||||||
_moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(_category)).ToList();
|
|
||||||
_moduleDefinitionName = "-";
|
|
||||||
_description = "";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CategoryChanged(ChangeEventArgs e)
|
private void CategoryChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
_category = (string) e.Value;
|
Category = (string) e.Value;
|
||||||
_moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(_category)).ToList();
|
|
||||||
_moduleDefinitionName = "-";
|
|
||||||
_description = "";
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ModuleChanged(ChangeEventArgs e)
|
private void ModuleChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
_moduleDefinitionName = (string)e.Value;
|
ModuleDefinitionName = (string) e.Value;
|
||||||
if (_moduleDefinitionName != "-")
|
if (ModuleDefinitionName != "-")
|
||||||
{
|
{
|
||||||
var moduleDefinition = _moduleDefinitions.FirstOrDefault(item => item.ModuleDefinitionName == _moduleDefinitionName);
|
var moduleDefinition = _moduleDefinitions.FirstOrDefault(item => item.ModuleDefinitionName == ModuleDefinitionName);
|
||||||
_description = "<br /><div class=\"alert alert-info\" role=\"alert\">" + moduleDefinition.Description + "</div>";
|
Description = "<br /><div class=\"alert alert-info\" role=\"alert\">" + moduleDefinition.Description + "</div>";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_description = "";
|
Description = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PageChanged(ChangeEventArgs e)
|
private void PageChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
_pageId = (string) e.Value;
|
PageId = (string) e.Value;
|
||||||
_modules?.Clear();
|
if (PageId != "-")
|
||||||
|
|
||||||
if (_pageId != "-")
|
|
||||||
{
|
{
|
||||||
foreach (Module module in PageState.Modules.Where(item => item.PageId == int.Parse(_pageId) && !item.IsDeleted))
|
_modules = PageState.Modules
|
||||||
{
|
.Where(module => module.PageId == int.Parse(PageId)
|
||||||
if (UserSecurity.IsAuthorized(PageState.User,PermissionNames.View, module.Permissions))
|
&& !module.IsDeleted
|
||||||
{
|
&& UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.Permissions))
|
||||||
_modules.Add(module);
|
.ToList();
|
||||||
}
|
}
|
||||||
}
|
ModuleId = "-";
|
||||||
}
|
|
||||||
|
|
||||||
_moduleId = "-";
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddModule()
|
private async Task AddModule()
|
||||||
{
|
{
|
||||||
if (UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, PageState.Page.Permissions))
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
||||||
{
|
{
|
||||||
if ((_moduleType == "new" && _moduleDefinitionName != "-") || (_moduleType != "new" && _moduleId != "-"))
|
if ((ModuleType == "new" && ModuleDefinitionName != "-") || (ModuleType != "new" && ModuleId != "-"))
|
||||||
{
|
{
|
||||||
if (_moduleType == "new")
|
if (ModuleType == "new")
|
||||||
{
|
{
|
||||||
Module module = new Module();
|
Module module = new Module();
|
||||||
module.SiteId = PageState.Site.SiteId;
|
module.SiteId = PageState.Site.SiteId;
|
||||||
module.PageId = PageState.Page.PageId;
|
module.PageId = PageState.Page.PageId;
|
||||||
module.ModuleDefinitionName = _moduleDefinitionName;
|
module.ModuleDefinitionName = ModuleDefinitionName;
|
||||||
module.AllPages = false;
|
module.AllPages = false;
|
||||||
module.Permissions = PageState.Page.Permissions;
|
module.Permissions = PageState.Page.Permissions;
|
||||||
module = await ModuleService.AddModuleAsync(module);
|
module = await ModuleService.AddModuleAsync(module);
|
||||||
_moduleId = module.ModuleId.ToString();
|
ModuleId = module.ModuleId.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
var pageModule = new PageModule
|
var pageModule = new PageModule
|
||||||
{
|
{
|
||||||
PageId = PageState.Page.PageId,
|
PageId = PageState.Page.PageId,
|
||||||
ModuleId = int.Parse(_moduleId),
|
ModuleId = int.Parse(ModuleId),
|
||||||
Title = _title
|
Title = Title
|
||||||
};
|
};
|
||||||
if (pageModule.Title == "")
|
if (pageModule.Title == "")
|
||||||
{
|
{
|
||||||
if (_moduleType == "new")
|
if (ModuleType == "new")
|
||||||
{
|
{
|
||||||
pageModule.Title = _moduleDefinitions.FirstOrDefault(item => item.ModuleDefinitionName == _moduleDefinitionName)?.Name;
|
pageModule.Title = _moduleDefinitions.FirstOrDefault(item => item.ModuleDefinitionName == ModuleDefinitionName)?.Name;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pageModule.Title = _modules.FirstOrDefault(item => item.ModuleId == int.Parse(_moduleId))?.Title;
|
pageModule.Title = _modules.FirstOrDefault(item => item.ModuleId == int.Parse(ModuleId))?.Title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pageModule.Pane = _pane;
|
pageModule.Pane = Pane;
|
||||||
pageModule.Order = int.MaxValue;
|
pageModule.Order = int.MaxValue;
|
||||||
pageModule.ContainerType = _containerType;
|
pageModule.ContainerType = ContainerType;
|
||||||
|
|
||||||
if (pageModule.ContainerType == PageState.Site.DefaultContainerType)
|
if (pageModule.ContainerType == PageState.Site.DefaultContainerType)
|
||||||
{
|
{
|
||||||
@ -397,32 +401,23 @@
|
|||||||
await PageModuleService.AddPageModuleAsync(pageModule);
|
await PageModuleService.AddPageModuleAsync(pageModule);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pageModule.PageId, pageModule.Pane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pageModule.PageId, pageModule.Pane);
|
||||||
|
|
||||||
_message = "<br /><div class=\"alert alert-success\" role=\"alert\">Module Added To Page</div>";
|
Message = "<br /><div class=\"alert alert-success\" role=\"alert\">Module Added To Page</div>";
|
||||||
|
|
||||||
_moduleDefinitionName = "-";
|
|
||||||
_description = "";
|
|
||||||
_pane = "";
|
|
||||||
_title = "";
|
|
||||||
_containerType = "";
|
|
||||||
_pageId = "-";
|
|
||||||
_moduleId = "-";
|
|
||||||
|
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_message = "<br /><div class=\"alert alert-warning\" role=\"alert\">You Must Select A Module</div>";
|
Message = "<br /><div class=\"alert alert-warning\" role=\"alert\">You Must Select A Module</div>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_message = "<br /><div class=\"alert alert-error\" role=\"alert\">Not Authorized</div>";
|
Message = "<br /><div class=\"alert alert-error\" role=\"alert\">Not Authorized</div>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ToggleEditMode(bool EditMode)
|
private async Task ToggleEditMode(bool EditMode)
|
||||||
{
|
{
|
||||||
if (UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, PageState.Page.Permissions))
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
||||||
{
|
{
|
||||||
if (EditMode)
|
if (EditMode)
|
||||||
{
|
{
|
||||||
@ -432,6 +427,7 @@
|
|||||||
{
|
{
|
||||||
PageState.EditMode = true;
|
PageState.EditMode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "edit=" + ((PageState.EditMode) ? "1" : "0")));
|
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "edit=" + ((PageState.EditMode) ? "1" : "0")));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -447,14 +443,14 @@
|
|||||||
|
|
||||||
private void ShowControlPanel()
|
private void ShowControlPanel()
|
||||||
{
|
{
|
||||||
_message = "";
|
Message = "";
|
||||||
_display = "width: 25%; min-width: 375px;";
|
_display = "width: 25%; min-width: 375px;";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HideControlPanel()
|
private void HideControlPanel()
|
||||||
{
|
{
|
||||||
_message = "";
|
Message = "";
|
||||||
_display = "width: 0%;";
|
_display = "width: 0%;";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
@ -503,6 +499,61 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void Publish(string action)
|
||||||
|
{
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
||||||
|
{
|
||||||
|
List<PermissionString> permissions;
|
||||||
|
|
||||||
|
if (action == "publish")
|
||||||
|
{
|
||||||
|
// publish all modules
|
||||||
|
foreach (var module in PageState.Modules.Where(item => item.PageId == PageState.Page.PageId))
|
||||||
|
{
|
||||||
|
permissions = UserSecurity.GetPermissionStrings(module.Permissions);
|
||||||
|
foreach (var permissionstring in permissions)
|
||||||
|
{
|
||||||
|
if (permissionstring.PermissionName == PermissionNames.View)
|
||||||
|
{
|
||||||
|
List<string> ids = permissionstring.Permissions.Split(';').ToList();
|
||||||
|
if (!ids.Contains(Constants.AllUsersRole)) ids.Add(Constants.AllUsersRole);
|
||||||
|
if (!ids.Contains(Constants.RegisteredRole)) ids.Add(Constants.RegisteredRole);
|
||||||
|
permissionstring.Permissions = string.Join(";", ids.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
module.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
||||||
|
await ModuleService.UpdateModuleAsync(module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// publish page
|
||||||
|
var page = PageState.Page;
|
||||||
|
permissions = UserSecurity.GetPermissionStrings(page.Permissions);
|
||||||
|
foreach (var permissionstring in permissions)
|
||||||
|
{
|
||||||
|
if (permissionstring.PermissionName == PermissionNames.View)
|
||||||
|
{
|
||||||
|
List<string> ids = permissionstring.Permissions.Split(';').ToList();
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case "publish":
|
||||||
|
if (!ids.Contains(Constants.AllUsersRole)) ids.Add(Constants.AllUsersRole);
|
||||||
|
if (!ids.Contains(Constants.RegisteredRole)) ids.Add(Constants.RegisteredRole);
|
||||||
|
break;
|
||||||
|
case "unpublish":
|
||||||
|
ids.Remove(Constants.AllUsersRole);
|
||||||
|
ids.Remove(Constants.RegisteredRole);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
permissionstring.Permissions = string.Join(";", ids.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
page.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
||||||
|
await PageService.UpdatePageAsync(page);
|
||||||
|
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "reload"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ConfirmDelete()
|
private void ConfirmDelete()
|
||||||
{
|
{
|
||||||
_deleteConfirmation = !_deleteConfirmation;
|
_deleteConfirmation = !_deleteConfirmation;
|
||||||
@ -536,4 +587,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string settingCategory = "CP-category";
|
||||||
|
private string settingPane = "CP-pane";
|
||||||
|
private string _pane = "";
|
||||||
|
|
||||||
|
private async Task LoadSettingsAsync()
|
||||||
|
{
|
||||||
|
Dictionary<string, string> settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
||||||
|
_category = SettingService.GetSetting(settings, settingCategory, "Common");
|
||||||
|
var pane = SettingService.GetSetting(settings, settingPane, "");
|
||||||
|
_pane = PageState.Page.Panes.Contains(pane) ? pane : PageState.Page.Panes.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdateSettingsAsync()
|
||||||
|
{
|
||||||
|
Dictionary<string, string> settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
||||||
|
SettingService.SetSetting(settings, settingCategory, _category);
|
||||||
|
SettingService.SetSetting(settings, settingPane, _pane);
|
||||||
|
await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
@namespace Oqtane.Themes.Controls
|
@namespace Oqtane.Themes.Controls
|
||||||
@inherits LoginBase
|
@inherits LoginBase
|
||||||
@attribute [OqtaneIgnore]
|
|
||||||
|
|
||||||
<span class="app-login">
|
<span class="app-login">
|
||||||
<AuthorizeView>
|
<AuthorizeView>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
@namespace Oqtane.Themes.Controls
|
@namespace Oqtane.Themes.Controls
|
||||||
@inherits ThemeControlBase
|
@inherits ThemeControlBase
|
||||||
@attribute [OqtaneIgnore]
|
|
||||||
|
|
||||||
@if (PageState.Site.LogoFileId != null)
|
@if (PageState.Site.LogoFileId != null)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
@namespace Oqtane.Themes.Controls
|
@namespace Oqtane.Themes.Controls
|
||||||
@inherits MenuBase
|
@inherits MenuBase
|
||||||
@attribute [OqtaneIgnore]
|
|
||||||
@if (MenuPages.Any())
|
@if (MenuPages.Any())
|
||||||
{
|
{
|
||||||
<span class="app-menu-toggler">
|
<span class="app-menu-toggler">
|
||||||
@ -16,7 +16,7 @@
|
|||||||
if (p.PageId == PageState.Page.PageId)
|
if (p.PageId == PageState.Page.PageId)
|
||||||
{
|
{
|
||||||
<li class="nav-item active">
|
<li class="nav-item active">
|
||||||
<a class="nav-link" href="@NavigateUrl(p.Path)">
|
<a class="nav-link" href="@GetUrl(p)" target="@GetTarget(p)" >
|
||||||
@if (p.Icon != string.Empty)
|
@if (p.Icon != string.Empty)
|
||||||
{
|
{
|
||||||
<span class="oi oi-@p.Icon" aria-hidden="true"></span>
|
<span class="oi oi-@p.Icon" aria-hidden="true"></span>
|
||||||
@ -28,7 +28,7 @@
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="@NavigateUrl(p.Path)">
|
<a class="nav-link" href="@GetUrl(p)" target="@GetTarget(p)" >
|
||||||
@if (p.Icon != string.Empty)
|
@if (p.Icon != string.Empty)
|
||||||
{
|
{
|
||||||
<span class="oi oi-@p.Icon" aria-hidden="true"></span>
|
<span class="oi oi-@p.Icon" aria-hidden="true"></span>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
@namespace Oqtane.Themes.Controls
|
@namespace Oqtane.Themes.Controls
|
||||||
@inherits MenuBase
|
@inherits MenuBase
|
||||||
@attribute [OqtaneIgnore]
|
|
||||||
@if (MenuPages.Any())
|
@if (MenuPages.Any())
|
||||||
{
|
{
|
||||||
<span class="app-menu-toggler">
|
<span class="app-menu-toggler">
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
@ -16,6 +17,7 @@ namespace Oqtane.Themes.Controls
|
|||||||
{
|
{
|
||||||
[Inject] public NavigationManager NavigationManager { get; set; }
|
[Inject] public NavigationManager NavigationManager { get; set; }
|
||||||
[Inject] public IPageModuleService PageModuleService { get; set; }
|
[Inject] public IPageModuleService PageModuleService { get; set; }
|
||||||
|
[Inject] public IModuleService ModuleService { get; set; }
|
||||||
|
|
||||||
protected List<ActionViewModel> Actions;
|
protected List<ActionViewModel> Actions;
|
||||||
|
|
||||||
@ -30,14 +32,23 @@ namespace Oqtane.Themes.Controls
|
|||||||
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, ModuleState.Permissions))
|
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, ModuleState.Permissions))
|
||||||
{
|
{
|
||||||
actionList.Add(new ActionViewModel {Name = "Manage Settings", Action = async (u, m) => await Settings(u, m)});
|
actionList.Add(new ActionViewModel {Name = "Manage Settings", Action = async (u, m) => await Settings(u, m)});
|
||||||
|
if (UserSecurity.GetPermissionStrings(ModuleState.Permissions).FirstOrDefault(item => item.PermissionName == PermissionNames.View).Permissions.Split(';').Contains(Constants.AllUsersRole))
|
||||||
|
{
|
||||||
|
actionList.Add(new ActionViewModel { Name = "Unpublish Module", Action = async (s, m) => await Unpublish(s, m) });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
actionList.Add(new ActionViewModel { Name = "Publish Module", Action = async (s, m) => await Publish(s, m) });
|
||||||
|
}
|
||||||
|
actionList.Add(new ActionViewModel { Name = "Delete Module", Action = async (u, m) => await DeleteModule(u, m) });
|
||||||
|
|
||||||
if (ModuleState.ModuleDefinition != null && ModuleState.ModuleDefinition.ServerManagerType != "")
|
if (ModuleState.ModuleDefinition != null && ModuleState.ModuleDefinition.ServerManagerType != "")
|
||||||
{
|
{
|
||||||
|
actionList.Add(new ActionViewModel { Name = "" });
|
||||||
actionList.Add(new ActionViewModel {Name = "Import Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Import")});
|
actionList.Add(new ActionViewModel {Name = "Import Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Import")});
|
||||||
actionList.Add(new ActionViewModel {Name = "Export Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Export")});
|
actionList.Add(new ActionViewModel {Name = "Export Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Export")});
|
||||||
}
|
}
|
||||||
|
|
||||||
actionList.Add(new ActionViewModel {Name = "Delete Module", Action = async (u, m) => await DeleteModule(u, m)});
|
|
||||||
actionList.Add(new ActionViewModel {Name = ""});
|
actionList.Add(new ActionViewModel {Name = ""});
|
||||||
|
|
||||||
if (ModuleState.PaneModuleIndex > 0)
|
if (ModuleState.PaneModuleIndex > 0)
|
||||||
@ -60,7 +71,7 @@ namespace Oqtane.Themes.Controls
|
|||||||
actionList.Add(new ActionViewModel {Name = "Move To Bottom", Action = async (s, m) => await MoveBottom(s, m)});
|
actionList.Add(new ActionViewModel {Name = "Move To Bottom", Action = async (s, m) => await MoveBottom(s, m)});
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (string pane in PageState.Page.Panes.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries))
|
foreach (string pane in PageState.Page.Panes)
|
||||||
{
|
{
|
||||||
if (pane != ModuleState.Pane)
|
if (pane != ModuleState.Pane)
|
||||||
{
|
{
|
||||||
@ -121,6 +132,42 @@ namespace Oqtane.Themes.Controls
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<string> Publish(string s, PageModule pagemodule)
|
||||||
|
{
|
||||||
|
var permissions = UserSecurity.GetPermissionStrings(pagemodule.Module.Permissions);
|
||||||
|
foreach (var permissionstring in permissions)
|
||||||
|
{
|
||||||
|
if (permissionstring.PermissionName == PermissionNames.View)
|
||||||
|
{
|
||||||
|
List<string> ids = permissionstring.Permissions.Split(';').ToList();
|
||||||
|
if (!ids.Contains(Constants.AllUsersRole)) ids.Add(Constants.AllUsersRole);
|
||||||
|
if (!ids.Contains(Constants.RegisteredRole)) ids.Add(Constants.RegisteredRole);
|
||||||
|
permissionstring.Permissions = string.Join(";", ids.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pagemodule.Module.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
||||||
|
await ModuleService.UpdateModuleAsync(pagemodule.Module);
|
||||||
|
return NavigateUrl(s, "reload");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string> Unpublish(string s, PageModule pagemodule)
|
||||||
|
{
|
||||||
|
var permissions = UserSecurity.GetPermissionStrings(pagemodule.Module.Permissions);
|
||||||
|
foreach (var permissionstring in permissions)
|
||||||
|
{
|
||||||
|
if (permissionstring.PermissionName == PermissionNames.View)
|
||||||
|
{
|
||||||
|
List<string> ids = permissionstring.Permissions.Split(';').ToList();
|
||||||
|
ids.Remove(Constants.AllUsersRole);
|
||||||
|
ids.Remove(Constants.RegisteredRole);
|
||||||
|
permissionstring.Permissions = string.Join(";", ids.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pagemodule.Module.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
||||||
|
await ModuleService.UpdateModuleAsync(pagemodule.Module);
|
||||||
|
return NavigateUrl(s, "reload");
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<string> MoveTop(string s, PageModule pagemodule)
|
private async Task<string> MoveTop(string s, PageModule pagemodule)
|
||||||
{
|
{
|
||||||
pagemodule.Order = 0;
|
pagemodule.Order = 0;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
@namespace Oqtane.Themes.Controls
|
@namespace Oqtane.Themes.Controls
|
||||||
@inherits ThemeControlBase
|
@inherits ThemeControlBase
|
||||||
@attribute [OqtaneIgnore]
|
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
<span class="app-profile">
|
<span class="app-profile">
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
{
|
{
|
||||||
public interface IContainerControl
|
public interface IContainerControl
|
||||||
{
|
{
|
||||||
string Name { get; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
{
|
{
|
||||||
public interface ILayoutControl
|
public interface ILayoutControl
|
||||||
{
|
{
|
||||||
string Panes { get; } // identifies all panes in a theme ( delimited by ";" )
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
namespace Oqtane.Themes
|
|
||||||
{
|
|
||||||
public interface IThemeControl
|
|
||||||
{
|
|
||||||
string Panes { get; } // identifies all panes in a theme ( delimited by ";" ) - assumed to be a layout if no panes specified
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +1,7 @@
|
|||||||
using Microsoft.AspNetCore.Components;
|
namespace Oqtane.Themes
|
||||||
using Oqtane.Shared;
|
|
||||||
using Oqtane.UI;
|
|
||||||
|
|
||||||
namespace Oqtane.Themes
|
|
||||||
{
|
{
|
||||||
public class LayoutBase : ComponentBase, ILayoutControl
|
public abstract class LayoutBase : ThemeBase, ILayoutControl
|
||||||
{
|
{
|
||||||
[CascadingParameter]
|
|
||||||
protected PageState PageState { get; set; }
|
|
||||||
public virtual string Panes { get; set; }
|
|
||||||
|
|
||||||
public string LayoutPath()
|
|
||||||
{
|
|
||||||
return "Themes/" + GetType().Namespace + "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,3 +13,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
public override string Name => "Standard Header";
|
||||||
|
}
|
@ -17,13 +17,16 @@
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
public override string Name => "Default";
|
||||||
|
|
||||||
public override string Panes => string.Empty;
|
public override string Panes => string.Empty;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
{
|
{
|
||||||
// go to https://www.bootstrapcdn.com/bootswatch/ and take your favorite theme
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://stackpath.bootstrapcdn.com/bootswatch/4.5.0/cyborg/bootstrap.min.css", Integrity = "sha384-GKugkVcT8wqoh3M8z1lqHbU+g6j498/ZT/zuXbepz7Dc09/otQZxTimkEMTkRWHP", CrossOrigin = "anonymous" },
|
||||||
//<link href="https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/cyborg/bootstrap.min.css" rel="stylesheet" integrity="sha384-l7xaoY0cJM4h9xh1RfazbgJVUZvdtyLWPueWNtLAphf/UbBgOVzqbOTogxPwYLHM" crossorigin="anonymous">
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" },
|
||||||
await LoadBootstrapTheme("https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/cyborg/bootstrap.min.css","sha384-l7xaoY0cJM4h9xh1RfazbgJVUZvdtyLWPueWNtLAphf/UbBgOVzqbOTogxPwYLHM");
|
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://code.jquery.com/jquery-3.5.1.slim.min.js", Integrity = "sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj", CrossOrigin = "anonymous" },
|
||||||
await IncludeCSS("Theme.css");
|
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js", Integrity = "sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo", CrossOrigin = "anonymous" },
|
||||||
}
|
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js", Integrity = "sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI", CrossOrigin = "anonymous" }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -14,5 +14,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
public override string Panes => "Top;Left;Content;Right;Bottom";
|
public override string Name => "Multiple Panes";
|
||||||
|
|
||||||
|
public override string Panes => "Top,Left,Content,Right,Bottom";
|
||||||
}
|
}
|
13
Oqtane.Client/Themes/OqtaneTheme/NoTitle.razor
Normal file
13
Oqtane.Client/Themes/OqtaneTheme/NoTitle.razor
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
@namespace Oqtane.Themes.OqtaneTheme
|
||||||
|
@inherits ContainerBase
|
||||||
|
<div class="container">
|
||||||
|
@if (PageState.EditMode)
|
||||||
|
{
|
||||||
|
<ModuleActions />
|
||||||
|
}
|
||||||
|
<ModuleInstance />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
public override string Name => "No Header";
|
||||||
|
}
|
@ -6,5 +6,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
public override string Name => "Single Pane";
|
||||||
|
|
||||||
public override string Panes => "Content";
|
public override string Panes => "Content";
|
||||||
}
|
}
|
@ -1,41 +1,55 @@
|
|||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
|
using Oqtane.Models;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
using Oqtane.UI;
|
using Oqtane.UI;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Oqtane.Themes
|
namespace Oqtane.Themes
|
||||||
{
|
{
|
||||||
public class ThemeBase : ComponentBase, IThemeControl
|
public abstract class ThemeBase : ComponentBase, IThemeControl
|
||||||
{
|
{
|
||||||
[Inject]
|
[Inject]
|
||||||
protected IJSRuntime JSRuntime { get; set; }
|
protected IJSRuntime JSRuntime { get; set; }
|
||||||
|
|
||||||
|
// optional interface properties
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
protected PageState PageState { get; set; }
|
protected PageState PageState { get; set; }
|
||||||
|
public virtual string Name { get; set; }
|
||||||
|
public virtual string Thumbnail { get; set; }
|
||||||
public virtual string Panes { get; set; }
|
public virtual string Panes { get; set; }
|
||||||
|
public virtual List<Resource> Resources { get; set; }
|
||||||
|
|
||||||
|
// base lifecycle method for handling JSInterop script registration
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
if (Resources != null && Resources.Exists(item => item.ResourceType == ResourceType.Script))
|
||||||
|
{
|
||||||
|
var scripts = new List<object>();
|
||||||
|
foreach (Resource resource in Resources.Where(item => item.ResourceType == ResourceType.Script))
|
||||||
|
{
|
||||||
|
scripts.Add(new { href = resource.Url, bundle = resource.Bundle ?? "", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "" });
|
||||||
|
}
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
await interop.IncludeScripts(scripts.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// path method
|
||||||
|
|
||||||
public string ThemePath()
|
public string ThemePath()
|
||||||
{
|
{
|
||||||
return "Themes/" + GetType().Namespace + "/";
|
return "Themes/" + GetType().Namespace + "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task IncludeCSS(string Url)
|
// url methods
|
||||||
{
|
|
||||||
if (!Url.StartsWith("http"))
|
|
||||||
{
|
|
||||||
Url = ThemePath() + Url;
|
|
||||||
}
|
|
||||||
var interop = new Interop(JSRuntime);
|
|
||||||
await interop.IncludeCSS("Theme", Url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task LoadBootstrapTheme(string url, string integrity = null)
|
|
||||||
{
|
|
||||||
var interop = new Interop(JSRuntime);
|
|
||||||
string crossorigin = string.IsNullOrEmpty(integrity) ? string.Empty : "anonymous";
|
|
||||||
await interop.IncludeLink("bootstrap", "stylesheet", url, "text/css", integrity, crossorigin);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string NavigateUrl()
|
public string NavigateUrl()
|
||||||
{
|
{
|
||||||
@ -66,5 +80,10 @@ namespace Oqtane.Themes
|
|||||||
{
|
{
|
||||||
return Utilities.EditUrl(PageState.Alias.Path, path, moduleid, action, parameters);
|
return Utilities.EditUrl(PageState.Alias.Path, path, moduleid, action, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string ContentUrl(int fileid)
|
||||||
|
{
|
||||||
|
return Utilities.ContentUrl(PageState.Alias, fileid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,47 +1,10 @@
|
|||||||
using Microsoft.AspNetCore.Components;
|
using Oqtane.Shared;
|
||||||
using Oqtane.Shared;
|
|
||||||
using Oqtane.UI;
|
|
||||||
|
|
||||||
namespace Oqtane.Themes
|
namespace Oqtane.Themes
|
||||||
{
|
{
|
||||||
public class ThemeControlBase : ComponentBase
|
[OqtaneIgnore]
|
||||||
|
public abstract class ThemeControlBase : ThemeBase
|
||||||
{
|
{
|
||||||
[CascadingParameter]
|
|
||||||
protected PageState PageState { get; set; }
|
|
||||||
|
|
||||||
public string NavigateUrl()
|
|
||||||
{
|
|
||||||
return NavigateUrl(PageState.Page.Path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string NavigateUrl(string path)
|
|
||||||
{
|
|
||||||
return NavigateUrl(path, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public string NavigateUrl(string path, string parameters)
|
|
||||||
{
|
|
||||||
return Utilities.NavigateUrl(PageState.Alias.Path, path, parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string EditUrl(int moduleid, string action)
|
|
||||||
{
|
|
||||||
return EditUrl(moduleid, action, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public string EditUrl(int moduleid, string action, string parameters)
|
|
||||||
{
|
|
||||||
return EditUrl(PageState.Page.Path, moduleid, action, parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string EditUrl(string path, int moduleid, string action, string parameters)
|
|
||||||
{
|
|
||||||
return Utilities.EditUrl(PageState.Alias.Path, path, moduleid, action, parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ContentUrl(int fileid)
|
|
||||||
{
|
|
||||||
return Utilities.ContentUrl(PageState.Alias, fileid);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,18 +27,13 @@
|
|||||||
DynamicComponent = builder =>
|
DynamicComponent = builder =>
|
||||||
{
|
{
|
||||||
Type containerType = Type.GetType(container);
|
Type containerType = Type.GetType(container);
|
||||||
if (containerType != null)
|
if (containerType == null)
|
||||||
{
|
{
|
||||||
|
// fallback
|
||||||
|
containerType = Type.GetType(Constants.DefaultContainer);
|
||||||
|
}
|
||||||
builder.OpenComponent(0, containerType);
|
builder.OpenComponent(0, containerType);
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// container does not exist with type specified
|
|
||||||
builder.OpenComponent(0, Type.GetType(Constants.ModuleMessageComponent));
|
|
||||||
builder.AddAttribute(1, "Message", "Error Loading Module Container " + container);
|
|
||||||
builder.CloseComponent();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,13 @@
|
|||||||
@inject IInstallationService InstallationService
|
@inject IInstallationService InstallationService
|
||||||
@inject ISiteService SiteService
|
@inject ISiteService SiteService
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
|
@inject IJSRuntime JSRuntime
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="mx-auto text-center">
|
<div class="mx-auto text-center">
|
||||||
<img src="oqtane.png" />
|
<img src="oqtane-black.png" />
|
||||||
|
<div style="font-weight: bold">Version: @Constants.Version</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr class="app-rule" />
|
<hr class="app-rule" />
|
||||||
@ -137,6 +139,15 @@
|
|||||||
private string _integratedSecurityDisplay = "display: none;";
|
private string _integratedSecurityDisplay = "display: none;";
|
||||||
private string _loadingDisplay = "display: none;";
|
private string _loadingDisplay = "display: none;";
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
await interop.IncludeLink("app-stylesheet", "stylesheet", "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css", "text/css", "sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T", "anonymous", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void SetIntegratedSecurity(ChangeEventArgs e)
|
private void SetIntegratedSecurity(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
_integratedSecurityDisplay = Convert.ToBoolean((string)e.Value)
|
_integratedSecurityDisplay = Convert.ToBoolean((string)e.Value)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.JSInterop;
|
||||||
using Microsoft.JSInterop;
|
using Oqtane.Models;
|
||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Oqtane.UI
|
namespace Oqtane.UI
|
||||||
@ -18,8 +17,8 @@ namespace Oqtane.UI
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_jsRuntime.InvokeAsync<string>(
|
_jsRuntime.InvokeVoidAsync(
|
||||||
"interop.setCookie",
|
"Oqtane.Interop.setCookie",
|
||||||
name, value, days);
|
name, value, days);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@ -34,7 +33,7 @@ namespace Oqtane.UI
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
return _jsRuntime.InvokeAsync<string>(
|
return _jsRuntime.InvokeAsync<string>(
|
||||||
"interop.getCookie",
|
"Oqtane.Interop.getCookie",
|
||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -47,8 +46,8 @@ namespace Oqtane.UI
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_jsRuntime.InvokeAsync<string>(
|
_jsRuntime.InvokeVoidAsync(
|
||||||
"interop.updateTitle",
|
"Oqtane.Interop.updateTitle",
|
||||||
title);
|
title);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@ -58,13 +57,13 @@ namespace Oqtane.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task IncludeMeta(string id, string attribute, string name, string content)
|
public Task IncludeMeta(string id, string attribute, string name, string content, string key)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_jsRuntime.InvokeAsync<string>(
|
_jsRuntime.InvokeVoidAsync(
|
||||||
"interop.includeMeta",
|
"Oqtane.Interop.includeMeta",
|
||||||
id, attribute, name, content);
|
id, attribute, name, content, key);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -73,13 +72,13 @@ namespace Oqtane.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task IncludeLink(string id, string rel, string url, string type, string integrity, string crossorigin)
|
public Task IncludeLink(string id, string rel, string href, string type, string integrity, string crossorigin, string key)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_jsRuntime.InvokeAsync<string>(
|
_jsRuntime.InvokeVoidAsync(
|
||||||
"interop.includeLink",
|
"Oqtane.Interop.includeLink",
|
||||||
id, rel, url, type, integrity, crossorigin);
|
id, rel, href, type, integrity, crossorigin, key);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -88,13 +87,13 @@ namespace Oqtane.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task IncludeScript(string id, string src, string content, string location, string integrity, string crossorigin)
|
public Task IncludeLinks(object[] links)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_jsRuntime.InvokeAsync<string>(
|
_jsRuntime.InvokeVoidAsync(
|
||||||
"interop.includeScript",
|
"Oqtane.Interop.includeLinks",
|
||||||
id, src, content, location, integrity, crossorigin);
|
(object) links);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -103,13 +102,42 @@ namespace Oqtane.UI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task IncludeCSS(string id, string url)
|
public Task IncludeScript(string id, string src, string integrity, string crossorigin, string content, string location, string key)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_jsRuntime.InvokeAsync<string>(
|
_jsRuntime.InvokeVoidAsync(
|
||||||
"interop.includeLink",
|
"Oqtane.Interop.includeScript",
|
||||||
id, "stylesheet", url, "text/css");
|
id, src, integrity, crossorigin, content, location, key);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task IncludeScripts(object[] scripts)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _jsRuntime.InvokeVoidAsync(
|
||||||
|
"Oqtane.Interop.includeScripts",
|
||||||
|
(object)scripts);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignore exception
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task RemoveElementsById(string prefix, string first, string last)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_jsRuntime.InvokeVoidAsync(
|
||||||
|
"Oqtane.Interop.removeElementsById",
|
||||||
|
prefix, first, last);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -123,7 +151,7 @@ namespace Oqtane.UI
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
return _jsRuntime.InvokeAsync<string>(
|
return _jsRuntime.InvokeAsync<string>(
|
||||||
"interop.getElementByName",
|
"Oqtane.Interop.getElementByName",
|
||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -136,8 +164,8 @@ namespace Oqtane.UI
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_jsRuntime.InvokeAsync<string>(
|
_jsRuntime.InvokeVoidAsync(
|
||||||
"interop.submitForm",
|
"Oqtane.Interop.submitForm",
|
||||||
path, fields);
|
path, fields);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@ -152,7 +180,7 @@ namespace Oqtane.UI
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
return _jsRuntime.InvokeAsync<string[]>(
|
return _jsRuntime.InvokeAsync<string[]>(
|
||||||
"interop.getFiles",
|
"Oqtane.Interop.getFiles",
|
||||||
id);
|
id);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -165,8 +193,8 @@ namespace Oqtane.UI
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_jsRuntime.InvokeAsync<string>(
|
_jsRuntime.InvokeVoidAsync(
|
||||||
"interop.uploadFiles",
|
"Oqtane.Interop.uploadFiles",
|
||||||
posturl, folder, id);
|
posturl, folder, id);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
@ -175,5 +203,36 @@ namespace Oqtane.UI
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task RefreshBrowser(bool force, int wait)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_jsRuntime.InvokeVoidAsync(
|
||||||
|
"Oqtane.Interop.refreshBrowser",
|
||||||
|
force, wait);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task RedirectBrowser(string url, int wait)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_jsRuntime.InvokeVoidAsync(
|
||||||
|
"Oqtane.Interop.redirectBrowser",
|
||||||
|
url, wait);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_paneadminborder = "";
|
_paneadminborder = "container";
|
||||||
_panetitle = "";
|
_panetitle = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,15 +13,13 @@
|
|||||||
DynamicComponent = builder =>
|
DynamicComponent = builder =>
|
||||||
{
|
{
|
||||||
var layoutType = Type.GetType(PageState.Page.LayoutType);
|
var layoutType = Type.GetType(PageState.Page.LayoutType);
|
||||||
if (layoutType != null)
|
if (layoutType == null)
|
||||||
{
|
{
|
||||||
|
// fallback
|
||||||
|
layoutType = Type.GetType(Constants.DefaultLayout);
|
||||||
|
}
|
||||||
builder.OpenComponent(0, layoutType);
|
builder.OpenComponent(0, layoutType);
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// layout does not exist with type specified
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,7 +11,6 @@
|
|||||||
@inject IPageService PageService
|
@inject IPageService PageService
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@inject IModuleService ModuleService
|
@inject IModuleService ModuleService
|
||||||
@inject IModuleDefinitionService ModuleDefinitionService
|
|
||||||
@inject ILogService LogService
|
@inject ILogService LogService
|
||||||
@implements IHandleAfterRender
|
@implements IHandleAfterRender
|
||||||
|
|
||||||
@ -91,7 +90,7 @@
|
|||||||
// parse querystring
|
// parse querystring
|
||||||
var querystring = ParseQueryString(uri.Query);
|
var querystring = ParseQueryString(uri.Query);
|
||||||
|
|
||||||
// the reload parameter is used during user login/logout
|
// the reload parameter is used to reload the PageState
|
||||||
if (querystring.ContainsKey("reload"))
|
if (querystring.ContainsKey("reload"))
|
||||||
{
|
{
|
||||||
reload = Reload.Site;
|
reload = Reload.Site;
|
||||||
@ -157,7 +156,6 @@
|
|||||||
|
|
||||||
if (PageState == null || reload >= Reload.Site)
|
if (PageState == null || reload >= Reload.Site)
|
||||||
{
|
{
|
||||||
await ModuleDefinitionService.LoadModuleDefinitionsAsync(site.SiteId, runtime);
|
|
||||||
pages = await PageService.GetPagesAsync(site.SiteId);
|
pages = await PageService.GetPagesAsync(site.SiteId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -175,13 +173,13 @@
|
|||||||
|
|
||||||
if (alias.Path != "")
|
if (alias.Path != "")
|
||||||
{
|
{
|
||||||
path = path.Replace(alias.Path + "/", "");
|
path = path.Substring(alias.Path.Length + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract admin route elements from path
|
// extract admin route elements from path
|
||||||
var segments = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
var segments = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
int result;
|
int result;
|
||||||
// check if path has moduleid and control specification ie. page/moduleid/control/
|
// check if path has moduleid and action specification ie. pagename/moduleid/action/
|
||||||
if (segments.Length >= 2 && int.TryParse(segments[segments.Length - 2], out result))
|
if (segments.Length >= 2 && int.TryParse(segments[segments.Length - 2], out result))
|
||||||
{
|
{
|
||||||
action = segments[segments.Length - 1];
|
action = segments[segments.Length - 1];
|
||||||
@ -190,7 +188,7 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// check if path has only moduleid specification ie. page/moduleid/
|
// check if path has moduleid specification ie. pagename/moduleid/
|
||||||
if (segments.Length >= 1 && int.TryParse(segments[segments.Length - 1], out result))
|
if (segments.Length >= 1 && int.TryParse(segments[segments.Length - 1], out result))
|
||||||
{
|
{
|
||||||
moduleid = result;
|
moduleid = result;
|
||||||
@ -240,21 +238,7 @@
|
|||||||
{
|
{
|
||||||
page = await ProcessPage(page, site, user);
|
page = await ProcessPage(page, site, user);
|
||||||
|
|
||||||
_pagestate = new PageState
|
if (PageState != null && (PageState.ModuleId != moduleid || PageState.Action != action))
|
||||||
{
|
|
||||||
Alias = alias,
|
|
||||||
Site = site,
|
|
||||||
Pages = pages,
|
|
||||||
Page = page,
|
|
||||||
User = user,
|
|
||||||
Uri = new Uri(_absoluteUri, UriKind.Absolute),
|
|
||||||
QueryString = querystring,
|
|
||||||
ModuleId = moduleid,
|
|
||||||
Action = action,
|
|
||||||
Runtime = runtime
|
|
||||||
};
|
|
||||||
|
|
||||||
if (PageState != null && (PageState.ModuleId != _pagestate.ModuleId || PageState.Action != _pagestate.Action))
|
|
||||||
{
|
{
|
||||||
reload = Reload.Page;
|
reload = Reload.Page;
|
||||||
}
|
}
|
||||||
@ -262,15 +246,29 @@
|
|||||||
if (PageState == null || reload >= Reload.Page)
|
if (PageState == null || reload >= Reload.Page)
|
||||||
{
|
{
|
||||||
modules = await ModuleService.GetModulesAsync(site.SiteId);
|
modules = await ModuleService.GetModulesAsync(site.SiteId);
|
||||||
modules = ProcessModules(modules, page.PageId, _pagestate.ModuleId, _pagestate.Action, page.Panes, site.DefaultContainerType);
|
(page, modules) = ProcessModules(page, modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
modules = PageState.Modules;
|
modules = PageState.Modules;
|
||||||
}
|
}
|
||||||
_pagestate.Modules = modules;
|
|
||||||
_pagestate.EditMode = editmode;
|
_pagestate = new PageState
|
||||||
_pagestate.LastSyncDate = lastsyncdate;
|
{
|
||||||
|
Alias = alias,
|
||||||
|
Site = site,
|
||||||
|
Pages = pages,
|
||||||
|
Page = page,
|
||||||
|
User = user,
|
||||||
|
Modules = modules,
|
||||||
|
Uri = new Uri(_absoluteUri, UriKind.Absolute),
|
||||||
|
QueryString = querystring,
|
||||||
|
ModuleId = moduleid,
|
||||||
|
Action = action,
|
||||||
|
EditMode = editmode,
|
||||||
|
LastSyncDate = lastsyncdate,
|
||||||
|
Runtime = runtime
|
||||||
|
};
|
||||||
|
|
||||||
OnStateChange?.Invoke(_pagestate);
|
OnStateChange?.Invoke(_pagestate);
|
||||||
}
|
}
|
||||||
@ -279,7 +277,6 @@
|
|||||||
{
|
{
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
await LogService.Log(null, null, null, GetType().AssemblyQualifiedName, Utilities.GetTypeNameLastSegment(GetType().AssemblyQualifiedName, 1), LogFunction.Security, LogLevel.Error, null, "Page Does Not Exist Or User Is Not Authorized To View Page {Path}", path);
|
|
||||||
// redirect to login page
|
// redirect to login page
|
||||||
NavigationManager.NavigateTo(Utilities.NavigateUrl(alias.Path, "login", "returnurl=" + path));
|
NavigationManager.NavigateTo(Utilities.NavigateUrl(alias.Path, "login", "returnurl=" + path));
|
||||||
}
|
}
|
||||||
@ -357,19 +354,36 @@
|
|||||||
page.ThemeType = site.DefaultThemeType;
|
page.ThemeType = site.DefaultThemeType;
|
||||||
page.LayoutType = site.DefaultLayoutType;
|
page.LayoutType = site.DefaultLayoutType;
|
||||||
}
|
}
|
||||||
Type type;
|
|
||||||
|
page.Panes = new List<string>();
|
||||||
|
page.Resources = new List<Resource>();
|
||||||
|
|
||||||
|
string panes = "";
|
||||||
|
Type themetype = Type.GetType(page.ThemeType);
|
||||||
|
if (themetype != null)
|
||||||
|
{
|
||||||
|
var themeobject = Activator.CreateInstance(themetype) as IThemeControl;
|
||||||
|
if (themeobject != null)
|
||||||
|
{
|
||||||
|
panes = themeobject.Panes;
|
||||||
|
page.Resources = ManagePageResources(page.Resources, themeobject.Resources);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(page.LayoutType))
|
if (!string.IsNullOrEmpty(page.LayoutType))
|
||||||
{
|
{
|
||||||
type = Type.GetType(page.LayoutType);
|
Type layouttype = Type.GetType(page.LayoutType);
|
||||||
}
|
if (layouttype != null)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
type = Type.GetType(page.ThemeType);
|
var layoutobject = Activator.CreateInstance(layouttype) as IThemeControl;
|
||||||
|
if (layoutobject != null)
|
||||||
|
{
|
||||||
|
panes = layoutobject.Panes;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var property = type.GetProperty("Panes");
|
page.Panes = panes.Replace(";", ",").Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||||
page.Panes = (string)property.GetValue(Activator.CreateInstance(type), null);
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@ -379,12 +393,12 @@
|
|||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Module> ProcessModules(List<Module> modules, int pageid, int moduleid, string control, string panes, string defaultcontainertype)
|
private (Page Page, List<Module> Modules) ProcessModules(Page page, List<Module> modules, int moduleid, string action, string defaultcontainertype)
|
||||||
{
|
{
|
||||||
var paneindex = new Dictionary<string, int>();
|
var paneindex = new Dictionary<string, int>();
|
||||||
foreach (Module module in modules)
|
foreach (Module module in modules)
|
||||||
{
|
{
|
||||||
if (module.PageId == pageid || module.ModuleId == moduleid)
|
if (module.PageId == page.PageId || module.ModuleId == moduleid)
|
||||||
{
|
{
|
||||||
var typename = string.Empty;
|
var typename = string.Empty;
|
||||||
if (module.ModuleDefinition != null)
|
if (module.ModuleDefinition != null)
|
||||||
@ -396,63 +410,72 @@
|
|||||||
typename = Constants.ErrorModule;
|
typename = Constants.ErrorModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (module.ModuleId == moduleid && control != "")
|
if (module.ModuleId == moduleid && action != "")
|
||||||
{
|
{
|
||||||
// check if the module defines custom routes
|
// check if the module defines custom routes
|
||||||
if (module.ModuleDefinition.ControlTypeRoutes != "")
|
if (module.ModuleDefinition.ControlTypeRoutes != "")
|
||||||
{
|
{
|
||||||
foreach (string route in module.ModuleDefinition.ControlTypeRoutes.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
foreach (string route in module.ModuleDefinition.ControlTypeRoutes.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
if (route.StartsWith(control + "="))
|
if (route.StartsWith(action + "="))
|
||||||
{
|
{
|
||||||
typename = route.Replace(control + "=", "");
|
typename = route.Replace(action + "=", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
module.ModuleType = typename.Replace(Constants.ActionToken, control);
|
module.ModuleType = typename.Replace(Constants.ActionToken, action);
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
module.ModuleType = typename.Replace(Constants.ActionToken, Constants.DefaultAction);
|
module.ModuleType = typename.Replace(Constants.ActionToken, Constants.DefaultAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get additional metadata from IModuleControl interface
|
||||||
|
typename = module.ModuleType;
|
||||||
|
if (Constants.DefaultModuleActions.Contains(action))
|
||||||
|
{
|
||||||
|
// core framework module action components
|
||||||
|
typename = Constants.DefaultModuleActionsTemplate.Replace(Constants.ActionToken, action);
|
||||||
|
}
|
||||||
|
Type moduletype = Type.GetType(typename);
|
||||||
|
|
||||||
|
// ensure component implements IModuleControl
|
||||||
|
if (moduletype != null && !moduletype.GetInterfaces().Contains(typeof(IModuleControl)))
|
||||||
|
{
|
||||||
|
module.ModuleType = "";
|
||||||
|
}
|
||||||
|
if (moduletype != null && module.ModuleType != "")
|
||||||
|
{
|
||||||
|
var moduleobject = Activator.CreateInstance(moduletype) as IModuleControl;
|
||||||
|
page.Resources = ManagePageResources(page.Resources, moduleobject.Resources);
|
||||||
|
|
||||||
|
// additional metadata needed for admin components
|
||||||
|
if (module.ModuleId == moduleid && action != "")
|
||||||
|
{
|
||||||
|
module.SecurityAccessLevel = moduleobject.SecurityAccessLevel;
|
||||||
|
module.ControlTitle = moduleobject.Title;
|
||||||
|
module.Actions = moduleobject.Actions;
|
||||||
|
module.UseAdminContainer = moduleobject.UseAdminContainer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ensure module's pane exists in current page and if not, assign it to the Admin pane
|
// ensure module's pane exists in current page and if not, assign it to the Admin pane
|
||||||
if (panes == null || !panes.ToLower().Contains(module.Pane.ToLower()))
|
if (page.Panes == null || page.Panes.FindIndex(item => item.Equals(module.Pane, StringComparison.OrdinalIgnoreCase)) == -1)
|
||||||
{
|
{
|
||||||
module.Pane = Constants.AdminPane;
|
module.Pane = Constants.AdminPane;
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate module position within pane
|
// calculate module position within pane
|
||||||
if (paneindex.ContainsKey(module.Pane))
|
if (paneindex.ContainsKey(module.Pane.ToLower()))
|
||||||
{
|
{
|
||||||
paneindex[module.Pane] += 1;
|
paneindex[module.Pane.ToLower()] += 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
paneindex.Add(module.Pane, 0);
|
paneindex.Add(module.Pane.ToLower(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.PaneModuleIndex = paneindex[module.Pane];
|
module.PaneModuleIndex = paneindex[module.Pane.ToLower()];
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(module.ContainerType))
|
if (string.IsNullOrEmpty(module.ContainerType))
|
||||||
{
|
{
|
||||||
@ -461,16 +484,32 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Module module in modules.Where(item => item.PageId == pageid))
|
foreach (Module module in modules.Where(item => item.PageId == page.PageId))
|
||||||
{
|
{
|
||||||
module.PaneModuleCount = paneindex[module.Pane] + 1;
|
module.PaneModuleCount = paneindex[module.Pane.ToLower()] + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return modules;
|
return (page, modules);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Resource> ManagePageResources(List<Resource> pageresources, List<Resource> resources)
|
||||||
|
{
|
||||||
|
if (resources != null)
|
||||||
|
{
|
||||||
|
foreach (var resource in resources)
|
||||||
|
{
|
||||||
|
// ensure resource does not exist already
|
||||||
|
if (pageresources.Find(item => item.Url == resource.Url) == null)
|
||||||
|
{
|
||||||
|
pageresources.Add(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pageresources;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Runtime GetRuntime()
|
private Runtime GetRuntime()
|
||||||
=> RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER"))
|
=> RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER"))
|
||||||
? Runtime.WebAssembly
|
? Runtime.WebAssembly
|
||||||
: Runtime.Server;
|
: Runtime.Server;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,15 @@
|
|||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
var interop = new Interop(JsRuntime);
|
var interop = new Interop(JsRuntime);
|
||||||
|
|
||||||
|
// handle page redirection
|
||||||
|
if (!string.IsNullOrEmpty(PageState.Page.Url))
|
||||||
|
{
|
||||||
|
NavigationManager.NavigateTo(PageState.Page.Url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set page title
|
||||||
if (!string.IsNullOrEmpty(PageState.Page.Title))
|
if (!string.IsNullOrEmpty(PageState.Page.Title))
|
||||||
{
|
{
|
||||||
await interop.UpdateTitle(PageState.Page.Title);
|
await interop.UpdateTitle(PageState.Page.Title);
|
||||||
@ -20,10 +29,23 @@
|
|||||||
{
|
{
|
||||||
await interop.UpdateTitle(PageState.Site.Name + " - " + PageState.Page.Name);
|
await interop.UpdateTitle(PageState.Site.Name + " - " + PageState.Page.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// manage stylesheets for this page
|
||||||
|
string batch = DateTime.Now.ToString("yyyyMMddHHmmssfff");
|
||||||
|
var links = new List<object>();
|
||||||
|
foreach (Resource resource in PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Stylesheet))
|
||||||
|
{
|
||||||
|
links.Add(new { id = "app-stylesheet-" + batch + "-" + (links.Count + 1).ToString("00"), rel = "stylesheet", href = resource.Url, type = "text/css", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "", key = "" });
|
||||||
|
}
|
||||||
|
await interop.IncludeLinks(links.ToArray());
|
||||||
|
await interop.RemoveElementsById("app-stylesheet", "", "app-stylesheet-" + batch + "-00");
|
||||||
|
|
||||||
|
// add favicon
|
||||||
if (PageState.Site.FaviconFileId != null)
|
if (PageState.Site.FaviconFileId != null)
|
||||||
{
|
{
|
||||||
await interop.IncludeLink("fav-icon", "shortcut icon", Utilities.ContentUrl(PageState.Alias, PageState.Site.FaviconFileId.Value), "image/x-icon", "", "");
|
await interop.IncludeLink("app-favicon", "shortcut icon", Utilities.ContentUrl(PageState.Alias, PageState.Site.FaviconFileId.Value), "image/x-icon", "", "", "id");
|
||||||
}
|
}
|
||||||
|
// add PWA support
|
||||||
if (PageState.Site.PwaIsEnabled)
|
if (PageState.Site.PwaIsEnabled)
|
||||||
{
|
{
|
||||||
await InitializePwa(interop);
|
await InitializePwa(interop);
|
||||||
@ -32,18 +54,13 @@
|
|||||||
DynamicComponent = builder =>
|
DynamicComponent = builder =>
|
||||||
{
|
{
|
||||||
var themeType = Type.GetType(PageState.Page.ThemeType);
|
var themeType = Type.GetType(PageState.Page.ThemeType);
|
||||||
if (themeType != null)
|
if (themeType == null)
|
||||||
{
|
{
|
||||||
|
// fallback
|
||||||
|
themeType = Type.GetType(Constants.DefaultTheme);
|
||||||
|
}
|
||||||
builder.OpenComponent(0, themeType);
|
builder.OpenComponent(0, themeType);
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,10 +88,10 @@
|
|||||||
"const serialized = JSON.stringify(manifest); " +
|
"const serialized = JSON.stringify(manifest); " +
|
||||||
"const blob = new Blob([serialized], {type: 'application/javascript'}); " +
|
"const blob = new Blob([serialized], {type: 'application/javascript'}); " +
|
||||||
"const url = URL.createObjectURL(blob); " +
|
"const url = URL.createObjectURL(blob); " +
|
||||||
"document.getElementById('pwa-manifest').setAttribute('href', url); " +
|
"document.getElementById('app-manifest').setAttribute('href', url); " +
|
||||||
"} " +
|
"} " +
|
||||||
", 1000);";
|
", 1000);";
|
||||||
await interop.IncludeScript("pwa-manifestscript", "", manifest, "body", "", "");
|
await interop.IncludeScript("app-pwa", "", "", "", manifest, "body", "id");
|
||||||
|
|
||||||
// service worker must be in root of site
|
// service worker must be in root of site
|
||||||
string serviceworker = "if ('serviceWorker' in navigator) { " +
|
string serviceworker = "if ('serviceWorker' in navigator) { " +
|
||||||
@ -84,6 +101,6 @@
|
|||||||
"console.log('ServiceWorker Registration Failed ', err); " +
|
"console.log('ServiceWorker Registration Failed ', err); " +
|
||||||
"}); " +
|
"}); " +
|
||||||
"}";
|
"}";
|
||||||
await interop.IncludeScript("pwa-serviceworker", "", serviceworker, "body", "", "");
|
await interop.IncludeScript("app-serviceworker", "", "", "", serviceworker, "body", "id");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
23
Oqtane.Package/Oqtane.Client.nuspec
Normal file
23
Oqtane.Package/Oqtane.Client.nuspec
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
|
<metadata>
|
||||||
|
<id>Oqtane.Client</id>
|
||||||
|
<version>1.0.1</version>
|
||||||
|
<authors>Shaun Walker</authors>
|
||||||
|
<owners>.NET Foundation</owners>
|
||||||
|
<title>Oqtane Framework</title>
|
||||||
|
<description>A modular application framework for Blazor</description>
|
||||||
|
<copyright>.NET Foundation</copyright>
|
||||||
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
|
<license type="expression">MIT</license>
|
||||||
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
|
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
|
||||||
|
<tags>oqtane</tags>
|
||||||
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</releaseNotes>
|
||||||
|
<summary>A modular application framework for Blazor</summary>
|
||||||
|
</metadata>
|
||||||
|
<files>
|
||||||
|
<file src="..\Oqtane.Client\bin\Release\netstandard2.1\Oqtane.Client.dll" target="lib\netstandard2.1" />
|
||||||
|
<file src="..\Oqtane.Client\bin\Release\netstandard2.1\Oqtane.Client.pdb" target="lib\netstandard2.1" />
|
||||||
|
</files>
|
||||||
|
</package>
|
@ -2,7 +2,7 @@
|
|||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Framework</id>
|
<id>Oqtane.Framework</id>
|
||||||
<version>0.9.1</version>
|
<version>1.0.1</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane Framework</title>
|
<title>Oqtane Framework</title>
|
||||||
@ -13,13 +13,16 @@
|
|||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
|
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
|
||||||
<tags>oqtane framework</tags>
|
<tags>oqtane framework</tags>
|
||||||
<releaseNotes>Initial Release</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</releaseNotes>
|
||||||
<summary>A modular application framework for Blazor</summary>
|
<summary>A modular application framework for Blazor</summary>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
<file src="..\Oqtane.Client\bin\Release\netstandard2.1\Oqtane.Client.dll" target="lib" />
|
<file src="..\Oqtane.Client\bin\Release\netstandard2.1\Oqtane.Client.dll" target="lib\netcoreapp3.1" />
|
||||||
<file src="..\Oqtane.Server\bin\Release\netcoreapp3.1\Oqtane.Server.dll" target="lib" />
|
<file src="..\Oqtane.Client\bin\Release\netstandard2.1\Oqtane.Client.pdb" target="lib\netcoreapp3.1" />
|
||||||
<file src="..\Oqtane.Shared\bin\Release\netstandard2.1\Oqtane.Shared.dll" target="lib" />
|
<file src="..\Oqtane.Server\bin\Release\netcoreapp3.1\Oqtane.Server.dll" target="lib\netcoreapp3.1" />
|
||||||
<file src="..\Oqtane.Server\bin\Release\netcoreapp3.1\Oqtane.Upgrade.dll" target="lib" />
|
<file src="..\Oqtane.Server\bin\Release\netcoreapp3.1\Oqtane.Server.pdb" target="lib\netcoreapp3.1" />
|
||||||
|
<file src="..\Oqtane.Shared\bin\Release\netstandard2.1\Oqtane.Shared.dll" target="lib\netcoreapp3.1" />
|
||||||
|
<file src="..\Oqtane.Shared\bin\Release\netstandard2.1\Oqtane.Shared.pdb" target="lib\netcoreapp3.1" />
|
||||||
|
<file src="..\Oqtane.Server\wwwroot\**\*.*" target="wwwroot" />
|
||||||
</files>
|
</files>
|
||||||
</package>
|
</package>
|
23
Oqtane.Package/Oqtane.Server.nuspec
Normal file
23
Oqtane.Package/Oqtane.Server.nuspec
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
|
<metadata>
|
||||||
|
<id>Oqtane.Server</id>
|
||||||
|
<version>1.0.1</version>
|
||||||
|
<authors>Shaun Walker</authors>
|
||||||
|
<owners>.NET Foundation</owners>
|
||||||
|
<title>Oqtane Framework</title>
|
||||||
|
<description>A modular application framework for Blazor</description>
|
||||||
|
<copyright>.NET Foundation</copyright>
|
||||||
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
|
<license type="expression">MIT</license>
|
||||||
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
|
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
|
||||||
|
<tags>oqtane</tags>
|
||||||
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</releaseNotes>
|
||||||
|
<summary>A modular application framework for Blazor</summary>
|
||||||
|
</metadata>
|
||||||
|
<files>
|
||||||
|
<file src="..\Oqtane.Server\bin\Release\netcoreapp3.1\Oqtane.Server.dll" target="lib\netcoreapp3.1" />
|
||||||
|
<file src="..\Oqtane.Server\bin\Release\netcoreapp3.1\Oqtane.Server.pdb" target="lib\netcoreapp3.1" />
|
||||||
|
</files>
|
||||||
|
</package>
|
23
Oqtane.Package/Oqtane.Shared.nuspec
Normal file
23
Oqtane.Package/Oqtane.Shared.nuspec
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
|
<metadata>
|
||||||
|
<id>Oqtane.Shared</id>
|
||||||
|
<version>1.0.1</version>
|
||||||
|
<authors>Shaun Walker</authors>
|
||||||
|
<owners>.NET Foundation</owners>
|
||||||
|
<title>Oqtane Framework</title>
|
||||||
|
<description>A modular application framework for Blazor</description>
|
||||||
|
<copyright>.NET Foundation</copyright>
|
||||||
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
|
<license type="expression">MIT</license>
|
||||||
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
|
<iconUrl>https://www.oqtane.org/Portals/0/icon.jpg</iconUrl>
|
||||||
|
<tags>oqtane</tags>
|
||||||
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v1.0.1</releaseNotes>
|
||||||
|
<summary>A modular application framework for Blazor</summary>
|
||||||
|
</metadata>
|
||||||
|
<files>
|
||||||
|
<file src="..\Oqtane.Shared\bin\Release\netstandard2.1\Oqtane.Shared.dll" target="lib\netstandard2.1" />
|
||||||
|
<file src="..\Oqtane.Shared\bin\Release\netstandard2.1\Oqtane.Shared.pdb" target="lib\netstandard2.1" />
|
||||||
|
</files>
|
||||||
|
</package>
|
@ -1,3 +0,0 @@
|
|||||||
DEL "*.nupkg"
|
|
||||||
nuget.exe pack Oqtane.Framework.nuspec
|
|
||||||
|
|
5
Oqtane.Package/release.cmd
Normal file
5
Oqtane.Package/release.cmd
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
DEL "*.nupkg"
|
||||||
|
dotnet clean -c Release ..\Oqtane.sln
|
||||||
|
dotnet build -c Release ..\Oqtane.sln
|
||||||
|
dotnet pack -o .\ -c Release ..\Oqtane.sln
|
||||||
|
nuget.exe pack Oqtane.Framework.nuspec
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
@ -47,7 +47,7 @@ namespace Oqtane.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GET api/<controller>/name/xxx?sync=yyyyMMddHHmmssfff
|
// GET api/<controller>/name/xxx?sync=yyyyMMddHHmmssfff
|
||||||
[HttpGet("name/{name}")]
|
[HttpGet("name/{**name}")]
|
||||||
public Alias Get(string name, string sync)
|
public Alias Get(string name, string sync)
|
||||||
{
|
{
|
||||||
List<Alias> aliases = _aliases.GetAliases().ToList(); // cached
|
List<Alias> aliases = _aliases.GetAliases().ToList(); // cached
|
||||||
|
@ -16,6 +16,7 @@ using System.Net;
|
|||||||
using Oqtane.Enums;
|
using Oqtane.Enums;
|
||||||
using Oqtane.Infrastructure;
|
using Oqtane.Infrastructure;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
|
using Microsoft.AspNetCore.Routing.Constraints;
|
||||||
|
|
||||||
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
||||||
|
|
||||||
@ -64,7 +65,7 @@ namespace Oqtane.Controllers
|
|||||||
{
|
{
|
||||||
foreach (string file in Directory.GetFiles(folder))
|
foreach (string file in Directory.GetFiles(folder))
|
||||||
{
|
{
|
||||||
files.Add(new Models.File {Name = Path.GetFileName(file), Extension = Path.GetExtension(file)?.Replace(".", "")});
|
files.Add(new Models.File { Name = Path.GetFileName(file), Extension = Path.GetExtension(file)?.Replace(".", "") });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -188,14 +189,37 @@ namespace Oqtane.Controllers
|
|||||||
{
|
{
|
||||||
Models.File file = null;
|
Models.File file = null;
|
||||||
Folder folder = _folders.GetFolder(int.Parse(folderid));
|
Folder folder = _folders.GetFolder(int.Parse(folderid));
|
||||||
if (folder != null && _userPermissions.IsAuthorized(User, PermissionNames.Edit, folder.Permissions))
|
|
||||||
|
if (folder == null || !_userPermissions.IsAuthorized(User, PermissionNames.Edit, folder.Permissions))
|
||||||
{
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Create,
|
||||||
|
"User Not Authorized To Download File {Url} {FolderId}", url, folderid);
|
||||||
|
HttpContext.Response.StatusCode = 401;
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
string folderPath = GetFolderPath(folder);
|
string folderPath = GetFolderPath(folder);
|
||||||
CreateDirectory(folderPath);
|
CreateDirectory(folderPath);
|
||||||
|
|
||||||
string filename = url.Substring(url.LastIndexOf("/", StringComparison.Ordinal) + 1);
|
string filename = url.Substring(url.LastIndexOf("/", StringComparison.Ordinal) + 1);
|
||||||
// check for allowable file extensions
|
// check for allowable file extensions
|
||||||
if (Constants.UploadableFiles.Contains(Path.GetExtension(filename).Replace(".", "")))
|
if (!Constants.UploadableFiles.Split(',')
|
||||||
|
.Contains(Path.GetExtension(filename).ToLower().Replace(".", "")))
|
||||||
{
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Create,
|
||||||
|
"File Could Not Be Downloaded From Url Due To Its File Extension {Url}", url);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict;
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!filename.IsPathOrFileValid())
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Create,
|
||||||
|
$"File Could Not Be Downloaded From Url Due To Its File Name Not Allowed {url}");
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict;
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var client = new WebClient();
|
var client = new WebClient();
|
||||||
@ -207,22 +231,12 @@ namespace Oqtane.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
client.DownloadFile(url, targetPath);
|
client.DownloadFile(url, targetPath);
|
||||||
_files.AddFile(CreateFile(filename, folder.FolderId, targetPath));
|
file = _files.AddFile(CreateFile(filename, folder.FolderId, targetPath));
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Create, "File Could Not Be Downloaded From Url {Url}", url);
|
_logger.Log(LogLevel.Error, this, LogFunction.Create,
|
||||||
}
|
"File Could Not Be Downloaded From Url {Url}", url);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Create, "File Could Not Be Downloaded From Url Due To Its File Extension {Url}", url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Create, "User Not Authorized To Download File {Url} {FolderId}", url, folderid);
|
|
||||||
HttpContext.Response.StatusCode = 401;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
@ -232,14 +246,24 @@ namespace Oqtane.Controllers
|
|||||||
[HttpPost("upload")]
|
[HttpPost("upload")]
|
||||||
public async Task UploadFile(string folder, IFormFile file)
|
public async Task UploadFile(string folder, IFormFile file)
|
||||||
{
|
{
|
||||||
if (file.Length > 0)
|
if (file.Length <= 0)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file.FileName.IsPathOrFileValid())
|
||||||
|
{
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
string folderPath = "";
|
string folderPath = "";
|
||||||
|
|
||||||
if (int.TryParse(folder, out int folderId))
|
if (int.TryParse(folder, out int folderId))
|
||||||
{
|
{
|
||||||
Folder virtualFolder = _folders.GetFolder(folderId);
|
Folder virtualFolder = _folders.GetFolder(folderId);
|
||||||
if (virtualFolder != null && _userPermissions.IsAuthorized(User, PermissionNames.Edit, virtualFolder.Permissions))
|
if (virtualFolder != null &&
|
||||||
|
_userPermissions.IsAuthorized(User, PermissionNames.Edit, virtualFolder.Permissions))
|
||||||
{
|
{
|
||||||
folderPath = GetFolderPath(virtualFolder);
|
folderPath = GetFolderPath(virtualFolder);
|
||||||
}
|
}
|
||||||
@ -268,11 +292,11 @@ namespace Oqtane.Controllers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Create, "User Not Authorized To Upload File {Folder} {File}", folder, file);
|
_logger.Log(LogLevel.Error, this, LogFunction.Create,
|
||||||
|
"User Not Authorized To Upload File {Folder} {File}", folder, file);
|
||||||
HttpContext.Response.StatusCode = 401;
|
HttpContext.Response.StatusCode = 401;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<string> MergeFile(string folder, string filename)
|
private async Task<string> MergeFile(string folder, string filename)
|
||||||
{
|
{
|
||||||
@ -282,7 +306,8 @@ namespace Oqtane.Controllers
|
|||||||
string token = ".part_";
|
string token = ".part_";
|
||||||
string parts = Path.GetExtension(filename)?.Replace(token, ""); // returns "x_y"
|
string parts = Path.GetExtension(filename)?.Replace(token, ""); // returns "x_y"
|
||||||
int totalparts = int.Parse(parts?.Substring(parts.IndexOf("_") + 1));
|
int totalparts = int.Parse(parts?.Substring(parts.IndexOf("_") + 1));
|
||||||
filename = filename?.Substring(0, filename.IndexOf(token)); // base filename
|
|
||||||
|
filename = Path.GetFileNameWithoutExtension(filename); // base filename
|
||||||
string[] fileParts = Directory.GetFiles(folder, filename + token + "*"); // list of all file parts
|
string[] fileParts = Directory.GetFiles(folder, filename + token + "*"); // list of all file parts
|
||||||
|
|
||||||
// if all of the file parts exist ( note that file parts can arrive out of order )
|
// if all of the file parts exist ( note that file parts can arrive out of order )
|
||||||
@ -317,7 +342,7 @@ namespace Oqtane.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check for allowable file extensions
|
// check for allowable file extensions
|
||||||
if (!Constants.UploadableFiles.Contains(Path.GetExtension(filename)?.Replace(".", "")))
|
if (!Constants.UploadableFiles.Split(',').Contains(Path.GetExtension(filename)?.ToLower().Replace(".", "")))
|
||||||
{
|
{
|
||||||
System.IO.File.Delete(Path.Combine(folder, filename + ".tmp"));
|
System.IO.File.Delete(Path.Combine(folder, filename + ".tmp"));
|
||||||
}
|
}
|
||||||
@ -339,13 +364,15 @@ namespace Oqtane.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// clean up file parts which are more than 2 hours old ( which can happen if a prior file upload failed )
|
// clean up file parts which are more than 2 hours old ( which can happen if a prior file upload failed )
|
||||||
fileParts = Directory.GetFiles(folder, "*" + token + "*");
|
var cleanupFiles = Directory.EnumerateFiles(folder, "*" + token + "*")
|
||||||
foreach (string filepart in fileParts)
|
.Where(f => Path.GetExtension(f).StartsWith(token));
|
||||||
|
|
||||||
|
foreach (var file in cleanupFiles)
|
||||||
{
|
{
|
||||||
DateTime createddate = System.IO.File.GetCreationTime(filepart).ToUniversalTime();
|
var createdDate = System.IO.File.GetCreationTime(file).ToUniversalTime();
|
||||||
if (createddate < DateTime.UtcNow.AddHours(-2))
|
if (createdDate < DateTime.UtcNow.AddHours(-2))
|
||||||
{
|
{
|
||||||
System.IO.File.Delete(filepart);
|
System.IO.File.Delete(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,12 +423,13 @@ namespace Oqtane.Controllers
|
|||||||
[HttpGet("download/{id}")]
|
[HttpGet("download/{id}")]
|
||||||
public IActionResult Download(int id)
|
public IActionResult Download(int id)
|
||||||
{
|
{
|
||||||
|
string errorpath = Path.Combine(GetFolderPath("images"), "error.png");
|
||||||
Models.File file = _files.GetFile(id);
|
Models.File file = _files.GetFile(id);
|
||||||
if (file != null)
|
if (file != null)
|
||||||
{
|
{
|
||||||
if (_userPermissions.IsAuthorized(User, PermissionNames.View, file.Folder.Permissions))
|
if (_userPermissions.IsAuthorized(User, PermissionNames.View, file.Folder.Permissions))
|
||||||
{
|
{
|
||||||
string filepath = Path.Combine(GetFolderPath(file.Folder) , file.Name);
|
string filepath = Path.Combine(GetFolderPath(file.Folder), file.Name);
|
||||||
if (System.IO.File.Exists(filepath))
|
if (System.IO.File.Exists(filepath))
|
||||||
{
|
{
|
||||||
byte[] filebytes = System.IO.File.ReadAllBytes(filepath);
|
byte[] filebytes = System.IO.File.ReadAllBytes(filepath);
|
||||||
@ -411,22 +439,29 @@ namespace Oqtane.Controllers
|
|||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FileId} {FilePath}", id, filepath);
|
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Does Not Exist {FileId} {FilePath}", id, filepath);
|
||||||
HttpContext.Response.StatusCode = 404;
|
HttpContext.Response.StatusCode = 404;
|
||||||
return null;
|
if (System.IO.File.Exists(errorpath))
|
||||||
|
{
|
||||||
|
byte[] filebytes = System.IO.File.ReadAllBytes(errorpath);
|
||||||
|
return File(filebytes, "application/octet-stream", file.Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Read, "User Not Authorized To Access File {FileId}", id);
|
_logger.Log(LogLevel.Error, this, LogFunction.Read, "User Not Authorized To Access File {FileId}", id);
|
||||||
HttpContext.Response.StatusCode = 401;
|
HttpContext.Response.StatusCode = 401;
|
||||||
return null;
|
byte[] filebytes = System.IO.File.ReadAllBytes(errorpath);
|
||||||
|
return File(filebytes, "application/octet-stream", file.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Not Found {FileId}", id);
|
_logger.Log(LogLevel.Error, this, LogFunction.Read, "File Not Found {FileId}", id);
|
||||||
HttpContext.Response.StatusCode = 404;
|
HttpContext.Response.StatusCode = 404;
|
||||||
return null;
|
byte[] filebytes = System.IO.File.ReadAllBytes(errorpath);
|
||||||
|
return File(filebytes, "application/octet-stream", "error.png");
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetFolderPath(Folder folder)
|
private string GetFolderPath(Folder folder)
|
||||||
@ -448,7 +483,7 @@ namespace Oqtane.Controllers
|
|||||||
string[] folders = folderpath.Split(separators, StringSplitOptions.RemoveEmptyEntries);
|
string[] folders = folderpath.Split(separators, StringSplitOptions.RemoveEmptyEntries);
|
||||||
foreach (string folder in folders)
|
foreach (string folder in folders)
|
||||||
{
|
{
|
||||||
path = Utilities.PathCombine(path, folder,"\\");
|
path = Utilities.PathCombine(path, folder, "\\");
|
||||||
if (!Directory.Exists(path))
|
if (!Directory.Exists(path))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(path);
|
Directory.CreateDirectory(path);
|
||||||
@ -465,11 +500,11 @@ namespace Oqtane.Controllers
|
|||||||
|
|
||||||
FileInfo fileinfo = new FileInfo(filepath);
|
FileInfo fileinfo = new FileInfo(filepath);
|
||||||
file.Extension = fileinfo.Extension.ToLower().Replace(".", "");
|
file.Extension = fileinfo.Extension.ToLower().Replace(".", "");
|
||||||
file.Size = (int) fileinfo.Length;
|
file.Size = (int)fileinfo.Length;
|
||||||
file.ImageHeight = 0;
|
file.ImageHeight = 0;
|
||||||
file.ImageWidth = 0;
|
file.ImageWidth = 0;
|
||||||
|
|
||||||
if (Constants.ImageFiles.Contains(file.Extension))
|
if (Constants.ImageFiles.Split(',').Contains(file.Extension.ToLower()))
|
||||||
{
|
{
|
||||||
FileStream stream = new FileStream(filepath, FileMode.Open, FileAccess.Read);
|
FileStream stream = new FileStream(filepath, FileMode.Open, FileAccess.Read);
|
||||||
using (var image = Image.FromStream(stream))
|
using (var image = Image.FromStream(stream))
|
||||||
|
@ -10,7 +10,6 @@ using Oqtane.Extensions;
|
|||||||
using Oqtane.Infrastructure;
|
using Oqtane.Infrastructure;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
using Oqtane.Security;
|
using Oqtane.Security;
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace Oqtane.Controllers
|
namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
@ -33,7 +32,7 @@ namespace Oqtane.Controllers
|
|||||||
public IEnumerable<Folder> Get(string siteid)
|
public IEnumerable<Folder> Get(string siteid)
|
||||||
{
|
{
|
||||||
List<Folder> folders = new List<Folder>();
|
List<Folder> folders = new List<Folder>();
|
||||||
foreach(Folder folder in _folders.GetFolders(int.Parse(siteid)))
|
foreach (Folder folder in _folders.GetFolders(int.Parse(siteid)))
|
||||||
{
|
{
|
||||||
if (_userPermissions.IsAuthorized(User, PermissionNames.Browse, folder.Permissions))
|
if (_userPermissions.IsAuthorized(User, PermissionNames.Browse, folder.Permissions))
|
||||||
{
|
{
|
||||||
@ -104,17 +103,27 @@ namespace Oqtane.Controllers
|
|||||||
new Permission(PermissionNames.Edit, Constants.AdminRole, true),
|
new Permission(PermissionNames.Edit, Constants.AdminRole, true),
|
||||||
}.EncodePermissions();
|
}.EncodePermissions();
|
||||||
}
|
}
|
||||||
if (_userPermissions.IsAuthorized(User,PermissionNames.Edit, permissions))
|
if (_userPermissions.IsAuthorized(User, PermissionNames.Edit, permissions))
|
||||||
|
{
|
||||||
|
if (folder.IsPathValid())
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(folder.Path) && folder.ParentId != null)
|
if (string.IsNullOrEmpty(folder.Path) && folder.ParentId != null)
|
||||||
{
|
{
|
||||||
Folder parent = _folders.GetFolder(folder.ParentId.Value);
|
Folder parent = _folders.GetFolder(folder.ParentId.Value);
|
||||||
folder.Path = Utilities.PathCombine(parent.Path, folder.Name,"\\");
|
folder.Path = Utilities.PathCombine(parent.Path, folder.Name);
|
||||||
}
|
}
|
||||||
|
folder.Path = Utilities.PathCombine(folder.Path, "\\");
|
||||||
folder = _folders.AddFolder(folder);
|
folder = _folders.AddFolder(folder);
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Folder Added {Folder}", folder);
|
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Folder Added {Folder}", folder);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Folder Name Not Valid {Folder}", folder);
|
||||||
|
HttpContext.Response.StatusCode = 401;
|
||||||
|
folder = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Create, "User Not Authorized To Add Folder {Folder}", folder);
|
_logger.Log(LogLevel.Error, this, LogFunction.Create, "User Not Authorized To Add Folder {Folder}", folder);
|
||||||
HttpContext.Response.StatusCode = 401;
|
HttpContext.Response.StatusCode = 401;
|
||||||
@ -130,16 +139,26 @@ namespace Oqtane.Controllers
|
|||||||
public Folder Put(int id, [FromBody] Folder folder)
|
public Folder Put(int id, [FromBody] Folder folder)
|
||||||
{
|
{
|
||||||
if (ModelState.IsValid && _userPermissions.IsAuthorized(User, EntityNames.Folder, folder.FolderId, PermissionNames.Edit))
|
if (ModelState.IsValid && _userPermissions.IsAuthorized(User, EntityNames.Folder, folder.FolderId, PermissionNames.Edit))
|
||||||
|
{
|
||||||
|
if (folder.IsPathValid())
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(folder.Path) && folder.ParentId != null)
|
if (string.IsNullOrEmpty(folder.Path) && folder.ParentId != null)
|
||||||
{
|
{
|
||||||
Folder parent = _folders.GetFolder(folder.ParentId.Value);
|
Folder parent = _folders.GetFolder(folder.ParentId.Value);
|
||||||
folder.Path = Utilities.PathCombine(parent.Path, folder.Name,"\\");
|
folder.Path = Utilities.PathCombine(parent.Path, folder.Name);
|
||||||
}
|
}
|
||||||
|
folder.Path = Utilities.PathCombine(folder.Path, "\\");
|
||||||
folder = _folders.UpdateFolder(folder);
|
folder = _folders.UpdateFolder(folder);
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Folder Updated {Folder}", folder);
|
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Folder Updated {Folder}", folder);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Folder Name Not Valid {Folder}", folder);
|
||||||
|
HttpContext.Response.StatusCode = 401;
|
||||||
|
folder = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Update, "User Not Authorized To Update Folder {Folder}", folder);
|
_logger.Log(LogLevel.Error, this, LogFunction.Update, "User Not Authorized To Update Folder {Folder}", folder);
|
||||||
HttpContext.Response.StatusCode = 401;
|
HttpContext.Response.StatusCode = 401;
|
||||||
|
@ -4,6 +4,14 @@ using Microsoft.Extensions.Configuration;
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
using Oqtane.Infrastructure;
|
using Oqtane.Infrastructure;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Linq;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using Oqtane.Modules;
|
||||||
|
using Oqtane.Themes;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Oqtane.Controllers
|
namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
@ -55,5 +63,76 @@ namespace Oqtane.Controllers
|
|||||||
_installationManager.UpgradeFramework();
|
_installationManager.UpgradeFramework();
|
||||||
return installation;
|
return installation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GET api/<controller>/load
|
||||||
|
[HttpGet("load")]
|
||||||
|
public IActionResult Load()
|
||||||
|
{
|
||||||
|
if (_config.GetSection("Runtime").Value == "WebAssembly")
|
||||||
|
{
|
||||||
|
// get list of assemblies which should be downloaded to browser
|
||||||
|
var assemblies = AppDomain.CurrentDomain.GetOqtaneClientAssemblies();
|
||||||
|
var list = assemblies.Select(a => a.GetName().Name).ToList();
|
||||||
|
|
||||||
|
// get module and theme dependencies
|
||||||
|
foreach (var assembly in assemblies)
|
||||||
|
{
|
||||||
|
foreach (var type in assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(IModule))))
|
||||||
|
{
|
||||||
|
var instance = Activator.CreateInstance(type) as IModule;
|
||||||
|
foreach (string name in instance.ModuleDefinition.Dependencies.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
if (!list.Contains(name)) list.Add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (var type in assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(ITheme))))
|
||||||
|
{
|
||||||
|
var instance = Activator.CreateInstance(type) as ITheme;
|
||||||
|
foreach (string name in instance.Theme.Dependencies.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
if (!list.Contains(name)) list.Add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create zip file containing assemblies and debug symbols
|
||||||
|
string binfolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
||||||
|
byte[] zipfile;
|
||||||
|
using (var memoryStream = new MemoryStream())
|
||||||
|
{
|
||||||
|
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
|
||||||
|
{
|
||||||
|
ZipArchiveEntry entry;
|
||||||
|
foreach (string file in list)
|
||||||
|
{
|
||||||
|
entry = archive.CreateEntry(file + ".dll");
|
||||||
|
using (var filestream = new FileStream(Path.Combine(binfolder, file + ".dll"), FileMode.Open, FileAccess.Read))
|
||||||
|
using (var entrystream = entry.Open())
|
||||||
|
{
|
||||||
|
filestream.CopyTo(entrystream);
|
||||||
|
}
|
||||||
|
|
||||||
|
// include debug symbols ( we may want to consider restricting this to only host users or when running in debug mode for performance )
|
||||||
|
if (System.IO.File.Exists(Path.Combine(binfolder, file + ".pdb")))
|
||||||
|
{
|
||||||
|
entry = archive.CreateEntry(file + ".pdb");
|
||||||
|
using (var filestream = new FileStream(Path.Combine(binfolder, file + ".pdb"), FileMode.Open, FileAccess.Read))
|
||||||
|
using (var entrystream = entry.Open())
|
||||||
|
{
|
||||||
|
filestream.CopyTo(entrystream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zipfile = memoryStream.ToArray();
|
||||||
|
}
|
||||||
|
return File(zipfile, "application/octet-stream", "oqtane.zip");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HttpContext.Response.StatusCode = 401;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,8 @@ using Oqtane.Repository;
|
|||||||
using Oqtane.Security;
|
using Oqtane.Security;
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
// ReSharper disable StringIndexOfIsCultureSpecific.1
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace Oqtane.Controllers
|
namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
@ -23,20 +24,24 @@ namespace Oqtane.Controllers
|
|||||||
private readonly IModuleDefinitionRepository _moduleDefinitions;
|
private readonly IModuleDefinitionRepository _moduleDefinitions;
|
||||||
private readonly IModuleRepository _modules;
|
private readonly IModuleRepository _modules;
|
||||||
private readonly ITenantRepository _tenants;
|
private readonly ITenantRepository _tenants;
|
||||||
|
private readonly ISqlRepository _sql;
|
||||||
private readonly IUserPermissions _userPermissions;
|
private readonly IUserPermissions _userPermissions;
|
||||||
private readonly IInstallationManager _installationManager;
|
private readonly IInstallationManager _installationManager;
|
||||||
private readonly IWebHostEnvironment _environment;
|
private readonly IWebHostEnvironment _environment;
|
||||||
|
private readonly IConfigurationRoot _config;
|
||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly IServiceProvider _serviceProvider;
|
||||||
private readonly ILogManager _logger;
|
private readonly ILogManager _logger;
|
||||||
|
|
||||||
public ModuleDefinitionController(IModuleDefinitionRepository moduleDefinitions, IModuleRepository modules,ITenantRepository tenants, IUserPermissions userPermissions, IInstallationManager installationManager, IWebHostEnvironment environment, IServiceProvider serviceProvider, ILogManager logger)
|
public ModuleDefinitionController(IModuleDefinitionRepository moduleDefinitions, IModuleRepository modules,ITenantRepository tenants, ISqlRepository sql, IUserPermissions userPermissions, IInstallationManager installationManager, IWebHostEnvironment environment, IConfigurationRoot config, IServiceProvider serviceProvider, ILogManager logger)
|
||||||
{
|
{
|
||||||
_moduleDefinitions = moduleDefinitions;
|
_moduleDefinitions = moduleDefinitions;
|
||||||
_modules = modules;
|
_modules = modules;
|
||||||
_tenants = tenants;
|
_tenants = tenants;
|
||||||
|
_sql = sql;
|
||||||
_userPermissions = userPermissions;
|
_userPermissions = userPermissions;
|
||||||
_installationManager = installationManager;
|
_installationManager = installationManager;
|
||||||
_environment = environment;
|
_environment = environment;
|
||||||
|
_config = config;
|
||||||
_serviceProvider = serviceProvider;
|
_serviceProvider = serviceProvider;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
@ -99,76 +104,61 @@ namespace Oqtane.Controllers
|
|||||||
public void Delete(int id, int siteid)
|
public void Delete(int id, int siteid)
|
||||||
{
|
{
|
||||||
ModuleDefinition moduledefinition = _moduleDefinitions.GetModuleDefinition(id, siteid);
|
ModuleDefinition moduledefinition = _moduleDefinitions.GetModuleDefinition(id, siteid);
|
||||||
if (moduledefinition != null)
|
if (moduledefinition != null )
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(moduledefinition.ServerManagerType))
|
if (!string.IsNullOrEmpty(moduledefinition.ServerManagerType) && Utilities.GetAssemblyName(moduledefinition.ServerManagerType) != "Oqtane.Server")
|
||||||
{
|
{
|
||||||
Type moduletype = Type.GetType(moduledefinition.ServerManagerType);
|
Type moduletype = Type.GetType(moduledefinition.ServerManagerType);
|
||||||
if (moduletype != null && moduletype.GetInterface("IInstallable") != null)
|
|
||||||
{
|
|
||||||
foreach (Tenant tenant in _tenants.GetTenants())
|
foreach (Tenant tenant in _tenants.GetTenants())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
{
|
||||||
|
if (moduletype.GetInterface("IInstallable") != null)
|
||||||
{
|
{
|
||||||
var moduleobject = ActivatorUtilities.CreateInstance(_serviceProvider, moduletype);
|
var moduleobject = ActivatorUtilities.CreateInstance(_serviceProvider, moduletype);
|
||||||
((IInstallable)moduleobject).Uninstall(tenant);
|
((IInstallable)moduleobject).Uninstall(tenant);
|
||||||
}
|
}
|
||||||
catch
|
else
|
||||||
{
|
{
|
||||||
// an error occurred executing the uninstall
|
_sql.ExecuteScript(tenant, moduletype.Assembly, Utilities.GetTypeName(moduledefinition.ModuleDefinitionName) + ".Uninstall.sql");
|
||||||
}
|
}
|
||||||
|
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "{ModuleDefinitionName} Uninstalled For Tenant {Tenant}", moduledefinition.ModuleDefinitionName, tenant.Name);
|
||||||
}
|
}
|
||||||
}
|
catch (Exception ex)
|
||||||
}
|
|
||||||
|
|
||||||
// format root assembly name
|
|
||||||
string assemblyname = Utilities.GetAssemblyName(moduledefinition.ModuleDefinitionName);
|
|
||||||
if (assemblyname != "Oqtane.Client")
|
|
||||||
{
|
{
|
||||||
assemblyname = assemblyname.Replace(".Client", "");
|
_logger.Log(LogLevel.Error, this, LogFunction.Delete, "Error Uninstalling {ModuleDefinitionName} For Tenant {Tenant} {Error}", moduledefinition.ModuleDefinitionName, tenant.Name, ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// clean up module static resource folder
|
// clean up module static resource folder
|
||||||
string folder = Path.Combine(_environment.WebRootPath, Path.Combine("Modules",assemblyname));
|
string folder = Path.Combine(_environment.WebRootPath, Path.Combine("Modules", Utilities.GetTypeName(moduledefinition.ModuleDefinitionName)));
|
||||||
if (Directory.Exists(folder))
|
if (Directory.Exists(folder))
|
||||||
{
|
{
|
||||||
Directory.Delete(folder, true);
|
Directory.Delete(folder, true);
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Static Resources Removed For {AssemblynName}", assemblyname);
|
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Static Resources Removed For {ModuleDefinitionName}", moduledefinition.ModuleDefinitionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove module assembly from /bin
|
// get root assembly name ( note that this only works if modules follow a specific naming convention for their assemblies )
|
||||||
|
string assemblyname = Utilities.GetAssemblyName(moduledefinition.ModuleDefinitionName).ToLower();
|
||||||
|
assemblyname = assemblyname.Replace(".client", "").Replace(".oqtane", "");
|
||||||
|
|
||||||
|
// remove module assemblies from /bin
|
||||||
string binfolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
string binfolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
||||||
foreach (string file in Directory.EnumerateFiles(binfolder, assemblyname + "*.*"))
|
foreach (string file in Directory.EnumerateFiles(binfolder, assemblyname + "*.*"))
|
||||||
{
|
{
|
||||||
System.IO.File.Delete(file);
|
System.IO.File.Delete(file);
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Assembly Removed {Filename}", file);
|
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Assembly {Filename} Removed For {ModuleDefinitionName}", file, moduledefinition.ModuleDefinitionName);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove module definition
|
// remove module definition
|
||||||
_moduleDefinitions.DeleteModuleDefinition(id, siteid);
|
_moduleDefinitions.DeleteModuleDefinition(id, siteid);
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Definition Deleted {ModuleDefinitionName}", moduledefinition.Name);
|
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Definition {ModuleDefinitionName} Deleted", moduledefinition.Name);
|
||||||
|
|
||||||
// restart application
|
// restart application
|
||||||
_installationManager.RestartApplication();
|
_installationManager.RestartApplication();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/<controller>/load/assembyname
|
|
||||||
[HttpGet("load/{assemblyname}")]
|
|
||||||
public IActionResult Load(string assemblyname)
|
|
||||||
{
|
|
||||||
if (Path.GetExtension(assemblyname).ToLower() == ".dll")
|
|
||||||
{
|
|
||||||
string binfolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
|
||||||
byte[] file = System.IO.File.ReadAllBytes(Path.Combine(binfolder, assemblyname));
|
|
||||||
return File(file, "application/octet-stream", assemblyname);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Read, "User Not Authorized To Download Assembly {Assembly}", assemblyname);
|
|
||||||
HttpContext.Response.StatusCode = 401;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST api/<controller>?moduleid=x
|
// POST api/<controller>?moduleid=x
|
||||||
@ -180,18 +170,18 @@ namespace Oqtane.Controllers
|
|||||||
{
|
{
|
||||||
string rootPath;
|
string rootPath;
|
||||||
DirectoryInfo rootFolder = Directory.GetParent(_environment.ContentRootPath);
|
DirectoryInfo rootFolder = Directory.GetParent(_environment.ContentRootPath);
|
||||||
string templatePath = Utilities.PathCombine(rootFolder.FullName, "Oqtane.Client", "Modules", "Admin", "ModuleCreator", "Templates",moduleDefinition.Template,"\\");
|
string templatePath = Utilities.PathCombine(_environment.WebRootPath, "Modules", "Templates", moduleDefinition.Template,"\\");
|
||||||
|
|
||||||
if (moduleDefinition.Template == "internal")
|
if (moduleDefinition.Template == "internal")
|
||||||
{
|
{
|
||||||
rootPath = Utilities.PathCombine(rootFolder.FullName,"\\");
|
rootPath = Utilities.PathCombine(rootFolder.FullName,"\\");
|
||||||
moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Modules, Oqtane.Client";
|
moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s, Oqtane.Client";
|
||||||
moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, Oqtane.Server";
|
moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, Oqtane.Server";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rootPath = Utilities.PathCombine(rootFolder.Parent.FullName , moduleDefinition.Owner + "." + moduleDefinition.Name + "s","\\");
|
rootPath = Utilities.PathCombine(rootFolder.Parent.FullName , moduleDefinition.Owner + "." + moduleDefinition.Name + "s","\\");
|
||||||
moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Modules, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Client.Oqtane";
|
moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + "s, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Client.Oqtane";
|
||||||
moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Server.Oqtane";
|
moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Manager." + moduleDefinition.Name + "Manager, " + moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Server.Oqtane";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +194,11 @@ namespace Oqtane.Controllers
|
|||||||
|
|
||||||
if (moduleDefinition.Template == "internal")
|
if (moduleDefinition.Template == "internal")
|
||||||
{
|
{
|
||||||
// need logic to add embedded scripts to Oqtane.Server.csproj - also you need to remove them on uninstall
|
// add embedded resources to project
|
||||||
|
List<string> resources = new List<string>();
|
||||||
|
resources.Add(Utilities.PathCombine("Modules", moduleDefinition.Owner + "." + moduleDefinition.Name + "s", "Scripts", moduleDefinition.Owner + "." + moduleDefinition.Name + "s.1.0.0.sql"));
|
||||||
|
resources.Add(Utilities.PathCombine("Modules", moduleDefinition.Owner + "." + moduleDefinition.Name + "s", "Scripts", moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Uninstall.sql"));
|
||||||
|
EmbedResourceFiles(Utilities.PathCombine(rootPath, "Oqtane.Server", "Oqtane.Server.csproj"), resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
_installationManager.RestartApplication();
|
_installationManager.RestartApplication();
|
||||||
@ -253,5 +247,19 @@ namespace Oqtane.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void EmbedResourceFiles(string projectfile, List<string> resources)
|
||||||
|
{
|
||||||
|
XDocument project = XDocument.Load(projectfile);
|
||||||
|
var itemGroup = project.Descendants("ItemGroup").Descendants("EmbeddedResource").FirstOrDefault().Parent;
|
||||||
|
if (itemGroup != null)
|
||||||
|
{
|
||||||
|
foreach (var resource in resources)
|
||||||
|
{
|
||||||
|
itemGroup.Add(new XElement("EmbeddedResource", new XAttribute("Include", resource)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
project.Save(projectfile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,10 +166,11 @@ namespace Oqtane.Controllers
|
|||||||
page.EditMode = false;
|
page.EditMode = false;
|
||||||
page.ThemeType = parent.ThemeType;
|
page.ThemeType = parent.ThemeType;
|
||||||
page.LayoutType = parent.LayoutType;
|
page.LayoutType = parent.LayoutType;
|
||||||
|
page.DefaultContainerType = parent.DefaultContainerType;
|
||||||
page.Icon = parent.Icon;
|
page.Icon = parent.Icon;
|
||||||
page.Permissions = new List<Permission> {
|
page.Permissions = new List<Permission> {
|
||||||
new Permission(PermissionNames.View, userid, true),
|
new Permission(PermissionNames.View, int.Parse(userid), true),
|
||||||
new Permission(PermissionNames.Edit, userid, true)
|
new Permission(PermissionNames.Edit, int.Parse(userid), true)
|
||||||
}.EncodePermissions();
|
}.EncodePermissions();
|
||||||
page.IsPersonalizable = false;
|
page.IsPersonalizable = false;
|
||||||
page.UserId = int.Parse(userid);
|
page.UserId = int.Parse(userid);
|
||||||
@ -186,8 +187,8 @@ namespace Oqtane.Controllers
|
|||||||
module.ModuleDefinitionName = pm.Module.ModuleDefinitionName;
|
module.ModuleDefinitionName = pm.Module.ModuleDefinitionName;
|
||||||
module.AllPages = false;
|
module.AllPages = false;
|
||||||
module.Permissions = new List<Permission> {
|
module.Permissions = new List<Permission> {
|
||||||
new Permission(PermissionNames.View, userid, true),
|
new Permission(PermissionNames.View, int.Parse(userid), true),
|
||||||
new Permission(PermissionNames.Edit, userid, true)
|
new Permission(PermissionNames.Edit, int.Parse(userid), true)
|
||||||
}.EncodePermissions();
|
}.EncodePermissions();
|
||||||
module = _modules.AddModule(module);
|
module = _modules.AddModule(module);
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Controllers
|
namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
@ -17,6 +19,7 @@ namespace Oqtane.Controllers
|
|||||||
|
|
||||||
// GET: api/<controller>
|
// GET: api/<controller>
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
[Authorize(Roles = Constants.HostRole)]
|
||||||
public IEnumerable<SiteTemplate> Get()
|
public IEnumerable<SiteTemplate> Get()
|
||||||
{
|
{
|
||||||
return _siteTemplates.GetSiteTemplates();
|
return _siteTemplates.GetSiteTemplates();
|
||||||
|
@ -54,22 +54,20 @@ namespace Oqtane.Controllers
|
|||||||
{
|
{
|
||||||
List<Theme> themes = _themes.GetThemes().ToList();
|
List<Theme> themes = _themes.GetThemes().ToList();
|
||||||
Theme theme = themes.Where(item => item.ThemeName == themename).FirstOrDefault();
|
Theme theme = themes.Where(item => item.ThemeName == themename).FirstOrDefault();
|
||||||
if (theme != null)
|
if (theme != null && Utilities.GetAssemblyName(theme.ThemeName) != "Oqtane.Client")
|
||||||
{
|
{
|
||||||
themename = theme.ThemeName.Substring(0, theme.ThemeName.IndexOf(","));
|
// clean up theme static resource folder
|
||||||
|
string folder = Path.Combine(_environment.WebRootPath, "Themes" , Utilities.GetTypeName(theme.ThemeName));
|
||||||
string folder = Path.Combine(_environment.WebRootPath, "Themes" , themename);
|
|
||||||
if (Directory.Exists(folder))
|
if (Directory.Exists(folder))
|
||||||
{
|
{
|
||||||
Directory.Delete(folder, true);
|
Directory.Delete(folder, true);
|
||||||
|
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Theme Static Resources Removed For {ThemeName}", theme.ThemeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove theme assembly from /bin
|
||||||
string binfolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
string binfolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
||||||
foreach (string file in Directory.EnumerateFiles(binfolder, themename + "*.dll"))
|
System.IO.File.Delete(Path.Combine(binfolder, Utilities.GetAssemblyName(theme.ThemeName) + ".dll"));
|
||||||
{
|
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Theme Assembly {Filename} Removed For {ThemeName}", Utilities.GetAssemblyName(theme.ThemeName) + ".dll", themename);
|
||||||
System.IO.File.Delete(file);
|
|
||||||
}
|
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Theme Deleted {ThemeName}", themename);
|
|
||||||
|
|
||||||
_installationManager.RestartApplication();
|
_installationManager.RestartApplication();
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ namespace Oqtane.Controllers
|
|||||||
user.SiteId = int.Parse(siteid);
|
user.SiteId = int.Parse(siteid);
|
||||||
user.Roles = GetUserRoles(user.UserId, user.SiteId);
|
user.Roles = GetUserRoles(user.UserId, user.SiteId);
|
||||||
}
|
}
|
||||||
return user;
|
return Filter(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/<controller>/name/x?siteid=x
|
// GET api/<controller>/name/x?siteid=x
|
||||||
@ -70,6 +70,29 @@ namespace Oqtane.Controllers
|
|||||||
user.SiteId = int.Parse(siteid);
|
user.SiteId = int.Parse(siteid);
|
||||||
user.Roles = GetUserRoles(user.UserId, user.SiteId);
|
user.Roles = GetUserRoles(user.UserId, user.SiteId);
|
||||||
}
|
}
|
||||||
|
return Filter(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
private User Filter(User user)
|
||||||
|
{
|
||||||
|
if (user != null && !User.IsInRole(Constants.AdminRole) && User.Identity.Name?.ToLower() != user.Username.ToLower())
|
||||||
|
{
|
||||||
|
user.DisplayName = "";
|
||||||
|
user.Email = "";
|
||||||
|
user.PhotoFileId = null;
|
||||||
|
user.LastLoginOn = DateTime.MinValue;
|
||||||
|
user.LastIPAddress = "";
|
||||||
|
user.Roles = "";
|
||||||
|
user.CreatedBy = "";
|
||||||
|
user.CreatedOn = DateTime.MinValue;
|
||||||
|
user.ModifiedBy = "";
|
||||||
|
user.ModifiedOn = DateTime.MinValue;
|
||||||
|
user.DeletedBy = "";
|
||||||
|
user.DeletedOn = DateTime.MinValue;
|
||||||
|
user.IsDeleted = false;
|
||||||
|
user.Password = "";
|
||||||
|
user.IsAuthenticated = false;
|
||||||
|
}
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +148,7 @@ namespace Oqtane.Controllers
|
|||||||
notification.SiteId = user.SiteId;
|
notification.SiteId = user.SiteId;
|
||||||
notification.FromUserId = null;
|
notification.FromUserId = null;
|
||||||
notification.ToUserId = newUser.UserId;
|
notification.ToUserId = newUser.UserId;
|
||||||
notification.ToEmail = "";
|
notification.ToEmail = newUser.Email;
|
||||||
notification.Subject = "User Account Verification";
|
notification.Subject = "User Account Verification";
|
||||||
string token = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
|
string token = await _identityUserManager.GenerateEmailConfirmationTokenAsync(identityuser);
|
||||||
string url = HttpContext.Request.Scheme + "://" + _tenants.GetAlias().Name + "/login?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token);
|
string url = HttpContext.Request.Scheme + "://" + _tenants.GetAlias().Name + "/login?name=" + user.Username + "&token=" + WebUtility.UrlEncode(token);
|
||||||
@ -134,6 +157,7 @@ namespace Oqtane.Controllers
|
|||||||
notification.CreatedOn = DateTime.UtcNow;
|
notification.CreatedOn = DateTime.UtcNow;
|
||||||
notification.IsDelivered = false;
|
notification.IsDelivered = false;
|
||||||
notification.DeliveredOn = null;
|
notification.DeliveredOn = null;
|
||||||
|
notification.SendOn = DateTime.UtcNow;
|
||||||
_notifications.AddNotification(notification);
|
_notifications.AddNotification(notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,6 +386,7 @@ namespace Oqtane.Controllers
|
|||||||
notification.CreatedOn = DateTime.UtcNow;
|
notification.CreatedOn = DateTime.UtcNow;
|
||||||
notification.IsDelivered = false;
|
notification.IsDelivered = false;
|
||||||
notification.DeliveredOn = null;
|
notification.DeliveredOn = null;
|
||||||
|
notification.SendOn = DateTime.UtcNow;
|
||||||
_notifications.AddNotification(notification);
|
_notifications.AddNotification(notification);
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Security, "Password Reset Notification Sent For {Username}", user.Username);
|
_logger.Log(LogLevel.Information, this, LogFunction.Security, "Password Reset Notification Sent For {Username}", user.Username);
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user