Merge remote-tracking branch 'upstream/dev' into clean-startup
# Conflicts: # Oqtane.Client/Program.cs # Oqtane.Server/Startup.cs
This commit is contained in:
commit
126024991c
5
.gitignore
vendored
5
.gitignore
vendored
@ -7,6 +7,7 @@ msbuild.binlog
|
|||||||
.vscode/
|
.vscode/
|
||||||
*.binlog
|
*.binlog
|
||||||
*.nupkg
|
*.nupkg
|
||||||
|
*.zip
|
||||||
|
|
||||||
*.idea
|
*.idea
|
||||||
|
|
||||||
@ -17,3 +18,7 @@ Oqtane.Server/Data/*.db
|
|||||||
|
|
||||||
/Oqtane.Server/Properties/PublishProfiles/FolderProfile.pubxml
|
/Oqtane.Server/Properties/PublishProfiles/FolderProfile.pubxml
|
||||||
Oqtane.Server/Content
|
Oqtane.Server/Content
|
||||||
|
Oqtane.Server/Packages
|
||||||
|
Oqtane.Server/wwwroot/Content
|
||||||
|
Oqtane.Server/wwwroot/Packages/*.log
|
||||||
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
@inject IInstallationService InstallationService
|
@inject IInstallationService InstallationService
|
||||||
|
@inject IJSRuntime JSRuntime
|
||||||
|
@inject SiteState SiteState
|
||||||
|
|
||||||
@if (_initialized)
|
@if (_initialized)
|
||||||
{
|
{
|
||||||
@ -20,21 +22,28 @@
|
|||||||
{
|
{
|
||||||
<div class="app-alert">
|
<div class="app-alert">
|
||||||
@_installation.Message
|
@_installation.Message
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private Installation _installation;
|
private bool _initialized = false;
|
||||||
private bool _initialized;
|
private Installation _installation = new Installation { Success = false, Message = "" };
|
||||||
|
|
||||||
private PageState PageState { get; set; }
|
private PageState PageState { get; set; }
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
_installation = await InstallationService.IsInstalled();
|
if (firstRender && !_initialized)
|
||||||
_initialized = true;
|
{
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
SiteState.AntiForgeryToken = await interop.GetElementByName(Constants.RequestVerificationToken);
|
||||||
|
_installation = await InstallationService.IsInstalled();
|
||||||
|
SiteState.Alias = _installation.Alias;
|
||||||
|
_initialized = true;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ChangeState(PageState pageState)
|
private void ChangeState(PageState pageState)
|
||||||
|
43
Oqtane.Client/Installer/Controls/LocalDBConfig.razor
Normal file
43
Oqtane.Client/Installer/Controls/LocalDBConfig.razor
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
@namespace Oqtane.Installer.Controls
|
||||||
|
@implements Oqtane.Interfaces.IDatabaseConfigControl
|
||||||
|
@inject IStringLocalizer<Installer> Localizer
|
||||||
|
|
||||||
|
@{
|
||||||
|
foreach (var field in _connectionStringFields)
|
||||||
|
{
|
||||||
|
var fieldId = field.Name.ToLowerInvariant();
|
||||||
|
field.Value = field.Value.Replace("{{Date}}", DateTime.UtcNow.ToString("yyyyMMddHHmm"));
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="@fieldId" HelpText="@field.HelpText" ResourceKey="@field.Name">@Localizer[$"{field.FriendlyName}:"]</Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="@fieldId" type="text" class="form-control" @bind="@field.Value" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private readonly List<ConnectionStringField> _connectionStringFields = new()
|
||||||
|
{
|
||||||
|
new() {Name = "Server", FriendlyName = "Server", Value = "(LocalDb)\\MSSQLLocalDB", HelpText="Enter the database server"},
|
||||||
|
new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}", HelpText="Enter the name of the database"}
|
||||||
|
};
|
||||||
|
|
||||||
|
public string GetConnectionString()
|
||||||
|
{
|
||||||
|
var connectionString = String.Empty;
|
||||||
|
|
||||||
|
var server = _connectionStringFields[0].Value;
|
||||||
|
var database = _connectionStringFields[1].Value;
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(server) && !String.IsNullOrEmpty(database))
|
||||||
|
{
|
||||||
|
connectionString = $"Data Source={server};AttachDbFilename=|DataDirectory|\\{database}.mdf;Initial Catalog={database};Integrated Security=SSPI;";
|
||||||
|
}
|
||||||
|
|
||||||
|
return connectionString;
|
||||||
|
}
|
||||||
|
}
|
54
Oqtane.Client/Installer/Controls/MySQLConfig.razor
Normal file
54
Oqtane.Client/Installer/Controls/MySQLConfig.razor
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
@namespace Oqtane.Installer.Controls
|
||||||
|
@implements Oqtane.Interfaces.IDatabaseConfigControl
|
||||||
|
@inject IStringLocalizer<Installer> Localizer
|
||||||
|
|
||||||
|
@{
|
||||||
|
foreach (var field in _connectionStringFields)
|
||||||
|
{
|
||||||
|
var fieldId = field.Name.ToLowerInvariant();
|
||||||
|
var fieldType = (field.Name == "Pwd") ? "password" : "text";
|
||||||
|
field.Value = field.Value.Replace("{{Date}}", DateTime.UtcNow.ToString("yyyyMMddHHmm"));
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="@fieldId" HelpText="@field.HelpText" ResourceKey="@field.Name">@Localizer[$"{field.FriendlyName}:"]</Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="@fieldId" type="@fieldType" class="form-control" @bind="@field.Value" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private readonly List<ConnectionStringField> _connectionStringFields = new()
|
||||||
|
{
|
||||||
|
new() {Name = "Server", FriendlyName = "Server", Value = "127.0.0.1", HelpText="Enter the database server"},
|
||||||
|
new() {Name = "Port", FriendlyName = "Port", Value = "3306", HelpText="Enter the port used to connect to the server"},
|
||||||
|
new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}", HelpText="Enter the name of the database"},
|
||||||
|
new() {Name = "Uid", FriendlyName = "User Id", Value = "", HelpText="Enter the username to use for the database"},
|
||||||
|
new() {Name = "Pwd", FriendlyName = "Password", Value = "", HelpText="Enter the password to use for the database"}
|
||||||
|
};
|
||||||
|
|
||||||
|
public string GetConnectionString()
|
||||||
|
{
|
||||||
|
var connectionString = String.Empty;
|
||||||
|
|
||||||
|
var server = _connectionStringFields[0].Value;
|
||||||
|
var port = _connectionStringFields[1].Value;
|
||||||
|
var database = _connectionStringFields[2].Value;
|
||||||
|
var userId = _connectionStringFields[3].Value;
|
||||||
|
var password = _connectionStringFields[4].Value;
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(server) && !String.IsNullOrEmpty(database) && !String.IsNullOrEmpty(userId) && !String.IsNullOrEmpty(password))
|
||||||
|
{
|
||||||
|
connectionString = $"Server={server};Database={database};Uid={userId};Pwd={password};";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(port))
|
||||||
|
{
|
||||||
|
connectionString += $"Port={port};";
|
||||||
|
}
|
||||||
|
return connectionString;
|
||||||
|
}
|
||||||
|
}
|
95
Oqtane.Client/Installer/Controls/PostgreSQLConfig.razor
Normal file
95
Oqtane.Client/Installer/Controls/PostgreSQLConfig.razor
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
@namespace Oqtane.Installer.Controls
|
||||||
|
@implements Oqtane.Interfaces.IDatabaseConfigControl
|
||||||
|
@inject IStringLocalizer<Installer> Localizer
|
||||||
|
|
||||||
|
@{
|
||||||
|
foreach (var field in _connectionStringFields)
|
||||||
|
{
|
||||||
|
var fieldId = field.Name.ToLowerInvariant();
|
||||||
|
if (field.Name != "IntegratedSecurity")
|
||||||
|
{
|
||||||
|
var isVisible = "";
|
||||||
|
var fieldType = (field.Name == "Pwd") ? "password" : "text";
|
||||||
|
if ((field.Name == "Uid" || field.Name == "Pwd") )
|
||||||
|
{
|
||||||
|
var intSecurityField = _connectionStringFields.Single(f => f.Name == "IntegratedSecurity");
|
||||||
|
if (intSecurityField != null)
|
||||||
|
{
|
||||||
|
isVisible = (Convert.ToBoolean(intSecurityField.Value)) ? "display: none;" : "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
field.Value = field.Value.Replace("{{Date}}", DateTime.UtcNow.ToString("yyyyMMddHHmm"));
|
||||||
|
|
||||||
|
<tr style="@isVisible">
|
||||||
|
<td>
|
||||||
|
<Label For="@fieldId" HelpText="@field.HelpText" ResourceKey="@field.Name">@Localizer[$"{field.FriendlyName}:"]</Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="@fieldId" type="@fieldType" class="form-control" @bind="@field.Value" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="@fieldId" HelpText="@field.HelpText" ResourceKey="@field.Name">@Localizer[$"{field.FriendlyName}:"]</Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select id="@fieldId" class="custom-select" @bind="@field.Value">
|
||||||
|
<option value="true" selected>@Localizer["True"]</option>
|
||||||
|
<option value="false">@Localizer["False"]</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private readonly List<ConnectionStringField> _connectionStringFields = new()
|
||||||
|
{
|
||||||
|
new() {Name = "Server", FriendlyName = "Server", Value = "127.0.0.1", HelpText="Enter the database server"},
|
||||||
|
new() {Name = "Port", FriendlyName = "Port", Value = "5432", HelpText="Enter the port used to connect to the server"},
|
||||||
|
new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}", HelpText="Enter the name of the database"},
|
||||||
|
new() {Name = "IntegratedSecurity", FriendlyName = "Integrated Security", Value = "true", HelpText="Select if you want integrated security or not"},
|
||||||
|
new() {Name = "Uid", FriendlyName = "User Id", Value = "", HelpText="Enter the username to use for the database"},
|
||||||
|
new() {Name = "Pwd", FriendlyName = "Password", Value = "", HelpText="Enter the password to use for the database"}
|
||||||
|
};
|
||||||
|
|
||||||
|
public string GetConnectionString()
|
||||||
|
{
|
||||||
|
var connectionString = String.Empty;
|
||||||
|
|
||||||
|
var server = _connectionStringFields[0].Value;
|
||||||
|
var port = _connectionStringFields[1].Value;
|
||||||
|
var database = _connectionStringFields[2].Value;
|
||||||
|
var integratedSecurity = Boolean.Parse(_connectionStringFields[3].Value);
|
||||||
|
var userId = _connectionStringFields[4].Value;
|
||||||
|
var password = _connectionStringFields[5].Value;
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(server) && !String.IsNullOrEmpty(database) && !String.IsNullOrEmpty(port))
|
||||||
|
{
|
||||||
|
connectionString = $"Server={server};Port={port};Database={database};";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (integratedSecurity)
|
||||||
|
{
|
||||||
|
connectionString += "Integrated Security=true;";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(userId) && !String.IsNullOrEmpty(password))
|
||||||
|
{
|
||||||
|
connectionString += $"User ID={userId};Password={password};";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connectionString = String.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return connectionString;
|
||||||
|
}
|
||||||
|
}
|
94
Oqtane.Client/Installer/Controls/SqlServerConfig.razor
Normal file
94
Oqtane.Client/Installer/Controls/SqlServerConfig.razor
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
@namespace Oqtane.Installer.Controls
|
||||||
|
@implements Oqtane.Interfaces.IDatabaseConfigControl
|
||||||
|
@inject IStringLocalizer<Installer> Localizer
|
||||||
|
|
||||||
|
@{
|
||||||
|
foreach (var field in _connectionStringFields)
|
||||||
|
{
|
||||||
|
var fieldId = field.Name.ToLowerInvariant();
|
||||||
|
if (field.Name != "IntegratedSecurity")
|
||||||
|
{
|
||||||
|
var isVisible = "";
|
||||||
|
var fieldType = (field.Name == "Pwd") ? "password" : "text";
|
||||||
|
if ((field.Name == "Uid" || field.Name == "Pwd") )
|
||||||
|
{
|
||||||
|
var intSecurityField = _connectionStringFields.Single(f => f.Name == "IntegratedSecurity");
|
||||||
|
if (intSecurityField != null)
|
||||||
|
{
|
||||||
|
isVisible = (Convert.ToBoolean(intSecurityField.Value)) ? "display: none;" : "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
field.Value = field.Value.Replace("{{Date}}", DateTime.UtcNow.ToString("yyyyMMddHHmm"));
|
||||||
|
|
||||||
|
<tr style="@isVisible">
|
||||||
|
<td>
|
||||||
|
<Label For="@fieldId" HelpText="@field.HelpText" ResourceKey="@field.Name">@Localizer[$"{field.FriendlyName}:"]</Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="@fieldId" type="@fieldType" class="form-control" @bind="@field.Value" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="@fieldId" HelpText="@field.HelpText" ResourceKey="@field.Name">@Localizer[$"{field.FriendlyName}:"]</Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select id="@fieldId" class="custom-select" @bind="@field.Value">
|
||||||
|
<option value="true" selected>@Localizer["True"]</option>
|
||||||
|
<option value="false">@Localizer["False"]</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private readonly List<ConnectionStringField> _connectionStringFields = new()
|
||||||
|
{
|
||||||
|
new() {Name = "Server", FriendlyName = "Server", Value = ".", HelpText="Enter the database server"},
|
||||||
|
new() {Name = "Database", FriendlyName = "Database", Value = "Oqtane-{{Date}}", HelpText="Enter the name of the database"},
|
||||||
|
new() {Name = "IntegratedSecurity", FriendlyName = "Integrated Security", Value = "true", HelpText="Select if you want integrated security or not"},
|
||||||
|
new() {Name = "Uid", FriendlyName = "User Id", Value = "", HelpText="Enter the username to use for the database"},
|
||||||
|
new() {Name = "Pwd", FriendlyName = "Password", Value = "", HelpText="Enter the password to use for the database"}
|
||||||
|
};
|
||||||
|
|
||||||
|
public string GetConnectionString()
|
||||||
|
{
|
||||||
|
var connectionString = String.Empty;
|
||||||
|
|
||||||
|
var server = _connectionStringFields[0].Value;
|
||||||
|
var database = _connectionStringFields[1].Value;
|
||||||
|
var integratedSecurity = Boolean.Parse(_connectionStringFields[2].Value);
|
||||||
|
var userId = _connectionStringFields[3].Value;
|
||||||
|
var password = _connectionStringFields[4].Value;
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(server) && !String.IsNullOrEmpty(database))
|
||||||
|
{
|
||||||
|
connectionString = $"Data Source={server};Initial Catalog={database};";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (integratedSecurity)
|
||||||
|
{
|
||||||
|
connectionString += "Integrated Security=SSPI;";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(userId) && !String.IsNullOrEmpty(password))
|
||||||
|
{
|
||||||
|
connectionString += $"User ID={userId};Password={password};";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connectionString = String.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return connectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
41
Oqtane.Client/Installer/Controls/SqliteConfig.razor
Normal file
41
Oqtane.Client/Installer/Controls/SqliteConfig.razor
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
@namespace Oqtane.Installer.Controls
|
||||||
|
@implements Oqtane.Interfaces.IDatabaseConfigControl
|
||||||
|
@inject IStringLocalizer<Installer> Localizer
|
||||||
|
|
||||||
|
@{
|
||||||
|
foreach (var field in _connectionStringFields)
|
||||||
|
{
|
||||||
|
var fieldId = field.Name.ToLowerInvariant();
|
||||||
|
field.Value = field.Value.Replace("{{Date}}", DateTime.UtcNow.ToString("yyyyMMddHHmm"));
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="@fieldId" HelpText="@field.HelpText" ResourceKey="@field.Name">@Localizer[$"{field.FriendlyName}:"]</Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="@fieldId" type="text" class="form-control" @bind="@field.Value" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private readonly List<ConnectionStringField> _connectionStringFields = new()
|
||||||
|
{
|
||||||
|
new() {Name = "Server", FriendlyName = "File Name", Value = "Oqtane-{{Date}}.db", HelpText="Enter the file name to use for the database"}
|
||||||
|
};
|
||||||
|
|
||||||
|
public string GetConnectionString()
|
||||||
|
{
|
||||||
|
var connectionstring = String.Empty;
|
||||||
|
|
||||||
|
var server = _connectionStringFields[0].Value;
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(server))
|
||||||
|
{
|
||||||
|
connectionstring = $"Data Source={server};";
|
||||||
|
}
|
||||||
|
|
||||||
|
return connectionstring;
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,12 @@
|
|||||||
|
@namespace Oqtane.Installer
|
||||||
@using Oqtane.Interfaces
|
@using Oqtane.Interfaces
|
||||||
@using System.Reflection
|
|
||||||
@namespace Oqtane.UI
|
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IInstallationService InstallationService
|
@inject IInstallationService InstallationService
|
||||||
@inject ISiteService SiteService
|
@inject ISiteService SiteService
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
|
@inject IDatabaseService DatabaseService
|
||||||
@inject IJSRuntime JSRuntime
|
@inject IJSRuntime JSRuntime
|
||||||
@inject IStringLocalizer<Installer> Localizer
|
@inject IStringLocalizer<Installer> Localizer
|
||||||
@inject IEnumerable<IOqtaneDatabase> Databases
|
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -24,63 +23,33 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<label class="control-label" style="font-weight: bold">@Localizer["Database Type:"] </label>
|
<Label For="databasetype" HelpText="Select the type of database you wish to create" ResourceKey="DatabaseType">Database Type:</Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select class="custom-select" @bind="@_databaseType">
|
<select id="databasetype" class="custom-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))">
|
||||||
@{
|
@if (_databases != null)
|
||||||
foreach (var database in Databases)
|
{
|
||||||
|
foreach (var database in _databases)
|
||||||
{
|
{
|
||||||
<option value="@database.Name">@Localizer[@database.FriendlyName]</option>
|
if (database.IsDefault)
|
||||||
|
{
|
||||||
|
<option value="@database.Name" selected>@Localizer[@database.Name]</option>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<option value="@database.Name">@Localizer[@database.Name]</option>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@{
|
@{
|
||||||
_selectedDatabase = Databases.Single(d => d.Name == _databaseType);
|
if (_databaseConfigType != null)
|
||||||
foreach (var field in _selectedDatabase.ConnectionStringFields)
|
|
||||||
{
|
|
||||||
if (field.Name != "IntegratedSecurity")
|
|
||||||
{
|
{
|
||||||
var isVisible = "";
|
@DatabaseConfigComponent;
|
||||||
var fieldType = (field.Name == "Pwd") ? "password" : "text";
|
|
||||||
if ((field.Name == "Uid" || field.Name == "Pwd") && _selectedDatabase.Name != "MySQL" )
|
|
||||||
{
|
|
||||||
var intSecurityField = _selectedDatabase.ConnectionStringFields.Single(f => f.Name == "IntegratedSecurity");
|
|
||||||
if (intSecurityField != null)
|
|
||||||
{
|
|
||||||
isVisible = (Convert.ToBoolean(intSecurityField.Value)) ? "display: none;" : "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
field.Value = field.Value.Replace("{{Date}}", DateTime.UtcNow.ToString("yyyyMMddHHmm"));
|
|
||||||
|
|
||||||
<tr style="@isVisible">
|
|
||||||
<td>
|
|
||||||
<label class="control-label" style="font-weight: bold">@Localizer[$"{field.FriendlyName}:"]</label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<input type="@fieldType" class="form-control" @bind="@field.Value" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<label class="control-label" style="font-weight: bold">@Localizer[$"{field.FriendlyName}:"]</label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<select class="custom-select" @bind="@field.Value">
|
|
||||||
<option value="true" selected>@Localizer["True"]</option>
|
|
||||||
<option value="false">@Localizer["False"]</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@ -90,31 +59,31 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<label class="control-label" style="font-weight: bold">@Localizer["Username:"] </label>
|
<Label For="username" HelpText="The username of the host user account ( this is not customizable )" ResourceKey="Username">Username:</Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" class="form-control" @bind="@_hostUsername" readonly />
|
<input id="username" type="text" class="form-control" @bind="@_hostUsername" readonly />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<label class="control-label" style="font-weight: bold">@Localizer["Password:"] </label>
|
<Label For="password" HelpText="Provide the password for the host user account" ResourceKey="Password">Password:</Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="password" class="form-control" @bind="@_hostPassword" />
|
<input id="password" type="password" class="form-control" @bind="@_hostPassword" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<label class="control-label" style="font-weight: bold">@Localizer["Confirm:"] </label>
|
<Label For="confirm" HelpText="Please confirm the password entered above by entering it again" ResourceKey="Confirm">Confirm:</Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="password" class="form-control" @bind="@_confirmPassword" />
|
<input id="confirm" type="password" class="form-control" @bind="@_confirmPassword" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<label class="control-label" style="font-weight: bold">@Localizer["Email:"] </label>
|
<Label For="email" HelpText="Provide the email address for the host user account" ResourceKey="Email">Email:</Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="text" class="form-control" @bind="@_hostEmail" />
|
<input type="text" class="form-control" @bind="@_hostEmail" />
|
||||||
@ -135,8 +104,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private IOqtaneDatabase _selectedDatabase;
|
private List<Database> _databases;
|
||||||
private string _databaseType = "LocalDB";
|
private string _databaseName = "LocalDB";
|
||||||
|
private Type _databaseConfigType;
|
||||||
|
private object _databaseConfig;
|
||||||
|
private RenderFragment DatabaseConfigComponent { get; set; }
|
||||||
|
|
||||||
private string _hostUsername = UserNames.Host;
|
private string _hostUsername = UserNames.Host;
|
||||||
private string _hostPassword = string.Empty;
|
private string _hostPassword = string.Empty;
|
||||||
private string _confirmPassword = string.Empty;
|
private string _confirmPassword = string.Empty;
|
||||||
@ -144,6 +117,41 @@
|
|||||||
private string _message = string.Empty;
|
private string _message = string.Empty;
|
||||||
private string _loadingDisplay = "display: none;";
|
private string _loadingDisplay = "display: none;";
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
_databases = await DatabaseService.GetDatabasesAsync();
|
||||||
|
LoadDatabaseConfigComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DatabaseChanged(ChangeEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_databaseName = (string)eventArgs.Value;
|
||||||
|
|
||||||
|
LoadDatabaseConfigComponent();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
_message = Localizer["Error loading Database Configuration Control"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadDatabaseConfigComponent()
|
||||||
|
{
|
||||||
|
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
||||||
|
if (database != null)
|
||||||
|
{
|
||||||
|
_databaseConfigType = Type.GetType(database.ControlType);
|
||||||
|
DatabaseConfigComponent = builder =>
|
||||||
|
{
|
||||||
|
builder.OpenComponent(0, _databaseConfigType);
|
||||||
|
builder.AddComponentReferenceCapture(1, inst => { _databaseConfig = Convert.ChangeType(inst, _databaseConfigType); });
|
||||||
|
builder.CloseComponent();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
@ -155,7 +163,11 @@
|
|||||||
|
|
||||||
private async Task Install()
|
private async Task Install()
|
||||||
{
|
{
|
||||||
var connectionString = _selectedDatabase.BuildConnectionString();
|
var connectionString = String.Empty;
|
||||||
|
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
||||||
|
{
|
||||||
|
connectionString = databaseConfigControl.GetConnectionString();
|
||||||
|
}
|
||||||
|
|
||||||
if (connectionString != "" && _hostUsername != "" && _hostPassword.Length >= 6 && _hostPassword == _confirmPassword && _hostEmail != "")
|
if (connectionString != "" && _hostUsername != "" && _hostPassword.Length >= 6 && _hostPassword == _confirmPassword && _hostEmail != "")
|
||||||
{
|
{
|
||||||
@ -163,10 +175,12 @@
|
|||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
|
|
||||||
Uri uri = new Uri(NavigationManager.Uri);
|
Uri uri = new Uri(NavigationManager.Uri);
|
||||||
|
|
||||||
|
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
||||||
|
|
||||||
var config = new InstallConfig
|
var config = new InstallConfig
|
||||||
{
|
{
|
||||||
DatabaseType = _databaseType,
|
DatabaseType = database.DBType,
|
||||||
ConnectionString = connectionString,
|
ConnectionString = connectionString,
|
||||||
Aliases = uri.Authority,
|
Aliases = uri.Authority,
|
||||||
HostEmail = _hostEmail,
|
HostEmail = _hostEmail,
|
47
Oqtane.Client/Localization/SharedResources.cs
Normal file
47
Oqtane.Client/Localization/SharedResources.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
namespace Oqtane
|
||||||
|
{
|
||||||
|
public class SharedResources
|
||||||
|
{
|
||||||
|
public static readonly string UserLogin = "User Login";
|
||||||
|
|
||||||
|
public static readonly string UserRegistration = "User Registration";
|
||||||
|
|
||||||
|
public static readonly string PasswordReset = "Password Reset";
|
||||||
|
|
||||||
|
public static readonly string UserProfile = "User Profile";
|
||||||
|
|
||||||
|
public static readonly string AdminDashboard = "Admin Dashboard";
|
||||||
|
|
||||||
|
public static readonly string SiteSettings = "Site Settings";
|
||||||
|
|
||||||
|
public static readonly string PageManagement = "Page Management";
|
||||||
|
|
||||||
|
public static readonly string UserManagement = "User Management";
|
||||||
|
|
||||||
|
public static readonly string ProfileManagement = "Profile Management";
|
||||||
|
|
||||||
|
public static readonly string RoleManagement = "Role Management";
|
||||||
|
|
||||||
|
public static readonly string FileManagement = "File Management";
|
||||||
|
|
||||||
|
public static readonly string RecycleBin = "Recycle Bin";
|
||||||
|
|
||||||
|
public static readonly string EventLog = "Event Log";
|
||||||
|
|
||||||
|
public static readonly string SiteManagement = "Site Management";
|
||||||
|
|
||||||
|
public static readonly string ModuleManagement = "Module Management";
|
||||||
|
|
||||||
|
public static readonly string ThemeManagement = "Theme Management";
|
||||||
|
|
||||||
|
public static readonly string LanguageManagement = "Language Management";
|
||||||
|
|
||||||
|
public static readonly string ScheduledJobs = "Scheduled Jobs";
|
||||||
|
|
||||||
|
public static readonly string SqlManagement = "Sql Management";
|
||||||
|
|
||||||
|
public static readonly string SystemInfo = "System Info";
|
||||||
|
|
||||||
|
public static readonly string SystemUpdate = "System Update";
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject IPageService PageService
|
@inject IPageService PageService
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
|
@inject IStringLocalizer<SharedResources> Localizer
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@foreach (var p in _pages)
|
@foreach (var p in _pages)
|
||||||
@ -11,7 +12,7 @@
|
|||||||
string url = NavigateUrl(p.Path);
|
string url = NavigateUrl(p.Path);
|
||||||
<div class="col-md-2 mx-auto text-center">
|
<div class="col-md-2 mx-auto text-center">
|
||||||
<NavLink class="nav-link" href="@url" Match="NavLinkMatch.All">
|
<NavLink class="nav-link" href="@url" Match="NavLinkMatch.All">
|
||||||
<h2><span class="@p.Icon" aria-hidden="true"></span></h2>@p.Name
|
<h2><span class="@p.Icon" aria-hidden="true"></span></h2>@Localizer[p.Name]
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@ -20,7 +21,7 @@
|
|||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<Page> _pages;
|
private List<Page> _pages;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
|
@ -33,6 +33,24 @@
|
|||||||
<input id="name" class="form-control" @bind="@_name" />
|
<input id="name" class="form-control" @bind="@_name" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label for="type" HelpText="Select the folder type. Private folders are only accessible by authorized users. Public folders can be accessed by all users" ResourceKey="Name">Type: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
@if (PageState.QueryString.ContainsKey("id"))
|
||||||
|
{
|
||||||
|
<input id="type" class="form-control" readonly @bind="@_type" />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<select id="type" class="form-control" @bind="@_type">
|
||||||
|
<option value="@FolderTypes.Private">@Localizer[FolderTypes.Private]</option>
|
||||||
|
<option value="@FolderTypes.Public">@Localizer[FolderTypes.Public]</option>
|
||||||
|
</select>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2" align="center">
|
<td colspan="2" align="center">
|
||||||
<Label For="permissions" HelpText="Select the permissions you want for the folder" ResourceKey="Permissions">Permissions: </Label>
|
<Label For="permissions" HelpText="Select the permissions you want for the folder" ResourceKey="Permissions">Permissions: </Label>
|
||||||
@ -43,10 +61,12 @@
|
|||||||
@if (!_isSystem)
|
@if (!_isSystem)
|
||||||
{
|
{
|
||||||
<button type="button" class="btn btn-success" @onclick="SaveFolder">@Localizer["Save"]</button>
|
<button type="button" class="btn btn-success" @onclick="SaveFolder">@Localizer["Save"]</button>
|
||||||
|
@((MarkupString)" ")
|
||||||
}
|
}
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
||||||
@if (!_isSystem && PageState.QueryString.ContainsKey("id"))
|
@if (!_isSystem && PageState.QueryString.ContainsKey("id"))
|
||||||
{
|
{
|
||||||
|
@((MarkupString)" ")
|
||||||
<ActionDialog Header="Delete Folder" Message="Are You Sure You Wish To Delete This Folder?" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteFolder())" ResourceKey="DeleteFolder" />
|
<ActionDialog Header="Delete Folder" Message="Are You Sure You Wish To Delete This Folder?" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteFolder())" ResourceKey="DeleteFolder" />
|
||||||
}
|
}
|
||||||
<br />
|
<br />
|
||||||
@ -60,8 +80,9 @@
|
|||||||
@code {
|
@code {
|
||||||
private List<Folder> _folders;
|
private List<Folder> _folders;
|
||||||
private int _folderId = -1;
|
private int _folderId = -1;
|
||||||
private string _name;
|
|
||||||
private int _parentId = -1;
|
private int _parentId = -1;
|
||||||
|
private string _name;
|
||||||
|
private string _type = FolderTypes.Private;
|
||||||
private bool _isSystem;
|
private bool _isSystem;
|
||||||
private string _permissions = string.Empty;
|
private string _permissions = string.Empty;
|
||||||
private string _createdBy;
|
private string _createdBy;
|
||||||
@ -91,6 +112,7 @@
|
|||||||
{
|
{
|
||||||
_parentId = folder.ParentId ?? -1;
|
_parentId = folder.ParentId ?? -1;
|
||||||
_name = folder.Name;
|
_name = folder.Name;
|
||||||
|
_type = folder.Type;
|
||||||
_isSystem = folder.IsSystem;
|
_isSystem = folder.IsSystem;
|
||||||
_permissions = folder.Permissions;
|
_permissions = folder.Permissions;
|
||||||
_createdBy = folder.CreatedBy;
|
_createdBy = folder.CreatedBy;
|
||||||
@ -150,6 +172,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
folder.Name = _name;
|
folder.Name = _name;
|
||||||
|
folder.Type = _type;
|
||||||
folder.IsSystem = _isSystem;
|
folder.IsSystem = _isSystem;
|
||||||
folder.Permissions = _permissionGrid.GetPermissions();
|
folder.Permissions = _permissionGrid.GetPermissions();
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
<Row>
|
<Row>
|
||||||
<td><ActionLink Action="Details" Text="Edit" Parameters="@($"id=" + context.FileId.ToString())" ResourceKey="Details" /></td>
|
<td><ActionLink Action="Details" Text="Edit" Parameters="@($"id=" + context.FileId.ToString())" ResourceKey="Details" /></td>
|
||||||
<td><ActionDialog Header="Delete File" Message="@Localizer["Are You Sure You Wish To Delete {0}?", context.Name]" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteFile(context))" ResourceKey="DeleteFile" /></td>
|
<td><ActionDialog Header="Delete File" Message="@Localizer["Are You Sure You Wish To Delete {0}?", context.Name]" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteFile(context))" ResourceKey="DeleteFile" /></td>
|
||||||
<td><a href="@(ContentUrl(context.FileId))" target="_new">@context.Name</a></td>
|
<td><a href="@context.Url" target="_new">@context.Name</a></td>
|
||||||
<td>@context.ModifiedOn</td>
|
<td>@context.ModifiedOn</td>
|
||||||
<td>@context.Extension.ToUpper() @Localizer["File"]</td>
|
<td>@context.Extension.ToUpper() @Localizer["File"]</td>
|
||||||
<td>@string.Format("{0:0.00}", ((decimal)context.Size / 1000)) KB</td>
|
<td>@string.Format("{0:0.00}", ((decimal)context.Size / 1000)) KB</td>
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject ILocalizationService LocalizationService
|
@inject ILocalizationService LocalizationService
|
||||||
@inject ILanguageService LanguageService
|
@inject ILanguageService LanguageService
|
||||||
|
@inject IPackageService PackageService
|
||||||
@inject IStringLocalizer<Add> Localizer
|
@inject IStringLocalizer<Add> Localizer
|
||||||
|
|
||||||
@if (_supportedCultures == null)
|
@if (_supportedCultures == null)
|
||||||
@ -13,53 +14,114 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@if (_supportedCultures?.Count() > 1)
|
<TabStrip>
|
||||||
{
|
<TabPanel Name="Manage" ResourceKey="Manage">
|
||||||
<table class="table table-borderless">
|
@if (_availableCultures.Count() == 0)
|
||||||
<tr>
|
{
|
||||||
<td>
|
<ModuleMessage Type="MessageType.Info" Message="@_message"></ModuleMessage>
|
||||||
<Label For="name" HelpText="Name Of The Langauage" ResourceKey="Name">Name:</Label>
|
}
|
||||||
</td>
|
else
|
||||||
<td>
|
{
|
||||||
<select id="_code" class="form-control" @bind="@_code">
|
<table class="table table-borderless">
|
||||||
@foreach (var culture in _supportedCultures)
|
<tr>
|
||||||
{
|
<td>
|
||||||
<option value="@culture.Name">@culture.DisplayName</option>
|
<Label For="name" HelpText="Name Of The Language" ResourceKey="Name">Name:</Label>
|
||||||
}
|
</td>
|
||||||
</select>
|
<td>
|
||||||
</td>
|
<select id="_code" class="form-control" @bind="@_code">
|
||||||
</tr>
|
@foreach (var culture in _availableCultures)
|
||||||
<tr>
|
{
|
||||||
<td>
|
<option value="@culture.Name">@culture.DisplayName</option>
|
||||||
<Label For="default" HelpText="Indicates Whether Or Not This Language Is The Default For The Site" ResourceKey="IsDefault">Default?</Label>
|
}
|
||||||
</td>
|
</select>
|
||||||
<td>
|
</td>
|
||||||
<select id="default" class="form-control" @bind="@_isDefault">
|
</tr>
|
||||||
<option value="True">@Localizer["Yes"]</option>
|
<tr>
|
||||||
<option value="False">@Localizer["No"]</option>
|
<td>
|
||||||
</select>
|
<Label For="default" HelpText="Indicates Whether Or Not This Language Is The Default For The Site" ResourceKey="IsDefault">Default?</Label>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
<td>
|
||||||
</table>
|
<select id="default" class="form-control" @bind="@_isDefault">
|
||||||
<button type="button" class="btn btn-success" @onclick="SaveLanguage">@Localizer["Save"]</button>
|
<option value="True">@Localizer["Yes"]</option>
|
||||||
}
|
<option value="False">@Localizer["No"]</option>
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<button type="button" class="btn btn-success" @onclick="SaveLanguage">@Localizer["Save"]</button>
|
||||||
|
}
|
||||||
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
||||||
|
</TabPanel>
|
||||||
|
<TabPanel Name="Download" ResourceKey="Download" Security="SecurityAccessLevel.Host">
|
||||||
|
@if (_packages != null && _packages.Count > 0)
|
||||||
|
{
|
||||||
|
<ModuleMessage Type="MessageType.Info" Message="Download one or more language packages from the list below. Once you are ready click Install to complete the installation."></ModuleMessage>
|
||||||
|
<Pager Items="@_packages">
|
||||||
|
<Header>
|
||||||
|
<th>@Localizer["Name"]</th>
|
||||||
|
<th>@Localizer["Version"]</th>
|
||||||
|
<th style="width: 1px"></th>
|
||||||
|
</Header>
|
||||||
|
<Row>
|
||||||
|
<td>@context.Name</td>
|
||||||
|
<td>@context.Version</td>
|
||||||
|
<td>
|
||||||
|
<button type="button" class="btn btn-primary" @onclick=@(async () => await DownloadLanguage(context.PackageId, context.Version))>@Localizer["Download"]</button>
|
||||||
|
</td>
|
||||||
|
</Row>
|
||||||
|
</Pager>
|
||||||
|
<button type="button" class="btn btn-success" @onclick="InstallLanguages">@Localizer["Install"]</button>
|
||||||
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<ModuleMessage Type="MessageType.Info" Message="No Language Packages Are Available To Download"></ModuleMessage>
|
||||||
|
}
|
||||||
|
</TabPanel>
|
||||||
|
<TabPanel Name="Upload" ResourceKey="Upload" Security="SecurityAccessLevel.Host">
|
||||||
|
<table class="table table-borderless">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label HelpText="Upload one or more language packages. Once they are uploaded click Install to complete the installation." ResourceKey="Module">Language: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<FileManager Filter="nupkg" ShowFiles="false" Folder="Packages" UploadMultiple="true" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<button type="button" class="btn btn-success" @onclick="InstallLanguages">@Localizer["Install"]</button>
|
||||||
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
||||||
|
</TabPanel>
|
||||||
|
</TabStrip>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string _code = string.Empty;
|
private string _code = string.Empty;
|
||||||
private string _isDefault = "False";
|
private string _isDefault = "False";
|
||||||
|
private string _message;
|
||||||
|
private IEnumerable<Culture> _supportedCultures;
|
||||||
|
private IEnumerable<Culture> _availableCultures;
|
||||||
|
private List<Package> _packages;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
|
|
||||||
private IEnumerable<Culture> _supportedCultures;
|
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
|
var languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId);
|
||||||
|
var languagesCodes = languages.Select(l => l.Code).ToList();
|
||||||
|
|
||||||
_supportedCultures = await LocalizationService.GetCulturesAsync();
|
_supportedCultures = await LocalizationService.GetCulturesAsync();
|
||||||
if (_supportedCultures.Count() <= 1)
|
_availableCultures = _supportedCultures
|
||||||
|
.Where(c => !c.Name.Equals(Constants.DefaultCulture) && !languagesCodes.Contains(c.Name));
|
||||||
|
_packages = await PackageService.GetPackagesAsync("language");
|
||||||
|
|
||||||
|
if (_supportedCultures.Count() == 1)
|
||||||
{
|
{
|
||||||
AddModuleMessage(Localizer["The Only Supported Culture That Has Been Defined Is English"], MessageType.Warning);
|
_message = Localizer["The Only Installed Language Is English"];
|
||||||
|
}
|
||||||
|
else if (_availableCultures.Count() == 0)
|
||||||
|
{
|
||||||
|
_message = Localizer["All The Installed Languages Have Been Added."];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +155,35 @@ else
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task InstallLanguages()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await PackageService.InstallPackagesAsync();
|
||||||
|
AddModuleMessage(Localizer["Language Packages Installed Successfully. You Must <a href=\"{0}\">Restart</a> Your Application To Apply These Changes.", NavigateUrl("admin/system")], MessageType.Success);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Installing Language Package");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DownloadLanguage(string packageid, string version)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await PackageService.DownloadPackageAsync(packageid, version, "Packages");
|
||||||
|
await logger.LogInformation("Language Paclage {Name} {Version} Downloaded Successfully", packageid, version);
|
||||||
|
AddModuleMessage(Localizer["Language Package Downloaded Successfully. Click Install To Complete Installation."], MessageType.Success);
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Downloading Language Package {Name} {Version}", packageid, version);
|
||||||
|
AddModuleMessage(Localizer["Error Downloading Language Package"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task SetCultureAsync(string culture)
|
private async Task SetCultureAsync(string culture)
|
||||||
{
|
{
|
||||||
if (culture != CultureInfo.CurrentUICulture.Name)
|
if (culture != CultureInfo.CurrentUICulture.Name)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
@namespace Oqtane.Modules.Admin.Languages
|
@namespace Oqtane.Modules.Admin.Languages
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject ILanguageService LanguageService
|
@inject ILanguageService LanguageService
|
||||||
|
@inject ILocalizationService LocalizationService
|
||||||
|
@inject IPackageService PackageService
|
||||||
@inject IStringLocalizer<Index> Localizer
|
@inject IStringLocalizer<Index> Localizer
|
||||||
|
|
||||||
@if (_languages == null)
|
@if (_languages == null)
|
||||||
@ -17,24 +19,43 @@ else
|
|||||||
<th>@Localizer["Name"]</th>
|
<th>@Localizer["Name"]</th>
|
||||||
<th>@Localizer["Code"]</th>
|
<th>@Localizer["Code"]</th>
|
||||||
<th>@Localizer["Default?"]</th>
|
<th>@Localizer["Default?"]</th>
|
||||||
|
<th style="width: 1px;"> </th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td><ActionDialog Header="Delete Langauge" Message="@Localizer["Are You Sure You Wish To Delete The {0} Language?", context.Name]" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteLanguage(context))" Disabled="@(context.IsDefault)" ResourceKey="DeleteLanguage" /></td>
|
<td><ActionDialog Header="Delete Langauge" Message="@Localizer["Are You Sure You Wish To Delete The {0} Language From This Site?", context.Name]" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteLanguage(context))" Disabled="@((context.IsDefault && _languages.Count > 2) || context.Code == Constants.DefaultCulture)" ResourceKey="DeleteLanguage" /></td>
|
||||||
<td>@context.Name</td>
|
<td>@context.Name</td>
|
||||||
<td>@context.Code</td>
|
<td>@context.Code</td>
|
||||||
<td><TriStateCheckBox Value="@(context.IsDefault)" Disabled="true"></TriStateCheckBox></td>
|
<td><TriStateCheckBox Value="@(context.IsDefault)" Disabled="true"></TriStateCheckBox></td>
|
||||||
|
<td>
|
||||||
|
@if (UpgradeAvailable(context.Code))
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadLanguage(context.Code))>@Localizer["Upgrade"]</button>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
</Row>
|
</Row>
|
||||||
</Pager>
|
</Pager>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<Language> _languages;
|
private List<Language> _languages;
|
||||||
|
private List<Package> _packages;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
_languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId);
|
_languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId);
|
||||||
|
|
||||||
|
var cultures = await LocalizationService.GetCulturesAsync();
|
||||||
|
var culture = cultures.First(c => c.Name.Equals(Constants.DefaultCulture));
|
||||||
|
|
||||||
|
// Adds English as default language
|
||||||
|
_languages.Insert(0, new Language { Name = culture.DisplayName, Code = culture.Name, IsDefault = !_languages.Any(l => l.IsDefault) });
|
||||||
|
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
|
{
|
||||||
|
_packages = await PackageService.GetPackagesAsync("language");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DeleteLanguage(Language language)
|
private async Task DeleteLanguage(Language language)
|
||||||
@ -53,4 +74,38 @@ else
|
|||||||
AddModuleMessage(Localizer["Error Deleting Language"], MessageType.Error);
|
AddModuleMessage(Localizer["Error Deleting Language"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool UpgradeAvailable(string code)
|
||||||
|
{
|
||||||
|
var upgradeavailable = false;
|
||||||
|
if (_packages != null)
|
||||||
|
{
|
||||||
|
var package = _packages.Where(item => item.PackageId == (Constants.PackageId + ".Client." + code)).FirstOrDefault();
|
||||||
|
if (package != null)
|
||||||
|
{
|
||||||
|
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(Constants.Version)) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return upgradeavailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DownloadLanguage(string code)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
|
{
|
||||||
|
await PackageService.DownloadPackageAsync(Constants.PackageId + ".Client." + code, Constants.Version, "Packages");
|
||||||
|
await logger.LogInformation("Language Package Downloaded {Code} {Version}", code, Constants.Version);
|
||||||
|
await PackageService.InstallPackagesAsync();
|
||||||
|
AddModuleMessage(Localizer["Language Package Installed Successfully. You Must <a href=\"{0}\">Restart</a> Your Application To Apply These Changes.", NavigateUrl("admin/system")], MessageType.Success);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Downloading Language Package {Code} {Version} {Error}", code, Constants.Version, ex.Message);
|
||||||
|
AddModuleMessage(Localizer["Error Downloading Language Package"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,20 @@
|
|||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@inject IServiceProvider ServiceProvider
|
@inject IServiceProvider ServiceProvider
|
||||||
|
@inject SiteState SiteState
|
||||||
@inject IStringLocalizer<Index> Localizer
|
@inject IStringLocalizer<Index> Localizer
|
||||||
|
|
||||||
@if (_message != string.Empty)
|
@if (_message != string.Empty)
|
||||||
{
|
{
|
||||||
<ModuleMessage Message="@_message" Type="@_type" />
|
<ModuleMessage Message="@_message" Type="@_type" />
|
||||||
}
|
}
|
||||||
<AuthorizeView>
|
<AuthorizeView Roles="@RoleNames.Registered">
|
||||||
|
<Authorizing>
|
||||||
|
<text>...</text>
|
||||||
|
</Authorizing>
|
||||||
|
<Authorized>
|
||||||
|
<ModuleMessage Message="@Localizer["You Are Already Signed In"]" Type="MessageType.Info" />
|
||||||
|
</Authorized>
|
||||||
<NotAuthorized>
|
<NotAuthorized>
|
||||||
<form @ref="login" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
<form @ref="login" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||||
<div class="container Oqtane-Modules-Admin-Login" @onkeypress="@(e => KeyPressed(e))">
|
<div class="container Oqtane-Modules-Admin-Login" @onkeypress="@(e => KeyPressed(e))">
|
||||||
@ -51,7 +58,7 @@
|
|||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous;
|
||||||
|
|
||||||
public override List<Resource> Resources => new List<Resource>()
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
{
|
{
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -102,7 +109,6 @@
|
|||||||
{
|
{
|
||||||
if (PageState.Runtime == Oqtane.Shared.Runtime.Server)
|
if (PageState.Runtime == Oqtane.Shared.Runtime.Server)
|
||||||
{
|
{
|
||||||
// server-side Blazor
|
|
||||||
var user = new User();
|
var user = new User();
|
||||||
user.SiteId = PageState.Site.SiteId;
|
user.SiteId = PageState.Site.SiteId;
|
||||||
user.Username = _username;
|
user.Username = _username;
|
||||||
@ -112,10 +118,10 @@
|
|||||||
if (user.IsAuthenticated)
|
if (user.IsAuthenticated)
|
||||||
{
|
{
|
||||||
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
|
// server-side Blazor needs to post to the Login page so that the cookies are set correctly
|
||||||
string antiforgerytoken = await interop.GetElementByName("__RequestVerificationToken");
|
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, username = _username, password = _password, remember = _remember, returnurl = _returnUrl };
|
||||||
var fields = new { __RequestVerificationToken = antiforgerytoken, username = _username, password = _password, remember = _remember, returnurl = _returnUrl };
|
string url = Utilities.TenantUrl(PageState.Alias, "/pages/login/");
|
||||||
await interop.SubmitForm($"/{PageState.Alias.AliasId}/pages/login/", fields);
|
await interop.SubmitForm(url, fields);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
@namespace Oqtane.Modules.Admin.ModuleCreator
|
@namespace Oqtane.Modules.Admin.ModuleCreator
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
|
@using System.Text.RegularExpressions
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IModuleDefinitionService ModuleDefinitionService
|
@inject IModuleDefinitionService ModuleDefinitionService
|
||||||
@inject IModuleService ModuleService
|
@inject IModuleService ModuleService
|
||||||
@inject ISystemService SystemService
|
|
||||||
@inject ISettingService SettingService
|
@inject ISettingService SettingService
|
||||||
@inject IStringLocalizer<Index> Localizer
|
@inject IStringLocalizer<Index> Localizer
|
||||||
@using System.Text.RegularExpressions
|
|
||||||
@using System.IO;
|
|
||||||
|
|
||||||
@if (string.IsNullOrEmpty(_moduledefinitionname) && _systeminfo != null && _templates != null)
|
@if (string.IsNullOrEmpty(_moduledefinitionname) && _templates != null)
|
||||||
{
|
{
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
@ -43,9 +41,9 @@
|
|||||||
<td>
|
<td>
|
||||||
<select id="template" class="form-control" @onchange="(e => TemplateChanged(e))">
|
<select id="template" class="form-control" @onchange="(e => TemplateChanged(e))">
|
||||||
<option value="-"><@Localizer["Select Template"]></option>
|
<option value="-"><@Localizer["Select Template"]></option>
|
||||||
@foreach (string template in _templates)
|
@foreach (Template template in _templates)
|
||||||
{
|
{
|
||||||
<option value="@template">@template</option>
|
<option value="@template.Name">@template.Title</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
@ -56,9 +54,9 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="reference" class="form-control" @bind="@_reference">
|
<select id="reference" class="form-control" @bind="@_reference">
|
||||||
@foreach (string version in Constants.ReleaseVersions.Split(','))
|
@foreach (string version in _versions)
|
||||||
{
|
{
|
||||||
if (Version.Parse(version).CompareTo(Version.Parse("2.0.0")) >= 0)
|
if (Version.Parse(version).CompareTo(Version.Parse(_minversion)) >= 0)
|
||||||
{
|
{
|
||||||
<option value="@(version)">@(version)</option>
|
<option value="@(version)">@(version)</option>
|
||||||
}
|
}
|
||||||
@ -91,13 +89,13 @@ else
|
|||||||
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 List<Template> _templates;
|
||||||
private string _template = "-";
|
private string _template = "-";
|
||||||
|
private string[] _versions;
|
||||||
private string _reference = Constants.Version;
|
private string _reference = Constants.Version;
|
||||||
|
private string _minversion = "2.0.0";
|
||||||
private string _location = string.Empty;
|
private string _location = string.Empty;
|
||||||
|
|
||||||
private Dictionary<string, string> _systeminfo;
|
|
||||||
private List<string> _templates;
|
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
@ -105,8 +103,8 @@ else
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_moduledefinitionname = SettingService.GetSetting(ModuleState.Settings, "ModuleDefinitionName", "");
|
_moduledefinitionname = SettingService.GetSetting(ModuleState.Settings, "ModuleDefinitionName", "");
|
||||||
_systeminfo = await SystemService.GetSystemInfoAsync();
|
|
||||||
_templates = await ModuleDefinitionService.GetModuleDefinitionTemplatesAsync();
|
_templates = await ModuleDefinitionService.GetModuleDefinitionTemplatesAsync();
|
||||||
|
_versions = Constants.ReleaseVersions.Split(',').Where(item => Version.Parse(item).CompareTo(Version.Parse("2.0.0")) >= 0).ToArray();
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(_moduledefinitionname))
|
if (string.IsNullOrEmpty(_moduledefinitionname))
|
||||||
{
|
{
|
||||||
@ -172,23 +170,29 @@ else
|
|||||||
private bool IsValid(string name)
|
private bool IsValid(string name)
|
||||||
{
|
{
|
||||||
// must contain letters, underscores and digits and first character must be letter or underscore
|
// must contain letters, underscores and digits and first character must be letter or underscore
|
||||||
return !string.IsNullOrEmpty(name) && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_]*$");
|
return !string.IsNullOrEmpty(name) && name.ToLower() != "module" && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_]*$");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TemplateChanged(ChangeEventArgs e)
|
private void TemplateChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
_template = (string)e.Value;
|
_template = (string)e.Value;
|
||||||
|
_minversion = "2.0.0";
|
||||||
|
if (_template != "-")
|
||||||
|
{
|
||||||
|
var template = _templates.FirstOrDefault(item => item.Name == _template);
|
||||||
|
_minversion = template.Version;
|
||||||
|
}
|
||||||
GetLocation();
|
GetLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetLocation()
|
private void GetLocation()
|
||||||
{
|
{
|
||||||
_location = string.Empty;
|
_location = string.Empty;
|
||||||
if (_template != "-" && _systeminfo != null && _systeminfo.ContainsKey("serverpath"))
|
if (_owner != "" && _module != "" && _template != "-")
|
||||||
{
|
{
|
||||||
string[] path = _systeminfo["serverpath"].Split(Path.DirectorySeparatorChar);
|
var template = _templates.FirstOrDefault(item => item.Name == _template);
|
||||||
_location = string.Join(Path.DirectorySeparatorChar, path, 0, path.Length - 2) +
|
_location = template.Location + _owner + "." + _module;
|
||||||
Path.DirectorySeparatorChar + _owner + "." + _module;
|
|
||||||
}
|
}
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
<Label HelpText="Upload one or more module packages. Once they are uploaded click Install to complete the installation." ResourceKey="Module">Module: </Label>
|
<Label HelpText="Upload one or more module packages. Once they are uploaded click Install to complete the installation." ResourceKey="Module">Module: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<FileManager Filter="nupkg" ShowFiles="false" Folder="Modules" UploadMultiple="true" />
|
<FileManager Filter="nupkg" ShowFiles="false" Folder="Packages" UploadMultiple="true" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
foreach (Package package in _packages.ToArray())
|
foreach (Package package in _packages.ToArray())
|
||||||
{
|
{
|
||||||
if (moduledefinitions.Exists(item => Utilities.GetTypeName(item.ModuleDefinitionName) == package.PackageId))
|
if (moduledefinitions.Exists(item => item.PackageName == package.PackageId))
|
||||||
{
|
{
|
||||||
_packages.Remove(package);
|
_packages.Remove(package);
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(packageid, version, "Modules");
|
await PackageService.DownloadPackageAsync(packageid, version, "Packages");
|
||||||
await logger.LogInformation("Module {ModuleDefinitionName} {Version} Downloaded Successfully", packageid, version);
|
await logger.LogInformation("Module {ModuleDefinitionName} {Version} Downloaded Successfully", packageid, version);
|
||||||
AddModuleMessage(Localizer["Modules Downloaded Successfully. Click Install To Complete Installation."], MessageType.Success);
|
AddModuleMessage(Localizer["Modules Downloaded Successfully. Click Install To Complete Installation."], MessageType.Success);
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
@namespace Oqtane.Modules.Admin.ModuleDefinitions
|
@namespace Oqtane.Modules.Admin.ModuleDefinitions
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
|
@using System.Text.RegularExpressions
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IModuleDefinitionService ModuleDefinitionService
|
@inject IModuleDefinitionService ModuleDefinitionService
|
||||||
@inject IModuleService ModuleService
|
@inject IModuleService ModuleService
|
||||||
@inject ISystemService SystemService
|
|
||||||
@inject ISettingService SettingService
|
@inject ISettingService SettingService
|
||||||
@inject IStringLocalizer<Index> Localizer
|
@inject IStringLocalizer<Index> Localizer
|
||||||
@using System.Text.RegularExpressions
|
|
||||||
@using System.IO;
|
|
||||||
|
|
||||||
@if (_systeminfo != null && _templates != null)
|
@if (_templates != null)
|
||||||
{
|
{
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
@ -43,9 +41,9 @@
|
|||||||
<td>
|
<td>
|
||||||
<select id="template" class="form-control" @onchange="(e => TemplateChanged(e))">
|
<select id="template" class="form-control" @onchange="(e => TemplateChanged(e))">
|
||||||
<option value="-"><@Localizer["Select Template"]></option>
|
<option value="-"><@Localizer["Select Template"]></option>
|
||||||
@foreach (string template in _templates)
|
@foreach (Template template in _templates)
|
||||||
{
|
{
|
||||||
<option value="@template">@template</option>
|
<option value="@template.Name">@template.Title</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
@ -56,9 +54,9 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="reference" class="form-control" @bind="@_reference">
|
<select id="reference" class="form-control" @bind="@_reference">
|
||||||
@foreach (string version in Constants.ReleaseVersions.Split(','))
|
@foreach (string version in _versions)
|
||||||
{
|
{
|
||||||
if (Version.Parse(version).CompareTo(Version.Parse("2.0.0")) >= 0)
|
if (Version.Parse(version).CompareTo(Version.Parse(_minversion)) >= 0)
|
||||||
{
|
{
|
||||||
<option value="@(version)">@(version)</option>
|
<option value="@(version)">@(version)</option>
|
||||||
}
|
}
|
||||||
@ -87,21 +85,21 @@
|
|||||||
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 List<Template> _templates;
|
||||||
private string _template = "-";
|
private string _template = "-";
|
||||||
|
private string[] _versions;
|
||||||
private string _reference = Constants.Version;
|
private string _reference = Constants.Version;
|
||||||
|
private string _minversion = "2.0.0";
|
||||||
private string _location = string.Empty;
|
private string _location = string.Empty;
|
||||||
|
|
||||||
private Dictionary<string, string> _systeminfo;
|
|
||||||
private List<string> _templates;
|
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_systeminfo = await SystemService.GetSystemInfoAsync();
|
|
||||||
_templates = await ModuleDefinitionService.GetModuleDefinitionTemplatesAsync();
|
_templates = await ModuleDefinitionService.GetModuleDefinitionTemplatesAsync();
|
||||||
|
_versions = Constants.ReleaseVersions.Split(',').Where(item => Version.Parse(item).CompareTo(Version.Parse("2.0.0")) >= 0).ToArray();
|
||||||
AddModuleMessage(Localizer["Please Note That The Module Creator Is Only Intended To Be Used In A Development Environment"], MessageType.Info);
|
AddModuleMessage(Localizer["Please Note That The Module Creator Is Only Intended To Be Used In A Development Environment"], MessageType.Info);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -135,23 +133,29 @@
|
|||||||
private bool IsValid(string name)
|
private bool IsValid(string name)
|
||||||
{
|
{
|
||||||
// must contain letters, underscores and digits and first character must be letter or underscore
|
// must contain letters, underscores and digits and first character must be letter or underscore
|
||||||
return !string.IsNullOrEmpty(name) && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_]*$");
|
return !string.IsNullOrEmpty(name) && name.ToLower() != "module" && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_]*$");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TemplateChanged(ChangeEventArgs e)
|
private void TemplateChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
_template = (string)e.Value;
|
_template = (string)e.Value;
|
||||||
|
_minversion = "2.0.0";
|
||||||
|
if (_template != "-")
|
||||||
|
{
|
||||||
|
var template = _templates.FirstOrDefault(item => item.Name == _template);
|
||||||
|
_minversion = template.Version;
|
||||||
|
}
|
||||||
GetLocation();
|
GetLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetLocation()
|
private void GetLocation()
|
||||||
{
|
{
|
||||||
_location = string.Empty;
|
_location = string.Empty;
|
||||||
if (_template != "-" && _systeminfo != null && _systeminfo.ContainsKey("serverpath"))
|
if (_owner != "" && _module != "" && _template != "-")
|
||||||
{
|
{
|
||||||
string[] path = _systeminfo["serverpath"].Split(Path.DirectorySeparatorChar);
|
var template = _templates.FirstOrDefault(item => item.Name == _template);
|
||||||
_location = string.Join(Path.DirectorySeparatorChar, path, 0, path.Length - 2) +
|
_location = template.Location + _owner + "." + _module;
|
||||||
Path.DirectorySeparatorChar + _owner + "." + _module;
|
|
||||||
}
|
}
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
@ -34,9 +34,9 @@ else
|
|||||||
<td>@context.Name</td>
|
<td>@context.Name</td>
|
||||||
<td>@context.Version</td>
|
<td>@context.Version</td>
|
||||||
<td>
|
<td>
|
||||||
@if (UpgradeAvailable(context.ModuleDefinitionName, context.Version))
|
@if (UpgradeAvailable(context.PackageName, context.Version))
|
||||||
{
|
{
|
||||||
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadModule(context.ModuleDefinitionName, context.Version))>@Localizer["Upgrade"]</button>
|
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadModule(context.PackageName, context.Version))>@Localizer["Upgrade"]</button>
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
</Row>
|
</Row>
|
||||||
@ -66,12 +66,12 @@ else
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool UpgradeAvailable(string moduledefinitionname, string version)
|
private bool UpgradeAvailable(string packagename, string version)
|
||||||
{
|
{
|
||||||
var upgradeavailable = false;
|
var upgradeavailable = false;
|
||||||
if (_packages != null)
|
if (_packages != null)
|
||||||
{
|
{
|
||||||
var package = _packages.Where(item => item.PackageId == Utilities.GetTypeName(moduledefinitionname)).FirstOrDefault();
|
var package = _packages.Where(item => item.PackageId == packagename).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);
|
||||||
@ -81,18 +81,18 @@ else
|
|||||||
return upgradeavailable;
|
return upgradeavailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DownloadModule(string moduledefinitionname, string version)
|
private async Task DownloadModule(string packagename, string version)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(moduledefinitionname, version, "Modules");
|
await PackageService.DownloadPackageAsync(packagename, version, "Packages");
|
||||||
await logger.LogInformation("Module Downloaded {ModuleDefinitionName} {Version}", moduledefinitionname, version);
|
await logger.LogInformation("Module Downloaded {ModuleDefinitionName} {Version}", packagename, version);
|
||||||
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
|
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
|
||||||
AddModuleMessage(Localizer["Module Installed Successfully. You Must <a href=\"{0}\">Restart</a> Your Application To Apply These Changes.", NavigateUrl("admin/system")], MessageType.Success);
|
AddModuleMessage(Localizer["Module Installed Successfully. You Must <a href=\"{0}\">Restart</a> Your Application To Apply These Changes.", NavigateUrl("admin/system")], MessageType.Success);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Downloading Module {ModuleDefinitionName} {Version} {Error}", moduledefinitionname, version, ex.Message);
|
await logger.LogError(ex, "Error Downloading Module {ModuleDefinitionName} {Version} {Error}", packagename, version, ex.Message);
|
||||||
AddModuleMessage(Localizer["Error Downloading Module"], MessageType.Error);
|
AddModuleMessage(Localizer["Error Downloading Module"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ else
|
|||||||
{
|
{
|
||||||
await ModuleDefinitionService.DeleteModuleDefinitionAsync(moduleDefinition.ModuleDefinitionId, moduleDefinition.SiteId);
|
await ModuleDefinitionService.DeleteModuleDefinitionAsync(moduleDefinition.ModuleDefinitionId, moduleDefinition.SiteId);
|
||||||
AddModuleMessage(Localizer["Module Deleted Successfully"], MessageType.Success);
|
AddModuleMessage(Localizer["Module Deleted Successfully"], MessageType.Success);
|
||||||
StateHasChanged();
|
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "reload"));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -167,46 +167,53 @@
|
|||||||
|
|
||||||
private async Task SaveModule()
|
private async Task SaveModule()
|
||||||
{
|
{
|
||||||
var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
|
if (!string.IsNullOrEmpty(_title))
|
||||||
pagemodule.PageId = int.Parse(_pageId);
|
|
||||||
pagemodule.Title = _title;
|
|
||||||
pagemodule.ContainerType = (_containerType != "-") ? _containerType : string.Empty;
|
|
||||||
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Page.DefaultContainerType)
|
|
||||||
{
|
{
|
||||||
pagemodule.ContainerType = string.Empty;
|
var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
|
||||||
}
|
pagemodule.PageId = int.Parse(_pageId);
|
||||||
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Site.DefaultContainerType)
|
pagemodule.Title = _title;
|
||||||
{
|
pagemodule.ContainerType = (_containerType != "-") ? _containerType : string.Empty;
|
||||||
pagemodule.ContainerType = string.Empty;
|
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Page.DefaultContainerType)
|
||||||
}
|
|
||||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
|
||||||
|
|
||||||
var module = ModuleState;
|
|
||||||
module.AllPages = bool.Parse(_allPages);
|
|
||||||
module.Permissions = _permissionGrid.GetPermissions();
|
|
||||||
await ModuleService.UpdateModuleAsync(module);
|
|
||||||
|
|
||||||
if (_moduleSettingsType != null)
|
|
||||||
{
|
|
||||||
if (_moduleSettings is ISettingsControl moduleSettingsControl)
|
|
||||||
{
|
{
|
||||||
// module settings updated using explicit interface
|
pagemodule.ContainerType = string.Empty;
|
||||||
await moduleSettingsControl.UpdateSettings();
|
|
||||||
}
|
}
|
||||||
else
|
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Site.DefaultContainerType)
|
||||||
{
|
{
|
||||||
// legacy support - module settings updated by convention ( ie. by calling a public method named "UpdateSettings" in settings component )
|
pagemodule.ContainerType = string.Empty;
|
||||||
_moduleSettings?.GetType().GetMethod("UpdateSettings")?.Invoke(_moduleSettings, null);
|
|
||||||
}
|
}
|
||||||
}
|
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||||
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||||
|
|
||||||
if (_containerSettingsType != null && _containerSettings is ISettingsControl containerSettingsControl)
|
var module = ModuleState;
|
||||||
|
module.AllPages = bool.Parse(_allPages);
|
||||||
|
module.Permissions = _permissionGrid.GetPermissions();
|
||||||
|
await ModuleService.UpdateModuleAsync(module);
|
||||||
|
|
||||||
|
if (_moduleSettingsType != null)
|
||||||
|
{
|
||||||
|
if (_moduleSettings is ISettingsControl moduleSettingsControl)
|
||||||
|
{
|
||||||
|
// module settings updated using explicit interface
|
||||||
|
await moduleSettingsControl.UpdateSettings();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// legacy support - module settings updated by convention ( ie. by calling a public method named "UpdateSettings" in settings component )
|
||||||
|
_moduleSettings?.GetType().GetMethod("UpdateSettings")?.Invoke(_moduleSettings, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_containerSettingsType != null && _containerSettings is ISettingsControl containerSettingsControl)
|
||||||
|
{
|
||||||
|
await containerSettingsControl.UpdateSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
await containerSettingsControl.UpdateSettings();
|
AddModuleMessage(Localizer["You Must Provide A Title For The Module"], MessageType.Warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,87 +5,98 @@
|
|||||||
@inject IThemeService ThemeService
|
@inject IThemeService ThemeService
|
||||||
@inject IStringLocalizer<Add> Localizer
|
@inject IStringLocalizer<Add> Localizer
|
||||||
|
|
||||||
<TabStrip>
|
<TabStrip Refresh="@_refresh">
|
||||||
<TabPanel Name="Settings" ResourceKey="Settings">
|
<TabPanel Name="Settings" ResourceKey="Settings">
|
||||||
@if (_themeList != null)
|
@if (_themeList != null)
|
||||||
{
|
{
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="Name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label>
|
<Label For="Name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input id="Name" class="form-control" @bind="@_name" />
|
<input id="Name" class="form-control" @bind="@_name" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="Parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
<Label For="Parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="Parent" class="form-control" @onchange="(e => ParentChanged(e))">
|
<select id="Parent" class="form-control" @onchange="(e => ParentChanged(e))">
|
||||||
<option value="-1"><@Localizer["Site Root"]></option>
|
<option value="-1"><@Localizer["Site Root"]></option>
|
||||||
@foreach (Page page in _pageList)
|
@foreach (Page page in _pageList)
|
||||||
{
|
|
||||||
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="Insert" HelpText="Select the location where you would like the page to be inserted in relation to other pages" ResourceKey="Insert">Insert: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<select id="Insert" class="form-control" @bind="@_insert">
|
|
||||||
<option value="<<">@Localizer["At Beginning"]</option>
|
|
||||||
@if (_children != null && _children.Count > 0)
|
|
||||||
{
|
|
||||||
<option value="<">@Localizer["Before"]</option>
|
|
||||||
<option value=">">@Localizer["After"]</option>
|
|
||||||
}
|
|
||||||
<option value=">>">@Localizer["At End"]</option>
|
|
||||||
</select>
|
|
||||||
@if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">"))
|
|
||||||
{
|
{
|
||||||
<select class="form-control" @bind="@_childid">
|
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
||||||
<option value="-1"><@Localizer["Select Page"]></option>
|
|
||||||
@foreach (Page page in _children)
|
|
||||||
{
|
|
||||||
<option value="@(page.PageId)">@(page.Name)</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
}
|
}
|
||||||
</td>
|
</select>
|
||||||
</tr>
|
</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td>
|
<tr>
|
||||||
<Label For="Navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
|
<td>
|
||||||
</td>
|
<Label For="Insert" HelpText="Select the location where you would like the page to be inserted in relation to other pages" ResourceKey="Insert">Insert: </Label>
|
||||||
<td>
|
</td>
|
||||||
<select id="Navigation" class="form-control" @bind="@_isnavigation">
|
<td>
|
||||||
<option value="True">@Localizer["Yes"]</option>
|
<select id="Insert" class="form-control" @bind="@_insert">
|
||||||
<option value="False">@Localizer["No"]</option>
|
<option value="<<">@Localizer["At Beginning"]</option>
|
||||||
|
@if (_children != null && _children.Count > 0)
|
||||||
|
{
|
||||||
|
<option value="<">@Localizer["Before"]</option>
|
||||||
|
<option value=">">@Localizer["After"]</option>
|
||||||
|
}
|
||||||
|
<option value=">>">@Localizer["At End"]</option>
|
||||||
|
</select>
|
||||||
|
@if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">"))
|
||||||
|
{
|
||||||
|
<select class="form-control" @bind="@_childid">
|
||||||
|
<option value="-1"><@Localizer["Select Page"]></option>
|
||||||
|
@foreach (Page page in _children)
|
||||||
|
{
|
||||||
|
<option value="@(page.PageId)">@(page.Name)</option>
|
||||||
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
}
|
||||||
</tr>
|
</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td>
|
<tr>
|
||||||
<Label For="Path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used." ResourceKey="UrlPath">Url Path: </Label>
|
<td>
|
||||||
</td>
|
<Label For="Navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
|
||||||
<td>
|
</td>
|
||||||
<input id="Path" class="form-control" @bind="@_path" />
|
<td>
|
||||||
</td>
|
<select id="Navigation" class="form-control" @bind="@_isnavigation">
|
||||||
</tr>
|
<option value="True">@Localizer["Yes"]</option>
|
||||||
<tr>
|
<option value="False">@Localizer["No"]</option>
|
||||||
<td>
|
</select>
|
||||||
<Label For="Url" HelpText="Optionally enter a url which this page should redirect to when a user navigates to it" ResourceKey="Redirect">Redirect: </Label>
|
</td>
|
||||||
</td>
|
</tr>
|
||||||
<td>
|
<tr>
|
||||||
<input id="Url" class="form-control" @bind="@_url" />
|
<td>
|
||||||
</td>
|
<Label For="Clickablen" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label>
|
||||||
</tr>
|
</td>
|
||||||
</table>
|
<td>
|
||||||
|
<select id="Navigation" class="form-control" @bind="@_isclickable">
|
||||||
|
<option value="True">@Localizer["Yes"]</option>
|
||||||
|
<option value="False">@Localizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="Path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used." ResourceKey="UrlPath">Url Path: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="Path" class="form-control" @bind="@_path" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="Url" HelpText="Optionally enter a url which this page should redirect to when a user navigates to it" ResourceKey="Redirect">Redirect: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="Url" class="form-control" @bind="@_url" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
<Section Name="Appearance" ResourceKey="Appearance">
|
<Section Name="Appearance" ResourceKey="Appearance">
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
@ -180,6 +191,7 @@
|
|||||||
private List<Page> _children;
|
private List<Page> _children;
|
||||||
private int _childid = -1;
|
private int _childid = -1;
|
||||||
private string _isnavigation = "True";
|
private string _isnavigation = "True";
|
||||||
|
private string _isclickable = "True";
|
||||||
private string _url;
|
private string _url;
|
||||||
private string _ispersonalizable = "False";
|
private string _ispersonalizable = "False";
|
||||||
private string _themetype = string.Empty;
|
private string _themetype = string.Empty;
|
||||||
@ -190,6 +202,7 @@
|
|||||||
private Type _themeSettingsType;
|
private Type _themeSettingsType;
|
||||||
private object _themeSettings;
|
private object _themeSettings;
|
||||||
private RenderFragment ThemeSettingsComponent { get; set; }
|
private RenderFragment ThemeSettingsComponent { get; set; }
|
||||||
|
private bool _refresh = false;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
@ -280,6 +293,7 @@
|
|||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
_refresh = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,7 +302,7 @@
|
|||||||
Page page = null;
|
Page page = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (_name != string.Empty && !string.IsNullOrEmpty(_themetype) && _containertype != "-")
|
if (!string.IsNullOrEmpty(_name) && !string.IsNullOrEmpty(_themetype) && _containertype != "-")
|
||||||
{
|
{
|
||||||
page = new Page();
|
page = new Page();
|
||||||
page.SiteId = PageState.Page.SiteId;
|
page.SiteId = PageState.Page.SiteId;
|
||||||
@ -349,6 +363,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
page.IsNavigation = (_isnavigation == null ? true : Boolean.Parse(_isnavigation));
|
page.IsNavigation = (_isnavigation == null ? true : Boolean.Parse(_isnavigation));
|
||||||
|
page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
|
||||||
page.Url = _url;
|
page.Url = _url;
|
||||||
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
||||||
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
|
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
|
||||||
|
@ -6,94 +6,105 @@
|
|||||||
@inject IThemeService ThemeService
|
@inject IThemeService ThemeService
|
||||||
@inject IStringLocalizer<Edit> Localizer
|
@inject IStringLocalizer<Edit> Localizer
|
||||||
|
|
||||||
<TabStrip>
|
<TabStrip Refresh="@_refresh">
|
||||||
<TabPanel Name="Settings" ResourceKey="Settings">
|
<TabPanel Name="Settings" ResourceKey="Settings">
|
||||||
@if (_themeList != null)
|
@if (_themeList != null)
|
||||||
{
|
{
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="Name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label>
|
<Label For="Name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input id="Name" class="form-control" @bind="@_name" />
|
<input id="Name" class="form-control" @bind="@_name" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="Parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
<Label For="Parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="Parent" class="form-control" value="@_parentid" @onchange="(e => ParentChanged(e))">
|
<select id="Parent" class="form-control" value="@_parentid" @onchange="(e => ParentChanged(e))">
|
||||||
<option value="-1"><@Localizer["Site Root"]></option>
|
<option value="-1"><@Localizer["Site Root"]></option>
|
||||||
@foreach (Page page in _pageList)
|
@foreach (Page page in _pageList)
|
||||||
{
|
|
||||||
if (page.PageId != _pageId)
|
|
||||||
{
|
|
||||||
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="Move" HelpText="Select the location where you would like the page to be moved in relation to other pages" ResourceKey="Move">Move: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<select id="Move" class="form-control" @bind="@_insert">
|
|
||||||
@if (_parentid == _currentparentid)
|
|
||||||
{
|
|
||||||
<option value="="><@Localizer["Maintain Current Location"]></option>
|
|
||||||
}
|
|
||||||
<option value="<<">@Localizer["To Beginning"]</option>
|
|
||||||
@if (_children != null && _children.Count > 0)
|
|
||||||
{
|
|
||||||
<option value="<">@Localizer["Before"]</option>
|
|
||||||
<option value=">">@Localizer["After"]</option>
|
|
||||||
}
|
|
||||||
<option value=">>">@Localizer["To End"]</option>
|
|
||||||
</select>
|
|
||||||
@if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">"))
|
|
||||||
{
|
{
|
||||||
<select class="form-control" @bind="@_childid">
|
if (page.PageId != _pageId)
|
||||||
<option value="-1"><@Localizer["Select Page"]></option>
|
{
|
||||||
@foreach (Page page in _children)
|
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
||||||
{
|
}
|
||||||
<option value="@(page.PageId)">@(page.Name)</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
}
|
}
|
||||||
</td>
|
</select>
|
||||||
</tr>
|
</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td>
|
<tr>
|
||||||
<Label For="Navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
|
<td>
|
||||||
</td>
|
<Label For="Move" HelpText="Select the location where you would like the page to be moved in relation to other pages" ResourceKey="Move">Move: </Label>
|
||||||
<td>
|
</td>
|
||||||
<select id="Navigation" class="form-control" @bind="@_isnavigation">
|
<td>
|
||||||
<option value="True">@Localizer["Yes"]</option>
|
<select id="Move" class="form-control" @bind="@_insert">
|
||||||
<option value="False">@Localizer["No"]</option>
|
@if (_parentid == _currentparentid)
|
||||||
|
{
|
||||||
|
<option value="="><@Localizer["Maintain Current Location"]></option>
|
||||||
|
}
|
||||||
|
<option value="<<">@Localizer["To Beginning"]</option>
|
||||||
|
@if (_children != null && _children.Count > 0)
|
||||||
|
{
|
||||||
|
<option value="<">@Localizer["Before"]</option>
|
||||||
|
<option value=">">@Localizer["After"]</option>
|
||||||
|
}
|
||||||
|
<option value=">>">@Localizer["To End"]</option>
|
||||||
|
</select>
|
||||||
|
@if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">"))
|
||||||
|
{
|
||||||
|
<select class="form-control" @bind="@_childid">
|
||||||
|
<option value="-1"><@Localizer["Select Page"]></option>
|
||||||
|
@foreach (Page page in _children)
|
||||||
|
{
|
||||||
|
<option value="@(page.PageId)">@(page.Name)</option>
|
||||||
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
}
|
||||||
</tr>
|
</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td>
|
<tr>
|
||||||
<Label For="Path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used." ResourceKey="UrlPath">Url Path: </Label>
|
<td>
|
||||||
</td>
|
<Label For="Navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
|
||||||
<td>
|
</td>
|
||||||
<input id="Path" class="form-control" @bind="@_path" />
|
<td>
|
||||||
</td>
|
<select id="Navigation" class="form-control" @bind="@_isnavigation">
|
||||||
</tr>
|
<option value="True">@Localizer["Yes"]</option>
|
||||||
<tr>
|
<option value="False">@Localizer["No"]</option>
|
||||||
<td>
|
</select>
|
||||||
<Label For="Url" HelpText="Optionally enter a url which this page should redirect to when a user navigates to it" ResourceKey="Redirect">Redirect: </Label>
|
</td>
|
||||||
</td>
|
</tr>
|
||||||
<td>
|
<tr>
|
||||||
<input id="Url" class="form-control" @bind="@_url" />
|
<td>
|
||||||
</td>
|
<Label For="Clickablen" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label>
|
||||||
</tr>
|
</td>
|
||||||
</table>
|
<td>
|
||||||
|
<select id="Navigation" class="form-control" @bind="@_isclickable">
|
||||||
|
<option value="True">@Localizer["Yes"]</option>
|
||||||
|
<option value="False">@Localizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="Path" HelpText="Optionally enter a url path for this page (ie. home ). If you do not provide a url path, the page name will be used." ResourceKey="UrlPath">Url Path: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="Path" class="form-control" @bind="@_path" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="Url" HelpText="Optionally enter a url which this page should redirect to when a user navigates to it" ResourceKey="Redirect">Redirect: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="Url" class="form-control" @bind="@_url" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
<Section Name="Appearance" ResourceKey="Appearance">
|
<Section Name="Appearance" ResourceKey="Appearance">
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
@ -195,6 +206,7 @@
|
|||||||
private List<Page> _children;
|
private List<Page> _children;
|
||||||
private int _childid = -1;
|
private int _childid = -1;
|
||||||
private string _isnavigation;
|
private string _isnavigation;
|
||||||
|
private string _isclickable;
|
||||||
private string _url;
|
private string _url;
|
||||||
private string _ispersonalizable;
|
private string _ispersonalizable;
|
||||||
private string _themetype;
|
private string _themetype;
|
||||||
@ -211,6 +223,7 @@
|
|||||||
private Type _themeSettingsType;
|
private Type _themeSettingsType;
|
||||||
private object _themeSettings;
|
private object _themeSettings;
|
||||||
private RenderFragment ThemeSettingsComponent { get; set; }
|
private RenderFragment ThemeSettingsComponent { get; set; }
|
||||||
|
private bool _refresh = false;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
@ -246,6 +259,7 @@
|
|||||||
|
|
||||||
_currentparentid = _parentid;
|
_currentparentid = _parentid;
|
||||||
_isnavigation = page.IsNavigation.ToString();
|
_isnavigation = page.IsNavigation.ToString();
|
||||||
|
_isclickable = page.IsClickable.ToString();
|
||||||
_url = page.Url;
|
_url = page.Url;
|
||||||
_ispersonalizable = page.IsPersonalizable.ToString();
|
_ispersonalizable = page.IsPersonalizable.ToString();
|
||||||
_themetype = page.ThemeType;
|
_themetype = page.ThemeType;
|
||||||
@ -354,6 +368,7 @@
|
|||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
_refresh = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,6 +440,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
page.IsNavigation = (_isnavigation == null || Boolean.Parse(_isnavigation));
|
page.IsNavigation = (_isnavigation == null || Boolean.Parse(_isnavigation));
|
||||||
|
page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
|
||||||
page.Url = _url;
|
page.Url = _url;
|
||||||
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
||||||
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
|
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
@if (PageState.Site.AllowRegistration)
|
@if (PageState.Site.AllowRegistration)
|
||||||
{
|
{
|
||||||
<AuthorizeView>
|
<AuthorizeView Roles="@RoleNames.Registered">
|
||||||
<Authorizing>
|
<Authorizing>
|
||||||
<text>...</text>
|
<text>...</text>
|
||||||
</Authorizing>
|
</Authorizing>
|
||||||
|
@ -4,39 +4,44 @@
|
|||||||
@inject IRoleService RoleService
|
@inject IRoleService RoleService
|
||||||
@inject IStringLocalizer<Add> Localizer
|
@inject IStringLocalizer<Add> Localizer
|
||||||
|
|
||||||
<table class="table table-borderless">
|
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||||
<tr>
|
<table class="table table-borderless">
|
||||||
<td>
|
<tr>
|
||||||
<Label For="name" HelpText="Name Of The Role" ResourceKey="Name">Name:</Label>
|
<td>
|
||||||
</td>
|
<Label For="name" HelpText="Name Of The Role" ResourceKey="Name">Name:</Label>
|
||||||
<td>
|
</td>
|
||||||
<input id="name" class="form-control" @bind="@_name" />
|
<td>
|
||||||
</td>
|
<input id="name" class="form-control" @bind="@_name" required />
|
||||||
</tr>
|
</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td>
|
<tr>
|
||||||
<Label For="description" HelpText="A Short Description Of The Role Which Describes Its Purpose" ResourceKey="Description">Description:</Label>
|
<td>
|
||||||
</td>
|
<Label For="description" HelpText="A Short Description Of The Role Which Describes Its Purpose" ResourceKey="Description">Description:</Label>
|
||||||
<td>
|
</td>
|
||||||
<textarea id="description" class="form-control" @bind="@_description" rows="5"></textarea>
|
<td>
|
||||||
</td>
|
<textarea id="description" class="form-control" @bind="@_description" rows="5" required></textarea>
|
||||||
</tr>
|
</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td>
|
<tr>
|
||||||
<Label For="isautoassigned" HelpText="Indicates Whether Or Not New Users Are Automatically Assigned To This Role" ResourceKey="AutoAssigned">Auto Assigned?</Label>
|
<td>
|
||||||
</td>
|
<Label For="isautoassigned" HelpText="Indicates Whether Or Not New Users Are Automatically Assigned To This Role" ResourceKey="AutoAssigned">Auto Assigned?</Label>
|
||||||
<td>
|
</td>
|
||||||
<select id="isautoassigned" class="form-control" @bind="@_isautoassigned">
|
<td>
|
||||||
<option value="True">@Localizer["Yes"]</option>
|
<select id="isautoassigned" class="form-control" @bind="@_isautoassigned">
|
||||||
<option value="False">@Localizer["No"]</option>
|
<option value="True">@Localizer["Yes"]</option>
|
||||||
</select>
|
<option value="False">@Localizer["No"]</option>
|
||||||
</td>
|
</select>
|
||||||
</tr>
|
</td>
|
||||||
</table>
|
</tr>
|
||||||
<button type="button" class="btn btn-success" @onclick="SaveRole">@Localizer["Save"]</button>
|
</table>
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
<button type="button" class="btn btn-success" @onclick="SaveRole">@Localizer["Save"]</button>
|
||||||
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
||||||
|
</form>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
private ElementReference form;
|
||||||
|
private bool validated = false;
|
||||||
|
|
||||||
private string _name = string.Empty;
|
private string _name = string.Empty;
|
||||||
private string _description = string.Empty;
|
private string _description = string.Empty;
|
||||||
private string _isautoassigned = "False";
|
private string _isautoassigned = "False";
|
||||||
@ -45,24 +50,33 @@
|
|||||||
|
|
||||||
private async Task SaveRole()
|
private async Task SaveRole()
|
||||||
{
|
{
|
||||||
var role = new Role();
|
validated = true;
|
||||||
role.SiteId = PageState.Page.SiteId;
|
var interop = new Interop(JSRuntime);
|
||||||
role.Name = _name;
|
if (await interop.FormValid(form))
|
||||||
role.Description = _description;
|
|
||||||
role.IsAutoAssigned = (_isautoassigned == null ? false : Boolean.Parse(_isautoassigned));
|
|
||||||
role.IsSystem = false;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
role = await RoleService.AddRoleAsync(role);
|
var role = new Role();
|
||||||
await logger.LogInformation("Role Added {Role}", role);
|
role.SiteId = PageState.Page.SiteId;
|
||||||
|
role.Name = _name;
|
||||||
|
role.Description = _description;
|
||||||
|
role.IsAutoAssigned = (_isautoassigned == null ? false : Boolean.Parse(_isautoassigned));
|
||||||
|
role.IsSystem = false;
|
||||||
|
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
try
|
||||||
|
{
|
||||||
|
role = await RoleService.AddRoleAsync(role);
|
||||||
|
await logger.LogInformation("Role Added {Role}", role);
|
||||||
|
|
||||||
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Adding Role {Role} {Error}", role, ex.Message);
|
||||||
|
AddModuleMessage(Localizer["Error Adding Role"], MessageType.Error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
else
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Adding Role {Role} {Error}", role, ex.Message);
|
AddModuleMessage(Localizer["Please Provide All Required Information"], MessageType.Warning);
|
||||||
AddModuleMessage(Localizer["Error Adding Role"], MessageType.Error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,43 +4,54 @@
|
|||||||
@inject IRoleService RoleService
|
@inject IRoleService RoleService
|
||||||
@inject IStringLocalizer<Edit> Localizer
|
@inject IStringLocalizer<Edit> Localizer
|
||||||
|
|
||||||
<table class="table table-borderless">
|
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||||
<tr>
|
<table class="table table-borderless">
|
||||||
<td>
|
<tr>
|
||||||
<Label For="name" HelpText="Name Of The Role" ResourceKey="Name">Name:</Label>
|
<td>
|
||||||
</td>
|
<Label For="name" HelpText="Name Of The Role" ResourceKey="Name">Name:</Label>
|
||||||
<td>
|
</td>
|
||||||
<input id="name" class="form-control" @bind="@_name" />
|
<td>
|
||||||
</td>
|
<input id="name" class="form-control" @bind="@_name" required />
|
||||||
</tr>
|
</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td>
|
<tr>
|
||||||
<Label For="description" HelpText="A Short Description Of The Role Which Describes Its Purpose" ResourceKey="Description">Description:</Label>
|
<td>
|
||||||
</td>
|
<Label For="description" HelpText="A Short Description Of The Role Which Describes Its Purpose" ResourceKey="Description">Description:</Label>
|
||||||
<td>
|
</td>
|
||||||
<textarea id="description" class="form-control" @bind="@_description" rows="5"></textarea>
|
<td>
|
||||||
</td>
|
<textarea id="description" class="form-control" @bind="@_description" rows="5" required></textarea>
|
||||||
</tr>
|
</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td>
|
<tr>
|
||||||
<Label For="isautoassigned" HelpText="Indicates Whether Or Not New Users Are Automatically Assigned To This Role" ResourceKey="AutoAssigned">Auto Assigned?</Label>
|
<td>
|
||||||
</td>
|
<Label For="isautoassigned" HelpText="Indicates Whether Or Not New Users Are Automatically Assigned To This Role" ResourceKey="AutoAssigned">Auto Assigned?</Label>
|
||||||
<td>
|
</td>
|
||||||
<select id="isautoassigned" class="form-control" @bind="@_isautoassigned">
|
<td>
|
||||||
<option value="True">@Localizer["Yes"]</option>
|
<select id="isautoassigned" class="form-control" @bind="@_isautoassigned">
|
||||||
<option value="False">@Localizer["No"]</option>
|
<option value="True">@Localizer["Yes"]</option>
|
||||||
</select>
|
<option value="False">@Localizer["No"]</option>
|
||||||
</td>
|
</select>
|
||||||
</tr>
|
</td>
|
||||||
</table>
|
</tr>
|
||||||
<button type="button" class="btn btn-success" @onclick="SaveRole">@Localizer["Save"]</button>
|
</table>
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
<button type="button" class="btn btn-success" @onclick="SaveRole">@Localizer["Save"]</button>
|
||||||
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
||||||
|
<br /><br />
|
||||||
|
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
|
||||||
|
</form>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
private ElementReference form;
|
||||||
|
private bool validated = false;
|
||||||
|
|
||||||
private int _roleid;
|
private int _roleid;
|
||||||
private string _name = string.Empty;
|
private string _name = string.Empty;
|
||||||
private string _description = string.Empty;
|
private string _description = string.Empty;
|
||||||
private string _isautoassigned = "False";
|
private string _isautoassigned = "False";
|
||||||
|
private string _createdby;
|
||||||
|
private DateTime _createdon;
|
||||||
|
private string _modifiedby;
|
||||||
|
private DateTime _modifiedon;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
|
|
||||||
@ -55,6 +66,10 @@
|
|||||||
_name = role.Name;
|
_name = role.Name;
|
||||||
_description = role.Description;
|
_description = role.Description;
|
||||||
_isautoassigned = role.IsAutoAssigned.ToString();
|
_isautoassigned = role.IsAutoAssigned.ToString();
|
||||||
|
_createdby = role.CreatedBy;
|
||||||
|
_createdon = role.CreatedOn;
|
||||||
|
_modifiedby = role.ModifiedBy;
|
||||||
|
_modifiedon = role.ModifiedOn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -66,22 +81,31 @@
|
|||||||
|
|
||||||
private async Task SaveRole()
|
private async Task SaveRole()
|
||||||
{
|
{
|
||||||
var role = await RoleService.GetRoleAsync(_roleid);
|
validated = true;
|
||||||
role.Name = _name;
|
var interop = new Interop(JSRuntime);
|
||||||
role.Description = _description;
|
if (await interop.FormValid(form))
|
||||||
role.IsAutoAssigned = (_isautoassigned != null && Boolean.Parse(_isautoassigned));
|
{
|
||||||
role.IsSystem = false;
|
var role = await RoleService.GetRoleAsync(_roleid);
|
||||||
|
role.Name = _name;
|
||||||
|
role.Description = _description;
|
||||||
|
role.IsAutoAssigned = (_isautoassigned != null && Boolean.Parse(_isautoassigned));
|
||||||
|
role.IsSystem = false;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
role = await RoleService.UpdateRoleAsync(role);
|
role = await RoleService.UpdateRoleAsync(role);
|
||||||
await logger.LogInformation("Role Saved {Role}", role);
|
await logger.LogInformation("Role Saved {Role}", role);
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Saving Role {Role} {Error}", role, ex.Message);
|
||||||
|
AddModuleMessage(Localizer["Error Saving Role"], MessageType.Error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
else
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Saving Role {Role} {Error}", role, ex.Message);
|
AddModuleMessage(Localizer["Please Provide All Required Information"], MessageType.Warning);
|
||||||
AddModuleMessage(Localizer["Error Saving Role"], MessageType.Error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ else
|
|||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
_roles = await RoleService.GetRolesAsync(PageState.Site.SiteId);
|
await GetRoles();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DeleteRole(Role role)
|
private async Task DeleteRole(Role role)
|
||||||
@ -43,6 +43,7 @@ else
|
|||||||
{
|
{
|
||||||
await RoleService.DeleteRoleAsync(role.RoleId);
|
await RoleService.DeleteRoleAsync(role.RoleId);
|
||||||
await logger.LogInformation("Role Deleted {Role}", role);
|
await logger.LogInformation("Role Deleted {Role}", role);
|
||||||
|
await GetRoles();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -51,4 +52,17 @@ else
|
|||||||
AddModuleMessage(Localizer["Error Deleting Role"], MessageType.Error);
|
AddModuleMessage(Localizer["Error Deleting Role"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task GetRoles()
|
||||||
|
{
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
|
{
|
||||||
|
_roles = await RoleService.GetRolesAsync(PageState.Site.SiteId, true);
|
||||||
|
_roles = _roles.Where(item => item.Name != RoleNames.Everyone).ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_roles = await RoleService.GetRolesAsync(PageState.Site.SiteId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,12 +58,16 @@ else
|
|||||||
<Pager Items="@userroles">
|
<Pager Items="@userroles">
|
||||||
<Header>
|
<Header>
|
||||||
<th>@Localizer["Users"]</th>
|
<th>@Localizer["Users"]</th>
|
||||||
|
<th>@Localizer["Effective"]</th>
|
||||||
|
<th>@Localizer["Expiry"]</th>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td>@context.User.DisplayName</td>
|
<td>@context.User.DisplayName</td>
|
||||||
|
<td>@context.EffectiveDate</td>
|
||||||
|
<td>@context.ExpiryDate</td>
|
||||||
<td>
|
<td>
|
||||||
<button type="button" class="btn btn-danger" @onclick=@(async () => await DeleteUserRole(context.UserRoleId))>@Localizer["Delete"]</button>
|
<ActionDialog Header="Remove User" Message="@Localizer["Are You Sure You Wish To Remove {0} From This Role?", context.User.DisplayName]" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@(context.Role.IsAutoAssigned)" ResourceKey="DeleteUserRole" />
|
||||||
</td>
|
</td>
|
||||||
</Row>
|
</Row>
|
||||||
</Pager>
|
</Pager>
|
||||||
@ -140,9 +144,10 @@ else
|
|||||||
await UserRoleService.AddUserRoleAsync(userrole);
|
await UserRoleService.AddUserRoleAsync(userrole);
|
||||||
}
|
}
|
||||||
|
|
||||||
await GetUserRoles();
|
|
||||||
await logger.LogInformation("User Assigned To Role {UserRole}", userrole);
|
await logger.LogInformation("User Assigned To Role {UserRole}", userrole);
|
||||||
AddModuleMessage(Localizer["User Assigned To Role"], MessageType.Success);
|
AddModuleMessage(Localizer["User Assigned To Role"], MessageType.Success);
|
||||||
|
await GetUserRoles();
|
||||||
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -161,9 +166,10 @@ else
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await UserRoleService.DeleteUserRoleAsync(UserRoleId);
|
await UserRoleService.DeleteUserRoleAsync(UserRoleId);
|
||||||
await GetUserRoles();
|
|
||||||
await logger.LogInformation("User Removed From Role {UserRoleId}", UserRoleId);
|
await logger.LogInformation("User Removed From Role {UserRoleId}", UserRoleId);
|
||||||
AddModuleMessage(Localizer["User Removed From Role"], MessageType.Success);
|
AddModuleMessage(Localizer["User Removed From Role"], MessageType.Success);
|
||||||
|
await GetUserRoles();
|
||||||
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject ISiteService SiteService
|
@inject ISiteService SiteService
|
||||||
@inject ITenantService TenantService
|
@inject ITenantService TenantService
|
||||||
|
@inject IDatabaseService DatabaseService
|
||||||
@inject IAliasService AliasService
|
@inject IAliasService AliasService
|
||||||
@inject IThemeService ThemeService
|
@inject IThemeService ThemeService
|
||||||
@inject ISettingService SettingService
|
@inject ISettingService SettingService
|
||||||
@ -22,20 +23,20 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="tenant" HelpText="Enter the tenant for the site" ResourceKey="Tenant">Tenant: </Label>
|
<Label For="alias" HelpText="The aliases for the site. An alias can be a domain name (www.site.com) or a virtual folder (ie. www.site.com/folder). If a site has multiple aliases they should be separated by commas." ResourceKey="Aliases">Aliases: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input id="tenant" class="form-control" @bind="@_tenant" readonly />
|
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
</td>
|
{
|
||||||
</tr>
|
<textarea id="alias" class="form-control" @bind="@_urls" rows="3"></textarea>
|
||||||
<tr>
|
}
|
||||||
<td>
|
else
|
||||||
<Label For="alias" HelpText="Enter the alias for the server" ResourceKey="Aliases">Aliases: </Label>
|
{
|
||||||
</td>
|
<textarea id="alias" class="form-control" @bind="@_urls" rows="3" readonly></textarea>
|
||||||
<td>
|
}
|
||||||
<textarea id="alias" class="form-control" @bind="@_urls" rows="3"></textarea>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="allowRegister" HelpText="Do you want the users to be able to register for an account on the site" ResourceKey="AllowRegistration">Allow User Registration? </Label>
|
<Label For="allowRegister" HelpText="Do you want the users to be able to register for an account on the site" ResourceKey="AllowRegistration">Allow User Registration? </Label>
|
||||||
@ -60,67 +61,67 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<Section Name="Appearance" Heading="Appearance" ResourceKey="Appearance">
|
<Section Name="Appearance" Heading="Appearance" ResourceKey="Appearance">
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="logo" HelpText="Specify a logo for the site" ResourceKey="Logo">Logo: </Label>
|
<Label For="logo" HelpText="Specify a logo for the site" ResourceKey="Logo">Logo: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<FileManager FileId="@_logofileid" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
|
<FileManager FileId="@_logofileid" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="favicon" HelpText="Specify a Favicon" ResourceKey="FavoriteIcon">Favicon: </Label>
|
<Label For="favicon" HelpText="Specify a Favicon" ResourceKey="FavoriteIcon">Favicon: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<FileManager FileId="@_faviconfileid" Filter="ico" @ref="_faviconfilemanager" />
|
<FileManager FileId="@_faviconfileid" Filter="ico" @ref="_faviconfilemanager" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="defaultTheme" HelpText="Select the sites default theme" ResourceKey="DefaultTheme">Default Theme: </Label>
|
<Label For="defaultTheme" HelpText="Select the sites default theme" ResourceKey="DefaultTheme">Default Theme: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="defaultTheme" class="form-control" value="@_themetype" @onchange="(e => ThemeChanged(e))">
|
<select id="defaultTheme" class="form-control" value="@_themetype" @onchange="(e => ThemeChanged(e))">
|
||||||
<option value="-"><@Localizer["Select Theme"]></option>
|
<option value="-"><@Localizer["Select Theme"]></option>
|
||||||
@foreach (var theme in _themes)
|
@foreach (var theme in _themes)
|
||||||
{
|
{
|
||||||
<option value="@theme.TypeName">@theme.Name</option>
|
<option value="@theme.TypeName">@theme.Name</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
|
<Label For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">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="-"><@Localizer["Select Container"]></option>
|
<option value="-"><@Localizer["Select Container"]></option>
|
||||||
@foreach (var container in _containers)
|
@foreach (var container in _containers)
|
||||||
{
|
{
|
||||||
<option value="@container.TypeName">@container.Name</option>
|
<option value="@container.TypeName">@container.Name</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="defaultAdminContainer" HelpText="Select the default admin container for the site" ResourceKey="DefaultAdminContainer">Default Admin Container: </Label>
|
<Label For="defaultAdminContainer" HelpText="Select the default admin container for the site" ResourceKey="DefaultAdminContainer">Default Admin Container: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="defaultAdminContainer" class="form-control" @bind="@_admincontainertype">
|
<select id="defaultAdminContainer" class="form-control" @bind="@_admincontainertype">
|
||||||
<option value="-"><@Localizer["Select Container"]></option>
|
<option value="-"><@Localizer["Select Container"]></option>
|
||||||
<option value=""><@Localizer["Default Admin Container"]></option>
|
<option value="@Constants.DefaultAdminContainer"><@Localizer["Default Admin Container"]></option>
|
||||||
@foreach (var container in _containers)
|
@foreach (var container in _containers)
|
||||||
{
|
{
|
||||||
<option value="@container.TypeName">@container.Name</option>
|
<option value="@container.TypeName">@container.Name</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</Section>
|
</Section>
|
||||||
<Section Name="SMTP" Heading="SMTP Settings" ResourceKey="SMTPSettings">
|
<Section Name="SMTP" Heading="SMTP Settings" ResourceKey="SMTPSettings">
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
@ -215,9 +216,40 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</Section>
|
</Section>
|
||||||
|
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
|
{
|
||||||
|
<Section Name="TenantInformation" Heading="Tenant Information" ResourceKey="TenantInformation">
|
||||||
|
<table class="table table-borderless">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="tenant" HelpText="The tenant for the site" ResourceKey="Tenant">Tenant: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="tenant" class="form-control" @bind="@_tenant" readonly />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="database" HelpText="The database for the tenant" ResourceKey="Database">Database: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="database" class="form-control" @bind="@_database" readonly />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="connectionstring" HelpText="The connection information for the database" ResourceKey="ConnectionString">Connection: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<textarea id="connectionstring" class="form-control" @bind="@_connectionstring" rows="2" readonly></textarea>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</Section>
|
||||||
|
}
|
||||||
<br />
|
<br />
|
||||||
<button type="button" class="btn btn-success" @onclick="SaveSite">@Localizer["Save"]</button>
|
<button type="button" class="btn btn-success" @onclick="SaveSite">@Localizer["Save"]</button>
|
||||||
|
<ActionDialog Header="Delete Site" Message="@Localizer["Are You Sure You Wish To Delete This Site?"]" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteSite())" ResourceKey="DeleteSite" />
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
|
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
|
||||||
@ -229,8 +261,6 @@
|
|||||||
private List<ThemeControl> _themes = new List<ThemeControl>();
|
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||||
private List<ThemeControl> _containers = 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 string _tenant = string.Empty;
|
|
||||||
private List<Alias> _aliasList;
|
private List<Alias> _aliasList;
|
||||||
private string _urls = string.Empty;
|
private string _urls = string.Empty;
|
||||||
private int _logofileid = -1;
|
private int _logofileid = -1;
|
||||||
@ -252,6 +282,9 @@
|
|||||||
private FileManager _pwaappiconfilemanager;
|
private FileManager _pwaappiconfilemanager;
|
||||||
private int _pwasplashiconfileid = -1;
|
private int _pwasplashiconfileid = -1;
|
||||||
private FileManager _pwasplashiconfilemanager;
|
private FileManager _pwasplashiconfilemanager;
|
||||||
|
private string _tenant = string.Empty;
|
||||||
|
private string _database = string.Empty;
|
||||||
|
private string _connectionstring = string.Empty;
|
||||||
private string _createdby;
|
private string _createdby;
|
||||||
private DateTime _createdon;
|
private DateTime _createdon;
|
||||||
private string _modifiedby;
|
private string _modifiedby;
|
||||||
@ -267,17 +300,24 @@
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_themeList = await ThemeService.GetThemesAsync();
|
_themeList = await ThemeService.GetThemesAsync();
|
||||||
_aliasList = await AliasService.GetAliasesAsync();
|
|
||||||
Site site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
|
Site site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
|
||||||
if (site != null)
|
if (site != null)
|
||||||
{
|
{
|
||||||
_name = site.Name;
|
_name = site.Name;
|
||||||
_tenantList = await TenantService.GetTenantsAsync();
|
_allowregistration = site.AllowRegistration.ToString();
|
||||||
_tenant = _tenantList.Find(item => item.TenantId == site.TenantId).Name;
|
_isdeleted = site.IsDeleted.ToString();
|
||||||
foreach (Alias alias in _aliasList.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList())
|
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
{
|
{
|
||||||
_urls += alias.Name + "\n";
|
_aliasList = await AliasService.GetAliasesAsync();
|
||||||
|
foreach (Alias alias in _aliasList.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList())
|
||||||
|
{
|
||||||
|
_urls += alias.Name + ",";
|
||||||
|
}
|
||||||
|
_urls = _urls.Substring(0, _urls.Length - 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (site.LogoFileId != null)
|
if (site.LogoFileId != null)
|
||||||
{
|
{
|
||||||
_logofileid = site.LogoFileId.Value;
|
_logofileid = site.LogoFileId.Value;
|
||||||
@ -289,11 +329,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
_themes = ThemeService.GetThemeControls(_themeList);
|
_themes = ThemeService.GetThemeControls(_themeList);
|
||||||
_themetype = site.DefaultThemeType;
|
_themetype = (!string.IsNullOrEmpty(site.DefaultThemeType)) ? site.DefaultThemeType : Constants.DefaultTheme;
|
||||||
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
||||||
_containertype = site.DefaultContainerType;
|
_containertype = (!string.IsNullOrEmpty(site.DefaultContainerType)) ? site.DefaultContainerType : Constants.DefaultContainer;
|
||||||
_admincontainertype = site.AdminContainerType;
|
_admincontainertype = (!string.IsNullOrEmpty(site.AdminContainerType)) ? site.AdminContainerType : Constants.DefaultAdminContainer;
|
||||||
_allowregistration = site.AllowRegistration.ToString();
|
|
||||||
|
|
||||||
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
|
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
|
||||||
_smtphost = SettingService.GetSetting(settings, "SMTPHost", string.Empty);
|
_smtphost = SettingService.GetSetting(settings, "SMTPHost", string.Empty);
|
||||||
@ -325,13 +364,25 @@
|
|||||||
_pwasplashiconfileid = site.PwaSplashIconFileId.Value;
|
_pwasplashiconfileid = site.PwaSplashIconFileId.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
|
{
|
||||||
|
var tenants = await TenantService.GetTenantsAsync();
|
||||||
|
var _databases = await DatabaseService.GetDatabasesAsync();
|
||||||
|
var tenant = tenants.Find(item => item.TenantId == site.TenantId);
|
||||||
|
if (tenant != null)
|
||||||
|
{
|
||||||
|
_tenant = tenant.Name;
|
||||||
|
_database = _databases.Find(item => item.DBType == tenant.DBType)?.Name;
|
||||||
|
_connectionstring = tenant.DBConnectionString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_createdby = site.CreatedBy;
|
_createdby = site.CreatedBy;
|
||||||
_createdon = site.CreatedOn;
|
_createdon = site.CreatedOn;
|
||||||
_modifiedby = site.ModifiedBy;
|
_modifiedby = site.ModifiedBy;
|
||||||
_modifiedon = site.ModifiedOn;
|
_modifiedon = site.ModifiedOn;
|
||||||
_deletedby = site.DeletedBy;
|
_deletedby = site.DeletedBy;
|
||||||
_deletedon = site.DeletedOn;
|
_deletedon = site.DeletedOn;
|
||||||
_isdeleted = site.IsDeleted.ToString();
|
|
||||||
|
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
@ -357,7 +408,7 @@
|
|||||||
_containers = new List<ThemeControl>();
|
_containers = new List<ThemeControl>();
|
||||||
}
|
}
|
||||||
_containertype = "-";
|
_containertype = "-";
|
||||||
_admincontainertype = "";
|
_admincontainertype = Constants.DefaultAdminContainer;
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -374,11 +425,14 @@
|
|||||||
if (_name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-")
|
if (_name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-")
|
||||||
{
|
{
|
||||||
var unique = true;
|
var unique = true;
|
||||||
foreach (string name in _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
{
|
{
|
||||||
if (_aliasList.Exists(item => item.Name == name && item.SiteId != PageState.Alias.SiteId && item.TenantId != PageState.Alias.TenantId))
|
foreach (string name in _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
{
|
{
|
||||||
unique = false;
|
if (_aliasList.Exists(item => item.Name == name && item.SiteId != PageState.Alias.SiteId && item.TenantId != PageState.Alias.TenantId))
|
||||||
|
{
|
||||||
|
unique = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,35 +441,33 @@
|
|||||||
var site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
|
var site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
|
||||||
if (site != null)
|
if (site != null)
|
||||||
{
|
{
|
||||||
|
bool refresh = (site.DefaultThemeType != _themetype || site.DefaultContainerType != _containertype);
|
||||||
|
|
||||||
site.Name = _name;
|
site.Name = _name;
|
||||||
|
site.AllowRegistration = (_allowregistration == null ? true : Boolean.Parse(_allowregistration));
|
||||||
|
site.IsDeleted = (_isdeleted == null ? true : Boolean.Parse(_isdeleted));
|
||||||
|
|
||||||
site.LogoFileId = null;
|
site.LogoFileId = null;
|
||||||
var logofileid = _logofilemanager.GetFileId();
|
var logofileid = _logofilemanager.GetFileId();
|
||||||
if (logofileid != -1)
|
if (logofileid != -1)
|
||||||
{
|
{
|
||||||
site.LogoFileId = logofileid;
|
site.LogoFileId = logofileid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var faviconFieldId = _faviconfilemanager.GetFileId();
|
var faviconFieldId = _faviconfilemanager.GetFileId();
|
||||||
if (faviconFieldId != -1)
|
if (faviconFieldId != -1)
|
||||||
{
|
{
|
||||||
site.FaviconFileId = faviconFieldId;
|
site.FaviconFileId = faviconFieldId;
|
||||||
}
|
}
|
||||||
|
|
||||||
site.DefaultThemeType = _themetype;
|
site.DefaultThemeType = _themetype;
|
||||||
site.DefaultContainerType = _containertype;
|
site.DefaultContainerType = _containertype;
|
||||||
site.AdminContainerType = _admincontainertype;
|
site.AdminContainerType = _admincontainertype;
|
||||||
site.AllowRegistration = (_allowregistration == null ? true : Boolean.Parse(_allowregistration));
|
|
||||||
site.IsDeleted = (_isdeleted == null ? true : Boolean.Parse(_isdeleted));
|
|
||||||
|
|
||||||
site.PwaIsEnabled = (_pwaisenabled == null ? true : Boolean.Parse(_pwaisenabled));
|
site.PwaIsEnabled = (_pwaisenabled == null ? true : Boolean.Parse(_pwaisenabled));
|
||||||
|
|
||||||
var pwaappiconfileid = _pwaappiconfilemanager.GetFileId();
|
var pwaappiconfileid = _pwaappiconfilemanager.GetFileId();
|
||||||
if (pwaappiconfileid != -1)
|
if (pwaappiconfileid != -1)
|
||||||
{
|
{
|
||||||
site.PwaAppIconFileId = pwaappiconfileid;
|
site.PwaAppIconFileId = pwaappiconfileid;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pwasplashiconfileid = _pwasplashiconfilemanager.GetFileId();
|
var pwasplashiconfileid = _pwasplashiconfilemanager.GetFileId();
|
||||||
if (pwasplashiconfileid != -1)
|
if (pwasplashiconfileid != -1)
|
||||||
{
|
{
|
||||||
@ -424,28 +476,6 @@
|
|||||||
|
|
||||||
site = await SiteService.UpdateSiteAsync(site);
|
site = await SiteService.UpdateSiteAsync(site);
|
||||||
|
|
||||||
_urls = _urls.Replace("\n", ",");
|
|
||||||
var names = _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
foreach (Alias alias in _aliasList.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList())
|
|
||||||
{
|
|
||||||
if (!names.Contains(alias.Name))
|
|
||||||
{
|
|
||||||
await AliasService.DeleteAliasAsync(alias.AliasId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (string name in names)
|
|
||||||
{
|
|
||||||
if (!_aliasList.Exists(item => item.Name == name))
|
|
||||||
{
|
|
||||||
Alias alias = new Alias();
|
|
||||||
alias.Name = name;
|
|
||||||
alias.TenantId = site.TenantId;
|
|
||||||
alias.SiteId = site.SiteId;
|
|
||||||
await AliasService.AddAliasAsync(alias);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
|
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
|
||||||
SettingService.SetSetting(settings, "SMTPHost", _smtphost);
|
SettingService.SetSetting(settings, "SMTPHost", _smtphost);
|
||||||
SettingService.SetSetting(settings, "SMTPPort", _smtpport);
|
SettingService.SetSetting(settings, "SMTPPort", _smtpport);
|
||||||
@ -455,8 +485,40 @@
|
|||||||
SettingService.SetSetting(settings, "SMTPSender", _smtpsender);
|
SettingService.SetSetting(settings, "SMTPSender", _smtpsender);
|
||||||
await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId);
|
await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId);
|
||||||
|
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
|
{
|
||||||
|
var names = _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
foreach (Alias alias in _aliasList.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList())
|
||||||
|
{
|
||||||
|
if (!names.Contains(alias.Name))
|
||||||
|
{
|
||||||
|
await AliasService.DeleteAliasAsync(alias.AliasId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string name in names)
|
||||||
|
{
|
||||||
|
if (!_aliasList.Exists(item => item.Name == name))
|
||||||
|
{
|
||||||
|
Alias alias = new Alias();
|
||||||
|
alias.Name = name;
|
||||||
|
alias.TenantId = site.TenantId;
|
||||||
|
alias.SiteId = site.SiteId;
|
||||||
|
await AliasService.AddAliasAsync(alias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await logger.LogInformation("Site Settings Saved {Site}", site);
|
await logger.LogInformation("Site Settings Saved {Site}", site);
|
||||||
AddModuleMessage(Localizer["Site Settings Saved"], MessageType.Success);
|
|
||||||
|
if (refresh)
|
||||||
|
{
|
||||||
|
NavigationManager.NavigateTo(NavigateUrl()); // refresh to show new theme or container
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddModuleMessage(Localizer["Site Settings Saved"], MessageType.Success);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -476,6 +538,36 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task DeleteSite()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var sites = await SiteService.GetSitesAsync();
|
||||||
|
if (sites.Count > 1)
|
||||||
|
{
|
||||||
|
await SiteService.DeleteSiteAsync(PageState.Site.SiteId);
|
||||||
|
await logger.LogInformation("Site Deleted {SiteId}", PageState.Site.SiteId);
|
||||||
|
|
||||||
|
var aliases = await AliasService.GetAliasesAsync();
|
||||||
|
foreach (Alias a in aliases.Where(item => item.SiteId == PageState.Site.SiteId && item.TenantId == PageState.Site.TenantId))
|
||||||
|
{
|
||||||
|
await AliasService.DeleteAliasAsync(a.AliasId);
|
||||||
|
}
|
||||||
|
|
||||||
|
NavigationManager.NavigateTo(NavigateUrl("admin/sites"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddModuleMessage(Localizer["You Are Not Authorized To Delete The Site"], MessageType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Deleting Site {SiteId} {Error}", PageState.Site.SiteId, ex.Message);
|
||||||
|
AddModuleMessage(Localizer["Error Deleting Site"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task SendEmail()
|
private async Task SendEmail()
|
||||||
{
|
{
|
||||||
if (_smtphost != "" && _smtpport != "" && _smtpsender != "")
|
if (_smtphost != "" && _smtpport != "" && _smtpsender != "")
|
||||||
@ -505,6 +597,5 @@
|
|||||||
{
|
{
|
||||||
AddModuleMessage(Localizer["You Must Specify The SMTP Host, Port, And Sender"], MessageType.Warning);
|
AddModuleMessage(Localizer["You Must Specify The SMTP Host, Port, And Sender"], MessageType.Warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
@inject ISiteTemplateService SiteTemplateService
|
@inject ISiteTemplateService SiteTemplateService
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@inject IInstallationService InstallationService
|
@inject IInstallationService InstallationService
|
||||||
|
@inject IDatabaseService DatabaseService
|
||||||
@inject IStringLocalizer<Add> Localizer
|
@inject IStringLocalizer<Add> Localizer
|
||||||
@inject IEnumerable<IOqtaneDatabase> Databases
|
|
||||||
|
|
||||||
@if (_tenants == null)
|
@if (_tenants == null)
|
||||||
{
|
{
|
||||||
@ -18,193 +18,164 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="name" HelpText="Enter the name of the site" ResourceKey="Name">Site Name: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<input id="name" class="form-control" @bind="@_name" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="alias" HelpText="Enter the alias for the server" ResourceKey="Aliases">Aliases: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<textarea id="alias" class="form-control" @bind="@_urls" rows="3"></textarea>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="defaultTheme" HelpText="Select the default theme for the website" ResourceKey="DefaultTheme">Default Theme: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<select id="defaultTheme" class="form-control" @onchange="(e => ThemeChanged(e))">
|
|
||||||
<option value="-"><@Localizer["Select Theme"]></option>
|
|
||||||
@foreach (var theme in _themes)
|
|
||||||
{
|
|
||||||
<option value="@theme.TypeName">@theme.Name</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<select id="defaultContainer" class="form-control" @bind="@_containertype">
|
|
||||||
<option value="-"><@Localizer["Select Container"]></option>
|
|
||||||
@foreach (var container in _containers)
|
|
||||||
{
|
|
||||||
<option value="@container.TypeName">@container.Name</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="adminContainer" HelpText="Select the admin container for the site" ResourceKey="AdminContainer">Admin Container: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<select id="adminContainer" class="form-control" @bind="@_admincontainertype">
|
|
||||||
<option value="-"><@Localizer["Select Container"]></option>
|
|
||||||
<option value=""><@Localizer["Default Admin Container"]></option>
|
|
||||||
@foreach (var container in _containers)
|
|
||||||
{
|
|
||||||
<option value="@container.TypeName">@container.Name</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="siteTemplate" HelpText="Select the site template" ResourceKey="SiteTemplate">Site Template: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<select id="siteTemplate" class="form-control" @bind="@_sitetemplatetype">
|
|
||||||
<option value="-"><@Localizer["Select Site Template"]></option>
|
|
||||||
@foreach (SiteTemplate siteTemplate in _siteTemplates)
|
|
||||||
{
|
|
||||||
<option value="@siteTemplate.TypeName">@siteTemplate.Name</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="tenant" HelpText="Select the tenant for the site" ResourceKey="Tenant">Tenant: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<select id="tenant" class="form-control" @onchange="(e => TenantChanged(e))">
|
|
||||||
<option value="-"><@Localizer["Select Tenant"]></option>
|
|
||||||
<option value="+"><@Localizer["Create New Tenant"]></option>
|
|
||||||
@foreach (Tenant tenant in _tenants)
|
|
||||||
{
|
|
||||||
<option value="@tenant.TenantId">@tenant.Name</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
@if (_tenantid == "+")
|
|
||||||
{
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td>
|
||||||
<hr class="app-rule" />
|
<Label For="name" HelpText="Enter the name of the site" ResourceKey="Name">Site Name: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="name" class="form-control" @bind="@_name" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="name" HelpText="Enter the name for the tenant" ResourceKey="TenantName">Tenant Name: </Label>
|
<Label For="alias" HelpText="Enter the aliases for the site. An alias can be a domain name (www.site.com) or a virtual folder (ie. www.site.com/folder). If a site has multiple aliases they can be separated by commas." ResourceKey="Aliases">Aliases: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input id="name" class="form-control" @bind="@_tenantName" />
|
<textarea id="alias" class="form-control" @bind="@_urls" rows="3"></textarea>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="databaseType" HelpText="Select the database type for the tenant" ResourceKey="DatabaseType">Database Type: </Label>
|
<Label For="defaultTheme" HelpText="Select the default theme for the website" ResourceKey="DefaultTheme">Default Theme: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="databaseType" class="custom-select" @bind="@_databaseType">
|
<select id="defaultTheme" class="form-control" @onchange="(e => ThemeChanged(e))">
|
||||||
@{
|
<option value="-"><@Localizer["Select Theme"]></option>
|
||||||
foreach (var database in Databases)
|
@foreach (var theme in _themes)
|
||||||
{
|
{
|
||||||
<option value="@database.Name">@Localizer[@database.FriendlyName]</option>
|
<option value="@theme.TypeName">@theme.Name</option>
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{
|
<tr>
|
||||||
_selectedDatabase = Databases.Single(d => d.Name == _databaseType);
|
<td>
|
||||||
foreach (var field in _selectedDatabase.ConnectionStringFields)
|
<Label For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
|
||||||
{
|
</td>
|
||||||
var fieldId = field.Name.ToLowerInvariant();
|
<td>
|
||||||
if (field.Name != "IntegratedSecurity")
|
<select id="defaultContainer" class="form-control" @bind="@_containertype">
|
||||||
{
|
<option value="-"><@Localizer["Select Container"]></option>
|
||||||
var isVisible = "";
|
@foreach (var container in _containers)
|
||||||
var fieldType = (field.Name == "Pwd") ? "password" : "text";
|
|
||||||
if ((field.Name == "Uid" || field.Name == "Pwd") && _selectedDatabase.Name != "MySQL" )
|
|
||||||
{
|
{
|
||||||
var intSecurityField = _selectedDatabase.ConnectionStringFields.Single(f => f.Name == "IntegratedSecurity");
|
<option value="@container.TypeName">@container.Name</option>
|
||||||
if (intSecurityField != null)
|
|
||||||
{
|
|
||||||
isVisible = (Convert.ToBoolean(intSecurityField.Value)) ? "display: none;" : "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
</select>
|
||||||
field.Value = field.Value.Replace("{{Date}}", DateTime.UtcNow.ToString("yyyyMMddHHmm"));
|
</td>
|
||||||
|
</tr>
|
||||||
<tr style="@isVisible">
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="@fieldId" HelpText="@field.HelpText" ResourceKey="@field.Name">@Localizer[$"{field.FriendlyName}:"]</Label>
|
<Label For="adminContainer" HelpText="Select the admin container for the site" ResourceKey="AdminContainer">Admin Container: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input id="@fieldId" type="@fieldType" class="form-control" @bind="@field.Value" />
|
<select id="adminContainer" class="form-control" @bind="@_admincontainertype">
|
||||||
</td>
|
<option value="-"><@Localizer["Select Container"]></option>
|
||||||
</tr>
|
<option value=""><@Localizer["Default Admin Container"]></option>
|
||||||
}
|
@foreach (var container in _containers)
|
||||||
else
|
{
|
||||||
{
|
<option value="@container.TypeName">@container.Name</option>
|
||||||
<tr>
|
}
|
||||||
<td>
|
</select>
|
||||||
<Label For="@fieldId" HelpText="@field.HelpText" ResourceKey="@field.Name">@Localizer[$"{field.FriendlyName}:"]</Label>
|
</td>
|
||||||
</td>
|
</tr>
|
||||||
<td>
|
<tr>
|
||||||
<select id="@fieldId" class="custom-select" @bind="@field.Value">
|
<td>
|
||||||
<option value="true" selected>@Localizer["True"]</option>
|
<Label For="siteTemplate" HelpText="Select the site template" ResourceKey="SiteTemplate">Site Template: </Label>
|
||||||
<option value="false">@Localizer["False"]</option>
|
</td>
|
||||||
</select>
|
<td>
|
||||||
</td>
|
<select id="siteTemplate" class="form-control" @bind="@_sitetemplatetype">
|
||||||
</tr>
|
<option value="-"><@Localizer["Select Site Template"]></option>
|
||||||
}
|
@foreach (SiteTemplate siteTemplate in _siteTemplates)
|
||||||
|
{
|
||||||
|
<option value="@siteTemplate.TypeName">@siteTemplate.Name</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="tenant" HelpText="Select the tenant for the site" ResourceKey="Tenant">Tenant: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select id="tenant" class="form-control" @onchange="(e => TenantChanged(e))">
|
||||||
|
<option value="-"><@Localizer["Select Tenant"]></option>
|
||||||
|
<option value="+"><@Localizer["Create New Tenant"]></option>
|
||||||
|
@foreach (Tenant tenant in _tenants)
|
||||||
|
{
|
||||||
|
<option value="@tenant.TenantId">@tenant.Name</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@if (_tenantid == "+")
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<hr class="app-rule" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="name" HelpText="Enter the name for the tenant" ResourceKey="TenantName">Tenant Name: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="name" class="form-control" @bind="@_tenantName" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="databaseType" HelpText="Select the database type for the tenant" ResourceKey="DatabaseType">Database Type: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select id="databaseType" class="custom-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))">
|
||||||
|
@foreach (var database in _databases)
|
||||||
|
{
|
||||||
|
if (database.IsDefault)
|
||||||
|
{
|
||||||
|
<option value="@database.Name" selected>@Localizer[@database.Name]</option>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<option value="@database.Name">@Localizer[@database.Name]</option>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
if (_databaseConfigType != null)
|
||||||
|
{
|
||||||
|
@DatabaseConfigComponent;
|
||||||
}
|
}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="hostUsername" HelpText="Enter the username of the host for this site" ResourceKey="HostUsername">Host Username:</Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="hostUsername" class="form-control" @bind="@_hostUserName" readonly />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="hostPassword" HelpText="Enter the password for the host of this site" ResourceKey="HostPassword">Host Password:</Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="hostPassword" type="password" class="form-control" @bind="@_hostpassword" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
}
|
}
|
||||||
<tr>
|
</table>
|
||||||
<td>
|
|
||||||
<Label For="hostUsername" HelpText="Enter the username of the host for this site" ResourceKey="HostUsername">Host Username:</Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<input id="hostUsername" class="form-control" @bind="@_hostUserName" readonly />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="hostPassword" HelpText="Enter the password for the host of this site" ResourceKey="HostPassword">Host Password:</Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<input id="hostPassword" type="password" class="form-control" @bind="@_hostpassword" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</table>
|
|
||||||
<button type="button" class="btn btn-success" @onclick="SaveSite">@Localizer["Save"]</button>
|
<button type="button" class="btn btn-success" @onclick="SaveSite">@Localizer["Save"]</button>
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
private List<Database> _databases;
|
||||||
|
private string _databaseName = "LocalDB";
|
||||||
|
private Type _databaseConfigType;
|
||||||
|
private object _databaseConfig;
|
||||||
|
private RenderFragment DatabaseConfigComponent { get; set; }
|
||||||
|
|
||||||
|
|
||||||
private List<Theme> _themeList;
|
private List<Theme> _themeList;
|
||||||
private List<ThemeControl> _themes = new List<ThemeControl>();
|
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
@ -213,8 +184,6 @@ else
|
|||||||
private string _tenantid = "-";
|
private string _tenantid = "-";
|
||||||
|
|
||||||
private string _tenantName = string.Empty;
|
private string _tenantName = string.Empty;
|
||||||
private IOqtaneDatabase _selectedDatabase;
|
|
||||||
private string _databaseType = "LocalDB";
|
|
||||||
|
|
||||||
private string _hostUserName = UserNames.Host;
|
private string _hostUserName = UserNames.Host;
|
||||||
private string _hostpassword = string.Empty;
|
private string _hostpassword = string.Empty;
|
||||||
@ -235,6 +204,37 @@ else
|
|||||||
_themeList = await ThemeService.GetThemesAsync();
|
_themeList = await ThemeService.GetThemesAsync();
|
||||||
_themes = ThemeService.GetThemeControls(_themeList);
|
_themes = ThemeService.GetThemeControls(_themeList);
|
||||||
_siteTemplates = await SiteTemplateService.GetSiteTemplatesAsync();
|
_siteTemplates = await SiteTemplateService.GetSiteTemplatesAsync();
|
||||||
|
_databases = await DatabaseService.GetDatabasesAsync();
|
||||||
|
LoadDatabaseConfigComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DatabaseChanged(ChangeEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_databaseName = (string)eventArgs.Value;
|
||||||
|
|
||||||
|
LoadDatabaseConfigComponent();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
AddModuleMessage(Localizer["Error loading Database Configuration Control"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadDatabaseConfigComponent()
|
||||||
|
{
|
||||||
|
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
||||||
|
if (database != null)
|
||||||
|
{
|
||||||
|
_databaseConfigType = Type.GetType(database.ControlType);
|
||||||
|
DatabaseConfigComponent = builder =>
|
||||||
|
{
|
||||||
|
builder.OpenComponent(0, _databaseConfigType);
|
||||||
|
builder.AddComponentReferenceCapture(1, inst => { _databaseConfig = Convert.ChangeType(inst, _databaseConfigType); });
|
||||||
|
builder.CloseComponent();
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TenantChanged(ChangeEventArgs e)
|
private void TenantChanged(ChangeEventArgs e)
|
||||||
@ -301,15 +301,21 @@ else
|
|||||||
user = await UserService.LoginUserAsync(user, false, false);
|
user = await UserService.LoginUserAsync(user, false, false);
|
||||||
if (user.IsAuthenticated)
|
if (user.IsAuthenticated)
|
||||||
{
|
{
|
||||||
var connectionString = _selectedDatabase.BuildConnectionString();
|
var connectionString = String.Empty;
|
||||||
|
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
||||||
|
{
|
||||||
|
connectionString = databaseConfigControl.GetConnectionString();
|
||||||
|
}
|
||||||
|
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
||||||
|
|
||||||
if (connectionString != "")
|
if (connectionString != "")
|
||||||
{
|
{
|
||||||
config.DatabaseType = _databaseType;
|
|
||||||
config.ConnectionString = connectionString;
|
|
||||||
config.HostPassword = _hostpassword;
|
|
||||||
config.HostEmail = user.Email;
|
|
||||||
config.HostName = user.DisplayName;
|
|
||||||
config.TenantName = _tenantName;
|
config.TenantName = _tenantName;
|
||||||
|
config.DatabaseType = database.DBType;
|
||||||
|
config.ConnectionString = connectionString;
|
||||||
|
config.HostEmail = user.Email;
|
||||||
|
config.HostPassword = _hostpassword;
|
||||||
|
config.HostName = user.DisplayName;
|
||||||
config.IsNewTenant = true;
|
config.IsNewTenant = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -333,15 +339,16 @@ else
|
|||||||
if (tenant != null)
|
if (tenant != null)
|
||||||
{
|
{
|
||||||
config.TenantName = tenant.Name;
|
config.TenantName = tenant.Name;
|
||||||
config.ConnectionString= tenant.DBConnectionString;
|
config.DatabaseType = tenant.DBType;
|
||||||
|
config.ConnectionString = tenant.DBConnectionString;
|
||||||
config.IsNewTenant = false;
|
config.IsNewTenant = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(config.TenantName))
|
if (!string.IsNullOrEmpty(config.TenantName))
|
||||||
{
|
{
|
||||||
config.SiteName = _name;
|
config.SiteName = _name;
|
||||||
config.Aliases = _urls.Replace("\n", ",");
|
config.Aliases = _urls;
|
||||||
config.DefaultTheme = _themetype;
|
config.DefaultTheme = _themetype;
|
||||||
config.DefaultContainer = _containertype;
|
config.DefaultContainer = _containertype;
|
||||||
config.DefaultAdminContainer = _admincontainertype;
|
config.DefaultAdminContainer = _admincontainertype;
|
||||||
|
@ -1,283 +0,0 @@
|
|||||||
@namespace Oqtane.Modules.Admin.Sites
|
|
||||||
@inherits ModuleBase
|
|
||||||
@inject NavigationManager NavigationManager
|
|
||||||
@inject ISiteService SiteService
|
|
||||||
@inject ITenantService TenantService
|
|
||||||
@inject IAliasService AliasService
|
|
||||||
@inject IThemeService ThemeService
|
|
||||||
@inject IStringLocalizer<Edit> Localizer
|
|
||||||
|
|
||||||
@if (_initialized)
|
|
||||||
{
|
|
||||||
<table class="table table-borderless">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="name" HelpText="Enter the name of the site" ResourceKey="Name">Name: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<input id="name" class="form-control" @bind="@_name" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="alias" HelpText="Enter the alias for the server" ResourceKey="Aliases">Aliases: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<textarea id="alias" class="form-control" @bind="@_urls" rows="3" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="defaultTheme" HelpText="Select the default theme for the website" ResourceKey="DefaultTheme">Default Theme: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<select id="defaultTheme" class="form-control" value="@_themetype" @onchange="(e => ThemeChanged(e))">
|
|
||||||
<option value="-"><@Localizer["Select Theme"]></option>
|
|
||||||
@foreach (var theme in _themes)
|
|
||||||
{
|
|
||||||
<option value="@theme.TypeName">@theme.Name</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<select id="defaultIdea" class="form-control" @bind="@_containertype">
|
|
||||||
<option value="-"><@Localizer["Select Container"]></option>
|
|
||||||
@foreach (var container in _containers)
|
|
||||||
{
|
|
||||||
<option value="@container.TypeName">@container.Name</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="defaultAdminContainer" HelpText="Select the default admin container for the site" ResourceKey="DefaultAdminContainer">Default Admin Container: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<select id="defaultAdminContainer" class="form-control" @bind="@_admincontainertype">
|
|
||||||
<option value="-"><@Localizer["Select Container"]></option>
|
|
||||||
<option value=""><@Localizer["Default Admin Container"]></option>
|
|
||||||
@foreach (var container in _containers)
|
|
||||||
{
|
|
||||||
<option value="@container.TypeName">@container.Name</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="isDeleted" HelpText="Has this site been deleted?" ResourceKey="IsDeleted">Is Deleted? </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<select id="isDeleted" class="form-control" @bind="@_isdeleted">
|
|
||||||
<option value="True">@Localizer["Yes"]</option>
|
|
||||||
<option value="False">@Localizer["No"]</option>
|
|
||||||
</select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="tenant" HelpText="The tenant for the site" ResourceKey="Tenant">Tenant: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<input id="tenant" class="form-control" @bind="@_tenant" readonly />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="connectionstring" HelpText="The database connection string" ResourceKey="ConnectionString">Connection String: </Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<textarea id="connectionstring" class="form-control" @bind="@_connectionstring" rows="3" readonly></textarea>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<br />
|
|
||||||
<button type="button" class="btn btn-success" @onclick="SaveSite">@Localizer["Save"]</button>
|
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
|
|
||||||
}
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private bool _initialized = false;
|
|
||||||
private List<Theme> _themeList;
|
|
||||||
private List<ThemeControl> _themes = new List<ThemeControl>();
|
|
||||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
|
||||||
private Alias _alias;
|
|
||||||
private string _name = string.Empty;
|
|
||||||
private List<Alias> _aliasList;
|
|
||||||
private string _urls = string.Empty;
|
|
||||||
private string _themetype;
|
|
||||||
private string _containertype = "-";
|
|
||||||
private string _admincontainertype = "-";
|
|
||||||
private string _createdby;
|
|
||||||
private DateTime _createdon;
|
|
||||||
private string _modifiedby;
|
|
||||||
private DateTime _modifiedon;
|
|
||||||
private string _deletedby;
|
|
||||||
private DateTime? _deletedon;
|
|
||||||
private string _isdeleted;
|
|
||||||
private string _tenant = string.Empty;
|
|
||||||
private string _connectionstring = string.Empty;
|
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_themeList = await ThemeService.GetThemesAsync();
|
|
||||||
_aliasList = await AliasService.GetAliasesAsync();
|
|
||||||
|
|
||||||
_alias = _aliasList.Find(item => item.AliasId == Int32.Parse(PageState.QueryString["id"]));
|
|
||||||
SiteService.SetAlias(_alias);
|
|
||||||
var site = await SiteService.GetSiteAsync(_alias.SiteId);
|
|
||||||
if (site != null)
|
|
||||||
{
|
|
||||||
_name = site.Name;
|
|
||||||
|
|
||||||
foreach (Alias alias in _aliasList.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList())
|
|
||||||
{
|
|
||||||
_urls += alias.Name + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
_themes = ThemeService.GetThemeControls(_themeList);
|
|
||||||
_themetype = site.DefaultThemeType;
|
|
||||||
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
|
||||||
_containertype = site.DefaultContainerType;
|
|
||||||
_admincontainertype = site.AdminContainerType;
|
|
||||||
_createdby = site.CreatedBy;
|
|
||||||
_createdon = site.CreatedOn;
|
|
||||||
_modifiedby = site.ModifiedBy;
|
|
||||||
_modifiedon = site.ModifiedOn;
|
|
||||||
_deletedby = site.DeletedBy;
|
|
||||||
_deletedon = site.DeletedOn;
|
|
||||||
_isdeleted = site.IsDeleted.ToString();
|
|
||||||
|
|
||||||
List<Tenant> tenants = await TenantService.GetTenantsAsync();
|
|
||||||
Tenant tenant = tenants.Find(item => item.TenantId == site.TenantId);
|
|
||||||
if (tenant != null)
|
|
||||||
{
|
|
||||||
_tenant = tenant.Name;
|
|
||||||
_connectionstring = tenant.DBConnectionString;
|
|
||||||
}
|
|
||||||
|
|
||||||
_initialized = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await Log(_alias, LogLevel.Error, string.Empty, ex, "Error Loading Site {SiteId} {Error}", _alias.SiteId, ex.Message);
|
|
||||||
AddModuleMessage(ex.Message, MessageType.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void ThemeChanged(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_themetype = (string)e.Value;
|
|
||||||
if (_themetype != "-")
|
|
||||||
{
|
|
||||||
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_containers = new List<ThemeControl>();
|
|
||||||
}
|
|
||||||
_containertype = "-";
|
|
||||||
_admincontainertype = "";
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Loading Pane Layouts For Theme {ThemeType} {Error}", _themetype, ex.Message);
|
|
||||||
AddModuleMessage(Localizer["Error Loading Pane Layouts For Theme"], MessageType.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SaveSite()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-")
|
|
||||||
{
|
|
||||||
var unique = true;
|
|
||||||
foreach (string name in _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
|
||||||
{
|
|
||||||
if (_aliasList.Exists(item => item.Name == name && item.SiteId != _alias.SiteId && item.TenantId != _alias.TenantId))
|
|
||||||
{
|
|
||||||
unique = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unique)
|
|
||||||
{
|
|
||||||
SiteService.SetAlias(_alias);
|
|
||||||
var site = await SiteService.GetSiteAsync(_alias.SiteId);
|
|
||||||
if (site != null)
|
|
||||||
{
|
|
||||||
site.Name = _name;
|
|
||||||
site.LogoFileId = null;
|
|
||||||
site.DefaultThemeType = _themetype;
|
|
||||||
site.DefaultContainerType = _containertype;
|
|
||||||
site.AdminContainerType = _admincontainertype;
|
|
||||||
site.IsDeleted = (_isdeleted == null || Boolean.Parse(_isdeleted));
|
|
||||||
|
|
||||||
site = await SiteService.UpdateSiteAsync(site);
|
|
||||||
|
|
||||||
_urls = _urls.Replace("\n", ",");
|
|
||||||
var names = _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
|
|
||||||
foreach (Alias alias in _aliasList.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList())
|
|
||||||
{
|
|
||||||
if (!names.Contains(alias.Name))
|
|
||||||
{
|
|
||||||
await AliasService.DeleteAliasAsync(alias.AliasId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (string name in names)
|
|
||||||
{
|
|
||||||
if (!_aliasList.Exists(item => item.Name == name))
|
|
||||||
{
|
|
||||||
Alias alias = new Alias
|
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
TenantId = site.TenantId,
|
|
||||||
SiteId = site.SiteId
|
|
||||||
};
|
|
||||||
await AliasService.AddAliasAsync(alias);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await Log(_alias, LogLevel.Information, PermissionNames.Edit, null, "Site Saved {Site}", site);
|
|
||||||
|
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AddModuleMessage(Localizer["An Alias Specified Has Already Been Used For Another Site"], MessageType.Warning);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AddModuleMessage(Localizer["You Must Provide A Site Name, Alias, And Default Theme/Container"], MessageType.Warning);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await Log(_alias, LogLevel.Error, string.Empty, ex, "Error Saving Site {SiteId} {Error}", _alias.SiteId, ex.Message);
|
|
||||||
AddModuleMessage(Localizer["Error Saving Site"], MessageType.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,9 +20,9 @@ else
|
|||||||
<th>@Localizer["Name"]</th>
|
<th>@Localizer["Name"]</th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.AliasId.ToString())" ResourceKey="EditSite" /></td>
|
<td><button type="button" class="btn btn-primary" @onclick="@(async () => Edit(context.Name))">@Localizer["Edit"]</button></td>
|
||||||
<td><ActionDialog Header="Delete Site" Message="@Localizer["Are You Sure You Wish To Delete The {0} Site?", context.Name]" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteSite(context))" ResourceKey="DeleteSite" /></td>
|
<td><button type="button" class="btn btn-secondary" @onclick="@(async () => Browse(context.Name))">@Localizer["Browse"]</button></td>
|
||||||
<td><a href="@(_scheme + context.Name +"?reload")">@context.Name</a></td>
|
<td>@context.Name</td>
|
||||||
</Row>
|
</Row>
|
||||||
</Pager>
|
</Pager>
|
||||||
}
|
}
|
||||||
@ -49,33 +49,14 @@ else
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DeleteSite(Alias alias)
|
private void Edit(string name)
|
||||||
{
|
{
|
||||||
try
|
NavigationManager.NavigateTo(_scheme + name + "/admin/site", true);
|
||||||
{
|
|
||||||
if (alias.SiteId != PageState.Site.SiteId || alias.TenantId != PageState.Site.TenantId)
|
|
||||||
{
|
|
||||||
SiteService.SetAlias(alias);
|
|
||||||
await SiteService.DeleteSiteAsync(alias.SiteId);
|
|
||||||
await Log(alias, LogLevel.Information, "", null, "Site Deleted {SiteId}", alias.SiteId);
|
|
||||||
|
|
||||||
var aliases = await AliasService.GetAliasesAsync();
|
|
||||||
foreach (Alias a in aliases.Where(item => item.SiteId == alias.SiteId && item.TenantId == alias.TenantId))
|
|
||||||
{
|
|
||||||
await AliasService.DeleteAliasAsync(a.AliasId);
|
|
||||||
}
|
|
||||||
|
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AddModuleMessage(Localizer["You Can Not Delete The Current Site"], MessageType.Warning);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await Log(alias, LogLevel.Error, "", ex, "Error Deleting Site {SiteId} {Error}", alias.SiteId, ex.Message);
|
|
||||||
AddModuleMessage(Localizer["Error Deleting Site"], MessageType.Error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Browse(string name)
|
||||||
|
{
|
||||||
|
NavigationManager.NavigateTo(_scheme + name, true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject ITenantService TenantService
|
@inject ITenantService TenantService
|
||||||
|
@inject IDatabaseService DatabaseService
|
||||||
@inject ISqlService SqlService
|
@inject ISqlService SqlService
|
||||||
@inject IStringLocalizer<Index> Localizer
|
@inject IStringLocalizer<Index> Localizer
|
||||||
|
|
||||||
@ -11,19 +12,37 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="tenant" HelpText="Select the tenant for the SQL server" ResourceKey="Tenant">Tenant: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select id="tenant" class="form-control" value="@_tenantid" @onchange="(e => TenantChanged(e))">
|
||||||
|
<option value="-1"><@Localizer["Select Tenant"]></option>
|
||||||
|
@foreach (Tenant tenant in _tenants)
|
||||||
|
{
|
||||||
|
<option value="@tenant.TenantId">@tenant.Name</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@if (_tenantid != "-1")
|
||||||
|
{
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="tenant" HelpText="Select the tenant for the SQL server" ResourceKey="Tenant">Tenant: </Label>
|
<Label For="database" HelpText="The database for the tenant" ResourceKey="Database">Database: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="teneant" class="form-control" @bind="_tenantid">
|
<input id="database" class="form-control" @bind="@_database" readonly />
|
||||||
<option value="-1"><@Localizer["Select Tenant"]></option>
|
</td>
|
||||||
@foreach (Tenant tenant in _tenants)
|
</tr>
|
||||||
{
|
<tr>
|
||||||
<option value="@tenant.TenantId">@tenant.Name</option>
|
<td>
|
||||||
}
|
<Label For="connectionstring" HelpText="The connection information for the database" ResourceKey="ConnectionString">Connection: </Label>
|
||||||
</select>
|
</td>
|
||||||
|
<td>
|
||||||
|
<textarea id="connectionstring" class="form-control" @bind="@_connectionstring" rows="2" readonly></textarea>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -34,6 +53,7 @@ else
|
|||||||
<textarea id="sqlQeury" class="form-control" @bind="@_sql" rows="5"></textarea>
|
<textarea id="sqlQeury" class="form-control" @bind="@_sql" rows="5"></textarea>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
}
|
||||||
</table>
|
</table>
|
||||||
<button type="button" class="btn btn-success" @onclick="Execute">@Localizer["Execute"]</button>
|
<button type="button" class="btn btn-success" @onclick="Execute">@Localizer["Execute"]</button>
|
||||||
<br />
|
<br />
|
||||||
@ -47,6 +67,8 @@ else
|
|||||||
@code {
|
@code {
|
||||||
private List<Tenant> _tenants;
|
private List<Tenant> _tenants;
|
||||||
private string _tenantid = "-1";
|
private string _tenantid = "-1";
|
||||||
|
private string _database = string.Empty;
|
||||||
|
private string _connectionstring = string.Empty;
|
||||||
private string _sql = string.Empty;
|
private string _sql = string.Empty;
|
||||||
private string _results = string.Empty;
|
private string _results = string.Empty;
|
||||||
|
|
||||||
@ -54,20 +76,59 @@ else
|
|||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
_tenants = await TenantService.GetTenantsAsync();
|
try
|
||||||
|
{
|
||||||
|
_tenants = await TenantService.GetTenantsAsync();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Loading Tenants {Error}", ex.Message);
|
||||||
|
AddModuleMessage(ex.Message, MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void TenantChanged(ChangeEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_tenantid = (string)e.Value;
|
||||||
|
var tenants = await TenantService.GetTenantsAsync();
|
||||||
|
var _databases = await DatabaseService.GetDatabasesAsync();
|
||||||
|
var tenant = tenants.Find(item => item.TenantId == int.Parse(_tenantid));
|
||||||
|
if (tenant != null)
|
||||||
|
{
|
||||||
|
_database = _databases.Find(item => item.DBType == tenant.DBType)?.Name;
|
||||||
|
_connectionstring = tenant.DBConnectionString;
|
||||||
|
}
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Loading Tenant {TenantId} {Error}", _tenantid, ex.Message);
|
||||||
|
AddModuleMessage(ex.Message, MessageType.Error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Execute()
|
private async Task Execute()
|
||||||
{
|
{
|
||||||
if (_tenantid != "-1" && !string.IsNullOrEmpty(_sql))
|
try
|
||||||
{
|
{
|
||||||
var sqlquery = new SqlQuery { TenantId = int.Parse(_tenantid), Query = _sql };
|
if (_tenantid != "-1" && !string.IsNullOrEmpty(_sql))
|
||||||
sqlquery = await SqlService.ExecuteQueryAsync(sqlquery);
|
{
|
||||||
_results = DisplayResults(sqlquery.Results);
|
var sqlquery = new SqlQuery { TenantId = int.Parse(_tenantid), Query = _sql };
|
||||||
|
sqlquery = await SqlService.ExecuteQueryAsync(sqlquery);
|
||||||
|
_results = DisplayResults(sqlquery.Results);
|
||||||
|
AddModuleMessage(Localizer["SQL Query Executed"], MessageType.Success);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddModuleMessage(Localizer["You Must Select A Tenant And Provide A Valid SQL Query"], MessageType.Warning);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
AddModuleMessage(Localizer["You Must Select A Tenant And Provide A SQL Query"], MessageType.Warning);
|
await logger.LogError(ex, "Error Executing SQL Query {SQL} {Error}", _sql, ex.Message);
|
||||||
|
AddModuleMessage(ex.Message, MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,10 +15,24 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label For="runtime" HelpText="Blazor Runtime (Server or WebAssembly)" ResourceKey="BlazorRunime">Blazor Runtime: </Label>
|
<Label For="runtime" HelpText="Blazor Runtime (Server or WebAssembly)" ResourceKey="BlazorRuntime">Blazor Runtime: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input id="runtime" class="form-control" @bind="@_runtime" readonly />
|
<select id="runtime" class="form-control" @bind="@_runtime">
|
||||||
|
<option value="Server">@Localizer["Server"]</option>
|
||||||
|
<option value="WebAssembly">@Localizer["WebAssembly"]</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="rendermode" HelpText="Blazor Server Render Mode" ResourceKey="RenderMode">Render Mode: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select id="rendermode" class="form-control" @bind="@_rendermode">
|
||||||
|
<option value="Server">@Localizer["Server"]</option>
|
||||||
|
<option value="ServerPrerendered">@Localizer["ServerPrerendered"]</option>
|
||||||
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@ -54,6 +68,7 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
<button type="button" class="btn btn-success" @onclick="SaveConfig">@Localizer["Save"]</button>
|
||||||
<a class="btn btn-primary" href="swagger/index.html" target="_new">@Localizer["Access Framework API"]</a>
|
<a class="btn btn-primary" href="swagger/index.html" target="_new">@Localizer["Access Framework API"]</a>
|
||||||
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
|
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
|
||||||
|
|
||||||
@ -62,6 +77,7 @@
|
|||||||
|
|
||||||
private string _version = string.Empty;
|
private string _version = string.Empty;
|
||||||
private string _runtime = string.Empty;
|
private string _runtime = string.Empty;
|
||||||
|
private string _rendermode = string.Empty;
|
||||||
private string _clrversion = string.Empty;
|
private string _clrversion = string.Empty;
|
||||||
private string _osversion = string.Empty;
|
private string _osversion = string.Empty;
|
||||||
private string _serverpath = string.Empty;
|
private string _serverpath = string.Empty;
|
||||||
@ -75,6 +91,7 @@
|
|||||||
Dictionary<string, string> systeminfo = await SystemService.GetSystemInfoAsync();
|
Dictionary<string, string> systeminfo = await SystemService.GetSystemInfoAsync();
|
||||||
if (systeminfo != null)
|
if (systeminfo != null)
|
||||||
{
|
{
|
||||||
|
_rendermode = systeminfo["rendermode"];
|
||||||
_clrversion = systeminfo["clrversion"];
|
_clrversion = systeminfo["clrversion"];
|
||||||
_osversion = systeminfo["osversion"];
|
_osversion = systeminfo["osversion"];
|
||||||
_serverpath = systeminfo["serverpath"];
|
_serverpath = systeminfo["serverpath"];
|
||||||
@ -82,6 +99,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task SaveConfig()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var settings = new Dictionary<string, string>();
|
||||||
|
settings.Add("runtime", _runtime);
|
||||||
|
settings.Add("rendermode", _rendermode);
|
||||||
|
await SystemService.UpdateSystemInfoAsync(settings);
|
||||||
|
AddModuleMessage(Localizer["Configuration Updated. Please Select Restart Application For These Changes To Be Activated."], MessageType.Success);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Saving Configuration");
|
||||||
|
AddModuleMessage(Localizer["An Error Occurred Updating The Configuration"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task RestartApplication()
|
private async Task RestartApplication()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
<Label HelpText="Upload one or more theme packages. Once they are uploaded click Install to complete the installation." ResourceKey="Theme">Theme: </Label>
|
<Label HelpText="Upload one or more theme packages. Once they are uploaded click Install to complete the installation." ResourceKey="Theme">Theme: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<FileManager Filter="nupkg" ShowFiles="false" Folder="Themes" UploadMultiple="@true" />
|
<FileManager Filter="nupkg" ShowFiles="false" Folder="Packages" UploadMultiple="@true" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
foreach (Package package in _packages.ToArray())
|
foreach (Package package in _packages.ToArray())
|
||||||
{
|
{
|
||||||
if (themes.Exists(item => Utilities.GetTypeName(item.ThemeName) == package.PackageId))
|
if (themes.Exists(item => item.PackageName == package.PackageId))
|
||||||
{
|
{
|
||||||
_packages.Remove(package);
|
_packages.Remove(package);
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(packageid, version, "Themes");
|
await PackageService.DownloadPackageAsync(packageid, version, "Packages");
|
||||||
await logger.LogInformation("Theme {ThemeName} {Version} Downloaded Successfully", packageid, version);
|
await logger.LogInformation("Theme {ThemeName} {Version} Downloaded Successfully", packageid, version);
|
||||||
AddModuleMessage(Localizer["Themes Downloaded Successfully. Click Install To Complete Installation."], MessageType.Success);
|
AddModuleMessage(Localizer["Themes Downloaded Successfully. Click Install To Complete Installation."], MessageType.Success);
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
@namespace Oqtane.Modules.Admin.Themes
|
@namespace Oqtane.Modules.Admin.Themes
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
|
@using System.Text.RegularExpressions
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IThemeService ThemeService
|
@inject IThemeService ThemeService
|
||||||
@inject IModuleService ModuleService
|
@inject IModuleService ModuleService
|
||||||
@inject IPageModuleService PageModuleService
|
@inject IPageModuleService PageModuleService
|
||||||
@inject ISystemService SystemService
|
|
||||||
@inject ISettingService SettingService
|
@inject ISettingService SettingService
|
||||||
@inject IStringLocalizer<Index> Localizer
|
@inject IStringLocalizer<Index> Localizer
|
||||||
@using System.Text.RegularExpressions
|
|
||||||
@using System.IO;
|
|
||||||
|
|
||||||
@if (_systeminfo != null && _templates != null)
|
@if (_templates != null)
|
||||||
{
|
{
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
@ -36,9 +34,9 @@
|
|||||||
<td>
|
<td>
|
||||||
<select id="template" class="form-control" @onchange="(e => TemplateChanged(e))">
|
<select id="template" class="form-control" @onchange="(e => TemplateChanged(e))">
|
||||||
<option value="-"><@Localizer["Select Template"]></option>
|
<option value="-"><@Localizer["Select Template"]></option>
|
||||||
@foreach (string template in _templates)
|
@foreach (Template template in _templates)
|
||||||
{
|
{
|
||||||
<option value="@template">@template</option>
|
<option value="@template.Name">@template.Title</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
@ -49,9 +47,9 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="reference" class="form-control" @bind="@_reference">
|
<select id="reference" class="form-control" @bind="@_reference">
|
||||||
@foreach (string version in Constants.ReleaseVersions.Split(','))
|
@foreach (string version in _versions)
|
||||||
{
|
{
|
||||||
if (Version.Parse(version).CompareTo(Version.Parse("2.0.0")) >= 0)
|
if (Version.Parse(version).CompareTo(Version.Parse(_minversion)) >= 0)
|
||||||
{
|
{
|
||||||
<option value="@(version)">@(version)</option>
|
<option value="@(version)">@(version)</option>
|
||||||
}
|
}
|
||||||
@ -79,21 +77,21 @@
|
|||||||
@code {
|
@code {
|
||||||
private string _owner = string.Empty;
|
private string _owner = string.Empty;
|
||||||
private string _theme = string.Empty;
|
private string _theme = string.Empty;
|
||||||
|
private List<Template> _templates;
|
||||||
private string _template = "-";
|
private string _template = "-";
|
||||||
|
private string[] _versions;
|
||||||
private string _reference = Constants.Version;
|
private string _reference = Constants.Version;
|
||||||
|
private string _minversion = "2.0.0";
|
||||||
private string _location = string.Empty;
|
private string _location = string.Empty;
|
||||||
|
|
||||||
private Dictionary<string, string> _systeminfo;
|
|
||||||
private List<string> _templates;
|
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_systeminfo = await SystemService.GetSystemInfoAsync();
|
|
||||||
_templates = await ThemeService.GetThemeTemplatesAsync();
|
_templates = await ThemeService.GetThemeTemplatesAsync();
|
||||||
|
_versions = Constants.ReleaseVersions.Split(',').Where(item => Version.Parse(item).CompareTo(Version.Parse("2.0.0")) >= 0).ToArray();
|
||||||
AddModuleMessage(Localizer["Please Note That The Theme Creator Is Only Intended To Be Used In A Development Environment"], MessageType.Info);
|
AddModuleMessage(Localizer["Please Note That The Theme Creator Is Only Intended To Be Used In A Development Environment"], MessageType.Info);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -111,7 +109,6 @@
|
|||||||
var theme = new Theme { Owner = _owner, Name = _theme, Template = _template, Version = _reference };
|
var theme = new Theme { Owner = _owner, Name = _theme, Template = _template, Version = _reference };
|
||||||
theme = await ThemeService.CreateThemeAsync(theme);
|
theme = await ThemeService.CreateThemeAsync(theme);
|
||||||
GetLocation();
|
GetLocation();
|
||||||
|
|
||||||
AddModuleMessage(Localizer["The Source Code For Your Theme Has Been Created At The Location Specified Below And Must Be Compiled In Order To Make It Functional. Once It Has Been Compiled You Must <a href=\"{0}\">Restart</a> Your Application To Activate The Module.", NavigateUrl("admin/system")], MessageType.Success);
|
AddModuleMessage(Localizer["The Source Code For Your Theme Has Been Created At The Location Specified Below And Must Be Compiled In Order To Make It Functional. Once It Has Been Compiled You Must <a href=\"{0}\">Restart</a> Your Application To Activate The Module.", NavigateUrl("admin/system")], MessageType.Success);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -128,23 +125,29 @@
|
|||||||
private bool IsValid(string name)
|
private bool IsValid(string name)
|
||||||
{
|
{
|
||||||
// must contain letters, underscores and digits and first character must be letter or underscore
|
// must contain letters, underscores and digits and first character must be letter or underscore
|
||||||
return !string.IsNullOrEmpty(name) && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_]*$");
|
return !string.IsNullOrEmpty(name) && name.ToLower() != "theme" && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_]*$");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TemplateChanged(ChangeEventArgs e)
|
private void TemplateChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
_template = (string)e.Value;
|
_template = (string)e.Value;
|
||||||
|
_minversion = "2.0.0";
|
||||||
|
if (_template != "-")
|
||||||
|
{
|
||||||
|
var template = _templates.FirstOrDefault(item => item.Name == _template);
|
||||||
|
_minversion = template.Version;
|
||||||
|
}
|
||||||
GetLocation();
|
GetLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetLocation()
|
private void GetLocation()
|
||||||
{
|
{
|
||||||
_location = string.Empty;
|
_location = string.Empty;
|
||||||
if (_template != "-" && _systeminfo != null && _systeminfo.ContainsKey("serverpath"))
|
if (_owner != "" && _theme != "" && _template != "-")
|
||||||
{
|
{
|
||||||
string[] path = _systeminfo["serverpath"].Split(Path.DirectorySeparatorChar);
|
var template = _templates.FirstOrDefault(item => item.Name == _template);
|
||||||
_location = string.Join(Path.DirectorySeparatorChar, path, 0, path.Length - 2) +
|
_location = template.Location + _owner + "." + _theme;
|
||||||
Path.DirectorySeparatorChar + _owner + "." + _theme;
|
|
||||||
}
|
}
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,9 @@ else
|
|||||||
<td>@context.Name</td>
|
<td>@context.Name</td>
|
||||||
<td>@context.Version</td>
|
<td>@context.Version</td>
|
||||||
<td>
|
<td>
|
||||||
@if (UpgradeAvailable(context.ThemeName, context.Version))
|
@if (UpgradeAvailable(context.PackageName, context.Version))
|
||||||
{
|
{
|
||||||
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadTheme(context.ThemeName, context.Version))>@Localizer["Upgrade"]</button>
|
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadTheme(context.PackageName, context.Version))>@Localizer["Upgrade"]</button>
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
@ -68,12 +68,12 @@ else
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool UpgradeAvailable(string themename, string version)
|
private bool UpgradeAvailable(string packagename, string version)
|
||||||
{
|
{
|
||||||
var upgradeavailable = false;
|
var upgradeavailable = false;
|
||||||
if (_packages != null)
|
if (_packages != null)
|
||||||
{
|
{
|
||||||
var package = _packages.Where(item => item.PackageId == Utilities.GetTypeName(themename)).FirstOrDefault();
|
var package = _packages.Where(item => item.PackageId == packagename).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);
|
||||||
@ -82,18 +82,18 @@ else
|
|||||||
return upgradeavailable;
|
return upgradeavailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DownloadTheme(string themename, string version)
|
private async Task DownloadTheme(string packagename, string version)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(themename, version, "Themes");
|
await PackageService.DownloadPackageAsync(packagename, version, "Packages");
|
||||||
await logger.LogInformation("Theme Downloaded {ThemeName} {Version}", themename, version);
|
await logger.LogInformation("Theme Downloaded {ThemeName} {Version}", packagename, version);
|
||||||
await ThemeService.InstallThemesAsync();
|
await ThemeService.InstallThemesAsync();
|
||||||
AddModuleMessage(Localizer["Theme Installed Successfully. You Must <a href=\"{0}\">Restart</a> Your Application To Apply These Changes.", NavigateUrl("admin/system")], MessageType.Success);
|
AddModuleMessage(Localizer["Theme Installed Successfully. You Must <a href=\"{0}\">Restart</a> Your Application To Apply These Changes.", NavigateUrl("admin/system")], MessageType.Success);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Downloading Theme {ThemeName} {Version} {Error}", themename, version, ex.Message);
|
await logger.LogError(ex, "Error Downloading Theme {ThemeName} {Version} {Error}", packagename, version, ex.Message);
|
||||||
AddModuleMessage(Localizer["Error Downloading Theme"], MessageType.Error);
|
AddModuleMessage(Localizer["Error Downloading Theme"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,7 +104,7 @@ else
|
|||||||
{
|
{
|
||||||
await ThemeService.DeleteThemeAsync(Theme.ThemeName);
|
await ThemeService.DeleteThemeAsync(Theme.ThemeName);
|
||||||
AddModuleMessage(Localizer["Theme Deleted Successfully"], MessageType.Success);
|
AddModuleMessage(Localizer["Theme Deleted Successfully"], MessageType.Success);
|
||||||
StateHasChanged();
|
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "reload"));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -12,8 +12,9 @@
|
|||||||
<TabPanel Name="Download" ResourceKey="Download">
|
<TabPanel Name="Download" ResourceKey="Download">
|
||||||
@if (_upgradeavailable)
|
@if (_upgradeavailable)
|
||||||
{
|
{
|
||||||
<ModuleMessage Type="MessageType.Info" Message="Select The Upgrade Button To Install a New Framework Version"></ModuleMessage>
|
<ModuleMessage Type="MessageType.Info" Message="Select The Download Button To Download The Framework Upgrade Package And Then Select Upgrade"></ModuleMessage>
|
||||||
<button type="button" class="btn btn-success" @onclick=@(async () => await Download(Constants.PackageId, @_package.Version))>@Localizer["Upgrade To"] @_package.Version</button>
|
<button type="button" class="btn btn-primary" @onclick=@(async () => await Download(Constants.PackageId, @_package.Version))>@Localizer["Download"] @_package.Version</button>
|
||||||
|
<button type="button" class="btn btn-success" @onclick="Upgrade">@Localizer["Upgrade"]</button>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -21,17 +22,18 @@
|
|||||||
}
|
}
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel Name="Upload" ResourceKey="Upload">
|
<TabPanel Name="Upload" ResourceKey="Upload">
|
||||||
|
<ModuleMessage Type="MessageType.Info" Message="Upload A Framework Package (Oqtane.Framework.version.nupkg) And Then Select Upgrade"></ModuleMessage>
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<Label HelpText="Upload a framework package and select Install to complete the installation" ResourceKey="Framework">Framework: </Label>
|
<Label HelpText="Upload A Framework Package And Then Select Upgrade" ResourceKey="Framework">Framework: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<FileManager Filter="nupkg" ShowFiles="false" Folder="Framework" />
|
<FileManager Filter="nupkg" ShowFiles="false" Folder="Packages" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<button type="button" class="btn btn-success" @onclick="Upgrade">@Localizer["Install"]</button>
|
<button type="button" class="btn btn-success" @onclick="Upgrade">@Localizer["Upgrade"]</button>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</TabStrip>
|
</TabStrip>
|
||||||
}
|
}
|
||||||
@ -49,7 +51,7 @@
|
|||||||
List<Package> packages = await PackageService.GetPackagesAsync("framework");
|
List<Package> packages = await PackageService.GetPackagesAsync("framework");
|
||||||
if (packages != null)
|
if (packages != null)
|
||||||
{
|
{
|
||||||
_package = packages.FirstOrDefault();
|
_package = packages.Where(item => item.PackageId.StartsWith(Constants.PackageId)).FirstOrDefault();
|
||||||
if (_package != null)
|
if (_package != null)
|
||||||
{
|
{
|
||||||
_upgradeavailable = (Version.Parse(_package.Version).CompareTo(Version.Parse(Constants.Version)) > 0);
|
_upgradeavailable = (Version.Parse(_package.Version).CompareTo(Version.Parse(Constants.Version)) > 0);
|
||||||
@ -70,9 +72,10 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
AddModuleMessage(Localizer["Please Be Patient While The Upgrade Is In Progress..."], MessageType.Info);
|
||||||
ShowProgressIndicator();
|
ShowProgressIndicator();
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
await interop.RedirectBrowser(NavigateUrl(), 10);
|
await interop.RedirectBrowser(NavigateUrl(), 30);
|
||||||
await InstallationService.Upgrade();
|
await InstallationService.Upgrade();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -86,16 +89,14 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(packageid, version, "Framework");
|
await PackageService.DownloadPackageAsync(packageid, version, "Packages");
|
||||||
ShowProgressIndicator();
|
await PackageService.DownloadPackageAsync(Constants.UpdaterPackageId, version, "Packages");
|
||||||
var interop = new Interop(JSRuntime);
|
AddModuleMessage(Localizer["Framework Downloaded Successfully... Please Select Upgrade To Complete the Process"], MessageType.Success);
|
||||||
await interop.RedirectBrowser(NavigateUrl(), 10);
|
|
||||||
await InstallationService.Upgrade();
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Downloading Framework {Error}", ex.Message);
|
await logger.LogError(ex, "Error Downloading Framework Package {Error}", ex.Message);
|
||||||
AddModuleMessage(Localizer["Error Downloading Framework"], MessageType.Error);
|
AddModuleMessage(Localizer["Error Downloading Framework Package"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,12 @@
|
|||||||
@inject IProfileService ProfileService
|
@inject IProfileService ProfileService
|
||||||
@inject ISettingService SettingService
|
@inject ISettingService SettingService
|
||||||
@inject INotificationService NotificationService
|
@inject INotificationService NotificationService
|
||||||
|
@inject IFileService FileService
|
||||||
@inject IStringLocalizer<Index> Localizer
|
@inject IStringLocalizer<Index> Localizer
|
||||||
|
|
||||||
@if (PageState.User != null && photofileid != -1)
|
@if (PageState.User != null && photo != null)
|
||||||
{
|
{
|
||||||
<img src="@(ContentUrl(photofileid))" alt="@displayname" style="max-width: 400px" class="rounded-circle mx-auto d-block">
|
<img src="@photo.Url" alt="@displayname" style="max-width: 400px" class="rounded-circle mx-auto d-block">
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -76,58 +77,58 @@ else
|
|||||||
<TabPanel Name="Profile" ResourceKey="Profile">
|
<TabPanel Name="Profile" ResourceKey="Profile">
|
||||||
@if (profiles != null && settings != 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)
|
||||||
{
|
|
||||||
var p = profile;
|
|
||||||
if (!p.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
|
||||||
{
|
{
|
||||||
if (p.Category != category)
|
var p = profile;
|
||||||
|
if (!p.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||||
{
|
{
|
||||||
|
if (p.Category != category)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<th colspan="2" style="text-align: center;">
|
||||||
|
@p.Category
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
category = p.Category;
|
||||||
|
}
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="2" style="text-align: center;">
|
<td>
|
||||||
@p.Category
|
<Label For="@p.Name" HelpText="@p.Description">@p.Title</Label>
|
||||||
</th>
|
</td>
|
||||||
</tr>
|
<td>
|
||||||
category = p.Category;
|
@if (!string.IsNullOrEmpty(p.Options))
|
||||||
}
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<Label For="@p.Name" HelpText="@p.Description">@p.Title</Label>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
@if (!string.IsNullOrEmpty(p.Options))
|
|
||||||
{
|
|
||||||
<select id="@p.Name" class="form-control" @onchange="@(e => ProfileChanged(e, p.Name))">
|
|
||||||
@foreach (var option in p.Options.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
|
||||||
{
|
|
||||||
@if(GetProfileValue(p.Name, "") == option || (GetProfileValue(p.Name, "") == "" && p.DefaultValue == option))
|
|
||||||
{
|
|
||||||
<option value="@option" selected>@option</option>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<option value="@option">@option</option>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
@if (p.IsRequired)
|
|
||||||
{
|
{
|
||||||
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" required @onchange="@(e => ProfileChanged(e, p.Name))" />
|
<select id="@p.Name" class="form-control" @onchange="@(e => ProfileChanged(e, p.Name))">
|
||||||
|
@foreach (var option in p.Options.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
@if (GetProfileValue(p.Name, "") == option || (GetProfileValue(p.Name, "") == "" && p.DefaultValue == option))
|
||||||
|
{
|
||||||
|
<option value="@option" selected>@option</option>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<option value="@option">@option</option>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</select>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" @onchange="@(e => ProfileChanged(e, p.Name))" />
|
@if (p.IsRequired)
|
||||||
|
{
|
||||||
|
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" required @onchange="@(e => ProfileChanged(e, p.Name))" />
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" @onchange="@(e => ProfileChanged(e, p.Name))" />
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
</td>
|
||||||
</td>
|
</tr>
|
||||||
</tr>
|
}
|
||||||
}
|
}
|
||||||
}
|
</table>
|
||||||
</table>
|
|
||||||
<button type="button" class="btn btn-primary" @onclick="Save">@Localizer["Save"]</button>
|
<button type="button" class="btn btn-primary" @onclick="Save">@Localizer["Save"]</button>
|
||||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@Localizer["Cancel"]</button>
|
<button type="button" class="btn btn-secondary" @onclick="Cancel">@Localizer["Cancel"]</button>
|
||||||
}
|
}
|
||||||
@ -157,13 +158,14 @@ else
|
|||||||
<Detail>
|
<Detail>
|
||||||
<td colspan="2"></td>
|
<td colspan="2"></td>
|
||||||
<td colspan="3">
|
<td colspan="3">
|
||||||
@{
|
@{
|
||||||
string input = "___";
|
string input = "___";
|
||||||
if (context.Body.Contains(input)){
|
if (context.Body.Contains(input))
|
||||||
context.Body = context.Body.Split(input)[0];
|
{
|
||||||
context.Body = context.Body.Replace("\n", "");
|
context.Body = context.Body.Split(input)[0];
|
||||||
context.Body = context.Body.Replace("\r", "");
|
context.Body = context.Body.Replace("\n", "");
|
||||||
} }
|
context.Body = context.Body.Replace("\r", "");
|
||||||
|
} }
|
||||||
@(context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body)
|
@(context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body)
|
||||||
</td>
|
</td>
|
||||||
</Detail>
|
</Detail>
|
||||||
@ -189,13 +191,14 @@ else
|
|||||||
<Detail>
|
<Detail>
|
||||||
<td colspan="2"></td>
|
<td colspan="2"></td>
|
||||||
<td colspan="3">
|
<td colspan="3">
|
||||||
@{
|
@{
|
||||||
string input = "___";
|
string input = "___";
|
||||||
if (context.Body.Contains(input)){
|
if (context.Body.Contains(input))
|
||||||
context.Body = context.Body.Split(input)[0];
|
{
|
||||||
context.Body = context.Body.Replace("\n", "");
|
context.Body = context.Body.Split(input)[0];
|
||||||
context.Body = context.Body.Replace("\r", "");
|
context.Body = context.Body.Replace("\n", "");
|
||||||
} }
|
context.Body = context.Body.Replace("\r", "");
|
||||||
|
} }
|
||||||
@(context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body)
|
@(context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body)
|
||||||
</td>
|
</td>
|
||||||
</Detail>
|
</Detail>
|
||||||
@ -218,6 +221,7 @@ else
|
|||||||
private string displayname = string.Empty;
|
private string displayname = string.Empty;
|
||||||
private FileManager filemanager;
|
private FileManager filemanager;
|
||||||
private int photofileid = -1;
|
private int photofileid = -1;
|
||||||
|
private File photo = null;
|
||||||
private List<Profile> profiles;
|
private List<Profile> profiles;
|
||||||
private Dictionary<string, string> settings;
|
private Dictionary<string, string> settings;
|
||||||
private string category = string.Empty;
|
private string category = string.Empty;
|
||||||
@ -226,7 +230,7 @@ else
|
|||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -239,6 +243,12 @@ else
|
|||||||
if (PageState.User.PhotoFileId != null)
|
if (PageState.User.PhotoFileId != null)
|
||||||
{
|
{
|
||||||
photofileid = PageState.User.PhotoFileId.Value;
|
photofileid = PageState.User.PhotoFileId.Value;
|
||||||
|
photo = await FileService.GetFileAsync(photofileid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
photofileid = -1;
|
||||||
|
photo = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
|
profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
|
||||||
@ -280,18 +290,17 @@ else
|
|||||||
user.Password = password;
|
user.Password = password;
|
||||||
user.Email = email;
|
user.Email = email;
|
||||||
user.DisplayName = (displayname == string.Empty ? username : displayname);
|
user.DisplayName = (displayname == string.Empty ? username : displayname);
|
||||||
user.PhotoFileId = null;
|
user.PhotoFileId = filemanager.GetFileId();
|
||||||
photofileid = filemanager.GetFileId();
|
if (user.PhotoFileId == -1)
|
||||||
|
|
||||||
if (photofileid != -1)
|
|
||||||
{
|
{
|
||||||
user.PhotoFileId = photofileid;
|
user.PhotoFileId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
await UserService.UpdateUserAsync(user);
|
await UserService.UpdateUserAsync(user);
|
||||||
await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
|
await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
|
||||||
await logger.LogInformation("User Profile Saved");
|
await logger.LogInformation("User Profile Saved");
|
||||||
AddModuleMessage(Localizer["User Profile Updated Successfully"], MessageType.Success);
|
|
||||||
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -131,26 +131,34 @@
|
|||||||
{
|
{
|
||||||
if (password == confirm)
|
if (password == confirm)
|
||||||
{
|
{
|
||||||
var user = new User();
|
var user = await UserService.GetUserAsync(username, PageState.Site.SiteId);
|
||||||
user.SiteId = PageState.Site.SiteId;
|
if (user == null)
|
||||||
user.Username = username;
|
|
||||||
user.Password = password;
|
|
||||||
user.Email = email;
|
|
||||||
user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname;
|
|
||||||
user.PhotoFileId = null;
|
|
||||||
|
|
||||||
user = await UserService.AddUserAsync(user);
|
|
||||||
|
|
||||||
if (user != null)
|
|
||||||
{
|
{
|
||||||
await SettingService.UpdateUserSettingsAsync(settings, user.UserId);
|
user = new User();
|
||||||
await logger.LogInformation("User Created {User}", user);
|
user.SiteId = PageState.Site.SiteId;
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
user.Username = username;
|
||||||
|
user.Password = password;
|
||||||
|
user.Email = email;
|
||||||
|
user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname;
|
||||||
|
user.PhotoFileId = null;
|
||||||
|
|
||||||
|
user = await UserService.AddUserAsync(user);
|
||||||
|
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
await SettingService.UpdateUserSettingsAsync(settings, user.UserId);
|
||||||
|
await logger.LogInformation("User Created {User}", user);
|
||||||
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await logger.LogError("Error Adding User {Username} {Email}", username, email);
|
||||||
|
AddModuleMessage(Localizer["Error Adding User. Please Ensure Password Meets Complexity Requirements And Username And Email Are Not Already In Use."], MessageType.Error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await logger.LogError("Error Adding User {Username} {Email}", username, email);
|
AddModuleMessage(Localizer["Username Already Exists"], MessageType.Warning);
|
||||||
AddModuleMessage(Localizer["Error Adding User. Please Ensure Password Meets Complexity Requirements And Username Is Not Already In Use."], MessageType.Error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -4,11 +4,12 @@
|
|||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@inject IProfileService ProfileService
|
@inject IProfileService ProfileService
|
||||||
@inject ISettingService SettingService
|
@inject ISettingService SettingService
|
||||||
|
@inject IFileService FileService
|
||||||
@inject IStringLocalizer<Edit> Localizer
|
@inject IStringLocalizer<Edit> Localizer
|
||||||
|
|
||||||
@if (PageState.User != null && photofileid != -1)
|
@if (PageState.User != null && photo != null)
|
||||||
{
|
{
|
||||||
<img src="@(ContentUrl(photofileid))" alt="@displayname" style="max-width: 400px" class="rounded-circle mx-auto d-block">
|
<img src="@photo.Url" alt="@displayname" style="max-width: 400px" class="rounded-circle mx-auto d-block">
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -133,6 +134,7 @@ else
|
|||||||
private string displayname = string.Empty;
|
private string displayname = string.Empty;
|
||||||
private FileManager filemanager;
|
private FileManager filemanager;
|
||||||
private int photofileid = -1;
|
private int photofileid = -1;
|
||||||
|
private File photo = null;
|
||||||
private List<Profile> profiles;
|
private List<Profile> profiles;
|
||||||
private Dictionary<string, string> settings;
|
private Dictionary<string, string> settings;
|
||||||
private string category = string.Empty;
|
private string category = string.Empty;
|
||||||
@ -146,7 +148,7 @@ else
|
|||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -159,12 +161,16 @@ else
|
|||||||
username = user.Username;
|
username = user.Username;
|
||||||
email = user.Email;
|
email = user.Email;
|
||||||
displayname = user.DisplayName;
|
displayname = user.DisplayName;
|
||||||
|
|
||||||
if (user.PhotoFileId != null)
|
if (user.PhotoFileId != null)
|
||||||
{
|
{
|
||||||
photofileid = user.PhotoFileId.Value;
|
photofileid = user.PhotoFileId.Value;
|
||||||
|
photo = await FileService.GetFileAsync(photofileid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
photofileid = -1;
|
||||||
|
photo = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
settings = await SettingService.GetUserSettingsAsync(user.UserId);
|
settings = await SettingService.GetUserSettingsAsync(user.UserId);
|
||||||
createdby = user.CreatedBy;
|
createdby = user.CreatedBy;
|
||||||
createdon = user.CreatedOn;
|
createdon = user.CreatedOn;
|
||||||
@ -200,11 +206,10 @@ else
|
|||||||
user.Email = email;
|
user.Email = email;
|
||||||
user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname;
|
user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname;
|
||||||
user.PhotoFileId = null;
|
user.PhotoFileId = null;
|
||||||
photofileid = filemanager.GetFileId();
|
user.PhotoFileId = filemanager.GetFileId();
|
||||||
|
if (user.PhotoFileId == -1)
|
||||||
if (photofileid != -1)
|
|
||||||
{
|
{
|
||||||
user.PhotoFileId = photofileid;
|
user.PhotoFileId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
user.IsDeleted = (isdeleted == null ? true : Boolean.Parse(isdeleted));
|
user.IsDeleted = (isdeleted == null ? true : Boolean.Parse(isdeleted));
|
||||||
|
@ -13,10 +13,15 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<ActionLink Action="Add" Text="Add User" ResourceKey="AddUser" />
|
<div class="form-row">
|
||||||
|
<div class="col">
|
||||||
<div class="d-flex p-1">
|
<ActionLink Action="Add" Text="Add User" ResourceKey="AddUser" />
|
||||||
<input class="form-control mr-4" @bind="@_search" /><button class="btn btn-outline-primary ml-1" @onclick="OnSearch">@Localizer["Search"]</button>
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<div class="input-group flex-nowrap">
|
||||||
|
<input class="form-control" @bind="@_search" /> <button class="btn btn-secondary" @onclick="OnSearch">@Localizer["Search"]</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Pager Items="@userroles">
|
<Pager Items="@userroles">
|
||||||
@ -31,7 +36,7 @@ else
|
|||||||
<ActionLink Action="Edit" Parameters="@($"id=" + context.UserId.ToString())" ResourceKey="EditUser" />
|
<ActionLink Action="Edit" Parameters="@($"id=" + context.UserId.ToString())" ResourceKey="EditUser" />
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ActionDialog Header="Delete User" Message="@Localizer["Are You Sure You Wish To Delete {0}?", context.User.DisplayName]" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteUser(context))" ResourceKey="DeleteUser" />
|
<ActionDialog Header="Delete User" Message="@Localizer["Are You Sure You Wish To Delete {0}?", context.User.DisplayName]" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteUser(context))" Disabled="@(context.Role.Name == RoleNames.Host)" ResourceKey="DeleteUser" />
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ActionLink Action="Roles" Parameters="@($"id=" + context.UserId.ToString())" ResourceKey="Roles" />
|
<ActionLink Action="Roles" Parameters="@($"id=" + context.UserId.ToString())" ResourceKey="Roles" />
|
||||||
@ -57,19 +62,19 @@ else
|
|||||||
|
|
||||||
private List<UserRole> Search(string search)
|
private List<UserRole> Search(string search)
|
||||||
{
|
{
|
||||||
|
var results = allroles.Where(item => item.Role.Name == RoleNames.Registered || (item.Role.Name == RoleNames.Host && UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)));
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(_search))
|
if (string.IsNullOrEmpty(_search))
|
||||||
{
|
{
|
||||||
return allroles.Where(item => item.Role.Name == RoleNames.Registered).ToList();
|
results = results.Where(item =>
|
||||||
|
(
|
||||||
|
item.User.Username.Contains(search, StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
item.User.Email.Contains(search, StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
item.User.DisplayName.Contains(search, StringComparison.OrdinalIgnoreCase)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return allroles
|
return results.ToList();
|
||||||
.Where(item => item.Role.Name == RoleNames.Registered &&
|
|
||||||
(
|
|
||||||
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()
|
private async Task OnSearch()
|
||||||
|
@ -59,15 +59,16 @@ else
|
|||||||
<Pager Items="@userroles">
|
<Pager Items="@userroles">
|
||||||
<Header>
|
<Header>
|
||||||
<th>@Localizer["Roles"]</th>
|
<th>@Localizer["Roles"]</th>
|
||||||
|
<th>@Localizer["Effective"]</th>
|
||||||
|
<th>@Localizer["Expiry"]</th>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td>@context.Role.Name</td>
|
<td>@context.Role.Name</td>
|
||||||
|
<td>@context.EffectiveDate</td>
|
||||||
|
<td>@context.ExpiryDate</td>
|
||||||
<td>
|
<td>
|
||||||
@if (context.Role.Name != RoleNames.Registered)
|
<ActionDialog Header="Remove Role" Message="@Localizer["Are You Sure You Wish To Remove This User From The {0} Role?", context.Role.Name]" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@(context.Role.IsAutoAssigned || (context.Role.Name == RoleNames.Host && userid == PageState.User.UserId))" ResourceKey="DeleteUserRole" />
|
||||||
{
|
|
||||||
<button type="button" class="btn btn-danger" @onclick=@(async () => await DeleteUserRole(context.UserRoleId))>@Localizer["Delete"]</button>
|
|
||||||
}
|
|
||||||
</td>
|
</td>
|
||||||
</Row>
|
</Row>
|
||||||
</Pager>
|
</Pager>
|
||||||
@ -92,7 +93,15 @@ else
|
|||||||
userid = Int32.Parse(PageState.QueryString["id"]);
|
userid = Int32.Parse(PageState.QueryString["id"]);
|
||||||
User user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
User user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
||||||
name = user.DisplayName;
|
name = user.DisplayName;
|
||||||
roles = await RoleService.GetRolesAsync(PageState.Site.SiteId);
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
|
{
|
||||||
|
roles = await RoleService.GetRolesAsync(PageState.Site.SiteId, true);
|
||||||
|
roles = roles.Where(item => item.Name != RoleNames.Everyone).ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
roles = await RoleService.GetRolesAsync(PageState.Site.SiteId);
|
||||||
|
}
|
||||||
await GetUserRoles();
|
await GetUserRoles();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -171,9 +180,10 @@ else
|
|||||||
await UserRoleService.AddUserRoleAsync(userrole);
|
await UserRoleService.AddUserRoleAsync(userrole);
|
||||||
}
|
}
|
||||||
|
|
||||||
await GetUserRoles();
|
|
||||||
await logger.LogInformation("User Assigned To Role {UserRole}", userrole);
|
await logger.LogInformation("User Assigned To Role {UserRole}", userrole);
|
||||||
AddModuleMessage(Localizer["User Assigned To Role"], MessageType.Success);
|
AddModuleMessage(Localizer["User Assigned To Role"], MessageType.Success);
|
||||||
|
await GetUserRoles();
|
||||||
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -192,9 +202,10 @@ else
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await UserRoleService.DeleteUserRoleAsync(UserRoleId);
|
await UserRoleService.DeleteUserRoleAsync(UserRoleId);
|
||||||
await GetUserRoles();
|
|
||||||
await logger.LogInformation("User Removed From Role {UserRoleId}", UserRoleId);
|
await logger.LogInformation("User Removed From Role {UserRoleId}", UserRoleId);
|
||||||
AddModuleMessage(Localizer["User Removed From Role"], MessageType.Success);
|
AddModuleMessage(Localizer["User Removed From Role"], MessageType.Success);
|
||||||
|
await GetUserRoles();
|
||||||
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -79,6 +79,7 @@
|
|||||||
private string _filter = "*";
|
private string _filter = "*";
|
||||||
private bool _haseditpermission = false;
|
private bool _haseditpermission = false;
|
||||||
private string _image = string.Empty;
|
private string _image = string.Empty;
|
||||||
|
private File _file = null;
|
||||||
private string _guid;
|
private string _guid;
|
||||||
private string _message = string.Empty;
|
private string _message = string.Empty;
|
||||||
private MessageType _messagetype;
|
private MessageType _messagetype;
|
||||||
@ -199,6 +200,7 @@
|
|||||||
FolderId = int.Parse((string)e.Value);
|
FolderId = int.Parse((string)e.Value);
|
||||||
await GetFiles();
|
await GetFiles();
|
||||||
FileId = -1;
|
FileId = -1;
|
||||||
|
_file = null;
|
||||||
_image = string.Empty;
|
_image = string.Empty;
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
@ -223,21 +225,22 @@
|
|||||||
private async Task SetImage()
|
private async Task SetImage()
|
||||||
{
|
{
|
||||||
_image = string.Empty;
|
_image = string.Empty;
|
||||||
|
_file = null;
|
||||||
if (FileId != -1)
|
if (FileId != -1)
|
||||||
{
|
{
|
||||||
File file = await FileService.GetFileAsync(FileId);
|
_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=\"" + _file.Url + "\" 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() + "\" />";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -331,4 +334,5 @@
|
|||||||
|
|
||||||
public int GetFileId() => FileId;
|
public int GetFileId() => FileId;
|
||||||
|
|
||||||
|
public File GetFile() => _file;
|
||||||
}
|
}
|
||||||
|
@ -191,11 +191,11 @@
|
|||||||
_message = string.Empty;
|
_message = string.Empty;
|
||||||
if (_filemanagervisible)
|
if (_filemanagervisible)
|
||||||
{
|
{
|
||||||
var fileid = _fileManager.GetFileId();
|
var file = _fileManager.GetFile();
|
||||||
if (fileid != -1)
|
if (file != null)
|
||||||
{
|
{
|
||||||
var interop = new RichTextEditorInterop(JSRuntime);
|
var interop = new RichTextEditorInterop(JSRuntime);
|
||||||
await interop.InsertImage(_editorElement, ContentUrl(fileid));
|
await interop.InsertImage(_editorElement, file.Url, file.Name);
|
||||||
_filemanagervisible = false;
|
_filemanagervisible = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -105,13 +105,13 @@ namespace Oqtane.Modules.Controls
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task InsertImage(ElementReference quillElement, string imageUrl)
|
public Task InsertImage(ElementReference quillElement, string imageUrl, string altText)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_jsRuntime.InvokeAsync<object>(
|
_jsRuntime.InvokeAsync<object>(
|
||||||
"Oqtane.RichTextEditor.insertQuillImage",
|
"Oqtane.RichTextEditor.insertQuillImage",
|
||||||
quillElement, imageUrl);
|
quillElement, imageUrl, altText);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
@ -7,23 +7,20 @@
|
|||||||
<ul class="nav nav-tabs" role="tablist">
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
@foreach (TabPanel tabPanel in _tabPanels)
|
@foreach (TabPanel tabPanel in _tabPanels)
|
||||||
{
|
{
|
||||||
@if (IsAuthorized(tabPanel))
|
<li class="nav-item" @key="tabPanel.Name">
|
||||||
{
|
@if (tabPanel.Name == ActiveTab)
|
||||||
<li class="nav-item" @key="tabPanel.Name">
|
{
|
||||||
@if (tabPanel.Name == ActiveTab)
|
<a class="nav-link active" data-toggle="tab" href="#@tabPanel.Name" role="tab" @onclick:preventDefault="true">
|
||||||
{
|
@tabPanel.DisplayHeading()
|
||||||
<a class="nav-link active" data-toggle="tab" href="#@tabPanel.Name" role="tab" @onclick:preventDefault="true">
|
</a>
|
||||||
@tabPanel.DisplayHeading()
|
}
|
||||||
</a>
|
else
|
||||||
}
|
{
|
||||||
else
|
<a class="nav-link" data-toggle="tab" href="#@tabPanel.Name" role="tab" @onclick:preventDefault="true">
|
||||||
{
|
@tabPanel.DisplayHeading()
|
||||||
<a class="nav-link" data-toggle="tab" href="#@tabPanel.Name" role="tab" @onclick:preventDefault="true">
|
</a>
|
||||||
@tabPanel.DisplayHeading()
|
}
|
||||||
</a>
|
</li>
|
||||||
}
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
@ -43,6 +40,9 @@
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string ActiveTab { get; set; } // optional - defaults to first TabPanel if not specified. Can also be set using a "tab=" querystring parameter.
|
public string ActiveTab { get; set; } // optional - defaults to first TabPanel if not specified. Can also be set using a "tab=" querystring parameter.
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public bool Refresh { get; set; } // optional - used in scenarios where TabPanels are added/removed dynamically within a parent form. ActiveTab may need to be reset as well when this property is used.
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
if (PageState.QueryString.ContainsKey("tab"))
|
if (PageState.QueryString.ContainsKey("tab"))
|
||||||
@ -53,20 +53,23 @@
|
|||||||
|
|
||||||
protected override void OnParametersSet()
|
protected override void OnParametersSet()
|
||||||
{
|
{
|
||||||
_tabPanels = new List<TabPanel>();
|
if (_tabPanels == null || Refresh)
|
||||||
|
{
|
||||||
|
_tabPanels = new List<TabPanel>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AddTabPanel(TabPanel tabPanel)
|
internal void AddTabPanel(TabPanel tabPanel)
|
||||||
{
|
{
|
||||||
if (!_tabPanels.Exists(item => item.Name == tabPanel.Name))
|
if (!_tabPanels.Exists(item => item.Name == tabPanel.Name) && IsAuthorized(tabPanel))
|
||||||
{
|
{
|
||||||
_tabPanels.Add(tabPanel);
|
_tabPanels.Add(tabPanel);
|
||||||
if (string.IsNullOrEmpty(ActiveTab))
|
|
||||||
{
|
|
||||||
ActiveTab = tabPanel.Name;
|
|
||||||
}
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
if (string.IsNullOrEmpty(ActiveTab))
|
||||||
|
{
|
||||||
|
ActiveTab = tabPanel.Name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsAuthorized(TabPanel tabPanel)
|
private bool IsAuthorized(TabPanel tabPanel)
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
if (htmltext != null)
|
if (htmltext != null)
|
||||||
{
|
{
|
||||||
_content = htmltext.Content;
|
_content = htmltext.Content;
|
||||||
_content = _content.Replace(Constants.ContentUrl, "/" + PageState.Alias.AliasId.ToString() + Constants.ContentUrl);
|
_content = Utilities.FormatContent(_content, PageState.Alias, "render");
|
||||||
_createdby = htmltext.CreatedBy;
|
_createdby = htmltext.CreatedBy;
|
||||||
_createdon = htmltext.CreatedOn;
|
_createdon = htmltext.CreatedOn;
|
||||||
_modifiedby = htmltext.ModifiedBy;
|
_modifiedby = htmltext.ModifiedBy;
|
||||||
@ -72,7 +72,7 @@
|
|||||||
private async Task SaveContent()
|
private async Task SaveContent()
|
||||||
{
|
{
|
||||||
string content = await RichTextEditorHtml.GetHtml();
|
string content = await RichTextEditorHtml.GetHtml();
|
||||||
content = content.Replace("/" + PageState.Alias.AliasId.ToString() + Constants.ContentUrl, Constants.ContentUrl);
|
content = Utilities.FormatContent(content, PageState.Alias, "save");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
if (htmltext != null)
|
if (htmltext != null)
|
||||||
{
|
{
|
||||||
content = htmltext.Content;
|
content = htmltext.Content;
|
||||||
content = content.Replace(Constants.ContentUrl, "/" + PageState.Alias.AliasId.ToString() + Constants.ContentUrl);
|
content = Utilities.FormatContent(content, PageState.Alias, "render");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -8,9 +8,9 @@ namespace Oqtane.Modules.HtmlText
|
|||||||
{
|
{
|
||||||
Name = "HtmlText",
|
Name = "HtmlText",
|
||||||
Description = "Renders HTML or Text Content",
|
Description = "Renders HTML or Text Content",
|
||||||
Version = "1.0.0",
|
Version = "1.0.1",
|
||||||
ServerManagerType = "Oqtane.Modules.HtmlText.Manager.HtmlTextManager, Oqtane.Server",
|
ServerManagerType = "Oqtane.Modules.HtmlText.Manager.HtmlTextManager, Oqtane.Server",
|
||||||
ReleaseVersions = "1.0.0",
|
ReleaseVersions = "1.0.0,1.0.1",
|
||||||
SettingsType = "Oqtane.Modules.HtmlText.Settings, Oqtane.Client"
|
SettingsType = "Oqtane.Modules.HtmlText.Settings, Oqtane.Client"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Oqtane.Modules.HtmlText.Models;
|
|
||||||
using Oqtane.Services;
|
using Oqtane.Services;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
@ -10,34 +7,28 @@ namespace Oqtane.Modules.HtmlText.Services
|
|||||||
{
|
{
|
||||||
public class HtmlTextService : ServiceBase, IHtmlTextService, IService
|
public class HtmlTextService : ServiceBase, IHtmlTextService, IService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
public HtmlTextService(HttpClient http, SiteState siteState) : base(http, siteState) {}
|
||||||
|
|
||||||
public HtmlTextService(HttpClient http, SiteState siteState) : base(http)
|
private string ApiUrl => CreateApiUrl("HtmlText");
|
||||||
{
|
|
||||||
_siteState = siteState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string ApiUrl => CreateApiUrl(_siteState.Alias, "HtmlText");
|
|
||||||
|
|
||||||
public async Task<Models.HtmlText> GetHtmlTextAsync(int moduleId)
|
public async Task<Models.HtmlText> GetHtmlTextAsync(int moduleId)
|
||||||
{
|
{
|
||||||
var htmltext = await GetJsonAsync<List<Models.HtmlText>>(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", moduleId));
|
return await GetJsonAsync<Models.HtmlText>(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", EntityNames.Module, moduleId));
|
||||||
return htmltext.FirstOrDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AddHtmlTextAsync(Models.HtmlText htmlText)
|
public async Task AddHtmlTextAsync(Models.HtmlText htmlText)
|
||||||
{
|
{
|
||||||
await PostJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}", htmlText.ModuleId), htmlText);
|
await PostJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}", EntityNames.Module, htmlText.ModuleId), htmlText);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateHtmlTextAsync(Models.HtmlText htmlText)
|
public async Task UpdateHtmlTextAsync(Models.HtmlText htmlText)
|
||||||
{
|
{
|
||||||
await PutJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{htmlText.HtmlTextId}", htmlText.ModuleId), htmlText);
|
await PutJsonAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{htmlText.HtmlTextId}", EntityNames.Module, htmlText.ModuleId), htmlText);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteHtmlTextAsync(int moduleId)
|
public async Task DeleteHtmlTextAsync(int moduleId)
|
||||||
{
|
{
|
||||||
await DeleteAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", moduleId));
|
await DeleteAsync(CreateAuthorizationPolicyUrl($"{ApiUrl}/{moduleId}", EntityNames.Module, moduleId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,16 +5,17 @@
|
|||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RazorLangVersion>3.0</RazorLangVersion>
|
<RazorLangVersion>3.0</RazorLangVersion>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
<Version>2.0.2</Version>
|
<Version>2.1.0</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
<Description>Modular Application Framework for Blazor</Description>
|
<Description>Modular Application Framework for Blazor</Description>
|
||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://github.com/oqtane</RepositoryUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v2.1.0</PackageReleaseNotes>
|
||||||
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v2.0.2</PackageReleaseNotes>
|
|
||||||
<RootNamespace>Oqtane</RootNamespace>
|
<RootNamespace>Oqtane</RootNamespace>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
|
<BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
|
||||||
|
2
Oqtane.Client/Oqtane.Client.csproj.DotSettings
Normal file
2
Oqtane.Client/Oqtane.Client.csproj.DotSettings
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=services_005Cinterfaces/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
@ -12,7 +12,6 @@ using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
|||||||
using Microsoft.AspNetCore.Localization;
|
using Microsoft.AspNetCore.Localization;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
using Oqtane.Interfaces;
|
|
||||||
using Oqtane.Modules;
|
using Oqtane.Modules;
|
||||||
using Oqtane.Services;
|
using Oqtane.Services;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
@ -71,7 +70,7 @@ namespace Oqtane.Client
|
|||||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetName().Name).ToList();
|
var assemblies = AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetName().Name).ToList();
|
||||||
|
|
||||||
// get assemblies from server and load into client app domain
|
// get assemblies from server and load into client app domain
|
||||||
var zip = await http.GetByteArrayAsync($"/~/api/Installation/load");
|
var zip = await http.GetByteArrayAsync($"/api/Installation/load");
|
||||||
|
|
||||||
// asemblies and debug symbols are packaged in a zip file
|
// asemblies and debug symbols are packaged in a zip file
|
||||||
using (ZipArchive archive = new ZipArchive(new MemoryStream(zip)))
|
using (ZipArchive archive = new ZipArchive(new MemoryStream(zip)))
|
||||||
|
@ -1,49 +1,42 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.AspNetCore.Components.Authorization;
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Services;
|
using Oqtane.Security;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Providers
|
namespace Oqtane.Providers
|
||||||
{
|
{
|
||||||
public class IdentityAuthenticationStateProvider : AuthenticationStateProvider
|
public class IdentityAuthenticationStateProvider : AuthenticationStateProvider
|
||||||
{
|
{
|
||||||
private readonly NavigationManager _navigationManager;
|
|
||||||
private readonly SiteState _siteState;
|
|
||||||
private readonly IServiceProvider _serviceProvider;
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
private readonly NavigationManager _navigationManager;
|
||||||
public IdentityAuthenticationStateProvider(NavigationManager navigationManager, SiteState siteState, IServiceProvider serviceProvider)
|
|
||||||
|
public IdentityAuthenticationStateProvider(IServiceProvider serviceProvider, NavigationManager navigationManager)
|
||||||
{
|
{
|
||||||
_navigationManager = navigationManager;
|
|
||||||
_siteState = siteState;
|
|
||||||
_serviceProvider = serviceProvider;
|
_serviceProvider = serviceProvider;
|
||||||
|
_navigationManager = navigationManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
|
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
|
||||||
{
|
{
|
||||||
// get HttpClient lazily from IServiceProvider as you cannot use standard dependency injection due to the AuthenticationStateProvider being initialized prior to NavigationManager ( https://github.com/aspnet/AspNetCore/issues/11867 )
|
|
||||||
var http = _serviceProvider.GetRequiredService<HttpClient>();
|
|
||||||
string apiurl = "/~/api/User/authenticate";
|
|
||||||
User user = await http.GetFromJsonAsync<User>(apiurl);
|
|
||||||
|
|
||||||
ClaimsIdentity identity = new ClaimsIdentity();
|
ClaimsIdentity identity = new ClaimsIdentity();
|
||||||
|
|
||||||
|
// get HttpClient lazily from IServiceProvider as you cannot use standard dependency injection due to the AuthenticationStateProvider being initialized prior to NavigationManager(https://github.com/aspnet/AspNetCore/issues/11867 )
|
||||||
|
var http = _serviceProvider.GetRequiredService<HttpClient>();
|
||||||
|
var siteState = _serviceProvider.GetRequiredService<SiteState>();
|
||||||
|
User user = await http.GetFromJsonAsync<User>(Utilities.TenantUrl(siteState.Alias, "/api/User/authenticate"));
|
||||||
if (user.IsAuthenticated)
|
if (user.IsAuthenticated)
|
||||||
{
|
{
|
||||||
identity = new ClaimsIdentity("Identity.Application");
|
identity = UserSecurity.CreateClaimsIdentity(siteState.Alias, user);
|
||||||
identity.AddClaim(new Claim(ClaimTypes.Name, user.Username));
|
|
||||||
identity.AddClaim(new Claim(ClaimTypes.PrimarySid, user.UserId.ToString()));
|
|
||||||
foreach (string role in user.Roles.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
|
||||||
{
|
|
||||||
identity.AddClaim(new Claim(ClaimTypes.Role, role));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new AuthenticationState(new ClaimsPrincipal(identity));
|
return new AuthenticationState(new ClaimsPrincipal(identity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,55 +1,58 @@
|
|||||||
using Oqtane.Models;
|
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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using Oqtane.Documentation;
|
||||||
using System;
|
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc cref="IAliasService" />
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class AliasService : ServiceBase, IAliasService
|
public class AliasService : ServiceBase, IAliasService
|
||||||
{
|
{
|
||||||
|
|
||||||
private readonly SiteState _siteState;
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor - should only be used by Dependency Injection
|
||||||
|
/// </summary>
|
||||||
public AliasService(HttpClient http, SiteState siteState) : base(http)
|
public AliasService(HttpClient http, SiteState siteState) : base(http)
|
||||||
{
|
{
|
||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Alias");
|
private string ApiUrl => CreateApiUrl("Alias", _siteState.Alias);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public async Task<List<Alias>> GetAliasesAsync()
|
public async Task<List<Alias>> GetAliasesAsync()
|
||||||
{
|
{
|
||||||
List<Alias> aliases = await GetJsonAsync<List<Alias>>(Apiurl);
|
List<Alias> aliases = await GetJsonAsync<List<Alias>>(ApiUrl);
|
||||||
return aliases.OrderBy(item => item.Name).ToList();
|
return aliases.OrderBy(item => item.Name).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public async Task<Alias> GetAliasAsync(int aliasId)
|
public async Task<Alias> GetAliasAsync(int aliasId)
|
||||||
{
|
{
|
||||||
return await GetJsonAsync<Alias>($"{Apiurl}/{aliasId}");
|
return await GetJsonAsync<Alias>($"{ApiUrl}/{aliasId}");
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Alias> GetAliasAsync(string name, DateTime lastSyncDate)
|
|
||||||
{
|
|
||||||
name = (string.IsNullOrEmpty(name)) ? "~" : name;
|
|
||||||
return await GetJsonAsync<Alias>($"{Apiurl}/name/{WebUtility.UrlEncode(name)}?sync={lastSyncDate.ToString("yyyyMMddHHmmssfff")}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public async Task<Alias> AddAliasAsync(Alias alias)
|
public async Task<Alias> AddAliasAsync(Alias alias)
|
||||||
{
|
{
|
||||||
return await PostJsonAsync<Alias>(Apiurl, alias);
|
return await PostJsonAsync<Alias>(ApiUrl, alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public async Task<Alias> UpdateAliasAsync(Alias alias)
|
public async Task<Alias> UpdateAliasAsync(Alias alias)
|
||||||
{
|
{
|
||||||
return await PutJsonAsync<Alias>($"{Apiurl}/{alias.AliasId}", alias);
|
return await PutJsonAsync<Alias>($"{ApiUrl}/{alias.AliasId}", alias);
|
||||||
}
|
}
|
||||||
|
/// <inheritdoc />
|
||||||
public async Task DeleteAliasAsync(int aliasId)
|
public async Task DeleteAliasAsync(int aliasId)
|
||||||
{
|
{
|
||||||
await DeleteAsync($"{Apiurl}/{aliasId}");
|
await DeleteAsync($"{ApiUrl}/{aliasId}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
30
Oqtane.Client/Services/DatabaseService.cs
Normal file
30
Oqtane.Client/Services/DatabaseService.cs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
using Oqtane.Models;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Documentation;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
namespace Oqtane.Services
|
||||||
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
|
public class DatabaseService : ServiceBase, IDatabaseService
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
|
public DatabaseService(HttpClient http, SiteState siteState) : base(http)
|
||||||
|
{
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Apiurl => CreateApiUrl("Database", _siteState.Alias);
|
||||||
|
|
||||||
|
public async Task<List<Database>> GetDatabasesAsync()
|
||||||
|
{
|
||||||
|
List<Database> databases = await GetJsonAsync<List<Database>>(Apiurl);
|
||||||
|
return databases.OrderBy(item => item.Name).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,12 +4,14 @@ using System.Net.Http;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
using Oqtane.UI;
|
using Oqtane.UI;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class FileService : ServiceBase, IFileService
|
public class FileService : ServiceBase, IFileService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
private readonly SiteState _siteState;
|
||||||
@ -21,7 +23,7 @@ namespace Oqtane.Services
|
|||||||
_jsRuntime = jsRuntime;
|
_jsRuntime = jsRuntime;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "File");
|
private string Apiurl => CreateApiUrl("File", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<File>> GetFilesAsync(int folderId)
|
public async Task<List<File>> GetFilesAsync(int folderId)
|
||||||
{
|
{
|
||||||
|
@ -7,9 +7,11 @@ using Oqtane.Shared;
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using Oqtane.Documentation;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class FolderService : ServiceBase, IFolderService
|
public class FolderService : ServiceBase, IFolderService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
private readonly SiteState _siteState;
|
||||||
@ -19,7 +21,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ApiUrl => CreateApiUrl(_siteState.Alias, "Folder");
|
private string ApiUrl => CreateApiUrl("Folder", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<Folder>> GetFoldersAsync(int siteId)
|
public async Task<List<Folder>> GetFoldersAsync(int siteId)
|
||||||
{
|
{
|
||||||
|
@ -1,19 +1,34 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class InstallationService : ServiceBase, IInstallationService
|
public class InstallationService : ServiceBase, IInstallationService
|
||||||
{
|
{
|
||||||
public InstallationService(HttpClient http):base(http) { }
|
private readonly NavigationManager _navigationManager;
|
||||||
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
private string ApiUrl => CreateApiUrl("Installation");
|
public InstallationService(HttpClient http, NavigationManager navigationManager, SiteState siteState) : base(http)
|
||||||
|
{
|
||||||
|
_navigationManager = navigationManager;
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ApiUrl => CreateApiUrl("Installation", null, ControllerRoutes.ApiRoute); // tenant agnostic
|
||||||
|
|
||||||
public async Task<Installation> IsInstalled()
|
public async Task<Installation> IsInstalled()
|
||||||
{
|
{
|
||||||
return await GetJsonAsync<Installation>($"{ApiUrl}/installed");
|
// add antiforgerytoken header so that it is included on all HttpClient calls for the lifetime of the app
|
||||||
|
AddRequestHeader(Constants.AntiForgeryTokenHeaderName, _siteState.AntiForgeryToken);
|
||||||
|
var path = new Uri(_navigationManager.Uri).LocalPath.Substring(1);
|
||||||
|
return await GetJsonAsync<Installation>($"{ApiUrl}/installed/?path={WebUtility.UrlEncode(path)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Installation> Install(InstallConfig config)
|
public async Task<Installation> Install(InstallConfig config)
|
||||||
|
@ -1,22 +1,47 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Service to retrieve and store <see cref="Alias"/> information.
|
||||||
|
/// </summary>
|
||||||
public interface IAliasService
|
public interface IAliasService
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get all aliases in the system
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
Task<List<Alias>> GetAliasesAsync();
|
Task<List<Alias>> GetAliasesAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a single alias
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="aliasId">The <see cref="Oqtane.Models.Alias"/> ID, not to be confused with a <see cref="Oqtane.Models.Site"/> ID</param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<Alias> GetAliasAsync(int aliasId);
|
Task<Alias> GetAliasAsync(int aliasId);
|
||||||
|
|
||||||
Task<Alias> GetAliasAsync(string url, DateTime lastSyncDate);
|
/// <summary>
|
||||||
|
/// Save another <see cref="Oqtane.Models.Alias"/> in the DB. It must already contain all the information incl. <see cref="Oqtane.Models.Tenant"/> it belongs to.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="alias">An <see cref="Oqtane.Models.Alias"/> to add.</param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<Alias> AddAliasAsync(Alias alias);
|
Task<Alias> AddAliasAsync(Alias alias);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update an <see cref="Oqtane.Models.Alias"/> in the DB. Make sure the object is correctly filled, as it must update an existing record.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="alias">The <see cref="Oqtane.Models.Alias"/> to update.</param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<Alias> UpdateAliasAsync(Alias alias);
|
Task<Alias> UpdateAliasAsync(Alias alias);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove an <see cref="Oqtane.Models.Alias"/> from the DB.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="aliasId">The Alias ID, not to be confused with a Site ID.</param>
|
||||||
|
/// <returns></returns>
|
||||||
Task DeleteAliasAsync(int aliasId);
|
Task DeleteAliasAsync(int aliasId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
Oqtane.Client/Services/Interfaces/IDatabaseService.cs
Normal file
11
Oqtane.Client/Services/Interfaces/IDatabaseService.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using Oqtane.Models;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Oqtane.Services
|
||||||
|
{
|
||||||
|
public interface IDatabaseService
|
||||||
|
{
|
||||||
|
Task<List<Database>> GetDatabasesAsync();
|
||||||
|
}
|
||||||
|
}
|
@ -1,22 +1,106 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Service to get / create / upload / download files.
|
||||||
|
/// </summary>
|
||||||
public interface IFileService
|
public interface IFileService
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get all <see cref="File"/>s in the specified Folder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folderId">The folder ID</param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<List<File>> GetFilesAsync(int folderId);
|
Task<List<File>> GetFilesAsync(int folderId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all <see cref="File"/>s in the specified folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">
|
||||||
|
/// The folder path relative to where the files are stored.
|
||||||
|
/// TODO: todoc verify exactly from where the folder path must start
|
||||||
|
/// </param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<List<File>> GetFilesAsync(string folder);
|
Task<List<File>> GetFilesAsync(string folder);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get one <see cref="File"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<File> GetFileAsync(int fileId);
|
Task<File> GetFileAsync(int fileId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add / store a <see cref="File"/> record.
|
||||||
|
/// This does not contain the file contents.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="file"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<File> AddFileAsync(File file);
|
Task<File> AddFileAsync(File file);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update a <see cref="File"/> record.
|
||||||
|
/// Use this for rename a file or change some attributes.
|
||||||
|
/// This does not contain the file contents.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="file"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<File> UpdateFileAsync(File file);
|
Task<File> UpdateFileAsync(File file);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete a <see cref="File"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task DeleteFileAsync(int fileId);
|
Task DeleteFileAsync(int fileId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Upload a file from a URL to a <see cref="Folder"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="url"></param>
|
||||||
|
/// <param name="folderId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<File> UploadFileAsync(string url, int folderId);
|
Task<File> UploadFileAsync(string url, int folderId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Upload one or more files.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folderId">Target <see cref="Folder"/></param>
|
||||||
|
/// <param name="files">The files to upload, serialized as a string.</param>
|
||||||
|
/// <param name="fileUploadName">A task-identifier, to ensure communication about this upload.</param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<string> UploadFilesAsync(int folderId, string[] files, string fileUploadName);
|
Task<string> UploadFilesAsync(int folderId, string[] files, string fileUploadName);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Upload one or more files.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">Target <see cref="Folder"/>
|
||||||
|
/// TODO: todoc verify exactly from where the folder path must start
|
||||||
|
/// </param>
|
||||||
|
/// <param name="files">The files to upload, serialized as a string.</param>
|
||||||
|
/// <param name="fileUploadName">A task-identifier, to ensure communication about this upload.</param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<string> UploadFilesAsync(string folder, string[] files, string fileUploadName);
|
Task<string> UploadFilesAsync(string folder, string[] files, string fileUploadName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get / download a file (the body).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileId">Reference to a <see cref="File"/></param>
|
||||||
|
/// <returns>The bytes of the file</returns>
|
||||||
Task<byte[]> DownloadFileAsync(int fileId);
|
Task<byte[]> DownloadFileAsync(int fileId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieve a list of files from a <see cref="Site"/> and <see cref="Folder"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId">Reference to the <see cref="Site"/></param>
|
||||||
|
/// <param name="folderPath">Path of the folder
|
||||||
|
/// TODO: todoc verify exactly from where the folder path must start
|
||||||
|
/// </param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<List<File>> GetFilesAsync(int siteId, string folderPath);
|
Task<List<File>> GetFilesAsync(int siteId, string folderPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,68 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Service to get / create / modify <see cref="Folder"/> objects.
|
||||||
|
/// </summary>
|
||||||
public interface IFolderService
|
public interface IFolderService
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieve root folders of a <see cref="Site"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<List<Folder>> GetFoldersAsync(int siteId);
|
Task<List<Folder>> GetFoldersAsync(int siteId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieve the information of one <see cref="Folder"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folderId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<Folder> GetFolderAsync(int folderId);
|
Task<Folder> GetFolderAsync(int folderId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create one Folder using a <see cref="Folder"/> object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<Folder> AddFolderAsync(Folder folder);
|
Task<Folder> AddFolderAsync(Folder folder);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update the information about a <see cref="Folder"/>
|
||||||
|
/// Use this to rename the folder etc.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<Folder> UpdateFolderAsync(Folder folder);
|
Task<Folder> UpdateFolderAsync(Folder folder);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update the internal Folder-Order within the list of Folders.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId">Reference to the <see cref="Site"/></param>
|
||||||
|
/// <param name="folderId">Reference to a <see cref="Folder"/> for the security check</param>
|
||||||
|
/// <param name="parentId">Reference to the Parent <see cref="Folder"/> or null - this Folders children will be re-sorted.</param>
|
||||||
|
/// <returns></returns>
|
||||||
Task UpdateFolderOrderAsync(int siteId, int folderId, int? parentId);
|
Task UpdateFolderOrderAsync(int siteId, int folderId, int? parentId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete a <see cref="Folder"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folderId">Reference to a <see cref="Folder"/></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task DeleteFolderAsync(int folderId);
|
Task DeleteFolderAsync(int folderId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a <see cref="Folder"/> of a <see cref="Site"/> based on the path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId">Reference to the <see cref="Site"/></param>
|
||||||
|
/// <param name="folderPath">Path of the folder
|
||||||
|
/// TODO: todoc verify exactly from where the folder path must start
|
||||||
|
/// </param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<Folder> GetFolderAsync(int siteId, [NotNull]string folderPath);
|
Task<Folder> GetFolderAsync(int siteId, [NotNull]string folderPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,6 @@ namespace Oqtane.Services
|
|||||||
Task InstallModuleDefinitionsAsync();
|
Task InstallModuleDefinitionsAsync();
|
||||||
Task DeleteModuleDefinitionAsync(int moduleDefinitionId, int siteId);
|
Task DeleteModuleDefinitionAsync(int moduleDefinitionId, int siteId);
|
||||||
Task<ModuleDefinition> CreateModuleDefinitionAsync(ModuleDefinition moduleDefinition);
|
Task<ModuleDefinition> CreateModuleDefinitionAsync(ModuleDefinition moduleDefinition);
|
||||||
Task<List<string>> GetModuleDefinitionTemplatesAsync();
|
Task<List<Template>> GetModuleDefinitionTemplatesAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -8,5 +8,6 @@ namespace Oqtane.Services
|
|||||||
{
|
{
|
||||||
Task<List<Package>> GetPackagesAsync(string tag);
|
Task<List<Package>> GetPackagesAsync(string tag);
|
||||||
Task DownloadPackageAsync(string packageId, string version, string folder);
|
Task DownloadPackageAsync(string packageId, string version, string folder);
|
||||||
|
Task InstallPackagesAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,57 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Service to manage <see cref="Role"/>s on a <see cref="Site"/>
|
||||||
|
/// </summary>
|
||||||
public interface IRoleService
|
public interface IRoleService
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get all <see cref="Role"/>s of this <see cref="Site"/>.
|
||||||
|
///
|
||||||
|
/// Will exclude global roles which are for all sites. To get those as well, use the overload <see cref="GetRolesAsync(int, bool)"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId">ID-reference of a <see cref="Site"/></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<List<Role>> GetRolesAsync(int siteId);
|
Task<List<Role>> GetRolesAsync(int siteId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get roles of the <see cref="Site"/> and optionally include global Roles.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId">ID-reference to a <see cref="Site"/></param>
|
||||||
|
/// <param name="includeGlobalRoles">True if it should also include global roles. False will return the same data as just calling <see cref="GetRolesAsync(int)"/></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<List<Role>> GetRolesAsync(int siteId, bool includeGlobalRoles);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get one specific <see cref="Role"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="roleId">ID-reference of a <see cref="Role"/></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<Role> GetRoleAsync(int roleId);
|
Task<Role> GetRoleAsync(int roleId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add / save a new <see cref="Role"/> to the database.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="role"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<Role> AddRoleAsync(Role role);
|
Task<Role> AddRoleAsync(Role role);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update a <see cref="Role"/> in the database.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="role"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<Role> UpdateRoleAsync(Role role);
|
Task<Role> UpdateRoleAsync(Role role);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete / mark-as-deleted a <see cref="Role"/> in the database.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="roleId">ID-reference of a <see cref="Role"/></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task DeleteRoleAsync(int roleId);
|
Task DeleteRoleAsync(int roleId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -6,8 +7,6 @@ namespace Oqtane.Services
|
|||||||
{
|
{
|
||||||
public interface ISiteService
|
public interface ISiteService
|
||||||
{
|
{
|
||||||
void SetAlias(Alias alias);
|
|
||||||
|
|
||||||
Task<List<Site>> GetSitesAsync();
|
Task<List<Site>> GetSitesAsync();
|
||||||
|
|
||||||
Task<Site> GetSiteAsync(int siteId);
|
Task<Site> GetSiteAsync(int siteId);
|
||||||
@ -17,5 +16,8 @@ namespace Oqtane.Services
|
|||||||
Task<Site> UpdateSiteAsync(Site site);
|
Task<Site> UpdateSiteAsync(Site site);
|
||||||
|
|
||||||
Task DeleteSiteAsync(int siteId);
|
Task DeleteSiteAsync(int siteId);
|
||||||
|
|
||||||
|
[Obsolete("This method is deprecated.", false)]
|
||||||
|
void SetAlias(Alias alias);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
Oqtane.Client/Services/Interfaces/ISyncService.cs
Normal file
19
Oqtane.Client/Services/Interfaces/ISyncService.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using Oqtane.Models;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Oqtane.Services
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Service to retrieve <see cref="Sync"/> information.
|
||||||
|
/// </summary>
|
||||||
|
public interface ISyncService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get sync events
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lastSyncDate"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<Sync> GetSyncAsync(DateTime lastSyncDate);
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
@ -6,5 +6,7 @@ namespace Oqtane.Services
|
|||||||
public interface ISystemService
|
public interface ISystemService
|
||||||
{
|
{
|
||||||
Task<Dictionary<string, string>> GetSystemInfoAsync();
|
Task<Dictionary<string, string>> GetSystemInfoAsync();
|
||||||
|
|
||||||
|
Task UpdateSystemInfoAsync(Dictionary<string, string> settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,46 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Service to manage <see cref="Tenant"/>s on the Oqtane installation.
|
||||||
|
/// </summary>
|
||||||
public interface ITenantService
|
public interface ITenantService
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get all <see cref="Tenant"/>s
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
Task<List<Tenant>> GetTenantsAsync();
|
Task<List<Tenant>> GetTenantsAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get one specific <see cref="Tenant"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenantId">ID-reference of the <see cref="Tenant"/></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<Tenant> GetTenantAsync(int tenantId);
|
Task<Tenant> GetTenantAsync(int tenantId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add / save another <see cref="Tenant"/> to the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenant">A <see cref="Tenant"/> object containing the configuration</param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<Tenant> AddTenantAsync(Tenant tenant);
|
Task<Tenant> AddTenantAsync(Tenant tenant);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update the <see cref="Tenant"/> information in the database.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenant"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<Tenant> UpdateTenantAsync(Tenant tenant);
|
Task<Tenant> UpdateTenantAsync(Tenant tenant);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete / remove a <see cref="Tenant"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenantId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task DeleteTenantAsync(int tenantId);
|
Task DeleteTenantAsync(int tenantId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,6 @@ namespace Oqtane.Services
|
|||||||
Task InstallThemesAsync();
|
Task InstallThemesAsync();
|
||||||
Task DeleteThemeAsync(string themeName);
|
Task DeleteThemeAsync(string themeName);
|
||||||
Task<Theme> CreateThemeAsync(Theme theme);
|
Task<Theme> CreateThemeAsync(Theme theme);
|
||||||
Task<List<string>> GetThemeTemplatesAsync();
|
Task<List<Template>> GetThemeTemplatesAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,47 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Manage <see cref="Role"/>s assigned to a specific <see cref="User"/>
|
||||||
|
/// </summary>
|
||||||
public interface IUserRoleService
|
public interface IUserRoleService
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get all <see cref="UserRole"/>s on a <see cref="Site"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId">ID-reference to a <see cref="Site"/></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<List<UserRole>> GetUserRolesAsync(int siteId);
|
Task<List<UserRole>> GetUserRolesAsync(int siteId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get one specific <see cref="UserRole"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userRoleId">ID-reference to a <see cref="UserRole"/></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<UserRole> GetUserRoleAsync(int userRoleId);
|
Task<UserRole> GetUserRoleAsync(int userRoleId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Save a new <see cref="UserRole"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userRole"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<UserRole> AddUserRoleAsync(UserRole userRole);
|
Task<UserRole> AddUserRoleAsync(UserRole userRole);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update a <see cref="UserRole"/> in the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userRole"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<UserRole> UpdateUserRoleAsync(UserRole userRole);
|
Task<UserRole> UpdateUserRoleAsync(UserRole userRole);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete a <see cref="UserRole"/> in the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userRoleId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task DeleteUserRoleAsync(int userRoleId);
|
Task DeleteUserRoleAsync(int userRoleId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,26 +3,90 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Manage (get / update) user information
|
||||||
|
/// </summary>
|
||||||
public interface IUserService
|
public interface IUserService
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get a <see cref="User"/> of a specific site
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId">ID of a <see cref="User"/></param>
|
||||||
|
/// <param name="siteId">ID of a <see cref="Site"/></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<User> GetUserAsync(int userId, int siteId);
|
Task<User> GetUserAsync(int userId, int siteId);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a <see cref="User"/> of a specific site
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="username">Username / login of a <see cref="User"/></param>
|
||||||
|
/// <param name="siteId">ID of a <see cref="Site"/></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<User> GetUserAsync(string username, int siteId);
|
Task<User> GetUserAsync(string username, int siteId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Save a user to the Database.
|
||||||
|
/// The <see cref="User"/> object contains all the information incl. what <see cref="Site"/> it belongs to.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<User> AddUserAsync(User user);
|
Task<User> AddUserAsync(User user);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update an existing user in the database.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<User> UpdateUserAsync(User user);
|
Task<User> UpdateUserAsync(User user);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete / remove a user in the database
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId">ID-reference to the <see cref="User"/></param>
|
||||||
|
/// <param name="siteId">ID-reference to the <see cref="Site"/></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task DeleteUserAsync(int userId, int siteId);
|
Task DeleteUserAsync(int userId, int siteId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Will login the specified <see cref="User"/>.
|
||||||
|
///
|
||||||
|
/// Note that this will probably not be a real User, but a user object where the `Username` and `Password` have been filled.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">A <see cref="User"/> object which should have at least the <see cref="User.Username"/> and <see cref="User.Password"/> set.</param>
|
||||||
|
/// <param name="setCookie">Determines if the login should be stored in the cookie.</param>
|
||||||
|
/// <param name="isPersistent">Determines if the login should be persisted in the cookie for a long time.</param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<User> LoginUserAsync(User user, bool setCookie, bool isPersistent);
|
Task<User> LoginUserAsync(User user, bool setCookie, bool isPersistent);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Logout a <see cref="User"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task LogoutUserAsync(User user);
|
Task LogoutUserAsync(User user);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update e-mail verification status of a user.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user">The <see cref="User"/> we're verifying</param>
|
||||||
|
/// <param name="token">A Hash value in the URL which verifies this user got the e-mail (containing this token)</param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<User> VerifyEmailAsync(User user, string token);
|
Task<User> VerifyEmailAsync(User user, string token);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Trigger a forgot-password e-mail for this <see cref="User"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task ForgotPasswordAsync(User user);
|
Task ForgotPasswordAsync(User user);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reset the password of this <see cref="User"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="user"></param>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
Task<User> ResetPasswordAsync(User user, string token);
|
Task<User> ResetPasswordAsync(User user, string token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
using Oqtane.Models;
|
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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class JobLogService : ServiceBase, IJobLogService
|
public class JobLogService : ServiceBase, IJobLogService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
private readonly SiteState _siteState;
|
||||||
@ -16,7 +18,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "JobLog");
|
private string Apiurl => CreateApiUrl("JobLog", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<JobLog>> GetJobLogsAsync()
|
public async Task<List<JobLog>> GetJobLogsAsync()
|
||||||
{
|
{
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
using Oqtane.Models;
|
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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class JobService : ServiceBase, IJobService
|
public class JobService : ServiceBase, IJobService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
private readonly SiteState _siteState;
|
||||||
@ -16,7 +18,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Job");
|
private string Apiurl => CreateApiUrl("Job", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<Job>> GetJobsAsync()
|
public async Task<List<Job>> GetJobsAsync()
|
||||||
{
|
{
|
||||||
|
@ -2,11 +2,13 @@ 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 Oqtane.Documentation;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class LanguageService : ServiceBase, ILanguageService
|
public class LanguageService : ServiceBase, ILanguageService
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -17,7 +19,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Language");
|
private string Apiurl => CreateApiUrl("Language", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<Language>> GetLanguagesAsync(int siteId)
|
public async Task<List<Language>> GetLanguagesAsync(int siteId)
|
||||||
{
|
{
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class LocalizationService : ServiceBase, ILocalizationService
|
public class LocalizationService : ServiceBase, ILocalizationService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
private readonly SiteState _siteState;
|
||||||
@ -15,7 +17,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Localization");
|
private string Apiurl => CreateApiUrl("Localization", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<IEnumerable<Culture>> GetCulturesAsync() => await GetJsonAsync<IEnumerable<Culture>>(Apiurl);
|
public async Task<IEnumerable<Culture>> GetCulturesAsync() => await GetJsonAsync<IEnumerable<Culture>>(Apiurl);
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Enums;
|
using Oqtane.Enums;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class LogService : ServiceBase, ILogService
|
public class LogService : ServiceBase, ILogService
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -23,7 +25,7 @@ namespace Oqtane.Services
|
|||||||
_navigationManager = navigationManager;
|
_navigationManager = navigationManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Log");
|
private string Apiurl => CreateApiUrl("Log", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<Log>> GetLogsAsync(int siteId, string level, string function, int rows)
|
public async Task<List<Log>> GetLogsAsync(int siteId, string level, string function, int rows)
|
||||||
{
|
{
|
||||||
@ -49,7 +51,6 @@ namespace Oqtane.Services
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
base.Alias = alias;
|
|
||||||
log.SiteId = alias.SiteId;
|
log.SiteId = alias.SiteId;
|
||||||
}
|
}
|
||||||
log.PageId = pageId;
|
log.PageId = pageId;
|
||||||
|
@ -5,11 +5,13 @@ using System.Net.Http;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
using Oqtane.UI;
|
using Oqtane.UI;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class ModuleDefinitionService : ServiceBase, IModuleDefinitionService
|
public class ModuleDefinitionService : ServiceBase, IModuleDefinitionService
|
||||||
{
|
{
|
||||||
private readonly HttpClient _http;
|
private readonly HttpClient _http;
|
||||||
@ -21,7 +23,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "ModuleDefinition");
|
private string Apiurl => CreateApiUrl("ModuleDefinition", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<ModuleDefinition>> GetModuleDefinitionsAsync(int siteId)
|
public async Task<List<ModuleDefinition>> GetModuleDefinitionsAsync(int siteId)
|
||||||
{
|
{
|
||||||
@ -54,9 +56,9 @@ namespace Oqtane.Services
|
|||||||
return await PostJsonAsync($"{Apiurl}", moduleDefinition);
|
return await PostJsonAsync($"{Apiurl}", moduleDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<string>> GetModuleDefinitionTemplatesAsync()
|
public async Task<List<Template>> GetModuleDefinitionTemplatesAsync()
|
||||||
{
|
{
|
||||||
List<string> templates = await GetJsonAsync<List<string>>($"{Apiurl}/templates");
|
List<Template> templates = await GetJsonAsync<List<Template>>($"{Apiurl}/templates");
|
||||||
return templates;
|
return templates;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
using Oqtane.Models;
|
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 Oqtane.Documentation;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class ModuleService : ServiceBase, IModuleService
|
public class ModuleService : ServiceBase, IModuleService
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -17,7 +19,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Module");
|
private string Apiurl => CreateApiUrl("Module", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<Module>> GetModulesAsync(int siteId)
|
public async Task<List<Module>> GetModulesAsync(int siteId)
|
||||||
{
|
{
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Oqtane.Documentation;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class NotificationService : ServiceBase, INotificationService
|
public class NotificationService : ServiceBase, INotificationService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
private readonly SiteState _siteState;
|
||||||
@ -16,7 +18,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Notification");
|
private string Apiurl => CreateApiUrl("Notification", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<Notification>> GetNotificationsAsync(int siteId, string direction, int userId)
|
public async Task<List<Notification>> GetNotificationsAsync(int siteId, string direction, int userId)
|
||||||
{
|
{
|
||||||
|
@ -1,16 +1,23 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Oqtane.Documentation;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class PackageService : ServiceBase, IPackageService
|
public class PackageService : ServiceBase, IPackageService
|
||||||
{
|
{
|
||||||
public PackageService(HttpClient http) : base(http) { }
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("Package");
|
public PackageService(HttpClient http, SiteState siteState) : base(http)
|
||||||
|
{
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
private string Apiurl => CreateApiUrl("Package", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<Package>> GetPackagesAsync(string tag)
|
public async Task<List<Package>> GetPackagesAsync(string tag)
|
||||||
{
|
{
|
||||||
@ -22,5 +29,10 @@ namespace Oqtane.Services
|
|||||||
{
|
{
|
||||||
await PostAsync($"{Apiurl}?packageid={packageId}&version={version}&folder={folder}");
|
await PostAsync($"{Apiurl}?packageid={packageId}&version={version}&folder={folder}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task InstallPackagesAsync()
|
||||||
|
{
|
||||||
|
await GetJsonAsync<List<string>>($"{Apiurl}/install");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class PageModuleService : ServiceBase, IPageModuleService
|
public class PageModuleService : ServiceBase, IPageModuleService
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -15,7 +17,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "PageModule");
|
private string Apiurl => CreateApiUrl("PageModule", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<PageModule> GetPageModuleAsync(int pageModuleId)
|
public async Task<PageModule> GetPageModuleAsync(int pageModuleId)
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
@ -6,9 +6,11 @@ using System.Collections.Generic;
|
|||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
using System;
|
using System;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using Oqtane.Documentation;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class PageService : ServiceBase, IPageService
|
public class PageService : ServiceBase, IPageService
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -20,7 +22,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Page");
|
private string Apiurl => CreateApiUrl("Page", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<Page>> GetPagesAsync(int siteId)
|
public async Task<List<Page>> GetPagesAsync(int siteId)
|
||||||
{
|
{
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
using Oqtane.Models;
|
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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class ProfileService : ServiceBase, IProfileService
|
public class ProfileService : ServiceBase, IProfileService
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -17,7 +19,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Profile");
|
private string Apiurl => CreateApiUrl("Profile", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<Profile>> GetProfilesAsync(int siteId)
|
public async Task<List<Profile>> GetProfilesAsync(int siteId)
|
||||||
{
|
{
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
using Oqtane.Models;
|
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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class RoleService : ServiceBase, IRoleService
|
public class RoleService : ServiceBase, IRoleService
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -18,11 +20,16 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Role");
|
private string Apiurl => CreateApiUrl("Role", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<Role>> GetRolesAsync(int siteId)
|
public async Task<List<Role>> GetRolesAsync(int siteId)
|
||||||
{
|
{
|
||||||
List<Role> roles = await GetJsonAsync<List<Role>>($"{Apiurl}?siteid={siteId}");
|
return await GetRolesAsync(siteId, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<Role>> GetRolesAsync(int siteId, bool includeGlobalRoles)
|
||||||
|
{
|
||||||
|
List<Role> roles = await GetJsonAsync<List<Role>>($"{Apiurl}?siteid={siteId}&global={includeGlobalRoles}");
|
||||||
return roles.OrderBy(item => item.Name).ToList();
|
return roles.OrderBy(item => item.Name).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,20 +1,113 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class ServiceBase
|
public class ServiceBase
|
||||||
{
|
{
|
||||||
private readonly HttpClient _http;
|
private readonly HttpClient _http;
|
||||||
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
protected ServiceBase(HttpClient client)
|
protected ServiceBase(HttpClient client, SiteState siteState)
|
||||||
{
|
{
|
||||||
_http = client;
|
_http = client;
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
|
||||||
|
// should be used with new constructor
|
||||||
|
public string CreateApiUrl(string serviceName)
|
||||||
|
{
|
||||||
|
if (_siteState != null)
|
||||||
|
{
|
||||||
|
return CreateApiUrl(serviceName, _siteState.Alias, ControllerRoutes.ApiRoute);
|
||||||
|
}
|
||||||
|
else // legacy support (before 2.1.0)
|
||||||
|
{
|
||||||
|
return CreateApiUrl(serviceName, null, ControllerRoutes.Default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CreateApiUrl(string serviceName, Alias alias)
|
||||||
|
{
|
||||||
|
return CreateApiUrl(serviceName, alias, ControllerRoutes.ApiRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CreateApiUrl(string serviceName, Alias alias, string routeTemplate)
|
||||||
|
{
|
||||||
|
string apiurl = "/";
|
||||||
|
if (routeTemplate == ControllerRoutes.ApiRoute)
|
||||||
|
{
|
||||||
|
if (alias != null && !string.IsNullOrEmpty(alias.Path))
|
||||||
|
{
|
||||||
|
// include the alias path for multi-tenant context
|
||||||
|
apiurl += alias.Path + "/";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// legacy support for ControllerRoutes.Default
|
||||||
|
if (alias != null)
|
||||||
|
{
|
||||||
|
// include the alias for multi-tenant context
|
||||||
|
apiurl += $"{alias.AliasId}/";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// tenant agnostic
|
||||||
|
apiurl += "~/";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
apiurl += $"api/{serviceName}";
|
||||||
|
return apiurl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add authentityid parameters to url for custom authorization policy
|
||||||
|
public string CreateAuthorizationPolicyUrl(string url, string entityName, int entityId)
|
||||||
|
{
|
||||||
|
return CreateAuthorizationPolicyUrl(url, new Dictionary<string, int>() { { entityName, entityId } });
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CreateAuthorizationPolicyUrl(string url, Dictionary<string, int> authEntityId)
|
||||||
|
{
|
||||||
|
string qs = "";
|
||||||
|
foreach (KeyValuePair<string, int> kvp in authEntityId)
|
||||||
|
{
|
||||||
|
qs += (qs != "") ? "&" : "";
|
||||||
|
qs += "auth" + kvp.Key.ToLower() + "id=" + kvp.Value.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.Contains("?"))
|
||||||
|
{
|
||||||
|
return url + "&" + qs;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return url + "?" + qs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// note that HttpClient is registered as a Scoped(shared) service and therefore you should not use request headers whose value can vary over the lifetime of the service
|
||||||
|
protected void AddRequestHeader(string name, string value)
|
||||||
|
{
|
||||||
|
RemoveRequestHeader(name);
|
||||||
|
_http.DefaultRequestHeaders.Add(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void RemoveRequestHeader(string name)
|
||||||
|
{
|
||||||
|
if (_http.DefaultRequestHeaders.Contains(name))
|
||||||
|
{
|
||||||
|
_http.DefaultRequestHeaders.Remove(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task GetAsync(string uri)
|
protected async Task GetAsync(string uri)
|
||||||
@ -31,7 +124,6 @@ namespace Oqtane.Services
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
//TODO replace with logging
|
|
||||||
Console.WriteLine(e);
|
Console.WriteLine(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,8 +211,6 @@ namespace Oqtane.Services
|
|||||||
if (response.IsSuccessStatusCode) return true;
|
if (response.IsSuccessStatusCode) return true;
|
||||||
if (response.StatusCode != HttpStatusCode.NoContent && response.StatusCode != HttpStatusCode.NotFound)
|
if (response.StatusCode != HttpStatusCode.NoContent && response.StatusCode != HttpStatusCode.NotFound)
|
||||||
{
|
{
|
||||||
//TODO: Log errors here
|
|
||||||
|
|
||||||
Console.WriteLine($"Request: {response.RequestMessage.RequestUri}");
|
Console.WriteLine($"Request: {response.RequestMessage.RequestUri}");
|
||||||
Console.WriteLine($"Response status: {response.StatusCode} {response.ReasonPhrase}");
|
Console.WriteLine($"Response status: {response.StatusCode} {response.ReasonPhrase}");
|
||||||
}
|
}
|
||||||
@ -132,64 +222,28 @@ namespace Oqtane.Services
|
|||||||
{
|
{
|
||||||
var mediaType = content?.Headers.ContentType?.MediaType;
|
var mediaType = content?.Headers.ContentType?.MediaType;
|
||||||
return mediaType != null && mediaType.Equals("application/json", StringComparison.OrdinalIgnoreCase);
|
return mediaType != null && mediaType.Equals("application/json", StringComparison.OrdinalIgnoreCase);
|
||||||
//TODO Missing content JSON validation
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// create an API Url which is tenant agnostic ( for use during installation )
|
//[Obsolete("This constructor is obsolete. Use ServiceBase(HttpClient client, SiteState siteState) : base(http, siteState) {} instead.", false)]
|
||||||
public string CreateApiUrl(string serviceName)
|
// This constructor is obsolete. Use ServiceBase(HttpClient client, SiteState siteState) : base(http, siteState) {} instead.
|
||||||
|
protected ServiceBase(HttpClient client)
|
||||||
{
|
{
|
||||||
return CreateApiUrl(null, serviceName);
|
_http = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create an API Url which is tenant aware ( for use with repositories )
|
[Obsolete("This method is obsolete. Use CreateApiUrl(string serviceName, Alias alias) in conjunction with ControllerRoutes.ApiRoute in Controllers instead.", false)]
|
||||||
public string CreateApiUrl(Alias alias, string serviceName)
|
public string CreateApiUrl(Alias alias, string serviceName)
|
||||||
{
|
{
|
||||||
string apiurl = "/";
|
return CreateApiUrl(serviceName, alias, ControllerRoutes.Default);
|
||||||
|
|
||||||
if (Alias != null)
|
|
||||||
{
|
|
||||||
alias = Alias; // override the default alias ( for cross-tenant service calls )
|
|
||||||
}
|
|
||||||
|
|
||||||
if (alias != null)
|
|
||||||
{
|
|
||||||
// include the alias for multi-tenant context
|
|
||||||
apiurl += $"{alias.AliasId}/";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// tenant agnostic
|
|
||||||
apiurl += "~/";
|
|
||||||
}
|
|
||||||
|
|
||||||
apiurl += $"api/{serviceName}";
|
|
||||||
|
|
||||||
return apiurl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// can be used to override the default alias
|
[Obsolete("This property of ServiceBase is deprecated. Cross tenant service calls are not supported.", false)]
|
||||||
public Alias Alias { get; set; }
|
public Alias Alias { get; set; }
|
||||||
|
|
||||||
// add entityid parameter to url for custom authorization policy
|
[Obsolete("This method is obsolete. Use CreateApiUrl(string entityName, int entityId) instead.", false)]
|
||||||
public string CreateAuthorizationPolicyUrl(string url, int entityId)
|
public string CreateAuthorizationPolicyUrl(string url, int entityId)
|
||||||
{
|
{
|
||||||
string qs = "entityid=" + entityId.ToString();
|
return url + ((url.Contains("?")) ? "&" : "?") + "entityid=" + entityId.ToString();
|
||||||
|
|
||||||
if (url.Contains("?"))
|
|
||||||
{
|
|
||||||
return url + "&" + qs;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return url + "?" + qs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Obsolete("This method is obsolete. Use CreateApiUrl(Alias alias, string serviceName) instead.", false)]
|
|
||||||
public string CreateApiUrl(Alias alias, string absoluteUri, string serviceName)
|
|
||||||
{
|
|
||||||
// only retained for short term backward compatibility
|
|
||||||
return CreateApiUrl(alias, serviceName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using Oqtane.Models;
|
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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class SettingService : ServiceBase, ISettingService
|
public class SettingService : ServiceBase, ISettingService
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -18,7 +20,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Setting");
|
private string Apiurl => CreateApiUrl("Setting", _siteState.Alias);
|
||||||
public async Task<Dictionary<string, string>> GetTenantSettingsAsync()
|
public async Task<Dictionary<string, string>> GetTenantSettingsAsync()
|
||||||
{
|
{
|
||||||
return await GetSettingsAsync(EntityNames.Tenant, -1);
|
return await GetSettingsAsync(EntityNames.Tenant, -1);
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
using Oqtane.Models;
|
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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
using System;
|
||||||
|
using Oqtane.Documentation;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class SiteService : ServiceBase, ISiteService
|
public class SiteService : ServiceBase, ISiteService
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -18,12 +21,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Site");
|
private string Apiurl => CreateApiUrl("Site", _siteState.Alias);
|
||||||
|
|
||||||
public void SetAlias(Alias alias)
|
|
||||||
{
|
|
||||||
base.Alias = alias;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<List<Site>> GetSitesAsync()
|
public async Task<List<Site>> GetSitesAsync()
|
||||||
{
|
{
|
||||||
@ -50,5 +48,11 @@ namespace Oqtane.Services
|
|||||||
{
|
{
|
||||||
await DeleteAsync($"{Apiurl}/{siteId}");
|
await DeleteAsync($"{Apiurl}/{siteId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete("This method is deprecated.", false)]
|
||||||
|
public void SetAlias(Alias alias)
|
||||||
|
{
|
||||||
|
base.Alias = alias;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,23 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Shared;
|
||||||
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 Oqtane.Documentation;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class SiteTemplateService : ServiceBase, ISiteTemplateService
|
public class SiteTemplateService : ServiceBase, ISiteTemplateService
|
||||||
{
|
{
|
||||||
public SiteTemplateService(HttpClient http) : base(http) { }
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("SiteTemplate");
|
public SiteTemplateService(HttpClient http, SiteState siteState) : base(http)
|
||||||
|
{
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
private string Apiurl => CreateApiUrl("SiteTemplate", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<SiteTemplate>> GetSiteTemplatesAsync()
|
public async Task<List<SiteTemplate>> GetSiteTemplatesAsync()
|
||||||
{
|
{
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Oqtane.Documentation;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class SqlService : ServiceBase, ISqlService
|
public class SqlService : ServiceBase, ISqlService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
private readonly SiteState _siteState;
|
||||||
@ -14,7 +16,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Sql");
|
private string Apiurl => CreateApiUrl("Sql", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<SqlQuery> ExecuteQueryAsync(SqlQuery sqlquery)
|
public async Task<SqlQuery> ExecuteQueryAsync(SqlQuery sqlquery)
|
||||||
{
|
{
|
||||||
|
33
Oqtane.Client/Services/SyncService.cs
Normal file
33
Oqtane.Client/Services/SyncService.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using Oqtane.Models;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System;
|
||||||
|
using Oqtane.Documentation;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
namespace Oqtane.Services
|
||||||
|
{
|
||||||
|
/// <inheritdoc cref="ISyncService" />
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
|
public class SyncService : ServiceBase, ISyncService
|
||||||
|
{
|
||||||
|
|
||||||
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor - should only be used by Dependency Injection
|
||||||
|
/// </summary>
|
||||||
|
public SyncService(HttpClient http, SiteState siteState) : base(http)
|
||||||
|
{
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ApiUrl => CreateApiUrl("Sync", _siteState.Alias);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task<Sync> GetSyncAsync(DateTime lastSyncDate)
|
||||||
|
{
|
||||||
|
return await GetJsonAsync<Sync>($"{ApiUrl}/{lastSyncDate.ToString("yyyyMMddHHmmssfff")}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,31 @@
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Oqtane.Documentation;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class SystemService : ServiceBase, ISystemService
|
public class SystemService : ServiceBase, ISystemService
|
||||||
{
|
{
|
||||||
public SystemService(HttpClient http) : base(http) { }
|
private readonly SiteState _siteState;
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl("System");
|
public SystemService(HttpClient http, SiteState siteState) : base(http)
|
||||||
|
{
|
||||||
|
_siteState = siteState;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string Apiurl => CreateApiUrl("System", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<Dictionary<string, string>> GetSystemInfoAsync()
|
public async Task<Dictionary<string, string>> GetSystemInfoAsync()
|
||||||
{
|
{
|
||||||
return await GetJsonAsync<Dictionary<string, string>>(Apiurl);
|
return await GetJsonAsync<Dictionary<string, string>>(Apiurl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task UpdateSystemInfoAsync(Dictionary<string, string> settings)
|
||||||
|
{
|
||||||
|
await PostJsonAsync(Apiurl, settings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System.Net.Http;
|
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.Documentation;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class TenantService : ServiceBase, ITenantService
|
public class TenantService : ServiceBase, ITenantService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
private readonly SiteState _siteState;
|
||||||
@ -16,7 +18,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "Tenant");
|
private string Apiurl => CreateApiUrl("Tenant", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<Tenant>> GetTenantsAsync()
|
public async Task<List<Tenant>> GetTenantsAsync()
|
||||||
{
|
{
|
||||||
|
@ -2,11 +2,13 @@ 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 Oqtane.Documentation;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class ThemeService : ServiceBase, IThemeService
|
public class ThemeService : ServiceBase, IThemeService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
private readonly SiteState _siteState;
|
||||||
@ -16,7 +18,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string ApiUrl => CreateApiUrl(_siteState.Alias, "Theme");
|
private string ApiUrl => CreateApiUrl("Theme", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<Theme>> GetThemesAsync()
|
public async Task<List<Theme>> GetThemesAsync()
|
||||||
{
|
{
|
||||||
@ -56,9 +58,9 @@ namespace Oqtane.Services
|
|||||||
return await PostJsonAsync($"{ApiUrl}", theme);
|
return await PostJsonAsync($"{ApiUrl}", theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<string>> GetThemeTemplatesAsync()
|
public async Task<List<Template>> GetThemeTemplatesAsync()
|
||||||
{
|
{
|
||||||
List<string> templates = await GetJsonAsync<List<string>>($"{ApiUrl}/templates");
|
List<Template> templates = await GetJsonAsync<List<Template>>($"{ApiUrl}/templates");
|
||||||
return templates;
|
return templates;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class UserRoleService : ServiceBase, IUserRoleService
|
public class UserRoleService : ServiceBase, IUserRoleService
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -16,7 +18,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "UserRole");
|
private string Apiurl => CreateApiUrl("UserRole", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<List<UserRole>> GetUserRolesAsync(int siteId)
|
public async Task<List<UserRole>> GetUserRolesAsync(int siteId)
|
||||||
{
|
{
|
||||||
|
@ -2,9 +2,11 @@ using Oqtane.Shared;
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Oqtane.Documentation;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
|
[PrivateApi("Don't show in the documentation, as everything should use the Interface")]
|
||||||
public class UserService : ServiceBase, IUserService
|
public class UserService : ServiceBase, IUserService
|
||||||
{
|
{
|
||||||
private readonly SiteState _siteState;
|
private readonly SiteState _siteState;
|
||||||
@ -14,7 +16,7 @@ namespace Oqtane.Services
|
|||||||
_siteState = siteState;
|
_siteState = siteState;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string Apiurl => CreateApiUrl(_siteState.Alias, "User");
|
private string Apiurl => CreateApiUrl("User", _siteState.Alias);
|
||||||
|
|
||||||
public async Task<User> GetUserAsync(int userId, int siteId)
|
public async Task<User> GetUserAsync(int userId, int siteId)
|
||||||
{
|
{
|
||||||
|
@ -115,7 +115,7 @@ namespace Oqtane.Themes.Controls
|
|||||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, oldPane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, oldPane);
|
||||||
return url;
|
return NavigateUrl(url, "reload");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> DeleteModule(string url, PageModule pagemodule)
|
private async Task<string> DeleteModule(string url, PageModule pagemodule)
|
||||||
@ -123,7 +123,7 @@ namespace Oqtane.Themes.Controls
|
|||||||
pagemodule.IsDeleted = true;
|
pagemodule.IsDeleted = true;
|
||||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||||
return url;
|
return NavigateUrl(url, "reload");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> Settings(string url, PageModule pagemodule)
|
private async Task<string> Settings(string url, PageModule pagemodule)
|
||||||
@ -174,7 +174,7 @@ namespace Oqtane.Themes.Controls
|
|||||||
pagemodule.Order = 0;
|
pagemodule.Order = 0;
|
||||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||||
return s;
|
return NavigateUrl(s, "reload");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> MoveBottom(string s, PageModule pagemodule)
|
private async Task<string> MoveBottom(string s, PageModule pagemodule)
|
||||||
@ -182,7 +182,7 @@ namespace Oqtane.Themes.Controls
|
|||||||
pagemodule.Order = int.MaxValue;
|
pagemodule.Order = int.MaxValue;
|
||||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||||
return s;
|
return NavigateUrl(s, "reload");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> MoveUp(string s, PageModule pagemodule)
|
private async Task<string> MoveUp(string s, PageModule pagemodule)
|
||||||
@ -190,7 +190,7 @@ namespace Oqtane.Themes.Controls
|
|||||||
pagemodule.Order -= 3;
|
pagemodule.Order -= 3;
|
||||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||||
return s;
|
return NavigateUrl(s, "reload");
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> MoveDown(string s, PageModule pagemodule)
|
private async Task<string> MoveDown(string s, PageModule pagemodule)
|
||||||
@ -198,7 +198,7 @@ namespace Oqtane.Themes.Controls
|
|||||||
pagemodule.Order += 3;
|
pagemodule.Order += 3;
|
||||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||||
return s;
|
return NavigateUrl(s, "reload");
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ActionViewModel
|
public class ActionViewModel
|
||||||
|
@ -203,7 +203,7 @@
|
|||||||
<LanguageSwitcher />
|
<LanguageSwitcher />
|
||||||
}
|
}
|
||||||
|
|
||||||
@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 && UserSecurity.IsAuthorized(PageState.User, RoleNames.Registered)))
|
||||||
{
|
{
|
||||||
if (PageState.EditMode)
|
if (PageState.EditMode)
|
||||||
{
|
{
|
||||||
@ -369,7 +369,12 @@
|
|||||||
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;
|
|
||||||
|
// set module view permissions to page edit permissions
|
||||||
|
List<PermissionString> permissions = UserSecurity.GetPermissionStrings(PageState.Page.Permissions);
|
||||||
|
permissions.Find(p => p.PermissionName == PermissionNames.View).Permissions = permissions.Find(p => p.PermissionName == PermissionNames.Edit).Permissions;
|
||||||
|
module.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
||||||
|
|
||||||
module = await ModuleService.AddModuleAsync(module);
|
module = await ModuleService.AddModuleAsync(module);
|
||||||
ModuleId = module.ModuleId.ToString();
|
ModuleId = module.ModuleId.ToString();
|
||||||
}
|
}
|
||||||
@ -508,28 +513,7 @@
|
|||||||
{
|
{
|
||||||
List<PermissionString> permissions;
|
List<PermissionString> permissions;
|
||||||
|
|
||||||
if (action == "publish")
|
// publish/unpublish page
|
||||||
{
|
|
||||||
// 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(RoleNames.Everyone)) ids.Add(RoleNames.Everyone);
|
|
||||||
if (!ids.Contains(RoleNames.Registered)) ids.Add(RoleNames.Registered);
|
|
||||||
permissionstring.Permissions = string.Join(";", ids.ToArray());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
module.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
|
||||||
await ModuleService.UpdateModuleAsync(module);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// publish page
|
|
||||||
var page = PageState.Page;
|
var page = PageState.Page;
|
||||||
permissions = UserSecurity.GetPermissionStrings(page.Permissions);
|
permissions = UserSecurity.GetPermissionStrings(page.Permissions);
|
||||||
foreach (var permissionstring in permissions)
|
foreach (var permissionstring in permissions)
|
||||||
|
@ -27,6 +27,10 @@
|
|||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
var languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId);
|
var languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId);
|
||||||
|
var defaultCulture = CultureInfo.GetCultureInfo(Constants.DefaultCulture);
|
||||||
|
|
||||||
|
languages.Add(new Language { Code = defaultCulture.Name, Name = defaultCulture.DisplayName });
|
||||||
|
|
||||||
_supportedCultures = languages.Select(l => new Culture { Name = l.Code, DisplayName = l.Name });
|
_supportedCultures = languages.Select(l => new Culture { Name = l.Code, DisplayName = l.Name });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user