commit
6cd1b1ceaa
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018-2020 .NET Foundation
|
||||
Copyright (c) 2018-2021 .NET Foundation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -12,11 +12,13 @@
|
|||
{
|
||||
@if (string.IsNullOrEmpty(_installation.Message))
|
||||
{
|
||||
<CascadingAuthenticationState>
|
||||
<CascadingValue Value="@PageState">
|
||||
<SiteRouter OnStateChange="@ChangeState" />
|
||||
</CascadingValue>
|
||||
</CascadingAuthenticationState>
|
||||
<div style="@_display">
|
||||
<CascadingAuthenticationState>
|
||||
<CascadingValue Value="@PageState">
|
||||
<SiteRouter Runtime="@Runtime" RenderMode="@RenderMode" OnStateChange="@ChangeState" />
|
||||
</CascadingValue>
|
||||
</CascadingAuthenticationState>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -28,27 +30,50 @@
|
|||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string AntiForgeryToken { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Runtime { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string RenderMode { get; set; }
|
||||
|
||||
private bool _initialized = false;
|
||||
private string _display = "display: none;";
|
||||
private Installation _installation = new Installation { Success = false, Message = "" };
|
||||
|
||||
private PageState PageState { get; set; }
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
_installation = await InstallationService.IsInstalled();
|
||||
if (_installation.Alias != null)
|
||||
{
|
||||
SiteState.Alias = _installation.Alias;
|
||||
SiteState.AntiForgeryToken = AntiForgeryToken;
|
||||
}
|
||||
else
|
||||
{
|
||||
_installation.Message = "Site Not Configured Correctly - No Matching Alias Exists For Host Name";
|
||||
}
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender && !_initialized)
|
||||
if (firstRender)
|
||||
{
|
||||
var interop = new Interop(JSRuntime);
|
||||
SiteState.AntiForgeryToken = await interop.GetElementByName(Constants.RequestVerificationToken);
|
||||
_installation = await InstallationService.IsInstalled();
|
||||
if (_installation.Alias != null)
|
||||
if (string.IsNullOrEmpty(AntiForgeryToken))
|
||||
{
|
||||
SiteState.Alias = _installation.Alias;
|
||||
// parameter values are not set when running on WebAssembly (seems to be a .NET 5 bug) - need to retrieve using JSInterop
|
||||
var interop = new Interop(JSRuntime);
|
||||
AntiForgeryToken = await interop.GetElementByName(Constants.RequestVerificationToken);
|
||||
SiteState.AntiForgeryToken = AntiForgeryToken;
|
||||
Runtime = await interop.GetElementByName("app_runtime");
|
||||
RenderMode = await interop.GetElementByName("app_rendermode");
|
||||
}
|
||||
else
|
||||
{
|
||||
_installation.Message = "Site Not Configured Correctly - No Matching Alias Exists For Host Name";
|
||||
}
|
||||
_initialized = true;
|
||||
_display = "";
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,41 +1,30 @@
|
|||
@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>
|
||||
}
|
||||
}
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="server" HelpText="Enter the database server" ResourceKey="Server">Server:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="server" type="text" class="form-control" @bind="@_server" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="database" HelpText="Enter the name of the database" ResourceKey="Database">Database:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="database" type="text" class="form-control" @bind="@_database" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@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"}
|
||||
};
|
||||
private string _server = "(LocalDb)\\MSSQLLocalDB";
|
||||
private string _database = "Oqtane-" + DateTime.UtcNow.ToString("yyyyMMddHHmm");
|
||||
|
||||
public string GetConnectionString()
|
||||
{
|
||||
var connectionString = String.Empty;
|
||||
|
||||
var server = _connectionStringFields[0].Value;
|
||||
var database = _connectionStringFields[1].Value;
|
||||
|
||||
if (!String.IsNullOrEmpty(server) && !String.IsNullOrEmpty(database))
|
||||
if (!String.IsNullOrEmpty(_server) && !String.IsNullOrEmpty(_database))
|
||||
{
|
||||
connectionString = $"Data Source={server};AttachDbFilename=|DataDirectory|\\{database}.mdf;Initial Catalog={database};Integrated Security=SSPI;";
|
||||
connectionString = $"Data Source={_server};AttachDbFilename=|DataDirectory|\\{_database}.mdf;Initial Catalog={_database};Integrated Security=SSPI;";
|
||||
}
|
||||
|
||||
return connectionString;
|
||||
|
|
|
@ -1,54 +1,58 @@
|
|||
@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>
|
||||
}
|
||||
}
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="server" HelpText="Enter the database server" ResourceKey="Server">Server:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="server" type="text" class="form-control" @bind="@_server" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="port" HelpText="Enter the port used to connect to the server" ResourceKey="Port">Port:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="port" type="text" class="form-control" @bind="@_port" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="database" HelpText="Enter the name of the database" ResourceKey="Database">Database:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="database" type="text" class="form-control" @bind="@_database" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="uid" HelpText="Enter the username to use for the database" ResourceKey="Uid">User Id:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="uid" type="text" class="form-control" @bind="@_uid" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="pwd" HelpText="Enter the password to use for the database" ResourceKey="Pwd">Password:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="pwd" type="password" class="form-control" @bind="@_pwd" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@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"}
|
||||
};
|
||||
private string _server = "127.0.0.1";
|
||||
private string _port = "3306";
|
||||
private string _database = "Oqtane-" + DateTime.UtcNow.ToString("yyyyMMddHHmm");
|
||||
private string _uid = String.Empty;
|
||||
private string _pwd = String.Empty;
|
||||
|
||||
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))
|
||||
if (!String.IsNullOrEmpty(_server) && !String.IsNullOrEmpty(_database) && !String.IsNullOrEmpty(_uid) && !String.IsNullOrEmpty(_pwd))
|
||||
{
|
||||
connectionString = $"Server={server};Database={database};Uid={userId};Pwd={password};";
|
||||
connectionString = $"Server={_server};Database={_database};Uid={_uid};Pwd={_pwd};";
|
||||
}
|
||||
|
||||
if (!String.IsNullOrEmpty(port))
|
||||
if (!String.IsNullOrEmpty(_port))
|
||||
{
|
||||
connectionString += $"Port={port};";
|
||||
connectionString += $"Port={_port};";
|
||||
}
|
||||
|
||||
return connectionString;
|
||||
}
|
||||
}
|
|
@ -1,89 +1,76 @@
|
|||
@namespace Oqtane.Installer.Controls
|
||||
@implements Oqtane.Interfaces.IDatabaseConfigControl
|
||||
@inject IStringLocalizer<Installer> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
@inject IStringLocalizer<PostgreSQLConfig> 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>@SharedLocalizer["True"]</option>
|
||||
<option value="false">@SharedLocalizer["False"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="server" HelpText="Enter the database server" ResourceKey="Server">Server:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="server" type="text" class="form-control" @bind="@_server" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="port" HelpText="Enter the port used to connect to the server" ResourceKey="Port">Port:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="port" type="text" class="form-control" @bind="@_port" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="database" HelpText="Enter the name of the database" ResourceKey="Database">Database:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="database" type="text" class="form-control" @bind="@_database" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="security" HelpText="Select your security method" ResourceKey="Security">Security:</Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="security" class="form-select custom-select" @bind="@_security">
|
||||
<option value="integrated" selected>@Localizer["Integrated"]</option>
|
||||
<option value="custom">@Localizer["Custom"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@if (_security == "custom")
|
||||
{
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="uid" HelpText="Enter the username to use for the database" ResourceKey="Uid">User Id:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="uid" type="text" class="form-control" @bind="@_uid" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="pwd" HelpText="Enter the password to use for the database" ResourceKey="Pwd">Password:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="pwd" type="password" class="form-control" @bind="@_pwd" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@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" }
|
||||
};
|
||||
private string _server = "127.0.0.1";
|
||||
private string _port = "5432";
|
||||
private string _database = "Oqtane-" + DateTime.UtcNow.ToString("yyyyMMddHHmm");
|
||||
private string _security = "integrated";
|
||||
private string _uid = String.Empty;
|
||||
private string _pwd = String.Empty;
|
||||
|
||||
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))
|
||||
if (!String.IsNullOrEmpty(_server) && !String.IsNullOrEmpty(_database) && !String.IsNullOrEmpty(_port))
|
||||
{
|
||||
connectionString = $"Server={server};Port={port};Database={database};";
|
||||
connectionString = $"Server={_server};Port={_port};Database={_database};";
|
||||
}
|
||||
|
||||
if (integratedSecurity)
|
||||
if (_security == "integrated")
|
||||
{
|
||||
connectionString += "Integrated Security=true;";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!String.IsNullOrEmpty(userId) && !String.IsNullOrEmpty(password))
|
||||
if (!String.IsNullOrEmpty(_uid) && !String.IsNullOrEmpty(_pwd))
|
||||
{
|
||||
connectionString += $"User ID={userId};Password={password};";
|
||||
connectionString += $"User ID={_uid};Password={_pwd};";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1,87 +1,69 @@
|
|||
@namespace Oqtane.Installer.Controls
|
||||
@implements Oqtane.Interfaces.IDatabaseConfigControl
|
||||
@inject IStringLocalizer<Installer> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
@inject IStringLocalizer<SqlServerConfig> 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>@SharedLocalizer["True"]</option>
|
||||
<option value="false">@SharedLocalizer["False"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="server" HelpText="Enter the database server" ResourceKey="Server">Server:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="server" type="text" class="form-control" @bind="@_server" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="database" HelpText="Enter the name of the database" ResourceKey="Database">Database:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="database" type="text" class="form-control" @bind="@_database" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="security" HelpText="Select your security method" ResourceKey="Security">Security:</Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="security" class="form-select custom-select" @bind="@_security">
|
||||
<option value="integrated" selected>@Localizer["Integrated"]</option>
|
||||
<option value="custom">@Localizer["Custom"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@if (_security == "custom")
|
||||
{
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="uid" HelpText="Enter the username to use for the database" ResourceKey="Uid">User Id:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="uid" type="text" class="form-control" @bind="@_uid" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="pwd" HelpText="Enter the password to use for the database" ResourceKey="Pwd">Password:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="pwd" type="password" class="form-control" @bind="@_pwd" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@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" }
|
||||
};
|
||||
private string _server = String.Empty;
|
||||
private string _database = "Oqtane-" + DateTime.UtcNow.ToString("yyyyMMddHHmm");
|
||||
private string _security = "integrated";
|
||||
private string _uid = String.Empty;
|
||||
private string _pwd = String.Empty;
|
||||
|
||||
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))
|
||||
if (!String.IsNullOrEmpty(_server) && !String.IsNullOrEmpty(_database))
|
||||
{
|
||||
connectionString = $"Data Source={server};Initial Catalog={database};";
|
||||
connectionString = $"Data Source={_server};Initial Catalog={_database};";
|
||||
}
|
||||
|
||||
if (integratedSecurity)
|
||||
if (_security == "integrated")
|
||||
{
|
||||
connectionString += "Integrated Security=SSPI;";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!String.IsNullOrEmpty(userId) && !String.IsNullOrEmpty(password))
|
||||
if (!String.IsNullOrEmpty(_uid) && !String.IsNullOrEmpty(_pwd))
|
||||
{
|
||||
connectionString += $"User ID={userId};Password={password};";
|
||||
connectionString += $"User ID={_uid};Password={_pwd};";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -91,5 +73,4 @@
|
|||
|
||||
return connectionString;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,39 +1,23 @@
|
|||
@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>
|
||||
}
|
||||
}
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="server" HelpText="Enter the file name to use for the database" ResourceKey="Server">File Name:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="server" type="text" class="form-control" @bind="@_server" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@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"}
|
||||
};
|
||||
private string _server = "Oqtane-" + DateTime.UtcNow.ToString("yyyyMMddHHmm") + ".db";
|
||||
|
||||
public string GetConnectionString()
|
||||
{
|
||||
var connectionstring = String.Empty;
|
||||
|
||||
var server = _connectionStringFields[0].Value;
|
||||
|
||||
if (!String.IsNullOrEmpty(server))
|
||||
if (!String.IsNullOrEmpty(_server))
|
||||
{
|
||||
connectionstring = $"Data Source={server};";
|
||||
connectionstring = $"Data Source={_server};";
|
||||
}
|
||||
|
||||
return connectionstring;
|
||||
|
|
|
@ -20,78 +20,64 @@
|
|||
<div class="row justify-content-center">
|
||||
<div class="col text-center">
|
||||
<h2>@Localizer["DatabaseConfig"]</h2><br />
|
||||
<table class="form-group" cellpadding="4" cellspacing="4" style="margin: auto;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="databasetype" HelpText="Select the type of database you wish to create" ResourceKey="DatabaseType">Database Type:</Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="databasetype" class="custom-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))">
|
||||
@if (_databases != null)
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="databasetype" HelpText="Select the type of database you wish to use" ResourceKey="DatabaseType">Database:</Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="databasetype" class="form-select custom-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))">
|
||||
@if (_databases != null)
|
||||
{
|
||||
foreach (var database in _databases)
|
||||
{
|
||||
foreach (var database in _databases)
|
||||
if (database.IsDefault)
|
||||
{
|
||||
if (database.IsDefault)
|
||||
{
|
||||
<option value="@database.Name" selected>@Localizer[@database.Name]</option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="@database.Name">@Localizer[@database.Name]</option>
|
||||
}
|
||||
<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;
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@{
|
||||
if (_databaseConfigType != null)
|
||||
{
|
||||
@DatabaseConfigComponent;
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col text-center">
|
||||
<h2>@Localizer["ApplicationAdmin"]</h2><br />
|
||||
<table class="form-group" cellpadding="4" cellspacing="4" style="margin: auto;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="username" HelpText="The username of the host user account ( this is not customizable )" ResourceKey="Username">Username:</Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="username" type="text" class="form-control" @bind="@_hostUsername" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="password" HelpText="Provide the password for the host user account" ResourceKey="Password">Password:</Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="password" type="password" class="form-control" @bind="@_hostPassword" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="confirm" HelpText="Please confirm the password entered above by entering it again" ResourceKey="Confirm">Confirm:</Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="confirm" type="password" class="form-control" @bind="@_confirmPassword" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="email" HelpText="Provide the email address for the host user account" ResourceKey="Email">Email:</Label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" class="form-control" @bind="@_hostEmail" />
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="username" HelpText="Provide a username for the primary user accountt" ResourceKey="Username">Username:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="username" type="text" class="form-control" @bind="@_hostUsername" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="password" HelpText="Provide a password for the primary user account" ResourceKey="Password">Password:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="password" type="password" class="form-control" @bind="@_hostPassword" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="confirm" HelpText="Please confirm the password entered above by entering it again" ResourceKey="Confirm">Confirm:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="confirm" type="password" class="form-control" @bind="@_confirmPassword" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="email" HelpText="Provide the email address for the host user account" ResourceKey="Email">Email:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control" @bind="@_hostEmail" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="app-rule" />
|
||||
|
@ -116,7 +102,7 @@
|
|||
private object _databaseConfig;
|
||||
private RenderFragment DatabaseConfigComponent { get; set; }
|
||||
|
||||
private string _hostUsername = UserNames.Host;
|
||||
private string _hostUsername = string.Empty;
|
||||
private string _hostPassword = string.Empty;
|
||||
private string _confirmPassword = string.Empty;
|
||||
private string _hostEmail = string.Empty;
|
||||
|
@ -164,7 +150,8 @@
|
|||
if (firstRender)
|
||||
{
|
||||
var interop = new Interop(JSRuntime);
|
||||
await interop.IncludeLink("app-stylesheet", "stylesheet", "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css", "text/css", "sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T", "anonymous", "");
|
||||
await interop.IncludeLink("", "stylesheet", "https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css", "text/css", "sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC", "anonymous", "");
|
||||
await interop.IncludeScript("", "https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js", "sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM", "anonymous", "", "head", "");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,7 +163,7 @@
|
|||
connectionString = databaseConfigControl.GetConnectionString();
|
||||
}
|
||||
|
||||
if (connectionString != "" && _hostUsername != "" && _hostPassword.Length >= 6 && _hostPassword == _confirmPassword && _hostEmail != "" && _hostEmail.Contains("@"))
|
||||
if (connectionString != "" && !string.IsNullOrEmpty(_hostUsername) && _hostPassword.Length >= 6 && _hostPassword == _confirmPassword && !string.IsNullOrEmpty(_hostEmail) && _hostEmail.Contains("@"))
|
||||
{
|
||||
_loadingDisplay = "";
|
||||
StateHasChanged();
|
||||
|
@ -190,9 +177,10 @@
|
|||
DatabaseType = database.DBType,
|
||||
ConnectionString = connectionString,
|
||||
Aliases = uri.Authority,
|
||||
HostEmail = _hostEmail,
|
||||
HostUsername = _hostUsername,
|
||||
HostPassword = _hostPassword,
|
||||
HostName = UserNames.Host,
|
||||
HostEmail = _hostEmail,
|
||||
HostName = _hostUsername,
|
||||
TenantName = TenantNames.Master,
|
||||
IsNewTenant = true,
|
||||
SiteName = Constants.DefaultSite,
|
||||
|
@ -215,5 +203,4 @@
|
|||
_message = Localizer["Message.Require.DbInfo"];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,55 +9,60 @@
|
|||
|
||||
<TabStrip>
|
||||
<TabPanel Name="Upload" Heading="Upload Files" ResourceKey="UploadFiles">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="upload" HelpText="Upload the file you want" ResourceKey="Upload">Upload: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="upload" HelpText="Upload the file you want" ResourceKey="Upload">Upload: </Label>
|
||||
<div class="col-sm-9">
|
||||
<FileManager UploadMultiple="true" ShowFiles="false" FolderId="@_folderId" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
</TabPanel>
|
||||
<TabPanel Name="Download" Heading="Download Files" ResourceKey="DownloadFiles">
|
||||
@if (_folders != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="url" HelpText="Enter the url of the file you wish to download" ResourceKey="Url">Url: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="url" class="form-control" @bind="@url" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="folder" HelpText="Select the folder to save the file in" ResourceKey="Folder">Folder: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="folder" class="form-select" @bind="@_folderId">
|
||||
<option value="-1"><@Localizer["Folder.Select"]></option>
|
||||
@foreach (Folder folder in _folders)
|
||||
{
|
||||
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="Download">@SharedLocalizer["Download"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="url" HelpText="Enter the url of the file you wish to download" ResourceKey="Url">Url: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="url" class="form-control" @bind="@_url" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="folder" HelpText="Select the folder to save the file in" ResourceKey="Folder">Folder: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="folder" class="form-select" @bind="@_folderId" required>
|
||||
<option value="-1"><@Localizer["Folder.Select"]></option>
|
||||
@foreach (Folder folder in _folders)
|
||||
{
|
||||
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="name" HelpText="Enter the name of the file being downloaded" ResourceKey="Name">Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="name" class="form-control" @bind="@_name" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-success" @onclick="Download">@SharedLocalizer["Download"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
</form>
|
||||
}
|
||||
</TabPanel>
|
||||
</TabStrip>
|
||||
|
||||
@code {
|
||||
private string url = string.Empty;
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
private string _url = string.Empty;
|
||||
private List<Folder> _folders;
|
||||
private int _folderId = -1;
|
||||
private string _name = "";
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||
|
||||
|
@ -73,37 +78,48 @@
|
|||
|
||||
private async Task Download()
|
||||
{
|
||||
if (url == string.Empty || _folderId == -1)
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Required.UrlFolder"], MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
if (_url == string.Empty || _folderId == -1)
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Required.UrlFolder"], MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var filename = url.Substring(url.LastIndexOf("/", StringComparison.Ordinal) + 1);
|
||||
if (string.IsNullOrEmpty(_name))
|
||||
{
|
||||
_name = _url.Substring(_url.LastIndexOf("/", StringComparison.Ordinal) + 1);
|
||||
}
|
||||
|
||||
if (!Constants.UploadableFiles.Split(',')
|
||||
.Contains(Path.GetExtension(filename).ToLower().Replace(".", "")))
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Download.InvalidExtension"], MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
if (!Constants.UploadableFiles.Split(',').Contains(Path.GetExtension(_name).ToLower().Replace(".", "")))
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Download.InvalidExtension"], MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!filename.IsPathOrFileValid())
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Required.UrlName"], MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
if (!_name.IsPathOrFileValid())
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Required.UrlName"], MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await FileService.UploadFileAsync(url, _folderId);
|
||||
await logger.LogInformation("File Downloaded Successfully From Url {Url}", url);
|
||||
AddModuleMessage(Localizer["Success.Download.File"], MessageType.Success);
|
||||
try
|
||||
{
|
||||
await FileService.UploadFileAsync(_url, _folderId, _name);
|
||||
await logger.LogInformation("File Downloaded Successfully From Url {Url}", _url);
|
||||
AddModuleMessage(Localizer["Success.Download.File"], MessageType.Success);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Downloading File From Url {Url} {Error}", _url, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Download.InvalidUrl"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
await logger.LogError(ex, "Error Downloading File From Url {Url} {Error}", url, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Download.InvalidUrl"], MessageType.Error);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,49 +8,54 @@
|
|||
|
||||
@if (_folders != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label for="name" HelpText="The name of the file" ResourceKey="Name">Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="name" class="form-control" @bind="@_name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="parent" HelpText="The folder where the file is located" ResourceKey="Folder">Folder: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="parent" class="form-select" @bind="@_folderId">
|
||||
@foreach (Folder folder in _folders)
|
||||
{
|
||||
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label for="size" HelpText="The size of the file (in bytes)" ResourceKey="Size">Size: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="size" class="form-control" @bind="@_size" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveFile">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@_createdBy" CreatedOn="@_createdOn" ModifiedBy="@_modifiedBy" ModifiedOn="@_modifiedOn"></AuditInfo>
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="name" HelpText="The name of the file" ResourceKey="Name">Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="name" class="form-control" @bind="@_name" maxlength="50" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="parent" HelpText="The folder where the file is located" ResourceKey="Folder">Folder: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="parent" class="form-select" @bind="@_folderId" required>
|
||||
@foreach (Folder folder in _folders)
|
||||
{
|
||||
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="description" HelpText="A description of the file. This can be used as a caption for image files." ResourceKey="Description">Description: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="description" class="form-control" @bind="@_description" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="size" HelpText="The size of the file (in bytes)" ResourceKey="Size">Size: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="size" class="form-control" @bind="@_size" readonly />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveFile">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@_createdBy" CreatedOn="@_createdOn" ModifiedBy="@_modifiedBy" ModifiedOn="@_modifiedOn"></AuditInfo>
|
||||
</form>
|
||||
}
|
||||
|
||||
@code {
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
private int _fileId = -1;
|
||||
private string _name;
|
||||
private List<Folder> _folders;
|
||||
private int _folderId = -1;
|
||||
private string _description = string.Empty;
|
||||
private int _size;
|
||||
private string _createdBy;
|
||||
private DateTime _createdOn;
|
||||
|
@ -72,6 +77,7 @@
|
|||
{
|
||||
_name = file.Name;
|
||||
_folderId = file.FolderId;
|
||||
_description = file.Description;
|
||||
_size = file.Size;
|
||||
_createdBy = file.CreatedBy;
|
||||
_createdOn = file.CreatedOn;
|
||||
|
@ -88,26 +94,36 @@
|
|||
|
||||
private async Task SaveFile()
|
||||
{
|
||||
try
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
if (_name.IsPathOrFileValid())
|
||||
try
|
||||
{
|
||||
File file = await FileService.GetFileAsync(_fileId);
|
||||
file.Name = _name;
|
||||
file.FolderId = _folderId;
|
||||
file = await FileService.UpdateFileAsync(file);
|
||||
await logger.LogInformation("File Saved {File}", file);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
if (_name.IsPathOrFileValid())
|
||||
{
|
||||
File file = await FileService.GetFileAsync(_fileId);
|
||||
file.Name = _name;
|
||||
file.FolderId = _folderId;
|
||||
file.Description = _description;
|
||||
file = await FileService.UpdateFileAsync(file);
|
||||
await logger.LogInformation("File Saved {File}", file);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.File.InvalidName"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.File.InvalidName"], MessageType.Warning);
|
||||
await logger.LogError(ex, "Error Saving File {FileId} {Error}", _fileId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.File.Save"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving File {FileId} {Error}", _fileId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.File.Save"], MessageType.Error);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,57 +8,67 @@
|
|||
|
||||
@if (_folders != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="parent" HelpText="Select the parent folder" ResourceKey="Parent">Parent: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="parent" class="form-select" @bind="@_parentId">
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="parent" HelpText="Select the parent folder" ResourceKey="Parent">Parent: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="parent" class="form-select" @bind="@_parentId" required>
|
||||
@if (PageState.QueryString.ContainsKey("id"))
|
||||
{
|
||||
<option value="-1"><@Localizer["NoParent"]></option>
|
||||
}
|
||||
@foreach (Folder folder in _folders)
|
||||
{
|
||||
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="name" HelpText="Enter the folder name" ResourceKey="Name">Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="name" class="form-control" @bind="@_name" maxlength="256" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="type" HelpText="Select the folder type. Private folders are only accessible by authorized users. Public folders can be accessed by all users" ResourceKey="Type">Type: </Label>
|
||||
<div class="col-sm-9">
|
||||
@if (PageState.QueryString.ContainsKey("id"))
|
||||
{
|
||||
<option value="-1"><@Localizer["NoParent"]></option>
|
||||
<input id="type" class="form-control" readonly @bind="@_type" />
|
||||
}
|
||||
@foreach (Folder folder in _folders)
|
||||
else
|
||||
{
|
||||
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
|
||||
<select id="type" class="form-select" @bind="@_type" required>
|
||||
<option value="@FolderTypes.Private">@Localizer[FolderTypes.Private]</option>
|
||||
<option value="@FolderTypes.Public">@Localizer[FolderTypes.Public]</option>
|
||||
</select>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label for="name" HelpText="Enter the folder name" ResourceKey="Name">Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="name" class="form-control" @bind="@_name" />
|
||||
</td>
|
||||
</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-select" @bind="@_type">
|
||||
<option value="@FolderTypes.Private">@Localizer[FolderTypes.Private]</option>
|
||||
<option value="@FolderTypes.Public">@Localizer[FolderTypes.Public]</option>
|
||||
</select>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" align="center">
|
||||
<Label For="permissions" HelpText="Select the permissions you want for the folder" ResourceKey="Permissions">Permissions: </Label>
|
||||
<PermissionGrid EntityName="@EntityNames.Folder" PermissionNames="@(PermissionNames.Browse + "," + PermissionNames.View + "," + PermissionNames.Edit)" Permissions="@_permissions" @ref="_permissionGrid" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="imagesizes" HelpText="Enter a list of image sizes which can be generated dynamically from uploaded images (ie. 200x200,x200,200x)" ResourceKey="ImageSizes">Image Sizes: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="imagesizes" class="form-control" @bind="@_imagesizes" maxlength="512" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="capacity" HelpText="Enter the maximum folder capacity (in megabytes). Specify zero if the capacity is unlimited." ResourceKey="Capacity">Capacity: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="capacity" class="form-control" @bind="@_capacity" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<div class="col-sm-12">
|
||||
<Label Class="col-sm-3" For="permissions" HelpText="Select the permissions you want for the folder" ResourceKey="Permissions">Permissions: </Label>
|
||||
<PermissionGrid EntityName="@EntityNames.Folder" PermissionNames="@(PermissionNames.Browse + "," + PermissionNames.View + "," + PermissionNames.Edit)" Permissions="@_permissions" @ref="_permissionGrid" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@if (!_isSystem)
|
||||
{
|
||||
<button type="button" class="btn btn-success" @onclick="SaveFolder">@SharedLocalizer["Save"]</button>
|
||||
|
@ -79,11 +89,15 @@
|
|||
}
|
||||
|
||||
@code {
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
private List<Folder> _folders;
|
||||
private int _folderId = -1;
|
||||
private int _parentId = -1;
|
||||
private string _name;
|
||||
private string _type = FolderTypes.Private;
|
||||
private string _imagesizes = string.Empty;
|
||||
private string _capacity = "0";
|
||||
private bool _isSystem;
|
||||
private string _permissions = string.Empty;
|
||||
private string _createdBy;
|
||||
|
@ -114,6 +128,8 @@
|
|||
_parentId = folder.ParentId ?? -1;
|
||||
_name = folder.Name;
|
||||
_type = folder.Type;
|
||||
_imagesizes = folder.ImageSizes;
|
||||
_capacity = folder.Capacity.ToString();
|
||||
_isSystem = folder.IsSystem;
|
||||
_permissions = folder.Permissions;
|
||||
_createdBy = folder.CreatedBy;
|
||||
|
@ -125,7 +141,6 @@
|
|||
else
|
||||
{
|
||||
_parentId = _folders[0].FolderId;
|
||||
_permissions = string.Empty;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -137,70 +152,81 @@
|
|||
|
||||
private async Task SaveFolder()
|
||||
{
|
||||
if (_name == string.Empty || _parentId == -1)
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Required.FolderParent"], MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_name.IsPathOrFileValid())
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Folder.InvalidName"], MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Folder folder;
|
||||
if (_folderId != -1)
|
||||
if (_name == string.Empty || _parentId == -1)
|
||||
{
|
||||
folder = await FolderService.GetFolderAsync(_folderId);
|
||||
}
|
||||
else
|
||||
{
|
||||
folder = new Folder();
|
||||
AddModuleMessage(Localizer["Message.Required.FolderParent"], MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
folder.SiteId = PageState.Site.SiteId;
|
||||
|
||||
if (_parentId == -1)
|
||||
if (!_name.IsPathOrFileValid())
|
||||
{
|
||||
folder.ParentId = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
folder.ParentId = _parentId;
|
||||
AddModuleMessage(Localizer["Message.Folder.InvalidName"], MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
folder.Name = _name;
|
||||
folder.Type = _type;
|
||||
folder.IsSystem = _isSystem;
|
||||
folder.Permissions = _permissionGrid.GetPermissions();
|
||||
try
|
||||
{
|
||||
Folder folder;
|
||||
if (_folderId != -1)
|
||||
{
|
||||
folder = await FolderService.GetFolderAsync(_folderId);
|
||||
}
|
||||
else
|
||||
{
|
||||
folder = new Folder();
|
||||
}
|
||||
|
||||
if (_folderId != -1)
|
||||
{
|
||||
folder = await FolderService.UpdateFolderAsync(folder);
|
||||
}
|
||||
else
|
||||
{
|
||||
folder = await FolderService.AddFolderAsync(folder);
|
||||
}
|
||||
folder.SiteId = PageState.Site.SiteId;
|
||||
|
||||
if (folder != null)
|
||||
{
|
||||
await FolderService.UpdateFolderOrderAsync(folder.SiteId, folder.FolderId, folder.ParentId);
|
||||
await logger.LogInformation("Folder Saved {Folder}", folder);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
if (_parentId == -1)
|
||||
{
|
||||
folder.ParentId = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
folder.ParentId = _parentId;
|
||||
}
|
||||
|
||||
folder.Name = _name;
|
||||
folder.Type = _type;
|
||||
folder.ImageSizes = _imagesizes;
|
||||
folder.Capacity = int.Parse(_capacity);
|
||||
folder.IsSystem = _isSystem;
|
||||
folder.Permissions = _permissionGrid.GetPermissions();
|
||||
|
||||
if (_folderId != -1)
|
||||
{
|
||||
folder = await FolderService.UpdateFolderAsync(folder);
|
||||
}
|
||||
else
|
||||
{
|
||||
folder = await FolderService.AddFolderAsync(folder);
|
||||
}
|
||||
|
||||
if (folder != null)
|
||||
{
|
||||
await FolderService.UpdateFolderOrderAsync(folder.SiteId, folder.FolderId, folder.ParentId);
|
||||
await logger.LogInformation("Folder Saved {Folder}", folder);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Error.Folder.Save"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving Folder {FolderId} {Error}", _folderId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Folder.Save"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving Folder {FolderId} {Error}", _folderId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Folder.Save"], MessageType.Error);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,4 +268,4 @@
|
|||
AddModuleMessage(Localizer["Error.Folder.Delete"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,34 +8,34 @@
|
|||
|
||||
@if (_files != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<div class="col-sm-2">
|
||||
<label class="control-label">@Localizer["Folder"] </label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<select class="form-select" @onchange="(e => FolderChanged(e))">
|
||||
@foreach (Folder folder in _folders)
|
||||
{
|
||||
<option value="@(folder.FolderId)">@(new string('-', folder.Level * 2))@(folder.Name)</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<ActionLink Action="Edit" Text="Edit Folder" Class="btn btn-secondary" Parameters="@($"id=" + _folderId.ToString())" ResourceKey="EditFolder" />
|
||||
<ActionLink Action="Edit" Text="Add Folder" Class="btn btn-secondary" ResourceKey="AddFolder" />
|
||||
<ActionLink Action="Add" Text="Upload Files" Parameters="@($"id=" + _folderId.ToString())" ResourceKey="UploadFiles" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Pager Items="@_files">
|
||||
<Header>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th>@SharedLocalizer["Name"]</th>
|
||||
<th>@Localizer["Modified"]</th>
|
||||
<th>@Localizer["Type"]</th>
|
||||
<th>@Localizer["Size"]</th>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th>@SharedLocalizer["Name"]</th>
|
||||
<th>@Localizer["Modified"]</th>
|
||||
<th>@Localizer["Type"]</th>
|
||||
<th>@Localizer["Size"]</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td><ActionLink Action="Details" Text="Edit" Parameters="@($"id=" + context.FileId.ToString())" ResourceKey="Details" /></td>
|
||||
|
|
|
@ -5,98 +5,111 @@
|
|||
@inject IStringLocalizer<Edit> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="name" HelpText="Enter the job name" ResourceKey="Name">Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="name" class="form-control" @bind="@_name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="type" HelpText="The fully qualified job type name" ResourceKey="Type">Type: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="type" class="form-control" @bind="@_jobType" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="enabled" HelpText="Select whether you want the job enabled or not" ResourceKey="Enabled">Enabled? </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="enabled" class="form-select" @bind="@_isEnabled">
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="runs-every" HelpText="Select how often you want the job to run" ResourceKey="RunsEvery">Runs Every: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="runs-every" class="form-control" @bind="@_interval" />
|
||||
<select id="runs-every" class="form-select" @bind="@_frequency">
|
||||
<option value="m">@Localizer["Minute(s)"]</option>
|
||||
<option value="H">@Localizer["Hour(s)"]</option>
|
||||
<option value="d">@Localizer["Day(s)"]</option>
|
||||
<option value="M">@Localizer["Month(s)"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="starting" HelpText="What time do you want the job to start" ResourceKey="Starting">Starting: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="starting" class="form-control" @bind="@_startDate" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="ending" HelpText="When do you want the job to end" ResourceKey="Ending">Ending: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="ending" class="form-control" @bind="@_endDate" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="retention" HelpText="Number of log entries to retain for this job" ResourceKey="RetentionLog">Retention Log (Items): </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="retention" class="form-control" @bind="@_retentionHistory" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="next" HelpText="Next execution for this job." ResourceKey="NextExecution">Next Execution: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="next" class="form-control" @bind="@_nextExecution" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveJob">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="name" HelpText="Enter the job name" ResourceKey="Name">Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="name" class="form-control" @bind="@_name" maxlength="200" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="type" HelpText="The fully qualified job type name" ResourceKey="Type">Type: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="type" class="form-control" @bind="@_jobType" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="enabled" HelpText="Select whether you want the job enabled or not" ResourceKey="Enabled">Enabled? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="enabled" class="form-select" @bind="@_isEnabled" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="runs-every" HelpText="Select how often you want the job to run" ResourceKey="RunsEvery">Runs Every: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="runs-every" class="form-control" @bind="@_interval" maxlength="4" required />
|
||||
<select id="runs-every" class="form-select" @bind="@_frequency" required>
|
||||
<option value="m">@Localizer["Minute(s)"]</option>
|
||||
<option value="H">@Localizer["Hour(s)"]</option>
|
||||
<option value="d">@Localizer["Day(s)"]</option>
|
||||
<option value="M">@Localizer["Month(s)"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="retention" HelpText="Number of log entries to retain for this job" ResourceKey="RetentionLog">Retention Log (Items): </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="retention" class="form-control" @bind="@_retentionHistory" maxlength="4" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="starting" HelpText="Optionally enter the date and time when this job should start executing" ResourceKey="Starting">Starting: </Label>
|
||||
<div class="col-sm-9">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<input id="starting" type="date" class="form-control" @bind="@_startDate" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<input id="starting" type="text" class="form-control" placeholder="hh:mm" @bind="@_startTime" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="ending" HelpText="Optionally enter the date and time when this job should stop executing" ResourceKey="Ending">Ending: </Label>
|
||||
<div class="col-sm-9">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<input id="ending" type="date" class="form-control" @bind="@_endDate" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<input id="ending" type="text" class="form-control" placeholder="hh:mm" @bind="@_endTime" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="next" HelpText="Optionally modify the date and time when this job should execute next" ResourceKey="NextExecution">Next Execution: </Label>
|
||||
<div class="col-sm-9">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<input id="next" type="date" class="form-control" @bind="@_nextDate" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<input id="next" type="text" class="form-control" placeholder="hh:mm" @bind="@_nextTime" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveJob">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
|
||||
</form>
|
||||
|
||||
@code {
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
private int _jobId;
|
||||
private string _name = string.Empty;
|
||||
private string _jobType = string.Empty;
|
||||
private string _isEnabled = "True";
|
||||
private string _interval = string.Empty;
|
||||
private string _frequency = string.Empty;
|
||||
private string _startDate = string.Empty;
|
||||
private string _endDate = string.Empty;
|
||||
private DateTime? _startDate = null;
|
||||
private string _startTime = string.Empty;
|
||||
private DateTime? _endDate = null;
|
||||
private string _endTime = string.Empty;
|
||||
private string _retentionHistory = string.Empty;
|
||||
private string _nextExecution = string.Empty;
|
||||
private DateTime? _nextDate = null;
|
||||
private string _nextTime = string.Empty;
|
||||
private string createdby;
|
||||
private DateTime createdon;
|
||||
private string modifiedby;
|
||||
|
@ -117,10 +130,22 @@
|
|||
_isEnabled = job.IsEnabled.ToString();
|
||||
_interval = job.Interval.ToString();
|
||||
_frequency = job.Frequency;
|
||||
_startDate = (job.StartDate != null) ? job.StartDate.ToString() : string.Empty;
|
||||
_endDate = (job.EndDate != null) ? job.EndDate.ToString() : string.Empty;
|
||||
_startDate = job.StartDate;
|
||||
if (job.StartDate != null && job.StartDate.Value.TimeOfDay.TotalSeconds != 0)
|
||||
{
|
||||
_startTime = job.StartDate.Value.ToString("HH:mm");
|
||||
}
|
||||
_endDate = job.EndDate;
|
||||
if (job.EndDate != null && job.EndDate.Value.TimeOfDay.TotalSeconds != 0)
|
||||
{
|
||||
_endTime = job.EndDate.Value.ToString("HH:mm");
|
||||
}
|
||||
_retentionHistory = job.RetentionHistory.ToString();
|
||||
_nextExecution = job.NextExecution.ToString();
|
||||
_nextDate = job.NextExecution;
|
||||
if (job.NextExecution != null && job.NextExecution.Value.TimeOfDay.TotalSeconds != 0)
|
||||
{
|
||||
_nextTime = job.NextExecution.Value.ToString("HH:mm");
|
||||
}
|
||||
createdby = job.CreatedBy;
|
||||
createdon = job.CreatedOn;
|
||||
modifiedby = job.ModifiedBy;
|
||||
|
@ -136,7 +161,9 @@
|
|||
|
||||
private async Task SaveJob()
|
||||
{
|
||||
if (_name != string.Empty && !string.IsNullOrEmpty(_jobType) && _frequency != string.Empty && _interval != string.Empty && _retentionHistory != string.Empty)
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
var job = await JobService.GetJobAsync(_jobId);
|
||||
job.Name = _name;
|
||||
|
@ -144,35 +171,34 @@
|
|||
job.IsEnabled = Boolean.Parse(_isEnabled);
|
||||
job.Frequency = _frequency;
|
||||
job.Interval = int.Parse(_interval);
|
||||
|
||||
if (_startDate == string.Empty)
|
||||
job.StartDate = _startDate;
|
||||
if (job.StartDate != null)
|
||||
{
|
||||
job.StartDate = null;
|
||||
job.StartDate = job.StartDate.Value.Date;
|
||||
if (!string.IsNullOrEmpty(_startTime))
|
||||
{
|
||||
job.StartDate = DateTime.Parse(job.StartDate.Value.ToShortDateString() + " " + _startTime);
|
||||
}
|
||||
}
|
||||
else
|
||||
job.EndDate = _endDate;
|
||||
if (job.EndDate != null)
|
||||
{
|
||||
job.StartDate = DateTime.Parse(_startDate);
|
||||
job.EndDate = job.EndDate.Value.Date;
|
||||
if (!string.IsNullOrEmpty(_endTime))
|
||||
{
|
||||
job.EndDate = DateTime.Parse(job.EndDate.Value.ToShortDateString() + " " + _endTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (_endDate == string.Empty)
|
||||
{
|
||||
job.EndDate = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
job.EndDate = DateTime.Parse(_endDate);
|
||||
}
|
||||
|
||||
if (_nextExecution == string.Empty)
|
||||
{
|
||||
job.NextExecution = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
job.NextExecution = DateTime.Parse(_nextExecution);
|
||||
}
|
||||
|
||||
job.RetentionHistory = int.Parse(_retentionHistory);
|
||||
job.NextExecution = _nextDate;
|
||||
if (job.NextExecution != null)
|
||||
{
|
||||
job.NextExecution = job.NextExecution.Value.Date;
|
||||
if (!string.IsNullOrEmpty(_nextTime))
|
||||
{
|
||||
job.NextExecution = DateTime.Parse(job.NextExecution.Value.ToShortDateString() + " " + _nextTime);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -191,5 +217,4 @@
|
|||
AddModuleMessage(Localizer["Message.Required.JobInfo"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,50 +23,48 @@ else
|
|||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="name" HelpText="Name Of The Language" ResourceKey="Name">Name:</Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="_code" class="form-select" @bind="@_code">
|
||||
@foreach (var culture in _availableCultures)
|
||||
{
|
||||
<option value="@culture.Name">@culture.DisplayName</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="default" HelpText="Indicates Whether Or Not This Language Is The Default For The Site" ResourceKey="IsDefault">Default?</Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="default" class="form-select" @bind="@_isDefault">
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveLanguage">@SharedLocalizer["Save"]</button>
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="name" HelpText="Name Of The Language" ResourceKey="Name">Name:</Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="_code" class="form-select" @bind="@_code" required>
|
||||
@foreach (var culture in _availableCultures)
|
||||
{
|
||||
<option value="@culture.Name">@culture.DisplayName</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="default" HelpText="Indicates Whether Or Not This Language Is The Default For The Site" ResourceKey="IsDefault">Default?</Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="default" class="form-select" @bind="@_isDefault" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveLanguage">@SharedLocalizer["Save"]</button>
|
||||
</form>
|
||||
}
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
</TabPanel>
|
||||
<TabPanel Name="Download" ResourceKey="Download" Security="SecurityAccessLevel.Host">
|
||||
<ModuleMessage Type="MessageType.Info" Message="Download one or more translations from the list below. Once you are ready click Install to complete the installation."></ModuleMessage>
|
||||
|
||||
<table class="table table-borderless" style=" margin: auto; width: 50% !important;">
|
||||
<tr>
|
||||
<td>
|
||||
<div class="row justify-content-center mb-3">
|
||||
<div class="col-sm-6">
|
||||
<div class="input-group">
|
||||
<select id="price" class="form-select custom-select" @onchange="(e => PriceChanged(e))">
|
||||
<option value="free">@SharedLocalizer["Free"]</option>
|
||||
<option value="paid">@SharedLocalizer["Paid"]</option>
|
||||
</select>
|
||||
<input id="search" class="form-control" placeholder="@SharedLocalizer["Search.Hint"]" @bind="@_search" />
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-primary" @onclick="Search">@SharedLocalizer["Search"]</button>
|
||||
<button type="button" class="btn btn-primary" @onclick="Search">@SharedLocalizer["Search"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Reset">@SharedLocalizer["Reset"]</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (_packages != null)
|
||||
{
|
||||
|
@ -77,10 +75,26 @@ else
|
|||
<td>
|
||||
<h3 style="display: inline;"><a href="@context.ProductUrl" target="_new">@context.Name</a></h3> by: <strong><a href="@context.OwnerUrl" target="new">@context.Owner</a></strong><br />
|
||||
@(context.Description.Length > 400 ? (context.Description.Substring(0, 400) + "...") : context.Description)<br />
|
||||
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] | @SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> | @SharedLocalizer["Search.Version"]: <strong>@context.Version</strong> | @SharedLocalizer["Search.Source"]: <strong>@context.PackageUrl</strong>
|
||||
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] |
|
||||
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> |
|
||||
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
|
||||
@((MarkupString)(context.TrialPeriod > 0 ? " | <strong>" + context.TrialPeriod + " " + @SharedLocalizer["Trial"] + "</strong>" : ""))
|
||||
</td>
|
||||
<td style="vertical-align: middle;">
|
||||
<button type="button" class="btn btn-primary" @onclick=@(async () => await DownloadLanguage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
||||
<td style="width: 1px; vertical-align: middle;">
|
||||
@if (context.Price != null && !string.IsNullOrEmpty(context.PackageUrl))
|
||||
{
|
||||
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
||||
}
|
||||
</td>
|
||||
<td style="width: 1px; vertical-align: middle;">
|
||||
@if (context.Price != null && !string.IsNullOrEmpty(context.PaymentUrl))
|
||||
{
|
||||
<a class="btn btn-primary" style="text-decoration: none !important" href="@context.PaymentUrl" target="_new">@context.Price.Value.ToString("$#,##0.00")</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
||||
}
|
||||
</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
|
@ -97,30 +111,69 @@ else
|
|||
}
|
||||
</TabPanel>
|
||||
<TabPanel Name="Upload" ResourceKey="Upload" Security="SecurityAccessLevel.Host">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<Label HelpText="Upload one or more translations. 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>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" HelpText="Upload one or more translations. Once they are uploaded click Install to complete the installation." ResourceKey="Module">Language: </Label>
|
||||
<div class="col-sm-9">
|
||||
<FileManager Filter="nupkg" ShowFiles="true" Folder="Packages" UploadMultiple="true" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-success" @onclick="InstallLanguages">@SharedLocalizer["Install"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
</TabPanel>
|
||||
</TabStrip>
|
||||
}
|
||||
|
||||
@if (_productname != "")
|
||||
{
|
||||
<div class="app-actiondialog">
|
||||
<div class="modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@SharedLocalizer["Review License Terms"]</h5>
|
||||
<button type="button" class="btn-close" aria-label="Close" @onclick="HideModal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p style="height: 200px; overflow-y: scroll;">
|
||||
<h3>@_productname</h3>
|
||||
@if (!string.IsNullOrEmpty(_license))
|
||||
{
|
||||
@((MarkupString)_license)
|
||||
}
|
||||
else
|
||||
{
|
||||
@SharedLocalizer["License Not Specified"]
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-success" @onclick="DownloadPackage">@SharedLocalizer["Accept"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="HideModal">@SharedLocalizer["Cancel"]</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
|
||||
private string _code = string.Empty;
|
||||
private string _isDefault = "False";
|
||||
private string _message;
|
||||
private IEnumerable<Culture> _supportedCultures;
|
||||
private IEnumerable<Culture> _availableCultures;
|
||||
private List<Package> _packages;
|
||||
private string _price = "free";
|
||||
private string _search = "";
|
||||
private string _productname = "";
|
||||
private string _license = "";
|
||||
private string _packageid = "";
|
||||
private string _version = "";
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||
|
||||
|
@ -146,7 +199,22 @@ else
|
|||
|
||||
private async Task LoadTranslations()
|
||||
{
|
||||
_packages = await PackageService.GetPackagesAsync("translation", _search);
|
||||
_packages = await PackageService.GetPackagesAsync("translation", _search, _price, "");
|
||||
}
|
||||
|
||||
private async void PriceChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
_price = (string)e.Value;
|
||||
_search = "";
|
||||
await LoadTranslations();
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error On PriceChanged");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Search()
|
||||
|
@ -176,31 +244,88 @@ else
|
|||
|
||||
private async Task SaveLanguage()
|
||||
{
|
||||
var language = new Language
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
SiteId = PageState.Page.SiteId,
|
||||
Name = CultureInfo.GetCultureInfo(_code).DisplayName,
|
||||
Code = _code,
|
||||
IsDefault = (_isDefault == null ? false : Boolean.Parse(_isDefault))
|
||||
};
|
||||
var language = new Language
|
||||
{
|
||||
SiteId = PageState.Page.SiteId,
|
||||
Name = CultureInfo.GetCultureInfo(_code).DisplayName,
|
||||
Code = _code,
|
||||
IsDefault = (_isDefault == null ? false : Boolean.Parse(_isDefault))
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
language = await LanguageService.AddLanguageAsync(language);
|
||||
|
||||
if (language.IsDefault)
|
||||
{
|
||||
await SetCultureAsync(language.Code);
|
||||
}
|
||||
|
||||
await logger.LogInformation("Language Added {Language}", language);
|
||||
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Adding Language {Language} {Error}", language, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Language.Add"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void HideModal()
|
||||
{
|
||||
_productname = "";
|
||||
_license = "";
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task GetPackage(string packageid, string version)
|
||||
{
|
||||
try
|
||||
{
|
||||
language = await LanguageService.AddLanguageAsync(language);
|
||||
|
||||
if (language.IsDefault)
|
||||
var package = await PackageService.GetPackageAsync(packageid, version);
|
||||
if (package != null)
|
||||
{
|
||||
await SetCultureAsync(language.Code);
|
||||
_productname = package.Name;
|
||||
if (!string.IsNullOrEmpty(package.License))
|
||||
{
|
||||
_license = package.License.Replace("\n", "<br />");
|
||||
}
|
||||
_packageid = package.PackageId;
|
||||
_version = package.Version;
|
||||
}
|
||||
|
||||
await logger.LogInformation("Language Added {Language}", language);
|
||||
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Adding Language {Language} {Error}", language, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Language.Add"], MessageType.Error);
|
||||
await logger.LogError(ex, "Error Getting Package {PackageId} {Version}", packageid, version);
|
||||
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DownloadPackage()
|
||||
{
|
||||
try
|
||||
{
|
||||
await PackageService.DownloadPackageAsync(_packageid, _version, "Packages");
|
||||
await logger.LogInformation("Language Package {Name} {Version} Downloaded Successfully", _packageid, _version);
|
||||
AddModuleMessage(Localizer["Success.Language.Download"], MessageType.Success);
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Downloading Translation {Name} {Version}", _packageid, _version);
|
||||
AddModuleMessage(Localizer["Error.Language.Download"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,22 +342,6 @@ else
|
|||
}
|
||||
}
|
||||
|
||||
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["Success.Language.Download"], MessageType.Success);
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Downloading Translation {Name} {Version}", packageid, version);
|
||||
AddModuleMessage(Localizer["Error.Language.Download"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SetCultureAsync(string culture)
|
||||
{
|
||||
if (culture != CultureInfo.CurrentUICulture.Name)
|
||||
|
|
|
@ -29,9 +29,9 @@ else
|
|||
<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))>@SharedLocalizer["Upgrade"]</button>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous;
|
||||
|
||||
public override List<Resource> Resources => new List<Resource>()
|
||||
{
|
||||
{
|
||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
|
||||
};
|
||||
|
||||
|
@ -84,10 +84,12 @@
|
|||
|
||||
if (user != null)
|
||||
{
|
||||
await logger.LogInformation(LogFunction.Security, "Email Verified For For Username {Username}", _username);
|
||||
_message = Localizer["Success.Account.Verified"];
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogError(LogFunction.Security, "Email Verification Failed For Username {Username}", _username);
|
||||
_message = Localizer["Message.Account.NotVerfied"];
|
||||
_type = MessageType.Warning;
|
||||
}
|
||||
|
@ -98,7 +100,10 @@
|
|||
{
|
||||
if (firstRender)
|
||||
{
|
||||
await username.FocusAsync();
|
||||
if(PageState.User == null)
|
||||
{
|
||||
await username.FocusAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,7 +123,7 @@
|
|||
|
||||
if (user.IsAuthenticated)
|
||||
{
|
||||
await logger.LogInformation("Login Successful For Username {Username}", _username);
|
||||
await logger.LogInformation(LogFunction.Security, "Login Successful For Username {Username}", _username);
|
||||
// server-side Blazor needs to post to the Login page so that the cookies are set correctly
|
||||
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, username = _username, password = _password, remember = _remember, returnurl = _returnUrl };
|
||||
string url = Utilities.TenantUrl(PageState.Alias, "/pages/login/");
|
||||
|
@ -126,7 +131,7 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
await logger.LogInformation("Login Failed For Username {Username}", _username);
|
||||
await logger.LogError(LogFunction.Security, "Login Failed For Username {Username}", _username);
|
||||
AddModuleMessage(Localizer["Error.Login.Fail"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
@ -140,14 +145,14 @@
|
|||
user = await UserService.LoginUserAsync(user, true, _remember);
|
||||
if (user.IsAuthenticated)
|
||||
{
|
||||
await logger.LogInformation("Login Successful For Username {Username}", _username);
|
||||
await logger.LogInformation(LogFunction.Security, "Login Successful For Username {Username}", _username);
|
||||
var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider));
|
||||
authstateprovider.NotifyAuthenticationChanged();
|
||||
NavigationManager.NavigateTo(NavigateUrl(_returnUrl, true));
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogInformation("Login Failed For Username {Username}", _username);
|
||||
await logger.LogError(LogFunction.Security, "Login Failed For Username {Username}", _username);
|
||||
AddModuleMessage(Localizer["Error.Login.Fail"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
@ -171,6 +176,7 @@
|
|||
if (user != null)
|
||||
{
|
||||
await UserService.ForgotPasswordAsync(user);
|
||||
await logger.LogInformation(LogFunction.Security, "Password Reset Notification Sent For Username {Username}", _username);
|
||||
_message = "Please Check The Email Address Associated To Your User Account For A Password Reset Notification";
|
||||
}
|
||||
else
|
||||
|
|
|
@ -9,206 +9,246 @@
|
|||
@inject IStringLocalizer<Detail> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="dateTime" HelpText="The date and time of this log" ResourceKey="DateTime">Date/Time: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="dateTime" class="form-control" @bind="@_logDate" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="level" HelpText="The level of this log" ResourceKey="Level">Level: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="level" class="form-control" @bind="@_level" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="feature" HelpText="The feature that was affected" ResourceKey="Feature">Feature: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="feature" class="form-control" @bind="@_feature" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="function" HelpText="The function that was performed" ResourceKey="Function">Function: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="function" class="form-control" @bind="@_function" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="category" HelpText="The categories that were affected" ResourceKey="Category">Category: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="category" class="form-control" @bind="@_category" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
@if (_pageName != string.Empty)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="page" HelpText="The page that was affected" ResourceKey="Page">Page: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="page" class="form-control" @bind="@_pageName" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@if (_moduleTitle != string.Empty)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="module" HelpText="The module that was affected" ResourceKey="Module">Module: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="module" class="form-control" @bind="@_moduleTitle" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@if (_username != string.Empty)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="user" HelpText="The user that caused this log" ResourceKey="User">User: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="user" class="form-control" @bind="@_username" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="url" HelpText="The url the log comes from" ResourceKey="Url">Url: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="url" class="form-control" @bind="@_url" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="template" HelpText="What the log is about" ResourceKey="Template">Template: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="template" class="form-control" @bind="@_template" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="message" HelpText="The message that the system generated" class="control-label" ResourceKey="Message">Message: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea id="message" class="form-control" @bind="@_message" rows="5" readonly></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
@if (!string.IsNullOrEmpty(_exception))
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="exception" HelpText="The exceptions generated by the system" ResourceKey="Exception">Exception: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea id="exception" class="form-control" @bind="@_exception" rows="5" readonly></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="properties" HelpText="The properties that were affected" ResourceKey="Properties">Properties: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea id="properties" class="form-control" @bind="@_properties" rows="5" readonly></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="server" HelpText="The server that was affected" ResourceKey="Server">Server: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="server" class="form-control" @bind="@_server" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
|
||||
@code {
|
||||
private int _logId;
|
||||
private string _logDate = string.Empty;
|
||||
private string _level = string.Empty;
|
||||
private string _feature = string.Empty;
|
||||
private string _function = string.Empty;
|
||||
private string _category = string.Empty;
|
||||
private string _pageName = string.Empty;
|
||||
private string _moduleTitle = string.Empty;
|
||||
private string _username = string.Empty;
|
||||
private string _url = string.Empty;
|
||||
private string _template = string.Empty;
|
||||
private string _message = string.Empty;
|
||||
private string _exception = string.Empty;
|
||||
private string _properties = string.Empty;
|
||||
private string _server = string.Empty;
|
||||
<div class="col-sm-9">
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
<div class="col-sm-9">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
|
||||
<div class="col-sm-9">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
|
||||
<div class="col-sm-9">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
|
||||
<div class="col-sm-9">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
|
||||
<div class="col-sm-9">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
|
||||
<div class="col-sm-9">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
|
||||
<div class="col-sm-9">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
|
||||
<div class="col-sm-9">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
|
||||
<div class="col-sm-9">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
|
||||
<div class="col-sm-9">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="dateTime" HelpText="The date and time of this log" ResourceKey="DateTime">Date/Time: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="dateTime" class="form-control" @bind="@_logDate" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="level" HelpText="The level of this log" ResourceKey="Level">Level: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="level" class="form-control" @bind="@_level" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="feature" HelpText="The feature that was affected" ResourceKey="Feature">Feature: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="feature" class="form-control" @bind="@_feature" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="function" HelpText="The function that was performed" ResourceKey="Function">Function: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="function" class="form-control" @bind="@_function" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="category" HelpText="The categories that were affected" ResourceKey="Category">Category: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="category" class="form-control" @bind="@_category" readonly />
|
||||
</div>
|
||||
</div>
|
||||
@if (_pageName != string.Empty)
|
||||
{
|
||||
_logId = Int32.Parse(PageState.QueryString["id"]);
|
||||
var log = await LogService.GetLogAsync(_logId);
|
||||
if (log != null)
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="page" HelpText="The page that was affected" ResourceKey="Page">Page: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="page" class="form-control" @bind="@_pageName" readonly />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (_moduleTitle != string.Empty)
|
||||
{
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="module" HelpText="The module that was affected" ResourceKey="Module">Module: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="module" class="form-control" @bind="@_moduleTitle" readonly />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (_username != string.Empty)
|
||||
{
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="user" HelpText="The user that caused this log" ResourceKey="User">User: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="user" class="form-control" @bind="@_username" readonly />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="url" HelpText="The url the log comes from" ResourceKey="Url">Url: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="url" class="form-control" @bind="@_url" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="template" HelpText="What the log is about" ResourceKey="Template">Template: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="template" class="form-control" @bind="@_template" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="message" HelpText="The message that the system generated" ResourceKey="Message">Message: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="message" class="form-control" @bind="@_message" rows="5" readonly></textarea>
|
||||
</div>
|
||||
</div>
|
||||
@if (!string.IsNullOrEmpty(_exception))
|
||||
{
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="exception" HelpText="The exceptions generated by the system" ResourceKey="Exception">Exception: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="exception" class="form-control" @bind="@_exception" rows="5" readonly></textarea>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="properties" HelpText="The properties that were affected" ResourceKey="Properties">Properties: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="properties" class="form-control" @bind="@_properties" rows="5" readonly></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="server" HelpText="The server that was affected" ResourceKey="Server">Server: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="server" class="form-control" @bind="@_server" readonly />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
|
||||
@code {
|
||||
private int _logId;
|
||||
private string _logDate = string.Empty;
|
||||
private string _level = string.Empty;
|
||||
private string _feature = string.Empty;
|
||||
private string _function = string.Empty;
|
||||
private string _category = string.Empty;
|
||||
private string _pageName = string.Empty;
|
||||
private string _moduleTitle = string.Empty;
|
||||
private string _username = string.Empty;
|
||||
private string _url = string.Empty;
|
||||
private string _template = string.Empty;
|
||||
private string _message = string.Empty;
|
||||
private string _exception = string.Empty;
|
||||
private string _properties = string.Empty;
|
||||
private string _server = string.Empty;
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
_logDate = log.LogDate.ToString(CultureInfo.CurrentCulture);
|
||||
_level = log.Level;
|
||||
_feature = log.Feature;
|
||||
_function = log.Function;
|
||||
_category = log.Category;
|
||||
|
||||
if (log.PageId != null)
|
||||
_logId = Int32.Parse(PageState.QueryString["id"]);
|
||||
var log = await LogService.GetLogAsync(_logId);
|
||||
if (log != null)
|
||||
{
|
||||
var page = await PageService.GetPageAsync(log.PageId.Value);
|
||||
if (page != null)
|
||||
{
|
||||
_pageName = page.Name;
|
||||
}
|
||||
}
|
||||
_logDate = log.LogDate.ToString(CultureInfo.CurrentCulture);
|
||||
_level = log.Level;
|
||||
_feature = log.Feature;
|
||||
_function = log.Function;
|
||||
_category = log.Category;
|
||||
|
||||
if (log.PageId != null && log.ModuleId != null)
|
||||
{
|
||||
var pagemodule = await PageModuleService.GetPageModuleAsync(log.PageId.Value, log.ModuleId.Value);
|
||||
if (pagemodule != null)
|
||||
if (log.PageId != null)
|
||||
{
|
||||
_moduleTitle = pagemodule.Title;
|
||||
var page = await PageService.GetPageAsync(log.PageId.Value);
|
||||
if (page != null)
|
||||
{
|
||||
_pageName = page.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (log.UserId != null)
|
||||
{
|
||||
var user = await UserService.GetUserAsync(log.UserId.Value, PageState.Site.SiteId);
|
||||
if (user != null)
|
||||
if (log.PageId != null && log.ModuleId != null)
|
||||
{
|
||||
_username = user.Username;
|
||||
var pagemodule = await PageModuleService.GetPageModuleAsync(log.PageId.Value, log.ModuleId.Value);
|
||||
if (pagemodule != null)
|
||||
{
|
||||
_moduleTitle = pagemodule.Title;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_url = log.Url;
|
||||
_template = log.MessageTemplate;
|
||||
_message = log.Message;
|
||||
_exception = log.Exception;
|
||||
_properties = log.Properties;
|
||||
_server = log.Server;
|
||||
if (log.UserId != null)
|
||||
{
|
||||
var user = await UserService.GetUserAsync(log.UserId.Value, PageState.Site.SiteId);
|
||||
if (user != null)
|
||||
{
|
||||
_username = user.Username;
|
||||
}
|
||||
}
|
||||
|
||||
_url = log.Url;
|
||||
_template = log.MessageTemplate;
|
||||
_message = log.Message;
|
||||
_exception = log.Exception;
|
||||
_properties = log.Properties;
|
||||
_server = log.Server;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Log {LogId} {Error}", _logId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Log.Load"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Loading Log {LogId} {Error}", _logId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Log.Load"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<div class="container g-0">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<div class="col-sm-4">
|
||||
<Label For="level" HelpText="Select the log level for event log items" ResourceKey="Level">Level: </Label><br /><br />
|
||||
<select id="level" class="form-select" @onchange="(e => LevelChanged(e))">
|
||||
<option value="-"><@Localizer["AllLevels"]></option>
|
||||
|
@ -23,8 +23,8 @@ else
|
|||
<option value="Error">@Localizer["Error"]</option>
|
||||
<option value="Critical">@Localizer["Critical"]</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<Label For="function" HelpText="Select the function for event log items" ResourceKey="Function">Function: </Label><br /><br />
|
||||
<select id="function" class="form-select" @onchange="(e => FunctionChanged(e))">
|
||||
<option value="-"><@Localizer["AllFunctions"]></option>
|
||||
|
@ -35,27 +35,27 @@ else
|
|||
<option value="Security">@Localizer["Security"]</option>
|
||||
<option value="Other">@Localizer["Other"]</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<Label For="rows" HelpText="Select the maximum number of event log items to review. Please note that if you choose more than 10 items the information will be split into pages." ResourceKey="Rows">Maximum Items: </Label><br /><br />
|
||||
<select id="rows" class="form-select" @onchange="(e => RowsChanged(e))">
|
||||
<option value="10">10</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (_logs.Any())
|
||||
{
|
||||
<Pager Items="@_logs">
|
||||
<Header>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th>@Localizer["Date"]</th>
|
||||
<th>@Localizer["Level"]</th>
|
||||
<th>@Localizer["Feature"]</th>
|
||||
<th>@Localizer["Function"]</th>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th>@Localizer["Date"]</th>
|
||||
<th>@Localizer["Level"]</th>
|
||||
<th>@Localizer["Feature"]</th>
|
||||
<th>@Localizer["Function"]</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td class="@GetClass(context.Function)"><ActionLink Action="Detail" Parameters="@($"id=" + context.LogId.ToString())" ResourceKey="LogDetails" /></td>
|
||||
|
|
|
@ -10,82 +10,75 @@
|
|||
|
||||
@if (string.IsNullOrEmpty(_moduledefinitionname) && _templates != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="owner" HelpText="Enter the name of the organization who is developing this module. It should not contain spaces or punctuation." ResourceKey="OwnerName">Owner Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="owner" class="form-control" @bind="@_owner" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="module" HelpText="Enter a name for this module. It should not contain spaces or punctuation." ResourceKey="ModuleName">Module Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="module" class="form-control" @bind="@_module" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="description" HelpText="Enter a short description for the module" ResourceKey="Description">Description: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea id="description" class="form-control" @bind="@_description" rows="3"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="template" HelpText="Select a module template. Templates are located in the wwwroot/Modules/Templates folder on the server." ResourceKey="Template">Template: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="template" class="form-select" @onchange="(e => TemplateChanged(e))">
|
||||
<option value="-"><@Localizer["Template.Select"]></option>
|
||||
@foreach (Template template in _templates)
|
||||
{
|
||||
<option value="@template.Name">@template.Title</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="reference" HelpText="Select a framework reference version" ResourceKey="FrameworkReference">Framework Reference: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="reference" class="form-select" @bind="@_reference">
|
||||
@foreach (string version in _versions)
|
||||
{
|
||||
if (Version.Parse(version).CompareTo(Version.Parse(_minversion)) >= 0)
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="owner" HelpText="Enter the name of the organization who is developing this module. It should not contain spaces or punctuation." ResourceKey="OwnerName">Owner Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="owner" class="form-control" @bind="@_owner" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="module" HelpText="Enter a name for this module. It should not contain spaces or punctuation." ResourceKey="ModuleName">Module Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="module" class="form-control" @bind="@_module" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="description" HelpText="Enter a short description for the module" ResourceKey="Description">Description: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="description" class="form-control" @bind="@_description" rows="3" ></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="template" HelpText="Select a module template. Templates are located in the wwwroot/Modules/Templates folder on the server." ResourceKey="Template">Template: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="template" class="form-select" @onchange="(e => TemplateChanged(e))" required>
|
||||
<option value="-"><@Localizer["Template.Select"]></option>
|
||||
@foreach (Template template in _templates)
|
||||
{
|
||||
<option value="@(version)">@(version)</option>
|
||||
<option value="@template.Name">@template.Title</option>
|
||||
}
|
||||
}
|
||||
<option value="local">@SharedLocalizer["LocalVersion"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
@if (!string.IsNullOrEmpty(_location))
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="location" HelpText="Location where the module will be created" ResourceKey="Location">Location: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="module" class="form-control" @bind="@_location" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="reference" HelpText="Select a framework reference version" ResourceKey="FrameworkReference">Framework Reference: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="reference" class="form-select" @bind="@_reference" required>
|
||||
@foreach (string version in _versions)
|
||||
{
|
||||
if (Version.Parse(version).CompareTo(Version.Parse(_minversion)) >= 0)
|
||||
{
|
||||
<option value="@(version)">@(version)</option>
|
||||
}
|
||||
}
|
||||
<option value="local">@SharedLocalizer["LocalVersion"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@if (!string.IsNullOrEmpty(_location))
|
||||
{
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="location" HelpText="Location where the module will be created" ResourceKey="Location">Location: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="module" class="form-control" @bind="@_location" readonly />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-success" @onclick="CreateModule">@Localizer["Module.Create"]</button>
|
||||
}
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="CreateModule">@Localizer["Module.Create"]</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn btn-success" @onclick="ActivateModule">@Localizer["Module.Activate"]</button>
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn btn-success" @onclick="ActivateModule">@Localizer["Module.Activate"]</button>
|
||||
</form>
|
||||
}
|
||||
|
||||
@code {
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
private string _moduledefinitionname = string.Empty;
|
||||
private string _owner = string.Empty;
|
||||
private string _module = string.Empty;
|
||||
|
@ -124,9 +117,11 @@ else
|
|||
|
||||
private async Task CreateModule()
|
||||
{
|
||||
try
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
if (IsValid(_owner) && IsValid(_module) && _owner != _module && _template != "-")
|
||||
try
|
||||
{
|
||||
var moduleDefinition = new ModuleDefinition { Owner = _owner, Name = _module, Description = _description, Template = _template, Version = _reference };
|
||||
moduleDefinition = await ModuleDefinitionService.CreateModuleDefinitionAsync(moduleDefinition);
|
||||
|
@ -139,14 +134,14 @@ else
|
|||
|
||||
AddModuleMessage(string.Format(Localizer["Success.Module.Create"], NavigateUrl("admin/system")), MessageType.Success);
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Require.ValidName"], MessageType.Warning);
|
||||
await logger.LogError(ex, "Error Creating Module");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
await logger.LogError(ex, "Error Creating Module");
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,19 +9,19 @@
|
|||
|
||||
<TabStrip>
|
||||
<TabPanel Name="Download" ResourceKey="Download">
|
||||
<ModuleMessage Type="MessageType.Info" Message="Download one or more modules from the list below. Once you are ready click Install to complete the installation."></ModuleMessage>
|
||||
|
||||
<table class="table table-borderless" style="margin: auto; width: 50% !important;">
|
||||
<tr>
|
||||
<td>
|
||||
<div class="row justify-content-center mb-3">
|
||||
<div class="col-sm-6">
|
||||
<div class="input-group">
|
||||
<select id="price" class="form-select custom-select" @onchange="(e => PriceChanged(e))">
|
||||
<option value="free">@SharedLocalizer["Free"]</option>
|
||||
<option value="paid">@SharedLocalizer["Paid"]</option>
|
||||
</select>
|
||||
<input id="search" class="form-control" placeholder="@SharedLocalizer["Search.Hint"]" @bind="@_search" />
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-primary" @onclick="Search">@SharedLocalizer["Search"]</button>
|
||||
<button type="button" class="btn btn-primary" @onclick="Search">@SharedLocalizer["Search"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Reset">@SharedLocalizer["Reset"]</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (_packages != null)
|
||||
{
|
||||
|
@ -32,10 +32,26 @@
|
|||
<td>
|
||||
<h3 style="display: inline;"><a href="@context.ProductUrl" target="_new">@context.Name</a></h3> by: <strong><a href="@context.OwnerUrl" target="new">@context.Owner</a></strong><br />
|
||||
@(context.Description.Length > 400 ? (context.Description.Substring(0, 400) + "...") : context.Description)<br />
|
||||
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] | @SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> | @SharedLocalizer["Search.Version"]: <strong>@context.Version</strong> | @SharedLocalizer["Search.Source"]: <strong>@context.PackageUrl</strong>
|
||||
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] |
|
||||
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> |
|
||||
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
|
||||
@((MarkupString)(context.TrialPeriod > 0 ? " | <strong>" + context.TrialPeriod + " " + @SharedLocalizer["Trial"] + "</strong>" : ""))
|
||||
</td>
|
||||
<td style="vertical-align: middle;">
|
||||
<button type="button" class="btn btn-primary" @onclick=@(async () => await DownloadModule(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
||||
<td style="width: 1px; vertical-align: middle;">
|
||||
@if (context.Price != null && !string.IsNullOrEmpty(context.PackageUrl))
|
||||
{
|
||||
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
||||
}
|
||||
</td>
|
||||
<td style="width: 1px; vertical-align: middle;">
|
||||
@if (context.Price != null && !string.IsNullOrEmpty(context.PaymentUrl))
|
||||
{
|
||||
<a class="btn btn-primary" style="text-decoration: none !important" href="@context.PaymentUrl" target="_new">@context.Price.Value.ToString("$#,##0.00")</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
||||
}
|
||||
</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
|
@ -50,25 +66,61 @@
|
|||
}
|
||||
</TabPanel>
|
||||
<TabPanel Name="Upload" ResourceKey="Upload">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<Label HelpText="Upload one or more module packages. Once they are uploaded click Install to complete the installation." ResourceKey="Module">Module: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" HelpText="Upload one or more module packages. Once they are uploaded click Install to complete the installation." ResourceKey="Module">Module: </Label>
|
||||
<div class="col-sm-9">
|
||||
<FileManager Filter="nupkg" ShowFiles="false" Folder="Packages" UploadMultiple="true" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</TabPanel>
|
||||
</TabStrip>
|
||||
|
||||
@if (_productname != "")
|
||||
{
|
||||
<div class="app-actiondialog">
|
||||
<div class="modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@SharedLocalizer["Review License Terms"]</h5>
|
||||
<button type="button" class="btn-close" aria-label="Close" @onclick="HideModal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p style="height: 200px; overflow-y: scroll;">
|
||||
<h3>@_productname</h3>
|
||||
@if (!string.IsNullOrEmpty(_license))
|
||||
{
|
||||
@((MarkupString)_license)
|
||||
}
|
||||
else
|
||||
{
|
||||
@SharedLocalizer["License Not Specified"]
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-success" @onclick="DownloadPackage">@SharedLocalizer["Accept"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="HideModal">@SharedLocalizer["Cancel"]</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<button type="button" class="btn btn-success" @onclick="InstallModules">@SharedLocalizer["Install"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
|
||||
@code {
|
||||
private List<Package> _packages;
|
||||
private string _price = "free";
|
||||
private string _search = "";
|
||||
private string _productname = "";
|
||||
private string _license = "";
|
||||
private string _packageid = "";
|
||||
private string _version = "";
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||
|
||||
|
@ -88,7 +140,7 @@
|
|||
private async Task LoadModuleDefinitions()
|
||||
{
|
||||
var moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
|
||||
_packages = await PackageService.GetPackagesAsync("module", _search);
|
||||
_packages = await PackageService.GetPackagesAsync("module", _search, _price, "");
|
||||
|
||||
if (_packages != null)
|
||||
{
|
||||
|
@ -102,6 +154,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
private async void PriceChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
_price = (string)e.Value;
|
||||
_search = "";
|
||||
await LoadModuleDefinitions();
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error On PriceChanged");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Search()
|
||||
{
|
||||
try
|
||||
|
@ -127,6 +194,55 @@
|
|||
}
|
||||
}
|
||||
|
||||
private void HideModal()
|
||||
{
|
||||
_productname = "";
|
||||
_license = "";
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task GetPackage(string packageid, string version)
|
||||
{
|
||||
try
|
||||
{
|
||||
var package = await PackageService.GetPackageAsync(packageid, version);
|
||||
if (package != null)
|
||||
{
|
||||
_productname = package.Name;
|
||||
if (!string.IsNullOrEmpty(package.License))
|
||||
{
|
||||
_license = package.License.Replace("\n", "<br />");
|
||||
}
|
||||
_packageid = package.PackageId;
|
||||
_version = package.Version;
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Getting Package {PackageId} {Version}", packageid, version);
|
||||
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DownloadPackage()
|
||||
{
|
||||
try
|
||||
{
|
||||
await PackageService.DownloadPackageAsync(_packageid, _version, "Packages");
|
||||
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _packageid, _version);
|
||||
AddModuleMessage(Localizer["Success.Module.Download"], MessageType.Success);
|
||||
_productname = "";
|
||||
_license = "";
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Downloading Package {PackageId} {Version}", _packageid, _version);
|
||||
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task InstallModules()
|
||||
{
|
||||
try
|
||||
|
@ -139,20 +255,4 @@
|
|||
await logger.LogError(ex, "Error Installing Module");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DownloadModule(string packageid, string version)
|
||||
{
|
||||
try
|
||||
{
|
||||
await PackageService.DownloadPackageAsync(packageid, version, "Packages");
|
||||
await logger.LogInformation("Module {ModuleDefinitionName} {Version} Downloaded Successfully", packageid, version);
|
||||
AddModuleMessage(Localizer["Success.Module.Download"], MessageType.Success);
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Downloading Module {ModuleDefinitionName} {Version}", packageid, version);
|
||||
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,79 +10,71 @@
|
|||
|
||||
@if (_templates != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="owner" HelpText="Enter the name of the organization who is developing this module. It should not contain spaces or punctuation." ResourceKey="OwnerName">Owner Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="owner" class="form-control" @bind="@_owner" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="module" HelpText="Enter a name for this module. It should not contain spaces or punctuation." ResourceKey="ModuleName">Module Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="module" class="form-control" @bind="@_module" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="description" HelpText="Enter a short description for the module" ResourceKey="Description">Description: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea id="description" class="form-control" @bind="@_description" rows="3"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="template" HelpText="Select a module template. Templates are located in the wwwroot/Modules/Templates folder on the server." ResourceKey="Template">Template: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="template" class="form-select" @onchange="(e => TemplateChanged(e))">
|
||||
<option value="-"><@Localizer["Template.Select"]></option>
|
||||
@foreach (Template template in _templates)
|
||||
{
|
||||
<option value="@template.Name">@template.Title</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="reference" HelpText="Select a framework reference version" ResourceKey="FrameworkReference">Framework Reference: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="reference" class="form-select" @bind="@_reference">
|
||||
@foreach (string version in _versions)
|
||||
{
|
||||
if (Version.Parse(version).CompareTo(Version.Parse(_minversion)) >= 0)
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="owner" HelpText="Enter the name of the organization who is developing this module. It should not contain spaces or punctuation." ResourceKey="OwnerName">Owner Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="owner" class="form-control" @bind="@_owner" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="module" HelpText="Enter a name for this module. It should not contain spaces or punctuation." ResourceKey="ModuleName">Module Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="module" class="form-control" @bind="@_module" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="description" HelpText="Enter a short description for the module" ResourceKey="Description">Description: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="description" class="form-control" @bind="@_description" rows="3" maxlength="2000" required></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="template" HelpText="Select a module template. Templates are located in the wwwroot/Modules/Templates folder on the server." ResourceKey="Template">Template: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="template" class="form-select" @onchange="(e => TemplateChanged(e))" required>
|
||||
<option value="-"><@Localizer["Template.Select"]></option>
|
||||
@foreach (Template template in _templates)
|
||||
{
|
||||
<option value="@(version)">@(version)</option>
|
||||
<option value="@template.Name">@template.Title</option>
|
||||
}
|
||||
}
|
||||
<option value="local">@SharedLocalizer["LocalVersion"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
@if (!string.IsNullOrEmpty(_location))
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="location" HelpText="Location where the module will be created" ResourceKey="Location">Location: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="module" class="form-control" @bind="@_location" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="CreateModule">@Localizer["CreateModule"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="reference" HelpText="Select a framework reference version" ResourceKey="FrameworkReference">Framework Reference: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="reference" class="form-select" @bind="@_reference" required>
|
||||
@foreach (string version in _versions)
|
||||
{
|
||||
if (Version.Parse(version).CompareTo(Version.Parse(_minversion)) >= 0)
|
||||
{
|
||||
<option value="@(version)">@(version)</option>
|
||||
}
|
||||
}
|
||||
<option value="local">@SharedLocalizer["LocalVersion"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@if (!string.IsNullOrEmpty(_location))
|
||||
{
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="location" HelpText="Location where the module will be created" ResourceKey="Location">Location: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="module" class="form-control" @bind="@_location" readonly />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<button type="button" class="btn btn-success" @onclick="CreateModule">@Localizer["CreateModule"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
</form>
|
||||
}
|
||||
|
||||
@code {
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
private string _owner = string.Empty;
|
||||
private string _module = string.Empty;
|
||||
private string _description = string.Empty;
|
||||
|
@ -111,23 +103,32 @@
|
|||
|
||||
private async Task CreateModule()
|
||||
{
|
||||
try
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
if (IsValid(_owner) && IsValid(_module) && _owner != _module && _template != "-")
|
||||
try
|
||||
{
|
||||
var moduleDefinition = new ModuleDefinition { Owner = _owner, Name = _module, Description = _description, Template = _template, Version = _reference };
|
||||
moduleDefinition = await ModuleDefinitionService.CreateModuleDefinitionAsync(moduleDefinition);
|
||||
GetLocation();
|
||||
AddModuleMessage(string.Format(Localizer["Success.Module.Create"], NavigateUrl("admin/system")), MessageType.Success);
|
||||
if (IsValid(_owner) && IsValid(_module) && _owner != _module && _template != "-")
|
||||
{
|
||||
var moduleDefinition = new ModuleDefinition { Owner = _owner, Name = _module, Description = _description, Template = _template, Version = _reference };
|
||||
moduleDefinition = await ModuleDefinitionService.CreateModuleDefinitionAsync(moduleDefinition);
|
||||
GetLocation();
|
||||
AddModuleMessage(string.Format(Localizer["Success.Module.Create"], NavigateUrl("admin/system")), MessageType.Success);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Require.ValidName"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Require.ValidName"], MessageType.Warning);
|
||||
await logger.LogError(ex, "Error Creating Module");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
await logger.LogError(ex, "Error Creating Module");
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,101 +7,81 @@
|
|||
|
||||
<TabStrip>
|
||||
<TabPanel Name="Definition" ResourceKey="Definition">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="name" HelpText="The name of the module" ResourceKey="Name">Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="name" class="form-control" @bind="@_name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="description" HelpText="The description of the module" ResourceKey="Description">Description: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea id="description" class="form-control" @bind="@_description" rows="2"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="categories" HelpText="Comma delimited list of module categories" ResourceKey="Categories">Categories: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="categories" class="form-control" @bind="@_categories" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="name" HelpText="The name of the module" ResourceKey="Name">Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="name" class="form-control" @bind="@_name" maxlength="200" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="description" HelpText="The description of the module" ResourceKey="Description">Description: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="description" class="form-control" @bind="@_description" rows="2" maxlength="2000" required></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="categories" HelpText="Comma delimited list of module categories" ResourceKey="Categories">Categories: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="categories" class="form-control" @bind="@_categories" maxlength="200" required />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<Section Name="Information" ResourceKey="Information">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="moduledefinitionname" HelpText="The internal name of the module" ResourceKey="InternalName">Internal Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="moduledefinitionname" HelpText="The internal name of the module" ResourceKey="InternalName">Internal Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="moduledefinitionname" class="form-control" @bind="@_moduledefinitionname" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="version" HelpText="The version of the module" ResourceKey="Version">Version: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="version" HelpText="The version of the module" ResourceKey="Version">Version: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="version" class="form-control" @bind="@_version" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="owner" HelpText="The owner or creator of the module" ResourceKey="Owner">Owner: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="owner" HelpText="The owner or creator of the module" ResourceKey="Owner">Owner: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="owner" class="form-control" @bind="@_owner" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="url" HelpText="The reference url of the module" ResourceKey="ReferenceUrl">Reference Url: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="url" HelpText="The reference url of the module" ResourceKey="ReferenceUrl">Reference Url: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="url" class="form-control" @bind="@_url" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="contact" HelpText="The contact for the module" ResourceKey="Contact">Contact: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="contact" HelpText="The contact for the module" ResourceKey="Contact">Contact: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="contact" class="form-control" @bind="@_contact" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="license" HelpText="The module license terms" ResourceKey="License">License: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="license" HelpText="The module license terms" ResourceKey="License">License: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="license" class="form-control" @bind="@_license" rows="5" disabled></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="runtimes" HelpText="The Blazor runtimes which this module supports" ResourceKey="Runtimes">Runtimes: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="runtimes" HelpText="The Blazor runtimes which this module supports" ResourceKey="Runtimes">Runtimes: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="runtimes" class="form-control" @bind="@_runtimes" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
</TabPanel>
|
||||
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<PermissionGrid EntityName="@EntityNames.ModuleDefinition" PermissionNames="@PermissionNames.Utilize" Permissions="@_permissions" @ref="_permissionGrid" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<PermissionGrid EntityName="@EntityNames.ModuleDefinition" PermissionNames="@PermissionNames.Utilize" Permissions="@_permissions" @ref="_permissionGrid" />
|
||||
</div>
|
||||
</div>
|
||||
</TabPanel>
|
||||
</TabStrip>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveModuleDefinition">@SharedLocalizer["Save"]</button>
|
||||
|
@ -111,6 +91,8 @@
|
|||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
|
||||
|
||||
@code {
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
private int _moduleDefinitionId;
|
||||
private string _name;
|
||||
private string _version;
|
||||
|
@ -168,30 +150,39 @@
|
|||
|
||||
private async Task SaveModuleDefinition()
|
||||
{
|
||||
try
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
var moduledefinition = await ModuleDefinitionService.GetModuleDefinitionAsync(_moduleDefinitionId, ModuleState.SiteId);
|
||||
if (moduledefinition.Name != _name)
|
||||
try
|
||||
{
|
||||
moduledefinition.Name = _name;
|
||||
var moduledefinition = await ModuleDefinitionService.GetModuleDefinitionAsync(_moduleDefinitionId, ModuleState.SiteId);
|
||||
if (moduledefinition.Name != _name)
|
||||
{
|
||||
moduledefinition.Name = _name;
|
||||
}
|
||||
if (moduledefinition.Description != _description)
|
||||
{
|
||||
moduledefinition.Description = _description;
|
||||
}
|
||||
if (moduledefinition.Categories != _categories)
|
||||
{
|
||||
moduledefinition.Categories = _categories;
|
||||
}
|
||||
moduledefinition.Permissions = _permissionGrid.GetPermissions();
|
||||
await ModuleDefinitionService.UpdateModuleDefinitionAsync(moduledefinition);
|
||||
await logger.LogInformation("ModuleDefinition Saved {ModuleDefinition}", moduledefinition);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
if (moduledefinition.Description != _description)
|
||||
catch (Exception ex)
|
||||
{
|
||||
moduledefinition.Description = _description;
|
||||
await logger.LogError(ex, "Error Saving ModuleDefinition {ModuleDefinitionId} {Error}", _moduleDefinitionId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Module.Save"], MessageType.Error);
|
||||
}
|
||||
if (moduledefinition.Categories != _categories)
|
||||
{
|
||||
moduledefinition.Categories = _categories;
|
||||
}
|
||||
moduledefinition.Permissions = _permissionGrid.GetPermissions();
|
||||
await ModuleDefinitionService.UpdateModuleDefinitionAsync(moduledefinition);
|
||||
await logger.LogInformation("ModuleDefinition Saved {ModuleDefinition}", moduledefinition);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving ModuleDefinition {ModuleDefinitionId} {Error}", _moduleDefinitionId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Module.Save"], MessageType.Error);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ else
|
|||
<th style="width: 1px;"> </th>
|
||||
<th>@SharedLocalizer["Name"]</th>
|
||||
<th>@SharedLocalizer["Version"]</th>
|
||||
<th>@SharedLocalizer["Expires"]</th>
|
||||
<th style="width: 1px;"> </th>
|
||||
</Header>
|
||||
<Row>
|
||||
|
@ -34,11 +35,14 @@ else
|
|||
</td>
|
||||
<td>@context.Name</td>
|
||||
<td>@context.Version</td>
|
||||
<td>
|
||||
@((MarkupString)PurchaseLink(context.PackageName))
|
||||
</td>
|
||||
<td>
|
||||
@if (UpgradeAvailable(context.PackageName, context.Version))
|
||||
{
|
||||
{
|
||||
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadModule(context.PackageName, context.Version))>@SharedLocalizer["Upgrade"]</button>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
|
@ -67,10 +71,31 @@ else
|
|||
}
|
||||
}
|
||||
|
||||
private string PurchaseLink(string packagename)
|
||||
{
|
||||
string link = "";
|
||||
if (!string.IsNullOrEmpty(packagename) && _packages != null)
|
||||
{
|
||||
var package = _packages.Where(item => item.PackageId == packagename).FirstOrDefault();
|
||||
if (package != null)
|
||||
{
|
||||
if (package.ExpiryDate != null && package.ExpiryDate.Value.Date != DateTime.MaxValue.Date)
|
||||
{
|
||||
link += "<span>" + package.ExpiryDate.Value.Date.ToString("MMM dd, yyyy") + "</span>";
|
||||
if (!string.IsNullOrEmpty(package.PaymentUrl))
|
||||
{
|
||||
link += " <a class=\"btn btn-primary\" style=\"text-decoration: none !important\" href=\"" + package.PaymentUrl + "\" target=\"_new\">" + SharedLocalizer["Extend"] + "</a>";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return link;
|
||||
}
|
||||
|
||||
private bool UpgradeAvailable(string packagename, string version)
|
||||
{
|
||||
var upgradeavailable = false;
|
||||
if (_packages != null)
|
||||
if (!string.IsNullOrEmpty(packagename) && _packages != null)
|
||||
{
|
||||
var package = _packages.Where(item => item.PackageId == packagename).FirstOrDefault();
|
||||
if (package != null)
|
||||
|
|
|
@ -5,31 +5,35 @@
|
|||
@inject IStringLocalizer<Export> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="content" HelpText="Enter the module content" ResourceKey="Content">Content: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea id="content" class="form-control" @bind="@_content" rows="5"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="content" HelpText="The Exported Module Content" ResourceKey="Content">Content: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="content" class="form-control" @bind="@_content" rows="5" readonly></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-success" @onclick="ExportModule">@Localizer["Export"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
|
||||
|
||||
@code {
|
||||
private string _content = string.Empty;
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||
public override string Title => "Export Content";
|
||||
|
||||
|
||||
private async Task ExportModule()
|
||||
{
|
||||
_content = await ModuleService.ExportModuleAsync(ModuleState.ModuleId);
|
||||
try
|
||||
{
|
||||
_content = await ModuleService.ExportModuleAsync(ModuleState.ModuleId);
|
||||
AddModuleMessage(Localizer["Success.Content.Export"], MessageType.Success);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Exporting Module {ModuleId} {Error}", ModuleState.ModuleId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Module.Export"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,53 +5,63 @@
|
|||
@inject IStringLocalizer<Import> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="content" HelpText="Enter the module content" ResourceKey="Content">Content: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea id="content" class="form-control" @bind="@_content" rows="5"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="ImportModule">@Localizer["Import"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="content" HelpText="Enter The Module Content To Import" ResourceKey="Content">Content: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="content" class="form-control" @bind="@_content" rows="5" required></textarea>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn btn-success" @onclick="ImportModule">@Localizer["Import"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
</form>
|
||||
|
||||
@code {
|
||||
private string _content = string.Empty;
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||
public override string Title => "Import Content";
|
||||
|
||||
private async Task ImportModule()
|
||||
{
|
||||
if (_content != string.Empty)
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
try
|
||||
if (_content != string.Empty)
|
||||
{
|
||||
bool success = await ModuleService.ImportModuleAsync(ModuleState.ModuleId, _content);
|
||||
if (success)
|
||||
try
|
||||
{
|
||||
AddModuleMessage(Localizer["Success.Content.Import"], MessageType.Success);
|
||||
bool success = await ModuleService.ImportModuleAsync(ModuleState.ModuleId, _content);
|
||||
if (success)
|
||||
{
|
||||
AddModuleMessage(Localizer["Success.Content.Import"], MessageType.Success);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Content.ImportProblem"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Content.ImportProblem"], MessageType.Warning);
|
||||
await logger.LogError(ex, "Error Importing Module {ModuleId} {Error}", ModuleState.ModuleId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Module.Import"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
await logger.LogError(ex, "Error Importing Module {ModuleId} {Error}", ModuleState.ModuleId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Module.Import"], MessageType.Error);
|
||||
AddModuleMessage(Localizer["Message.Required.ImportContent"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Required.ImportContent"], MessageType.Warning);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,97 +8,93 @@
|
|||
@inject IStringLocalizer<Settings> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
<TabStrip>
|
||||
<TabPanel Name="Settings" Heading="Settings" ResourceKey="Settings">
|
||||
@if (_containers != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="title" HelpText="Enter the title of the module" ResourceKey="Title">Title: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="title" type="text" name="Title" class="form-control" @bind="@_title" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="container" HelpText="Select the module's container" ResourceKey="Container">Container: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="container" class="form-select" @bind="@_containerType">
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="allpages" HelpText="Indicate if this module should be displayed on all pages" ResourceKey="DisplayOnAllPages">Display On All Pages? </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="allpages" class="form-select" @bind="@_allPages">
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="page" HelpText="The page that the module is located on" ResourceKey="Page">Page: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="page" class="form-select" @bind="@_pageId">
|
||||
@foreach (Page p in PageState.Pages)
|
||||
{
|
||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<TabStrip>
|
||||
<TabPanel Name="Settings" Heading="Settings" ResourceKey="Settings">
|
||||
@if (_containers != null)
|
||||
{
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="title" HelpText="Enter the title of the module" ResourceKey="Title">Title: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="title" type="text" name="Title" class="form-control" @bind="@_title" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="container" HelpText="Select the module's container" ResourceKey="Container">Container: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="container" class="form-select" @bind="@_containerType" required>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@p.PageId">@(new string('-', p.Level * 2))@(p.Name)</option>
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
}
|
||||
</TabPanel>
|
||||
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
||||
@if (_permissions != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="allpages" HelpText="Indicate if this module should be displayed on all pages" ResourceKey="DisplayOnAllPages">Display On All Pages? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="allpages" class="form-select" @bind="@_allPages" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="page" HelpText="The page that the module is located on" ResourceKey="Page">Page: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="page" class="form-select" @bind="@_pageId" required>
|
||||
@foreach (Page p in PageState.Pages)
|
||||
{
|
||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
|
||||
{
|
||||
<option value="@p.PageId">@(new string('-', p.Level * 2))@(p.Name)</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</TabPanel>
|
||||
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
||||
@if (_permissions != null)
|
||||
{
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<PermissionGrid EntityName="@EntityNames.Module" PermissionNames="@_permissionNames" Permissions="@_permissions" @ref="_permissionGrid" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
</TabPanel>
|
||||
@if (_moduleSettingsType != null)
|
||||
{
|
||||
<TabPanel Name="ModuleSettings" Heading="@_moduleSettingsTitle" ResourceKey="ModuleSettings">
|
||||
@ModuleSettingsComponent
|
||||
</TabPanel>
|
||||
}
|
||||
</TabPanel>
|
||||
@if (_moduleSettingsType != null)
|
||||
{
|
||||
<TabPanel Name="ModuleSettings" Heading="@_moduleSettingsTitle" ResourceKey="ModuleSettings">
|
||||
@ModuleSettingsComponent
|
||||
</TabPanel>
|
||||
}
|
||||
@if (_containerSettingsType != null)
|
||||
{
|
||||
<TabPanel Name="ContainerSettings" Heading="Container Settings" ResourceKey="ContainerSettings">
|
||||
@ContainerSettingsComponent
|
||||
</TabPanel>
|
||||
}
|
||||
</TabStrip>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveModule">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
|
||||
@if (_containerSettingsType != null)
|
||||
{
|
||||
<TabPanel Name="ContainerSettings" Heading="Container Settings" ResourceKey="ContainerSettings">
|
||||
@ContainerSettingsComponent
|
||||
</TabPanel>
|
||||
}
|
||||
</TabStrip>
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveModule">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
|
||||
</form>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||
public override string Title => "Module Settings";
|
||||
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
private List<Theme> _themes;
|
||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||
private string _title;
|
||||
|
@ -179,52 +175,61 @@
|
|||
|
||||
private async Task SaveModule()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_title))
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
|
||||
pagemodule.PageId = int.Parse(_pageId);
|
||||
pagemodule.Title = _title;
|
||||
pagemodule.ContainerType = (_containerType != "-") ? _containerType : string.Empty;
|
||||
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Page.DefaultContainerType)
|
||||
if (!string.IsNullOrEmpty(_title))
|
||||
{
|
||||
pagemodule.ContainerType = string.Empty;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Site.DefaultContainerType)
|
||||
{
|
||||
pagemodule.ContainerType = string.Empty;
|
||||
}
|
||||
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)
|
||||
var pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
|
||||
pagemodule.PageId = int.Parse(_pageId);
|
||||
pagemodule.Title = _title;
|
||||
pagemodule.ContainerType = (_containerType != "-") ? _containerType : string.Empty;
|
||||
if (!string.IsNullOrEmpty(pagemodule.ContainerType) && pagemodule.ContainerType == PageState.Page.DefaultContainerType)
|
||||
{
|
||||
// module settings updated using explicit interface
|
||||
await moduleSettingsControl.UpdateSettings();
|
||||
pagemodule.ContainerType = string.Empty;
|
||||
}
|
||||
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 )
|
||||
_moduleSettings?.GetType().GetMethod("UpdateSettings")?.Invoke(_moduleSettings, null);
|
||||
pagemodule.ContainerType = string.Empty;
|
||||
}
|
||||
}
|
||||
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["Message.Required.Title"], MessageType.Warning);
|
||||
}
|
||||
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Required.Title"], MessageType.Warning);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,176 +6,154 @@
|
|||
@inject IStringLocalizer<Add> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
<TabStrip Refresh="@_refresh">
|
||||
<TabPanel Name="Settings" ResourceKey="Settings">
|
||||
@if (_themeList != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="Name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="Name" class="form-control" @bind="@_name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="Parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="Parent" class="form-select" @onchange="(e => ParentChanged(e))">
|
||||
<option value="-1"><@Localizer["SiteRoot"]></option>
|
||||
@foreach (Page page in _pageList)
|
||||
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<TabStrip Refresh="@_refresh">
|
||||
<TabPanel Name="Settings" ResourceKey="Settings">
|
||||
@if (_themeList != null)
|
||||
{
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="name" class="form-control" @bind="@_name" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="parent" class="form-select" @onchange="(e => ParentChanged(e))" required>
|
||||
<option value="-1"><@Localizer["SiteRoot"]></option>
|
||||
@foreach (Page page in _pageList)
|
||||
{
|
||||
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="insert" HelpText="Select the location where you would like the page to be inserted in relation to other pages" ResourceKey="Insert">Insert: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="insert" class="form-select" @bind="@_insert" required>
|
||||
<option value="<<">@Localizer["AtBeginning"]</option>
|
||||
@if (_children != null && _children.Count > 0)
|
||||
{
|
||||
<option value="<">@Localizer["Before"]</option>
|
||||
<option value=">">@Localizer["After"]</option>
|
||||
}
|
||||
<option value=">>">@Localizer["AtEnd"]</option>
|
||||
</select>
|
||||
@if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">"))
|
||||
{
|
||||
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
||||
<select class="form-select" @bind="@_childid">
|
||||
<option value="-1"><@Localizer["Page.Select"]></option>
|
||||
@foreach (Page page in _children)
|
||||
{
|
||||
<option value="@(page.PageId)">@(page.Name)</option>
|
||||
}
|
||||
</select>
|
||||
}
|
||||
</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-select" @bind="@_insert">
|
||||
<option value="<<">@Localizer["AtBeginning"]</option>
|
||||
@if (_children != null && _children.Count > 0)
|
||||
{
|
||||
<option value="<">@Localizer["Before"]</option>
|
||||
<option value=">">@Localizer["After"]</option>
|
||||
}
|
||||
<option value=">>">@Localizer["AtEnd"]</option>
|
||||
</select>
|
||||
@if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">"))
|
||||
{
|
||||
<select class="form-select" @bind="@_childid">
|
||||
<option value="-1"><@Localizer["Page.Select"]></option>
|
||||
@foreach (Page page in _children)
|
||||
{
|
||||
<option value="@(page.PageId)">@(page.Name)</option>
|
||||
}
|
||||
</select>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="navigation" class="form-select" @bind="@_isnavigation">
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="clickable" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="clickable" class="form-select" @bind="@_isclickable">
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["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">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="Title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="Title" class="form-control" @bind="@_title" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="Theme" HelpText="Select the theme for this page" ResourceKey="Theme">Theme: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="Theme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))">
|
||||
@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 page" ResourceKey="DefaultContainer">Default Container: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="defaultContainer" class="form-select" @bind="@_containertype">
|
||||
<option value="-"><@Localizer["Container.Select"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="Icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="Icon" class="form-control" @bind="@_icon" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="Personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="Personalizable" class="form-select" @bind="@_ispersonalizable">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="navigation" class="form-select" @bind="@_isnavigation" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</Section>
|
||||
}
|
||||
</TabPanel>
|
||||
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<PermissionGrid EntityName="@EntityNames.Page" Permissions="@_permissions" @ref="_permissionGrid" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</TabPanel>
|
||||
@if (_themeSettingsType != null)
|
||||
{
|
||||
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
|
||||
@ThemeSettingsComponent
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="clickable" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="clickable" class="form-select" @bind="@_isclickable" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" 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>
|
||||
<div class="col-sm-9">
|
||||
<input id="path" class="form-control" @bind="@_path" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="url" HelpText="Optionally enter a url which this page should redirect to when a user navigates to it" ResourceKey="Redirect">Redirect: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="url" class="form-control" @bind="@_url" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Section Name="Appearance" ResourceKey="Appearance">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="title" class="form-control" @bind="@_title" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="theme" HelpText="Select the theme for this page" ResourceKey="Theme">Theme: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="theme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))" required>
|
||||
@foreach (var theme in _themes)
|
||||
{
|
||||
<option value="@theme.TypeName">@theme.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="container" HelpText="Select the default container for the page" ResourceKey="DefaultContainer">Default Container: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="container" class="form-select" @bind="@_containertype" required>
|
||||
<option value="-"><@Localizer["Container.Select"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="icon" class="form-control" @bind="@_icon" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="personalizable" class="form-select" @bind="@_ispersonalizable" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
}
|
||||
</TabPanel>
|
||||
}
|
||||
</TabStrip>
|
||||
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<PermissionGrid EntityName="@EntityNames.Page" Permissions="@_permissions" @ref="_permissionGrid" />
|
||||
</div>
|
||||
</div>
|
||||
</TabPanel>
|
||||
@if (_themeSettingsType != null)
|
||||
{
|
||||
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
|
||||
@ThemeSettingsComponent
|
||||
</TabPanel>
|
||||
}
|
||||
</TabStrip>
|
||||
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||
</form>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||
|
@ -187,7 +165,7 @@
|
|||
private string _name;
|
||||
private string _title;
|
||||
private string _path = string.Empty;
|
||||
private string _parentid;
|
||||
private string _parentid = "-1";
|
||||
private string _insert = ">>";
|
||||
private List<Page> _children;
|
||||
private int _childid = -1;
|
||||
|
@ -204,6 +182,8 @@
|
|||
private object _themeSettings;
|
||||
private RenderFragment ThemeSettingsComponent { get; set; }
|
||||
private bool _refresh = false;
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
|
@ -300,110 +280,125 @@
|
|||
|
||||
private async Task SavePage()
|
||||
{
|
||||
Page page = null;
|
||||
try
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_name) && !string.IsNullOrEmpty(_themetype) && _containertype != "-")
|
||||
Page page = null;
|
||||
try
|
||||
{
|
||||
page = new Page();
|
||||
page.SiteId = PageState.Page.SiteId;
|
||||
page.Name = _name;
|
||||
page.Title = _title;
|
||||
if (_path == "")
|
||||
if (!string.IsNullOrEmpty(_themetype) && _containertype != "-")
|
||||
{
|
||||
_path = _name;
|
||||
}
|
||||
|
||||
if (_path.Contains("/"))
|
||||
{
|
||||
_path = _path.Substring(_path.LastIndexOf("/") + 1);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(_parentid))
|
||||
{
|
||||
page.ParentId = null;
|
||||
page.Path = Utilities.GetFriendlyUrl(_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
page.ParentId = Int32.Parse(_parentid);
|
||||
var parent = PageState.Pages.Where(item => item.PageId == page.ParentId).FirstOrDefault();
|
||||
if (parent.Path == string.Empty)
|
||||
page = new Page();
|
||||
page.SiteId = PageState.Page.SiteId;
|
||||
page.Name = _name;
|
||||
page.Title = _title;
|
||||
if (string.IsNullOrEmpty(_path))
|
||||
{
|
||||
page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path);
|
||||
_path = _name;
|
||||
}
|
||||
|
||||
if (_path.Contains("/"))
|
||||
{
|
||||
_path = _path.Substring(_path.LastIndexOf("/") + 1);
|
||||
}
|
||||
|
||||
if (_parentid == "-1")
|
||||
{
|
||||
page.ParentId = null;
|
||||
page.Path = Utilities.GetFriendlyUrl(_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path);
|
||||
page.ParentId = Int32.Parse(_parentid);
|
||||
var parent = PageState.Pages.Where(item => item.PageId == page.ParentId).FirstOrDefault();
|
||||
if (parent.Path == string.Empty)
|
||||
{
|
||||
page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!PagePathIsUnique(page.Path, page.SiteId, _pageList))
|
||||
{
|
||||
AddModuleMessage(string.Format(Localizer["Message.Page.Exists"], _path), MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
if(PagePathIsDeleted(page.Path, page.SiteId, _pageList))
|
||||
{
|
||||
AddModuleMessage(string.Format(Localizer["Message.Page.Deleted"], _path), MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
Page child;
|
||||
switch (_insert)
|
||||
{
|
||||
case "<<":
|
||||
page.Order = 0;
|
||||
break;
|
||||
case "<":
|
||||
child = PageState.Pages.Where(item => item.PageId == _childid).FirstOrDefault();
|
||||
page.Order = child.Order - 1;
|
||||
break;
|
||||
case ">":
|
||||
child = PageState.Pages.Where(item => item.PageId == _childid).FirstOrDefault();
|
||||
page.Order = child.Order + 1;
|
||||
break;
|
||||
case ">>":
|
||||
page.Order = int.MaxValue;
|
||||
break;
|
||||
}
|
||||
if (!PagePathIsUnique(page.Path, page.SiteId, _pageList))
|
||||
{
|
||||
AddModuleMessage(string.Format(Localizer["Message.Page.Exists"], _path), MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
page.IsNavigation = (_isnavigation == null ? true : Boolean.Parse(_isnavigation));
|
||||
page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
|
||||
page.Url = _url;
|
||||
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
||||
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
|
||||
{
|
||||
page.ThemeType = string.Empty;
|
||||
}
|
||||
page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
|
||||
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
|
||||
{
|
||||
page.DefaultContainerType = string.Empty;
|
||||
}
|
||||
page.Icon = (_icon == null ? string.Empty : _icon);
|
||||
page.Permissions = _permissionGrid.GetPermissions();
|
||||
page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable));
|
||||
page.UserId = null;
|
||||
Page child;
|
||||
switch (_insert)
|
||||
{
|
||||
case "<<":
|
||||
page.Order = 0;
|
||||
break;
|
||||
case "<":
|
||||
child = PageState.Pages.Where(item => item.PageId == _childid).FirstOrDefault();
|
||||
page.Order = child.Order - 1;
|
||||
break;
|
||||
case ">":
|
||||
child = PageState.Pages.Where(item => item.PageId == _childid).FirstOrDefault();
|
||||
page.Order = child.Order + 1;
|
||||
break;
|
||||
case ">>":
|
||||
page.Order = int.MaxValue;
|
||||
break;
|
||||
}
|
||||
|
||||
page = await PageService.AddPageAsync(page);
|
||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId);
|
||||
page.IsNavigation = (_isnavigation == null ? true : Boolean.Parse(_isnavigation));
|
||||
page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
|
||||
page.Url = _url;
|
||||
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
||||
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
|
||||
{
|
||||
page.ThemeType = string.Empty;
|
||||
}
|
||||
page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
|
||||
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
|
||||
{
|
||||
page.DefaultContainerType = string.Empty;
|
||||
}
|
||||
page.Icon = (_icon == null ? string.Empty : _icon);
|
||||
page.Permissions = _permissionGrid.GetPermissions();
|
||||
page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable));
|
||||
page.UserId = null;
|
||||
|
||||
await logger.LogInformation("Page Added {Page}", page);
|
||||
if (PageState.QueryString.ContainsKey("cp"))
|
||||
{
|
||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Pages.First(item => item.PageId == int.Parse(PageState.QueryString["cp"])).Path));
|
||||
page = await PageService.AddPageAsync(page);
|
||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId);
|
||||
|
||||
await logger.LogInformation("Page Added {Page}", page);
|
||||
if (PageState.QueryString.ContainsKey("cp"))
|
||||
{
|
||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Pages.First(item => item.PageId == int.Parse(PageState.QueryString["cp"])).Path));
|
||||
}
|
||||
else
|
||||
{
|
||||
NavigationManager.NavigateTo(NavigateUrl(page.Path));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NavigationManager.NavigateTo(NavigateUrl(page.Path));
|
||||
AddModuleMessage(Localizer["Message.Required.PageInfo"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Required.PageInfo"], MessageType.Warning);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving Page {Page} {Error}", page, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Page.Save"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving Page {Page} {Error}", page, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Page.Save"], MessageType.Error);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -423,4 +418,9 @@
|
|||
{
|
||||
return !existingPages.Any(page => page.SiteId == siteId && page.Path == pagePath);
|
||||
}
|
||||
|
||||
private static bool PagePathIsDeleted(string pagePath, int siteId, List<Page> existingPages)
|
||||
{
|
||||
return existingPages.Any(page => page.SiteId == siteId && page.Path == pagePath && page.IsDeleted == true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,192 +7,173 @@
|
|||
@inject IStringLocalizer<Edit> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
<TabStrip Refresh="@_refresh">
|
||||
<TabPanel Name="Settings" ResourceKey="Settings">
|
||||
@if (_themeList != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="Name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="Name" class="form-control" @bind="@_name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="Parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="Parent" class="form-select" value="@_parentid" @onchange="(e => ParentChanged(e))">
|
||||
<option value="-1"><@Localizer["SiteRoot"]></option>
|
||||
@foreach (Page page in _pageList)
|
||||
{
|
||||
if (page.PageId != _pageId)
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<TabStrip Refresh="@_refresh">
|
||||
<TabPanel Name="Settings" ResourceKey="Settings">
|
||||
@if (_themeList != null)
|
||||
{
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="name" class="form-control" @bind="@_name" maxlength="50" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="parent" class="form-select" value="@_parentid" @onchange="(e => ParentChanged(e))" required>
|
||||
<option value="-1"><@Localizer["SiteRoot"]></option>
|
||||
@foreach (Page page in _pageList)
|
||||
{
|
||||
<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-select" @bind="@_insert">
|
||||
@if (_parentid == _currentparentid)
|
||||
{
|
||||
<option value="="><@Localizer["ThisLocation.Keep"]></option>
|
||||
}
|
||||
<option value="<<">@Localizer["ToBeginning"]</option>
|
||||
@if (_children != null && _children.Count > 0)
|
||||
{
|
||||
<option value="<">@Localizer["Before"]</option>
|
||||
<option value=">">@Localizer["After"]</option>
|
||||
}
|
||||
<option value=">>">@Localizer["ToEnd"]</option>
|
||||
</select>
|
||||
@if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">"))
|
||||
{
|
||||
<select class="form-select" @bind="@_childid">
|
||||
<option value="-1"><@Localizer["Page.Select"]></option>
|
||||
@foreach (Page page in _children)
|
||||
{
|
||||
<option value="@(page.PageId)">@(page.Name)</option>
|
||||
if (page.PageId != _pageId)
|
||||
{
|
||||
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="Navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="Navigation" class="form-select" @bind="@_isnavigation">
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="Clickablen" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="Navigation" class="form-select" @bind="@_isclickable">
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["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">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="Title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="Title" class="form-control" @bind="@_title" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="Theme" HelpText="Select the theme for this page" ResourceKey="Theme">Theme: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="Theme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))">
|
||||
@foreach (var theme in _themes)
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="move" HelpText="Select the location where you would like the page to be moved in relation to other pages" ResourceKey="Move">Move: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="move" class="form-select" @bind="@_insert" required>
|
||||
@if (_parentid == _currentparentid)
|
||||
{
|
||||
<option value="@theme.TypeName">@theme.Name</option>
|
||||
<option value="="><@Localizer["ThisLocation.Keep"]></option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="defaultContainer" HelpText="Select the default container for the page" ResourceKey="DefaultContainer">Default Container: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="defaultContainer" class="form-select" @bind="@_containertype">
|
||||
<option value="-"><@Localizer["Container.Select"]></option>
|
||||
@foreach (var container in _containers)
|
||||
<option value="<<">@Localizer["ToBeginning"]</option>
|
||||
@if (_children != null && _children.Count > 0)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
<option value="<">@Localizer["Before"]</option>
|
||||
<option value=">">@Localizer["After"]</option>
|
||||
}
|
||||
<option value=">>">@Localizer["ToEnd"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="Icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="Icon" class="form-control" @bind="@_icon" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="Personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="Personalizable" class="form-select" @bind="@_ispersonalizable">
|
||||
@if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">"))
|
||||
{
|
||||
<select class="form-select" @bind="@_childid">
|
||||
<option value="-1"><@Localizer["Page.Select"]></option>
|
||||
@foreach (Page page in _children)
|
||||
{
|
||||
<option value="@(page.PageId)">@(page.Name)</option>
|
||||
}
|
||||
</select>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="navigation" class="form-select" @bind="@_isnavigation" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</Section>
|
||||
<br /><br />
|
||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
|
||||
}
|
||||
</TabPanel>
|
||||
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
||||
@if (_permissions != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<PermissionGrid EntityName="@EntityNames.Page" Permissions="@_permissions" @ref="_permissionGrid" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
}
|
||||
</TabPanel>
|
||||
@if (_themeSettingsType != null)
|
||||
{
|
||||
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
|
||||
@ThemeSettingsComponent
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="clickable" HelpText="Select whether the link in the site navigation is enabled or disabled" ResourceKey="Clickable">Clickable? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="clickable" class="form-select" @bind="@_isclickable" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" 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>
|
||||
<div class="col-sm-9">
|
||||
<input id="path" class="form-control" @bind="@_path" maxlength="256"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="url" HelpText="Optionally enter a url which this page should redirect to when a user navigates to it" ResourceKey="Redirect">Redirect: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="url" class="form-control" @bind="@_url" maxlength="500"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Section Name="Appearance" ResourceKey="Appearance">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="title" class="form-control" @bind="@_title" maxlength="200"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="theme" HelpText="Select the theme for this page" ResourceKey="Theme">Theme: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="theme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))" required>
|
||||
@foreach (var theme in _themes)
|
||||
{
|
||||
<option value="@theme.TypeName">@theme.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="container" HelpText="Select the default container for the page" ResourceKey="DefaultContainer">Default Container: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="container" class="form-select" @bind="@_containertype" required>
|
||||
<option value="-"><@Localizer["Container.Select"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="icon" class="form-control" @bind="@_icon" maxlength="50"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="personalizable" class="form-select" @bind="@_ispersonalizable" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
<br /><br />
|
||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
|
||||
}
|
||||
</TabPanel>
|
||||
}
|
||||
</TabStrip>
|
||||
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
||||
@if (_permissions != null)
|
||||
{
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<PermissionGrid EntityName="@EntityNames.Page" Permissions="@_permissions" @ref="_permissionGrid" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
</TabPanel>
|
||||
@if (_themeSettingsType != null)
|
||||
{
|
||||
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
|
||||
@ThemeSettingsComponent
|
||||
</TabPanel>
|
||||
<br />
|
||||
}
|
||||
</TabStrip>
|
||||
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||
</form>
|
||||
|
||||
@code {
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
private List<Theme> _themeList;
|
||||
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||
|
@ -202,7 +183,7 @@
|
|||
private string _title;
|
||||
private string _path;
|
||||
private string _currentparentid;
|
||||
private string _parentid;
|
||||
private string _parentid = "-1";
|
||||
private string _insert = "=";
|
||||
private List<Page> _children;
|
||||
private int _childid = -1;
|
||||
|
@ -251,7 +232,7 @@
|
|||
|
||||
if (page.ParentId == null)
|
||||
{
|
||||
_parentid = string.Empty;
|
||||
_parentid = "-1";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -375,134 +356,142 @@
|
|||
|
||||
private async Task SavePage()
|
||||
{
|
||||
Page page = null;
|
||||
try
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
if (_name != string.Empty && !string.IsNullOrEmpty(_themetype) && _containertype != "-")
|
||||
Page page = null;
|
||||
try
|
||||
{
|
||||
page = PageState.Pages.FirstOrDefault(item => item.PageId == _pageId);
|
||||
string currentPath = page.Path;
|
||||
if (!string.IsNullOrEmpty(_themetype) && _containertype != "-")
|
||||
{
|
||||
page = PageState.Pages.FirstOrDefault(item => item.PageId == _pageId);
|
||||
string currentPath = page.Path;
|
||||
|
||||
page.Name = _name;
|
||||
page.Title = _title;
|
||||
if (_path == "" && _name.ToLower() != "home")
|
||||
if (_path == string.Empty && _name.ToLower() != "home")
|
||||
page.Name = _name;
|
||||
page.Title = _title;
|
||||
if (string.IsNullOrEmpty(_path) && _name.ToLower() != "home")
|
||||
{
|
||||
_path = _name;
|
||||
}
|
||||
if (_path.Contains("/"))
|
||||
{
|
||||
_path = _path.Substring(_path.LastIndexOf("/") + 1);
|
||||
}
|
||||
if (string.IsNullOrEmpty(_parentid) || _parentid == "-1")
|
||||
{
|
||||
page.ParentId = null;
|
||||
page.Path = Utilities.GetFriendlyUrl(_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
page.ParentId = Int32.Parse(_parentid);
|
||||
Page parent = PageState.Pages.FirstOrDefault(item => item.PageId == page.ParentId);
|
||||
if (parent.Path == string.Empty)
|
||||
if (_path.Contains("/"))
|
||||
{
|
||||
page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path);
|
||||
_path = _path.Substring(_path.LastIndexOf("/") + 1);
|
||||
}
|
||||
if (_parentid == "-1")
|
||||
{
|
||||
page.ParentId = null;
|
||||
page.Path = Utilities.GetFriendlyUrl(_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path);
|
||||
page.ParentId = Int32.Parse(_parentid);
|
||||
Page parent = PageState.Pages.FirstOrDefault(item => item.PageId == page.ParentId);
|
||||
if (parent.Path == string.Empty)
|
||||
{
|
||||
page.Path = Utilities.GetFriendlyUrl(parent.Name) + "/" + Utilities.GetFriendlyUrl(_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
page.Path = parent.Path + "/" + Utilities.GetFriendlyUrl(_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!PagePathIsUnique(page.Path, page.SiteId, page.PageId, _pageList))
|
||||
{
|
||||
AddModuleMessage(string.Format(Localizer["Mesage.Page.PathExists"], _path), MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_insert != "=")
|
||||
{
|
||||
Page child;
|
||||
switch (_insert)
|
||||
if (!PagePathIsUnique(page.Path, page.SiteId, page.PageId, _pageList))
|
||||
{
|
||||
case "<<":
|
||||
page.Order = 0;
|
||||
break;
|
||||
case "<":
|
||||
child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid);
|
||||
if (child != null) page.Order = child.Order - 1;
|
||||
break;
|
||||
case ">":
|
||||
child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid);
|
||||
if (child != null) page.Order = child.Order + 1;
|
||||
break;
|
||||
case ">>":
|
||||
page.Order = int.MaxValue;
|
||||
break;
|
||||
AddModuleMessage(string.Format(Localizer["Mesage.Page.PathExists"], _path), MessageType.Warning);
|
||||
return;
|
||||
}
|
||||
}
|
||||
page.IsNavigation = (_isnavigation == null || Boolean.Parse(_isnavigation));
|
||||
page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
|
||||
page.Url = _url;
|
||||
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
||||
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
|
||||
{
|
||||
page.ThemeType = string.Empty;
|
||||
}
|
||||
page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
|
||||
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
|
||||
{
|
||||
page.DefaultContainerType = string.Empty;
|
||||
}
|
||||
page.Icon = _icon ?? string.Empty;
|
||||
page.Permissions = _permissionGrid.GetPermissions();
|
||||
page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable));
|
||||
page.UserId = null;
|
||||
|
||||
page = await PageService.UpdatePageAsync(page);
|
||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId);
|
||||
if (_currentparentid == string.Empty)
|
||||
{
|
||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, null);
|
||||
if (_insert != "=")
|
||||
{
|
||||
Page child;
|
||||
switch (_insert)
|
||||
{
|
||||
case "<<":
|
||||
page.Order = 0;
|
||||
break;
|
||||
case "<":
|
||||
child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid);
|
||||
if (child != null) page.Order = child.Order - 1;
|
||||
break;
|
||||
case ">":
|
||||
child = PageState.Pages.FirstOrDefault(item => item.PageId == _childid);
|
||||
if (child != null) page.Order = child.Order + 1;
|
||||
break;
|
||||
case ">>":
|
||||
page.Order = int.MaxValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
page.IsNavigation = (_isnavigation == null || Boolean.Parse(_isnavigation));
|
||||
page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
|
||||
page.Url = _url;
|
||||
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
||||
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
|
||||
{
|
||||
page.ThemeType = string.Empty;
|
||||
}
|
||||
page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
|
||||
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
|
||||
{
|
||||
page.DefaultContainerType = string.Empty;
|
||||
}
|
||||
page.Icon = _icon ?? string.Empty;
|
||||
page.Permissions = _permissionGrid.GetPermissions();
|
||||
page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable));
|
||||
page.UserId = null;
|
||||
|
||||
page = await PageService.UpdatePageAsync(page);
|
||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId);
|
||||
if (_currentparentid == string.Empty)
|
||||
{
|
||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, int.Parse(_currentparentid));
|
||||
}
|
||||
|
||||
// update child paths
|
||||
if (_parentid != _currentparentid)
|
||||
{
|
||||
foreach (Page p in PageState.Pages.Where(item => item.Path.StartsWith(currentPath)))
|
||||
{
|
||||
p.Path = p.Path.Replace(currentPath, page.Path);
|
||||
await PageService.UpdatePageAsync(p);
|
||||
}
|
||||
}
|
||||
|
||||
if (_themeSettingsType != null && _themeSettings is ISettingsControl themeSettingsControl)
|
||||
{
|
||||
await themeSettingsControl.UpdateSettings();
|
||||
}
|
||||
|
||||
await logger.LogInformation("Page Saved {Page}", page);
|
||||
if (PageState.QueryString.ContainsKey("cp"))
|
||||
{
|
||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Pages.First(item => item.PageId == int.Parse(PageState.QueryString["cp"])).Path));
|
||||
}
|
||||
else
|
||||
{
|
||||
NavigationManager.NavigateTo(NavigateUrl(page.Path));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, int.Parse(_currentparentid));
|
||||
}
|
||||
|
||||
// update child paths
|
||||
if (_parentid != _currentparentid)
|
||||
{
|
||||
foreach (Page p in PageState.Pages.Where(item => item.Path.StartsWith(currentPath)))
|
||||
{
|
||||
p.Path = p.Path.Replace(currentPath, page.Path);
|
||||
await PageService.UpdatePageAsync(p);
|
||||
}
|
||||
}
|
||||
|
||||
if (_themeSettingsType != null && _themeSettings is ISettingsControl themeSettingsControl)
|
||||
{
|
||||
await themeSettingsControl.UpdateSettings();
|
||||
}
|
||||
|
||||
await logger.LogInformation("Page Saved {Page}", page);
|
||||
if (PageState.QueryString.ContainsKey("cp"))
|
||||
{
|
||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Pages.First(item => item.PageId == int.Parse(PageState.QueryString["cp"])).Path));
|
||||
}
|
||||
else
|
||||
{
|
||||
NavigationManager.NavigateTo(NavigateUrl(page.Path));
|
||||
AddModuleMessage(Localizer["Message.Required.PageInfo"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Required.PageInfo"], MessageType.Warning);
|
||||
await logger.LogError(ex, "Error Saving Page {Page} {Error}", page, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Page.Save"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving Page {Page} {Error}", page, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Page.Save"], MessageType.Error);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,105 +5,90 @@
|
|||
@inject IStringLocalizer<Edit> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="name" HelpText="The name of this profile item" ResourceKey="Name">Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="name" class="form-control" @bind="@_name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="title" HelpText="The title of the profile item to display to the user" ResourceKey="Title">Title: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="title" class="form-control" @bind="@_title" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="description" HelpText="The help text displayed to the user for this profile item" ResourceKey="Description">Description: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea id="description" class="form-control" @bind="@_description" rows="5"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="category" HelpText="The category of this profile item (for grouping)" ResourceKey="Category">Category: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="category" class="form-control" @bind="@_category" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="order" HelpText="The index order of where this profile item should be displayed" ResourceKey="Order">Order: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="order" class="form-control" @bind="@_vieworder" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="length" HelpText="The max number of characters this profile item should accept (enter zero for unlimited)" ResourceKey="Length">Length: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="length" class="form-control" @bind="@_maxlength" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="defaultVal" HelpText="The default value for this profile item" ResourceKey="DefaultValue">Default Value: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="defaultVal" class="form-control" @bind="@_defaultvalue" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="options" HelpText="A comma delimited list of options the user can select from" ResourceKey="Options">Options: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="options" class="form-control" @bind="@_options" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="required" HelpText="Should a user be required to provide a value for this profile item?" ResourceKey="Required">Required? </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="required" class="form-select" @bind="@_isrequired">
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="private" HelpText="Should this profile item be visible to all users?" ResourceKey="Private">Private? </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="private" class="form-select" @bind="@_isprivate">
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveProfile">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
@if (PageState.QueryString.ContainsKey("id"))
|
||||
{
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="name" HelpText="The name of this profile item" ResourceKey="Name">Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="name" class="form-control" @bind="@_name" maxlength="50" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="title" HelpText="The title of the profile item to display to the user" ResourceKey="Title">Title: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="title" class="form-control" @bind="@_title" maxlength="50" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="description" HelpText="The help text displayed to the user for this profile item" ResourceKey="Description">Description: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="description" class="form-control" @bind="@_description" rows="5" maxlength="256" required ></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="category" HelpText="The category of this profile item (for grouping)" ResourceKey="Category">Category: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="category" class="form-control" @bind="@_category" maxlength="50" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="order" HelpText="The index order of where this profile item should be displayed" ResourceKey="Order">Order: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="order" class="form-control" @bind="@_vieworder" maxlength="4" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="length" HelpText="The max number of characters this profile item should accept (enter zero for unlimited)" ResourceKey="Length">Length: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="length" class="form-control" @bind="@_maxlength" maxlength="4" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="defaultVal" HelpText="The default value for this profile item" ResourceKey="DefaultValue">Default Value: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="defaultVal" class="form-control" @bind="@_defaultvalue" maxlength="2000"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="options" HelpText="A comma delimited list of options the user can select from" ResourceKey="Options">Options: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="options" class="form-control" @bind="@_options" maxlength="2000" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="required" HelpText="Should a user be required to provide a value for this profile item?" ResourceKey="Required">Required? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="required" class="form-select" @bind="@_isrequired" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="private" HelpText="Should this profile item be visible to all users?" ResourceKey="Private">Private? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="private" class="form-select" @bind="@_isprivate" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
|
||||
}
|
||||
<button type="button" class="btn btn-success" @onclick="SaveProfile">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
@if (PageState.QueryString.ContainsKey("id"))
|
||||
{
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon"></AuditInfo>
|
||||
}
|
||||
</form>
|
||||
|
||||
@code {
|
||||
private int _profileid = -1;
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
private string _name = string.Empty;
|
||||
private string _title = string.Empty;
|
||||
private string _description = string.Empty;
|
||||
|
@ -159,45 +144,54 @@
|
|||
|
||||
private async Task SaveProfile()
|
||||
{
|
||||
try
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
Profile profile;
|
||||
if (_profileid != -1)
|
||||
try
|
||||
{
|
||||
profile = await ProfileService.GetProfileAsync(_profileid);
|
||||
}
|
||||
else
|
||||
{
|
||||
profile = new Profile();
|
||||
}
|
||||
Profile profile;
|
||||
if (_profileid != -1)
|
||||
{
|
||||
profile = await ProfileService.GetProfileAsync(_profileid);
|
||||
}
|
||||
else
|
||||
{
|
||||
profile = new Profile();
|
||||
}
|
||||
|
||||
profile.SiteId = PageState.Site.SiteId;
|
||||
profile.Name = _name;
|
||||
profile.Title = _title;
|
||||
profile.Description = _description;
|
||||
profile.Category = _category;
|
||||
profile.ViewOrder = int.Parse(_vieworder);
|
||||
profile.MaxLength = int.Parse(_maxlength);
|
||||
profile.DefaultValue = _defaultvalue;
|
||||
profile.Options = _options;
|
||||
profile.IsRequired = (_isrequired == null ? false : Boolean.Parse(_isrequired));
|
||||
profile.IsPrivate = (_isprivate == null ? false : Boolean.Parse(_isprivate));
|
||||
if (_profileid != -1)
|
||||
{
|
||||
profile = await ProfileService.UpdateProfileAsync(profile);
|
||||
}
|
||||
else
|
||||
{
|
||||
profile = await ProfileService.AddProfileAsync(profile);
|
||||
}
|
||||
profile.SiteId = PageState.Site.SiteId;
|
||||
profile.Name = _name;
|
||||
profile.Title = _title;
|
||||
profile.Description = _description;
|
||||
profile.Category = _category;
|
||||
profile.ViewOrder = int.Parse(_vieworder);
|
||||
profile.MaxLength = int.Parse(_maxlength);
|
||||
profile.DefaultValue = _defaultvalue;
|
||||
profile.Options = _options;
|
||||
profile.IsRequired = (_isrequired == null ? false : Boolean.Parse(_isrequired));
|
||||
profile.IsPrivate = (_isprivate == null ? false : Boolean.Parse(_isprivate));
|
||||
if (_profileid != -1)
|
||||
{
|
||||
profile = await ProfileService.UpdateProfileAsync(profile);
|
||||
}
|
||||
else
|
||||
{
|
||||
profile = await ProfileService.AddProfileAsync(profile);
|
||||
}
|
||||
|
||||
await logger.LogInformation("Profile Saved {Profile}", profile);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
await logger.LogInformation("Profile Saved {Profile}", profile);
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving Profile {ProfleId} {Error}", _profileid, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Profile.Save"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving Profile {ProfleId} {Error}", _profileid, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Profile.Save"], MessageType.Error);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,52 +16,43 @@
|
|||
</Authorized>
|
||||
<NotAuthorized>
|
||||
<ModuleMessage Message="@Localizer["Info.Registration.InvalidEmail"]" Type="MessageType.Info" />
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="username" HelpText="Your username. Note that this field can not be modified once it is saved." ResourceKey="Username"></Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="username" class="form-control" @bind="@_username" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="password" HelpText="If you wish to change your password you can enter it here. Please choose a sufficiently secure password." ResourceKey="Password"></Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="password" type="password" class="form-control" @bind="@_password" autocomplete="new-password" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="confirm" HelpText="If you are changing your password you must enter it again to confirm it matches" ResourceKey="Confirm"></Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="confirm" type="password" class="form-control" @bind="@_confirm" autocomplete="new-password" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="email" HelpText="Your email address where you wish to receive notifications" ResourceKey="Email"></Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="email" class="form-control" @bind="@_email" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="displayname" HelpText="Your full name" ResourceKey="DisplayName"></Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="displayname" class="form-control" @bind="@_displayname" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<button type="button" class="btn btn-primary" @onclick="Register">@Localizer["Register"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="username" HelpText="Your username. Note that this field can not be modified once it is saved." ResourceKey="Username"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="username" class="form-control" @bind="@_username" maxlength="256" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="password" HelpText="Please choose a sufficiently secure password and enter it here" ResourceKey="Password"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="password" type="password" class="form-control" @bind="@_password" autocomplete="new-password" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="confirm" HelpText="Enter your password again to confirm it matches the value entered above" ResourceKey="Confirm"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="confirm" type="password" class="form-control" @bind="@_confirm" autocomplete="new-password" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="email" HelpText="Your email address where you wish to receive notifications" ResourceKey="Email"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="email" class="form-control" @bind="@_email" maxlength="256" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="displayname" HelpText="Your full name" ResourceKey="DisplayName"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="displayname" class="form-control" @bind="@_displayname" maxlength="50" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<button type="button" class="btn btn-primary" @onclick="Register">@Localizer["Register"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||
</form>
|
||||
</NotAuthorized>
|
||||
</AuthorizeView>
|
||||
}
|
||||
|
@ -72,6 +63,8 @@ else
|
|||
|
||||
@code {
|
||||
private string _username = string.Empty;
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
private string _password = string.Empty;
|
||||
private string _confirm = string.Empty;
|
||||
private string _email = string.Empty;
|
||||
|
@ -81,49 +74,58 @@ else
|
|||
|
||||
private async Task Register()
|
||||
{
|
||||
try
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
bool _isEmailValid = Utilities.IsValidEmail(_email);
|
||||
|
||||
if (_username != "" && _password != "" && _confirm != "" && _isEmailValid)
|
||||
try
|
||||
{
|
||||
if (_password == _confirm)
|
||||
{
|
||||
var user = new User
|
||||
{
|
||||
SiteId = PageState.Site.SiteId,
|
||||
Username = _username,
|
||||
DisplayName = (_displayname == string.Empty ? _username : _displayname),
|
||||
Email = _email,
|
||||
Password = _password
|
||||
};
|
||||
user = await UserService.AddUserAsync(user);
|
||||
bool _isEmailValid = Utilities.IsValidEmail(_email);
|
||||
|
||||
if (user != null)
|
||||
if (_isEmailValid)
|
||||
{
|
||||
if (_password == _confirm)
|
||||
{
|
||||
await logger.LogInformation("User Created {Username} {Email}", _username, _email);
|
||||
AddModuleMessage(Localizer["Info.User.AccountCreate"], MessageType.Info);
|
||||
var user = new User
|
||||
{
|
||||
SiteId = PageState.Site.SiteId,
|
||||
Username = _username,
|
||||
DisplayName = (_displayname == string.Empty ? _username : _displayname),
|
||||
Email = _email,
|
||||
Password = _password
|
||||
};
|
||||
user = await UserService.AddUserAsync(user);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
await logger.LogInformation("User Created {Username} {Email}", _username, _email);
|
||||
AddModuleMessage(Localizer["Info.User.AccountCreate"], MessageType.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogError("Error Adding User {Username} {Email}", _username, _email);
|
||||
AddModuleMessage(Localizer["Error.User.AddInfo"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogError("Error Adding User {Username} {Email}", _username, _email);
|
||||
AddModuleMessage(Localizer["Error.User.AddInfo"], MessageType.Error);
|
||||
AddModuleMessage(Localizer["Message.Password.NoMatch"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Password.NoMatch"], MessageType.Warning);
|
||||
AddModuleMessage(Localizer["Message.Required.UserInfo"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Required.UserInfo"], MessageType.Warning);
|
||||
await logger.LogError(ex, "Error Adding User {Username} {Email} {Error}", _username, _email, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.User.Add"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
await logger.LogError(ex, "Error Adding User {Username} {Email} {Error}", _username, _email, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.User.Add"], MessageType.Error);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,4 +133,4 @@ else
|
|||
{
|
||||
NavigationManager.NavigateTo(NavigateUrl(string.Empty));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,24 +5,28 @@
|
|||
@inject IStringLocalizer<Index> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
<div class="container">
|
||||
<div class="form-group">
|
||||
<label for="Username" class="control-label">@SharedLocalizer["Username"] </label>
|
||||
<input type="text" class="form-control" placeholder="Username" @bind="@_username" readonly id="Username" />
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<div class="container">
|
||||
<div class="form-group">
|
||||
<label for="Username" class="control-label">@SharedLocalizer["Username"] </label>
|
||||
<input type="text" class="form-control" placeholder="Username" @bind="@_username" readonly id="Username" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="Password" class="control-label">@SharedLocalizer["Password"] </label>
|
||||
<input type="password" class="form-control" placeholder="Password" @bind="@_password" id="Password" required />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="Confirm" class="control-label">@Localizer["Password.Confirm"] </label>
|
||||
<input type="password" class="form-control" placeholder="Password" @bind="@_confirm" id="Confirm" required />
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary" @onclick="Reset">@Localizer["Password.Reset"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="Password" class="control-label">@SharedLocalizer["Password"] </label>
|
||||
<input type="password" class="form-control" placeholder="Password" @bind="@_password" id="Password" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="Confirm" class="control-label">@Localizer["Password.Confirm"] </label>
|
||||
<input type="password" class="form-control" placeholder="Password" @bind="@_confirm" id="Confirm" />
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary" @onclick="Reset">@Localizer["Password.Reset"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@code {
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
private string _username = string.Empty;
|
||||
private string _password = string.Empty;
|
||||
private string _confirm = string.Empty;
|
||||
|
@ -43,45 +47,54 @@
|
|||
|
||||
private async Task Reset()
|
||||
{
|
||||
try
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
if (_username != string.Empty && _password != string.Empty && _confirm != string.Empty)
|
||||
try
|
||||
{
|
||||
if (_password == _confirm)
|
||||
if (_username != string.Empty && _password != string.Empty && _confirm != string.Empty)
|
||||
{
|
||||
var user = new User
|
||||
if (_password == _confirm)
|
||||
{
|
||||
SiteId = PageState.Site.SiteId,
|
||||
Username = _username,
|
||||
Password = _password
|
||||
};
|
||||
user = await UserService.ResetPasswordAsync(user, PageState.QueryString["token"]);
|
||||
var user = new User
|
||||
{
|
||||
SiteId = PageState.Site.SiteId,
|
||||
Username = _username,
|
||||
Password = _password
|
||||
};
|
||||
user = await UserService.ResetPasswordAsync(user, PageState.QueryString["token"]);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
await logger.LogInformation("User Password Reset {Username}", _username);
|
||||
NavigationManager.NavigateTo(NavigateUrl("login"));
|
||||
if (user != null)
|
||||
{
|
||||
await logger.LogInformation("User Password Reset {Username}", _username);
|
||||
NavigationManager.NavigateTo(NavigateUrl("login"));
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogError("Error Resetting User Password {Username}", _username);
|
||||
AddModuleMessage(Localizer["Error.Password.ResetInfo"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogError("Error Resetting User Password {Username}", _username);
|
||||
AddModuleMessage(Localizer["Error.Password.ResetInfo"], MessageType.Error);
|
||||
AddModuleMessage(Localizer["Message.Password.NoMatch"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Password.NoMatch"], MessageType.Warning);
|
||||
AddModuleMessage(Localizer["Message.Required.UserInfo"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Required.UserInfo"], MessageType.Warning);
|
||||
await logger.LogError(ex, "Error Resetting User Password {Username} {Error}", _username, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Password.Reset"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
await logger.LogError(ex, "Error Resetting User Password {Username} {Error}", _username, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.Password.Reset"], MessageType.Error);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,37 +6,32 @@
|
|||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="name" HelpText="Name Of The Role" ResourceKey="Name">Name:</Label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="name" HelpText="Name Of The Role" ResourceKey="Name">Name:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="name" class="form-control" @bind="@_name" maxlength="256" required />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="description" HelpText="A Short Description Of The Role Which Describes Its Purpose" ResourceKey="Description">Description:</Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="description" HelpText="A Short Description Of The Role Which Describes Its Purpose" ResourceKey="Description">Description:</Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="description" class="form-control" @bind="@_description" rows="5" maxlength="256" required></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<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-select" @bind="@_isautoassigned">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="isautoassigned" HelpText="Indicates Whether Or Not New Users Are Automatically Assigned To This Role" ResourceKey="AutoAssigned">Auto Assigned?</Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="isautoassigned" class="form-select" @bind="@_isautoassigned" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveRole">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
</div>
|
||||
</div>
|
||||
<br /><br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveRole">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@code {
|
||||
|
@ -77,7 +72,7 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.InfoRequired"], MessageType.Warning);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,39 +6,34 @@
|
|||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="name" HelpText="Name Of The Role" ResourceKey="Name">Name:</Label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="name" HelpText="Name Of The Role" ResourceKey="Name">Name:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="name" class="form-control" @bind="@_name" maxlength="256" required />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="description" HelpText="A Short Description Of The Role Which Describes Its Purpose" ResourceKey="Description">Description:</Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="description" HelpText="A Short Description Of The Role Which Describes Its Purpose" ResourceKey="Description">Description:</Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="description" class="form-control" @bind="@_description" rows="5" maxlength="256" required></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<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-select" @bind="@_isautoassigned">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="isautoassigned" HelpText="Indicates Whether Or Not New Users Are Automatically Assigned To This Role" ResourceKey="AutoAssigned">Auto Assigned?</Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="isautoassigned" class="form-select" @bind="@_isautoassigned" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveRole">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
<br /><br />
|
||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
|
||||
</div>
|
||||
</div>
|
||||
<br /><br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveRole">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
<br /><br />
|
||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@code {
|
||||
|
@ -106,7 +101,7 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.InfoRequired"], MessageType.Warning);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,71 +11,71 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="role" HelpText="The role you are assigning users to" ResourceKey="Role">Role: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="role" class="form-control" @bind="@name" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="user" HelpText="Select a user" ResourceKey="User">User: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="user" class="form-select" @bind="@userid">
|
||||
<option value="-1"><@Localizer["User.Select"]></option>
|
||||
@foreach (UserRole userrole in users)
|
||||
{
|
||||
<option value="@(userrole.UserId)">@userrole.User.DisplayName</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="effectiveDate" HelpText="The date that this role assignment is active" ResourceKey="EffectiveDate">Effective Date: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="date" id="effectiveDate" class="form-control" @bind="@effectivedate" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="expiryDate" HelpText="The date that this role assignment expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="date" id="expiryDate" class="form-control" @bind="@expirydate" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveUserRole">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
|
||||
<hr class="app-rule" />
|
||||
<p align="center">
|
||||
<Pager Items="@userroles">
|
||||
<Header>
|
||||
<th>@Localizer["Users"]</th>
|
||||
<th>@Localizer["Effective"]</th>
|
||||
<th>@Localizer["Expiry"]</th>
|
||||
<th> </th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td>@context.User.DisplayName</td>
|
||||
<td>@context.EffectiveDate</td>
|
||||
<td>@context.ExpiryDate</td>
|
||||
<td>
|
||||
<ActionDialog Header="Remove User" Message="@string.Format(Localizer["Confirm.User.DeleteRole"], context.User.DisplayName)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@(context.Role.IsAutoAssigned || PageState.User.Username == UserNames.Host)" ResourceKey="DeleteUserRole" />
|
||||
</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
</p>
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="role" HelpText="The role you are assigning users to" ResourceKey="Role">Role: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="role" class="form-control" @bind="@name" disabled />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="user" HelpText="Select a user" ResourceKey="User">User: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="user" class="form-select" @bind="@userid" required>
|
||||
<option value="-1"><@Localizer["User.Select"]></option>
|
||||
@foreach (UserRole userrole in users)
|
||||
{
|
||||
<option value="@(userrole.UserId)">@userrole.User.DisplayName</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="effectiveDate" HelpText="The date that this role assignment is active" ResourceKey="EffectiveDate">Effective Date: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input type="date" id="effectiveDate" class="form-control" @bind="@effectivedate" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="expiryDate" HelpText="The date that this role assignment expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input type="date" id="expiryDate" class="form-control" @bind="@expirydate" required />
|
||||
</div>
|
||||
</div>
|
||||
<br /><br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveUserRole">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
<hr class="app-rule" />
|
||||
<div class="row mb-1 align-items-center">
|
||||
<p align="center">
|
||||
<Pager Items="@userroles">
|
||||
<Header>
|
||||
<th>@Localizer["Users"]</th>
|
||||
<th>@Localizer["Effective"]</th>
|
||||
<th>@Localizer["Expiry"]</th>
|
||||
<th> </th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td>@context.User.DisplayName</td>
|
||||
<td>@context.EffectiveDate</td>
|
||||
<td>@context.ExpiryDate</td>
|
||||
<td>
|
||||
<ActionDialog Header="Remove User" Message="@string.Format(Localizer["Confirm.User.DeleteRole"], context.User.DisplayName)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteUserRole(context.UserRoleId))" Disabled="@(context.Role.IsAutoAssigned || PageState.User.Username == UserNames.Host)" ResourceKey="DeleteUserRole" />
|
||||
</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
|
||||
@code {
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
|
||||
private int roleid;
|
||||
private string name = string.Empty;
|
||||
private List<UserRole> users;
|
||||
|
@ -123,59 +123,78 @@ else
|
|||
|
||||
private async Task SaveUserRole()
|
||||
{
|
||||
try
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
if (userid != -1)
|
||||
try
|
||||
{
|
||||
var userrole = userroles.Where(item => item.UserId == userid && item.RoleId == roleid).FirstOrDefault();
|
||||
if (userrole != null)
|
||||
if (userid != -1)
|
||||
{
|
||||
userrole.EffectiveDate = effectivedate;
|
||||
userrole.ExpiryDate = expirydate;
|
||||
await UserRoleService.UpdateUserRoleAsync(userrole);
|
||||
var userrole = userroles.Where(item => item.UserId == userid && item.RoleId == roleid).FirstOrDefault();
|
||||
if (userrole != null)
|
||||
{
|
||||
userrole.EffectiveDate = effectivedate;
|
||||
userrole.ExpiryDate = expirydate;
|
||||
await UserRoleService.UpdateUserRoleAsync(userrole);
|
||||
}
|
||||
else
|
||||
{
|
||||
userrole = new UserRole();
|
||||
userrole.UserId = userid;
|
||||
userrole.RoleId = roleid;
|
||||
userrole.EffectiveDate = effectivedate;
|
||||
userrole.ExpiryDate = expirydate;
|
||||
|
||||
await UserRoleService.AddUserRoleAsync(userrole);
|
||||
}
|
||||
|
||||
await logger.LogInformation("User Assigned To Role {UserRole}", userrole);
|
||||
AddModuleMessage(Localizer["Success.User.AssignedRole"], MessageType.Success);
|
||||
await GetUserRoles();
|
||||
StateHasChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
userrole = new UserRole();
|
||||
userrole.UserId = userid;
|
||||
userrole.RoleId = roleid;
|
||||
userrole.EffectiveDate = effectivedate;
|
||||
userrole.ExpiryDate = expirydate;
|
||||
|
||||
await UserRoleService.AddUserRoleAsync(userrole);
|
||||
AddModuleMessage(Localizer["Message.Required.UserSelect"], MessageType.Warning);
|
||||
}
|
||||
|
||||
await logger.LogInformation("User Assigned To Role {UserRole}", userrole);
|
||||
AddModuleMessage(Localizer["Success.User.AssignedRole"], MessageType.Success);
|
||||
await GetUserRoles();
|
||||
StateHasChanged();
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Required.UserSelect"], MessageType.Warning);
|
||||
await logger.LogError(ex, "Error Saving User Roles {RoleId} {Error}", roleid, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.User.SaveRole"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
else
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving User Roles {RoleId} {Error}", roleid, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.User.SaveRole"], MessageType.Error);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteUserRole(int UserRoleId)
|
||||
{
|
||||
try
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
await UserRoleService.DeleteUserRoleAsync(UserRoleId);
|
||||
await logger.LogInformation("User Removed From Role {UserRoleId}", UserRoleId);
|
||||
AddModuleMessage(Localizer["Confirm.User.RoleRemoved"], MessageType.Success);
|
||||
await GetUserRoles();
|
||||
StateHasChanged();
|
||||
try
|
||||
{
|
||||
await UserRoleService.DeleteUserRoleAsync(UserRoleId);
|
||||
await logger.LogInformation("User Removed From Role {UserRoleId}", UserRoleId);
|
||||
AddModuleMessage(Localizer["Confirm.User.RoleRemoved"], MessageType.Success);
|
||||
await GetUserRoles();
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Removing User From Role {UserRoleId} {Error}", UserRoleId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.User.RemoveRole"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
await logger.LogError(ex, "Error Removing User From Role {UserRoleId} {Error}", UserRoleId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.User.RemoveRole"], MessageType.Error);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,251 +13,217 @@
|
|||
|
||||
@if (_initialized)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="name" HelpText="Enter the site name" ResourceKey="Name">Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="name" class="form-control" @bind="@_name" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<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>
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||
{
|
||||
<textarea id="alias" class="form-control" @bind="@_urls" rows="3"></textarea>
|
||||
}
|
||||
else
|
||||
{
|
||||
<textarea id="alias" class="form-control" @bind="@_urls" rows="3" readonly></textarea>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="name" HelpText="Enter the site name" ResourceKey="Name">Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="name" class="form-control" @bind="@_name" maxlength="200" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" 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>
|
||||
<div class="col-sm-9">
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||
{
|
||||
<textarea id="alias" class="form-control" @bind="@_urls" rows="3" required></textarea>
|
||||
}
|
||||
else
|
||||
{
|
||||
<textarea id="alias" class="form-control" @bind="@_urls" rows="3" readonly></textarea>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" 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>
|
||||
<div class="col-sm-9">
|
||||
<select id="allowRegister" class="form-select" @bind="@_allowregistration" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="isDeleted" HelpText="Is this site deleted?" ResourceKey="IsDeleted">Is Deleted? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="isDeleted" class="form-select" @bind="@_isdeleted" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Section Name="Appearance" Heading="Appearance" ResourceKey="Appearance">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="logo" HelpText="Specify a logo for the site" ResourceKey="Logo">Logo: </Label>
|
||||
<div class="col-sm-9">
|
||||
<FileManager FileId="@_logofileid" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="favicon" HelpText="Specify a Favicon" ResourceKey="FavoriteIcon">Favicon: </Label>
|
||||
<div class="col-sm-9">
|
||||
<FileManager FileId="@_faviconfileid" Filter="ico" @ref="_faviconfilemanager" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="defaultTheme" HelpText="Select the sites default theme" ResourceKey="DefaultTheme">Default Theme: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="defaultTheme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))" required>
|
||||
<option value="-"><@Localizer["Theme.Select"]></option>
|
||||
@foreach (var theme in _themes)
|
||||
{
|
||||
<option value="@theme.TypeName">@theme.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="defaultContainer" class="form-select" @bind="@_containertype" required>
|
||||
<option value="-"><@Localizer["Container.Select"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="defaultAdminContainer" HelpText="Select the default admin container for the site" ResourceKey="DefaultAdminContainer">Default Admin Container: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="defaultAdminContainer" class="form-select" @bind="@_admincontainertype" required>
|
||||
<option value="-"><@Localizer["Container.Select"]></option>
|
||||
<option value="@Constants.DefaultAdminContainer"><@Localizer["DefaultAdminContainer"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<tr>
|
||||
<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>
|
||||
</td>
|
||||
<td>
|
||||
<select id="allowRegister" class="form-select" @bind="@_allowregistration">
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="isDeleted" HelpText="Is this site deleted?" ResourceKey="IsDeleted">Is Deleted? </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="isDeleted" class="form-select" @bind="@_isdeleted">
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<Section Name="Appearance" Heading="Appearance" ResourceKey="Appearance">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="logo" HelpText="Specify a logo for the site" ResourceKey="Logo">Logo: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<FileManager FileId="@_logofileid" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="favicon" HelpText="Specify a Favicon" ResourceKey="FavoriteIcon">Favicon: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<FileManager FileId="@_faviconfileid" Filter="ico" @ref="_faviconfilemanager" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="defaultTheme" HelpText="Select the sites default theme" ResourceKey="DefaultTheme">Default Theme: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="defaultTheme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))">
|
||||
<option value="-"><@Localizer["Theme.Select"]></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-select" @bind="@_containertype">
|
||||
<option value="-"><@Localizer["Container.Select"]></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-select" @bind="@_admincontainertype">
|
||||
<option value="-"><@Localizer["Container.Select"]></option>
|
||||
<option value="@Constants.DefaultAdminContainer"><@Localizer["DefaultAdminContainer"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</Section>
|
||||
<Section Name="SMTP" Heading="SMTP Settings" ResourceKey="SMTPSettings">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%"> </td>
|
||||
<td>
|
||||
<strong>@Localizer["Smtp.Required.EnableNotificationJob"]</strong><br />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="host" HelpText="Enter the host name of the SMTP server" ResourceKey="Host">Host: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="host" class="form-control" @bind="@_smtphost" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="port" HelpText="Enter the port number for the SMTP server. Please note this field is required if you provide a host name." ResourceKey="Port">Port: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="port" class="form-control" @bind="@_smtpport" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="enabledSSl" HelpText="Specify if SSL is required for your SMTP server" ResourceKey="UseSsl">SSL Enabled: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="enabledSSl" class="form-select" @bind="@_smtpssl">
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="username" HelpText="Enter the username for your SMTP account" ResourceKey="SmptUsername">Username: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="username" class="form-control" @bind="@_smtpusername" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="password" HelpText="Enter the password for your SMTP account" ResourceKey="SmtpPassword">Password: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="password" type="password" class="form-control" @bind="@_smtppassword" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="sender" HelpText="Enter the email which emails will be sent from. Please note that this email address may need to be authorized with the SMTP server." ResourceKey="SmptSender">Email Sender: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="sender" class="form-control" @bind="@_smtpsender" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button type="button" class="btn btn-secondary" @onclick="SendEmail">@Localizer["Smtp.TestConfig"]</button>
|
||||
<br /><br />
|
||||
</Section>
|
||||
<Section Name="PWA" Heading="Progressive Web Application Settings" ResourceKey="PWASettings">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="isEnabled" HelpText="Select whether you would like this site to be available as a Progressive Web Application (PWA)" ResourceKey="EnablePWA">Is Enabled? </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="isEnabled" class="form-select" @bind="@_pwaisenabled">
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="appIcon" HelpText="Include an application icon for your PWA. It should be a PNG which is 192 X 192 pixels in dimension." ResourceKey="PwaApplicationIcon">App Icon: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<FileManager FileId="@_pwaappiconfileid" Filter="png" @ref="_pwaappiconfilemanager" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="splashIcon" HelpText="Include a splash icon for your PWA. It should be a PNG which is 512 X 512 pixels in dimension." ResourceKey="PwaSplashIcon">Splash Icon: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<FileManager FileId="@_pwasplashiconfileid" Filter="png" @ref="_pwasplashiconfilemanager" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</Section>
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||
{
|
||||
<Section Name="TenantInformation" Heading="Tenant Information" ResourceKey="TenantInformation">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<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>
|
||||
</div>
|
||||
</Section>
|
||||
}
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveSite">@SharedLocalizer["Save"]</button>
|
||||
<ActionDialog Header="Delete Site" Message="@Localizer["Confirm.DeleteSite"]" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteSite())" ResourceKey="DeleteSite" />
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
|
||||
<Section Name="SMTP" Heading="SMTP Settings" ResourceKey="SMTPSettings">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<div class="col-sm-3">
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<strong>@Localizer["Smtp.Required.EnableNotificationJob"]</strong><br />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="host" HelpText="Enter the host name of the SMTP server" ResourceKey="Host">Host: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="host" class="form-control" @bind="@_smtphost" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="port" HelpText="Enter the port number for the SMTP server. Please note this field is required if you provide a host name." ResourceKey="Port">Port: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="port" class="form-control" @bind="@_smtpport" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="enabledSSl" HelpText="Specify if SSL is required for your SMTP server" ResourceKey="UseSsl">SSL Enabled: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="enabledSSl" class="form-select" @bind="@_smtpssl" >
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="username" HelpText="Enter the username for your SMTP account" ResourceKey="SmptUsername">Username: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="username" class="form-control" @bind="@_smtpusername" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="password" HelpText="Enter the password for your SMTP account" ResourceKey="SmtpPassword">Password: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="password" type="password" class="form-control" @bind="@_smtppassword" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="sender" HelpText="Enter the email which emails will be sent from. Please note that this email address may need to be authorized with the SMTP server." ResourceKey="SmptSender">Email Sender: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="sender" class="form-control" @bind="@_smtpsender" />
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-secondary" @onclick="SendEmail">@Localizer["Smtp.TestConfig"]</button>
|
||||
<br /><br />
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</Section>
|
||||
<Section Name="PWA" Heading="Progressive Web Application Settings" ResourceKey="PWASettings">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="isEnabled" HelpText="Select whether you would like this site to be available as a Progressive Web Application (PWA)" ResourceKey="EnablePWA">Is Enabled? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="isEnabled" class="form-select" @bind="@_pwaisenabled" required>
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="appIcon" HelpText="Include an application icon for your PWA. It should be a PNG which is 192 X 192 pixels in dimension." ResourceKey="PwaApplicationIcon">App Icon: </Label>
|
||||
<div class="col-sm-9">
|
||||
<FileManager FileId="@_pwaappiconfileid" Filter="png" @ref="_pwaappiconfilemanager" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="splashIcon" HelpText="Include a splash icon for your PWA. It should be a PNG which is 512 X 512 pixels in dimension." ResourceKey="PwaSplashIcon">Splash Icon: </Label>
|
||||
<div class="col-sm-9">
|
||||
<FileManager FileId="@_pwasplashiconfileid" Filter="png" @ref="_pwasplashiconfilemanager" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||
{
|
||||
<Section Name="TenantInformation" Heading="Tenant Information" ResourceKey="TenantInformation">
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="tenant" HelpText="The tenant for the site" ResourceKey="Tenant">Tenant: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="tenant" class="form-control" @bind="@_tenant" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="database" HelpText="The database for the tenant" ResourceKey="Database">Database: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="database" class="form-control" @bind="@_database" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="connectionstring" HelpText="The connection information for the database" ResourceKey="ConnectionString">Connection: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="connectionstring" class="form-control" @bind="@_connectionstring" rows="2" readonly></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
}
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveSite">@SharedLocalizer["Save"]</button>
|
||||
<ActionDialog Header="Delete Site" Message="@Localizer["Confirm.DeleteSite"]" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteSite())" ResourceKey="DeleteSite" />
|
||||
<br />
|
||||
<br />
|
||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon" DeletedBy="@_deletedby" DeletedOn="@_deletedon"></AuditInfo>
|
||||
</form>
|
||||
}
|
||||
|
||||
@code {
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
private bool _initialized = false;
|
||||
private List<Theme> _themeList;
|
||||
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||
|
@ -422,121 +388,130 @@
|
|||
|
||||
private async Task SaveSite()
|
||||
{
|
||||
try
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
if (_name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-")
|
||||
try
|
||||
{
|
||||
var unique = true;
|
||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||
if (_name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-")
|
||||
{
|
||||
foreach (string name in _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
var unique = true;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unique)
|
||||
{
|
||||
var site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
|
||||
if (site != null)
|
||||
if (unique)
|
||||
{
|
||||
bool refresh = (site.DefaultThemeType != _themetype || site.DefaultContainerType != _containertype);
|
||||
|
||||
site.Name = _name;
|
||||
site.AllowRegistration = (_allowregistration == null ? true : Boolean.Parse(_allowregistration));
|
||||
site.IsDeleted = (_isdeleted == null ? true : Boolean.Parse(_isdeleted));
|
||||
|
||||
site.LogoFileId = null;
|
||||
var logofileid = _logofilemanager.GetFileId();
|
||||
if (logofileid != -1)
|
||||
var site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
|
||||
if (site != null)
|
||||
{
|
||||
site.LogoFileId = logofileid;
|
||||
}
|
||||
var faviconFieldId = _faviconfilemanager.GetFileId();
|
||||
if (faviconFieldId != -1)
|
||||
{
|
||||
site.FaviconFileId = faviconFieldId;
|
||||
}
|
||||
site.DefaultThemeType = _themetype;
|
||||
site.DefaultContainerType = _containertype;
|
||||
site.AdminContainerType = _admincontainertype;
|
||||
bool refresh = (site.DefaultThemeType != _themetype || site.DefaultContainerType != _containertype);
|
||||
|
||||
site.PwaIsEnabled = (_pwaisenabled == null ? true : Boolean.Parse(_pwaisenabled));
|
||||
var pwaappiconfileid = _pwaappiconfilemanager.GetFileId();
|
||||
if (pwaappiconfileid != -1)
|
||||
{
|
||||
site.PwaAppIconFileId = pwaappiconfileid;
|
||||
}
|
||||
var pwasplashiconfileid = _pwasplashiconfilemanager.GetFileId();
|
||||
if (pwasplashiconfileid != -1)
|
||||
{
|
||||
site.PwaSplashIconFileId = pwasplashiconfileid;
|
||||
}
|
||||
site.Name = _name;
|
||||
site.AllowRegistration = (_allowregistration == null ? true : Boolean.Parse(_allowregistration));
|
||||
site.IsDeleted = (_isdeleted == null ? true : Boolean.Parse(_isdeleted));
|
||||
|
||||
site = await SiteService.UpdateSiteAsync(site);
|
||||
|
||||
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
|
||||
SettingService.SetSetting(settings, "SMTPHost", _smtphost);
|
||||
SettingService.SetSetting(settings, "SMTPPort", _smtpport);
|
||||
SettingService.SetSetting(settings, "SMTPSSL", _smtpssl);
|
||||
SettingService.SetSetting(settings, "SMTPUsername", _smtpusername);
|
||||
SettingService.SetSetting(settings, "SMTPPassword", _smtppassword);
|
||||
SettingService.SetSetting(settings, "SMTPSender", _smtpsender);
|
||||
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())
|
||||
site.LogoFileId = null;
|
||||
var logofileid = _logofilemanager.GetFileId();
|
||||
if (logofileid != -1)
|
||||
{
|
||||
if (!names.Contains(alias.Name))
|
||||
site.LogoFileId = logofileid;
|
||||
}
|
||||
var faviconFieldId = _faviconfilemanager.GetFileId();
|
||||
if (faviconFieldId != -1)
|
||||
{
|
||||
site.FaviconFileId = faviconFieldId;
|
||||
}
|
||||
site.DefaultThemeType = _themetype;
|
||||
site.DefaultContainerType = _containertype;
|
||||
site.AdminContainerType = _admincontainertype;
|
||||
|
||||
site.PwaIsEnabled = (_pwaisenabled == null ? true : Boolean.Parse(_pwaisenabled));
|
||||
var pwaappiconfileid = _pwaappiconfilemanager.GetFileId();
|
||||
if (pwaappiconfileid != -1)
|
||||
{
|
||||
site.PwaAppIconFileId = pwaappiconfileid;
|
||||
}
|
||||
var pwasplashiconfileid = _pwasplashiconfilemanager.GetFileId();
|
||||
if (pwasplashiconfileid != -1)
|
||||
{
|
||||
site.PwaSplashIconFileId = pwasplashiconfileid;
|
||||
}
|
||||
|
||||
site = await SiteService.UpdateSiteAsync(site);
|
||||
|
||||
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
|
||||
SettingService.SetSetting(settings, "SMTPHost", _smtphost);
|
||||
SettingService.SetSetting(settings, "SMTPPort", _smtpport);
|
||||
SettingService.SetSetting(settings, "SMTPSSL", _smtpssl);
|
||||
SettingService.SetSetting(settings, "SMTPUsername", _smtpusername);
|
||||
SettingService.SetSetting(settings, "SMTPPassword", _smtppassword);
|
||||
SettingService.SetSetting(settings, "SMTPSender", _smtpsender);
|
||||
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())
|
||||
{
|
||||
await AliasService.DeleteAliasAsync(alias.AliasId);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string name in names)
|
||||
await logger.LogInformation("Site Settings Saved {Site}", site);
|
||||
|
||||
if (refresh)
|
||||
{
|
||||
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);
|
||||
}
|
||||
NavigationManager.NavigateTo(NavigateUrl()); // refresh to show new theme or container
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Success.Settings.SaveSite"], MessageType.Success);
|
||||
}
|
||||
}
|
||||
|
||||
await logger.LogInformation("Site Settings Saved {Site}", site);
|
||||
|
||||
if (refresh)
|
||||
{
|
||||
NavigationManager.NavigateTo(NavigateUrl()); // refresh to show new theme or container
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Success.Settings.SaveSite"], MessageType.Success);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Aliases.Taken"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Aliases.Taken"], MessageType.Warning);
|
||||
AddModuleMessage(Localizer["Message.Required.SiteName"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Required.SiteName"], MessageType.Warning);
|
||||
await logger.LogError(ex, "Error Saving Site {SiteId} {Error}", PageState.Site.SiteId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.SaveSite"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
await logger.LogError(ex, "Error Saving Site {SiteId} {Error}", PageState.Site.SiteId, ex.Message);
|
||||
AddModuleMessage(Localizer["Error.SaveSite"], MessageType.Error);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,158 +19,140 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<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 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>
|
||||
<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-select" @onchange="(e => ThemeChanged(e))">
|
||||
<option value="-"><@Localizer["Theme.Select"]></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-select" @bind="@_containertype">
|
||||
<option value="-"><@Localizer["Container.Select"]></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-select" @bind="@_admincontainertype">
|
||||
<option value="-"><@Localizer["Container.Select"]></option>
|
||||
<option value=""><@Localizer["DefaultContainer.Admin"]></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-select" @bind="@_sitetemplatetype">
|
||||
<option value="-"><@Localizer["SiteTemplate.Select"]></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-select" @onchange="(e => TenantChanged(e))">
|
||||
<option value="-"><@Localizer["Tenant.Select"]></option>
|
||||
<option value="+"><@Localizer["Tenant.Add"]></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="form-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))">
|
||||
@foreach (var database in _databases)
|
||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="name" HelpText="Enter the name of the site" ResourceKey="Name">Site Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="name" class="form-control" @bind="@_name" maxlength="200" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" 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>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="alias" class="form-control" @bind="@_urls" rows="3" required></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="defaultTheme" HelpText="Select the default theme for the website" ResourceKey="DefaultTheme">Default Theme: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="defaultTheme" class="form-select" @onchange="(e => ThemeChanged(e))" required>
|
||||
<option value="-"><@Localizer["Theme.Select"]></option>
|
||||
@foreach (var theme in _themes)
|
||||
{
|
||||
if (database.IsDefault)
|
||||
{
|
||||
<option value="@database.Name" selected>@Localizer[@database.Name]</option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="@database.Name">@Localizer[@database.Name]</option>
|
||||
}
|
||||
<option value="@theme.TypeName">@theme.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
if (_databaseConfigType != null)
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="defaultContainer" class="form-select" @bind="@_containertype" required>
|
||||
<option value="-"><@Localizer["Container.Select"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="adminContainer" HelpText="Select the admin container for the site" ResourceKey="AdminContainer">Admin Container: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="adminContainer" class="form-select" @bind="@_admincontainertype" required>
|
||||
<option value="-"><@Localizer["Container.Select"]></option>
|
||||
<option value=""><@Localizer["DefaultContainer.Admin"]></option>
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="siteTemplate" HelpText="Select the site template" ResourceKey="SiteTemplate">Site Template: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="siteTemplate" class="form-select" @bind="@_sitetemplatetype" required>
|
||||
<option value="-"><@Localizer["SiteTemplate.Select"]></option>
|
||||
@foreach (SiteTemplate siteTemplate in _siteTemplates)
|
||||
{
|
||||
<option value="@siteTemplate.TypeName">@siteTemplate.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="tenant" HelpText="Select the tenant for the site" ResourceKey="Tenant">Tenant: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="tenant" class="form-select" @onchange="(e => TenantChanged(e))" required>
|
||||
<option value="-"><@Localizer["Tenant.Select"]></option>
|
||||
<option value="+"><@Localizer["Tenant.Add"]></option>
|
||||
@foreach (Tenant tenant in _tenants)
|
||||
{
|
||||
<option value="@tenant.TenantId">@tenant.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@if (_tenantid == "+")
|
||||
{
|
||||
@DatabaseConfigComponent;
|
||||
<div class="row mb-1 align-items-center">
|
||||
<hr class="app-rule" />
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="name" HelpText="Enter the name for the tenant" ResourceKey="TenantName">Tenant Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="name" class="form-control" @bind="@_tenantName" maxlength="100" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="databaseType" HelpText="Select the database type for the tenant" ResourceKey="DatabaseType">Database Type: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="databaseType" class="form-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))" required>
|
||||
@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>
|
||||
</div>
|
||||
</div>
|
||||
if (_databaseConfigType != null)
|
||||
{
|
||||
@DatabaseConfigComponent;
|
||||
}
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="hostUsername" HelpText="Enter the username of the host for this site" ResourceKey="HostUsername">Host Username:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="hostUsername" class="form-control" @bind="@_hostUserName" readonly />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="hostPassword" HelpText="Enter the password for the host of this site" ResourceKey="HostPassword">Host Password:</Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="hostPassword" type="password" class="form-control" @bind="@_hostpassword" required />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<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>
|
||||
}
|
||||
</table>
|
||||
<button type="button" class="btn btn-success" @onclick="SaveSite">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveSite">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
</form>
|
||||
}
|
||||
|
||||
@code {
|
||||
private List<Database> _databases;
|
||||
private ElementReference form;
|
||||
private bool validated = false;
|
||||
private string _databaseName = "LocalDB";
|
||||
private Type _databaseConfigType;
|
||||
private object _databaseConfig;
|
||||
|
@ -274,111 +256,120 @@ else
|
|||
|
||||
private async Task SaveSite()
|
||||
{
|
||||
if (_tenantid != "-" && _name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-" && _sitetemplatetype != "-")
|
||||
validated = true;
|
||||
var interop = new Interop(JSRuntime);
|
||||
if (await interop.FormValid(form))
|
||||
{
|
||||
var duplicates = new List<string>();
|
||||
var aliases = await AliasService.GetAliasesAsync();
|
||||
foreach (string name in _urls.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
if (_tenantid != "-" && _name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-" && _sitetemplatetype != "-")
|
||||
{
|
||||
if (aliases.Exists(item => item.Name == name))
|
||||
var duplicates = new List<string>();
|
||||
var aliases = await AliasService.GetAliasesAsync();
|
||||
foreach (string name in _urls.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
duplicates.Add(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (duplicates.Count == 0)
|
||||
{
|
||||
InstallConfig config = new InstallConfig();
|
||||
|
||||
if (_tenantid == "+")
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_tenantName) && _tenants.FirstOrDefault(item => item.Name == _tenantName) == null)
|
||||
if (aliases.Exists(item => item.Name == name))
|
||||
{
|
||||
// validate host credentials
|
||||
var user = new User();
|
||||
user.SiteId = PageState.Site.SiteId;
|
||||
user.Username = UserNames.Host;
|
||||
user.Password = _hostpassword;
|
||||
user = await UserService.LoginUserAsync(user, false, false);
|
||||
if (user.IsAuthenticated)
|
||||
{
|
||||
var connectionString = String.Empty;
|
||||
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
||||
{
|
||||
connectionString = databaseConfigControl.GetConnectionString();
|
||||
}
|
||||
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
||||
duplicates.Add(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (connectionString != "")
|
||||
if (duplicates.Count == 0)
|
||||
{
|
||||
InstallConfig config = new InstallConfig();
|
||||
|
||||
if (_tenantid == "+")
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_tenantName) && _tenants.FirstOrDefault(item => item.Name == _tenantName) == null)
|
||||
{
|
||||
// validate host credentials
|
||||
var user = new User();
|
||||
user.SiteId = PageState.Site.SiteId;
|
||||
user.Username = UserNames.Host;
|
||||
user.Password = _hostpassword;
|
||||
user = await UserService.LoginUserAsync(user, false, false);
|
||||
if (user.IsAuthenticated)
|
||||
{
|
||||
config.TenantName = _tenantName;
|
||||
config.DatabaseType = database.DBType;
|
||||
config.ConnectionString = connectionString;
|
||||
config.HostEmail = user.Email;
|
||||
config.HostPassword = _hostpassword;
|
||||
config.HostName = user.DisplayName;
|
||||
config.IsNewTenant = true;
|
||||
var connectionString = String.Empty;
|
||||
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
||||
{
|
||||
connectionString = databaseConfigControl.GetConnectionString();
|
||||
}
|
||||
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
||||
|
||||
if (connectionString != "")
|
||||
{
|
||||
config.TenantName = _tenantName;
|
||||
config.DatabaseType = database.DBType;
|
||||
config.ConnectionString = connectionString;
|
||||
config.HostEmail = user.Email;
|
||||
config.HostPassword = _hostpassword;
|
||||
config.HostName = user.DisplayName;
|
||||
config.IsNewTenant = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Error.Required.ServerDatabase"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Error.Required.ServerDatabase"], MessageType.Error);
|
||||
AddModuleMessage(Localizer["Error.InvalidPassword"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Error.InvalidPassword"], MessageType.Error);
|
||||
AddModuleMessage(Localizer["Error.TenantName.Exists"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Error.TenantName.Exists"], MessageType.Error);
|
||||
var tenant = _tenants.FirstOrDefault(item => item.TenantId == int.Parse(_tenantid));
|
||||
if (tenant != null)
|
||||
{
|
||||
config.TenantName = tenant.Name;
|
||||
config.DatabaseType = tenant.DBType;
|
||||
config.ConnectionString = tenant.DBConnectionString;
|
||||
config.IsNewTenant = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(config.TenantName))
|
||||
{
|
||||
config.SiteName = _name;
|
||||
config.Aliases = _urls;
|
||||
config.DefaultTheme = _themetype;
|
||||
config.DefaultContainer = _containertype;
|
||||
config.DefaultAdminContainer = _admincontainertype;
|
||||
config.SiteTemplate = _sitetemplatetype;
|
||||
|
||||
ShowProgressIndicator();
|
||||
|
||||
var installation = await InstallationService.Install(config);
|
||||
if (installation.Success)
|
||||
{
|
||||
var aliasname = config.Aliases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[0];
|
||||
var uri = new Uri(NavigationManager.Uri);
|
||||
NavigationManager.NavigateTo(uri.Scheme + "://" + aliasname, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogError("Error Creating Site {Error}", installation.Message);
|
||||
AddModuleMessage(installation.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var tenant = _tenants.FirstOrDefault(item => item.TenantId == int.Parse(_tenantid));
|
||||
if (tenant != null)
|
||||
{
|
||||
config.TenantName = tenant.Name;
|
||||
config.DatabaseType = tenant.DBType;
|
||||
config.ConnectionString = tenant.DBConnectionString;
|
||||
config.IsNewTenant = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(config.TenantName))
|
||||
{
|
||||
config.SiteName = _name;
|
||||
config.Aliases = _urls;
|
||||
config.DefaultTheme = _themetype;
|
||||
config.DefaultContainer = _containertype;
|
||||
config.DefaultAdminContainer = _admincontainertype;
|
||||
config.SiteTemplate = _sitetemplatetype;
|
||||
|
||||
ShowProgressIndicator();
|
||||
|
||||
var installation = await InstallationService.Install(config);
|
||||
if (installation.Success)
|
||||
{
|
||||
var aliasname = config.Aliases.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[0];
|
||||
var uri = new Uri(NavigationManager.Uri);
|
||||
NavigationManager.NavigateTo(uri.Scheme + "://" + aliasname, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
await logger.LogError("Error Creating Site {Error}", installation.Message);
|
||||
AddModuleMessage(installation.Message, MessageType.Error);
|
||||
}
|
||||
AddModuleMessage(string.Format(Localizer["Message.SiteName.InUse"], string.Join(", ", duplicates.ToArray())), MessageType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(string.Format(Localizer["Message.SiteName.InUse"], string.Join(", ", duplicates.ToArray())), MessageType.Warning);
|
||||
AddModuleMessage(Localizer["Message.Required.Tenant"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AddModuleMessage(Localizer["Message.Required.Tenant"], MessageType.Warning);
|
||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,12 +13,11 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="tenant" HelpText="Select the tenant for the SQL server" ResourceKey="Tenant">Tenant: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="container">
|
||||
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="tenant" HelpText="Select the tenant for the SQL server" ResourceKey="Tenant">Tenant: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="tenant" class="form-select" value="@_tenantid" @onchange="(e => TenantChanged(e))">
|
||||
<option value="-1"><@Localizer["Tenant.Select"]></option>
|
||||
@foreach (Tenant tenant in _tenants)
|
||||
|
@ -26,42 +25,61 @@ else
|
|||
<option value="@tenant.TenantId">@tenant.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</div>
|
||||
</div>
|
||||
@if (_tenantid != "-1")
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="database" HelpText="The database for the tenant" ResourceKey="Database">Database: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="database" HelpText="The database for the tenant" ResourceKey="Database">Database: </Label>
|
||||
<div class="col-sm-9">
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="connectionstring" HelpText="The connection information for the database" ResourceKey="ConnectionString">Connection: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="connectionstring" class="form-control" @bind="@_connectionstring" rows="2" readonly></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="sqlQeury" HelpText="Enter the query for the SQL server" ResourceKey="SqlQuery">SQL Query: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea id="sqlQeury" class="form-control" @bind="@_sql" rows="5"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="sqlQeury" HelpText="Enter the query for the SQL server" ResourceKey="SqlQuery">SQL Query: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="sqlQeury" class="form-control" @bind="@_sql" rows="3"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</table>
|
||||
</div>
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="Execute">@Localizer["Execute"]</button>
|
||||
<br />
|
||||
<br />
|
||||
@if (!string.IsNullOrEmpty(_results))
|
||||
@if (_results != null)
|
||||
{
|
||||
@((MarkupString)_results)
|
||||
@if (_results.Count > 0)
|
||||
{
|
||||
<div class="table-responsive">
|
||||
<Pager Class="table table-bordered" Items="@_results">
|
||||
<Header>
|
||||
@foreach (KeyValuePair<string, string> kvp in _results.First())
|
||||
{
|
||||
<th>@kvp.Key</th>
|
||||
}
|
||||
</Header>
|
||||
<Row>
|
||||
@foreach (KeyValuePair<string, string> kvp in context)
|
||||
{
|
||||
<td>@kvp.Value</td>
|
||||
}
|
||||
</Row>
|
||||
</Pager>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@Localizer["Return.NoResult"]
|
||||
}
|
||||
<br />
|
||||
<br />
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,7 +89,7 @@ else
|
|||
private string _database = string.Empty;
|
||||
private string _connectionstring = string.Empty;
|
||||
private string _sql = string.Empty;
|
||||
private string _results = string.Empty;
|
||||
private List<Dictionary<string, string>> _results;
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||
|
||||
|
@ -118,7 +136,7 @@ else
|
|||
{
|
||||
var sqlquery = new SqlQuery { TenantId = int.Parse(_tenantid), Query = _sql };
|
||||
sqlquery = await SqlService.ExecuteQueryAsync(sqlquery);
|
||||
_results = DisplayResults(sqlquery.Results);
|
||||
_results = sqlquery.Results;
|
||||
AddModuleMessage(Localizer["Success.QueryExecuted"], MessageType.Success);
|
||||
}
|
||||
else
|
||||
|
@ -132,44 +150,4 @@ else
|
|||
AddModuleMessage(ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private string DisplayResults(List<Dictionary<string, string>> results)
|
||||
{
|
||||
var table = string.Empty;
|
||||
foreach (Dictionary<string, string> item in results)
|
||||
{
|
||||
if (table == string.Empty)
|
||||
{
|
||||
table = "<div class=\"table-responsive\">";
|
||||
table += "<table class=\"table table-bordered\"><thead><tr>";
|
||||
|
||||
foreach (KeyValuePair<string, string> kvp in item)
|
||||
{
|
||||
table += "<th scope=\"col\">" + kvp.Key + "</th>";
|
||||
}
|
||||
|
||||
table += "</tr></thead><tbody>";
|
||||
}
|
||||
|
||||
table += "<tr>";
|
||||
|
||||
foreach (KeyValuePair<string, string> kvp in item)
|
||||
{
|
||||
table += "<td>" + kvp.Value + "</td>";
|
||||
}
|
||||
|
||||
table += "</tr>";
|
||||
}
|
||||
|
||||
if (table != string.Empty)
|
||||
{
|
||||
table += "</tbody></table></div>";
|
||||
}
|
||||
else
|
||||
{
|
||||
table = Localizer["Return.NoResult"];
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,105 +7,79 @@
|
|||
|
||||
<TabStrip>
|
||||
<TabPanel Name="Info" Heading="Info" ResourceKey="Info">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="version" HelpText="Framework Version" ResourceKey="FrameworkVersion">Framework Version: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="version" HelpText="Framework Version" ResourceKey="FrameworkVersion">Framework Version: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="version" class="form-control" @bind="@_version" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="clrversion" HelpText="Common Language Runtime Version" ResourceKey="CLRVersion">CLR Version: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="clrversion" HelpText="Common Language Runtime Version" ResourceKey="CLRVersion">CLR Version: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="clrversion" class="form-control" @bind="@_clrversion" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="osversion" HelpText="Operating System Version" ResourceKey="OSVersion">OS Version: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="osversion" HelpText="Operating System Version" ResourceKey="OSVersion">OS Version: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="osversion" class="form-control" @bind="@_osversion" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="serverpath" HelpText="Server Path" ResourceKey="ServerPath">Server Path: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="serverpath" HelpText="Server Path" ResourceKey="ServerPath">Server Path: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="serverpath" class="form-control" @bind="@_serverpath" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="servertime" HelpText="Server Time" ResourceKey="ServerTime">Server Time: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="servertime" HelpText="Server Time" ResourceKey="ServerTime">Server Time: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="servertime" class="form-control" @bind="@_servertime" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="installationid" HelpText="The Unique Identifier For Your Installation" ResourceKey="InstallationId">Installation ID: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="installationid" HelpText="The Unique Identifier For Your Installation" ResourceKey="InstallationId">Installation ID: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="installationid" class="form-control" @bind="@_installationid" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>
|
||||
<br /><input type="checkbox" @onchange="(e => RegisterChecked(e))" /> @Localizer["Register"]
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br /><br />
|
||||
<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" />
|
||||
</TabPanel>
|
||||
<TabPanel Name="Options" Heading="Options" ResourceKey="Options">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="runtime" HelpText="Blazor Runtime (Server or WebAssembly)" ResourceKey="BlazorRuntime">Blazor Runtime: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="runtime" HelpText="Blazor Runtime (Server or WebAssembly)" ResourceKey="BlazorRuntime">Blazor Runtime: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="runtime" class="form-select" @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>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="rendermode" HelpText="Blazor Server Render Mode" ResourceKey="RenderMode">Render Mode: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="rendermode" class="form-select" @bind="@_rendermode">
|
||||
<option value="Server">@Localizer["Server"]</option>
|
||||
<option value="ServerPrerendered">@Localizer["ServerPrerendered"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="detailederrors" HelpText="Specify If Detailed Errors Are Enabled For Blazor. This Option Should Not Not Be Enabled In Production." ResourceKey="DetailedErrors">Detailed Errors? </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="detailederrors" HelpText="Specify If Detailed Errors Are Enabled For Blazor. This Option Should Not Not Be Enabled In Production." ResourceKey="DetailedErrors">Detailed Errors? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="detailederrors" class="form-select" @bind="@_detailederrors">
|
||||
<option value="true">@SharedLocalizer["True"]</option>
|
||||
<option value="false">@SharedLocalizer["False"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="logginglevel" HelpText="The Minimum Logging Level For The Event Log. This Option Can Be Used To Control The Volume Of Items Stored In Your Event Log." ResourceKey="LoggingLevel">Logging Level: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="logginglevel" HelpText="The Minimum Logging Level For The Event Log. This Option Can Be Used To Control The Volume Of Items Stored In Your Event Log." ResourceKey="LoggingLevel">Logging Level: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="logginglevel" class="form-select" @bind="@_logginglevel">
|
||||
<option value="Trace">@Localizer["Trace"]</option>
|
||||
<option value="Debug">@Localizer["Debug"]</option>
|
||||
|
@ -114,31 +88,27 @@
|
|||
<option value="Error">@Localizer["Error"]</option>
|
||||
<option value="Critical">@Localizer["Critical"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="swagger" HelpText="Specify If Swagger Is Enabled For Your Server API" ResourceKey="Swagger">Swagger Enabled? </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="swagger" HelpText="Specify If Swagger Is Enabled For Your Server API" ResourceKey="Swagger">Swagger Enabled? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="swagger" class="form-select" @bind="@_swagger">
|
||||
<option value="true">@SharedLocalizer["True"]</option>
|
||||
<option value="false">@SharedLocalizer["False"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="packageservice" HelpText="Specify If The Package Service Is Enabled For Installing Modules, Themes, And Translations" ResourceKey="PackageService">Enable Package Service? </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="packageservice" HelpText="Specify If The Package Service Is Enabled For Installing Modules, Themes, And Translations" ResourceKey="PackageService">Enable Package Service? </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="packageservice" class="form-select" @bind="@_packageservice">
|
||||
<option value="true">@SharedLocalizer["True"]</option>
|
||||
<option value="false">@SharedLocalizer["False"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br /><br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveConfig">@SharedLocalizer["Save"]</button>
|
||||
<a class="btn btn-primary" href="swagger/index.html" target="_new">@Localizer["Access.ApiFramework"]</a>
|
||||
|
@ -220,20 +190,4 @@
|
|||
await logger.LogError(ex, "Error Restarting Application");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RegisterChecked(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if ((bool)e.Value)
|
||||
{
|
||||
await InstallationService.RegisterAsync(PageState.User.Email);
|
||||
AddModuleMessage(Localizer["Success.Register"], MessageType.Success);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error On Register");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,19 +9,19 @@
|
|||
|
||||
<TabStrip>
|
||||
<TabPanel Name="Download" ResourceKey="Download">
|
||||
<ModuleMessage Type="MessageType.Info" Message="Download one or more themes from the list below. Once you are ready click Install to complete the installation."></ModuleMessage>
|
||||
|
||||
<table class="table table-borderless" style=" margin: auto; width: 50% !important;">
|
||||
<tr>
|
||||
<td>
|
||||
<div class="row justify-content-center mb-3">
|
||||
<div class="col-sm-6">
|
||||
<div class="input-group">
|
||||
<select id="price" class="form-select custom-select" @onchange="(e => PriceChanged(e))">
|
||||
<option value="free">@SharedLocalizer["Free"]</option>
|
||||
<option value="paid">@SharedLocalizer["Paid"]</option>
|
||||
</select>
|
||||
<input id="search" class="form-control" placeholder="@SharedLocalizer["Search.Hint"]" @bind="@_search" />
|
||||
</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-primary" @onclick="Search">@SharedLocalizer["Search"]</button>
|
||||
<button type="button" class="btn btn-primary" @onclick="Search">@SharedLocalizer["Search"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Reset">@SharedLocalizer["Reset"]</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (_packages != null)
|
||||
{
|
||||
|
@ -32,10 +32,26 @@
|
|||
<td>
|
||||
<h3 style="display: inline;"><a href="@context.ProductUrl" target="_new">@context.Name</a></h3> @SharedLocalizer["Search.By"]: <strong><a href="@context.OwnerUrl" target="new">@context.Owner</a></strong><br />
|
||||
@(context.Description.Length > 400 ? (context.Description.Substring(0, 400) + "...") : context.Description)<br />
|
||||
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] | @SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> | @SharedLocalizer["Search.Version"]: <strong>@context.Version</strong> | @SharedLocalizer["Search.Source"]: <strong>@context.PackageUrl</strong>
|
||||
<strong>@(String.Format("{0:n0}", context.Downloads))</strong> @SharedLocalizer["Search.Downloads"] |
|
||||
@SharedLocalizer["Search.Released"]: <strong>@context.ReleaseDate.ToString("MMM dd, yyyy")</strong> |
|
||||
@SharedLocalizer["Search.Version"]: <strong>@context.Version</strong>
|
||||
@((MarkupString)(context.TrialPeriod > 0 ? " | <strong>" + context.TrialPeriod + " " + @SharedLocalizer["Trial"] + "</strong>" : ""))
|
||||
</td>
|
||||
<td style="vertical-align: middle;">
|
||||
<button type="button" class="btn btn-primary" @onclick=@(async () => await DownloadTheme(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
||||
<td style="width: 1px; vertical-align: middle;">
|
||||
@if (context.Price != null && !string.IsNullOrEmpty(context.PackageUrl))
|
||||
{
|
||||
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
||||
}
|
||||
</td>
|
||||
<td style="width: 1px; vertical-align: middle;">
|
||||
@if (context.Price != null && !string.IsNullOrEmpty(context.PaymentUrl))
|
||||
{
|
||||
<a class="btn btn-primary" style="text-decoration: none !important" href="@context.PaymentUrl" target="_new">@context.Price.Value.ToString("$#,##0.00")</a>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(context.PackageId, context.Version))>@SharedLocalizer["Download"]</button>
|
||||
}
|
||||
</td>
|
||||
</Row>
|
||||
</Pager>
|
||||
|
@ -50,25 +66,62 @@
|
|||
}
|
||||
</TabPanel>
|
||||
<TabPanel Name="Upload" ResourceKey="Upload">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<Label HelpText="Upload one or more theme packages. Once they are uploaded click Install to complete the installation." ResourceKey="Theme">Theme: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" HelpText="Upload one or more theme packages. Once they are uploaded click Install to complete the installation." ResourceKey="Theme">Theme: </Label>
|
||||
<div class="col-sm-9">
|
||||
<FileManager Filter="nupkg" ShowFiles="false" Folder="Packages" UploadMultiple="@true" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</TabPanel>
|
||||
</TabStrip>
|
||||
|
||||
@if (_productname != "")
|
||||
{
|
||||
<div class="app-actiondialog">
|
||||
<div class="modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@SharedLocalizer["Review License Terms"]</h5>
|
||||
<button type="button" class="btn-close" aria-label="Close" @onclick="HideModal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p style="height: 200px; overflow-y: scroll;">
|
||||
<h3>@_productname</h3>
|
||||
@if (!string.IsNullOrEmpty(_license))
|
||||
{
|
||||
@((MarkupString)_license)
|
||||
}
|
||||
else
|
||||
{
|
||||
@SharedLocalizer["License Not Specified"]
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-success" @onclick="DownloadPackage">@SharedLocalizer["Accept"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="HideModal">@SharedLocalizer["Cancel"]</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<button type="button" class="btn btn-success" @onclick="InstallThemes">@SharedLocalizer["Install"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
|
||||
@code {
|
||||
private List<Package> _packages;
|
||||
private string _price = "free";
|
||||
private string _search = "";
|
||||
private string _productname = "";
|
||||
private string _license = "";
|
||||
private string _packageid = "";
|
||||
private string _version = "";
|
||||
|
||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||
|
||||
|
@ -88,7 +141,7 @@
|
|||
private async Task LoadThemes()
|
||||
{
|
||||
var themes = await ThemeService.GetThemesAsync();
|
||||
_packages = await PackageService.GetPackagesAsync("theme", _search);
|
||||
_packages = await PackageService.GetPackagesAsync("theme", _search, _price, "");
|
||||
|
||||
if (_packages != null)
|
||||
{
|
||||
|
@ -102,6 +155,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
private async void PriceChanged(ChangeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
_price = (string)e.Value;
|
||||
_search = "";
|
||||
await LoadThemes();
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error On PriceChanged");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Search()
|
||||
{
|
||||
try
|
||||
|
@ -127,6 +195,55 @@
|
|||
}
|
||||
}
|
||||
|
||||
private void HideModal()
|
||||
{
|
||||
_productname = "";
|
||||
_license = "";
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task GetPackage(string packageid, string version)
|
||||
{
|
||||
try
|
||||
{
|
||||
var package = await PackageService.GetPackageAsync(packageid, version);
|
||||
if (package != null)
|
||||
{
|
||||
_productname = package.Name;
|
||||
if (!string.IsNullOrEmpty(package.License))
|
||||
{
|
||||
_license = package.License.Replace("\n", "<br />");
|
||||
}
|
||||
_packageid = package.PackageId;
|
||||
_version = package.Version;
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Getting Package {PackageId} {Version}", packageid, version);
|
||||
AddModuleMessage(Localizer["Error.Theme.Download"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DownloadPackage()
|
||||
{
|
||||
try
|
||||
{
|
||||
await PackageService.DownloadPackageAsync(_packageid, _version, "Packages");
|
||||
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _packageid, _version);
|
||||
AddModuleMessage(Localizer["Success.Theme.Download"], MessageType.Success);
|
||||
_productname = "";
|
||||
_license = "";
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Downloading Package {PackageId} {Version}", _packageid, _version);
|
||||
AddModuleMessage(Localizer["Error.Theme.Download"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task InstallThemes()
|
||||
{
|
||||
try
|
||||
|
@ -139,20 +256,4 @@
|
|||
await logger.LogError(ex, "Error Installing Theme");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DownloadTheme(string packageid, string version)
|
||||
{
|
||||
try
|
||||
{
|
||||
await PackageService.DownloadPackageAsync(packageid, version, "Packages");
|
||||
await logger.LogInformation("Theme {ThemeName} {Version} Downloaded Successfully", packageid, version);
|
||||
AddModuleMessage(Localizer["Success.Theme.Download"], MessageType.Success);
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await logger.LogError(ex, "Error Downloading Module {ThemeName} {Version}", packageid, version);
|
||||
AddModuleMessage(Localizer["Error.Theme.Download"], MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,66 +11,56 @@
|
|||
|
||||
@if (_templates != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="owner" HelpText="Enter the name of the organization who is developing this theme. It should not contain spaces or punctuation." ResourceKey="OwnerName">Owner Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="owner" class="form-control" @bind="@_owner" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="module" HelpText="Enter a name for this theme. It should not contain spaces or punctuation." ResourceKey="ThemeName">Theme Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="module" class="form-control" @bind="@_theme" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="template" HelpText="Select a theme template. Templates are located in the wwwroot/Themes/Templates folder on the server." ResourceKey="Template">Template: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="template" class="form-select" @onchange="(e => TemplateChanged(e))">
|
||||
<option value="-"><@Localizer["Template.Select"]></option>
|
||||
@foreach (Template template in _templates)
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="owner" HelpText="Enter the name of the organization who is developing this theme. It should not contain spaces or punctuation." ResourceKey="OwnerName">Owner Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="owner" class="form-control" @bind="@_owner" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="module" HelpText="Enter a name for this theme. It should not contain spaces or punctuation." ResourceKey="ThemeName">Theme Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="module" class="form-control" @bind="@_theme" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="template" HelpText="Select a theme template. Templates are located in the wwwroot/Themes/Templates folder on the server." ResourceKey="Template">Template: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="template" class="form-select" @onchange="(e => TemplateChanged(e))">
|
||||
<option value="-"><@Localizer["Template.Select"]></option>
|
||||
@foreach (Template template in _templates)
|
||||
{
|
||||
<option value="@template.Name">@template.Title</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="reference" HelpText="Select a framework reference version" ResourceKey="FrameworkReference">Framework Reference: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="reference" class="form-select" @bind="@_reference">
|
||||
@foreach (string version in _versions)
|
||||
{
|
||||
if (Version.Parse(version).CompareTo(Version.Parse(_minversion)) >= 0)
|
||||
{
|
||||
<option value="@template.Name">@template.Title</option>
|
||||
<option value="@(version)">@(version)</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="reference" HelpText="Select a framework reference version" ResourceKey="FrameworkReference">Framework Reference: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="reference" class="form-select" @bind="@_reference">
|
||||
@foreach (string version in _versions)
|
||||
{
|
||||
if (Version.Parse(version).CompareTo(Version.Parse(_minversion)) >= 0)
|
||||
{
|
||||
<option value="@(version)">@(version)</option>
|
||||
}
|
||||
}
|
||||
<option value="local">@SharedLocalizer["LocalVersion"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
@if (!string.IsNullOrEmpty(_location))
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="location" HelpText="Location where the theme will be created" ResourceKey="Location">Location: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="module" class="form-control" @bind="@_location" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
}
|
||||
<option value="local">@SharedLocalizer["LocalVersion"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@if (!string.IsNullOrEmpty(_location)) {
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="location" HelpText="Location where the theme will be created" ResourceKey="Location">Location: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="module" class="form-control" @bind="@_location" readonly />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="CreateTheme">@Localizer["Theme.Create"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
}
|
||||
|
|
|
@ -21,8 +21,9 @@ else
|
|||
<Header>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th scope="col">@SharedLocalizer["Name"]</th>
|
||||
<th scope="col">@SharedLocalizer["Version"]</th>
|
||||
<th>@SharedLocalizer["Name"]</th>
|
||||
<th>@SharedLocalizer["Version"]</th>
|
||||
<th>@SharedLocalizer["Expires"]</th>
|
||||
<th> </th>
|
||||
</Header>
|
||||
<Row>
|
||||
|
@ -35,11 +36,14 @@ else
|
|||
</td>
|
||||
<td>@context.Name</td>
|
||||
<td>@context.Version</td>
|
||||
<td>
|
||||
@((MarkupString)PurchaseLink(context.PackageName))
|
||||
</td>
|
||||
<td>
|
||||
@if (UpgradeAvailable(context.PackageName, context.Version))
|
||||
{
|
||||
{
|
||||
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadTheme(context.PackageName, context.Version))>@SharedLocalizer["Upgrade"]</button>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
<td></td>
|
||||
</Row>
|
||||
|
@ -69,10 +73,31 @@ else
|
|||
}
|
||||
}
|
||||
|
||||
private string PurchaseLink(string packagename)
|
||||
{
|
||||
string link = "";
|
||||
if (!string.IsNullOrEmpty(packagename) && _packages != null)
|
||||
{
|
||||
var package = _packages.Where(item => item.PackageId == packagename).FirstOrDefault();
|
||||
if (package != null)
|
||||
{
|
||||
if (package.ExpiryDate != null && package.ExpiryDate.Value.Date != DateTime.MaxValue.Date)
|
||||
{
|
||||
link += "<span>" + package.ExpiryDate.Value.Date.ToString("MMM dd, yyyy") + "</span>";
|
||||
if (!string.IsNullOrEmpty(package.PaymentUrl))
|
||||
{
|
||||
link += " <a class=\"btn btn-primary\" style=\"text-decoration: none !important\" href=\"" + package.PaymentUrl + "\" target=\"_new\">" + SharedLocalizer["Extend"] + "</a>";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return link;
|
||||
}
|
||||
|
||||
private bool UpgradeAvailable(string packagename, string version)
|
||||
{
|
||||
var upgradeavailable = false;
|
||||
if (_packages != null)
|
||||
if (!string.IsNullOrEmpty(packagename) && _packages != null)
|
||||
{
|
||||
var package = _packages.Where(item => item.PackageId == packagename).FirstOrDefault();
|
||||
if (package != null)
|
||||
|
|
|
@ -6,64 +6,50 @@
|
|||
@inject IStringLocalizer<View> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="name" HelpText="The name of the theme" ResourceKey="Name">Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="name" HelpText="The name of the theme" ResourceKey="Name">Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="name" class="form-control" @bind="@_name" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="themename" HelpText="The internal name of the module" ResourceKey="InternalName">Internal Name: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="themename" HelpText="The internal name of the module" ResourceKey="InternalName">Internal Name: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="themename" class="form-control" @bind="@_themeName" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="version" HelpText="The version of the theme" ResourceKey="Version">Version: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="version" HelpText="The version of the theme" ResourceKey="Version">Version: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="version" class="form-control" @bind="@_version" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="owner" HelpText="The owner or creator of the theme" ResourceKey="Owner">Owner: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="owner" HelpText="The owner or creator of the theme" ResourceKey="Owner">Owner: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="owner" class="form-control" @bind="@_owner" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="url" HelpText="The reference url of the theme" ResourceKey="ReferenceUrl">Reference Url: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="url" HelpText="The reference url of the theme" ResourceKey="ReferenceUrl">Reference Url: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="url" class="form-control" @bind="@_url" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="contact" HelpText="The contact for the theme" ResourceKey="Contact">Contact: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="contact" HelpText="The contact for the theme" ResourceKey="Contact">Contact: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="contact" class="form-control" @bind="@_contact" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="license" HelpText="The license of the theme" ResourceKey="License">License: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="license" HelpText="The license of the theme" ResourceKey="License">License: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="license" class="form-control" @bind="@_license" rows="5" disabled></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
|
||||
@code {
|
||||
|
|
|
@ -22,16 +22,14 @@
|
|||
</TabPanel>
|
||||
<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">
|
||||
<tr>
|
||||
<td>
|
||||
<Label HelpText="Upload A Framework Package And Then Select Upgrade" ResourceKey="Framework">Framework: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" HelpText="Upload A Framework Package And Then Select Upgrade" ResourceKey="Framework">Framework: </Label>
|
||||
<div class="col-sm-9">
|
||||
<FileManager Filter="nupkg" ShowFiles="false" Folder="Packages" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-success" @onclick="Upgrade">@SharedLocalizer["Upgrade"]</button>
|
||||
</TabPanel>
|
||||
</TabStrip>
|
||||
|
@ -46,7 +44,7 @@
|
|||
{
|
||||
try
|
||||
{
|
||||
List<Package> packages = await PackageService.GetPackagesAsync("framework");
|
||||
List<Package> packages = await PackageService.GetPackagesAsync("framework", "", "", "");
|
||||
if (packages != null)
|
||||
{
|
||||
_package = packages.Where(item => item.PackageId.StartsWith(Constants.PackageId)).FirstOrDefault();
|
||||
|
@ -73,7 +71,7 @@
|
|||
AddModuleMessage(Localizer["Info.Upgrade.Wait"], MessageType.Info);
|
||||
ShowProgressIndicator();
|
||||
var interop = new Interop(JSRuntime);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 20);
|
||||
await interop.RedirectBrowser(NavigateUrl(), 10);
|
||||
await InstallationService.Upgrade();
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
@ -8,32 +8,27 @@
|
|||
|
||||
@if (PageState.User != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="to" HelpText="Enter the username you wish to send a message to" ResourceKey="To">To: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="to" class="form-control" @bind="@username" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="subject" HelpText="Enter the subject of the message" ResourceKey="Subject">Subject: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id="subject" class="form-control" @bind="@subject" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="message" HelpText="Enter the message" ResourceKey="Message">Message: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea id="message" class="form-control" @bind="@body" rows="5" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="to" HelpText="Enter the username you wish to send a message to" ResourceKey="To">To: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="to" class="form-control" @bind="@username" />
|
||||
</div> >
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="subject" HelpText="Enter the subject of the message" ResourceKey="Subject">Subject: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="subject" class="form-control" @bind="@subject" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="message" HelpText="Enter the message" ResourceKey="Message">Message: </Label>
|
||||
<div class="col-sm-9">
|
||||
<textarea id="message" class="form-control" @bind="@body" rows="5" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<button type="button" class="btn btn-primary" @onclick="Send">@SharedLocalizer["Send"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
}
|
||||
|
|
|
@ -6,12 +6,13 @@
|
|||
@inject ISettingService SettingService
|
||||
@inject INotificationService NotificationService
|
||||
@inject IFileService FileService
|
||||
@inject IFolderService FolderService
|
||||
@inject IStringLocalizer<Index> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
@if (PageState.User != null && photo != null)
|
||||
{
|
||||
<img src="@photo.Url" alt="@displayname" style="max-width: 400px" class="rounded-circle mx-auto d-block">
|
||||
<img src="@ImageUrl(photofileid, 400, 400, "crop")" alt="@displayname" style="max-width: 400px" class="rounded-circle mx-auto d-block">
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -19,58 +20,47 @@ else
|
|||
}
|
||||
<TabStrip>
|
||||
<TabPanel Name="Identity" ResourceKey="Identity">
|
||||
@if (PageState.User != null)
|
||||
@if (profiles != null && settings != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="username" HelpText="Your username. Note that this field can not be modified." ResourceKey="Username"></Label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="username" HelpText="Your username. Note that this field can not be modified." ResourceKey="Username"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="username" class="form-control" @bind="@username" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="password" HelpText="If you wish to change your password you can enter it here. Please choose a sufficiently secure password." ResourceKey="Password"></Label>
|
||||
</td>
|
||||
<td>
|
||||
<input id ="password" type="password" class="form-control" @bind="@password" autocomplete="new-password" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="confirm" HelpText="If you are changing your password you must enter it again to confirm it matches" ResourceKey="Confirm"></Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="password" HelpText="If you wish to change your password you can enter it here. Please choose a sufficiently secure password." ResourceKey="Password"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="password" type="password" class="form-control" @bind="@password" autocomplete="new-password" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="confirm" HelpText="If you are changing your password you must enter it again to confirm it matches" ResourceKey="Confirm"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="confirm" type="password" class="form-control" @bind="@confirm" autocomplete="new-password" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="email" HelpText="Your email address where you wish to receive notifications" ResourceKey="Email"></Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="email" HelpText="Your email address where you wish to receive notifications" ResourceKey="Email"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="email" class="form-control" @bind="@email" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="displayname" HelpText="Your full name" ResourceKey="DisplayName"></Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="displayname" HelpText="Your full name" ResourceKey="DisplayName"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="displayname" class="form-control" @bind="@displayname" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="@photofileid.ToString()" HelpText="A photo of yourself" ResourceKey="Photo"></Label>
|
||||
</td>
|
||||
<td>
|
||||
<FileManager FileId="@photofileid" @ref="filemanager" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="@photofileid.ToString()" HelpText="A photo of yourself" ResourceKey="Photo"></Label>
|
||||
<div class="col-sm-9">
|
||||
<FileManager FileId="@photofileid" Filter="@Constants.ImageFiles" ShowFolders="false" ShowFiles="true" UploadMultiple="false" FolderId="@folderid" @ref="filemanager" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="Save">@SharedLocalizer["Save"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||
}
|
||||
|
@ -78,58 +68,56 @@ else
|
|||
<TabPanel Name="Profile" ResourceKey="Profile">
|
||||
@if (profiles != null && settings != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
@foreach (Profile profile in profiles)
|
||||
{
|
||||
var p = profile;
|
||||
if (!p.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
@foreach (Profile profile in profiles)
|
||||
{
|
||||
if (p.Category != category)
|
||||
var p = profile;
|
||||
if (!p.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||
{
|
||||
<tr>
|
||||
<th colspan="2" style="text-align: center;">
|
||||
if (p.Category != category)
|
||||
{
|
||||
<div class="col text-center pb-2">
|
||||
@p.Category
|
||||
</th>
|
||||
</tr>
|
||||
category = p.Category;
|
||||
}
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="@p.Name" HelpText="@p.Description">@p.Title</Label>
|
||||
</td>
|
||||
<td>
|
||||
@if (!string.IsNullOrEmpty(p.Options))
|
||||
{
|
||||
<select id="@p.Name" class="form-select" @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)
|
||||
</div>
|
||||
category = p.Category;
|
||||
}
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="@p.Name" HelpText="@p.Description">@p.Title</Label>
|
||||
<div class="col-sm-9">
|
||||
@if (!string.IsNullOrEmpty(p.Options))
|
||||
{
|
||||
<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-select" @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
|
||||
{
|
||||
<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>
|
||||
</tr>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-success" @onclick="Save">@SharedLocalizer["Save"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||
}
|
||||
|
@ -221,6 +209,7 @@ else
|
|||
private string email = string.Empty;
|
||||
private string displayname = string.Empty;
|
||||
private FileManager filemanager;
|
||||
private int folderid = -1;
|
||||
private int photofileid = -1;
|
||||
private File photo = null;
|
||||
private List<Profile> profiles;
|
||||
|
@ -241,6 +230,13 @@ else
|
|||
email = PageState.User.Email;
|
||||
displayname = PageState.User.DisplayName;
|
||||
|
||||
// get user folder
|
||||
var folder = await FolderService.GetFolderAsync(ModuleState.SiteId, PageState.User.FolderPath);
|
||||
if (folder != null)
|
||||
{
|
||||
folderid = folder.FolderId;
|
||||
}
|
||||
|
||||
if (PageState.User.PhotoFileId != null)
|
||||
{
|
||||
photofileid = PageState.User.PhotoFileId.Value;
|
||||
|
|
|
@ -8,75 +8,71 @@
|
|||
|
||||
@if (PageState.User != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<label class="control-label">@Localizer["Title"] </label>
|
||||
</td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<label Class="col-sm-3">@Localizer["Title"] </label>
|
||||
@if (title == "From")
|
||||
{
|
||||
<td>
|
||||
<div class="col-sm-3">
|
||||
<input class="form-control" @bind="@username" readonly />
|
||||
</td>
|
||||
</div>
|
||||
}
|
||||
@if (title == "To")
|
||||
{
|
||||
<td>
|
||||
<div class="col-sm-3">
|
||||
<input class="form-control" @bind="@username" />
|
||||
</td>
|
||||
</div>
|
||||
}
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">@Localizer["Subject"] </label>
|
||||
</td>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<label Class="col-sm-3">@Localizer["Subject"] </label>
|
||||
@if (title == "From")
|
||||
{
|
||||
<td>
|
||||
<div class="col-sm-3">
|
||||
<input class="form-control" @bind="@subject" readonly />
|
||||
</td>
|
||||
</div>
|
||||
}
|
||||
@if (title == "To")
|
||||
{
|
||||
<td>
|
||||
<div class="col-sm-3">
|
||||
<input class="form-control" @bind="@subject" />
|
||||
</td>
|
||||
</div>
|
||||
}
|
||||
</tr>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
@if (title == "From")
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">@Localizer["Date"] </label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<label class="col-sm-3">@Localizer["Date"] </label>
|
||||
<div class="col-sm-9">
|
||||
<input class="form-control" @bind="@createdon" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (title == "From")
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">@Localizer["Message"] </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@body" rows="5" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<label class="col-sm-3">@Localizer["Message"] </label>
|
||||
<div class="col-sm-9">
|
||||
<textarea class="form-control" @bind="@body" rows="5" readonly />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
@if (title == "To")
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<label class="control-label">@Localizer["Message"] </label>
|
||||
</td>
|
||||
<td>
|
||||
<textarea class="form-control" @bind="@body" rows="5" />
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<div class="row mb-1 align-items-center">
|
||||
<label class="col-sm-3">@Localizer["Message"] </label>
|
||||
<div class="col-sm-9">
|
||||
<textarea class="form-control" @bind="@body" rows="5" readonly />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@if (reply != string.Empty)
|
||||
|
|
|
@ -11,87 +11,78 @@
|
|||
<TabPanel Name="Identity" ResourceKey="Identity">
|
||||
@if (profiles != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="username" HelpText="A unique username for a user. Note that this field can not be modified once it is saved." ResourceKey="Username"></Label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="username" HelpText="A unique username for a user. Note that this field can not be modified once it is saved." ResourceKey="Username"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="username" class="form-control" @bind="@username" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="password" HelpText="The user's password. Please choose a password which is sufficiently secure." ResourceKey="Password"></Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="password" HelpText="The user's password. Please choose a password which is sufficiently secure." ResourceKey="Password"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="password" type="password" class="form-control" @bind="@password" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="confirm" HelpText="Please enter the password again to confirm it matches with the value above" ResourceKey="Confirm"></Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="confirm" HelpText="Please enter the password again to confirm it matches with the value above" ResourceKey="Confirm"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="confirm" type="password" class="form-control" @bind="@confirm" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="email" HelpText="The email address where the user will receive notifications" ResourceKey="Email"></Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="email" HelpText="The email address where the user will receive notifications" ResourceKey="Email"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="email" class="form-control" @bind="@email" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="displayname" HelpText="The full name of the user" ResourceKey="DisplayName"></Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="displayname" HelpText="The full name of the user" ResourceKey="DisplayName"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="displayname" class="form-control" @bind="@displayname" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
</TabPanel>
|
||||
<TabPanel Name="Profile" ResourceKey="Profile">
|
||||
@if (profiles != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
@foreach (Profile profile in profiles)
|
||||
{
|
||||
var p = profile;
|
||||
if (p.Category != category)
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
@foreach (Profile profile in profiles)
|
||||
{
|
||||
<tr>
|
||||
<th colspan="2" style="text-align: center;">
|
||||
@p.Category
|
||||
</th>
|
||||
</tr>
|
||||
category = p.Category;
|
||||
var p = profile;
|
||||
if (p.Category != category)
|
||||
{
|
||||
<div class="col text-center pb-2">
|
||||
<strong>@p.Category</strong>
|
||||
</div>
|
||||
category = p.Category;
|
||||
}
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="@p.Name" HelpText="@p.Description">@p.Title</Label>
|
||||
<div class="col-sm-9">
|
||||
@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))" />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="@p.Name" HelpText="@p.Description">@p.Title</Label>
|
||||
</td>
|
||||
<td>
|
||||
@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>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</TabPanel>
|
||||
</TabStrip>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveUser">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
|
||||
|
|
|
@ -20,102 +20,106 @@ else
|
|||
<TabPanel Name="Identity" ResourceKey="Identity">
|
||||
@if (profiles != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="username" HelpText="The unique username for a user. Note that this field can not be modified." ResourceKey="Username"></Label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="username" HelpText="The unique username for a user. Note that this field can not be modified." ResourceKey="Username"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="username" class="form-control" @bind="@username" readonly />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="password" HelpText="The user's password. Please choose a password which is sufficiently secure." ResourceKey="Password"></Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="password" HelpText="The user's password. Please choose a password which is sufficiently secure." ResourceKey="Password"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="password" type="password" class="form-control" @bind="@password" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="confirm" HelpText="Please enter the password again to confirm it matches with the value above" ResourceKey="Confirm"></Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="confirm" HelpText="Please enter the password again to confirm it matches with the value above" ResourceKey="Confirm"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="confirm" type="password" class="form-control" @bind="@confirm" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="email" HelpText="The email address where the user will receive notifications" ResourceKey="Email"></Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="email" HelpText="The email address where the user will receive notifications" ResourceKey="Email"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="email" class="form-control" @bind="@email" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="displayname" HelpText="The full name of the user" ResourceKey="DisplayName"></Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="displayname" HelpText="The full name of the user" ResourceKey="DisplayName"></Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="displayname" class="form-control" @bind="@displayname" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="@photofileid.ToString()" HelpText="A photo of the user" ResourceKey="Photo"></Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="@photofileid.ToString()" HelpText="A photo of the user" ResourceKey="Photo"></Label>
|
||||
<div class="col-sm-9">
|
||||
<FileManager FileId="@photofileid" @ref="filemanager" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="isdeleted" HelpText="Indicate if the user is active" ResourceKey="IsDeleted"></Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="isdeleted" HelpText="Indicate if the user is active" ResourceKey="IsDeleted"></Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="isdeleted" class="form-select" @bind="@isdeleted">
|
||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||
<option value="False">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
</TabPanel>
|
||||
<TabPanel Name="Profile" ResourceKey="Profile">
|
||||
@if (profiles != null)
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
@foreach (Profile profile in profiles)
|
||||
{
|
||||
var p = profile;
|
||||
if (p.Category != category)
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
@foreach (Profile profile in profiles)
|
||||
{
|
||||
<tr>
|
||||
<th colspan="2" style="text-align: center;">
|
||||
@p.Category
|
||||
</th>
|
||||
</tr>
|
||||
category = p.Category;
|
||||
var p = profile;
|
||||
if (p.Category != category)
|
||||
{
|
||||
<div class="col text-center pb-2">
|
||||
<strong>@p.Category</strong>
|
||||
</div>
|
||||
category = p.Category;
|
||||
}
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="@p.Name" HelpText="@p.Description">@p.Title</Label>
|
||||
<div class="col-sm-9">
|
||||
@if (!string.IsNullOrEmpty(p.Options))
|
||||
{
|
||||
<select id="@p.Name" class="form-select" @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))" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<input id="@p.Name" class="form-control" maxlength="@p.MaxLength" value="@GetProfileValue(p.Name, p.DefaultValue)" @onchange="@(e => ProfileChanged(e, p.Name))" />
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="@p.Name" HelpText="@p.Description">@p.Title</Label>
|
||||
</td>
|
||||
<td>
|
||||
@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>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</TabPanel>
|
||||
</TabStrip>
|
||||
|
|
|
@ -14,33 +14,32 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td>
|
||||
<div><ActionLink Action="Add" Text="Add User" ResourceKey="AddUser" /></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<div class="col-sm-4">
|
||||
<ActionLink Action="Add" Text="Add User" ResourceKey="AddUser" />
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<input class="form-control" @bind="@_search" />
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<button class="btn btn-secondary" @onclick="OnSearch">@SharedLocalizer["Search"]</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Pager Items="@userroles">
|
||||
<Header>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th>@SharedLocalizer["Name"]</th>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th style="width: 1px;"> </th>
|
||||
<th>@SharedLocalizer["Name"]</th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td>
|
||||
<ActionLink Action="Edit" Parameters="@($"id=" + context.UserId.ToString())" ResourceKey="EditUser" />
|
||||
</td>
|
||||
<td>
|
||||
<ActionDialog Header="Delete User" Message="@string.Format(Localizer["Confirm.User.Delete"], 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" />
|
||||
<ActionDialog Header="Delete User" Message="@string.Format(Localizer["Confirm.User.Delete"], context.User.DisplayName)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteUser(context))" Disabled="@(context.UserId == PageState.User.UserId)" ResourceKey="DeleteUser" />
|
||||
</td>
|
||||
<td>
|
||||
<ActionLink Action="Roles" Parameters="@($"id=" + context.UserId.ToString())" ResourceKey="Roles" />
|
||||
|
@ -96,6 +95,8 @@ else
|
|||
{
|
||||
await UserService.DeleteUserAsync(user.UserId, PageState.Site.SiteId);
|
||||
await logger.LogInformation("User Deleted {User}", UserRole.User);
|
||||
allroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId);
|
||||
userroles = Search(_search);
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,20 +12,16 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="user" HelpText="The user you are assigning roles to" ResourceKey="User">User: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="user" HelpText="The user you are assigning roles to" ResourceKey="User">User: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="user" class="form-control" @bind="@name" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="role" HelpText="Select a role" ResourceKey="Role">Role: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="role" HelpText="Select a role" ResourceKey="Role">Role: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="role" class="form-select" @bind="@roleid">
|
||||
<option value="-1"><@Localizer["Role.Select"]></option>
|
||||
@foreach (Role role in roles)
|
||||
|
@ -33,36 +29,34 @@ else
|
|||
<option value="@(role.RoleId)">@role.Name</option>
|
||||
}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="effectiveDate" HelpText="The date that this role assignment is active" ResourceKey="EffectiveDate">Effective Date: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="effectiveDate" HelpText="The date that this role assignment is active" ResourceKey="EffectiveDate">Effective Date: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="effectiveDate" class="form-control" @bind="@effectivedate" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Label For="expiryDate" HelpText="The date that this role assignment expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="expiryDate" HelpText="The date that this role assignment expires" ResourceKey="ExpiryDate">Expiry Date: </Label>
|
||||
<div class="col-sm-9">
|
||||
<input id="expiryDate" class="form-control" @bind="@expirydate" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<button type="button" class="btn btn-success" @onclick="SaveUserRole">@SharedLocalizer["Save"]</button>
|
||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||
|
||||
<hr class="app-rule" />
|
||||
<p align="center">
|
||||
<Pager Items="@userroles">
|
||||
<Header>
|
||||
<th>@Localizer["Roles"]</th>
|
||||
<th>@Localizer["Effective"]</th>
|
||||
<th>@Localizer["Expiry"]</th>
|
||||
<th> </th>
|
||||
<th>@Localizer["Roles"]</th>
|
||||
<th>@Localizer["Effective"]</th>
|
||||
<th>@Localizer["Expiry"]</th>
|
||||
<th> </th>
|
||||
</Header>
|
||||
<Row>
|
||||
<td>@context.Role.Name</td>
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
</span>
|
||||
</div>
|
||||
}
|
||||
<ModuleMessage Message="@_message" Type="@_messagetype"></ModuleMessage>
|
||||
</div>
|
||||
@if (_image != string.Empty)
|
||||
{
|
||||
|
@ -67,6 +66,14 @@
|
|||
</div>
|
||||
}
|
||||
</div>
|
||||
@if (!string.IsNullOrEmpty(_message))
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col mt-2">
|
||||
<ModuleMessage Message="@_message" Type="@_messagetype" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
@ -89,7 +96,7 @@
|
|||
public string Id { get; set; } // optional - for setting the id of the FileManager component for accessibility
|
||||
|
||||
[Parameter]
|
||||
public string Folder { get; set; } // optional - for setting a specific folder by default
|
||||
public string Folder { get; set; } // optional - for setting a specific folder by default ( only relevant for host functions )
|
||||
|
||||
[Parameter]
|
||||
public int FolderId { get; set; } = -1; // optional - for setting a specific folderid by default
|
||||
|
@ -104,7 +111,10 @@
|
|||
public bool ShowFolders { get; set; } = true; // optional - for indicating whether a list of folders should be displayed - default is true
|
||||
|
||||
[Parameter]
|
||||
public int FileId { get; set; } = -1; // optional - for setting a specific file by default
|
||||
public bool ShowImage { get; set; } = true; // optional - for indicating whether an image thumbnail should be displayed - default is true
|
||||
|
||||
[Parameter]
|
||||
public int FileId { get; set; } = -1; // optional - for selecting a specific file by default
|
||||
|
||||
[Parameter]
|
||||
public string Filter { get; set; } // optional - comma delimited list of file types that can be selected or uploaded ie. "jpg,gif"
|
||||
|
@ -112,6 +122,15 @@
|
|||
[Parameter]
|
||||
public bool UploadMultiple { get; set; } = false; // optional - enable multiple file uploads - default false
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<int> OnUpload { get; set; } // optional - executes a method in the calling component when a file is uploaded
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<int> OnSelect { get; set; } // optional - executes a method in the calling component when a file is selected
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<int> OnDelete { get; set; } // optional - executes a method in the calling component when a file is deleted
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Id))
|
||||
|
@ -119,6 +138,11 @@
|
|||
_id = Id;
|
||||
}
|
||||
|
||||
if (!ShowFiles)
|
||||
{
|
||||
ShowImage = false;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(Folder))
|
||||
{
|
||||
_folders = new List<Folder> { new Folder { FolderId = -1, Name = Folder } };
|
||||
|
@ -135,12 +159,14 @@
|
|||
if (file != null)
|
||||
{
|
||||
FolderId = file.FolderId;
|
||||
await OnSelect.InvokeAsync(FileId);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileId = -1; // file does not exist
|
||||
}
|
||||
}
|
||||
|
||||
await SetImage();
|
||||
|
||||
if (!string.IsNullOrEmpty(Filter))
|
||||
|
@ -218,6 +244,10 @@
|
|||
{
|
||||
_message = string.Empty;
|
||||
FileId = int.Parse((string)e.Value);
|
||||
if (FileId != -1)
|
||||
{
|
||||
await OnSelect.InvokeAsync(FileId);
|
||||
}
|
||||
|
||||
await SetImage();
|
||||
StateHasChanged();
|
||||
|
@ -230,7 +260,7 @@
|
|||
if (FileId != -1)
|
||||
{
|
||||
_file = await FileService.GetFileAsync(FileId);
|
||||
if (_file != null && _file.ImageHeight != 0 && _file.ImageWidth != 0)
|
||||
if (_file != null && ShowImage && _file.ImageHeight != 0 && _file.ImageWidth != 0)
|
||||
{
|
||||
var maxwidth = 200;
|
||||
var maxheight = 200;
|
||||
|
@ -272,16 +302,14 @@
|
|||
_message = Localizer["Success.File.Upload"];
|
||||
_messagetype = MessageType.Success;
|
||||
|
||||
// set FileId to first file in upload collection
|
||||
await GetFiles();
|
||||
|
||||
if (upload.Length == 1)
|
||||
var file = _files.Where(item => item.Name == upload[0]).FirstOrDefault();
|
||||
if (file != null)
|
||||
{
|
||||
var file = _files.Where(item => item.Name == upload[0]).FirstOrDefault();
|
||||
if (file != null)
|
||||
{
|
||||
FileId = file.FileId;
|
||||
await SetImage();
|
||||
}
|
||||
FileId = file.FileId;
|
||||
await SetImage();
|
||||
await OnUpload.InvokeAsync(FileId);
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
|
@ -315,6 +343,7 @@
|
|||
{
|
||||
await FileService.DeleteFileAsync(FileId);
|
||||
await logger.LogInformation("File Deleted {File}", FileId);
|
||||
await OnDelete.InvokeAsync(FileId);
|
||||
|
||||
_message = Localizer["Success.File.Delete"];
|
||||
_messagetype = MessageType.Success;
|
||||
|
|
|
@ -3,17 +3,16 @@
|
|||
|
||||
@if (!string.IsNullOrEmpty(HelpText))
|
||||
{
|
||||
<span class="app-tooltip" data-tip="@((MarkupString)HelpText)">@((MarkupString)_openLabel)@ChildContent@((MarkupString)_closeLabel) <img src="images/help.png" /></span>
|
||||
<span class="@_spanclass" data-tip="@((MarkupString)@_helptext)">
|
||||
<label for="@For" class="@_labelclass">@ChildContent</label> <img src="images/help.png" />
|
||||
</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
@((MarkupString)_openLabel)@ChildContent@((MarkupString)_closeLabel)
|
||||
<label for="@For" class="@_labelclass">@ChildContent</label>
|
||||
}
|
||||
|
||||
@code {
|
||||
private string _openLabel = string.Empty;
|
||||
private string _closeLabel = "</label>";
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
|
||||
|
@ -21,39 +20,33 @@ else
|
|||
public string For { get; set; } // optional - the id of the associated input control for accessibility
|
||||
|
||||
[Parameter]
|
||||
public string Class { get; set; } // optional - the class for the label ( ie. control-label )
|
||||
public string Class { get; set; } // optional - CSS classes
|
||||
|
||||
[Parameter]
|
||||
public string HelpText { get; set; } // optional - tooltip for this label
|
||||
|
||||
private string _spanclass = "app-tooltip";
|
||||
private string _labelclass = "form-label";
|
||||
private string _helptext = string.Empty;
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
base.OnParametersSet();
|
||||
|
||||
if (string.IsNullOrEmpty(Class))
|
||||
if (!string.IsNullOrEmpty(HelpText))
|
||||
{
|
||||
Class = "form-label";
|
||||
_helptext = Localize(nameof(HelpText), HelpText);
|
||||
_spanclass += (!string.IsNullOrEmpty(Class)) ? " " + Class : "";
|
||||
}
|
||||
|
||||
_openLabel = "<label";
|
||||
if (!string.IsNullOrEmpty(For))
|
||||
else
|
||||
{
|
||||
_openLabel += " for=\"" + For + "\"";
|
||||
_labelclass += (!string.IsNullOrEmpty(Class)) ? " " + Class : "";
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(Class))
|
||||
{
|
||||
_openLabel += " class=\"" + Class + "\"";
|
||||
}
|
||||
|
||||
_openLabel += ">";
|
||||
|
||||
var text = Localize("Text", String.Empty);
|
||||
if (text != String.Empty)
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
ChildContent =@<text>@text</text>;
|
||||
}
|
||||
|
||||
HelpText = Localize(nameof(HelpText), HelpText);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
@if (!string.IsNullOrEmpty(_message))
|
||||
{
|
||||
<div class="@_classname alert-dismissible fade show" role="alert">
|
||||
<div class="@_classname alert-dismissible fade show mb-3" role="alert">
|
||||
@((MarkupString)_message)
|
||||
@if (Type == MessageType.Error && PageState != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||
{
|
||||
|
@ -12,7 +12,6 @@
|
|||
}
|
||||
<button type="button" class="btn-close" aria-label="Close" @onclick="DismissModal"></button>
|
||||
</div>
|
||||
<br />
|
||||
}
|
||||
|
||||
@code {
|
||||
|
|
|
@ -2,45 +2,57 @@
|
|||
@inherits ModuleControlBase
|
||||
@typeparam TableItem
|
||||
|
||||
<p>
|
||||
@if (Toolbar == "Top")
|
||||
@if (ItemList != null)
|
||||
{
|
||||
@if (Toolbar == "Top" && _pages > 0 && Items.Count() > _maxItems)
|
||||
{
|
||||
<div class="mx-auto text-center">
|
||||
@if (_endPage > 1)
|
||||
<ul class="pagination justify-content-center my-2">
|
||||
<li class="page-item@((_page > 1) ? "" : " disabled")">
|
||||
<a class="page-link" @onclick=@(async () => UpdateList(1))><span class="oi oi-media-step-backward" title="start" aria-hidden="true"></span></a>
|
||||
</li>
|
||||
@if (_pages > _displayPages)
|
||||
{
|
||||
<button class="btn btn-secondary m-1" @onclick=@(async () => UpdateList(1))><span class="oi oi-media-step-backward" title="first" aria-hidden="true"></span></button>
|
||||
<li class="page-item@((_page > _displayPages) ? "" : " disabled")">
|
||||
<a class="page-link" @onclick=@(async () => SkipPages("back"))><span class="oi oi-media-skip-backward" title="skip back" aria-hidden="true"></span></a>
|
||||
</li>
|
||||
}
|
||||
@if (_page > _maxPages)
|
||||
<li class="page-item@((_page > 1) ? "" : " disabled")">
|
||||
<a class="page-link" @onclick=@(async () => NavigateToPage("previous"))><span class="oi oi-chevron-left" title="previous" aria-hidden="true"></span></a>
|
||||
</li>
|
||||
@for (int i = _startPage; i <= _endPage; i++)
|
||||
{
|
||||
<button class="btn btn-secondary m-1" @onclick=@(async () => SetPagerSize("back"))><span class="oi oi-media-skip-backward" title="back" aria-hidden="true"></span></button>
|
||||
}
|
||||
@if (_endPage > 1)
|
||||
{
|
||||
<button class="btn btn-secondary m-1" @onclick=@(async () => NavigateToPage("previous"))><span class="oi oi-chevron-left" title="previous" aria-hidden="true"></span></button>
|
||||
@for (int i = _startPage; i <= _endPage; i++)
|
||||
var pager = i;
|
||||
if (pager == _page)
|
||||
{
|
||||
var pager = i;
|
||||
<button class="btn @((pager == _page) ? "btn-primary" : "btn-link")" @onclick=@(async () => UpdateList(pager))>
|
||||
@pager
|
||||
</button>
|
||||
<li class="page-item active">
|
||||
<a class="page-link" @onclick=@(async () => UpdateList(pager))>@pager</a>
|
||||
</li>
|
||||
}
|
||||
else
|
||||
{
|
||||
<li class="page-item">
|
||||
<a class="page-link" @onclick=@(async () => UpdateList(pager))>@pager</a>
|
||||
</li>
|
||||
}
|
||||
<button class="btn btn-secondary m-1" @onclick=@(async () => NavigateToPage("next"))><span class="oi oi-chevron-right" title="next" aria-hidden="true"></span></button>
|
||||
}
|
||||
@if (_endPage < _pages)
|
||||
<li class="page-item@((_page < _pages) ? "" : " disabled")">
|
||||
<a class="page-link" @onclick=@(async () => NavigateToPage("next"))><span class="oi oi-chevron-right" title="next" aria-hidden="true"></span></a>
|
||||
</li>
|
||||
@if (_pages > _displayPages)
|
||||
{
|
||||
<button class="btn btn-secondary m-1" @onclick=@(async () => SetPagerSize("forward"))><span class="oi oi-media-skip-forward" title="forward" aria-hidden="true"></span></button>
|
||||
<li class="page-item@((_endPage < _pages) ? "" : " disabled")">
|
||||
<a class="page-link" @onclick=@(async () => SkipPages("forward"))><span class="oi oi-media-skip-forward" title="skip forward" aria-hidden="true"></span></a>
|
||||
</li>
|
||||
}
|
||||
@if (_endPage > 1)
|
||||
{
|
||||
<button class="btn btn-secondary m-1" @onclick=@(async () => UpdateList(_pages))><span class="oi oi-media-step-forward" title="last" aria-hidden="true"></span></button>
|
||||
}
|
||||
@if (_endPage > 1)
|
||||
{
|
||||
<span class="btn btn-link disabled">Page @_page of @_pages</span>
|
||||
}
|
||||
</div>
|
||||
<li class="page-item@((_page < _pages) ? "" : " disabled")">
|
||||
<a class="page-link" @onclick=@(async () => UpdateList(_pages))><span class="oi oi-media-step-forward" title="end" aria-hidden="true"></span></a>
|
||||
</li>
|
||||
<li class="page-item disabled">
|
||||
<a class="page-link">Page @_page of @_pages</a>
|
||||
</li>
|
||||
</ul>
|
||||
}
|
||||
@if (Format == "Table")
|
||||
@if (Format == "Table" && Row != null)
|
||||
{
|
||||
<table class="@Class">
|
||||
<thead>
|
||||
|
@ -58,90 +70,125 @@
|
|||
</tbody>
|
||||
</table>
|
||||
}
|
||||
@if (Format == "Grid")
|
||||
@if (Format == "Grid" && Row != null)
|
||||
{
|
||||
int count = 0;
|
||||
if (ItemList != null)
|
||||
{
|
||||
count = (int)Math.Ceiling(ItemList.Count() / (decimal)_columns) * _columns;
|
||||
}
|
||||
<div class="@Class">
|
||||
<div class="row">@Header</div>
|
||||
@foreach (var item in ItemList)
|
||||
@if (Header != null)
|
||||
{
|
||||
<div class="row">@Row(item)</div>
|
||||
@if (Detail != null)
|
||||
{
|
||||
<div class="row">@Detail(item)</div>
|
||||
}
|
||||
<div class="row"><div class="col">@Header</div></div>
|
||||
}
|
||||
@for (int row = 0; row < (count / _columns); row++)
|
||||
{
|
||||
<div class="row">
|
||||
@for (int col = 0; col < _columns; col++)
|
||||
{
|
||||
int index = (row * _columns) + col;
|
||||
if (index < ItemList.Count())
|
||||
{
|
||||
<div class="col">@Row(ItemList.ElementAt(index))</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="col"> </div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (Toolbar == "Bottom")
|
||||
@if (Toolbar == "Bottom" && _pages > 0 && Items.Count() > _maxItems)
|
||||
{
|
||||
<div class="mx-auto text-center">
|
||||
@if (_endPage > 1)
|
||||
<ul class="pagination justify-content-center my-2">
|
||||
<li class="page-item@((_page > 1) ? "" : " disabled")">
|
||||
<a class="page-link" @onclick=@(async () => UpdateList(1))><span class="oi oi-media-step-backward" title="start" aria-hidden="true"></span></a>
|
||||
</li>
|
||||
@if (_pages > _displayPages)
|
||||
{
|
||||
<button class="btn btn-secondary mr-1" @onclick=@(async () => UpdateList(1))><span class="oi oi-media-step-backward" title="first" aria-hidden="true"></span></button>
|
||||
<li class="page-item@((_page > _displayPages) ? "" : " disabled")">
|
||||
<a class="page-link" @onclick=@(async () => SkipPages("back"))><span class="oi oi-media-skip-backward" title="skip back" aria-hidden="true"></span></a>
|
||||
</li>
|
||||
}
|
||||
@if (_page > _maxPages)
|
||||
<li class="page-item@((_page > 1) ? "" : " disabled")">
|
||||
<a class="page-link" @onclick=@(async () => NavigateToPage("previous"))><span class="oi oi-chevron-left" title="previous" aria-hidden="true"></span></a>
|
||||
</li>
|
||||
@for (int i = _startPage; i <= _endPage; i++)
|
||||
{
|
||||
<button class="btn btn-secondary mr-1" @onclick=@(async () => SetPagerSize("back"))><span class="oi oi-media-skip-backward" title="back" aria-hidden="true"></span></button>
|
||||
}
|
||||
@if (_endPage > 1)
|
||||
{
|
||||
<button class="btn btn-secondary mr-1" @onclick=@(async () => NavigateToPage("previous"))><span class="oi oi-chevron-left" title="previous" aria-hidden="true"></span></button>
|
||||
@for (int i = _startPage; i <= _endPage; i++)
|
||||
var pager = i;
|
||||
if (pager == _page)
|
||||
{
|
||||
var pager = i;
|
||||
<button class="btn @((pager == _page) ? "btn-primary" : "btn-link")" @onclick=@(async () => UpdateList(pager))>
|
||||
@pager
|
||||
</button>
|
||||
<li class="page-item active">
|
||||
<a class="page-link" @onclick=@(async () => UpdateList(pager))>@pager</a>
|
||||
</li>
|
||||
}
|
||||
else
|
||||
{
|
||||
<li class="page-item">
|
||||
<a class="page-link" @onclick=@(async () => UpdateList(pager))>@pager</a>
|
||||
</li>
|
||||
}
|
||||
<button class="btn btn-secondary mr-1" @onclick=@(async () => NavigateToPage("next"))><span class="oi oi-chevron-right" title="next" aria-hidden="true"></span></button>
|
||||
}
|
||||
@if (_endPage < _pages)
|
||||
<li class="page-item@((_page < _pages) ? "" : " disabled")">
|
||||
<a class="page-link" @onclick=@(async () => NavigateToPage("next"))><span class="oi oi-chevron-right" title="next" aria-hidden="true"></span></a>
|
||||
</li>
|
||||
@if (_pages > _displayPages)
|
||||
{
|
||||
<button class="btn btn-secondary mr-1" @onclick=@(async () => SetPagerSize("forward"))><span class="oi oi-media-skip-forward" title="forward" aria-hidden="true"></span></button>
|
||||
<li class="page-item@((_endPage < _pages) ? "" : " disabled")">
|
||||
<a class="page-link" @onclick=@(async () => SkipPages("forward"))><span class="oi oi-media-skip-forward" title="skip forward" aria-hidden="true"></span></a>
|
||||
</li>
|
||||
}
|
||||
@if (_endPage > 1)
|
||||
{
|
||||
<button class="btn btn-secondary mr-1" @onclick=@(async () => UpdateList(_pages))><span class="oi oi-media-step-forward" title="last" aria-hidden="true"></span></button>
|
||||
}
|
||||
@if (_endPage > 1)
|
||||
{
|
||||
<span class="btn btn-link disabled">Page @_page of @_pages</span>
|
||||
}
|
||||
</div>
|
||||
<li class="page-item@((_page < _pages) ? "" : " disabled")">
|
||||
<a class="page-link" @onclick=@(async () => UpdateList(_pages))><span class="oi oi-media-step-forward" title="end" aria-hidden="true"></span></a>
|
||||
</li>
|
||||
<li class="page-item disabled">
|
||||
<a class="page-link">Page @_page of @_pages</a>
|
||||
</li>
|
||||
</ul>
|
||||
}
|
||||
</p>
|
||||
}
|
||||
|
||||
@code {
|
||||
private int _pages = 0;
|
||||
private int _page = 1;
|
||||
private int _maxItems = 10;
|
||||
private int _maxPages = 5;
|
||||
private int _displayPages = 5;
|
||||
private int _startPage = 0;
|
||||
private int _endPage = 0;
|
||||
private int _columns = 1;
|
||||
|
||||
[Parameter]
|
||||
public string Format { get; set; }
|
||||
public string Format { get; set; } // Table or Grid
|
||||
|
||||
[Parameter]
|
||||
public string Toolbar { get; set; }
|
||||
public string Toolbar { get; set; } // Top or Bottom
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment Header { get; set; }
|
||||
public RenderFragment Header { get; set; } = null;
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment<TableItem> Row { get; set; }
|
||||
public RenderFragment<TableItem> Row { get; set; } = null;
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment<TableItem> Detail { get; set; }
|
||||
public RenderFragment<TableItem> Detail { get; set; } = null; // only applicable to Table layouts
|
||||
|
||||
[Parameter]
|
||||
public IEnumerable<TableItem> Items { get; set; }
|
||||
public IEnumerable<TableItem> Items { get; set; } // the IEnumerable data source
|
||||
|
||||
[Parameter]
|
||||
public string PageSize { get; set; }
|
||||
public string PageSize { get; set; } // number of items to display on a page
|
||||
|
||||
[Parameter]
|
||||
public string DisplayPages { get; set; }
|
||||
public string Columns { get; set; } // only applicable to Grid layouts
|
||||
|
||||
[Parameter]
|
||||
public string CurrentPage { get; set; } // optional property to set the initial page to display
|
||||
|
||||
[Parameter]
|
||||
public string DisplayPages { get; set; } // maximum number of page numbers to display for user selection
|
||||
|
||||
[Parameter]
|
||||
public string Class { get; set; }
|
||||
|
@ -177,86 +224,89 @@
|
|||
_maxItems = int.Parse(PageSize);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(DisplayPages))
|
||||
if (!string.IsNullOrEmpty(Columns))
|
||||
{
|
||||
_maxPages = int.Parse(DisplayPages);
|
||||
_columns = int.Parse(Columns);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(DisplayPages))
|
||||
{
|
||||
_displayPages = int.Parse(DisplayPages);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(CurrentPage))
|
||||
{
|
||||
_page = int.Parse(CurrentPage);
|
||||
}
|
||||
else
|
||||
{
|
||||
_page = 1;
|
||||
}
|
||||
|
||||
_page = 1;
|
||||
_startPage = 0;
|
||||
_endPage = 0;
|
||||
|
||||
if (Items != null)
|
||||
{
|
||||
ItemList = Items.Skip((_page - 1) * _maxItems).Take(_maxItems);
|
||||
_pages = (int)Math.Ceiling(Items.Count() / (decimal)_maxItems);
|
||||
if (_page > _pages)
|
||||
{
|
||||
_page = _pages;
|
||||
}
|
||||
ItemList = Items.Skip((_page - 1) * _maxItems).Take(_maxItems);
|
||||
SetPagerSize();
|
||||
}
|
||||
|
||||
SetPagerSize("forward");
|
||||
}
|
||||
|
||||
public void UpdateList(int currentPage)
|
||||
public void SetPagerSize()
|
||||
{
|
||||
ItemList = Items.Skip((currentPage - 1) * _maxItems).Take(_maxItems);
|
||||
_page = currentPage;
|
||||
|
||||
_startPage = ((_page - 1) / _displayPages) * _displayPages + 1;
|
||||
_endPage = _startPage + _displayPages - 1;
|
||||
if (_endPage > _pages)
|
||||
{
|
||||
_endPage = _pages;
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
public void SetPagerSize(string direction)
|
||||
public void UpdateList(int page)
|
||||
{
|
||||
if (direction == "forward")
|
||||
{
|
||||
if (_endPage + 1 < _pages)
|
||||
{
|
||||
_startPage = _endPage + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_startPage = 1;
|
||||
}
|
||||
ItemList = Items.Skip((page - 1) * _maxItems).Take(_maxItems);
|
||||
_page = page;
|
||||
SetPagerSize();
|
||||
}
|
||||
|
||||
if (_endPage + _maxPages < _pages)
|
||||
{
|
||||
_endPage = _startPage + _maxPages - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_endPage = _pages;
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
else if (direction == "back")
|
||||
public void SkipPages(string direction)
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
_endPage = _startPage - 1;
|
||||
_startPage = _startPage - _maxPages;
|
||||
case "forward":
|
||||
_page = _endPage + 1;
|
||||
break;
|
||||
case "back":
|
||||
_page = _startPage - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
SetPagerSize();
|
||||
}
|
||||
|
||||
public void NavigateToPage(string direction)
|
||||
{
|
||||
if (direction == "next")
|
||||
switch (direction)
|
||||
{
|
||||
if (_page < _pages)
|
||||
{
|
||||
if (_page == _endPage)
|
||||
case "next":
|
||||
if (_page < _pages)
|
||||
{
|
||||
SetPagerSize("forward");
|
||||
_page += 1;
|
||||
}
|
||||
_page += 1;
|
||||
}
|
||||
}
|
||||
else if (direction == "previous")
|
||||
{
|
||||
if (_page > 1)
|
||||
{
|
||||
if (_page == _startPage)
|
||||
break;
|
||||
case "previous":
|
||||
if (_page > 1)
|
||||
{
|
||||
SetPagerSize("back");
|
||||
_page -= 1;
|
||||
}
|
||||
_page -= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateList(_page);
|
||||
|
|
|
@ -7,73 +7,96 @@
|
|||
|
||||
@if (_permissions != null)
|
||||
{
|
||||
<br />
|
||||
<table class="table table-borderless" style="width: 50%; min-width: 250px;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="col">@Localizer["Role"]</th>
|
||||
@foreach (PermissionString permission in _permissions)
|
||||
{
|
||||
<th style="text-align: center; width: 1px;">@Localizer[permission.PermissionName]</th>
|
||||
}
|
||||
</tr>
|
||||
@foreach (Role role in _roles)
|
||||
{
|
||||
<tr>
|
||||
<td>@role.Name</td>
|
||||
@foreach (PermissionString permission in _permissions)
|
||||
{
|
||||
var p = permission;
|
||||
<td style="text-align: center;">
|
||||
<TriStateCheckBox Value=@GetPermissionValue(p.Permissions, role.Name) Disabled=@GetPermissionDisabled(role.Name) OnChange="@(e => PermissionChanged(e, p.PermissionName, role.Name))" />
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
@if (_users.Count != 0)
|
||||
{
|
||||
<table class="table table-borderless" style="width: 50%; min-width: 250px;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">@Localizer["User"]</th>
|
||||
@foreach (PermissionString permission in _permissions)
|
||||
{
|
||||
<th style="text-align: center; width: 1px;">@Localizer[permission.PermissionName]</th>
|
||||
}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (User user in _users)
|
||||
{
|
||||
string userid = "[" + user.UserId.ToString() + "]";
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table class="table table-borderless">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>@user.DisplayName</td>
|
||||
<th scope="col">@Localizer["Role"]</th>
|
||||
@foreach (PermissionString permission in _permissions)
|
||||
{
|
||||
var p = permission;
|
||||
<td style="text-align: center; width: 1px;">
|
||||
<TriStateCheckBox Value=@GetPermissionValue(p.Permissions, userid) Disabled=false OnChange="@(e => PermissionChanged(e, p.PermissionName, userid))" />
|
||||
</td>
|
||||
<th style="text-align: center; width: 1px;">@Localizer[permission.PermissionName]</th>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
<table class="table table-borderless" style="width: 50%; min-width: 250px;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="input-group">
|
||||
<input type="text" name="Username" class="form-control" placeholder="@Localizer["Username.Enter"]" @bind="@_username" />
|
||||
<button type="button" class="btn btn-primary" @onclick="AddUser">@SharedLocalizer["Add"]</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br />
|
||||
<ModuleMessage Type="MessageType.Error" Message="@_message" />
|
||||
@foreach (Role role in _roles)
|
||||
{
|
||||
<tr>
|
||||
<td>@role.Name</td>
|
||||
@foreach (PermissionString permission in _permissions)
|
||||
{
|
||||
var p = permission;
|
||||
<td style="text-align: center;">
|
||||
<TriStateCheckBox Value=@GetPermissionValue(p.Permissions, role.Name) Disabled=@GetPermissionDisabled(role.Name) OnChange="@(e => PermissionChanged(e, p.PermissionName, role.Name))" />
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
@if (_users.Count != 0)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-borderless">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">@Localizer["User"]</th>
|
||||
@foreach (PermissionString permission in _permissions)
|
||||
{
|
||||
<th style="text-align: center; width: 1px;">@Localizer[permission.PermissionName]</th>
|
||||
}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (User user in _users)
|
||||
{
|
||||
string userid = "[" + user.UserId.ToString() + "]";
|
||||
<tr>
|
||||
<td>@user.DisplayName</td>
|
||||
@foreach (PermissionString permission in _permissions)
|
||||
{
|
||||
var p = permission;
|
||||
<td style="text-align: center; width: 1px;">
|
||||
<TriStateCheckBox Value=@GetPermissionValue(p.Permissions, userid) Disabled=false OnChange="@(e => PermissionChanged(e, p.PermissionName, userid))" />
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<br />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<table class="table table-borderless">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="input-group">
|
||||
<input type="text" name="Username" class="form-control" placeholder="@Localizer["Username.Enter"]" @bind="@_username" />
|
||||
<button type="button" class="btn btn-primary" @onclick="AddUser">@SharedLocalizer["Add"]</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<ModuleMessage Type="MessageType.Error" Message="@_message" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
@namespace Oqtane.Modules.HtmlText
|
||||
@inherits ModuleBase
|
||||
@inject IHtmlTextService HtmlTextService
|
||||
@inject IStringLocalizer<Edit> Localizer
|
||||
@inject IStringLocalizer<Index> Localizer
|
||||
|
||||
@((MarkupString)content)
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
|||
|
||||
@code {
|
||||
public override List<Resource> Resources => new List<Resource>()
|
||||
{
|
||||
{
|
||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
|
||||
};
|
||||
|
||||
|
|
|
@ -5,46 +5,44 @@
|
|||
@inject IStringLocalizer<Settings> Localizer
|
||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="30%">
|
||||
<Label For="files" ResourceKey="Allow File Management" HelpText="Specify If Editors Can Upload and Select Files">Allow File Management: </Label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="files" class="form-select" @bind="@_allowfilemanagement">
|
||||
<option value="true">@SharedLocalizer["Yes"]</option>
|
||||
<option value="false">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="container">
|
||||
<div class="row mb-1 align-items-center">
|
||||
<Label Class="col-sm-3" For="files" ResourceKey="Allow File Management" HelpText="Specify If Editors Can Upload and Select Files">Allow File Management: </Label>
|
||||
<div class="col-sm-9">
|
||||
<select id="files" class="form-select" @bind="@_allowfilemanagement">
|
||||
<option value="true">@SharedLocalizer["Yes"]</option>
|
||||
<option value="false">@SharedLocalizer["No"]</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private string _allowfilemanagement;
|
||||
@code {
|
||||
private string _allowfilemanagement;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
try
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_allowfilemanagement = SettingService.GetSetting(ModuleState.Settings, "AllowFileManagement", "true");
|
||||
try
|
||||
{
|
||||
_allowfilemanagement = SettingService.GetSetting(ModuleState.Settings, "AllowFileManagement", "true");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModuleInstance.AddModuleMessage(ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
public async Task UpdateSettings()
|
||||
{
|
||||
ModuleInstance.AddModuleMessage(ex.Message, MessageType.Error);
|
||||
try
|
||||
{
|
||||
var settings = ModuleState.Settings;
|
||||
settings = SettingService.SetSetting(settings, "AllowFileManagement", _allowfilemanagement);
|
||||
await SettingService.UpdateModuleSettingsAsync(settings, ModuleState.ModuleId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModuleInstance.AddModuleMessage(ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
var settings = ModuleState.Settings;
|
||||
settings = SettingService.SetSetting(settings, "AllowFileManagement", _allowfilemanagement);
|
||||
await SettingService.UpdateModuleSettingsAsync(settings, ModuleState.ModuleId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ModuleInstance.AddModuleMessage(ex.Message, MessageType.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,6 +134,11 @@ namespace Oqtane.Modules
|
|||
return Utilities.ContentUrl(PageState.Alias, fileid, asAttachment);
|
||||
}
|
||||
|
||||
public string ImageUrl(int fileid, int width, int height, string mode)
|
||||
{
|
||||
return Utilities.ImageUrl(PageState.Alias, fileid, width, height, mode);
|
||||
}
|
||||
|
||||
public virtual Dictionary<string, string> GetUrlParameters(string parametersTemplate = "")
|
||||
{
|
||||
var urlParameters = new Dictionary<string, string>();
|
||||
|
@ -205,6 +210,38 @@ namespace Oqtane.Modules
|
|||
|
||||
// logging methods
|
||||
public async Task Log(Alias alias, LogLevel level, string function, Exception exception, string message, params object[] args)
|
||||
{
|
||||
LogFunction logFunction;
|
||||
if (string.IsNullOrEmpty(function))
|
||||
{
|
||||
// try to infer from page action
|
||||
function = PageState.Action;
|
||||
}
|
||||
if (!Enum.TryParse(function, out logFunction))
|
||||
{
|
||||
switch (function.ToLower())
|
||||
{
|
||||
case "add":
|
||||
logFunction = LogFunction.Create;
|
||||
break;
|
||||
case "edit":
|
||||
logFunction = LogFunction.Update;
|
||||
break;
|
||||
case "delete":
|
||||
logFunction = LogFunction.Delete;
|
||||
break;
|
||||
case "":
|
||||
logFunction = LogFunction.Read;
|
||||
break;
|
||||
default:
|
||||
logFunction = LogFunction.Other;
|
||||
break;
|
||||
}
|
||||
}
|
||||
await Log(alias, level, logFunction, exception, message, args);
|
||||
}
|
||||
|
||||
public async Task Log(Alias alias, LogLevel level, LogFunction function, Exception exception, string message, params object[] args)
|
||||
{
|
||||
int pageId = ModuleState.PageId;
|
||||
int moduleId = ModuleState.ModuleId;
|
||||
|
@ -215,34 +252,8 @@ namespace Oqtane.Modules
|
|||
}
|
||||
string category = GetType().AssemblyQualifiedName;
|
||||
string feature = Utilities.GetTypeNameLastSegment(category, 1);
|
||||
LogFunction logFunction;
|
||||
if (string.IsNullOrEmpty(function))
|
||||
{
|
||||
function = PageState.Action;
|
||||
}
|
||||
switch (function.ToLower())
|
||||
{
|
||||
case "add":
|
||||
logFunction = LogFunction.Create;
|
||||
break;
|
||||
|
||||
case "edit":
|
||||
logFunction = LogFunction.Update;
|
||||
break;
|
||||
|
||||
case "delete":
|
||||
logFunction = LogFunction.Delete;
|
||||
break;
|
||||
|
||||
default:
|
||||
logFunction = LogFunction.Read;
|
||||
break;
|
||||
}
|
||||
if (feature == "Login")
|
||||
{
|
||||
logFunction = LogFunction.Security;
|
||||
}
|
||||
await LoggingService.Log(alias, pageId, moduleId, userId, category, feature, logFunction, level, exception, message, args);
|
||||
await LoggingService.Log(alias, pageId, moduleId, userId, category, feature, function, level, exception, message, args);
|
||||
}
|
||||
|
||||
public class Logger
|
||||
|
@ -259,6 +270,11 @@ namespace Oqtane.Modules
|
|||
await _moduleBase.Log(null, LogLevel.Trace, "", null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogTrace(LogFunction function, string message, params object[] args)
|
||||
{
|
||||
await _moduleBase.Log(null, LogLevel.Trace, function, null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogTrace(Exception exception, string message, params object[] args)
|
||||
{
|
||||
await _moduleBase.Log(null, LogLevel.Trace, "", exception, message, args);
|
||||
|
@ -269,6 +285,11 @@ namespace Oqtane.Modules
|
|||
await _moduleBase.Log(null, LogLevel.Debug, "", null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogDebug(LogFunction function, string message, params object[] args)
|
||||
{
|
||||
await _moduleBase.Log(null, LogLevel.Debug, function, null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogDebug(Exception exception, string message, params object[] args)
|
||||
{
|
||||
await _moduleBase.Log(null, LogLevel.Debug, "", exception, message, args);
|
||||
|
@ -279,6 +300,11 @@ namespace Oqtane.Modules
|
|||
await _moduleBase.Log(null, LogLevel.Information, "", null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogInformation(LogFunction function, string message, params object[] args)
|
||||
{
|
||||
await _moduleBase.Log(null, LogLevel.Information, function, null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogInformation(Exception exception, string message, params object[] args)
|
||||
{
|
||||
await _moduleBase.Log(null, LogLevel.Information, "", exception, message, args);
|
||||
|
@ -289,6 +315,11 @@ namespace Oqtane.Modules
|
|||
await _moduleBase.Log(null, LogLevel.Warning, "", null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogWarning(LogFunction function, string message, params object[] args)
|
||||
{
|
||||
await _moduleBase.Log(null, LogLevel.Warning, function, null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogWarning(Exception exception, string message, params object[] args)
|
||||
{
|
||||
await _moduleBase.Log(null, LogLevel.Warning, "", exception, message, args);
|
||||
|
@ -299,6 +330,11 @@ namespace Oqtane.Modules
|
|||
await _moduleBase.Log(null, LogLevel.Error, "", null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogError(LogFunction function, string message, params object[] args)
|
||||
{
|
||||
await _moduleBase.Log(null, LogLevel.Error, function, null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogError(Exception exception, string message, params object[] args)
|
||||
{
|
||||
await _moduleBase.Log(null, LogLevel.Error, "", exception, message, args);
|
||||
|
@ -309,6 +345,11 @@ namespace Oqtane.Modules
|
|||
await _moduleBase.Log(null, LogLevel.Critical, "", null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogCritical(LogFunction function, string message, params object[] args)
|
||||
{
|
||||
await _moduleBase.Log(null, LogLevel.Critical, function, null, message, args);
|
||||
}
|
||||
|
||||
public async Task LogCritical(Exception exception, string message, params object[] args)
|
||||
{
|
||||
await _moduleBase.Log(null, LogLevel.Critical, "", exception, message, args);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<OutputType>Exe</OutputType>
|
||||
<RazorLangVersion>3.0</RazorLangVersion>
|
||||
<Configurations>Debug;Release</Configurations>
|
||||
<Version>2.2.0</Version>
|
||||
<Version>2.3.0</Version>
|
||||
<Product>Oqtane</Product>
|
||||
<Authors>Shaun Walker</Authors>
|
||||
<Company>.NET Foundation</Company>
|
||||
|
@ -13,7 +13,7 @@
|
|||
<Copyright>.NET Foundation</Copyright>
|
||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v2.2.0</PackageReleaseNotes>
|
||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v2.3.0</PackageReleaseNotes>
|
||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
<RootNamespace>Oqtane</RootNamespace>
|
||||
|
@ -38,4 +38,15 @@
|
|||
<Folder Include="Resources\" />
|
||||
<Folder Include="Resources\Themes\Controls\Theme\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<TrimmerRootAssembly Include="System.Runtime" />
|
||||
<TrimmerRootAssembly Include="System.Linq.Parallel" />
|
||||
<TrimmerRootAssembly Include="System.Runtime.CompilerServices.VisualC" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<BlazorEnableCompression>false</BlazorEnableCompression>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -153,4 +153,10 @@
|
|||
<data name="Pwd.HelpText" xml:space="preserve">
|
||||
<value>Enter the password to use for the database</value>
|
||||
</data>
|
||||
<data name="Custom" xml:space="preserve">
|
||||
<value>Custom</value>
|
||||
</data>
|
||||
<data name="Integrated" xml:space="preserve">
|
||||
<value>Integrated</value>
|
||||
</data>
|
||||
</root>
|
|
@ -147,4 +147,10 @@
|
|||
<data name="Pwd.HelpText" xml:space="preserve">
|
||||
<value>Enter the password to use for the database</value>
|
||||
</data>
|
||||
<data name="Custom" xml:space="preserve">
|
||||
<value>Custom</value>
|
||||
</data>
|
||||
<data name="Integrated" xml:space="preserve">
|
||||
<value>Integrated</value>
|
||||
</data>
|
||||
</root>
|
|
@ -120,8 +120,8 @@
|
|||
<data name="DatabaseConfig" xml:space="preserve">
|
||||
<value>Database Configuration</value>
|
||||
</data>
|
||||
<data name="DatabaseType" xml:space="preserve">
|
||||
<value>Database Type:</value>
|
||||
<data name="DatabaseType.Text" xml:space="preserve">
|
||||
<value>Database:</value>
|
||||
</data>
|
||||
<data name="ApplicationAdmin" xml:space="preserve">
|
||||
<value>Application Administrator</value>
|
||||
|
@ -138,4 +138,31 @@
|
|||
<data name="Register" xml:space="preserve">
|
||||
<value>Please Register Me For Major Product Updates And Security Bulletins</value>
|
||||
</data>
|
||||
<data name="Confirm.HelpText" xml:space="preserve">
|
||||
<value>Please confirm the password entered above by entering it again</value>
|
||||
</data>
|
||||
<data name="Confirm.Text" xml:space="preserve">
|
||||
<value>Confirm:</value>
|
||||
</data>
|
||||
<data name="DatabaseType.HelpText" xml:space="preserve">
|
||||
<value>Select the type of database you wish to use</value>
|
||||
</data>
|
||||
<data name="Email.HelpText" xml:space="preserve">
|
||||
<value>Provide the email address for the host user account</value>
|
||||
</data>
|
||||
<data name="Email.Text" xml:space="preserve">
|
||||
<value>Email:</value>
|
||||
</data>
|
||||
<data name="Password.HelpText" xml:space="preserve">
|
||||
<value>Provide a password for the primary user account</value>
|
||||
</data>
|
||||
<data name="Password.Text" xml:space="preserve">
|
||||
<value>Password:</value>
|
||||
</data>
|
||||
<data name="Username.HelpText" xml:space="preserve">
|
||||
<value>Provide a username for the primary user account</value>
|
||||
</data>
|
||||
<data name="Username.Text" xml:space="preserve">
|
||||
<value>Username:</value>
|
||||
</data>
|
||||
</root>
|
|
@ -156,4 +156,10 @@
|
|||
<data name="UploadFiles.Heading" xml:space="preserve">
|
||||
<value>Upload Files</value>
|
||||
</data>
|
||||
<data name="Name.HelpText" xml:space="preserve">
|
||||
<value>Enter the name of the file being downloaded</value>
|
||||
</data>
|
||||
<data name="Name.Text" xml:space="preserve">
|
||||
<value>Name:</value>
|
||||
</data>
|
||||
</root>
|
|
@ -144,4 +144,10 @@
|
|||
<data name="Size.Text" xml:space="preserve">
|
||||
<value>Size: </value>
|
||||
</data>
|
||||
<data name="Description.HelpText" xml:space="preserve">
|
||||
<value>A description of the file. This can be used as a caption for image files.</value>
|
||||
</data>
|
||||
<data name="Description.Text" xml:space="preserve">
|
||||
<value>Description:</value>
|
||||
</data>
|
||||
</root>
|
|
@ -165,4 +165,22 @@
|
|||
<data name="DeleteFolder.Message" xml:space="preserve">
|
||||
<value>Are You Sure You Wish To Delete This Folder?</value>
|
||||
</data>
|
||||
<data name="Type.HelpText" xml:space="preserve">
|
||||
<value>Select the folder type. Private folders are only accessible by authorized users. Public folders can be accessed by all users</value>
|
||||
</data>
|
||||
<data name="Type.Text" xml:space="preserve">
|
||||
<value>Type:</value>
|
||||
</data>
|
||||
<data name="Capacity.HelpText" xml:space="preserve">
|
||||
<value>Enter the maximum folder capacity (in megabytes). Specify zero if the capacity is unlimited.</value>
|
||||
</data>
|
||||
<data name="Capacity.Text" xml:space="preserve">
|
||||
<value>Capacity:</value>
|
||||
</data>
|
||||
<data name="ImageSizes.HelpText" xml:space="preserve">
|
||||
<value>Enter a list of image sizes which can be generated dynamically from uploaded images (ie. 200x200,x200,200x)</value>
|
||||
</data>
|
||||
<data name="ImageSizes.Text" xml:space="preserve">
|
||||
<value>Image Sizes:</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
@ -154,16 +154,16 @@
|
|||
<value>Select how often you want the job to run</value>
|
||||
</data>
|
||||
<data name="Starting.HelpText" xml:space="preserve">
|
||||
<value>What time do you want the job to start</value>
|
||||
<value>Optionally enter the date and time when this job should start executing</value>
|
||||
</data>
|
||||
<data name="Ending.HelpText" xml:space="preserve">
|
||||
<value>When do you want the job to end</value>
|
||||
<value>Optionally enter the date and time when this job should stop executing</value>
|
||||
</data>
|
||||
<data name="RetentionLog.HelpText" xml:space="preserve">
|
||||
<value>Number of log entries to retain for this job</value>
|
||||
</data>
|
||||
<data name="NextExecution.HelpText" xml:space="preserve">
|
||||
<value>Next execution for this job.</value>
|
||||
<value>Optionally modify the date and time when this job should execute next</value>
|
||||
</data>
|
||||
<data name="Type.Text" xml:space="preserve">
|
||||
<value>Type: </value>
|
||||
|
|
|
@ -121,9 +121,15 @@
|
|||
<value>Export</value>
|
||||
</data>
|
||||
<data name="Content.HelpText" xml:space="preserve">
|
||||
<value>Enter the module content</value>
|
||||
<value>The Exported Module Content</value>
|
||||
</data>
|
||||
<data name="Content.Text" xml:space="preserve">
|
||||
<value>Content: </value>
|
||||
</data>
|
||||
<data name="Error.Module.Export" xml:space="preserve">
|
||||
<value>Error Exporting Module Content</value>
|
||||
</data>
|
||||
<data name="Success.Content.Export" xml:space="preserve">
|
||||
<value>Content Exported Successfully</value>
|
||||
</data>
|
||||
</root>
|
|
@ -118,7 +118,7 @@
|
|||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Content.HelpText" xml:space="preserve">
|
||||
<value>Enter the module content</value>
|
||||
<value>Enter The Module Content To Import</value>
|
||||
</data>
|
||||
<data name="Content.Text" xml:space="preserve">
|
||||
<value>Content: </value>
|
||||
|
@ -133,7 +133,7 @@
|
|||
<value>A Problem Was Encountered Importing Content. Please Ensure The Content Is Formatted Correctly For The Module.</value>
|
||||
</data>
|
||||
<data name="Error.Module.Import" xml:space="preserve">
|
||||
<value>Error Importing Module</value>
|
||||
<value>Error Importing Module Content</value>
|
||||
</data>
|
||||
<data name="Message.Required.ImportContent" xml:space="preserve">
|
||||
<value>You Must Enter Some Content To Import</value>
|
||||
|
|
|
@ -228,4 +228,7 @@
|
|||
<data name="Appearance.Name" xml:space="preserve">
|
||||
<value>Appearance</value>
|
||||
</data>
|
||||
<data name="Message.Page.Deleted" xml:space="preserve">
|
||||
<value>A page with path {0} already exists for the selected parent page in the Recycle Bin. Either recover the page or remove from the Recycle Bin and create it again.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -148,7 +148,7 @@
|
|||
<value>Error Adding User</value>
|
||||
</data>
|
||||
<data name="Confirm.HelpText" xml:space="preserve">
|
||||
<value>If you are changing your password you must enter it again to confirm it matches</value>
|
||||
<value>Enter your password again to confirm it matches the value entered above</value>
|
||||
</data>
|
||||
<data name="Confirm.Text" xml:space="preserve">
|
||||
<value>Confirm Password:</value>
|
||||
|
@ -166,7 +166,7 @@
|
|||
<value>Email:</value>
|
||||
</data>
|
||||
<data name="Password.HelpText" xml:space="preserve">
|
||||
<value>If you wish to change your password you can enter it here. Please choose a sufficiently secure password.</value>
|
||||
<value>Please choose a sufficiently secure password and enter it here</value>
|
||||
</data>
|
||||
<data name="Password.Text" xml:space="preserve">
|
||||
<value>Password:</value>
|
||||
|
|
|
@ -217,10 +217,10 @@
|
|||
<value>Enter the password for the integrated security</value>
|
||||
</data>
|
||||
<data name="HostUsername.HelpText" xml:space="preserve">
|
||||
<value>Enter the username of the host for this site</value>
|
||||
<value>Enter a valid host username</value>
|
||||
</data>
|
||||
<data name="HostPassword.HelpText" xml:space="preserve">
|
||||
<value>Enter the password for the host of this site</value>
|
||||
<value>Enter a valid host password</value>
|
||||
</data>
|
||||
<data name="Name.Text" xml:space="preserve">
|
||||
<value>Site Name: </value>
|
||||
|
|
|
@ -273,10 +273,43 @@
|
|||
<data name="FullName" xml:space="preserve">
|
||||
<value>Full Name:</value>
|
||||
</data>
|
||||
<data name="LocalVersion" xml:space="preserve">
|
||||
<data name="LocalVersion" xml:space="preserve">
|
||||
<value>Local Version</value>
|
||||
</data>
|
||||
<data name="Search.Source" xml:space="preserve">
|
||||
<value>source</value>
|
||||
</data>
|
||||
<data name="Message.InfoRequired" xml:space="preserve">
|
||||
<value>Please Provide All Required Information</value>
|
||||
</data>
|
||||
<data name="Free" xml:space="preserve">
|
||||
<value>Free</value>
|
||||
</data>
|
||||
<data name="Paid" xml:space="preserve">
|
||||
<value>Paid</value>
|
||||
</data>
|
||||
<data name="Search.Price" xml:space="preserve">
|
||||
<value>price</value>
|
||||
</data>
|
||||
<data name="Accept" xml:space="preserve">
|
||||
<value>Accept</value>
|
||||
</data>
|
||||
<data name="License Not Specified" xml:space="preserve">
|
||||
<value>License Not Specified</value>
|
||||
</data>
|
||||
<data name="Review License Terms" xml:space="preserve">
|
||||
<value>Review License Terms</value>
|
||||
</data>
|
||||
<data name="Trial" xml:space="preserve">
|
||||
<value>Day Trial</value>
|
||||
</data>
|
||||
<data name="Expires" xml:space="preserve">
|
||||
<value>Expires</value>
|
||||
</data>
|
||||
<data name="Extend" xml:space="preserve">
|
||||
<value>Extend</value>
|
||||
</data>
|
||||
<data name="Not Specified" xml:space="preserve">
|
||||
<value>Not Specified</value>
|
||||
</data>
|
||||
</root>
|
|
@ -1,65 +1,65 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
|
@ -117,10 +117,28 @@
|
|||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Title.HelpText" xml:space="preserve">
|
||||
<value>Specify If The Page Footer Should Be Displayed</value>
|
||||
<data name="Footer.HelpText" xml:space="preserve">
|
||||
<value>Specify if a Footer pane should always be displayed in a fixed location at the bottom of the page.</value>
|
||||
</data>
|
||||
<data name="Title.Text" xml:space="preserve">
|
||||
<data name="Footer.Text" xml:space="preserve">
|
||||
<value>Display Footer?</value>
|
||||
</data>
|
||||
<data name="Login.HelpText" xml:space="preserve">
|
||||
<value>Specify if a Login option should be displayed, Note that this option does not prevent the login page from being accessible via a direct url.</value>
|
||||
</data>
|
||||
<data name="Login.Text" xml:space="preserve">
|
||||
<value>Show Login?</value>
|
||||
</data>
|
||||
<data name="Page" xml:space="preserve">
|
||||
<value>Page</value>
|
||||
</data>
|
||||
<data name="Register.HelpText" xml:space="preserve">
|
||||
<value>Specify if a Register option should be displayed. Note that this option is also dependent on the Allow Registration option in Site Settings.</value>
|
||||
</data>
|
||||
<data name="Register.Text" xml:space="preserve">
|
||||
<value>Show Register?</value>
|
||||
</data>
|
||||
<data name="Site" xml:space="preserve">
|
||||
<value>Site</value>
|
||||
</data>
|
||||
</root>
|
|
@ -67,9 +67,9 @@ namespace Oqtane.Services
|
|||
await DeleteAsync($"{Apiurl}/{fileId}");
|
||||
}
|
||||
|
||||
public async Task<File> UploadFileAsync(string url, int folderId)
|
||||
public async Task<File> UploadFileAsync(string url, int folderId, string name)
|
||||
{
|
||||
return await GetJsonAsync<File>($"{Apiurl}/upload?url={WebUtility.UrlEncode(url)}&folderid={folderId}");
|
||||
return await GetJsonAsync<File>($"{Apiurl}/upload?url={WebUtility.UrlEncode(url)}&folderid={folderId}&name={name}");
|
||||
}
|
||||
|
||||
public async Task<string> UploadFilesAsync(int folderId, string[] files, string id)
|
||||
|
|
|
@ -4,8 +4,15 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to retrieve <see cref="Database"/> information.
|
||||
/// </summary>
|
||||
public interface IDatabaseService
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a list of databases
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<Database>> GetDatabasesAsync();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,8 +62,9 @@ namespace Oqtane.Services
|
|||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="folderId"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <returns></returns>
|
||||
Task<File> UploadFileAsync(string url, int folderId);
|
||||
Task<File> UploadFileAsync(string url, int folderId, string name);
|
||||
|
||||
/// <summary>
|
||||
/// Upload one or more files.
|
||||
|
|
|
@ -4,12 +4,42 @@ using Oqtane.Shared;
|
|||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Service to manage (install master database / upgrade version / etc.) the installation
|
||||
/// </summary>
|
||||
public interface IInstallationService
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a status/message object with the current installation state
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<Installation> IsInstalled();
|
||||
|
||||
/// <summary>
|
||||
/// Starts the installation process
|
||||
/// </summary>
|
||||
/// <param name="config">connectionString, database type, alias etc.</param>
|
||||
/// <returns>internal status/message object</returns>
|
||||
Task<Installation> Install(InstallConfig config);
|
||||
|
||||
/// <summary>
|
||||
/// Starts the upgrade process
|
||||
/// </summary>
|
||||
/// <returns>internal status/message object</returns>
|
||||
Task<Installation> Upgrade();
|
||||
|
||||
/// <summary>
|
||||
/// Restarts the installation
|
||||
/// </summary>
|
||||
/// <returns>internal status/message object</returns>
|
||||
Task RestartAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Registers a new <see cref="User"/>
|
||||
/// </summary>
|
||||
/// <param name="email">Email of the user to be registered</param>
|
||||
/// <returns></returns>
|
||||
Task RegisterAsync(string email);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,22 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to read the job schedule log
|
||||
/// </summary>
|
||||
public interface IJobLogService
|
||||
{
|
||||
/// <summary>
|
||||
/// Return a list of all <see cref="JobLog"/> entries
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<JobLog>> GetJobLogsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Return a <see cref="JobLog"/> entry for the given Id
|
||||
/// </summary>
|
||||
/// <param name="jobLogId"></param>
|
||||
/// <returns></returns>
|
||||
Task<JobLog> GetJobLogAsync(int jobLogId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,23 +1,61 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Service to manage jobs (<see cref="Job"/>)
|
||||
/// </summary>
|
||||
public interface IJobService
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a list of all jobs
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<Job>> GetJobsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Return a specific job
|
||||
/// </summary>
|
||||
/// <param name="jobId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Job> GetJobAsync(int jobId);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new job
|
||||
/// </summary>
|
||||
/// <param name="job"></param>
|
||||
/// <returns></returns>
|
||||
Task<Job> AddJobAsync(Job job);
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing job
|
||||
/// </summary>
|
||||
/// <param name="job"></param>
|
||||
/// <returns></returns>
|
||||
Task<Job> UpdateJobAsync(Job job);
|
||||
|
||||
/// <summary>
|
||||
/// Delete an existing job
|
||||
/// </summary>
|
||||
/// <param name="jobId"></param>
|
||||
/// <returns></returns>
|
||||
Task DeleteJobAsync(int jobId);
|
||||
|
||||
/// <summary>
|
||||
/// Starts the given job
|
||||
/// </summary>
|
||||
/// <param name="jobId"></param>
|
||||
/// <returns></returns>
|
||||
Task StartJobAsync(int jobId);
|
||||
|
||||
/// <summary>
|
||||
/// Stops the given job
|
||||
/// </summary>
|
||||
/// <param name="jobId"></param>
|
||||
/// <returns></returns>
|
||||
Task StopJobAsync(int jobId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,38 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Service to manage <see cref="Language"/> entries
|
||||
/// </summary>
|
||||
public interface ILanguageService
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a list of all available languages for the given <see cref="Site"/>
|
||||
/// </summary>
|
||||
/// <param name="siteId"></param>
|
||||
/// <returns></returns>
|
||||
Task<List<Language>> GetLanguagesAsync(int siteId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the given language
|
||||
/// </summary>
|
||||
/// <param name="languageId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Language> GetLanguageAsync(int languageId);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given language
|
||||
/// </summary>
|
||||
/// <param name="language"></param>
|
||||
/// <returns></returns>
|
||||
Task<Language> AddLanguageAsync(Language language);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the given language
|
||||
/// </summary>
|
||||
/// <param name="languageId"></param>
|
||||
/// <returns></returns>
|
||||
Task DeleteLanguageAsync(int languageId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,15 @@ using Oqtane.Models;
|
|||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to retrieve localizations (<see cref="Culture"/>)
|
||||
/// </summary>
|
||||
public interface ILocalizationService
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a collection of supported cultures
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<IEnumerable<Culture>> GetCulturesAsync();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using Oqtane.Shared;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -7,11 +7,59 @@ using Oqtane.Enums;
|
|||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to retrieve and store <see cref="Log"/> entries
|
||||
/// </summary>
|
||||
public interface ILogService
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a list of log entires for the given params
|
||||
/// </summary>
|
||||
/// <param name="siteId"></param>
|
||||
/// <param name="level"></param>
|
||||
/// <param name="function"></param>
|
||||
/// <param name="rows"></param>
|
||||
/// <returns></returns>
|
||||
Task<List<Log>> GetLogsAsync(int siteId, string level, string function, int rows);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specific log entry for the given id
|
||||
/// </summary>
|
||||
/// <param name="logId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Log> GetLogAsync(int logId);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new log entry
|
||||
/// </summary>
|
||||
/// <param name="pageId"></param>
|
||||
/// <param name="moduleId"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="category"></param>
|
||||
/// <param name="feature"></param>
|
||||
/// <param name="function"></param>
|
||||
/// <param name="level"></param>
|
||||
/// <param name="exception"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
Task Log(int? pageId, int? moduleId, int? userId, string category, string feature, LogFunction function, LogLevel level, Exception exception, string message, params object[] args);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new log entry
|
||||
/// </summary>
|
||||
/// <param name="alias"></param>
|
||||
/// <param name="pageId"></param>
|
||||
/// <param name="moduleId"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="category"></param>
|
||||
/// <param name="feature"></param>
|
||||
/// <param name="function"></param>
|
||||
/// <param name="level"></param>
|
||||
/// <param name="exception"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
Task Log(Alias alias, int? pageId, int? moduleId, int? userId, string category, string feature, LogFunction function, LogLevel level, Exception exception, string message, params object[] args);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,14 +5,60 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Service to manage a <see cref="ModuleDefinition"/>
|
||||
/// </summary>
|
||||
public interface IModuleDefinitionService
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a list of module definitions for the given site
|
||||
/// </summary>
|
||||
/// <param name="siteId"></param>
|
||||
/// <returns></returns>
|
||||
Task<List<ModuleDefinition>> GetModuleDefinitionsAsync(int siteId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specific module definition
|
||||
/// </summary>
|
||||
/// <param name="moduleDefinitionId"></param>
|
||||
/// <param name="siteId"></param>
|
||||
/// <returns></returns>
|
||||
Task<ModuleDefinition> GetModuleDefinitionAsync(int moduleDefinitionId, int siteId);
|
||||
|
||||
/// <summary>
|
||||
/// Updates a existing module definition
|
||||
/// </summary>
|
||||
/// <param name="moduleDefinition"></param>
|
||||
/// <returns></returns>
|
||||
Task UpdateModuleDefinitionAsync(ModuleDefinition moduleDefinition);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Installs all module definitions located in //TODO: 2dm where?
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task InstallModuleDefinitionsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a module definition
|
||||
/// </summary>
|
||||
/// <param name="moduleDefinitionId"></param>
|
||||
/// <param name="siteId"></param>
|
||||
/// <returns></returns>
|
||||
Task DeleteModuleDefinitionAsync(int moduleDefinitionId, int siteId);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new module definition
|
||||
/// </summary>
|
||||
/// <param name="moduleDefinition"></param>
|
||||
/// <returns></returns>
|
||||
Task<ModuleDefinition> CreateModuleDefinitionAsync(ModuleDefinition moduleDefinition);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of module definition templates
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<Template>> GetModuleDefinitionTemplatesAsync();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,62 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to retreive and store modules (<see cref="Module"/>)
|
||||
/// </summary>
|
||||
public interface IModuleService
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a list of modules for the given site
|
||||
/// </summary>
|
||||
/// <param name="siteId"></param>
|
||||
/// <returns></returns>
|
||||
Task<List<Module>> GetModulesAsync(int siteId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specific module
|
||||
/// </summary>
|
||||
/// <param name="moduleId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Module> GetModuleAsync(int moduleId);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new module
|
||||
/// </summary>
|
||||
/// <param name="module"></param>
|
||||
/// <returns></returns>
|
||||
Task<Module> AddModuleAsync(Module module);
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing module
|
||||
/// </summary>
|
||||
/// <param name="module"></param>
|
||||
/// <returns></returns>
|
||||
Task<Module> UpdateModuleAsync(Module module);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a module
|
||||
/// </summary>
|
||||
/// <param name="moduleId"></param>
|
||||
/// <returns></returns>
|
||||
Task DeleteModuleAsync(int moduleId);
|
||||
|
||||
/// <summary>
|
||||
/// Imports a module
|
||||
/// </summary>
|
||||
/// <param name="moduleId"></param>
|
||||
/// <param name="content">module in JSON format</param>
|
||||
/// <returns></returns>
|
||||
Task<bool> ImportModuleAsync(int moduleId, string content);
|
||||
|
||||
/// <summary>
|
||||
/// Exports a given module
|
||||
/// </summary>
|
||||
/// <param name="moduleId"></param>
|
||||
/// <returns>module in JSON</returns>
|
||||
Task<string> ExportModuleAsync(int moduleId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,49 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to store and retreive notifications (<see cref="Notification"/>)
|
||||
/// </summary>
|
||||
public interface INotificationService
|
||||
{
|
||||
/// <summary>
|
||||
/// Return a list of notifications
|
||||
/// </summary>
|
||||
/// <param name="siteId"></param>
|
||||
/// <param name="direction"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
Task<List<Notification>> GetNotificationsAsync(int siteId, string direction, int userId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specific notifications
|
||||
/// </summary>
|
||||
/// <param name="notificationId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Notification> GetNotificationAsync(int notificationId);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new notification
|
||||
/// </summary>
|
||||
/// <param name="notification"></param>
|
||||
/// <returns></returns>
|
||||
Task<Notification> AddNotificationAsync(Notification notification);
|
||||
|
||||
/// <summary>
|
||||
/// Updates a existing notification
|
||||
/// </summary>
|
||||
/// <param name="notification"></param>
|
||||
/// <returns></returns>
|
||||
Task<Notification> UpdateNotificationAsync(Notification notification);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a notification
|
||||
/// </summary>
|
||||
/// <param name="notificationId"></param>
|
||||
/// <returns></returns>
|
||||
Task DeleteNotificationAsync(int notificationId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,50 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Service to manage packages (<see cref="Package"/>)
|
||||
/// </summary>
|
||||
public interface IPackageService
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a list of packages matching the given parameters
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
Task<List<Package>> GetPackagesAsync(string type);
|
||||
Task<List<Package>> GetPackagesAsync(string type, string search);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of packages matching the given parameters
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="search"></param>
|
||||
/// <param name="price"></param>
|
||||
/// <param name="package"></param>
|
||||
/// <returns></returns>
|
||||
Task<List<Package>> GetPackagesAsync(string type, string search, string price, string package);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specific package
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="version"></param>
|
||||
/// <returns></returns>
|
||||
Task<Package> GetPackageAsync(string packageId, string version);
|
||||
|
||||
/// <summary>
|
||||
/// Downloads a specific package as .nupkg file
|
||||
/// </summary>
|
||||
/// <param name="packageId"></param>
|
||||
/// <param name="version"></param>
|
||||
/// <param name="folder"></param>
|
||||
/// <returns></returns>
|
||||
Task DownloadPackageAsync(string packageId, string version, string folder);
|
||||
|
||||
/// <summary>
|
||||
/// Installs all packages located in //TODO: 2dm where?
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task InstallPackagesAsync();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,56 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to store and retreive a <see cref="PageModule"/>
|
||||
/// </summary>
|
||||
public interface IPageModuleService
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specific page module
|
||||
/// </summary>
|
||||
/// <param name="pageModuleId"></param>
|
||||
/// <returns></returns>
|
||||
Task<PageModule> GetPageModuleAsync(int pageModuleId);
|
||||
|
||||
/// <summary>
|
||||
/// Return a specific page module
|
||||
/// </summary>
|
||||
/// <param name="pageId"></param>
|
||||
/// <param name="moduleId"></param>
|
||||
/// <returns></returns>
|
||||
Task<PageModule> GetPageModuleAsync(int pageId, int moduleId);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new page module
|
||||
/// </summary>
|
||||
/// <param name="pageModule"></param>
|
||||
/// <returns></returns>
|
||||
Task<PageModule> AddPageModuleAsync(PageModule pageModule);
|
||||
|
||||
/// <summary>
|
||||
/// Updates a existing page module
|
||||
/// </summary>
|
||||
/// <param name="pageModule"></param>
|
||||
/// <returns></returns>
|
||||
Task<PageModule> UpdatePageModuleAsync(PageModule pageModule);
|
||||
|
||||
/// <summary>
|
||||
/// Updates order of all page modules in the given pane
|
||||
/// </summary>
|
||||
/// <param name="pageId"></param>
|
||||
/// <param name="pane"></param>
|
||||
/// <returns></returns>
|
||||
Task UpdatePageModuleOrderAsync(int pageId, string pane);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a page module
|
||||
/// </summary>
|
||||
/// <param name="pageModuleId"></param>
|
||||
/// <returns></returns>
|
||||
Task DeletePageModuleAsync(int pageModuleId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,79 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Services to store and retrieve a <see cref="Page"/>
|
||||
/// </summary>
|
||||
public interface IPageService
|
||||
{
|
||||
/// <summary>
|
||||
/// Retuns a list of pages
|
||||
/// </summary>
|
||||
/// <param name="siteId"></param>
|
||||
/// <returns></returns>
|
||||
Task<List<Page>> GetPagesAsync(int siteId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specific page
|
||||
/// </summary>
|
||||
/// <param name="pageId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Page> GetPageAsync(int pageId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specific page personalized for the given user
|
||||
/// </summary>
|
||||
/// <param name="pageId"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Page> GetPageAsync(int pageId, int userId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specific page by its defined path
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="siteId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Page> GetPageAsync(string path, int siteId);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new page
|
||||
/// </summary>
|
||||
/// <param name="page"></param>
|
||||
/// <returns></returns>
|
||||
Task<Page> AddPageAsync(Page page);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new page
|
||||
/// </summary>
|
||||
/// <param name="page"></param>
|
||||
/// <returns></returns>
|
||||
Task<Page> AddPageAsync(int pageId, int userId);
|
||||
|
||||
/// <summary>
|
||||
/// Updates a existing page
|
||||
/// </summary>
|
||||
/// <param name="page"></param>
|
||||
/// <returns></returns>
|
||||
Task<Page> UpdatePageAsync(Page page);
|
||||
|
||||
/// <summary>
|
||||
/// Updates order of all page modules in the given parent
|
||||
/// </summary>
|
||||
/// <param name="siteId"></param>
|
||||
/// <param name="pageId"></param>
|
||||
/// <param name="parentId"></param>
|
||||
/// <returns></returns>
|
||||
Task UpdatePageOrderAsync(int siteId, int pageId, int? parentId);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a page
|
||||
/// </summary>
|
||||
/// <param name="pageId"></param>
|
||||
/// <returns></returns>
|
||||
Task DeletePageAsync(int pageId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,48 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to store and retreive <see cref="Profile"/> entries
|
||||
/// </summary>
|
||||
public interface IProfileService
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of profile entries
|
||||
/// </summary>
|
||||
/// <param name="siteId"></param>
|
||||
/// <returns></returns>
|
||||
Task<List<Profile>> GetProfilesAsync(int siteId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specific profile entry
|
||||
/// </summary>
|
||||
/// <param name="profileId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Profile> GetProfileAsync(int profileId);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new profile entry
|
||||
/// </summary>
|
||||
/// <param name="profile"></param>
|
||||
/// <returns></returns>
|
||||
Task<Profile> AddProfileAsync(Profile profile);
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing profile entry
|
||||
/// </summary>
|
||||
/// <param name="profile"></param>
|
||||
/// <returns></returns>
|
||||
Task<Profile> UpdateProfileAsync(Profile profile);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a profile entry
|
||||
/// </summary>
|
||||
/// <param name="profileId"></param>
|
||||
/// <returns></returns>
|
||||
Task DeleteProfileAsync(int profileId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,55 +1,184 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to manage <see cref="Setting"/>s
|
||||
/// </summary>
|
||||
public interface ISettingService
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a key-value dictionary of all tenant settings
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<Dictionary<string, string>> GetTenantSettingsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Updates a tenant setting
|
||||
/// </summary>
|
||||
/// <param name="tenantSettings"></param>
|
||||
/// <returns></returns>
|
||||
Task UpdateTenantSettingsAsync(Dictionary<string, string> tenantSettings);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a key-value dictionary of all site settings for the given site
|
||||
/// </summary>
|
||||
/// <param name="siteId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Dictionary<string, string>> GetSiteSettingsAsync(int siteId);
|
||||
|
||||
/// <summary>
|
||||
/// Updates a site setting
|
||||
/// </summary>
|
||||
/// <param name="siteSettings"></param>
|
||||
/// <param name="siteId"></param>
|
||||
/// <returns></returns>
|
||||
Task UpdateSiteSettingsAsync(Dictionary<string, string> siteSettings, int siteId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a key-value dictionary of all page settings for the given page
|
||||
/// </summary>
|
||||
/// <param name="pageId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Dictionary<string, string>> GetPageSettingsAsync(int pageId);
|
||||
|
||||
/// <summary>
|
||||
/// Updates a page setting
|
||||
/// </summary>
|
||||
/// <param name="pageSettings"></param>
|
||||
/// <param name="pageId"></param>
|
||||
/// <returns></returns>
|
||||
Task UpdatePageSettingsAsync(Dictionary<string, string> pageSettings, int pageId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a key-value dictionary of all page module settings for the given page module
|
||||
/// </summary>
|
||||
/// <param name="pageId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Dictionary<string, string>> GetPageModuleSettingsAsync(int pageModuleId);
|
||||
|
||||
/// <summary>
|
||||
/// Updates a page module setting
|
||||
/// </summary>
|
||||
/// <param name="pageModuleSettings"></param>
|
||||
/// <param name="pageModuleId"></param>
|
||||
/// <returns></returns>
|
||||
Task UpdatePageModuleSettingsAsync(Dictionary<string, string> pageModuleSettings, int pageModuleId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a key-value dictionary of all module settings for the given module
|
||||
/// </summary>
|
||||
/// <param name="pageId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Dictionary<string, string>> GetModuleSettingsAsync(int moduleId);
|
||||
|
||||
/// <summary>
|
||||
/// Updates a module setting
|
||||
/// </summary>
|
||||
/// <param name="moduleSettings"></param>
|
||||
/// <param name="moduleId"></param>
|
||||
/// <returns></returns>
|
||||
Task UpdateModuleSettingsAsync(Dictionary<string, string> moduleSettings, int moduleId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a key-value dictionary of all user settings for the given user
|
||||
/// </summary>
|
||||
/// <param name="pageId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Dictionary<string, string>> GetUserSettingsAsync(int userId);
|
||||
|
||||
/// <summary>
|
||||
/// Updates a user setting
|
||||
/// </summary>
|
||||
/// <param name="userSettings"></param>
|
||||
/// <param name="userId"></param>
|
||||
/// <returns></returns>
|
||||
Task UpdateUserSettingsAsync(Dictionary<string, string> userSettings, int userId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a key-value dictionary of all folder settings for the given folder
|
||||
/// </summary>
|
||||
/// <param name="pageId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Dictionary<string, string>> GetFolderSettingsAsync(int folderId);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Updates a folder setting
|
||||
/// </summary>
|
||||
/// <param name="folderSettings"></param>
|
||||
/// <param name="folderId"></param>
|
||||
/// <returns></returns>
|
||||
Task UpdateFolderSettingsAsync(Dictionary<string, string> folderSettings, int folderId);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a key-value dictionary of all settings for the given entityName
|
||||
/// </summary>
|
||||
/// <param name="pageId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Dictionary<string, string>> GetSettingsAsync(string entityName, int entityId);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Updates settings for a given entityName and Id
|
||||
/// </summary>
|
||||
/// <param name="settings"></param>
|
||||
/// <param name="entityName"></param>
|
||||
/// <param name="entityId"></param>
|
||||
/// <returns></returns>
|
||||
Task UpdateSettingsAsync(Dictionary<string, string> settings, string entityName, int entityId);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specific setting
|
||||
/// </summary>
|
||||
/// <param name="settingId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Setting> GetSettingAsync(int settingId);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new setting
|
||||
/// </summary>
|
||||
/// <param name="setting"></param>
|
||||
/// <returns></returns>
|
||||
Task<Setting> AddSettingAsync(Setting setting);
|
||||
|
||||
/// <summary>
|
||||
/// Updates a existing setting
|
||||
/// </summary>
|
||||
/// <param name="setting"></param>
|
||||
/// <returns></returns>
|
||||
Task<Setting> UpdateSettingAsync(Setting setting);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a setting
|
||||
/// </summary>
|
||||
/// <param name="settingId"></param>
|
||||
/// <returns></returns>
|
||||
Task DeleteSettingAsync(int settingId);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the given settingName (key) from the given key-value dictionary
|
||||
/// </summary>
|
||||
/// <param name="settings"></param>
|
||||
/// <param name="settingName"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
string GetSetting(Dictionary<string, string> settings, string settingName, string defaultValue);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of the given settingName (key) in the given key-value dictionary
|
||||
/// </summary>
|
||||
/// <param name="settings"></param>
|
||||
/// <param name="settingName"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
Dictionary<string, string> SetSetting(Dictionary<string, string> settings, string settingName, string settingValue);
|
||||
}
|
||||
|
||||
Dictionary<string, string> SetSetting(Dictionary<string, string> settings, string settingName, string settingValue, bool isPublic);
|
||||
|
||||
Dictionary<string, string> MergeSettings(Dictionary<string, string> settings1, Dictionary<string, string> settings2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using Oqtane.Documentation;
|
||||
using Oqtane.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
@ -5,18 +6,47 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to store and retreive <see cref="Site"/> entries
|
||||
/// </summary>
|
||||
public interface ISiteService
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of sites
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<Site>> GetSitesAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a specific site
|
||||
/// </summary>
|
||||
/// <param name="siteId"></param>
|
||||
/// <returns></returns>
|
||||
Task<Site> GetSiteAsync(int siteId);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new site
|
||||
/// </summary>
|
||||
/// <param name="site"></param>
|
||||
/// <returns></returns>
|
||||
Task<Site> AddSiteAsync(Site site);
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing site
|
||||
/// </summary>
|
||||
/// <param name="site"></param>
|
||||
/// <returns></returns>
|
||||
Task<Site> UpdateSiteAsync(Site site);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a site
|
||||
/// </summary>
|
||||
/// <param name="siteId"></param>
|
||||
/// <returns></returns>
|
||||
Task DeleteSiteAsync(int siteId);
|
||||
|
||||
[PrivateApi]
|
||||
[Obsolete("This method is deprecated.", false)]
|
||||
void SetAlias(Alias alias);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to retreive <see cref="SiteTemplate"/> entries
|
||||
/// </summary>
|
||||
public interface ISiteTemplateService
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a list of site templates
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<SiteTemplate>> GetSiteTemplatesAsync();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
using Oqtane.Models;
|
||||
using Oqtane.Models;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to execute a <see cref="SqlQuery"/> against the backend database
|
||||
/// </summary>
|
||||
public interface ISqlService
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes a sql query and returns its result
|
||||
/// </summary>
|
||||
/// <param name="sqlquery"></param>
|
||||
/// <returns></returns>
|
||||
Task<SqlQuery> ExecuteQueryAsync(SqlQuery sqlquery);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,22 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to retrieve and update system information.
|
||||
/// </summary>
|
||||
public interface ISystemService
|
||||
{
|
||||
/// <summary>
|
||||
/// returns a key-value directory with the current system information (os-version, clr-version, etc.)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<Dictionary<string, string>> GetSystemInfoAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Updates system information
|
||||
/// </summary>
|
||||
/// <param name="settings"></param>
|
||||
/// <returns></returns>
|
||||
Task UpdateSystemInfoAsync(Dictionary<string, string> settings);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,15 +4,65 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Oqtane.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service to manage <see cref="Theme"/> entries
|
||||
/// </summary>
|
||||
public interface IThemeService
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of available themes
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<Theme>> GetThemesAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of <see cref="ThemeControl"/>s from the given themes
|
||||
/// </summary>
|
||||
/// <param name="themes"></param>
|
||||
/// <returns></returns>
|
||||
List<ThemeControl> GetThemeControls(List<Theme> themes);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of layouts (<see cref="ThemeControl"/>) from the given themes with a matching theme name
|
||||
/// </summary>
|
||||
/// <param name="themes"></param>
|
||||
/// <param name="themeName"></param>
|
||||
/// <returns></returns>
|
||||
List<ThemeControl> GetLayoutControls(List<Theme> themes, string themeName);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of containers (<see cref="ThemeControl"/>) from the given themes with a matching theme name
|
||||
/// </summary>
|
||||
/// <param name="themes"></param>
|
||||
/// <param name="themeName"></param>
|
||||
/// <returns></returns>
|
||||
List<ThemeControl> GetContainerControls(List<Theme> themes, string themeName);
|
||||
|
||||
/// <summary>
|
||||
/// Installs all themes located in //TODO: 2dm where?
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task InstallThemesAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a theme
|
||||
/// </summary>
|
||||
/// <param name="themeName"></param>
|
||||
/// <returns></returns>
|
||||
Task DeleteThemeAsync(string themeName);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new theme
|
||||
/// </summary>
|
||||
/// <param name="theme"></param>
|
||||
/// <returns></returns>
|
||||
Task<Theme> CreateThemeAsync(Theme theme);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of theme templates (<see cref="Template"/>)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<List<Template>> GetThemeTemplatesAsync();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,12 +22,17 @@ namespace Oqtane.Services
|
|||
|
||||
public async Task<List<Package>> GetPackagesAsync(string type)
|
||||
{
|
||||
return await GetPackagesAsync(type, "");
|
||||
return await GetPackagesAsync(type, "", "", "");
|
||||
}
|
||||
|
||||
public async Task<List<Package>> GetPackagesAsync(string type, string search)
|
||||
public async Task<List<Package>> GetPackagesAsync(string type, string search, string price, string package)
|
||||
{
|
||||
return await GetJsonAsync<List<Package>>($"{Apiurl}?type={type}&search={WebUtility.UrlEncode(search)}");
|
||||
return await GetJsonAsync<List<Package>>($"{Apiurl}?type={type}&search={WebUtility.UrlEncode(search)}&price={price}&package={package}");
|
||||
}
|
||||
|
||||
public async Task<Package> GetPackageAsync(string packageId, string version)
|
||||
{
|
||||
return await PostJsonAsync<Package>($"{Apiurl}?packageid={packageId}&version={version}", null);
|
||||
}
|
||||
|
||||
public async Task DownloadPackageAsync(string packageId, string version, string folder)
|
||||
|
|
|
@ -47,6 +47,7 @@ namespace Oqtane.Services
|
|||
{
|
||||
return await PutJsonAsync<Role>($"{Apiurl}/{role.RoleId}", role);
|
||||
}
|
||||
|
||||
public async Task DeleteRoleAsync(int roleId)
|
||||
{
|
||||
await DeleteAsync($"{Apiurl}/{roleId}");
|
||||
|
|
|
@ -109,21 +109,34 @@ namespace Oqtane.Services
|
|||
|
||||
foreach (KeyValuePair<string, string> kvp in settings)
|
||||
{
|
||||
Setting setting = settingsList.FirstOrDefault(item => item.SettingName.Equals(kvp.Key,StringComparison.OrdinalIgnoreCase));
|
||||
string value = kvp.Value;
|
||||
bool ispublic = false;
|
||||
if (value.StartsWith("[Public]"))
|
||||
{
|
||||
if (entityName == EntityNames.Site)
|
||||
{
|
||||
ispublic = true;
|
||||
}
|
||||
value = value.Substring(8); // remove [Public]
|
||||
}
|
||||
|
||||
Setting setting = settingsList.FirstOrDefault(item => item.SettingName.Equals(kvp.Key, StringComparison.OrdinalIgnoreCase));
|
||||
if (setting == null)
|
||||
{
|
||||
setting = new Setting();
|
||||
setting.EntityName = entityName;
|
||||
setting.EntityId = entityId;
|
||||
setting.SettingName = kvp.Key;
|
||||
setting.SettingValue = kvp.Value;
|
||||
setting.SettingValue = value;
|
||||
setting.IsPublic = ispublic;
|
||||
setting = await AddSettingAsync(setting);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (setting.SettingValue != kvp.Value)
|
||||
{
|
||||
setting.SettingValue = kvp.Value;
|
||||
setting.SettingValue = value;
|
||||
setting.IsPublic = ispublic;
|
||||
setting = await UpdateSettingAsync(setting);
|
||||
}
|
||||
}
|
||||
|
@ -163,13 +176,19 @@ namespace Oqtane.Services
|
|||
}
|
||||
|
||||
public Dictionary<string, string> SetSetting(Dictionary<string, string> settings, string settingName, string settingValue)
|
||||
{
|
||||
return SetSetting(settings, settingName, settingValue, false);
|
||||
}
|
||||
|
||||
public Dictionary<string, string> SetSetting(Dictionary<string, string> settings, string settingName, string settingValue, bool isPublic)
|
||||
{
|
||||
if (settings == null)
|
||||
{
|
||||
settings = new Dictionary<string, string>();
|
||||
}
|
||||
settingValue = (isPublic) ? "[Public]" + settingValue : settingValue;
|
||||
if (settings.ContainsKey(settingName))
|
||||
{
|
||||
{
|
||||
settings[settingName] = settingValue;
|
||||
}
|
||||
else
|
||||
|
@ -178,5 +197,28 @@ namespace Oqtane.Services
|
|||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> MergeSettings(Dictionary<string, string> settings1, Dictionary<string, string> settings2)
|
||||
{
|
||||
if (settings1 == null)
|
||||
{
|
||||
settings1 = new Dictionary<string, string>();
|
||||
}
|
||||
if (settings2 != null)
|
||||
{
|
||||
foreach (var setting in settings2)
|
||||
{
|
||||
if (settings1.ContainsKey(setting.Key))
|
||||
{
|
||||
settings1[setting.Key] = setting.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
settings1.Add(setting.Key, setting.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return settings1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ namespace Oqtane.Themes.Controls
|
|||
{
|
||||
PageModule pagemodule = await PageModuleService.GetPageModuleAsync(ModuleState.PageModuleId);
|
||||
|
||||
string url = NavigateUrl();
|
||||
string url = NavigateUrl(true);
|
||||
|
||||
if (action.Action != null)
|
||||
{
|
||||
|
@ -115,7 +115,7 @@ namespace Oqtane.Themes.Controls
|
|||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, oldPane);
|
||||
return NavigateUrl(url, true);
|
||||
return url;
|
||||
}
|
||||
|
||||
private async Task<string> DeleteModule(string url, PageModule pagemodule)
|
||||
|
@ -123,7 +123,7 @@ namespace Oqtane.Themes.Controls
|
|||
pagemodule.IsDeleted = true;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
return NavigateUrl(url, true);
|
||||
return url;
|
||||
}
|
||||
|
||||
private async Task<string> Settings(string url, PageModule pagemodule)
|
||||
|
@ -133,7 +133,7 @@ namespace Oqtane.Themes.Controls
|
|||
return url;
|
||||
}
|
||||
|
||||
private async Task<string> Publish(string s, PageModule pagemodule)
|
||||
private async Task<string> Publish(string url, PageModule pagemodule)
|
||||
{
|
||||
var permissions = UserSecurity.GetPermissionStrings(pagemodule.Module.Permissions);
|
||||
foreach (var permissionstring in permissions)
|
||||
|
@ -148,10 +148,10 @@ namespace Oqtane.Themes.Controls
|
|||
}
|
||||
pagemodule.Module.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
||||
await ModuleService.UpdateModuleAsync(pagemodule.Module);
|
||||
return NavigateUrl(s, true);
|
||||
return url;
|
||||
}
|
||||
|
||||
private async Task<string> Unpublish(string s, PageModule pagemodule)
|
||||
private async Task<string> Unpublish(string url, PageModule pagemodule)
|
||||
{
|
||||
var permissions = UserSecurity.GetPermissionStrings(pagemodule.Module.Permissions);
|
||||
foreach (var permissionstring in permissions)
|
||||
|
@ -166,39 +166,39 @@ namespace Oqtane.Themes.Controls
|
|||
}
|
||||
pagemodule.Module.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
||||
await ModuleService.UpdateModuleAsync(pagemodule.Module);
|
||||
return NavigateUrl(s, true);
|
||||
return url;
|
||||
}
|
||||
|
||||
private async Task<string> MoveTop(string s, PageModule pagemodule)
|
||||
private async Task<string> MoveTop(string url, PageModule pagemodule)
|
||||
{
|
||||
pagemodule.Order = 0;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
return NavigateUrl(s, true);
|
||||
return url;
|
||||
}
|
||||
|
||||
private async Task<string> MoveBottom(string s, PageModule pagemodule)
|
||||
private async Task<string> MoveBottom(string url, PageModule pagemodule)
|
||||
{
|
||||
pagemodule.Order = int.MaxValue;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
return NavigateUrl(s, true);
|
||||
return url;
|
||||
}
|
||||
|
||||
private async Task<string> MoveUp(string s, PageModule pagemodule)
|
||||
private async Task<string> MoveUp(string url, PageModule pagemodule)
|
||||
{
|
||||
pagemodule.Order -= 3;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
return NavigateUrl(s, true);
|
||||
return url;
|
||||
}
|
||||
|
||||
private async Task<string> MoveDown(string s, PageModule pagemodule)
|
||||
private async Task<string> MoveDown(string url, PageModule pagemodule)
|
||||
{
|
||||
pagemodule.Order += 3;
|
||||
await PageModuleService.UpdatePageModuleAsync(pagemodule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pagemodule.PageId, pagemodule.Pane);
|
||||
return NavigateUrl(s, true);
|
||||
return url;
|
||||
}
|
||||
|
||||
public class ActionViewModel
|
||||
|
|
|
@ -14,182 +14,177 @@
|
|||
|
||||
@if (_moduleDefinitions != null && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
||||
{
|
||||
<div class="app-controlpanel" style="@_display">
|
||||
<div class="@CardClass">
|
||||
<div class="@HeaderClass d-flex">
|
||||
<span class="font-weight-bold">@Localizer["ControlPanel"]</span>
|
||||
<div class="ms-auto">
|
||||
<button type="button" class="btn-close" aria-label="Close" @onclick="HideControlPanel"></button>
|
||||
<div class="@ContainerClass" tabindex="-1" data-bs-scroll="true" data-bs-backdrop="true" id="offcanvasControlPanel" aria-labelledby="offcanvasScrollingLabel">
|
||||
<div class="@HeaderClass">
|
||||
<h5 id="offcanvasScrollingLabel">@Localizer["ControlPanel"]</h5>
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="@BodyClass">
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||
{
|
||||
<div class="row d-flex">
|
||||
<div class="col">
|
||||
<button data-bs-dismiss="offcanvas" type="button" class="btn btn-primary col-12" @onclick=@(async () => Navigate("Admin"))>@Localizer["AdminDash"]</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="@BodyClass">
|
||||
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||
{
|
||||
<div class="row d-flex">
|
||||
<div class="col">
|
||||
<button type="button" class="btn btn-primary col-12" @onclick=@(async () => Navigate("Admin"))>@Localizer["AdminDash"]</button>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="app-rule" />
|
||||
|
||||
<hr class="app-rule" />
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<label class="control-label">@Localizer["Page.Manage"] </label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row d-flex">
|
||||
<div class="col d-flex justify-content-between">
|
||||
<button type="button" class="btn btn-secondary col-3" data-bs-dismiss="offcanvas" @onclick=@(async () => Navigate("Add"))>@SharedLocalizer["Add"]</button>
|
||||
<button type="button" class="btn btn-secondary col-3" data-bs-dismiss="offcanvas" @onclick=@(async () => Navigate("Edit"))>@SharedLocalizer["Edit"]</button>
|
||||
<button type="button" class="btn btn-danger col-3" @onclick="ConfirmDelete">@SharedLocalizer["Delete"]</button>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="row d-flex">
|
||||
<div class="col">
|
||||
@if (UserSecurity.GetPermissionStrings(PageState.Page.Permissions).FirstOrDefault(item => item.PermissionName == PermissionNames.View).Permissions.Split(';').Contains(RoleNames.Everyone))
|
||||
{
|
||||
<button type="button" class="btn btn-secondary col-12" @onclick=@(async () => Publish("unpublish"))>@Localizer["Page.Unpublish"]</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn btn-secondary col-12" @onclick=@(async () => Publish("publish"))>@Localizer["Page.Publish"]</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<label class="control-label">@Localizer["Page.Manage"] </label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row d-flex">
|
||||
<div class="col d-flex justify-content-between">
|
||||
<button type="button" class="btn btn-secondary col-3" @onclick=@(async () => Navigate("Add"))>@SharedLocalizer["Add"]</button>
|
||||
<button type="button" class="btn btn-secondary col-3" @onclick=@(async () => Navigate("Edit"))>@SharedLocalizer["Edit"]</button>
|
||||
<button type="button" class="btn btn-danger col-3" @onclick="ConfirmDelete">@SharedLocalizer["Delete"]</button>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="row d-flex">
|
||||
<div class="col">
|
||||
@if (UserSecurity.GetPermissionStrings(PageState.Page.Permissions).FirstOrDefault(item => item.PermissionName == PermissionNames.View).Permissions.Split(';').Contains(RoleNames.Everyone))
|
||||
{
|
||||
<button type="button" class="btn btn-secondary col-12" @onclick=@(async () => Publish("unpublish"))>@Localizer["Page.Unpublish"]</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="btn btn-secondary col-12" @onclick=@(async () => Publish("publish"))>@Localizer["Page.Publish"]</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (_deleteConfirmation)
|
||||
{
|
||||
<div class="app-admin-modal">
|
||||
<div class="modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@Localizer["Page.Delete"]</h5>
|
||||
<button type="button" class="btn-close" aria-label="Close" @onclick="ConfirmDelete"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Are You Sure You Want To Delete This Page?</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger" @onclick="DeletePage">@SharedLocalizer["Delete"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="ConfirmDelete">@SharedLocalizer["Cancel"]</button>
|
||||
</div>
|
||||
@if (_deleteConfirmation)
|
||||
{
|
||||
<div class="app-admin-modal">
|
||||
<div class="modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@Localizer["Page.Delete"]</h5>
|
||||
<button type="button" class="btn-close" aria-label="Close" @onclick="ConfirmDelete"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Are You Sure You Want To Delete This Page?</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger" @onclick="DeletePage">@SharedLocalizer["Delete"]</button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="ConfirmDelete">@SharedLocalizer["Cancel"]</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<hr class="app-rule" />
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<label for="Module" class="control-label">@Localizer["Module.Manage"] </label>
|
||||
<select class="form-select" @bind="@ModuleType">
|
||||
<option value="new">@Localizer["Module.AddNew"]</option>
|
||||
<option value="existing">@Localizer["Module.AddExisting"]</option>
|
||||
</select>
|
||||
@if (ModuleType == "new")
|
||||
</div>
|
||||
}
|
||||
<hr class="app-rule" />
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<label for="Module" class="control-label">@Localizer["Module.Manage"] </label>
|
||||
<select class="form-select" @bind="@ModuleType">
|
||||
<option value="new">@Localizer["Module.AddNew"]</option>
|
||||
<option value="existing">@Localizer["Module.AddExisting"]</option>
|
||||
</select>
|
||||
@if (ModuleType == "new")
|
||||
{
|
||||
@if (_moduleDefinitions != null)
|
||||
{
|
||||
@if (_moduleDefinitions != null)
|
||||
{
|
||||
<select class="form-select" @onchange="(e => CategoryChanged(e))">
|
||||
@foreach (var category in _categories)
|
||||
<select class="form-select" @onchange="(e => CategoryChanged(e))">
|
||||
@foreach (var category in _categories)
|
||||
{
|
||||
if (category == Category)
|
||||
{
|
||||
if (category == Category)
|
||||
{
|
||||
<option value="@category" selected>@category @Localizer["Modules"]</option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="@category">@category @Localizer["Modules"]</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
<select class="form-select" @onchange="(e => ModuleChanged(e))">
|
||||
@if (ModuleDefinitionName == "-")
|
||||
{
|
||||
<option value="-" selected><@Localizer["Module.Select"]></option>
|
||||
<option value="@category" selected>@category @Localizer["Modules"]</option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="-"><@Localizer["Module.Select"]></option>
|
||||
<option value="@category">@category @Localizer["Modules"]</option>
|
||||
}
|
||||
@foreach (var moduledefinition in _moduleDefinitions)
|
||||
}
|
||||
</select>
|
||||
<select class="form-select" @onchange="(e => ModuleChanged(e))">
|
||||
@if (ModuleDefinitionName == "-")
|
||||
{
|
||||
<option value="-" selected><@Localizer["Module.Select"]></option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="-"><@Localizer["Module.Select"]></option>
|
||||
}
|
||||
@foreach (var moduledefinition in _moduleDefinitions)
|
||||
{
|
||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Utilize, moduledefinition.Permissions))
|
||||
{
|
||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Utilize, moduledefinition.Permissions))
|
||||
if (moduledefinition.Runtimes == "" || moduledefinition.Runtimes.Contains(PageState.Runtime.ToString()))
|
||||
{
|
||||
if (moduledefinition.Runtimes == "" || moduledefinition.Runtimes.Contains(PageState.Runtime.ToString()))
|
||||
{
|
||||
<option value="@moduledefinition.ModuleDefinitionName">@moduledefinition.Name</option>
|
||||
}
|
||||
<option value="@moduledefinition.ModuleDefinitionName">@moduledefinition.Name</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
@((MarkupString) Description)
|
||||
}
|
||||
}
|
||||
</select>
|
||||
@((MarkupString) Description)
|
||||
}
|
||||
else
|
||||
{
|
||||
<select class="form-select" @onchange="(e => PageChanged(e))">
|
||||
<option value="-"><@Localizer["Page.Select"]></option>
|
||||
@foreach (Page p in _pages)
|
||||
{
|
||||
<option value="@p.PageId">@p.Name</option>
|
||||
}
|
||||
</select>
|
||||
<select class="form-select" @bind="@ModuleId">
|
||||
<option value="-"><@Localizer["Module.Select"]></option>
|
||||
@foreach (Module module in _modules)
|
||||
{
|
||||
<option value="@module.ModuleId">@module.Title</option>
|
||||
}
|
||||
</select>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<label for="Title" class="control-label">@Localizer["Title"] </label>
|
||||
<input type="text" name="Title" class="form-control" @bind="@Title" />
|
||||
</div>
|
||||
</div>
|
||||
@if (_pane.Length > 1)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<label for="Pane" class="control-label">@Localizer["Pane"] </label>
|
||||
<select class="form-select" @bind="@Pane">
|
||||
@foreach (string pane in PageState.Page.Panes)
|
||||
{
|
||||
<option value="@pane">@pane Pane</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<label for="Container" class="control-label">@Localizer["Container"] </label>
|
||||
<select class="form-select" @bind="@ContainerType">
|
||||
@foreach (var container in _containers)
|
||||
}
|
||||
else
|
||||
{
|
||||
<select class="form-select" @onchange="(e => PageChanged(e))">
|
||||
<option value="-"><@Localizer["Page.Select"]></option>
|
||||
@foreach (Page p in _pages)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
<option value="@p.PageId">@p.Name</option>
|
||||
}
|
||||
</select>
|
||||
<select class="form-select" @bind="@ModuleId">
|
||||
<option value="-"><@Localizer["Module.Select"]></option>
|
||||
@foreach (Module module in _modules)
|
||||
{
|
||||
<option value="@module.ModuleId">@module.Title</option>
|
||||
}
|
||||
</select>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<label for="Title" class="control-label">@Localizer["Title"] </label>
|
||||
<input type="text" name="Title" class="form-control" @bind="@Title" />
|
||||
</div>
|
||||
</div>
|
||||
@if (_pane.Length > 1)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<label for="Pane" class="control-label">@Localizer["Pane"] </label>
|
||||
<select class="form-select" @bind="@Pane">
|
||||
@foreach (string pane in PageState.Page.Panes)
|
||||
{
|
||||
<option value="@pane">@pane Pane</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<button type="button" class="btn btn-primary col-12" @onclick="@AddModule">@Localizer["Page.Module.Add"]</button>
|
||||
@((MarkupString) Message)
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||
{
|
||||
<hr class="app-rule" />
|
||||
<NavLink class="btn btn-info col-12" href="@NavigateUrl("admin/update")">@Localizer["System.Update"]</NavLink>
|
||||
}
|
||||
}
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<label for="Container" class="control-label">@Localizer["Container"] </label>
|
||||
<select class="form-select" @bind="@ContainerType">
|
||||
@foreach (var container in _containers)
|
||||
{
|
||||
<option value="@container.TypeName">@container.Name</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<button type="button" class="btn btn-primary col-12" @onclick="@AddModule">@Localizer["Page.Module.Add"]</button>
|
||||
@((MarkupString) Message)
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||
{
|
||||
<hr class="app-rule" />
|
||||
<NavLink class="btn btn-info col-12" data-bs-dismiss="offcanvas" href="@NavigateUrl("admin/update")">@Localizer["System.Update"]</NavLink>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
@ -217,7 +212,8 @@
|
|||
|
||||
@if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
||||
{
|
||||
<button type="button" class="btn @ButtonClass" @onclick="ShowControlPanel">
|
||||
|
||||
<button class="btn @ButtonClass" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasControlPanel" aria-controls="offcanvasControlPanel">
|
||||
<span class="oi oi-cog"></span>
|
||||
</button>
|
||||
}
|
||||
|
@ -231,7 +227,6 @@
|
|||
private List<Page> _pages = new List<Page>();
|
||||
private List<Module> _modules = new List<Module>();
|
||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||
private string _display = "display: none;";
|
||||
private string _category = "Common";
|
||||
|
||||
protected string PageId { get; private set; } = "-";
|
||||
|
@ -280,13 +275,13 @@
|
|||
public string ButtonClass { get; set; } = "btn-outline-secondary";
|
||||
|
||||
[Parameter]
|
||||
public string CardClass { get; set; } = "card border-secondary mb-3";
|
||||
public string ContainerClass { get; set; } = "offcanvas offcanvas-end";
|
||||
|
||||
[Parameter]
|
||||
public string HeaderClass { get; set; } = "card-header";
|
||||
public string HeaderClass { get; set; } = "offcanvas-header";
|
||||
|
||||
[Parameter]
|
||||
public string BodyClass { get; set; } = "card-body";
|
||||
public string BodyClass { get; set; } = "offcanvas-body overflow-auto";
|
||||
|
||||
[Parameter]
|
||||
public bool ShowLanguageSwitcher { get; set; } = true;
|
||||
|
@ -405,17 +400,17 @@
|
|||
await PageModuleService.AddPageModuleAsync(pageModule);
|
||||
await PageModuleService.UpdatePageModuleOrderAsync(pageModule.PageId, pageModule.Pane);
|
||||
|
||||
Message = $"<br /><div class=\"alert alert-success\" role=\"alert\">{Localizer["Success.Page.ModuleAdd"]}</div>";
|
||||
Message = $"<div class=\"alert alert-success mt-2 text-center\" role=\"alert\">{Localizer["Success.Page.ModuleAdd"]}</div>";
|
||||
NavigationManager.NavigateTo(NavigateUrl());
|
||||
}
|
||||
else
|
||||
{
|
||||
Message = $"<br /><div class=\"alert alert-warning\" role=\"alert\">{Localizer["Message.Require.ModuleSelect"]}</div>";
|
||||
Message = $"<div class=\"alert alert-warning mt-2 text-center\" role=\"alert\">{Localizer["Message.Require.ModuleSelect"]}</div>";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Message = $"<br /><div class=\"alert alert-error\" role=\"alert\">{Localizer["Error.Authorize.No"]}</div>";
|
||||
Message = $"<div class=\"alert alert-error mt-2 text-center\" role=\"alert\">{Localizer["Error.Authorize.No"]}</div>";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -445,23 +440,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
private void ShowControlPanel()
|
||||
{
|
||||
Message = "";
|
||||
_display = "width: 25%; min-width: 375px;";
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void HideControlPanel()
|
||||
{
|
||||
Message = "";
|
||||
_display = "width: 0%;";
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void Navigate(string location)
|
||||
{
|
||||
HideControlPanel();
|
||||
//HideControlPanel();
|
||||
Module module;
|
||||
switch (location)
|
||||
{
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user