Compare commits
191 Commits
Author | SHA1 | Date | |
---|---|---|---|
c8f56e1659 | |||
56631a3e6b | |||
84ee9de18c | |||
0aeb4e9173 | |||
bb65e5c373 | |||
45e2027c56 | |||
6dc5ef44b7 | |||
e88d3cca07 | |||
a4b7381141 | |||
2ea054dc72 | |||
13ec726ab2 | |||
2e32b65421 | |||
f48ca53cdb | |||
c5b632cb24 | |||
422e9ae99e | |||
68ada8fbe4 | |||
e40bf08691 | |||
a04c7222b2 | |||
172faec5a0 | |||
e01c3e7e4a | |||
7a3d5d0429 | |||
ddf1caaaaa | |||
021293cbb0 | |||
1438e61f1b | |||
182f4dbae7 | |||
26ec3fc7cf | |||
225c758795 | |||
5e653250f3 | |||
b7a3713946 | |||
44242fdb4a | |||
45515b2c06 | |||
2d95fe294c | |||
72cc44641b | |||
9ac3fa5269 | |||
d1ea141165 | |||
dca21fbb8c | |||
06812d5df8 | |||
564410d3cd | |||
4b1cec979a | |||
a5f1bc3895 | |||
b097d031b5 | |||
45df729711 | |||
802ee8a1ff | |||
e312970212 | |||
c0f4069a9b | |||
654352827e | |||
7dd210976d | |||
5302be8bc1 | |||
9ed7181e28 | |||
23ae4b01cb | |||
59764d3378 | |||
b8e2c729c1 | |||
530d80a011 | |||
2d306e8fda | |||
b3d9a70fd1 | |||
b880207f61 | |||
ee76d02999 | |||
804c33a375 | |||
de784714d9 | |||
2404e26b61 | |||
b191fdda2c | |||
e8adfd45d2 | |||
7158595801 | |||
ba97f63338 | |||
62eca2aedc | |||
b15f6b1fa7 | |||
5b22de589c | |||
d1f50f12af | |||
d40c1d9b31 | |||
b69041d4af | |||
64c5d9a09f | |||
dd170bb41a | |||
1e6e4033f8 | |||
01fabc8d9e | |||
2ca2539b53 | |||
51e2e2966f | |||
55d02d2db5 | |||
282a0b0c44 | |||
8432779b23 | |||
13b9982461 | |||
d76b8cebdc | |||
80315ae6d4 | |||
95e7344286 | |||
28f73727b5 | |||
68f5bf5759 | |||
075748d697 | |||
e8d86f94f2 | |||
d6bb802892 | |||
52680e9002 | |||
d6385d82ae | |||
d058de067c | |||
32d6d143dd | |||
b49432802b | |||
99d4d75d8e | |||
1f584d57ac | |||
2c1543aa82 | |||
4390cbbfae | |||
bbf9e5717e | |||
c7edc28bd9 | |||
6e0de6f7bf | |||
3659422165 | |||
1af30da44e | |||
56c082cb26 | |||
e8eca582de | |||
4084b352de | |||
633e4acf0e | |||
468df15d80 | |||
f4537b4fcb | |||
8bca345b45 | |||
ee80712c77 | |||
3cf7153f44 | |||
8e2fc75e48 | |||
4aa51c8583 | |||
3c6ebd7742 | |||
b85539dc17 | |||
4cae3f02ed | |||
469b436f10 | |||
66e3e6729b | |||
fc6a794714 | |||
d75ed3d5ac | |||
bd0a218214 | |||
f96129fa37 | |||
920418618a | |||
29247481a6 | |||
773710aeef | |||
d0c8ee57e6 | |||
cf2adc7f6a | |||
b621f24540 | |||
99be638525 | |||
d35c204e07 | |||
d8b4267668 | |||
3c2f3be451 | |||
e846cf8672 | |||
8804bce6c0 | |||
83acda6d05 | |||
063719532f | |||
7b1b061355 | |||
ed4540887e | |||
6968476ed0 | |||
5d2c7c3058 | |||
e6cb90e545 | |||
ec73f4dbea | |||
4f41a52ee7 | |||
c097956fcb | |||
8cbc17ed98 | |||
50d89d0f13 | |||
7b4d13b73e | |||
2909aa1656 | |||
64131b6764 | |||
0b78d75a21 | |||
b35c342960 | |||
24c858d379 | |||
b8a31a8be9 | |||
02c30d6454 | |||
985f003e6d | |||
98045e1e2e | |||
5762ce58a4 | |||
2787ee71fc | |||
e61a6df4d7 | |||
0a5c2ecbf5 | |||
6bfab696ad | |||
928f2dd496 | |||
bcf75892f7 | |||
594761385f | |||
d05fba06ec | |||
25155b1b38 | |||
ded6c9c199 | |||
c62e6c0045 | |||
b3feda9fd1 | |||
7ef8e2c8b8 | |||
d5ff211871 | |||
51c23e3842 | |||
557b30815e | |||
145459bfc3 | |||
f97a6a2bee | |||
1134422891 | |||
6012275c7b | |||
2f07063375 | |||
310d1ed485 | |||
a48edbb16e | |||
d6258409fc | |||
1b94b1247b | |||
9ef63ae60e | |||
f99de4be48 | |||
80fd1820c2 | |||
0a4a983d20 | |||
c2cc830691 | |||
4d0490d1c6 | |||
02d1838547 | |||
5c6edff778 | |||
7cbca32ddd |
2
.gitignore
vendored
2
.gitignore
vendored
@ -10,6 +10,8 @@ msbuild.binlog
|
|||||||
*.zip
|
*.zip
|
||||||
|
|
||||||
*.idea
|
*.idea
|
||||||
|
_ReSharper.Caches
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
Oqtane.Server/appsettings.json
|
Oqtane.Server/appsettings.json
|
||||||
Oqtane.Server/Data
|
Oqtane.Server/Data
|
||||||
|
@ -16,7 +16,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static IServiceCollection AddOqtaneScopedServices(this IServiceCollection services)
|
public static IServiceCollection AddOqtaneScopedServices(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddScoped<SiteState>();
|
services.AddScoped<SiteState>();
|
||||||
services.AddScoped<IInstallationService, InstallationService>();
|
services.AddScoped<IInstallationService, InstallationService>();
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="server" HelpText="Enter the database server" ResourceKey="Server">Server:</Label>
|
<Label Class="col-sm-3" For="server" HelpText="Enter the database server name. This might include a port number as well if you are using a cloud service (ie. servername.database.windows.net,1433) " ResourceKey="Server">Server:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="server" type="text" class="form-control" @bind="@_server" />
|
<input id="server" type="text" class="form-control" @bind="@_server" />
|
||||||
</div>
|
</div>
|
||||||
@ -51,7 +51,7 @@
|
|||||||
@if (_encryption == "true")
|
@if (_encryption == "true")
|
||||||
{
|
{
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="trustservercertificate" HelpText="Specify the type of certificate you are using for encryption" ResourceKey="TrustServerCertificate">Certificate:</Label>
|
<Label Class="col-sm-3" For="trustservercertificate" HelpText="Specify the type of certificate you are using for encryption. Verifiable is equivalent to False. Self Signed is equivalent to True." ResourceKey="TrustServerCertificate">Certificate:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="encryption" class="form-select custom-select" @bind="@_trustservercertificate">
|
<select id="encryption" class="form-select custom-select" @bind="@_trustservercertificate">
|
||||||
<option value="true">@Localizer["Self Signed"]</option>
|
<option value="true">@Localizer["Self Signed"]</option>
|
||||||
|
@ -26,22 +26,42 @@
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
@if (_databases != null)
|
@if (_databases != null)
|
||||||
{
|
{
|
||||||
<select id="databasetype" class="form-select custom-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))">
|
<div class="input-group">
|
||||||
@foreach (var database in _databases)
|
<select id="databaseType" class="form-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))" required>
|
||||||
{
|
@foreach (var database in _databases)
|
||||||
<option value="@database.Name">@Localizer[@database.Name]</option>
|
{
|
||||||
}
|
<option value="@database.Name">@Localizer[@database.Name]</option>
|
||||||
</select>
|
}
|
||||||
|
</select>
|
||||||
|
@if (!_showConnectionString)
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="ToggleConnectionString">@Localizer["EnterConnectionString"]</button>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="ToggleConnectionString">@Localizer["EnterConnectionParameters"]</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@{
|
@if (!_showConnectionString)
|
||||||
if (_databaseConfigType != null)
|
{
|
||||||
{
|
if (_databaseConfigType != null)
|
||||||
@DatabaseConfigComponent;
|
{
|
||||||
}
|
@DatabaseConfigComponent
|
||||||
}
|
}
|
||||||
</div>
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="connectionstring" HelpText="Enter a complete connection string including all parameters and delimiters" ResourceKey="ConnectionString">String:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea id="connectionstring" class="form-control" @bind="@_connectionString" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col text-center">
|
<div class="col text-center">
|
||||||
<h2>@Localizer["ApplicationAdmin"]</h2><br />
|
<h2>@Localizer["ApplicationAdmin"]</h2><br />
|
||||||
@ -100,13 +120,15 @@
|
|||||||
private Type _databaseConfigType;
|
private Type _databaseConfigType;
|
||||||
private object _databaseConfig;
|
private object _databaseConfig;
|
||||||
private RenderFragment DatabaseConfigComponent { get; set; }
|
private RenderFragment DatabaseConfigComponent { get; set; }
|
||||||
|
private bool _showConnectionString = false;
|
||||||
|
private string _connectionString = string.Empty;
|
||||||
|
|
||||||
private string _hostUsername = string.Empty;
|
private string _hostUsername = string.Empty;
|
||||||
private string _hostPassword = string.Empty;
|
private string _hostPassword = string.Empty;
|
||||||
private string _passwordType = "password";
|
private string _passwordType = "password";
|
||||||
private string _confirmPasswordType = "password";
|
private string _confirmPasswordType = "password";
|
||||||
private string _togglePassword = string.Empty;
|
private string _togglePassword = string.Empty;
|
||||||
private string _toggleConfirmPassword = string.Empty;
|
private string _toggleConfirmPassword = string.Empty;
|
||||||
private string _confirmPassword = string.Empty;
|
private string _confirmPassword = string.Empty;
|
||||||
private string _hostEmail = string.Empty;
|
private string _hostEmail = string.Empty;
|
||||||
private bool _register = true;
|
private bool _register = true;
|
||||||
@ -116,7 +138,7 @@
|
|||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
_togglePassword = SharedLocalizer["ShowPassword"];
|
_togglePassword = SharedLocalizer["ShowPassword"];
|
||||||
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
|
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
|
||||||
|
|
||||||
_databases = await DatabaseService.GetDatabasesAsync();
|
_databases = await DatabaseService.GetDatabasesAsync();
|
||||||
if (_databases.Exists(item => item.IsDefault))
|
if (_databases.Exists(item => item.IsDefault))
|
||||||
@ -135,7 +157,7 @@
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_databaseName = (string)eventArgs.Value;
|
_databaseName = (string)eventArgs.Value;
|
||||||
|
_showConnectionString = false;
|
||||||
LoadDatabaseConfigComponent();
|
LoadDatabaseConfigComponent();
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -164,17 +186,24 @@
|
|||||||
if (firstRender)
|
if (firstRender)
|
||||||
{
|
{
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
await interop.IncludeLink("", "stylesheet", "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/css/bootstrap.min.css", "text/css", "sha512-GQGU0fMMi238uA+a/bdWJfpUGKUkBdgfFdgBm72SUQ6BeyWjoY/ton0tEjH+OSH9iP4Dfh+7HM0I9f5eR0L/4w==", "anonymous", "");
|
await interop.IncludeLink("", "stylesheet", "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.0/css/bootstrap.min.css", "text/css", "sha512-XWTTruHZEYJsxV3W/lSXG1n3Q39YIWOstqvmFsdNEEQfHoZ6vm6E9GK2OrF6DSJSpIbRbi+Nn0WDPID9O7xB2Q==", "anonymous", "");
|
||||||
await interop.IncludeScript("", "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/js/bootstrap.bundle.min.js", "sha512-pax4MlgXjHEPfCwcJLQhigY7+N8rt6bVvWLFyUMuxShv170X53TRzGPmPkZmGBhk+jikR8WBM4yl7A9WMHHqvg==", "anonymous", "", "head");
|
await interop.IncludeScript("", "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.0/js/bootstrap.bundle.min.js", "sha512-9GacT4119eY3AcosfWtHMsT5JyZudrexyEVzTBWV3viP/YfB9e2pEy3N7WXL3SV6ASXpTU0vzzSxsbfsuUH4sQ==", "anonymous", "", "head");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Install()
|
private async Task Install()
|
||||||
{
|
{
|
||||||
var connectionString = String.Empty;
|
var connectionString = String.Empty;
|
||||||
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
if (_showConnectionString)
|
||||||
{
|
{
|
||||||
connectionString = databaseConfigControl.GetConnectionString();
|
connectionString = _connectionString;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
||||||
|
{
|
||||||
|
connectionString = databaseConfigControl.GetConnectionString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connectionString != "" && !string.IsNullOrEmpty(_hostUsername) && !string.IsNullOrEmpty(_hostPassword) && _hostPassword == _confirmPassword && !string.IsNullOrEmpty(_hostEmail) && _hostEmail.Contains("@"))
|
if (connectionString != "" && !string.IsNullOrEmpty(_hostUsername) && !string.IsNullOrEmpty(_hostPassword) && _hostPassword == _confirmPassword && !string.IsNullOrEmpty(_hostEmail) && _hostEmail.Contains("@"))
|
||||||
@ -218,12 +247,12 @@
|
|||||||
{
|
{
|
||||||
_message = Localizer["Message.Password.Invalid"];
|
_message = Localizer["Message.Password.Invalid"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_message = Localizer["Message.Require.DbInfo"];
|
_message = Localizer["Message.Require.DbInfo"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TogglePassword()
|
private void TogglePassword()
|
||||||
{
|
{
|
||||||
@ -239,7 +268,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ToggleConfirmPassword()
|
private void ToggleConfirmPassword()
|
||||||
{
|
{
|
||||||
if (_confirmPasswordType == "password")
|
if (_confirmPasswordType == "password")
|
||||||
{
|
{
|
||||||
@ -252,4 +281,14 @@
|
|||||||
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
|
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ToggleConnectionString()
|
||||||
|
{
|
||||||
|
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
||||||
|
{
|
||||||
|
_connectionString = databaseConfigControl.GetConnectionString();
|
||||||
|
}
|
||||||
|
_showConnectionString = !_showConnectionString;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.Permissions))
|
||||||
{
|
{
|
||||||
string url = NavigateUrl(p.Path);
|
string url = NavigateUrl(p.Path);
|
||||||
<div class="col-md-2 mx-auto text-center">
|
<div class="col-md-2 mx-auto text-center mb-3">
|
||||||
<NavLink class="nav-link" href="@url" Match="NavLinkMatch.All">
|
<NavLink class="nav-link text-primary" href="@url" Match="NavLinkMatch.All">
|
||||||
<h2><span class="@p.Icon" aria-hidden="true"></span></h2>@SharedLocalizer[p.Name]
|
<h2><span class="@p.Icon" aria-hidden="true"></span></h2>@SharedLocalizer[p.Name]
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,8 +11,7 @@
|
|||||||
Module module = await ModuleService.GetModuleAsync(ModuleState.ModuleId);
|
Module module = await ModuleService.GetModuleAsync(ModuleState.ModuleId);
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
{
|
{
|
||||||
string message = string.Format(Localizer["Error.Module.Load"], module.ModuleDefinitionName);
|
AddModuleMessage(string.Format(Localizer["Error.Module.Load"], module.ModuleDefinitionName), MessageType.Error);
|
||||||
AddModuleMessage(message, MessageType.Error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await logger.LogCritical("Error Loading Module {Module}", module);
|
await logger.LogCritical("Error Loading Module {Module}", module);
|
||||||
|
@ -132,22 +132,10 @@
|
|||||||
_isEnabled = job.IsEnabled.ToString();
|
_isEnabled = job.IsEnabled.ToString();
|
||||||
_interval = job.Interval.ToString();
|
_interval = job.Interval.ToString();
|
||||||
_frequency = job.Frequency;
|
_frequency = job.Frequency;
|
||||||
_startDate = job.StartDate;
|
(_startDate, _startTime) = Utilities.UtcAsLocalDateAndTime(job.StartDate);
|
||||||
if (job.StartDate != null && job.StartDate.Value.TimeOfDay.TotalSeconds != 0)
|
(_endDate, _endTime) = Utilities.UtcAsLocalDateAndTime(job.EndDate);
|
||||||
{
|
|
||||||
_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();
|
_retentionHistory = job.RetentionHistory.ToString();
|
||||||
_nextDate = job.NextExecution;
|
(_nextDate, _nextTime) = Utilities.UtcAsLocalDateAndTime(job.NextExecution);
|
||||||
if (job.NextExecution != null && job.NextExecution.Value.TimeOfDay.TotalSeconds != 0)
|
|
||||||
{
|
|
||||||
_nextTime = job.NextExecution.Value.ToString("HH:mm");
|
|
||||||
}
|
|
||||||
createdby = job.CreatedBy;
|
createdby = job.CreatedBy;
|
||||||
createdon = job.CreatedOn;
|
createdon = job.CreatedOn;
|
||||||
modifiedby = job.ModifiedBy;
|
modifiedby = job.ModifiedBy;
|
||||||
@ -180,50 +168,27 @@
|
|||||||
{
|
{
|
||||||
job.Interval = int.Parse(_interval);
|
job.Interval = int.Parse(_interval);
|
||||||
}
|
}
|
||||||
job.StartDate = _startDate;
|
job.StartDate = Utilities.LocalDateAndTimeAsUtc(_startDate, _startTime);
|
||||||
if (job.StartDate != null)
|
job.EndDate = Utilities.LocalDateAndTimeAsUtc(_endDate, _endTime);
|
||||||
{
|
job.RetentionHistory = int.Parse(_retentionHistory);
|
||||||
job.StartDate = job.StartDate.Value.Date;
|
job.NextExecution = Utilities.LocalDateAndTimeAsUtc(_nextDate, _nextTime);
|
||||||
if (!string.IsNullOrEmpty(_startTime))
|
|
||||||
{
|
try
|
||||||
job.StartDate = DateTime.Parse(job.StartDate.Value.ToShortDateString() + " " + _startTime);
|
{
|
||||||
}
|
job = await JobService.UpdateJobAsync(job);
|
||||||
}
|
await logger.LogInformation("Job Updated {Job}", job);
|
||||||
job.EndDate = _endDate;
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
if (job.EndDate != null)
|
}
|
||||||
{
|
catch (Exception ex)
|
||||||
job.EndDate = job.EndDate.Value.Date;
|
{
|
||||||
if (!string.IsNullOrEmpty(_endTime))
|
await logger.LogError(ex, "Error Udate Job {Job} {Error}", job, ex.Message);
|
||||||
{
|
AddModuleMessage(Localizer["Error.Job.Update"], MessageType.Error);
|
||||||
job.EndDate = DateTime.Parse(job.EndDate.Value.ToShortDateString() + " " + _endTime);
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
job.RetentionHistory = int.Parse(_retentionHistory);
|
{
|
||||||
job.NextExecution = _nextDate;
|
AddModuleMessage(Localizer["Message.Required.JobInfo"], MessageType.Warning);
|
||||||
if (job.NextExecution != null)
|
}
|
||||||
{
|
}
|
||||||
job.NextExecution = job.NextExecution.Value.Date;
|
|
||||||
if (!string.IsNullOrEmpty(_nextTime))
|
|
||||||
{
|
|
||||||
job.NextExecution = DateTime.Parse(job.NextExecution.Value.ToShortDateString() + " " + _nextTime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
job = await JobService.UpdateJobAsync(job);
|
|
||||||
await logger.LogInformation("Job Updated {Job}", job);
|
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Udate Job {Job} {Error}", job, ex.Message);
|
|
||||||
AddModuleMessage(Localizer["Error.Job.Update"], MessageType.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AddModuleMessage(Localizer["Message.Required.JobInfo"], MessageType.Warning);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ else
|
|||||||
<td>@context.Name</td>
|
<td>@context.Name</td>
|
||||||
<td>@DisplayStatus(context.IsEnabled, context.IsExecuting)</td>
|
<td>@DisplayStatus(context.IsEnabled, context.IsExecuting)</td>
|
||||||
<td>@DisplayFrequency(context.Interval, context.Frequency)</td>
|
<td>@DisplayFrequency(context.Interval, context.Frequency)</td>
|
||||||
<td>@context.NextExecution</td>
|
<td>@context.NextExecution?.ToLocalTime()</td>
|
||||||
<td>
|
<td>
|
||||||
@if (context.IsStarted)
|
@if (context.IsStarted)
|
||||||
{
|
{
|
||||||
@ -56,6 +56,10 @@ else
|
|||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
_jobs = await JobService.GetJobsAsync();
|
_jobs = await JobService.GetJobsAsync();
|
||||||
|
if (_jobs.Count == 0)
|
||||||
|
{
|
||||||
|
AddModuleMessage(string.Format(Localizer["Message.NoJobs"], NavigateUrl("admin/system")), MessageType.Warning);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string DisplayStatus(bool isEnabled, bool isExecuting)
|
private string DisplayStatus(bool isEnabled, bool isExecuting)
|
||||||
|
@ -32,7 +32,7 @@ else
|
|||||||
<select id="_code" class="form-select" @bind="@_code" required>
|
<select id="_code" class="form-select" @bind="@_code" required>
|
||||||
@foreach (var culture in _availableCultures)
|
@foreach (var culture in _availableCultures)
|
||||||
{
|
{
|
||||||
<option value="@culture.Name">@culture.DisplayName</option>
|
<option value="@culture.Name">@(culture.DisplayName + " (" + culture.Name + ")")</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@ -52,7 +52,7 @@ else
|
|||||||
</form>
|
</form>
|
||||||
}
|
}
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel Name="Download" ResourceKey="Download" Security="SecurityAccessLevel.Host">
|
<TabPanel Name="Translations" Heading="Translations" ResourceKey="Download" Security="SecurityAccessLevel.Host">
|
||||||
<div class="row justify-content-center mb-3">
|
<div class="row justify-content-center mb-3">
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
@ -110,12 +110,16 @@ else
|
|||||||
}
|
}
|
||||||
<button type="button" class="btn btn-success" @onclick="InstallLanguages">@SharedLocalizer["Install"]</button>
|
<button type="button" class="btn btn-success" @onclick="InstallLanguages">@SharedLocalizer["Install"]</button>
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<ModuleMessage Type="MessageType.Info" Message="@SharedLocalizer["Oqtane.Marketplace"]" />
|
||||||
}
|
}
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel Name="Upload" ResourceKey="Upload" Security="SecurityAccessLevel.Host">
|
<TabPanel Name="Upload" ResourceKey="Upload" Security="SecurityAccessLevel.Host">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<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="LanguageUpload">Language: </Label>
|
<Label Class="col-sm-3" HelpText="Upload one or more translations. Once they are uploaded click Install to complete the installation." ResourceKey="LanguageUpload">Translation: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" />
|
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" />
|
||||||
</div>
|
</div>
|
||||||
@ -161,33 +165,32 @@ else
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private ElementReference form;
|
private ElementReference form;
|
||||||
private bool validated = false;
|
private bool validated = false;
|
||||||
|
|
||||||
private string _code = string.Empty;
|
private string _code = string.Empty;
|
||||||
private string _isDefault = "False";
|
private string _isDefault = "False";
|
||||||
private string _message;
|
private string _message;
|
||||||
private IEnumerable<Culture> _supportedCultures;
|
private IEnumerable<Culture> _supportedCultures;
|
||||||
private IEnumerable<Culture> _availableCultures;
|
private IEnumerable<Culture> _availableCultures;
|
||||||
private List<Package> _packages;
|
private List<Package> _packages;
|
||||||
private string _price = "free";
|
private string _price = "free";
|
||||||
private string _search = "";
|
private string _search = "";
|
||||||
private string _productname = "";
|
private string _productname = "";
|
||||||
private string _license = "";
|
private string _license = "";
|
||||||
private string _packageid = "";
|
private string _packageid = "";
|
||||||
private string _version = "";
|
private string _version = "";
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
var languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId);
|
var languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId);
|
||||||
var languagesCodes = languages.Select(l => l.Code).ToList();
|
var languagesCodes = languages.Select(l => l.Code).ToList();
|
||||||
|
|
||||||
_supportedCultures = await LocalizationService.GetCulturesAsync();
|
_supportedCultures = await LocalizationService.GetCulturesAsync();
|
||||||
_availableCultures = _supportedCultures
|
_availableCultures = _supportedCultures.Where(c => !c.Name.Equals(Constants.DefaultCulture) && !languagesCodes.Contains(c.Name));
|
||||||
.Where(c => !c.Name.Equals(Constants.DefaultCulture) && !languagesCodes.Contains(c.Name));
|
await LoadTranslations();
|
||||||
await LoadTranslations();
|
|
||||||
|
|
||||||
if (_supportedCultures.Count() == 1)
|
if (_supportedCultures.Count() == 1)
|
||||||
{
|
{
|
||||||
|
@ -19,16 +19,18 @@ else
|
|||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>@SharedLocalizer["Name"]</th>
|
<th>@SharedLocalizer["Name"]</th>
|
||||||
<th>@Localizer["Code"]</th>
|
<th>@Localizer["Code"]</th>
|
||||||
|
<th>@Localizer["Translation"]</th>
|
||||||
<th>@Localizer["Default"]</th>
|
<th>@Localizer["Default"]</th>
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td><ActionDialog Header="Delete Language" Message="@string.Format(Localizer["Confirm.Language.Delete"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteLanguage(context))" Disabled="@((context.IsDefault && _languages.Count > 2) || context.Code == Constants.DefaultCulture)" ResourceKey="DeleteLanguage" /></td>
|
<td><ActionDialog Header="Delete Language" Message="@string.Format(Localizer["Confirm.Language.Delete"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteLanguage(context))" Disabled="@((context.IsDefault && _languages.Count > 2) || context.Code == Constants.DefaultCulture)" ResourceKey="DeleteLanguage" /></td>
|
||||||
<td>@context.Name</td>
|
<td>@context.Name</td>
|
||||||
<td>@context.Code</td>
|
<td>@context.Code</td>
|
||||||
<td><TriStateCheckBox Value="@(context.IsDefault)" Disabled="true"></TriStateCheckBox></td>
|
<td>@context.Version</td>
|
||||||
<td>
|
<td><TriStateCheckBox Value="@(context.IsDefault)" Disabled="true"></TriStateCheckBox></td>
|
||||||
@if (UpgradeAvailable(context.Code))
|
<td>
|
||||||
|
@if (UpgradeAvailable(context.Code, context.Version))
|
||||||
{
|
{
|
||||||
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadLanguage(context.Code))>@SharedLocalizer["Upgrade"]</button>
|
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadLanguage(context.Code))>@SharedLocalizer["Upgrade"]</button>
|
||||||
}
|
}
|
||||||
@ -38,21 +40,18 @@ else
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<Language> _languages;
|
private List<Language> _languages;
|
||||||
private List<Package> _packages;
|
private List<Package> _packages;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
_languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId);
|
_languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId, Constants.ClientId);
|
||||||
|
|
||||||
var cultures = await LocalizationService.GetCulturesAsync();
|
var cultures = await LocalizationService.GetCulturesAsync();
|
||||||
var culture = cultures.First(c => c.Name.Equals(Constants.DefaultCulture));
|
var culture = cultures.First(c => c.Name.Equals(Constants.DefaultCulture));
|
||||||
|
|
||||||
// Adds English as default language
|
|
||||||
_languages.Insert(0, new Language { Name = culture.DisplayName, Code = culture.Name, IsDefault = !_languages.Any(l => l.IsDefault) });
|
|
||||||
|
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
{
|
{
|
||||||
_packages = await PackageService.GetPackagesAsync("translation");
|
_packages = await PackageService.GetPackagesAsync("translation");
|
||||||
@ -76,15 +75,16 @@ else
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool UpgradeAvailable(string code)
|
private bool UpgradeAvailable(string code, string version)
|
||||||
{
|
{
|
||||||
var upgradeavailable = false;
|
var upgradeavailable = false;
|
||||||
if (_packages != null)
|
if (_packages != null && version != null)
|
||||||
{
|
{
|
||||||
var package = _packages.Where(item => item.PackageId == (Constants.PackageId + ".Client." + code)).FirstOrDefault();
|
var package = _packages.Where(item => item.PackageId == (Constants.PackageId + "." + code)).FirstOrDefault();
|
||||||
if (package != null)
|
if (package != null)
|
||||||
{
|
{
|
||||||
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(Constants.Version)) == 0);
|
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(Constants.Version)) == 0) &&
|
||||||
|
(Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ else
|
|||||||
{
|
{
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(Constants.PackageId + ".Client." + code, Constants.Version, Constants.PackagesFolder);
|
await PackageService.DownloadPackageAsync(Constants.PackageId + "." + code, Constants.Version, Constants.PackagesFolder);
|
||||||
await logger.LogInformation("Translation Downloaded {Code} {Version}", code, Constants.Version);
|
await logger.LogInformation("Translation Downloaded {Code} {Version}", code, Constants.Version);
|
||||||
await PackageService.InstallPackagesAsync();
|
await PackageService.InstallPackagesAsync();
|
||||||
AddModuleMessage(string.Format(Localizer["Success.Language.Install"], NavigateUrl("admin/system")), MessageType.Success);
|
AddModuleMessage(string.Format(Localizer["Success.Language.Install"], NavigateUrl("admin/system")), MessageType.Success);
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@inject IServiceProvider ServiceProvider
|
@inject IServiceProvider ServiceProvider
|
||||||
@inject SiteState SiteState
|
|
||||||
@inject IStringLocalizer<Index> Localizer
|
@inject IStringLocalizer<Index> Localizer
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
|
||||||
@ -184,11 +183,12 @@
|
|||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
if (await interop.FormValid(login))
|
if (await interop.FormValid(login))
|
||||||
{
|
{
|
||||||
|
var hybrid = (PageState.Runtime == Shared.Runtime.Hybrid);
|
||||||
var user = new User { SiteId = PageState.Site.SiteId, Username = _username, Password = _password, LastIPAddress = SiteState.RemoteIPAddress};
|
var user = new User { SiteId = PageState.Site.SiteId, Username = _username, Password = _password, LastIPAddress = SiteState.RemoteIPAddress};
|
||||||
|
|
||||||
if (!twofactor)
|
if (!twofactor)
|
||||||
{
|
{
|
||||||
user = await UserService.LoginUserAsync(user);
|
user = await UserService.LoginUserAsync(user, hybrid, _remember);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -199,10 +199,21 @@
|
|||||||
{
|
{
|
||||||
await logger.LogInformation(LogFunction.Security, "Login Successful For Username {Username}", _username);
|
await logger.LogInformation(LogFunction.Security, "Login Successful For Username {Username}", _username);
|
||||||
|
|
||||||
// post back to the Login page so that the cookies are set correctly
|
if (hybrid)
|
||||||
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, username = _username, password = _password, remember = _remember, returnurl = _returnUrl };
|
{
|
||||||
string url = Utilities.TenantUrl(PageState.Alias, "/pages/login/");
|
// hybrid apps utilize an interactive login
|
||||||
await interop.SubmitForm(url, fields);
|
var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider
|
||||||
|
.GetService(typeof(IdentityAuthenticationStateProvider));
|
||||||
|
authstateprovider.NotifyAuthenticationChanged();
|
||||||
|
NavigationManager.NavigateTo(NavigateUrl(_returnUrl, true));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// post back 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/");
|
||||||
|
await interop.SubmitForm(url, fields);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -130,13 +130,14 @@
|
|||||||
private string _properties = string.Empty;
|
private string _properties = string.Empty;
|
||||||
private string _server = string.Empty;
|
private string _server = string.Empty;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override string UrlParametersTemplate => "/{id}";
|
||||||
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_logId = Int32.Parse(PageState.QueryString["id"]);
|
_logId = Int32.Parse(UrlParameters["id"]);
|
||||||
var log = await LogService.GetLogAsync(_logId);
|
var log = await LogService.GetLogAsync(_logId);
|
||||||
if (log != null)
|
if (log != null)
|
||||||
{
|
{
|
||||||
@ -191,13 +192,6 @@
|
|||||||
|
|
||||||
private string CloseUrl()
|
private string CloseUrl()
|
||||||
{
|
{
|
||||||
if (!PageState.QueryString.ContainsKey("level"))
|
return (!string.IsNullOrEmpty(PageState.ReturnUrl)) ? PageState.ReturnUrl : NavigateUrl();
|
||||||
{
|
|
||||||
return NavigateUrl();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return NavigateUrl(PageState.Page.Path, "level=" + PageState.QueryString["level"] + "&function=" + PageState.QueryString["function"] + "&rows=" + PageState.QueryString["rows"] + "&page=" + PageState.QueryString["page"]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ else
|
|||||||
<th>@Localizer["Function"]</th>
|
<th>@Localizer["Function"]</th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td class="@GetClass(context.Function)"><ActionLink Action="Detail" Parameters="@($"id=" + context.LogId.ToString() + "&level=" + _level + "&function=" + _function + "&rows=" + _rows + "&page=" + _page.ToString())" ResourceKey="LogDetails" /></td>
|
<td class="@GetClass(context.Function)"><ActionLink Action="Detail" Parameters="@($"/{context.LogId}")" ReturnUrl="@(NavigateUrl(PageState.Page.Path, AddUrlParameters(_level, _function, _rows, _page)))" ResourceKey="LogDetails" /></td>
|
||||||
<td class="@GetClass(context.Function)">@context.LogDate</td>
|
<td class="@GetClass(context.Function)">@context.LogDate</td>
|
||||||
<td class="@GetClass(context.Function)">@context.Level</td>
|
<td class="@GetClass(context.Function)">@context.Level</td>
|
||||||
<td class="@GetClass(context.Function)">@context.Feature</td>
|
<td class="@GetClass(context.Function)">@context.Feature</td>
|
||||||
@ -99,29 +99,32 @@ else
|
|||||||
private List<Log> _logs;
|
private List<Log> _logs;
|
||||||
private string _retention = "";
|
private string _retention = "";
|
||||||
|
|
||||||
|
public override string UrlParametersTemplate => "/{level}/{function}/{rows}/{page}";
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// external link to log item will display Details component
|
||||||
if (PageState.QueryString.ContainsKey("id") && int.TryParse(PageState.QueryString["id"], out int id))
|
if (PageState.QueryString.ContainsKey("id") && int.TryParse(PageState.QueryString["id"], out int id))
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(EditUrl(PageState.Page.Path, ModuleState.ModuleId, "Detail", $"id={id}"));
|
NavigationManager.NavigateTo(EditUrl(PageState.Page.Path, ModuleState.ModuleId, "Detail", $"/{id}"));
|
||||||
}
|
}
|
||||||
if (PageState.QueryString.ContainsKey("level"))
|
|
||||||
|
if (UrlParameters.ContainsKey("level"))
|
||||||
{
|
{
|
||||||
_level = PageState.QueryString["level"];
|
_level = UrlParameters["level"];
|
||||||
}
|
}
|
||||||
if (PageState.QueryString.ContainsKey("function"))
|
if (UrlParameters.ContainsKey("function"))
|
||||||
{
|
{
|
||||||
_function = PageState.QueryString["function"];
|
_function = UrlParameters["function"];
|
||||||
}
|
}
|
||||||
if (PageState.QueryString.ContainsKey("rows"))
|
if (UrlParameters.ContainsKey("rows"))
|
||||||
{
|
{
|
||||||
_rows = PageState.QueryString["rows"];
|
_rows = UrlParameters["rows"];
|
||||||
}
|
}
|
||||||
if (PageState.QueryString.ContainsKey("page") && int.TryParse(PageState.QueryString["page"], out int page))
|
if (UrlParameters.ContainsKey("page") && int.TryParse(UrlParameters["page"], out int page))
|
||||||
{
|
{
|
||||||
_page = page;
|
_page = page;
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ else
|
|||||||
private List<Template> _templates;
|
private List<Template> _templates;
|
||||||
private string _template = "-";
|
private string _template = "-";
|
||||||
private string[] _versions;
|
private string[] _versions;
|
||||||
private string _reference = Constants.Version;
|
private string _reference = "local";
|
||||||
private string _minversion = "2.0.0";
|
private string _minversion = "2.0.0";
|
||||||
private string _location = string.Empty;
|
private string _location = string.Empty;
|
||||||
|
|
||||||
|
@ -91,9 +91,9 @@
|
|||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<p style="height: 200px; overflow-y: scroll;">
|
<p style="height: 200px; overflow-y: scroll;">
|
||||||
<h3>@_productname</h3>
|
<h3>@_productname</h3>
|
||||||
@if (!string.IsNullOrEmpty(_license))
|
@if (!string.IsNullOrEmpty(_packagelicense))
|
||||||
{
|
{
|
||||||
@((MarkupString)_license)
|
@((MarkupString)_packagelicense)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -114,14 +114,18 @@
|
|||||||
<button type="button" class="btn btn-success" @onclick="InstallModules">@SharedLocalizer["Install"]</button>
|
<button type="button" class="btn btn-success" @onclick="InstallModules">@SharedLocalizer["Install"]</button>
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<ModuleMessage Type="MessageType.Info" Message="@SharedLocalizer["Oqtane.Marketplace"]" />
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<Package> _packages;
|
private List<Package> _packages;
|
||||||
private string _price = "free";
|
private string _price = "free";
|
||||||
private string _search = "";
|
private string _search = "";
|
||||||
private string _productname = "";
|
private string _productname = "";
|
||||||
private string _license = "";
|
|
||||||
private string _packageid = "";
|
private string _packageid = "";
|
||||||
private string _version = "";
|
private string _packagelicense = "";
|
||||||
|
private string _packageversion = "";
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
@ -198,7 +202,7 @@
|
|||||||
private void HideModal()
|
private void HideModal()
|
||||||
{
|
{
|
||||||
_productname = "";
|
_productname = "";
|
||||||
_license = "";
|
_packagelicense = "";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,12 +214,12 @@
|
|||||||
if (package != null)
|
if (package != null)
|
||||||
{
|
{
|
||||||
_productname = package.Name;
|
_productname = package.Name;
|
||||||
|
_packageid = package.PackageId;
|
||||||
if (!string.IsNullOrEmpty(package.License))
|
if (!string.IsNullOrEmpty(package.License))
|
||||||
{
|
{
|
||||||
_license = package.License.Replace("\n", "<br />");
|
_packagelicense = package.License.Replace("\n", "<br />");
|
||||||
}
|
}
|
||||||
_packageid = package.PackageId;
|
_packageversion = package.Version;
|
||||||
_version = package.Version;
|
|
||||||
}
|
}
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
@ -230,16 +234,16 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(_packageid, _version, Constants.PackagesFolder);
|
await PackageService.DownloadPackageAsync(_packageid, _packageversion, Constants.PackagesFolder);
|
||||||
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _packageid, _version);
|
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _packageid, _packageversion);
|
||||||
AddModuleMessage(Localizer["Success.Module.Download"], MessageType.Success);
|
AddModuleMessage(Localizer["Success.Module.Download"], MessageType.Success);
|
||||||
_productname = "";
|
_productname = "";
|
||||||
_license = "";
|
_packagelicense = "";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Downloading Package {PackageId} {Version}", _packageid, _version);
|
await logger.LogError(ex, "Error Downloading Package {PackageId} {Version}", _packageid, _packageversion);
|
||||||
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -253,7 +257,7 @@
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Installing Module");
|
await logger.LogError(ex, "Error Installing Modules");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@
|
|||||||
var template = _templates.FirstOrDefault(item => item.Name == _template);
|
var template = _templates.FirstOrDefault(item => item.Name == _template);
|
||||||
_minversion = template.Version;
|
_minversion = template.Version;
|
||||||
}
|
}
|
||||||
GetLocation();
|
GetLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetLocation()
|
private void GetLocation()
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
@namespace Oqtane.Modules.Admin.ModuleDefinitions
|
@namespace Oqtane.Modules.Admin.ModuleDefinitions
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
|
@using System.Globalization
|
||||||
|
@using Microsoft.AspNetCore.Localization
|
||||||
@inject IModuleDefinitionService ModuleDefinitionService
|
@inject IModuleDefinitionService ModuleDefinitionService
|
||||||
|
@inject IPackageService PackageService
|
||||||
|
@inject ILanguageService LanguageService
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IStringLocalizer<Edit> Localizer
|
@inject IStringLocalizer<Edit> Localizer
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
@ -43,7 +47,13 @@
|
|||||||
<input id="version" class="form-control" @bind="@_version" disabled />
|
<input id="version" class="form-control" @bind="@_version" disabled />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="packagename" HelpText="The unique name of the package from which this module was installed" ResourceKey="PackageName">Package Name: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="packagename" class="form-control" @bind="@_packagename" disabled />
|
||||||
|
</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>
|
<Label Class="col-sm-3" For="owner" HelpText="The owner or creator of the module" ResourceKey="Owner">Owner: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="owner" class="form-control" @bind="@_owner" disabled />
|
<input id="owner" class="form-control" @bind="@_owner" disabled />
|
||||||
@ -74,7 +84,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Section>
|
</Section>
|
||||||
|
<br />
|
||||||
|
<button type="button" class="btn btn-success" @onclick="SaveModuleDefinition">@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>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@ -82,107 +98,278 @@
|
|||||||
<PermissionGrid EntityName="@EntityNames.ModuleDefinition" PermissionNames="@PermissionNames.Utilize" Permissions="@_permissions" @ref="_permissionGrid" />
|
<PermissionGrid EntityName="@EntityNames.ModuleDefinition" PermissionNames="@PermissionNames.Utilize" Permissions="@_permissions" @ref="_permissionGrid" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<button type="button" class="btn btn-success" @onclick="SaveModuleDefinition">@SharedLocalizer["Save"]</button>
|
||||||
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
<TabPanel Name="Translations" ResourceKey="Translations">
|
||||||
|
@if (_languages != null && _languages.Count > 0)
|
||||||
|
{
|
||||||
|
<Pager Items="@_languages">
|
||||||
|
<Header>
|
||||||
|
<th>@SharedLocalizer["Name"]</th>
|
||||||
|
<th>@Localizer["Code"]</th>
|
||||||
|
<th>@Localizer["Version"]</th>
|
||||||
|
<th style="width: 1px;"> </th>
|
||||||
|
</Header>
|
||||||
|
<Row>
|
||||||
|
<td>@context.Name</td>
|
||||||
|
<td>@context.Code</td>
|
||||||
|
<td>@context.Version</td>
|
||||||
|
<td>
|
||||||
|
@if (context.IsDefault)
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-primary" @onclick=@(async () => await GetPackage(_packagename + "." + context.Code))>@SharedLocalizer["Download"]</button>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (UpgradeAvailable(_packagename + "." + context.Code, context.Version))
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-primary" @onclick=@(async () => await DownloadPackage(_packagename + "." + context.Code))>@SharedLocalizer["Upgrade"]</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
</Row>
|
||||||
|
</Pager>
|
||||||
|
<button type="button" class="btn btn-success" @onclick="InstallTranslations">@SharedLocalizer["Install"]</button>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<br />
|
||||||
|
<div class="mx-auto text-center">
|
||||||
|
@Localizer["Search.NoResults"]
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
}
|
||||||
|
</TabPanel>
|
||||||
</TabStrip>
|
</TabStrip>
|
||||||
<button type="button" class="btn btn-success" @onclick="SaveModuleDefinition">@SharedLocalizer["Save"]</button>
|
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
@if (_productname != "")
|
||||||
<br />
|
{
|
||||||
<br />
|
<div class="app-actiondialog">
|
||||||
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
|
<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(_packagelicense))
|
||||||
|
{
|
||||||
|
@((MarkupString)_packagelicense)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@SharedLocalizer["License Not Specified"]
|
||||||
|
}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-success" @onclick=@(async () => await DownloadPackage(_packageid))>@SharedLocalizer["Accept"]</button>
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="HideModal">@SharedLocalizer["Cancel"]</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private ElementReference form;
|
private ElementReference form;
|
||||||
private bool validated = false;
|
private bool validated = false;
|
||||||
private int _moduleDefinitionId;
|
private int _moduleDefinitionId;
|
||||||
private string _name;
|
private string _name;
|
||||||
private string _version;
|
private string _description = "";
|
||||||
private string _categories;
|
private string _categories;
|
||||||
private string _moduledefinitionname = "";
|
private string _moduledefinitionname = "";
|
||||||
private string _description = "";
|
private string _version;
|
||||||
private string _owner = "";
|
private string _packagename = "";
|
||||||
private string _url = "";
|
private string _owner = "";
|
||||||
private string _contact = "";
|
private string _url = "";
|
||||||
private string _license = "";
|
private string _contact = "";
|
||||||
private string _runtimes = "";
|
private string _license = "";
|
||||||
private string _permissions;
|
private string _runtimes = "";
|
||||||
private string _createdby;
|
private string _permissions;
|
||||||
private DateTime _createdon;
|
private string _createdby;
|
||||||
private string _modifiedby;
|
private DateTime _createdon;
|
||||||
private DateTime _modifiedon;
|
private string _modifiedby;
|
||||||
|
private DateTime _modifiedon;
|
||||||
|
|
||||||
#pragma warning disable 649
|
#pragma warning disable 649
|
||||||
private PermissionGrid _permissionGrid;
|
private PermissionGrid _permissionGrid;
|
||||||
#pragma warning restore 649
|
#pragma warning restore 649
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
private List<Package> _packages;
|
||||||
|
private List<Language> _languages;
|
||||||
|
private string _productname = "";
|
||||||
|
private string _packagelicense = "";
|
||||||
|
private string _packageid = "";
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_moduleDefinitionId = Int32.Parse(PageState.QueryString["id"]);
|
|
||||||
var moduleDefinition = await ModuleDefinitionService.GetModuleDefinitionAsync(_moduleDefinitionId, ModuleState.SiteId);
|
|
||||||
if (moduleDefinition != null)
|
|
||||||
{
|
|
||||||
_name = moduleDefinition.Name;
|
|
||||||
_version = moduleDefinition.Version;
|
|
||||||
_categories = moduleDefinition.Categories;
|
|
||||||
_moduledefinitionname = moduleDefinition.ModuleDefinitionName;
|
|
||||||
_description = moduleDefinition.Description;
|
|
||||||
_owner = moduleDefinition.Owner;
|
|
||||||
_url = moduleDefinition.Url;
|
|
||||||
_contact = moduleDefinition.Contact;
|
|
||||||
_license = moduleDefinition.License;
|
|
||||||
_runtimes = moduleDefinition.Runtimes;
|
|
||||||
_permissions = moduleDefinition.Permissions;
|
|
||||||
_createdby = moduleDefinition.CreatedBy;
|
|
||||||
_createdon = moduleDefinition.CreatedOn;
|
|
||||||
_modifiedby = moduleDefinition.ModifiedBy;
|
|
||||||
_modifiedon = moduleDefinition.ModifiedOn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Loading ModuleDefinition {ModuleDefinitionId} {Error}", _moduleDefinitionId, ex.Message);
|
|
||||||
AddModuleMessage(Localizer["Error.Module.Load"], MessageType.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SaveModuleDefinition()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
validated = true;
|
try
|
||||||
var interop = new Interop(JSRuntime);
|
{
|
||||||
if (await interop.FormValid(form))
|
_moduleDefinitionId = Int32.Parse(PageState.QueryString["id"]);
|
||||||
{
|
var moduleDefinition = await ModuleDefinitionService.GetModuleDefinitionAsync(_moduleDefinitionId, ModuleState.SiteId);
|
||||||
try
|
if (moduleDefinition != null)
|
||||||
{
|
{
|
||||||
var moduledefinition = await ModuleDefinitionService.GetModuleDefinitionAsync(_moduleDefinitionId, ModuleState.SiteId);
|
_name = moduleDefinition.Name;
|
||||||
if (moduledefinition.Name != _name)
|
_description = moduleDefinition.Description;
|
||||||
{
|
_categories = moduleDefinition.Categories;
|
||||||
moduledefinition.Name = _name;
|
_moduledefinitionname = moduleDefinition.ModuleDefinitionName;
|
||||||
}
|
_version = moduleDefinition.Version;
|
||||||
if (moduledefinition.Description != _description)
|
_packagename = moduleDefinition.PackageName;
|
||||||
{
|
_owner = moduleDefinition.Owner;
|
||||||
moduledefinition.Description = _description;
|
_url = moduleDefinition.Url;
|
||||||
}
|
_contact = moduleDefinition.Contact;
|
||||||
if (moduledefinition.Categories != _categories)
|
_license = moduleDefinition.License;
|
||||||
{
|
_runtimes = moduleDefinition.Runtimes;
|
||||||
moduledefinition.Categories = _categories;
|
_permissions = moduleDefinition.Permissions;
|
||||||
}
|
_createdby = moduleDefinition.CreatedBy;
|
||||||
moduledefinition.Permissions = _permissionGrid.GetPermissions();
|
_createdon = moduleDefinition.CreatedOn;
|
||||||
await ModuleDefinitionService.UpdateModuleDefinitionAsync(moduledefinition);
|
_modifiedby = moduleDefinition.ModifiedBy;
|
||||||
await logger.LogInformation("ModuleDefinition Saved {ModuleDefinition}", moduledefinition);
|
_modifiedon = moduleDefinition.ModifiedOn;
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
|
||||||
}
|
if (!string.IsNullOrEmpty(_packagename))
|
||||||
catch (Exception ex)
|
{
|
||||||
{
|
_packages = await PackageService.GetPackagesAsync("translation", "", "", _packagename);
|
||||||
await logger.LogError(ex, "Error Saving ModuleDefinition {ModuleDefinitionId} {Error}", _moduleDefinitionId, ex.Message);
|
_languages = await LanguageService.GetLanguagesAsync(-1, _packagename);
|
||||||
AddModuleMessage(Localizer["Error.Module.Save"], MessageType.Error);
|
foreach (var package in _packages)
|
||||||
}
|
{
|
||||||
}
|
var code = package.PackageId.Split('.').Last();
|
||||||
else
|
if (!_languages.Any(item => item.Code == code))
|
||||||
{
|
{
|
||||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
_languages.Add(new Language { Code = code, Name = CultureInfo.GetCultureInfo(code).DisplayName, Version = package.Version, IsDefault = true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_languages = _languages.OrderBy(item => item.Name).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Loading ModuleDefinition {ModuleDefinitionId} {Error}", _moduleDefinitionId, ex.Message);
|
||||||
|
AddModuleMessage(Localizer["Error.Module.Load"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SaveModuleDefinition()
|
||||||
|
{
|
||||||
|
validated = true;
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
if (await interop.FormValid(form))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Saving ModuleDefinition {ModuleDefinitionId} {Error}", _moduleDefinitionId, ex.Message);
|
||||||
|
AddModuleMessage(Localizer["Error.Module.Save"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HideModal()
|
||||||
|
{
|
||||||
|
_productname = "";
|
||||||
|
_packagelicense = "";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool UpgradeAvailable(string packagename, string version)
|
||||||
|
{
|
||||||
|
var upgradeavailable = false;
|
||||||
|
if (_packages != null)
|
||||||
|
{
|
||||||
|
var package = _packages.Where(item => item.PackageId == packagename).FirstOrDefault();
|
||||||
|
if (package != null)
|
||||||
|
{
|
||||||
|
upgradeavailable = (Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return upgradeavailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task GetPackage(string packagename)
|
||||||
|
{
|
||||||
|
var version = _packages.Where(item => item.PackageId == packagename).FirstOrDefault().Version;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var package = await PackageService.GetPackageAsync(packagename, version);
|
||||||
|
if (package != null)
|
||||||
|
{
|
||||||
|
_productname = package.Name;
|
||||||
|
if (!string.IsNullOrEmpty(package.License))
|
||||||
|
{
|
||||||
|
_packagelicense = package.License.Replace("\n", "<br />");
|
||||||
|
}
|
||||||
|
_packageid = package.PackageId;
|
||||||
|
}
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Getting Package {PackageId} {Version}", packagename, version);
|
||||||
|
AddModuleMessage(Localizer["Error.Translation.Download"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DownloadPackage(string packagename)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var version = _packages.Where(item => item.PackageId == packagename).FirstOrDefault().Version;
|
||||||
|
await PackageService.DownloadPackageAsync(packagename, version, Constants.PackagesFolder);
|
||||||
|
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", packagename, version);
|
||||||
|
AddModuleMessage(Localizer["Success.Translation.Download"], MessageType.Success);
|
||||||
|
_productname = "";
|
||||||
|
_packagelicense = "";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Downloading Package {PackageId} {Version}", _packagename, _version);
|
||||||
|
AddModuleMessage(Localizer["Error.Translation.Download"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task InstallTranslations()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await PackageService.InstallPackagesAsync();
|
||||||
|
AddModuleMessage(string.Format(Localizer["Success.Translation.Install"], NavigateUrl("admin/system")), MessageType.Success);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Installing Translations");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ else
|
|||||||
<Row>
|
<Row>
|
||||||
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.ModuleDefinitionId.ToString())" ResourceKey="EditModule" /></td>
|
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.ModuleDefinitionId.ToString())" ResourceKey="EditModule" /></td>
|
||||||
<td>
|
<td>
|
||||||
@if (context.AssemblyName != "Oqtane.Client")
|
@if (context.AssemblyName != Constants.ClientId)
|
||||||
{
|
{
|
||||||
<ActionDialog Header="Delete Module" Message="@string.Format(Localizer["Confirm.Module.Delete", context.Name])" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" ResourceKey="DeleteModule" />
|
<ActionDialog Header="Delete Module" Message="@string.Format(Localizer["Confirm.Module.Delete", context.Name])" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" ResourceKey="DeleteModule" />
|
||||||
}
|
}
|
||||||
@ -58,7 +58,7 @@ else
|
|||||||
<td>@context.Name</td>
|
<td>@context.Name</td>
|
||||||
<td>@context.Version</td>
|
<td>@context.Version</td>
|
||||||
<td>
|
<td>
|
||||||
@if(context.AssemblyName == "Oqtane.Client" || PageState.Modules.Where(m => m.ModuleDefinition?.ModuleDefinitionId == context.ModuleDefinitionId).FirstOrDefault() != null)
|
@if (context.AssemblyName == Constants.ClientId || PageState.Modules.Where(m => m.ModuleDefinition?.ModuleDefinitionId == context.ModuleDefinitionId).FirstOrDefault() != null)
|
||||||
{
|
{
|
||||||
<span>@SharedLocalizer["Yes"]</span>
|
<span>@SharedLocalizer["Yes"]</span>
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string _content = string.Empty;
|
private string _content = string.Empty;
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||||
public override string Title => "Export Content";
|
public override string Title => "Export Content";
|
||||||
|
|
||||||
|
|
||||||
@ -27,7 +27,7 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_content = await ModuleService.ExportModuleAsync(ModuleState.ModuleId);
|
_content = await ModuleService.ExportModuleAsync(ModuleState.ModuleId, PageState.Page.PageId);
|
||||||
AddModuleMessage(Localizer["Success.Content.Export"], MessageType.Success);
|
AddModuleMessage(Localizer["Success.Content.Export"], MessageType.Success);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
private ElementReference form;
|
private ElementReference form;
|
||||||
private bool validated = false;
|
private bool validated = false;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||||
public override string Title => "Import Content";
|
public override string Title => "Import Content";
|
||||||
|
|
||||||
private async Task ImportModule()
|
private async Task ImportModule()
|
||||||
@ -38,7 +38,7 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bool success = await ModuleService.ImportModuleAsync(ModuleState.ModuleId, _content);
|
bool success = await ModuleService.ImportModuleAsync(ModuleState.ModuleId, PageState.Page.PageId, _content);
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
AddModuleMessage(Localizer["Success.Content.Import"], MessageType.Success);
|
AddModuleMessage(Localizer["Success.Content.Import"], MessageType.Success);
|
||||||
|
@ -124,37 +124,45 @@
|
|||||||
_containerType = ModuleState.ContainerType;
|
_containerType = ModuleState.ContainerType;
|
||||||
_allPages = ModuleState.AllPages.ToString();
|
_allPages = ModuleState.AllPages.ToString();
|
||||||
_permissions = ModuleState.Permissions;
|
_permissions = ModuleState.Permissions;
|
||||||
_permissionNames = ModuleState.ModuleDefinition.PermissionNames;
|
|
||||||
_pageId = ModuleState.PageId.ToString();
|
_pageId = ModuleState.PageId.ToString();
|
||||||
createdby = ModuleState.CreatedBy;
|
createdby = ModuleState.CreatedBy;
|
||||||
createdon = ModuleState.CreatedOn;
|
createdon = ModuleState.CreatedOn;
|
||||||
modifiedby = ModuleState.ModifiedBy;
|
modifiedby = ModuleState.ModifiedBy;
|
||||||
modifiedon = ModuleState.ModifiedOn;
|
modifiedon = ModuleState.ModifiedOn;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(ModuleState.ModuleDefinition.SettingsType))
|
if (ModuleState.ModuleDefinition != null)
|
||||||
{
|
{
|
||||||
// module settings type explicitly declared in IModule interface
|
_permissionNames = ModuleState.ModuleDefinition?.PermissionNames;
|
||||||
_moduleSettingsType = Type.GetType(ModuleState.ModuleDefinition.SettingsType);
|
|
||||||
|
if (!string.IsNullOrEmpty(ModuleState.ModuleDefinition.SettingsType))
|
||||||
|
{
|
||||||
|
// module settings type explicitly declared in IModule interface
|
||||||
|
_moduleSettingsType = Type.GetType(ModuleState.ModuleDefinition.SettingsType);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// legacy support - module settings type determined by convention ( ie. existence of a "Settings.razor" component in module )
|
||||||
|
_moduleSettingsType = Type.GetType(ModuleState.ModuleDefinition.ControlTypeTemplate.Replace(Constants.ActionToken, PageState.Action), false, true);
|
||||||
|
}
|
||||||
|
if (_moduleSettingsType != null)
|
||||||
|
{
|
||||||
|
var moduleobject = Activator.CreateInstance(_moduleSettingsType) as IModuleControl;
|
||||||
|
if (!string.IsNullOrEmpty(moduleobject.Title))
|
||||||
|
{
|
||||||
|
_moduleSettingsTitle = moduleobject.Title;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModuleSettingsComponent = builder =>
|
||||||
|
{
|
||||||
|
builder.OpenComponent(0, _moduleSettingsType);
|
||||||
|
builder.AddComponentReferenceCapture(1, inst => { _moduleSettings = Convert.ChangeType(inst, _moduleSettingsType); });
|
||||||
|
builder.CloseComponent();
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// legacy support - module settings type determined by convention ( ie. existence of a "Settings.razor" component in module )
|
AddModuleMessage(string.Format(Localizer["Error.Module.Load"], ModuleState.ModuleDefinitionName), MessageType.Error);
|
||||||
_moduleSettingsType = Type.GetType(ModuleState.ModuleDefinition.ControlTypeTemplate.Replace(Constants.ActionToken, PageState.Action), false, true);
|
|
||||||
}
|
|
||||||
if (_moduleSettingsType != null)
|
|
||||||
{
|
|
||||||
var moduleobject = Activator.CreateInstance(_moduleSettingsType) as IModuleControl;
|
|
||||||
if (!string.IsNullOrEmpty(moduleobject.Title))
|
|
||||||
{
|
|
||||||
_moduleSettingsTitle = moduleobject.Title;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModuleSettingsComponent = builder =>
|
|
||||||
{
|
|
||||||
builder.OpenComponent(0, _moduleSettingsType);
|
|
||||||
builder.AddComponentReferenceCapture(1, inst => { _moduleSettings = Convert.ChangeType(inst, _moduleSettingsType); });
|
|
||||||
builder.CloseComponent();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var theme = _themes.FirstOrDefault(item => item.Containers.Any(themecontrol => themecontrol.TypeName.Equals(_containerType)));
|
var theme = _themes.FirstOrDefault(item => item.Containers.Any(themecontrol => themecontrol.TypeName.Equals(_containerType)));
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="parent" class="form-select" @onchange="(e => ParentChanged(e))" required>
|
<select id="parent" class="form-select" @onchange="(e => ParentChanged(e))" required>
|
||||||
<option value="-1"><@Localizer["SiteRoot"]></option>
|
<option value="-1"><@Localizer["SiteRoot"]></option>
|
||||||
@foreach (Page page in _pageList)
|
@foreach (Page page in PageState.Pages)
|
||||||
{
|
{
|
||||||
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
||||||
}
|
}
|
||||||
@ -167,7 +167,6 @@
|
|||||||
private List<Theme> _themeList;
|
private List<Theme> _themeList;
|
||||||
private List<ThemeControl> _themes = new List<ThemeControl>();
|
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
private List<Page> _pageList;
|
|
||||||
private string _name;
|
private string _name;
|
||||||
private string _title;
|
private string _title;
|
||||||
private string _meta;
|
private string _meta;
|
||||||
@ -201,7 +200,6 @@
|
|||||||
_themetype = PageState.Site.DefaultThemeType;
|
_themetype = PageState.Site.DefaultThemeType;
|
||||||
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
||||||
_containertype = PageState.Site.DefaultContainerType;
|
_containertype = PageState.Site.DefaultContainerType;
|
||||||
_pageList = PageState.Pages;
|
|
||||||
_children = PageState.Pages.Where(item => item.ParentId == null).ToList();
|
_children = PageState.Pages.Where(item => item.ParentId == null).ToList();
|
||||||
_permissions = string.Empty;
|
_permissions = string.Empty;
|
||||||
ThemeSettings();
|
ThemeSettings();
|
||||||
@ -307,6 +305,10 @@
|
|||||||
}
|
}
|
||||||
if (_path.Contains("/"))
|
if (_path.Contains("/"))
|
||||||
{
|
{
|
||||||
|
if (_path.EndsWith("/") && _path != "/")
|
||||||
|
{
|
||||||
|
_path = _path.Substring(0, _path.Length - 1);
|
||||||
|
}
|
||||||
_path = _path.Substring(_path.LastIndexOf("/") + 1);
|
_path = _path.Substring(_path.LastIndexOf("/") + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,15 +331,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(PagePathIsDeleted(page.Path, page.SiteId, _pageList))
|
var _pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
|
||||||
|
if (_pages.Any(item => item.Path == page.Path))
|
||||||
{
|
{
|
||||||
AddModuleMessage(string.Format(Localizer["Message.Page.Deleted"], _path), MessageType.Warning);
|
AddModuleMessage(string.Format(Localizer["Message.Page.Exists"], _path), MessageType.Warning);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PagePathIsUnique(page.Path, page.SiteId, _pageList))
|
if (page.ParentId == null && Constants.ReservedRoutes.Contains(page.Name.ToLower()))
|
||||||
{
|
{
|
||||||
AddModuleMessage(string.Format(Localizer["Message.Page.Exists"], _path), MessageType.Warning);
|
AddModuleMessage(string.Format(Localizer["Message.Page.Reserved"], page.Name), MessageType.Warning);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,14 +424,4 @@
|
|||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool PagePathIsUnique(string pagePath, int siteId, List<Page> existingPages)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="parent" class="form-select" value="@_parentid" @onchange="(e => ParentChanged(e))" required>
|
<select id="parent" class="form-select" value="@_parentid" @onchange="(e => ParentChanged(e))" required>
|
||||||
<option value="-1"><@Localizer["SiteRoot"]></option>
|
<option value="-1"><@Localizer["SiteRoot"]></option>
|
||||||
@foreach (Page page in _pageList)
|
@foreach (Page page in PageState.Pages)
|
||||||
{
|
{
|
||||||
if (page.PageId != _pageId)
|
if (page.PageId != _pageId)
|
||||||
{
|
{
|
||||||
@ -201,7 +201,6 @@
|
|||||||
private List<Theme> _themeList;
|
private List<Theme> _themeList;
|
||||||
private List<ThemeControl> _themes = new List<ThemeControl>();
|
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
private List<Page> _pageList;
|
|
||||||
private List<Module> _pageModules;
|
private List<Module> _pageModules;
|
||||||
private int _pageId;
|
private int _pageId;
|
||||||
private string _name;
|
private string _name;
|
||||||
@ -238,7 +237,6 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_pageList = PageState.Pages;
|
|
||||||
_children = PageState.Pages.Where(item => item.ParentId == null).ToList();
|
_children = PageState.Pages.Where(item => item.ParentId == null).ToList();
|
||||||
_themeList = await ThemeService.GetThemesAsync();
|
_themeList = await ThemeService.GetThemesAsync();
|
||||||
_themes = ThemeService.GetThemeControls(_themeList);
|
_themes = ThemeService.GetThemeControls(_themeList);
|
||||||
@ -435,6 +433,10 @@
|
|||||||
}
|
}
|
||||||
if (_path.Contains("/"))
|
if (_path.Contains("/"))
|
||||||
{
|
{
|
||||||
|
if (_path.EndsWith("/") && _path != "/")
|
||||||
|
{
|
||||||
|
_path = _path.Substring(0, _path.Length - 1);
|
||||||
|
}
|
||||||
_path = _path.Substring(_path.LastIndexOf("/") + 1);
|
_path = _path.Substring(_path.LastIndexOf("/") + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -457,12 +459,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PagePathIsUnique(page.Path, page.SiteId, page.PageId, _pageList))
|
var _pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
|
||||||
|
if (_pages.Any(item => item.Path == page.Path && item.PageId != page.PageId))
|
||||||
{
|
{
|
||||||
AddModuleMessage(string.Format(Localizer["Mesage.Page.PathExists"], _path), MessageType.Warning);
|
AddModuleMessage(string.Format(Localizer["Mesage.Page.PathExists"], _path), MessageType.Warning);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (page.ParentId == null && Constants.ReservedRoutes.Contains(page.Name.ToLower()))
|
||||||
|
{
|
||||||
|
AddModuleMessage(string.Format(Localizer["Message.Page.Reserved"], page.Name), MessageType.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (_insert != "=")
|
if (_insert != "=")
|
||||||
{
|
{
|
||||||
Page child;
|
Page child;
|
||||||
@ -567,9 +576,4 @@
|
|||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool PagePathIsUnique(string pagePath, int siteId, int pageId, List<Page> existingPages)
|
|
||||||
{
|
|
||||||
return !existingPages.Any(page => page.SiteId == siteId && page.Path == pagePath && page.PageId != pageId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,75 +7,77 @@
|
|||||||
@inject IStringLocalizer<Index> Localizer
|
@inject IStringLocalizer<Index> Localizer
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
|
||||||
<TabStrip>
|
@if (_pages == null || _modules == null)
|
||||||
<TabPanel Name="Pages" ResourceKey="Pages">
|
{
|
||||||
@if (_pages == null)
|
<p><em>@SharedLocalizer["Loading"]</em></p>
|
||||||
{
|
}
|
||||||
<br />
|
else
|
||||||
<p>@Localizer["NoPage.Deleted"]</p>
|
{
|
||||||
}
|
<TabStrip>
|
||||||
else
|
<TabPanel Name="Pages" ResourceKey="Pages">
|
||||||
{
|
@if (!_pages.Where(item => item.IsDeleted).Any())
|
||||||
<Pager Items="@_pages">
|
{
|
||||||
<Header>
|
<br />
|
||||||
<th style="width: 1px;"> </th>
|
<p>@Localizer["NoPage.Deleted"]</p>
|
||||||
<th style="width: 1px;"> </th>
|
}
|
||||||
<th>@SharedLocalizer["Name"]</th>
|
else
|
||||||
<th>@Localizer["DeletedBy"]</th>
|
{
|
||||||
<th>@Localizer["DeletedOn"]</th>
|
<Pager Items="@_pages.Where(item => item.IsDeleted)">
|
||||||
</Header>
|
<Header>
|
||||||
<Row>
|
<th style="width: 1px;"> </th>
|
||||||
<td><button type="button" @onclick="@(() => RestorePage(context))" class="btn btn-success" title="Restore">Restore</button></td>
|
<th style="width: 1px;"> </th>
|
||||||
<td><ActionDialog Header="Delete Page" Message="@string.Format(Localizer["Confirm.Page.Delete"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeletePage(context))" ResourceKey="DeletePage" /></td>
|
<th>@SharedLocalizer["Name"]</th>
|
||||||
<td>@context.Name</td>
|
<th>@Localizer["DeletedBy"]</th>
|
||||||
<td>@context.DeletedBy</td>
|
<th>@Localizer["DeletedOn"]</th>
|
||||||
<td>@context.DeletedOn</td>
|
</Header>
|
||||||
</Row>
|
<Row>
|
||||||
</Pager>
|
<td><button type="button" @onclick="@(() => RestorePage(context))" class="btn btn-success" title="Restore">Restore</button></td>
|
||||||
@if (_pages.Any())
|
<td><ActionDialog Header="Delete Page" Message="@string.Format(Localizer["Confirm.Page.Delete"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeletePage(context))" ResourceKey="DeletePage" /></td>
|
||||||
{
|
<td>@context.Name</td>
|
||||||
<br /><ActionDialog Header="Delete All Pages" Message="Are You Sure You Wish To Permanently Delete All Pages?" Action="Delete All Pages" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteAllPages())" ResourceKey="DeleteAllPages" />
|
<td>@context.DeletedBy</td>
|
||||||
}
|
<td>@context.DeletedOn</td>
|
||||||
}
|
</Row>
|
||||||
</TabPanel>
|
</Pager>
|
||||||
<TabPanel Name="Modules" ResourceKey="Modules">
|
<br />
|
||||||
@if (_modules == null)
|
<ActionDialog Header="Remove All Deleted Pages" Message="Are You Sure You Wish To Permanently Remove All Deleted Pages?" Action="Remove All Deleted Pages" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteAllPages())" ResourceKey="DeleteAllPages" />
|
||||||
{
|
}
|
||||||
<br />
|
</TabPanel>
|
||||||
<p>@Localizer["NoModule.Deleted"]</p>
|
<TabPanel Name="Modules" ResourceKey="Modules">
|
||||||
}
|
@if (!_modules.Where(item => item.IsDeleted).Any())
|
||||||
else
|
{
|
||||||
{
|
<br />
|
||||||
<Pager Items="@_modules">
|
<p>@Localizer["NoModule.Deleted"]</p>
|
||||||
<Header>
|
}
|
||||||
<th style="width: 1px;"> </th>
|
else
|
||||||
<th style="width: 1px;"> </th>
|
{
|
||||||
<th>@Localizer["Page"]</th>
|
<Pager Items="@_modules.Where(item => item.IsDeleted)">
|
||||||
<th>@Localizer["Module"]</th>
|
<Header>
|
||||||
<th>@Localizer["DeletedBy"]</th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>@Localizer["DeletedOn"]</th>
|
<th style="width: 1px;"> </th>
|
||||||
</Header>
|
<th>@Localizer["Page"]</th>
|
||||||
<Row>
|
<th>@Localizer["Module"]</th>
|
||||||
<td><button type="button" @onclick="@(() => RestoreModule(context))" class="btn btn-success" title="Restore">@Localizer["Restore"]</button></td>
|
<th>@Localizer["DeletedBy"]</th>
|
||||||
<td><ActionDialog Header="Delete Module" Message="@string.Format(Localizer["Confirm.Module.Delete"], context.Title)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" ResourceKey="DeleteModule" /></td>
|
<th>@Localizer["DeletedOn"]</th>
|
||||||
<td>@PageState.Pages.Find(item => item.PageId == context.PageId).Name</td>
|
</Header>
|
||||||
<td>@context.Title</td>
|
<Row>
|
||||||
<td>@context.DeletedBy</td>
|
<td><button type="button" @onclick="@(() => RestoreModule(context))" class="btn btn-success" title="Restore">@Localizer["Restore"]</button></td>
|
||||||
<td>@context.DeletedOn</td>
|
<td><ActionDialog Header="Delete Module" Message="@string.Format(Localizer["Confirm.Module.Delete"], context.Title)" Action="Delete" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteModule(context))" ResourceKey="DeleteModule" /></td>
|
||||||
</Row>
|
<td>@_pages.Find(item => item.PageId == context.PageId).Name</td>
|
||||||
</Pager>
|
<td>@context.Title</td>
|
||||||
@if (_modules.Any())
|
<td>@context.DeletedBy</td>
|
||||||
{
|
<td>@context.DeletedOn</td>
|
||||||
<br /><ActionDialog Header="Delete All Modules" Message="Are You Sure You Wish To Permanently Delete All Modules?" Action="Delete All Modules" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteAllModules())" ResourceKey="DeleteAllModules" />
|
</Row>
|
||||||
}
|
</Pager>
|
||||||
|
<br />
|
||||||
}
|
<ActionDialog Header="Remove All Deleted Modules" Message="Are You Sure You Wish To Permanently Remove All Deleted Modules?" Action="Remove All Deleted Modules" Security="SecurityAccessLevel.Admin" Class="btn btn-danger" OnClick="@(async () => await DeleteAllModules())" ResourceKey="DeleteAllModules" />
|
||||||
</TabPanel>
|
}
|
||||||
</TabStrip>
|
</TabPanel>
|
||||||
|
</TabStrip>
|
||||||
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<Page> _pages;
|
private List<Page> _pages;
|
||||||
private List<Module> _modules;
|
private List<Module> _modules;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
|
|
||||||
@ -95,10 +97,7 @@
|
|||||||
private async Task Load()
|
private async Task Load()
|
||||||
{
|
{
|
||||||
_pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
|
_pages = await PageService.GetPagesAsync(PageState.Site.SiteId);
|
||||||
_pages = _pages.Where(item => item.IsDeleted).ToList();
|
|
||||||
|
|
||||||
_modules = await ModuleService.GetModulesAsync(PageState.Site.SiteId);
|
_modules = await ModuleService.GetModulesAsync(PageState.Site.SiteId);
|
||||||
_modules = _modules.Where(item => item.IsDeleted).ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RestorePage(Page page)
|
private async Task RestorePage(Page page)
|
||||||
@ -140,7 +139,8 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (Page page in _pages)
|
ModuleInstance.ShowProgressIndicator();
|
||||||
|
foreach (Page page in _pages.Where(item => item.IsDeleted))
|
||||||
{
|
{
|
||||||
await PageService.DeletePageAsync(page.PageId);
|
await PageService.DeletePageAsync(page.PageId);
|
||||||
await logger.LogInformation("Page Permanently Deleted {Page}", page);
|
await logger.LogInformation("Page Permanently Deleted {Page}", page);
|
||||||
@ -148,6 +148,7 @@
|
|||||||
|
|
||||||
await logger.LogInformation("Pages Permanently Deleted");
|
await logger.LogInformation("Pages Permanently Deleted");
|
||||||
await Load();
|
await Load();
|
||||||
|
ModuleInstance.HideProgressIndicator();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
}
|
}
|
||||||
@ -155,6 +156,7 @@
|
|||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Permanently Deleting Pages {Error}", ex.Message);
|
await logger.LogError(ex, "Error Permanently Deleting Pages {Error}", ex.Message);
|
||||||
AddModuleMessage(ex.Message, MessageType.Error);
|
AddModuleMessage(ex.Message, MessageType.Error);
|
||||||
|
ModuleInstance.HideProgressIndicator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,9 +183,8 @@
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await PageModuleService.DeletePageModuleAsync(module.PageModuleId);
|
await PageModuleService.DeletePageModuleAsync(module.PageModuleId);
|
||||||
// check if there are any remaining module instances in the site
|
|
||||||
_modules = await ModuleService.GetModulesAsync(PageState.Site.SiteId);
|
|
||||||
|
|
||||||
|
// check if there are any remaining module instances in the site
|
||||||
if (!_modules.Exists(item => item.ModuleId == module.ModuleId))
|
if (!_modules.Exists(item => item.ModuleId == module.ModuleId))
|
||||||
{
|
{
|
||||||
await ModuleService.DeleteModuleAsync(module.ModuleId);
|
await ModuleService.DeleteModuleAsync(module.ModuleId);
|
||||||
@ -204,12 +205,12 @@
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (Module module in _modules)
|
ModuleInstance.ShowProgressIndicator();
|
||||||
|
foreach (Module module in _modules.Where(item => item.IsDeleted))
|
||||||
{
|
{
|
||||||
await PageModuleService.DeletePageModuleAsync(module.PageModuleId);
|
await PageModuleService.DeletePageModuleAsync(module.PageModuleId);
|
||||||
// check if there are any remaining module instances in the site
|
|
||||||
_modules = await ModuleService.GetModulesAsync(PageState.Site.SiteId);
|
|
||||||
|
|
||||||
|
// check if there are any remaining module instances in the site
|
||||||
if (!_modules.Exists(item => item.ModuleId == module.ModuleId))
|
if (!_modules.Exists(item => item.ModuleId == module.ModuleId))
|
||||||
{
|
{
|
||||||
await ModuleService.DeleteModuleAsync(module.ModuleId);
|
await ModuleService.DeleteModuleAsync(module.ModuleId);
|
||||||
@ -218,12 +219,14 @@
|
|||||||
|
|
||||||
await logger.LogInformation("Modules Permanently Deleted");
|
await logger.LogInformation("Modules Permanently Deleted");
|
||||||
await Load();
|
await Load();
|
||||||
|
ModuleInstance.HideProgressIndicator();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Permanently Deleting Modules {Error}", ex.Message);
|
await logger.LogError(ex, "Error Permanently Deleting Modules {Error}", ex.Message);
|
||||||
AddModuleMessage(Localizer["Error.Modules.Delete"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.Modules.Delete"], MessageType.Error);
|
||||||
|
ModuleInstance.HideProgressIndicator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,21 @@
|
|||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="homepage" HelpText="Select the home page for the site (to be used if there is no page with a path of '/')" ResourceKey="HomePage">Home Page: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="homepage" class="form-select" @bind="@_homepageid" required>
|
||||||
|
<option value="-"><@Localizer["Not Specified"]></option>
|
||||||
|
@foreach (Page page in PageState.Pages)
|
||||||
|
{
|
||||||
|
if (UserSecurity.ContainsRole(page.Permissions, PermissionNames.View, RoleNames.Everyone))
|
||||||
|
{
|
||||||
|
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="isDeleted" HelpText="Is this site deleted?" ResourceKey="IsDeleted">Deleted? </Label>
|
<Label Class="col-sm-3" For="isDeleted" HelpText="Is this site deleted?" ResourceKey="IsDeleted">Deleted? </Label>
|
||||||
@ -228,6 +243,7 @@
|
|||||||
<select id="runtime" class="form-select" @bind="@_runtime" required>
|
<select id="runtime" class="form-select" @bind="@_runtime" required>
|
||||||
<option value="Server">@SharedLocalizer["BlazorServer"]</option>
|
<option value="Server">@SharedLocalizer["BlazorServer"]</option>
|
||||||
<option value="WebAssembly">@SharedLocalizer["BlazorWebAssembly"]</option>
|
<option value="WebAssembly">@SharedLocalizer["BlazorWebAssembly"]</option>
|
||||||
|
<option value="Hybrid">@SharedLocalizer["BlazorHybrid"]</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -295,6 +311,7 @@
|
|||||||
private string _themetype = "-";
|
private string _themetype = "-";
|
||||||
private string _containertype = "-";
|
private string _containertype = "-";
|
||||||
private string _admincontainertype = "-";
|
private string _admincontainertype = "-";
|
||||||
|
private string _homepageid = "-";
|
||||||
private string _smtphost = string.Empty;
|
private string _smtphost = string.Empty;
|
||||||
private string _smtpport = string.Empty;
|
private string _smtpport = string.Empty;
|
||||||
private string _smtpssl = "False";
|
private string _smtpssl = "False";
|
||||||
@ -353,6 +370,11 @@
|
|||||||
_containertype = (!string.IsNullOrEmpty(site.DefaultContainerType)) ? site.DefaultContainerType : Constants.DefaultContainer;
|
_containertype = (!string.IsNullOrEmpty(site.DefaultContainerType)) ? site.DefaultContainerType : Constants.DefaultContainer;
|
||||||
_admincontainertype = (!string.IsNullOrEmpty(site.AdminContainerType)) ? site.AdminContainerType : Constants.DefaultAdminContainer;
|
_admincontainertype = (!string.IsNullOrEmpty(site.AdminContainerType)) ? site.AdminContainerType : Constants.DefaultAdminContainer;
|
||||||
|
|
||||||
|
if (site.HomePageId != null)
|
||||||
|
{
|
||||||
|
_homepageid = site.HomePageId.Value.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
_pwaisenabled = site.PwaIsEnabled.ToString();
|
_pwaisenabled = site.PwaIsEnabled.ToString();
|
||||||
if (site.PwaAppIconFileId != null)
|
if (site.PwaAppIconFileId != null)
|
||||||
{
|
{
|
||||||
@ -479,6 +501,7 @@
|
|||||||
refresh = true; // needs to be refreshed on client
|
refresh = true; // needs to be refreshed on client
|
||||||
}
|
}
|
||||||
site.AdminContainerType = _admincontainertype;
|
site.AdminContainerType = _admincontainertype;
|
||||||
|
site.HomePageId = (_homepageid != "-" ? int.Parse(_homepageid) : null);
|
||||||
|
|
||||||
if (site.PwaIsEnabled.ToString() != _pwaisenabled)
|
if (site.PwaIsEnabled.ToString() != _pwaisenabled)
|
||||||
{
|
{
|
||||||
@ -557,8 +580,8 @@
|
|||||||
await AliasService.DeleteAliasAsync(alias.AliasId);
|
await AliasService.DeleteAliasAsync(alias.AliasId);
|
||||||
}
|
}
|
||||||
|
|
||||||
aliases = await AliasService.GetAliasesAsync();
|
var redirect = aliases.First(item => item.SiteId != PageState.Site.SiteId || item.TenantId != PageState.Site.TenantId);
|
||||||
NavigationManager.NavigateTo(PageState.Uri.Scheme + "://" + aliases.First().Name, true);
|
NavigationManager.NavigateTo(PageState.Uri.Scheme + "://" + redirect.Name, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@ else
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<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>
|
<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)." ResourceKey="Aliases">Aliases: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<textarea id="alias" class="form-control" @bind="@_urls" rows="3" required></textarea>
|
<textarea id="alias" class="form-control" @bind="@_urls" rows="3" required></textarea>
|
||||||
</div>
|
</div>
|
||||||
@ -89,7 +89,8 @@ else
|
|||||||
<select id="runtime" class="form-select" @bind="@_runtime" required>
|
<select id="runtime" class="form-select" @bind="@_runtime" required>
|
||||||
<option value="Server">@SharedLocalizer["BlazorServer"]</option>
|
<option value="Server">@SharedLocalizer["BlazorServer"]</option>
|
||||||
<option value="WebAssembly">@SharedLocalizer["BlazorWebAssembly"]</option>
|
<option value="WebAssembly">@SharedLocalizer["BlazorWebAssembly"]</option>
|
||||||
</select>
|
<option value="Hybrid">@SharedLocalizer["BlazorHybrid"]</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
@ -128,18 +129,43 @@ else
|
|||||||
<div class="row mb-1 align-items-center">
|
<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>
|
<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">
|
<div class="col-sm-9">
|
||||||
<select id="databaseType" class="form-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))" required>
|
@if (_databases != null)
|
||||||
@foreach (var database in _databases)
|
{
|
||||||
{
|
<div class="input-group">
|
||||||
<option value="@database.Name">@Localizer[@database.Name]</option>
|
<select id="databaseType" class="form-select" value="@_databaseName" @onchange="(e => DatabaseChanged(e))" required>
|
||||||
}
|
@foreach (var database in _databases)
|
||||||
</select>
|
{
|
||||||
</div>
|
<option value="@database.Name">@Localizer[@database.Name]</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
@if (!_showConnectionString)
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="ToggleConnectionString">@Localizer["EnterConnectionString"]</button>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="ToggleConnectionString">@Localizer["EnterConnectionParameters"]</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
if (_databaseConfigType != null)
|
@if (!_showConnectionString)
|
||||||
{
|
{
|
||||||
@DatabaseConfigComponent;
|
if (_databaseConfigType != null)
|
||||||
}
|
{
|
||||||
|
@DatabaseConfigComponent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="connectionstring" HelpText="Enter a complete connection string including all parameters and delimiters" ResourceKey="ConnectionString">String:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea id="connectionstring" class="form-control" @bind="@_connectionString" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="hostUsername" HelpText="Enter the username of an existing host user" ResourceKey="HostUsername">Host Username:</Label>
|
<Label Class="col-sm-3" For="hostUsername" HelpText="Enter the username of an existing host user" ResourceKey="HostUsername">Host Username:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
@ -169,6 +195,8 @@ else
|
|||||||
private Type _databaseConfigType;
|
private Type _databaseConfigType;
|
||||||
private object _databaseConfig;
|
private object _databaseConfig;
|
||||||
private RenderFragment DatabaseConfigComponent { get; set; }
|
private RenderFragment DatabaseConfigComponent { get; set; }
|
||||||
|
private bool _showConnectionString = false;
|
||||||
|
private string _connectionString = string.Empty;
|
||||||
|
|
||||||
private List<Theme> _themeList;
|
private List<Theme> _themeList;
|
||||||
private List<ThemeControl> _themes = new List<ThemeControl>();
|
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||||
@ -218,7 +246,7 @@ else
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_databaseName = (string)eventArgs.Value;
|
_databaseName = (string)eventArgs.Value;
|
||||||
|
_showConnectionString = false;
|
||||||
LoadDatabaseConfigComponent();
|
LoadDatabaseConfigComponent();
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -309,15 +337,22 @@ else
|
|||||||
user.Username = _hostusername;
|
user.Username = _hostusername;
|
||||||
user.Password = _hostpassword;
|
user.Password = _hostpassword;
|
||||||
user.LastIPAddress = PageState.RemoteIPAddress;
|
user.LastIPAddress = PageState.RemoteIPAddress;
|
||||||
user = await UserService.LoginUserAsync(user);
|
user = await UserService.LoginUserAsync(user, false, false);
|
||||||
if (user.IsAuthenticated)
|
if (user.IsAuthenticated)
|
||||||
{
|
{
|
||||||
var connectionString = String.Empty;
|
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
||||||
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
var connectionString = String.Empty;
|
||||||
{
|
if (_showConnectionString)
|
||||||
connectionString = databaseConfigControl.GetConnectionString();
|
{
|
||||||
}
|
connectionString = _connectionString;
|
||||||
var database = _databases.SingleOrDefault(d => d.Name == _databaseName);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
||||||
|
{
|
||||||
|
connectionString = databaseConfigControl.GetConnectionString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (connectionString != "")
|
if (connectionString != "")
|
||||||
{
|
{
|
||||||
@ -398,4 +433,13 @@ else
|
|||||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ToggleConnectionString()
|
||||||
|
{
|
||||||
|
if (_databaseConfig is IDatabaseConfigControl databaseConfigControl)
|
||||||
|
{
|
||||||
|
_connectionString = databaseConfigControl.GetConnectionString();
|
||||||
|
}
|
||||||
|
_showConnectionString = !_showConnectionString;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,13 @@
|
|||||||
<input id="ipaddress" class="form-control" @bind="@_ipaddress" readonly />
|
<input id="ipaddress" class="form-control" @bind="@_ipaddress" readonly />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="environment" HelpText="Environment name" ResourceKey="Environment">Environment: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="environment" class="form-control" @bind="@_environment" readonly />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="contentrootpath" HelpText="Root Path" ResourceKey="ContentRootPath">Root Path: </Label>
|
<Label Class="col-sm-3" For="contentrootpath" HelpText="Root Path" ResourceKey="ContentRootPath">Root Path: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="contentrootpath" class="form-control" @bind="@_contentrootpath" readonly />
|
<input id="contentrootpath" class="form-control" @bind="@_contentrootpath" readonly />
|
||||||
@ -152,6 +158,7 @@
|
|||||||
private string _osversion = string.Empty;
|
private string _osversion = string.Empty;
|
||||||
private string _machinename = string.Empty;
|
private string _machinename = string.Empty;
|
||||||
private string _ipaddress = string.Empty;
|
private string _ipaddress = string.Empty;
|
||||||
|
private string _environment = string.Empty;
|
||||||
private string _contentrootpath = string.Empty;
|
private string _contentrootpath = string.Empty;
|
||||||
private string _webrootpath = string.Empty;
|
private string _webrootpath = string.Empty;
|
||||||
private string _servertime = string.Empty;
|
private string _servertime = string.Empty;
|
||||||
@ -176,6 +183,7 @@
|
|||||||
_osversion = systeminfo["OSVersion"].ToString();
|
_osversion = systeminfo["OSVersion"].ToString();
|
||||||
_machinename = systeminfo["MachineName"].ToString();
|
_machinename = systeminfo["MachineName"].ToString();
|
||||||
_ipaddress = systeminfo["IPAddress"].ToString();
|
_ipaddress = systeminfo["IPAddress"].ToString();
|
||||||
|
_environment = systeminfo["Environment"].ToString();
|
||||||
_contentrootpath = systeminfo["ContentRootPath"].ToString();
|
_contentrootpath = systeminfo["ContentRootPath"].ToString();
|
||||||
_webrootpath = systeminfo["WebRootPath"].ToString();
|
_webrootpath = systeminfo["WebRootPath"].ToString();
|
||||||
_servertime = systeminfo["ServerTime"].ToString() + " UTC";
|
_servertime = systeminfo["ServerTime"].ToString() + " UTC";
|
||||||
|
@ -114,6 +114,10 @@
|
|||||||
<button type="button" class="btn btn-success" @onclick="InstallThemes">@SharedLocalizer["Install"]</button>
|
<button type="button" class="btn btn-success" @onclick="InstallThemes">@SharedLocalizer["Install"]</button>
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<ModuleMessage Type="MessageType.Info" Message="@SharedLocalizer["Oqtane.Marketplace"]" />
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<Package> _packages;
|
private List<Package> _packages;
|
||||||
private string _price = "free";
|
private string _price = "free";
|
||||||
|
@ -29,7 +29,7 @@ else
|
|||||||
<Row>
|
<Row>
|
||||||
<td><ActionLink Action="View" Parameters="@($"name=" + WebUtility.UrlEncode(context.ThemeName))" ResourceKey="ViewTheme" /></td>
|
<td><ActionLink Action="View" Parameters="@($"name=" + WebUtility.UrlEncode(context.ThemeName))" ResourceKey="ViewTheme" /></td>
|
||||||
<td>
|
<td>
|
||||||
@if (context.AssemblyName != "Oqtane.Client")
|
@if (context.AssemblyName != Constants.ClientId)
|
||||||
{
|
{
|
||||||
<ActionDialog Header="Delete Theme" Message="@string.Format(Localizer["Confirm.Theme.Delete"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteTheme(context))" ResourceKey="DeleteTheme" />
|
<ActionDialog Header="Delete Theme" Message="@string.Format(Localizer["Confirm.Theme.Delete"], context.Name)" Action="Delete" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await DeleteTheme(context))" ResourceKey="DeleteTheme" />
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,13 @@
|
|||||||
<input id="version" class="form-control" @bind="@_version" disabled />
|
<input id="version" class="form-control" @bind="@_version" disabled />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="packagename" HelpText="The unique name of the package from which this module was installed" ResourceKey="PackageName">Package Name: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="packagename" class="form-control" @bind="@_packagename" disabled />
|
||||||
|
</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>
|
<Label Class="col-sm-3" For="owner" HelpText="The owner or creator of the theme" ResourceKey="Owner">Owner: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="owner" class="form-control" @bind="@_owner" disabled />
|
<input id="owner" class="form-control" @bind="@_owner" disabled />
|
||||||
@ -53,28 +59,30 @@
|
|||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string _themeName = "";
|
private string _themeName = "";
|
||||||
private string _name;
|
private string _name;
|
||||||
private string _version;
|
private string _version;
|
||||||
private string _owner = "";
|
private string _packagename;
|
||||||
private string _url = "";
|
private string _owner = "";
|
||||||
private string _contact = "";
|
private string _url = "";
|
||||||
private string _license = "";
|
private string _contact = "";
|
||||||
|
private string _license = "";
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_themeName = WebUtility.UrlDecode(PageState.QueryString["name"]);
|
_themeName = WebUtility.UrlDecode(PageState.QueryString["name"]);
|
||||||
var themes = await ThemeService.GetThemesAsync();
|
var themes = await ThemeService.GetThemesAsync();
|
||||||
var theme = themes.FirstOrDefault(item => item.ThemeName == _themeName);
|
var theme = themes.FirstOrDefault(item => item.ThemeName == _themeName);
|
||||||
if (theme != null)
|
if (theme != null)
|
||||||
{
|
{
|
||||||
_name = theme.Name;
|
_name = theme.Name;
|
||||||
_version = theme.Version;
|
_version = theme.Version;
|
||||||
_owner = theme.Owner;
|
_packagename = theme.PackageName;
|
||||||
|
_owner = theme.Owner;
|
||||||
_url = theme.Url;
|
_url = theme.Url;
|
||||||
_contact = theme.Contact;
|
_contact = theme.Contact;
|
||||||
_license = theme.License;
|
_license = theme.License;
|
||||||
|
@ -226,8 +226,8 @@ else
|
|||||||
@code {
|
@code {
|
||||||
private string username = string.Empty;
|
private string username = string.Empty;
|
||||||
private string _password = string.Empty;
|
private string _password = string.Empty;
|
||||||
private string _passwordtype = "password";
|
private string _passwordtype = "password";
|
||||||
private string _togglepassword = string.Empty;
|
private string _togglepassword = string.Empty;
|
||||||
private string confirm = string.Empty;
|
private string confirm = string.Empty;
|
||||||
private bool allowtwofactor = false;
|
private bool allowtwofactor = false;
|
||||||
private string twofactor = "False";
|
private string twofactor = "False";
|
||||||
@ -429,6 +429,7 @@ else
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
ModuleInstance.ShowProgressIndicator();
|
||||||
foreach(var Notification in notifications)
|
foreach(var Notification in notifications)
|
||||||
{
|
{
|
||||||
if (!Notification.IsDeleted)
|
if (!Notification.IsDeleted)
|
||||||
@ -444,12 +445,15 @@ else
|
|||||||
}
|
}
|
||||||
await logger.LogInformation("Notifications Permanently Deleted");
|
await logger.LogInformation("Notifications Permanently Deleted");
|
||||||
await LoadNotificationsAsync();
|
await LoadNotificationsAsync();
|
||||||
|
ModuleInstance.HideProgressIndicator();
|
||||||
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Deleting Notifications {Error}", ex.Message);
|
await logger.LogError(ex, "Error Deleting Notifications {Error}", ex.Message);
|
||||||
AddModuleMessage(ex.Message, MessageType.Error);
|
AddModuleMessage(ex.Message, MessageType.Error);
|
||||||
|
ModuleInstance.HideProgressIndicator();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
@inject ISiteService SiteService
|
@inject ISiteService SiteService
|
||||||
@inject IStringLocalizer<Index> Localizer
|
@inject IStringLocalizer<Index> Localizer
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
@inject SiteState SiteState
|
|
||||||
|
|
||||||
@if (users == null)
|
@if (users == null)
|
||||||
{
|
{
|
||||||
@ -287,6 +286,15 @@ else
|
|||||||
<input id="emailclaimtype" class="form-control" @bind="@_emailclaimtype" />
|
<input id="emailclaimtype" class="form-control" @bind="@_emailclaimtype" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@if (_providertype == AuthenticationProviderTypes.OpenIDConnect)
|
||||||
|
{
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="roleclaimtype" HelpText="The name of the role claim provided by the provider" ResourceKey="RoleClaimType">Role Claim:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="roleclaimtype" class="form-control" @bind="@_roleclaimtype" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="domainfilter" HelpText="Provide any email domain filter criteria (separated by commas). Domains to exclude should be prefixed with an exclamation point (!). For example 'microsoft.com,!hotmail.com' would include microsoft.com email addresses but not hotmail.com email addresses." ResourceKey="DomainFilter">Domain Filter:</Label>
|
<Label Class="col-sm-3" For="domainfilter" HelpText="Provide any email domain filter criteria (separated by commas). Domains to exclude should be prefixed with an exclamation point (!). For example 'microsoft.com,!hotmail.com' would include microsoft.com email addresses but not hotmail.com email addresses." ResourceKey="DomainFilter">Domain Filter:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
@ -386,6 +394,7 @@ else
|
|||||||
private string _redirecturl;
|
private string _redirecturl;
|
||||||
private string _identifierclaimtype;
|
private string _identifierclaimtype;
|
||||||
private string _emailclaimtype;
|
private string _emailclaimtype;
|
||||||
|
private string _roleclaimtype;
|
||||||
private string _domainfilter;
|
private string _domainfilter;
|
||||||
private string _createusers;
|
private string _createusers;
|
||||||
|
|
||||||
@ -437,8 +446,9 @@ else
|
|||||||
_parameters = SettingService.GetSetting(settings, "ExternalLogin:Parameters", "");
|
_parameters = SettingService.GetSetting(settings, "ExternalLogin:Parameters", "");
|
||||||
_pkce = SettingService.GetSetting(settings, "ExternalLogin:PKCE", "false");
|
_pkce = SettingService.GetSetting(settings, "ExternalLogin:PKCE", "false");
|
||||||
_redirecturl = PageState.Uri.Scheme + "://" + PageState.Alias.Name + "/signin-" + _providertype;
|
_redirecturl = PageState.Uri.Scheme + "://" + PageState.Alias.Name + "/signin-" + _providertype;
|
||||||
_identifierclaimtype = SettingService.GetSetting(settings, "ExternalLogin:IdentifierClaimType", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier");
|
_identifierclaimtype = SettingService.GetSetting(settings, "ExternalLogin:IdentifierClaimType", "sub");
|
||||||
_emailclaimtype = SettingService.GetSetting(settings, "ExternalLogin:EmailClaimType", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress");
|
_emailclaimtype = SettingService.GetSetting(settings, "ExternalLogin:EmailClaimType", "email");
|
||||||
|
_roleclaimtype = SettingService.GetSetting(settings, "ExternalLogin:RoleClaimType", "");
|
||||||
_domainfilter = SettingService.GetSetting(settings, "ExternalLogin:DomainFilter", "");
|
_domainfilter = SettingService.GetSetting(settings, "ExternalLogin:DomainFilter", "");
|
||||||
_createusers = SettingService.GetSetting(settings, "ExternalLogin:CreateUsers", "true");
|
_createusers = SettingService.GetSetting(settings, "ExternalLogin:CreateUsers", "true");
|
||||||
|
|
||||||
@ -556,6 +566,7 @@ else
|
|||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:PKCE", _pkce, true);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:PKCE", _pkce, true);
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:IdentifierClaimType", _identifierclaimtype, true);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:IdentifierClaimType", _identifierclaimtype, true);
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:EmailClaimType", _emailclaimtype, true);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:EmailClaimType", _emailclaimtype, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "ExternalLogin:RoleClaimType", _roleclaimtype, true);
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:DomainFilter", _domainfilter, true);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:DomainFilter", _domainfilter, true);
|
||||||
settings = SettingService.SetSetting(settings, "ExternalLogin:CreateUsers", _createusers, true);
|
settings = SettingService.SetSetting(settings, "ExternalLogin:CreateUsers", _createusers, true);
|
||||||
|
|
||||||
@ -591,14 +602,10 @@ else
|
|||||||
if (_providertype == AuthenticationProviderTypes.OpenIDConnect)
|
if (_providertype == AuthenticationProviderTypes.OpenIDConnect)
|
||||||
{
|
{
|
||||||
_scopes = "openid,profile,email";
|
_scopes = "openid,profile,email";
|
||||||
_identifierclaimtype = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier";
|
|
||||||
_emailclaimtype = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_scopes = "";
|
_scopes = "";
|
||||||
_identifierclaimtype = "sub";
|
|
||||||
_emailclaimtype = "email";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_redirecturl = PageState.Uri.Scheme + "://" + PageState.Alias.Name + "/signin-" + _providertype;
|
_redirecturl = PageState.Uri.Scheme + "://" + PageState.Alias.Name + "/signin-" + _providertype;
|
||||||
|
@ -128,13 +128,6 @@
|
|||||||
|
|
||||||
private string CloseUrl()
|
private string CloseUrl()
|
||||||
{
|
{
|
||||||
if (!PageState.QueryString.ContainsKey("type"))
|
return (!string.IsNullOrEmpty(PageState.ReturnUrl)) ? PageState.ReturnUrl : NavigateUrl();
|
||||||
{
|
|
||||||
return NavigateUrl();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return NavigateUrl(PageState.Page.Path, "type=" + PageState.QueryString["type"] + "&days=" + PageState.QueryString["days"] + "&page=" + PageState.QueryString["page"]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ else
|
|||||||
<th>@Localizer["Created"]</th>
|
<th>@Localizer["Created"]</th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td><ActionLink Action="Detail" Parameters="@($"id=" + context.VisitorId.ToString() + "&type=" + _type.ToString() + "&days=" + _days.ToString() + "&page=" + _page.ToString())" ResourceKey="Details" /></td>
|
<td><ActionLink Action="Detail" Parameters="@($"id={context.VisitorId}")" ReturnUrl="@(NavigateUrl(PageState.Page.Path, $"type={_type}&days={_days}&page={_page}"))" ResourceKey="Details" /></td>
|
||||||
<td>@context.IPAddress</td>
|
<td>@context.IPAddress</td>
|
||||||
<td>
|
<td>
|
||||||
@if (context.UserId != null)
|
@if (context.UserId != null)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
@namespace Oqtane.Modules.Controls
|
@namespace Oqtane.Modules.Controls
|
||||||
|
@using System.Net
|
||||||
@inherits LocalizableComponent
|
@inherits LocalizableComponent
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
|
|
||||||
@ -71,6 +72,9 @@
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public bool IconOnly { get; set; } // optional - specifies only icon in link
|
public bool IconOnly { get; set; } // optional - specifies only icon in link
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string ReturnUrl { get; set; } // optional - used to set a url to redirect to
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
protected override void OnParametersSet()
|
||||||
{
|
{
|
||||||
base.OnParametersSet();
|
base.OnParametersSet();
|
||||||
@ -117,8 +121,12 @@
|
|||||||
|
|
||||||
_permissions = (string.IsNullOrEmpty(Permissions)) ? ModuleState.Permissions : Permissions;
|
_permissions = (string.IsNullOrEmpty(Permissions)) ? ModuleState.Permissions : Permissions;
|
||||||
_text = Localize(nameof(Text), _text);
|
_text = Localize(nameof(Text), _text);
|
||||||
_url = (ModuleId == -1) ? EditUrl(Action, _parameters) : EditUrl(ModuleId, Action, _parameters);
|
_url = (ModuleId == -1) ? EditUrl(Action, _parameters) : EditUrl(ModuleId, Action, _parameters);
|
||||||
_authorized = IsAuthorized();
|
if (!string.IsNullOrEmpty(ReturnUrl))
|
||||||
|
{
|
||||||
|
_url += ((_url.Contains("?")) ? "&" : "?") + $"returnurl={WebUtility.UrlEncode(ReturnUrl)}";
|
||||||
|
}
|
||||||
|
_authorized = IsAuthorized();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsAuthorized()
|
private bool IsAuthorized()
|
||||||
|
@ -376,42 +376,62 @@
|
|||||||
_messagetype = MessageType.Warning;
|
_messagetype = MessageType.Warning;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_message = Localizer["Message.File.NotSelected"];
|
_message = Localizer["Message.File.NotSelected"];
|
||||||
_messagetype = MessageType.Warning;
|
_messagetype = MessageType.Warning;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DeleteFile()
|
private async Task DeleteFile()
|
||||||
{
|
{
|
||||||
_message = string.Empty;
|
_message = string.Empty;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await FileService.DeleteFileAsync(FileId);
|
await FileService.DeleteFileAsync(FileId);
|
||||||
await logger.LogInformation("File Deleted {File}", FileId);
|
await logger.LogInformation("File Deleted {File}", FileId);
|
||||||
await OnDelete.InvokeAsync(FileId);
|
await OnDelete.InvokeAsync(FileId);
|
||||||
|
|
||||||
_message = Localizer["Success.File.Delete"];
|
_message = Localizer["Success.File.Delete"];
|
||||||
_messagetype = MessageType.Success;
|
_messagetype = MessageType.Success;
|
||||||
|
|
||||||
await GetFiles();
|
await GetFiles();
|
||||||
FileId = -1;
|
FileId = -1;
|
||||||
await SetImage();
|
await SetImage();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Deleting File {File} {Error}", FileId, ex.Message);
|
await logger.LogError(ex, "Error Deleting File {File} {Error}", FileId, ex.Message);
|
||||||
|
|
||||||
_message = Localizer["Error.File.Delete"];
|
_message = Localizer["Error.File.Delete"];
|
||||||
_messagetype = MessageType.Error;
|
_messagetype = MessageType.Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetFileId() => FileId;
|
public int GetFileId() => FileId;
|
||||||
|
|
||||||
public int GetFolderId() => FolderId;
|
public int GetFolderId() => FolderId;
|
||||||
|
|
||||||
public File GetFile() => _file;
|
public File GetFile() => _file;
|
||||||
|
|
||||||
|
public async Task Refresh()
|
||||||
|
{
|
||||||
|
await Refresh(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Refresh(int fileId)
|
||||||
|
{
|
||||||
|
await GetFiles();
|
||||||
|
if (fileId != -1)
|
||||||
|
{
|
||||||
|
var file = _files.Where(item => item.FileId == fileId).FirstOrDefault();
|
||||||
|
if (file != null)
|
||||||
|
{
|
||||||
|
FileId = file.FileId;
|
||||||
|
await SetImage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr class="@RowClass">@Footer</tr>
|
||||||
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@ -185,6 +188,9 @@
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public RenderFragment<TableItem> Row { get; set; } = null; // required
|
public RenderFragment<TableItem> Row { get; set; } = null; // required
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public RenderFragment Footer { get; set; } = null; // only applicable to Table layouts
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public RenderFragment<TableItem> Detail { get; set; } = null; // only applicable to Table layouts
|
public RenderFragment<TableItem> Detail { get; set; } = null; // only applicable to Table layouts
|
||||||
|
|
||||||
@ -293,6 +299,7 @@
|
|||||||
{
|
{
|
||||||
_page = 1;
|
_page = 1;
|
||||||
}
|
}
|
||||||
|
if (_page < 1) _page = 1;
|
||||||
|
|
||||||
_startPage = 0;
|
_startPage = 0;
|
||||||
_endPage = 0;
|
_endPage = 0;
|
||||||
|
@ -5,79 +5,100 @@
|
|||||||
<div class="row" style="margin-bottom: 50px;">
|
<div class="row" style="margin-bottom: 50px;">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<TabStrip>
|
<TabStrip>
|
||||||
<TabPanel Name="Rich" Heading="Rich Text Editor">
|
<TabPanel Name="Rich" Heading="Rich Text Editor">
|
||||||
@if (AllowFileManagement)
|
@if (_richfilemanager)
|
||||||
{
|
{
|
||||||
@if (_filemanagervisible)
|
<FileManager @ref="_fileManager" Filter="@Constants.ImageFiles" />
|
||||||
{
|
<ModuleMessage Message="@_message" Type="MessageType.Warning"></ModuleMessage>
|
||||||
<FileManager @ref="_fileManager" Filter="@Constants.ImageFiles" />
|
<br />
|
||||||
<ModuleMessage Message="@_message" Type="MessageType.Warning"></ModuleMessage>
|
}
|
||||||
<br />
|
<div class="d-flex justify-content-center mb-2">
|
||||||
}
|
@if (AllowRawHtml)
|
||||||
<div class="d-flex justify-content-center mb-2">
|
{
|
||||||
<button type="button" class="btn btn-secondary" @onclick="RefreshRichText">@Localizer["SynchronizeContent"]</button>
|
<button type="button" class="btn btn-secondary" @onclick="RefreshRichText">@Localizer["SynchronizeContent"]</button>@((MarkupString)" ")
|
||||||
<button type="button" class="btn btn-primary" @onclick="InsertImage">@Localizer["InsertImage"]</button>
|
}
|
||||||
@if (_filemanagervisible)
|
@if (AllowFileManagement)
|
||||||
{
|
{
|
||||||
@((MarkupString)" ")
|
<button type="button" class="btn btn-primary" @onclick="InsertRichImage">@Localizer["InsertImage"]</button>
|
||||||
<button type="button" class="btn btn-secondary" @onclick="CloseFileManager">@Localizer["Close"]</button>
|
}
|
||||||
}
|
@if (_richfilemanager)
|
||||||
</div>
|
{
|
||||||
}
|
@((MarkupString)" ")
|
||||||
<div class="row">
|
<button type="button" class="btn btn-secondary" @onclick="CloseRichFileManager">@Localizer["Close"]</button>
|
||||||
<div class="col">
|
}
|
||||||
<div @ref="@_toolBar">
|
</div>
|
||||||
@if (ToolbarContent != null)
|
<div class="row">
|
||||||
{
|
<div class="col">
|
||||||
@ToolbarContent
|
<div @ref="@_toolBar">
|
||||||
}
|
@if (ToolbarContent != null)
|
||||||
else
|
{
|
||||||
{
|
@ToolbarContent
|
||||||
<select class="ql-header">
|
}
|
||||||
<option selected=""></option>
|
else
|
||||||
<option value="1"></option>
|
{
|
||||||
<option value="2"></option>
|
<select class="ql-header">
|
||||||
<option value="3"></option>
|
<option selected=""></option>
|
||||||
<option value="4"></option>
|
<option value="1"></option>
|
||||||
<option value="5"></option>
|
<option value="2"></option>
|
||||||
</select>
|
<option value="3"></option>
|
||||||
<span class="ql-formats">
|
<option value="4"></option>
|
||||||
<button class="ql-bold"></button>
|
<option value="5"></option>
|
||||||
<button class="ql-italic"></button>
|
</select>
|
||||||
<button class="ql-underline"></button>
|
<span class="ql-formats">
|
||||||
<button class="ql-strike"></button>
|
<button class="ql-bold"></button>
|
||||||
</span>
|
<button class="ql-italic"></button>
|
||||||
<span class="ql-formats">
|
<button class="ql-underline"></button>
|
||||||
<select class="ql-color"></select>
|
<button class="ql-strike"></button>
|
||||||
<select class="ql-background"></select>
|
</span>
|
||||||
</span>
|
<span class="ql-formats">
|
||||||
<span class="ql-formats">
|
<select class="ql-color"></select>
|
||||||
<button class="ql-list" value="ordered"></button>
|
<select class="ql-background"></select>
|
||||||
<button class="ql-list" value="bullet"></button>
|
</span>
|
||||||
</span>
|
<span class="ql-formats">
|
||||||
<span class="ql-formats">
|
<button class="ql-list" value="ordered"></button>
|
||||||
<button class="ql-link"></button>
|
<button class="ql-list" value="bullet"></button>
|
||||||
</span>
|
</span>
|
||||||
}
|
<span class="ql-formats">
|
||||||
</div>
|
<button class="ql-link"></button>
|
||||||
<div @ref="@_editorElement">
|
</span>
|
||||||
</div>
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div @ref="@_editorElement">
|
||||||
</TabPanel>
|
</div>
|
||||||
<TabPanel Name="Raw" Heading="Raw HTML Editor" ResourceKey="HtmlEditor">
|
</div>
|
||||||
<div class="d-flex justify-content-center mb-2">
|
</div>
|
||||||
<button type="button" class="btn btn-secondary" @onclick="RefreshRawHtml">@Localizer["SynchronizeContent"]</button>
|
</TabPanel>
|
||||||
</div>
|
@if (AllowRawHtml)
|
||||||
@if (ReadOnly)
|
{
|
||||||
{
|
<TabPanel Name="Raw" Heading="Raw HTML Editor" ResourceKey="HtmlEditor">
|
||||||
<textarea class="form-control" placeholder="@Placeholder" @bind="@_rawhtml" rows="10" readonly></textarea>
|
@if (_rawfilemanager)
|
||||||
}
|
{
|
||||||
else
|
<FileManager @ref="_fileManager" Filter="@Constants.ImageFiles" />
|
||||||
{
|
<ModuleMessage Message="@_message" Type="MessageType.Warning"></ModuleMessage>
|
||||||
<textarea class="form-control" placeholder="@Placeholder" @bind="@_rawhtml" rows="10"></textarea>
|
<br />
|
||||||
}
|
}
|
||||||
</TabPanel>
|
<div class="d-flex justify-content-center mb-2">
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="RefreshRawHtml">@Localizer["SynchronizeContent"]</button>
|
||||||
|
@if (AllowFileManagement)
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-primary" @onclick="InsertRawImage">@Localizer["InsertImage"]</button>
|
||||||
|
}
|
||||||
|
@if (_rawfilemanager)
|
||||||
|
{
|
||||||
|
@((MarkupString)" ")
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="CloseRawFileManager">@Localizer["Close"]</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
@if (ReadOnly)
|
||||||
|
{
|
||||||
|
<textarea id="rawhtmleditor" class="form-control" placeholder="@Placeholder" @bind="@_rawhtml" rows="10" readonly></textarea>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<textarea id="rawhtmleditor" class="form-control" placeholder="@Placeholder" @bind="@_rawhtml" rows="10"></textarea>
|
||||||
|
}
|
||||||
|
</TabPanel>
|
||||||
|
}
|
||||||
</TabStrip>
|
</TabStrip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -85,10 +106,11 @@
|
|||||||
@code {
|
@code {
|
||||||
private ElementReference _editorElement;
|
private ElementReference _editorElement;
|
||||||
private ElementReference _toolBar;
|
private ElementReference _toolBar;
|
||||||
private bool _filemanagervisible = false;
|
private bool _richfilemanager = false;
|
||||||
private FileManager _fileManager;
|
private FileManager _fileManager;
|
||||||
private string _richhtml = string.Empty;
|
private string _richhtml = string.Empty;
|
||||||
private string _originalrichhtml = string.Empty;
|
private string _originalrichhtml = string.Empty;
|
||||||
|
private bool _rawfilemanager = false;
|
||||||
private string _rawhtml = string.Empty;
|
private string _rawhtml = string.Empty;
|
||||||
private string _originalrawhtml = string.Empty;
|
private string _originalrawhtml = string.Empty;
|
||||||
private string _message = string.Empty;
|
private string _message = string.Empty;
|
||||||
@ -102,6 +124,12 @@
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string Placeholder { get; set; } = "Enter Your Content...";
|
public string Placeholder { get; set; } = "Enter Your Content...";
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public bool AllowFileManagement { get; set; } = true;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public bool AllowRawHtml { get; set; } = true;
|
||||||
|
|
||||||
// parameters only applicable to rich text editor
|
// parameters only applicable to rich text editor
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public RenderFragment ToolbarContent { get; set; }
|
public RenderFragment ToolbarContent { get; set; }
|
||||||
@ -112,9 +140,6 @@
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public string DebugLevel { get; set; } = "info";
|
public string DebugLevel { get; set; } = "info";
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public bool AllowFileManagement { get; set; } = true;
|
|
||||||
|
|
||||||
public override List<Resource> Resources => new List<Resource>()
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
{
|
{
|
||||||
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill.min.js" },
|
new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill.min.js" },
|
||||||
@ -152,9 +177,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CloseFileManager()
|
public void CloseRichFileManager()
|
||||||
{
|
{
|
||||||
_filemanagervisible = false;
|
_richfilemanager = false;
|
||||||
|
_message = string.Empty;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CloseRawFileManager()
|
||||||
|
{
|
||||||
|
_rawfilemanager = false;
|
||||||
_message = string.Empty;
|
_message = string.Empty;
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
@ -194,29 +226,55 @@
|
|||||||
return _originalrawhtml;
|
return _originalrawhtml;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InsertImage()
|
public async Task InsertRichImage()
|
||||||
{
|
{
|
||||||
_message = string.Empty;
|
_message = string.Empty;
|
||||||
if (_filemanagervisible)
|
if (_richfilemanager)
|
||||||
{
|
{
|
||||||
var file = _fileManager.GetFile();
|
var file = _fileManager.GetFile();
|
||||||
if (file != null)
|
if (file != null)
|
||||||
{
|
{
|
||||||
var interop = new RichTextEditorInterop(JSRuntime);
|
var interop = new RichTextEditorInterop(JSRuntime);
|
||||||
await interop.InsertImage(_editorElement, file.Url, file.Name);
|
await interop.InsertImage(_editorElement, file.Url, ((!string.IsNullOrEmpty(file.Description)) ? file.Description : file.Name));
|
||||||
_filemanagervisible = false;
|
_richfilemanager = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_message = Localizer["Message.Require.Image"];
|
_message = Localizer["Message.Require.Image"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_filemanagervisible = true;
|
_richfilemanager = true;
|
||||||
}
|
}
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task InsertRawImage()
|
||||||
|
{
|
||||||
|
_message = string.Empty;
|
||||||
|
if (_rawfilemanager)
|
||||||
|
{
|
||||||
|
var file = _fileManager.GetFile();
|
||||||
|
if (file != null)
|
||||||
|
{
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
int pos = await interop.GetCaretPosition("rawhtmleditor");
|
||||||
|
var image = "<img src=\"" + file.Url + "\" alt=\"" + ((!string.IsNullOrEmpty(file.Description)) ? file.Description : file.Name) + "\" class=\"img-fluid\">";
|
||||||
|
_rawhtml = _rawhtml.Substring(0, pos) + image + _rawhtml.Substring(pos);
|
||||||
|
_rawfilemanager = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_message = Localizer["Message.Require.Image"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_rawfilemanager = true;
|
||||||
|
}
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<TabPanel Name="Edit" Heading="Edit" ResourceKey="Edit">
|
<TabPanel Name="Edit" Heading="Edit" ResourceKey="Edit">
|
||||||
@if (_content != null)
|
@if (_content != null)
|
||||||
{
|
{
|
||||||
<RichTextEditor Content="@_content" AllowFileManagement="@_allowfilemanagement" @ref="@RichTextEditorHtml"></RichTextEditor>
|
<RichTextEditor Content="@_content" AllowFileManagement="@_allowfilemanagement" AllowRawHtml="@_allowrawhtml" @ref="@RichTextEditorHtml"></RichTextEditor>
|
||||||
<br />
|
<br />
|
||||||
<button type="button" class="btn btn-success" @onclick="SaveContent">@SharedLocalizer["Save"]</button>
|
<button type="button" class="btn btn-success" @onclick="SaveContent">@SharedLocalizer["Save"]</button>
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||||
@ -60,6 +60,7 @@
|
|||||||
|
|
||||||
private RichTextEditor RichTextEditorHtml;
|
private RichTextEditor RichTextEditorHtml;
|
||||||
private bool _allowfilemanagement;
|
private bool _allowfilemanagement;
|
||||||
|
private bool _allowrawhtml;
|
||||||
private string _content = null;
|
private string _content = null;
|
||||||
private string _createdby;
|
private string _createdby;
|
||||||
private DateTime _createdon;
|
private DateTime _createdon;
|
||||||
@ -73,6 +74,7 @@
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_allowfilemanagement = bool.Parse(SettingService.GetSetting(ModuleState.Settings, "AllowFileManagement", "true"));
|
_allowfilemanagement = bool.Parse(SettingService.GetSetting(ModuleState.Settings, "AllowFileManagement", "true"));
|
||||||
|
_allowrawhtml = bool.Parse(SettingService.GetSetting(ModuleState.Settings, "AllowRawHtml", "true"));
|
||||||
await LoadContent();
|
await LoadContent();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -15,18 +15,29 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="files" ResourceKey="AllowRawHtml" ResourceType="@resourceType" HelpText="Specify If Editors Can Enter Raw HTML">Allow Raw HTML: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="files" class="form-select" @bind="@_allowrawhtml">
|
||||||
|
<option value="true">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="false">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string resourceType = "Oqtane.Modules.HtmlText.Settings, Oqtane.Client"; // for localization
|
private string resourceType = "Oqtane.Modules.HtmlText.Settings, Oqtane.Client"; // for localization
|
||||||
private string _allowfilemanagement;
|
private string _allowfilemanagement;
|
||||||
|
private string _allowrawhtml;
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_allowfilemanagement = SettingService.GetSetting(ModuleState.Settings, "AllowFileManagement", "true");
|
_allowfilemanagement = SettingService.GetSetting(ModuleState.Settings, "AllowFileManagement", "true");
|
||||||
}
|
_allowrawhtml = SettingService.GetSetting(ModuleState.Settings, "AllowRawHtml", "true");
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
ModuleInstance.AddModuleMessage(ex.Message, MessageType.Error);
|
ModuleInstance.AddModuleMessage(ex.Message, MessageType.Error);
|
||||||
@ -39,7 +50,8 @@
|
|||||||
{
|
{
|
||||||
var settings = await SettingService.GetModuleSettingsAsync(ModuleState.ModuleId);
|
var settings = await SettingService.GetModuleSettingsAsync(ModuleState.ModuleId);
|
||||||
settings = SettingService.SetSetting(settings, "AllowFileManagement", _allowfilemanagement);
|
settings = SettingService.SetSetting(settings, "AllowFileManagement", _allowfilemanagement);
|
||||||
await SettingService.UpdateModuleSettingsAsync(settings, ModuleState.ModuleId);
|
settings = SettingService.SetSetting(settings, "AllowRawHtml", _allowrawhtml);
|
||||||
|
await SettingService.UpdateModuleSettingsAsync(settings, ModuleState.ModuleId);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,8 @@ namespace Oqtane.Modules
|
|||||||
public abstract class ModuleBase : ComponentBase, IModuleControl
|
public abstract class ModuleBase : ComponentBase, IModuleControl
|
||||||
{
|
{
|
||||||
private Logger _logger;
|
private Logger _logger;
|
||||||
|
private string _urlparametersstate;
|
||||||
|
private Dictionary<string, string> _urlparameters;
|
||||||
|
|
||||||
protected Logger logger => _logger ?? (_logger = new Logger(this));
|
protected Logger logger => _logger ?? (_logger = new Logger(this));
|
||||||
|
|
||||||
@ -24,6 +26,9 @@ namespace Oqtane.Modules
|
|||||||
[Inject]
|
[Inject]
|
||||||
protected IJSRuntime JSRuntime { get; set; }
|
protected IJSRuntime JSRuntime { get; set; }
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
protected SiteState SiteState { get; set; }
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
protected PageState PageState { get; set; }
|
protected PageState PageState { get; set; }
|
||||||
|
|
||||||
@ -44,6 +49,21 @@ namespace Oqtane.Modules
|
|||||||
|
|
||||||
public virtual List<Resource> Resources { get; set; }
|
public virtual List<Resource> Resources { get; set; }
|
||||||
|
|
||||||
|
// url parameters
|
||||||
|
public virtual string UrlParametersTemplate { get; set; }
|
||||||
|
|
||||||
|
public Dictionary<string, string> UrlParameters {
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_urlparametersstate == null || _urlparametersstate != PageState.UrlParameters)
|
||||||
|
{
|
||||||
|
_urlparametersstate = PageState.UrlParameters;
|
||||||
|
_urlparameters = GetUrlParameters(UrlParametersTemplate);
|
||||||
|
}
|
||||||
|
return _urlparameters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// base lifecycle method for handling JSInterop script registration
|
// base lifecycle method for handling JSInterop script registration
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
@ -55,7 +75,8 @@ namespace Oqtane.Modules
|
|||||||
var scripts = new List<object>();
|
var scripts = new List<object>();
|
||||||
foreach (Resource resource in Resources.Where(item => item.ResourceType == ResourceType.Script))
|
foreach (Resource resource in Resources.Where(item => item.ResourceType == ResourceType.Script))
|
||||||
{
|
{
|
||||||
scripts.Add(new { href = resource.Url, bundle = resource.Bundle ?? "", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "", es6module = resource.ES6Module });
|
var url = (resource.Url.Contains("://")) ? resource.Url : PageState.Alias.BaseUrl + resource.Url;
|
||||||
|
scripts.Add(new { href = url, bundle = resource.Bundle ?? "", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "", es6module = resource.ES6Module });
|
||||||
}
|
}
|
||||||
if (scripts.Any())
|
if (scripts.Any())
|
||||||
{
|
{
|
||||||
@ -70,7 +91,7 @@ namespace Oqtane.Modules
|
|||||||
|
|
||||||
public string ModulePath()
|
public string ModulePath()
|
||||||
{
|
{
|
||||||
return "Modules/" + GetType().Namespace + "/";
|
return PageState?.Alias.BaseUrl + "/Modules/" + GetType().Namespace + "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
// url methods
|
// url methods
|
||||||
@ -124,14 +145,23 @@ namespace Oqtane.Modules
|
|||||||
return Utilities.EditUrl(PageState.Alias.Path, path, moduleid, action, parameters);
|
return Utilities.EditUrl(PageState.Alias.Path, path, moduleid, action, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ContentUrl(int fileid)
|
public string FileUrl(string folderpath, string filename)
|
||||||
{
|
{
|
||||||
return ContentUrl(fileid, false);
|
return FileUrl(folderpath, filename, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ContentUrl(int fileid, bool asAttachment)
|
public string FileUrl(string folderpath, string filename, bool download)
|
||||||
{
|
{
|
||||||
return Utilities.ContentUrl(PageState.Alias, fileid, asAttachment);
|
return Utilities.FileUrl(PageState.Alias, folderpath, filename, download);
|
||||||
|
}
|
||||||
|
public string FileUrl(int fileid)
|
||||||
|
{
|
||||||
|
return FileUrl(fileid, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FileUrl(int fileid, bool download)
|
||||||
|
{
|
||||||
|
return Utilities.FileUrl(PageState.Alias, fileid, download);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ImageUrl(int fileid, int width, int height)
|
public string ImageUrl(int fileid, int width, int height)
|
||||||
@ -149,15 +179,26 @@ namespace Oqtane.Modules
|
|||||||
return Utilities.ImageUrl(PageState.Alias, fileid, width, height, mode, position, background, rotate, recreate);
|
return Utilities.ImageUrl(PageState.Alias, fileid, width, height, mode, position, background, rotate, recreate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Dictionary<string, string> GetUrlParameters(string parametersTemplate = "")
|
public string AddUrlParameters(params object[] parameters)
|
||||||
|
{
|
||||||
|
var url = "";
|
||||||
|
for (var i = 0; i < parameters.Length; i++)
|
||||||
|
{
|
||||||
|
url += "/" + parameters[i].ToString();
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// template is in the form of a standard route template ie. "/{id}/{name}" and produces dictionary of key/value pairs
|
||||||
|
// if url parameters belong to a specific module you should embed a unique key into the route (ie. /!/blog/1) and validate the url parameter key in the module
|
||||||
|
public virtual Dictionary<string, string> GetUrlParameters(string template = "")
|
||||||
{
|
{
|
||||||
var urlParameters = new Dictionary<string, string>();
|
var urlParameters = new Dictionary<string, string>();
|
||||||
string[] templateSegments;
|
var parameters = _urlparametersstate.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
||||||
var parameters = PageState.UrlParameters.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
var parameterId = 0;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(parametersTemplate))
|
if (string.IsNullOrEmpty(template))
|
||||||
{
|
{
|
||||||
|
// no template will populate dictionary with generic "parameter#" keys
|
||||||
for (int i = 0; i < parameters.Length; i++)
|
for (int i = 0; i < parameters.Length; i++)
|
||||||
{
|
{
|
||||||
urlParameters.TryAdd("parameter" + i, parameters[i]);
|
urlParameters.TryAdd("parameter" + i, parameters[i]);
|
||||||
@ -165,39 +206,37 @@ namespace Oqtane.Modules
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
templateSegments = parametersTemplate.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
var segments = template.Split('/', StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
string key;
|
||||||
|
|
||||||
if (parameters.Length == templateSegments.Length)
|
for (int i = 0; i < parameters.Length; i++)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < parameters.Length; i++)
|
if (i < segments.Length)
|
||||||
{
|
{
|
||||||
if (parameters.Length > i)
|
key = segments[i];
|
||||||
|
if (key.StartsWith("{") && key.EndsWith("}"))
|
||||||
{
|
{
|
||||||
if (templateSegments[i] == parameters[i])
|
// dynamic segment
|
||||||
{
|
key = key.Substring(1, key.Length - 2);
|
||||||
urlParameters.TryAdd("parameter" + parameterId, parameters[i]);
|
}
|
||||||
parameterId++;
|
else
|
||||||
}
|
{
|
||||||
else if (templateSegments[i].StartsWith("{") && templateSegments[i].EndsWith("}"))
|
// static segments use generic "parameter#" keys
|
||||||
{
|
key = "parameter" + i.ToString();
|
||||||
var key = templateSegments[i].Replace("{", "");
|
|
||||||
key = key.Replace("}", "");
|
|
||||||
urlParameters.TryAdd(key, parameters[i]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i = parameters.Length;
|
|
||||||
urlParameters.Clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else // unspecified segments use generic "parameter#" keys
|
||||||
|
{
|
||||||
|
key = "parameter" + i.ToString();
|
||||||
|
}
|
||||||
|
urlParameters.TryAdd(key, parameters[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return urlParameters;
|
return urlParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
// user feedback methods
|
// UI methods
|
||||||
public void AddModuleMessage(string message, MessageType type)
|
public void AddModuleMessage(string message, MessageType type)
|
||||||
{
|
{
|
||||||
ModuleInstance.AddModuleMessage(message, type);
|
ModuleInstance.AddModuleMessage(message, type);
|
||||||
@ -218,6 +257,18 @@ namespace Oqtane.Modules
|
|||||||
ModuleInstance.HideProgressIndicator();
|
ModuleInstance.HideProgressIndicator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetModuleTitle(string title)
|
||||||
|
{
|
||||||
|
var obj = new { PageModuleId = ModuleState.PageModuleId, Title = title };
|
||||||
|
SiteState.Properties.ModuleTitle = obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetModuleVisibility(bool visible)
|
||||||
|
{
|
||||||
|
var obj = new { PageModuleId = ModuleState.PageModuleId, Visible = visible };
|
||||||
|
SiteState.Properties.ModuleVisibility = obj;
|
||||||
|
}
|
||||||
|
|
||||||
// logging methods
|
// logging methods
|
||||||
public async Task Log(Alias alias, LogLevel level, string function, Exception exception, string message, params object[] args)
|
public async Task Log(Alias alias, LogLevel level, string function, Exception exception, string message, params object[] args)
|
||||||
{
|
{
|
||||||
@ -365,5 +416,17 @@ namespace Oqtane.Modules
|
|||||||
await _moduleBase.Log(null, LogLevel.Critical, "", exception, message, args);
|
await _moduleBase.Log(null, LogLevel.Critical, "", exception, message, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete("ContentUrl(int fileId) is deprecated. Use FileUrl(int fileId) instead.", false)]
|
||||||
|
public string ContentUrl(int fileid)
|
||||||
|
{
|
||||||
|
return ContentUrl(fileid, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("ContentUrl(int fileId, bool asAttachment) is deprecated. Use FileUrl(int fileId, bool download) instead.", false)]
|
||||||
|
public string ContentUrl(int fileid, bool asAttachment)
|
||||||
|
{
|
||||||
|
return Utilities.FileUrl(PageState.Alias, fileid, asAttachment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,15 +5,15 @@
|
|||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RazorLangVersion>3.0</RazorLangVersion>
|
<RazorLangVersion>3.0</RazorLangVersion>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
<Version>3.1.3</Version>
|
<Version>3.2.1</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
<Description>Modular Application Framework for Blazor</Description>
|
<Description>Modular Application Framework for Blazor and MAUI</Description>
|
||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.1.3</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<RootNamespace>Oqtane</RootNamespace>
|
<RootNamespace>Oqtane</RootNamespace>
|
||||||
@ -35,13 +35,8 @@
|
|||||||
<ProjectReference Include="..\Oqtane.Shared\Oqtane.Shared.csproj" />
|
<ProjectReference Include="..\Oqtane.Shared\Oqtane.Shared.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<TrimmerRootAssembly Include="System.Runtime" />
|
|
||||||
<TrimmerRootAssembly Include="System.Linq.Parallel" />
|
|
||||||
<TrimmerRootAssembly Include="System.Runtime.CompilerServices.VisualC" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
<PublishTrimmed>false</PublishTrimmed>
|
||||||
<BlazorEnableCompression>false</BlazorEnableCompression>
|
<BlazorEnableCompression>false</BlazorEnableCompression>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ using System.Linq;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.Loader;
|
using System.Runtime.Loader;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||||
using Microsoft.AspNetCore.Localization;
|
using Microsoft.AspNetCore.Localization;
|
||||||
@ -15,7 +16,6 @@ using Microsoft.JSInterop;
|
|||||||
using Oqtane.Documentation;
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Modules;
|
using Oqtane.Modules;
|
||||||
using Oqtane.Services;
|
using Oqtane.Services;
|
||||||
using Oqtane.Shared;
|
|
||||||
using Oqtane.UI;
|
using Oqtane.UI;
|
||||||
|
|
||||||
namespace Oqtane.Client
|
namespace Oqtane.Client
|
||||||
@ -33,7 +33,7 @@ namespace Oqtane.Client
|
|||||||
|
|
||||||
builder.Services.AddOptions();
|
builder.Services.AddOptions();
|
||||||
|
|
||||||
// Register localization services
|
// register localization services
|
||||||
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
|
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
|
||||||
|
|
||||||
// register auth services
|
// register auth services
|
||||||
@ -42,7 +42,9 @@ namespace Oqtane.Client
|
|||||||
// register scoped core services
|
// register scoped core services
|
||||||
builder.Services.AddOqtaneScopedServices();
|
builder.Services.AddOqtaneScopedServices();
|
||||||
|
|
||||||
await LoadClientAssemblies(httpClient);
|
var serviceProvider = builder.Services.BuildServiceProvider();
|
||||||
|
|
||||||
|
await LoadClientAssemblies(httpClient, serviceProvider);
|
||||||
|
|
||||||
var assemblies = AppDomain.CurrentDomain.GetOqtaneAssemblies();
|
var assemblies = AppDomain.CurrentDomain.GetOqtaneAssemblies();
|
||||||
foreach (var assembly in assemblies)
|
foreach (var assembly in assemblies)
|
||||||
@ -54,37 +56,106 @@ namespace Oqtane.Client
|
|||||||
RegisterClientStartups(assembly, builder.Services);
|
RegisterClientStartups(assembly, builder.Services);
|
||||||
}
|
}
|
||||||
|
|
||||||
var host = builder.Build();
|
await builder.Build().RunAsync();
|
||||||
|
|
||||||
await SetCultureFromLocalizationCookie(host.Services);
|
|
||||||
|
|
||||||
ServiceActivator.Configure(host.Services);
|
|
||||||
|
|
||||||
await host.RunAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task LoadClientAssemblies(HttpClient http)
|
private static async Task LoadClientAssemblies(HttpClient http, IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
// get list of loaded assemblies on the client
|
var dlls = new Dictionary<string, byte[]>();
|
||||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetName().Name).ToList();
|
var pdbs = new Dictionary<string, byte[]>();
|
||||||
|
var list = new List<string>();
|
||||||
|
|
||||||
// get assemblies from server and load into client app domain
|
var jsRuntime = serviceProvider.GetRequiredService<IJSRuntime>();
|
||||||
var zip = await http.GetByteArrayAsync($"/api/Installation/load");
|
var interop = new Interop(jsRuntime);
|
||||||
|
var files = await interop.GetIndexedDBKeys(".dll");
|
||||||
|
|
||||||
// asemblies and debug symbols are packaged in a zip file
|
if (files.Count() != 0)
|
||||||
using (ZipArchive archive = new ZipArchive(new MemoryStream(zip)))
|
|
||||||
{
|
{
|
||||||
var dlls = new Dictionary<string, byte[]>();
|
// get list of assemblies from server
|
||||||
var pdbs = new Dictionary<string, byte[]>();
|
var json = await http.GetStringAsync("/api/Installation/list");
|
||||||
|
var assemblies = JsonSerializer.Deserialize<List<string>>(json);
|
||||||
|
|
||||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
// determine which assemblies need to be downloaded
|
||||||
|
foreach (var assembly in assemblies)
|
||||||
{
|
{
|
||||||
if (!assemblies.Contains(Path.GetFileNameWithoutExtension(entry.FullName)))
|
var file = files.FirstOrDefault(item => item.Contains(assembly));
|
||||||
|
if (file == null)
|
||||||
|
{
|
||||||
|
list.Add(assembly);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// check if newer version available
|
||||||
|
if (GetFileDate(assembly) > GetFileDate(file))
|
||||||
|
{
|
||||||
|
list.Add(assembly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get assemblies already downloaded
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
if (assemblies.Contains(file) && !list.Contains(file))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dlls.Add(file, await interop.GetIndexedDBItem<byte[]>(file));
|
||||||
|
var pdb = file.Replace(".dll", ".pdb");
|
||||||
|
if (files.Contains(pdb))
|
||||||
|
{
|
||||||
|
pdbs.Add(pdb, await interop.GetIndexedDBItem<byte[]>(pdb));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // file is deprecated
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await interop.RemoveIndexedDBItem(file);
|
||||||
|
await interop.RemoveIndexedDBItem(file.Replace(".dll", ".pdb"));
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list.Add("*");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list.Count != 0)
|
||||||
|
{
|
||||||
|
// get assemblies from server and load into client app domain
|
||||||
|
var zip = await http.GetByteArrayAsync($"/api/Installation/load?list=" + string.Join(",", list));
|
||||||
|
|
||||||
|
// asemblies and debug symbols are packaged in a zip file
|
||||||
|
using (ZipArchive archive = new ZipArchive(new MemoryStream(zip)))
|
||||||
|
{
|
||||||
|
foreach (ZipArchiveEntry entry in archive.Entries)
|
||||||
{
|
{
|
||||||
using (var memoryStream = new MemoryStream())
|
using (var memoryStream = new MemoryStream())
|
||||||
{
|
{
|
||||||
entry.Open().CopyTo(memoryStream);
|
entry.Open().CopyTo(memoryStream);
|
||||||
byte[] file = memoryStream.ToArray();
|
byte[] file = memoryStream.ToArray();
|
||||||
|
|
||||||
|
// save assembly to indexeddb
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await interop.SetIndexedDBItem(entry.FullName, file);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
switch (Path.GetExtension(entry.FullName))
|
switch (Path.GetExtension(entry.FullName))
|
||||||
{
|
{
|
||||||
case ".dll":
|
case ".dll":
|
||||||
@ -97,23 +168,31 @@ namespace Oqtane.Client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var item in dlls)
|
// load assemblies into app domain
|
||||||
|
foreach (var item in dlls)
|
||||||
|
{
|
||||||
|
if (pdbs.ContainsKey(item.Key.Replace(".dll", ".pdb")))
|
||||||
{
|
{
|
||||||
if (pdbs.ContainsKey(item.Key))
|
AssemblyLoadContext.Default.LoadFromStream(new MemoryStream(item.Value), new MemoryStream(pdbs[item.Key.Replace(".dll", ".pdb")]));
|
||||||
{
|
}
|
||||||
AssemblyLoadContext.Default.LoadFromStream(new MemoryStream(item.Value), new MemoryStream(pdbs[item.Key]));
|
else
|
||||||
}
|
{
|
||||||
else
|
AssemblyLoadContext.Default.LoadFromStream(new MemoryStream(item.Value));
|
||||||
{
|
|
||||||
AssemblyLoadContext.Default.LoadFromStream(new MemoryStream(item.Value));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static DateTime GetFileDate(string filepath)
|
||||||
|
{
|
||||||
|
var segments = filepath.Split('.');
|
||||||
|
return DateTime.ParseExact(segments[segments.Length - 2], "yyyyMMddHHmmss", CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
|
||||||
private static void RegisterModuleServices(Assembly assembly, IServiceCollection services)
|
private static void RegisterModuleServices(Assembly assembly, IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
// dynamically register module scoped services
|
||||||
var implementationTypes = assembly.GetInterfaces<IService>();
|
var implementationTypes = assembly.GetInterfaces<IService>();
|
||||||
foreach (var implementationType in implementationTypes)
|
foreach (var implementationType in implementationTypes)
|
||||||
{
|
{
|
||||||
|
@ -121,7 +121,7 @@
|
|||||||
<value>Server:</value>
|
<value>Server:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Server.HelpText" xml:space="preserve">
|
<data name="Server.HelpText" xml:space="preserve">
|
||||||
<value>Enter the database server</value>
|
<value>Enter the database server name. This might include a port number as well if you are using a cloud service (ie. servername.database.windows.net,1433) </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Database.Text" xml:space="preserve">
|
<data name="Database.Text" xml:space="preserve">
|
||||||
<value>Database:</value>
|
<value>Database:</value>
|
||||||
@ -133,7 +133,7 @@
|
|||||||
<value>Integrated Security:</value>
|
<value>Integrated Security:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IntegratedSecurity.HelpText" xml:space="preserve">
|
<data name="IntegratedSecurity.HelpText" xml:space="preserve">
|
||||||
<value>Select if you want integrated security or not</value>
|
<value>Select if you are using integrated security</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Uid.Text" xml:space="preserve">
|
<data name="Uid.Text" xml:space="preserve">
|
||||||
<value>User Id:</value>
|
<value>User Id:</value>
|
||||||
@ -163,7 +163,7 @@
|
|||||||
<value>Self Signed</value>
|
<value>Self Signed</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TrustServerCertificate.HelpText" xml:space="preserve">
|
<data name="TrustServerCertificate.HelpText" xml:space="preserve">
|
||||||
<value>Specify the type of certificate you are using for encryption</value>
|
<value>Specify the type of certificate you are using for encryption. Verifiable is equivalent to False. Self Signed is equivalent to True.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TrustServerCertificate.Text" xml:space="preserve">
|
<data name="TrustServerCertificate.Text" xml:space="preserve">
|
||||||
<value>Trust Server Certificate:</value>
|
<value>Trust Server Certificate:</value>
|
||||||
|
@ -135,10 +135,10 @@
|
|||||||
<data name="Message.Require.DbInfo" xml:space="preserve">
|
<data name="Message.Require.DbInfo" xml:space="preserve">
|
||||||
<value>Please Enter All Required Fields. Ensure Passwords Match And Email Address Provided Is Valid.</value>
|
<value>Please Enter All Required Fields. Ensure Passwords Match And Email Address Provided Is Valid.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Message.Password.Invalid" xml:space="preserve">
|
<data name="Message.Password.Invalid" xml:space="preserve">
|
||||||
<value>The Password Provided Does Not Meet The Password Policy. Please Verify The Minimum Password Length And Complexity Requirements.</value>
|
<value>The Password Provided Does Not Meet The Password Policy. Please Verify The Minimum Password Length And Complexity Requirements.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Register" xml:space="preserve">
|
<data name="Register" xml:space="preserve">
|
||||||
<value>Please Register Me For Major Product Updates And Security Bulletins</value>
|
<value>Please Register Me For Major Product Updates And Security Bulletins</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Confirm.HelpText" xml:space="preserve">
|
<data name="Confirm.HelpText" xml:space="preserve">
|
||||||
@ -168,4 +168,16 @@
|
|||||||
<data name="Username.Text" xml:space="preserve">
|
<data name="Username.Text" xml:space="preserve">
|
||||||
<value>Username:</value>
|
<value>Username:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectionString.HelpText" xml:space="preserve">
|
||||||
|
<value>Enter a complete connection string including all parameters and delimiters</value>
|
||||||
|
</data>
|
||||||
|
<data name="ConnectionString.Text" xml:space="preserve">
|
||||||
|
<value>String:</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnterConnectionParameters" xml:space="preserve">
|
||||||
|
<value>Enter Connection Parameters</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnterConnectionString" xml:space="preserve">
|
||||||
|
<value>Enter Connection String</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@ -118,6 +118,6 @@
|
|||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<data name="Error.Module.Load" xml:space="preserve">
|
<data name="Error.Module.Load" xml:space="preserve">
|
||||||
<value>A Problem Was Encountered Loading Module {0}</value>
|
<value>A Problem Was Encountered Loading Module {0}. The Module Is Either Invalid Or Does Not Exist.</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
@ -192,4 +192,7 @@
|
|||||||
<data name="Once" xml:space="preserve">
|
<data name="Once" xml:space="preserve">
|
||||||
<value>Execute Once</value>
|
<value>Execute Once</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Message.NoJobs" xml:space="preserve">
|
||||||
|
<value>Please Note That After An Initial Installation You Must &lt;a href={0}&gt;Restart&lt;/a&gt; The Application In Order To Activate The Default Scheduled Jobs.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -154,13 +154,13 @@
|
|||||||
<value>No Translations Match The Criteria Provided Or Package Service Is Disabled</value>
|
<value>No Translations Match The Criteria Provided Or Package Service Is Disabled</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Download.Heading" xml:space="preserve">
|
<data name="Download.Heading" xml:space="preserve">
|
||||||
<value>Download</value>
|
<value>Translations</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LanguageUpload.HelpText" xml:space="preserve">
|
<data name="LanguageUpload.HelpText" xml:space="preserve">
|
||||||
<value>Upload one or more translations. Once they are uploaded click Install to complete the installation.</value>
|
<value>Upload one or more translation packages. Once they are uploaded click Install to complete the installation.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LanguageUpload.Text" xml:space="preserve">
|
<data name="LanguageUpload.Text" xml:space="preserve">
|
||||||
<value>Upload Language</value>
|
<value>Translation</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Manage.Heading" xml:space="preserve">
|
<data name="Manage.Heading" xml:space="preserve">
|
||||||
<value>Manage</value>
|
<value>Manage</value>
|
||||||
|
@ -144,4 +144,7 @@
|
|||||||
<data name="DeleteLanguage.Text" xml:space="preserve">
|
<data name="DeleteLanguage.Text" xml:space="preserve">
|
||||||
<value>Delete</value>
|
<value>Delete</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Translation" xml:space="preserve">
|
||||||
|
<value>Translation</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -195,4 +195,25 @@
|
|||||||
<data name="Information.Text" xml:space="preserve">
|
<data name="Information.Text" xml:space="preserve">
|
||||||
<value>Information</value>
|
<value>Information</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PackageName.HelpText" xml:space="preserve">
|
||||||
|
<value>The unique name of the package from which this module was installed</value>
|
||||||
|
</data>
|
||||||
|
<data name="PackageName.Text" xml:space="preserve">
|
||||||
|
<value>Package Name:</value>
|
||||||
|
</data>
|
||||||
|
<data name="Error.Translation.Download" xml:space="preserve">
|
||||||
|
<value>Error Downloading Translation</value>
|
||||||
|
</data>
|
||||||
|
<data name="Search.NoResults" xml:space="preserve">
|
||||||
|
<value>No Translations Exist For This Module Or Package Service Is Disabled</value>
|
||||||
|
</data>
|
||||||
|
<data name="Success.Translation.Download" xml:space="preserve">
|
||||||
|
<value>Translation Downloaded Successfully. Click Install To Complete Installation.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Success.Translation.Install" xml:space="preserve">
|
||||||
|
<value>Translation Installed Successfully. You Must <a href={0}>Restart</a> Your Application To Apply These Changes.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Translations.Heading" xml:space="preserve">
|
||||||
|
<value>Translations</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -147,4 +147,7 @@
|
|||||||
<data name="Message.Required.Title" xml:space="preserve">
|
<data name="Message.Required.Title" xml:space="preserve">
|
||||||
<value>You Must Provide A Title For The Module</value>
|
<value>You Must Provide A Title For The Module</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Error.Module.Load" xml:space="preserve">
|
||||||
|
<value>A Problem Was Encountered Loading Module {0}. The Module Is Either Invalid Or Does Not Exist.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@ -160,7 +160,7 @@
|
|||||||
<value>Error Loading Pane Layouts For Theme</value>
|
<value>Error Loading Pane Layouts For Theme</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Message.Page.Exists" xml:space="preserve">
|
<data name="Message.Page.Exists" xml:space="preserve">
|
||||||
<value>A page with path {0} already exists for the selected parent page. The page path needs to be unique for the selected parent.</value>
|
<value>A page with path '{0}' already exists for this site. Page paths must be unique. You may need to check if a page with this path exists in the Recycle Bin.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Message.Required.PageInfo" xml:space="preserve">
|
<data name="Message.Required.PageInfo" xml:space="preserve">
|
||||||
<value>You Must Provide Page Name, Theme, and Container</value>
|
<value>You Must Provide Page Name, Theme, and Container</value>
|
||||||
@ -228,13 +228,13 @@
|
|||||||
<data name="Appearance.Name" xml:space="preserve">
|
<data name="Appearance.Name" xml:space="preserve">
|
||||||
<value>Appearance</value>
|
<value>Appearance</value>
|
||||||
</data>
|
</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>
|
|
||||||
<data name="Meta.HelpText" xml:space="preserve">
|
<data name="Meta.HelpText" xml:space="preserve">
|
||||||
<value>Optionally enter meta tags (in exactly the form you want them to be included in the page output).</value>
|
<value>Optionally enter meta tags (in exactly the form you want them to be included in the page output).</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Meta.Text" xml:space="preserve">
|
<data name="Meta.Text" xml:space="preserve">
|
||||||
<value>Meta:</value>
|
<value>Meta:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Message.Page.Reserved" xml:space="preserve">
|
||||||
|
<value>The page name {0} is reserved. Please enter a different name for your page.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -151,7 +151,7 @@
|
|||||||
<value>Error Loading Pane Layouts For Theme</value>
|
<value>Error Loading Pane Layouts For Theme</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Mesage.Page.PathExists" xml:space="preserve">
|
<data name="Mesage.Page.PathExists" xml:space="preserve">
|
||||||
<value>A page with path {0} already exists for the selected parent page. The page path needs to be unique for the selected parent.</value>
|
<value>A page with path '{0}' already exists for this site. Page paths must be unique. You may need to check if a page with this path exists in the Recycle Bin.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Message.Required.PageInfo" xml:space="preserve">
|
<data name="Message.Required.PageInfo" xml:space="preserve">
|
||||||
<value>You Must Provide Page Name, Theme, and Container</value>
|
<value>You Must Provide Page Name, Theme, and Container</value>
|
||||||
@ -270,4 +270,7 @@
|
|||||||
<data name="Meta.Text" xml:space="preserve">
|
<data name="Meta.Text" xml:space="preserve">
|
||||||
<value>Meta:</value>
|
<value>Meta:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Message.Page.Reserved" xml:space="preserve">
|
||||||
|
<value>The page name {0} is reserved. Please enter a different name for your page.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
<!--
|
||||||
Microsoft ResX Schema
|
Microsoft ResX Schema
|
||||||
@ -166,16 +166,22 @@
|
|||||||
<value>Error Permanently Deleting Modules</value>
|
<value>Error Permanently Deleting Modules</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DeleteAllPages.Header" xml:space="preserve">
|
<data name="DeleteAllPages.Header" xml:space="preserve">
|
||||||
<value>Delete All Pages</value>
|
<value>Remove All Deleted Pages</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DeleteAllPages.Message" xml:space="preserve">
|
<data name="DeleteAllPages.Message" xml:space="preserve">
|
||||||
<value>Are You Sure You Wish To Permanently Delete All Pages?</value>
|
<value>Are You Sure You Wish To Permanently Remove All Deleted Pages?</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeleteAllPages.Text" xml:space="preserve">
|
||||||
|
<value>Remove All Deleted Pages</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DeleteAllModules.Header" xml:space="preserve">
|
<data name="DeleteAllModules.Header" xml:space="preserve">
|
||||||
<value>Delete All Modules</value>
|
<value>Remove All Deleted Modules</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DeleteAllModules.Message" xml:space="preserve">
|
<data name="DeleteAllModules.Message" xml:space="preserve">
|
||||||
<value>Are You Sure You Wish To Permanently Delete All Modules?</value>
|
<value>Are You Sure You Wish To Permanently Remove All Deleted Modules?</value>
|
||||||
|
</data>
|
||||||
|
<data name="DeleteAllModules.Text" xml:space="preserve">
|
||||||
|
<value>Remove All Deleted Modules</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Pages.Heading" xml:space="preserve">
|
<data name="Pages.Heading" xml:space="preserve">
|
||||||
<value>Pages</value>
|
<value>Pages</value>
|
||||||
|
@ -166,7 +166,7 @@
|
|||||||
<value>Enter the tenant for the site</value>
|
<value>Enter the tenant for the site</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Aliases.HelpText" xml:space="preserve">
|
<data name="Aliases.HelpText" xml:space="preserve">
|
||||||
<value>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.</value>
|
<value>The aliases for the site. An alias can be a domain name (www.site.com) or a virtual folder (ie. www.site.com/folder).</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IsDeleted.HelpText" xml:space="preserve">
|
<data name="IsDeleted.HelpText" xml:space="preserve">
|
||||||
<value>Is this site deleted?</value>
|
<value>Is this site deleted?</value>
|
||||||
@ -333,4 +333,10 @@
|
|||||||
<data name="Confirm.Alias.Delete" xml:space="preserve">
|
<data name="Confirm.Alias.Delete" xml:space="preserve">
|
||||||
<value>Are You Sure You Wish To Delete {0}?</value>
|
<value>Are You Sure You Wish To Delete {0}?</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="HomePage.HelpText" xml:space="preserve">
|
||||||
|
<value>Select the home page for the site (to be used if there is no page with a path of '/')</value>
|
||||||
|
</data>
|
||||||
|
<data name="HomePage.Text" xml:space="preserve">
|
||||||
|
<value>Home Page:</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -270,4 +270,16 @@
|
|||||||
<data name="Runtime.Text" xml:space="preserve">
|
<data name="Runtime.Text" xml:space="preserve">
|
||||||
<value>Runtime: </value>
|
<value>Runtime: </value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ConnectionString.HelpText" xml:space="preserve">
|
||||||
|
<value>Enter a complete connection string including all parameters and delimiters</value>
|
||||||
|
</data>
|
||||||
|
<data name="ConnectionString.Text" xml:space="preserve">
|
||||||
|
<value>String:</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnterConnectionParameters" xml:space="preserve">
|
||||||
|
<value>Enter Connection Parameters</value>
|
||||||
|
</data>
|
||||||
|
<data name="EnterConnectionString" xml:space="preserve">
|
||||||
|
<value>Enter Connection String</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -270,4 +270,10 @@
|
|||||||
<data name="WorkingSet.Text" xml:space="preserve">
|
<data name="WorkingSet.Text" xml:space="preserve">
|
||||||
<value>Memory Allocation:</value>
|
<value>Memory Allocation:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Environment.HelpText" xml:space="preserve">
|
||||||
|
<value>Environment Name</value>
|
||||||
|
</data>
|
||||||
|
<data name="Environment.Text" xml:space="preserve">
|
||||||
|
<value>Environment:</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -162,4 +162,10 @@
|
|||||||
<data name="License.HelpText" xml:space="preserve">
|
<data name="License.HelpText" xml:space="preserve">
|
||||||
<value>The license of the theme</value>
|
<value>The license of the theme</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="PackageName.HelpText" xml:space="preserve">
|
||||||
|
<value>The unique name of the package from which this module was installed</value>
|
||||||
|
</data>
|
||||||
|
<data name="PackageName.Text" xml:space="preserve">
|
||||||
|
<value>Package Name:</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -211,25 +211,25 @@
|
|||||||
<value>Allow Login?</value>
|
<value>Allow Login?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Authority.HelpText" xml:space="preserve">
|
<data name="Authority.HelpText" xml:space="preserve">
|
||||||
<value>The Authority Url or Issuer Url associated with the OpenID Connect provider</value>
|
<value>The authority url or issuer url associated with the identity provider</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Authority.Text" xml:space="preserve">
|
<data name="Authority.Text" xml:space="preserve">
|
||||||
<value>Authority:</value>
|
<value>Authority:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AuthorizationUrl.HelpText" xml:space="preserve">
|
<data name="AuthorizationUrl.HelpText" xml:space="preserve">
|
||||||
<value>The endpoint for obtaining an Authorization Code</value>
|
<value>The endpoint for obtaining an authorization code</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AuthorizationUrl.Text" xml:space="preserve">
|
<data name="AuthorizationUrl.Text" xml:space="preserve">
|
||||||
<value>Authorization Url:</value>
|
<value>Authorization Url:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ClientID.HelpText" xml:space="preserve">
|
<data name="ClientID.HelpText" xml:space="preserve">
|
||||||
<value>The Client ID from the provider</value>
|
<value>The client id for the identity provider</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ClientID.Text" xml:space="preserve">
|
<data name="ClientID.Text" xml:space="preserve">
|
||||||
<value>Client ID:</value>
|
<value>Client ID:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ClientSecret.HelpText" xml:space="preserve">
|
<data name="ClientSecret.HelpText" xml:space="preserve">
|
||||||
<value>The Client Secret from the provider</value>
|
<value>The client secret for the identity provider</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ClientSecret.Text" xml:space="preserve">
|
<data name="ClientSecret.Text" xml:space="preserve">
|
||||||
<value>Client Secret:</value>
|
<value>Client Secret:</value>
|
||||||
@ -247,7 +247,7 @@
|
|||||||
<value>Domain Filter:</value>
|
<value>Domain Filter:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EmailClaimType.HelpText" xml:space="preserve">
|
<data name="EmailClaimType.HelpText" xml:space="preserve">
|
||||||
<value>The name of the email address claim provided by the provider</value>
|
<value>The name of the email address claim provided by the identity provider</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EmailClaimType.Text" xml:space="preserve">
|
<data name="EmailClaimType.Text" xml:space="preserve">
|
||||||
<value>Email Claim:</value>
|
<value>Email Claim:</value>
|
||||||
@ -259,7 +259,7 @@
|
|||||||
<value>Lockout Settings</value>
|
<value>Lockout Settings</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MetadataUrl.HelpText" xml:space="preserve">
|
<data name="MetadataUrl.HelpText" xml:space="preserve">
|
||||||
<value>The discovery endpoint for obtaining metadata for this provider. Only specify if the OpenID Connect provider does not use the standard approach (ie. /.well-known/openid-configuration)</value>
|
<value>The discovery endpoint for obtaining metadata for this identity provider. Only specify if the identity provider does not use the standard approach (ie. /.well-known/openid-configuration)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MetadataUrl.Text" xml:space="preserve">
|
<data name="MetadataUrl.Text" xml:space="preserve">
|
||||||
<value>Metadata Url:</value>
|
<value>Metadata Url:</value>
|
||||||
@ -268,7 +268,7 @@
|
|||||||
<value>Password Settings</value>
|
<value>Password Settings</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PKCE.HelpText" xml:space="preserve">
|
<data name="PKCE.HelpText" xml:space="preserve">
|
||||||
<value>Indicate if the provider supports Proof Key for Code Exchange (PKCE)</value>
|
<value>Indicate if the identity provider supports proof key for code exchange (PKCE)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PKCE.Text" xml:space="preserve">
|
<data name="PKCE.Text" xml:space="preserve">
|
||||||
<value>Use PKCE?</value>
|
<value>Use PKCE?</value>
|
||||||
@ -286,25 +286,25 @@
|
|||||||
<value>Provider Type:</value>
|
<value>Provider Type:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RedirectUrl.HelpText" xml:space="preserve">
|
<data name="RedirectUrl.HelpText" xml:space="preserve">
|
||||||
<value>The Redirect Url (or Callback Url) which usually needs to be registered with the provider</value>
|
<value>The redirect url (or callback url) which usually needs to be registered with the identity provider</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RedirectUrl.Text" xml:space="preserve">
|
<data name="RedirectUrl.Text" xml:space="preserve">
|
||||||
<value>Redirect Url:</value>
|
<value>Redirect Url:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Scopes.HelpText" xml:space="preserve">
|
<data name="Scopes.HelpText" xml:space="preserve">
|
||||||
<value>A list of Scopes to request from the provider (separated by commas). If none are specified, standard Scopes will be used by default.</value>
|
<value>A list of scopes to request from the identity provider (separated by commas). If none are specified, standard Scopes will be used by default.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Scopes.Text" xml:space="preserve">
|
<data name="Scopes.Text" xml:space="preserve">
|
||||||
<value>Scopes:</value>
|
<value>Scopes:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TokenUrl.HelpText" xml:space="preserve">
|
<data name="TokenUrl.HelpText" xml:space="preserve">
|
||||||
<value>The endpoint for obtaining an Auth Token</value>
|
<value>The endpoint for obtaining an auth token</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TokenUrl.Text" xml:space="preserve">
|
<data name="TokenUrl.Text" xml:space="preserve">
|
||||||
<value>Token Url:</value>
|
<value>Token Url:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UserInfoUrl.HelpText" xml:space="preserve">
|
<data name="UserInfoUrl.HelpText" xml:space="preserve">
|
||||||
<value>The endpoint for obtaining user information. This should be an API or Page Url which contains the users email address.</value>
|
<value>The endpoint for obtaining user information. This should be an API endpoint or page url which contains the users email address.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UserInfoUrl.Text" xml:space="preserve">
|
<data name="UserInfoUrl.Text" xml:space="preserve">
|
||||||
<value>User Info Url:</value>
|
<value>User Info Url:</value>
|
||||||
@ -373,15 +373,21 @@
|
|||||||
<value>Last Login</value>
|
<value>Last Login</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IdentifierClaimType.HelpText" xml:space="preserve">
|
<data name="IdentifierClaimType.HelpText" xml:space="preserve">
|
||||||
<value>The name of the unique user identifier claim provided by the provider</value>
|
<value>The name of the unique user identifier claim provided by the identity provider</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IdentifierClaimType.Text" xml:space="preserve">
|
<data name="IdentifierClaimType.Text" xml:space="preserve">
|
||||||
<value>Identifier Claim:</value>
|
<value>Identifier Claim:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Parameters.HelpText" xml:space="preserve">
|
<data name="Parameters.HelpText" xml:space="preserve">
|
||||||
<value>Optionally specify any additional parameters as name/value pairs to send to the provider (separated by commas if there are multiple).</value>
|
<value>Optionally specify any additional parameters as name/value pairs to send to the identity provider (separated by commas if there are multiple).</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Parameters.Text" xml:space="preserve">
|
<data name="Parameters.Text" xml:space="preserve">
|
||||||
<value>Parameters:</value>
|
<value>Parameters:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="RoleClaimType.HelpText" xml:space="preserve">
|
||||||
|
<value>Optionally provide the name of the role claim provided by the identity provider. These roles will be used in addition to any internal user roles assigned within the site.</value>
|
||||||
|
</data>
|
||||||
|
<data name="RoleClaimType.Text" xml:space="preserve">
|
||||||
|
<value>Role Claim Type:</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -123,4 +123,10 @@
|
|||||||
<data name="AllowFileManagement.Text" xml:space="preserve">
|
<data name="AllowFileManagement.Text" xml:space="preserve">
|
||||||
<value>Allow File Management: </value>
|
<value>Allow File Management: </value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="AllowRawHtml.HelpText" xml:space="preserve">
|
||||||
|
<value>Specify If Editors Can Enter Raw HTML</value>
|
||||||
|
</data>
|
||||||
|
<data name="AllowRawHtml.Text" xml:space="preserve">
|
||||||
|
<value>Allow Raw HTML:</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -318,6 +318,9 @@
|
|||||||
<data name="BlazorWebAssembly" xml:space="preserve">
|
<data name="BlazorWebAssembly" xml:space="preserve">
|
||||||
<value>Blazor WebAssembly</value>
|
<value>Blazor WebAssembly</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="BlazorHybrid" xml:space="preserve">
|
||||||
|
<value>Blazor Hybrid</value>
|
||||||
|
</data>
|
||||||
<data name="Settings" xml:space="preserve">
|
<data name="Settings" xml:space="preserve">
|
||||||
<value>Settings</value>
|
<value>Settings</value>
|
||||||
</data>
|
</data>
|
||||||
@ -336,4 +339,7 @@
|
|||||||
<data name="Visitor Management" xml:space="preserve">
|
<data name="Visitor Management" xml:space="preserve">
|
||||||
<value>Visitor Management</value>
|
<value>Visitor Management</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Oqtane.Marketplace" xml:space="preserve">
|
||||||
|
<value>Please note that the third party extensions displayed above have been registered in the <a href="https://www.oqtane.net" target="_new">Oqtane Marketplace</a> which enables them to be seamlessly downloaded and installed into the framework.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -138,6 +138,12 @@
|
|||||||
<data name="Register.Text" xml:space="preserve">
|
<data name="Register.Text" xml:space="preserve">
|
||||||
<value>Show Register?</value>
|
<value>Show Register?</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Scope.HelpText" xml:space="preserve">
|
||||||
|
<value>Specify if the settings are applicable to this page or the entire site.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Scope.Text" xml:space="preserve">
|
||||||
|
<value>Setting Scope:</value>
|
||||||
|
</data>
|
||||||
<data name="Site" xml:space="preserve">
|
<data name="Site" xml:space="preserve">
|
||||||
<value>Site</value>
|
<value>Site</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -47,7 +47,7 @@ namespace Oqtane.Services
|
|||||||
var path = WebUtility.UrlEncode(folderPath);
|
var path = WebUtility.UrlEncode(folderPath);
|
||||||
|
|
||||||
List<File> files = await GetJsonAsync<List<File>>($"{Apiurl}/{siteId}/{path}");
|
List<File> files = await GetJsonAsync<List<File>>($"{Apiurl}/{siteId}/{path}");
|
||||||
return files.OrderBy(item => item.Name).ToList();
|
return files?.OrderBy(item => item.Name).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<File> GetFileAsync(int fileId)
|
public async Task<File> GetFileAsync(int fileId)
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
using System;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Oqtane.Documentation;
|
using Oqtane.Documentation;
|
||||||
@ -20,9 +18,7 @@ namespace Oqtane.Services
|
|||||||
|
|
||||||
public async Task<List<Folder>> GetFoldersAsync(int siteId)
|
public async Task<List<Folder>> GetFoldersAsync(int siteId)
|
||||||
{
|
{
|
||||||
List<Folder> folders = await GetJsonAsync<List<Folder>>($"{ApiUrl}?siteid={siteId}");
|
return await GetJsonAsync<List<Folder>>($"{ApiUrl}?siteid={siteId}");
|
||||||
folders = GetFoldersHierarchy(folders);
|
|
||||||
return folders;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Folder> GetFolderAsync(int folderId)
|
public async Task<Folder> GetFolderAsync(int folderId)
|
||||||
@ -58,48 +54,5 @@ namespace Oqtane.Services
|
|||||||
{
|
{
|
||||||
await DeleteAsync($"{ApiUrl}/{folderId}");
|
await DeleteAsync($"{ApiUrl}/{folderId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Folder> GetFoldersHierarchy(List<Folder> folders)
|
|
||||||
{
|
|
||||||
List<Folder> hierarchy = new List<Folder>();
|
|
||||||
Action<List<Folder>, Folder> getPath = null;
|
|
||||||
var folders1 = folders;
|
|
||||||
getPath = (folderList, folder) =>
|
|
||||||
{
|
|
||||||
IEnumerable<Folder> children;
|
|
||||||
int level;
|
|
||||||
if (folder == null)
|
|
||||||
{
|
|
||||||
level = -1;
|
|
||||||
children = folders1.Where(item => item.ParentId == null);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
level = folder.Level;
|
|
||||||
children = folders1.Where(item => item.ParentId == folder.FolderId);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (Folder child in children)
|
|
||||||
{
|
|
||||||
child.Level = level + 1;
|
|
||||||
child.HasChildren = folders1.Any(item => item.ParentId == child.FolderId);
|
|
||||||
hierarchy.Add(child);
|
|
||||||
if (getPath != null) getPath(folderList, child);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
folders = folders.OrderBy(item => item.Order).ToList();
|
|
||||||
getPath(folders, null);
|
|
||||||
|
|
||||||
// add any non-hierarchical items to the end of the list
|
|
||||||
foreach (Folder folder in folders)
|
|
||||||
{
|
|
||||||
if (hierarchy.Find(item => item.FolderId == folder.FolderId) == null)
|
|
||||||
{
|
|
||||||
hierarchy.Add(folder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return hierarchy;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,14 @@ namespace Oqtane.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<List<Language>> GetLanguagesAsync(int siteId);
|
Task<List<Language>> GetLanguagesAsync(int siteId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of all available languages for the given <see cref="Site" /> and package
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="packageName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<List<Language>> GetLanguagesAsync(int siteId, string packageName);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the given language
|
/// Returns the given language
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -50,13 +50,13 @@ namespace Oqtane.Services
|
|||||||
/// <param name="moduleId"></param>
|
/// <param name="moduleId"></param>
|
||||||
/// <param name="content">module in JSON format</param>
|
/// <param name="content">module in JSON format</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<bool> ImportModuleAsync(int moduleId, string content);
|
Task<bool> ImportModuleAsync(int moduleId, int pageId, string content);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Exports a given module
|
/// Exports a given module
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="moduleId"></param>
|
/// <param name="moduleId"></param>
|
||||||
/// <returns>module in JSON</returns>
|
/// <returns>module in JSON</returns>
|
||||||
Task<string> ExportModuleAsync(int moduleId);
|
Task<string> ExportModuleAsync(int moduleId, int pageId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,8 +54,10 @@ namespace Oqtane.Services
|
|||||||
/// Note that this will probably not be a real User, but a user object where the `Username` and `Password` have been filled.
|
/// Note that this will probably not be a real User, but a user object where the `Username` and `Password` have been filled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="user">A <see cref="User"/> object which should have at least the <see cref="User.Username"/> and <see cref="User.Password"/> set.</param>
|
/// <param name="user">A <see cref="User"/> object which should have at least the <see cref="User.Username"/> and <see cref="User.Password"/> set.</param>
|
||||||
|
/// <param name="setCookie">Determines if the login cookie should be set (only relevant for Hybrid scenarios)</param>
|
||||||
|
/// <param name="isPersistent">Determines if the login cookie should be persisted for a long time.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<User> LoginUserAsync(User user);
|
Task<User> LoginUserAsync(User user, bool setCookie, bool isPersistent);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Logout a <see cref="User"/>
|
/// Logout a <see cref="User"/>
|
||||||
|
@ -17,18 +17,27 @@ namespace Oqtane.Services
|
|||||||
|
|
||||||
public async Task<List<Language>> GetLanguagesAsync(int siteId)
|
public async Task<List<Language>> GetLanguagesAsync(int siteId)
|
||||||
{
|
{
|
||||||
var languages = await GetJsonAsync<List<Language>>($"{Apiurl}?siteid={siteId}");
|
return await GetLanguagesAsync(siteId, "");
|
||||||
|
}
|
||||||
|
|
||||||
return languages?.OrderBy(l => l.Name).ToList() ?? Enumerable.Empty<Language>().ToList();
|
public async Task<List<Language>> GetLanguagesAsync(int siteId, string packageName)
|
||||||
|
{
|
||||||
|
return await GetJsonAsync<List<Language>>($"{Apiurl}?siteid={siteId}&packagename={packageName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Language> GetLanguageAsync(int languageId)
|
public async Task<Language> GetLanguageAsync(int languageId)
|
||||||
=> await GetJsonAsync<Language>($"{Apiurl}/{languageId}");
|
{
|
||||||
|
return await GetJsonAsync<Language>($"{Apiurl}/{languageId}");
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<Language> AddLanguageAsync(Language language)
|
public async Task<Language> AddLanguageAsync(Language language)
|
||||||
=> await PostJsonAsync<Language>(Apiurl, language);
|
{
|
||||||
|
return await PostJsonAsync<Language>(Apiurl, language);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task DeleteLanguageAsync(int languageId)
|
public async Task DeleteLanguageAsync(int languageId)
|
||||||
=> await DeleteAsync($"{Apiurl}/{languageId}");
|
{
|
||||||
|
await DeleteAsync($"{Apiurl}/{languageId}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ using System.Net.Http;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Oqtane.Documentation;
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
using Oqtane.Modules.Controls;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
@ -44,14 +45,14 @@ namespace Oqtane.Services
|
|||||||
await DeleteAsync($"{Apiurl}/{moduleId.ToString()}");
|
await DeleteAsync($"{Apiurl}/{moduleId.ToString()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> ImportModuleAsync(int moduleId, string content)
|
public async Task<bool> ImportModuleAsync(int moduleId, int pageId, string content)
|
||||||
{
|
{
|
||||||
return await PostJsonAsync<string,bool>($"{Apiurl}/import?moduleid={moduleId}", content);
|
return await PostJsonAsync<string,bool>($"{Apiurl}/import?moduleid={moduleId}&pageid={pageId}", content);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> ExportModuleAsync(int moduleId)
|
public async Task<string> ExportModuleAsync(int moduleId, int pageId)
|
||||||
{
|
{
|
||||||
return await GetStringAsync($"{Apiurl}/export?moduleid={moduleId}");
|
return await GetStringAsync($"{Apiurl}/export?moduleid={moduleId}&pageid={pageId}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
using System;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Oqtane.Documentation;
|
using Oqtane.Documentation;
|
||||||
|
|
||||||
@ -19,9 +17,7 @@ namespace Oqtane.Services
|
|||||||
|
|
||||||
public async Task<List<Page>> GetPagesAsync(int siteId)
|
public async Task<List<Page>> GetPagesAsync(int siteId)
|
||||||
{
|
{
|
||||||
List<Page> pages = await GetJsonAsync<List<Page>>($"{Apiurl}?siteid={siteId}");
|
return await GetJsonAsync<List<Page>>($"{Apiurl}?siteid={siteId}");
|
||||||
pages = GetPagesHierarchy(pages);
|
|
||||||
return pages;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Page> GetPageAsync(int pageId)
|
public async Task<Page> GetPageAsync(int pageId)
|
||||||
@ -73,45 +69,5 @@ namespace Oqtane.Services
|
|||||||
{
|
{
|
||||||
await DeleteAsync($"{Apiurl}/{pageId}");
|
await DeleteAsync($"{Apiurl}/{pageId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Page> GetPagesHierarchy(List<Page> pages)
|
|
||||||
{
|
|
||||||
List<Page> hierarchy = new List<Page>();
|
|
||||||
Action<List<Page>, Page> getPath = null;
|
|
||||||
getPath = (pageList, page) =>
|
|
||||||
{
|
|
||||||
IEnumerable<Page> children;
|
|
||||||
int level;
|
|
||||||
if (page == null)
|
|
||||||
{
|
|
||||||
level = -1;
|
|
||||||
children = pages.Where(item => item.ParentId == null);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
level = page.Level;
|
|
||||||
children = pages.Where(item => item.ParentId == page.PageId);
|
|
||||||
}
|
|
||||||
foreach (Page child in children)
|
|
||||||
{
|
|
||||||
child.Level = level + 1;
|
|
||||||
child.HasChildren = pages.Any(item => item.ParentId == child.PageId);
|
|
||||||
hierarchy.Add(child);
|
|
||||||
getPath(pageList, child);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
pages = pages.OrderBy(item => item.Order).ToList();
|
|
||||||
getPath(pages, null);
|
|
||||||
|
|
||||||
// add any non-hierarchical items to the end of the list
|
|
||||||
foreach (Page page in pages)
|
|
||||||
{
|
|
||||||
if (hierarchy.Find(item => item.PageId == page.PageId) == null)
|
|
||||||
{
|
|
||||||
hierarchy.Add(page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hierarchy;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,9 +39,9 @@ namespace Oqtane.Services
|
|||||||
await DeleteAsync($"{Apiurl}/{userId}?siteid={siteId}");
|
await DeleteAsync($"{Apiurl}/{userId}?siteid={siteId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<User> LoginUserAsync(User user)
|
public async Task<User> LoginUserAsync(User user, bool setCookie, bool isPersistent)
|
||||||
{
|
{
|
||||||
return await PostJsonAsync<User>($"{Apiurl}/login", user);
|
return await PostJsonAsync<User>($"{Apiurl}/login?setcookie={setCookie}&persistent={isPersistent}", user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task LogoutUserAsync(User user)
|
public async Task LogoutUserAsync(User user)
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private void CloseModal()
|
private void CloseModal()
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo((!string.IsNullOrEmpty(PageState.ReturnUrl)) ? PageState.ReturnUrl : NavigateUrl());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,9 +31,9 @@
|
|||||||
public override List<Resource> Resources => new List<Resource>()
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
{
|
{
|
||||||
// obtained from https://cdnjs.com/libraries
|
// obtained from https://cdnjs.com/libraries
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/css/bootstrap.min.css", Integrity = "sha512-GQGU0fMMi238uA+a/bdWJfpUGKUkBdgfFdgBm72SUQ6BeyWjoY/ton0tEjH+OSH9iP4Dfh+7HM0I9f5eR0L/4w==", CrossOrigin = "anonymous" },
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.0/css/bootstrap.min.css", Integrity = "sha512-XWTTruHZEYJsxV3W/lSXG1n3Q39YIWOstqvmFsdNEEQfHoZ6vm6E9GK2OrF6DSJSpIbRbi+Nn0WDPID9O7xB2Q==", CrossOrigin = "anonymous" },
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" },
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" },
|
||||||
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/js/bootstrap.bundle.min.js", Integrity = "sha512-pax4MlgXjHEPfCwcJLQhigY7+N8rt6bVvWLFyUMuxShv170X53TRzGPmPkZmGBhk+jikR8WBM4yl7A9WMHHqvg==", CrossOrigin = "anonymous" }
|
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.0/js/bootstrap.bundle.min.js", Integrity = "sha512-9GacT4119eY3AcosfWtHMsT5JyZudrexyEVzTBWV3viP/YfB9e2pEy3N7WXL3SV6ASXpTU0vzzSxsbfsuUH4sQ==", CrossOrigin = "anonymous" }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -2,44 +2,44 @@
|
|||||||
@inherits ModuleActionsBase
|
@inherits ModuleActionsBase
|
||||||
@attribute [OqtaneIgnore]
|
@attribute [OqtaneIgnore]
|
||||||
|
|
||||||
@if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, ModuleState.Permissions) && PageState.Action == Constants.DefaultAction)
|
@if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions) && PageState.Action == Constants.DefaultAction)
|
||||||
{
|
{
|
||||||
<div class="app-moduleactions">
|
<div class="app-moduleactions py-2 px-3">
|
||||||
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"></a>
|
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"></a>
|
||||||
<ul class="dropdown-menu" x-placement="bottom-start" style="position: absolute; will-change: transform; top: 0px; left: 0px; transform: translate3d(0px, 37px, 0px);">
|
<ul class="dropdown-menu" x-placement="bottom-start" style="position: absolute; will-change: transform; top: 0px; left: 0px; transform: translate3d(0px, 37px, 0px);">
|
||||||
@foreach (var action in Actions.Where(item => !item.Name.Contains("Pane")))
|
@foreach (var action in Actions.Where(item => !item.Name.Contains("Pane")))
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(action.Name))
|
if (string.IsNullOrEmpty(action.Name))
|
||||||
{
|
{
|
||||||
<li class="dropdown-divider"></li>
|
<li class="dropdown-divider"></li>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<li>
|
<li>
|
||||||
<a class="dropdown-item" @onclick="(async () => await ModuleAction(action))">
|
<a class="dropdown-item" @onclick="(async () => await ModuleAction(action))">
|
||||||
<span class="@action.Icon" aria-hidden="true"></span> @action.Name
|
<span class="@action.Icon" aria-hidden="true"></span> @action.Name
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@if (Actions.Where(item => item.Name.Contains("Pane")).Any())
|
@if (Actions.Where(item => item.Name.Contains("Pane")).Any())
|
||||||
{
|
{
|
||||||
<li class="dropdown-submenu">
|
<li class="dropdown-submenu">
|
||||||
<a class="dropdown-item" onclick="return subMenu(this)">
|
<a class="dropdown-item" onclick="return subMenu(this)">
|
||||||
<span class="@Icons.AccountLogin" aria-hidden="true"></span> Move To >
|
<span class="@Icons.AccountLogin" aria-hidden="true"></span> Move To >
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
@foreach (var action in Actions.Where(item => item.Name.Contains("Pane")))
|
@foreach (var action in Actions.Where(item => item.Name.Contains("Pane")))
|
||||||
{
|
{
|
||||||
<li>
|
<li>
|
||||||
<a class="dropdown-item" @onclick="(async () => await ModuleAction(action))">
|
<a class="dropdown-item" @onclick="(async () => await ModuleAction(action))">
|
||||||
<span class="@action.Icon" aria-hidden="true"></span> @action.Name
|
<span class="@action.Icon" aria-hidden="true"></span> @action.Name
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -29,54 +29,55 @@ namespace Oqtane.Themes.Controls
|
|||||||
protected virtual List<ActionViewModel> GetActions()
|
protected virtual List<ActionViewModel> GetActions()
|
||||||
{
|
{
|
||||||
var actionList = new List<ActionViewModel>();
|
var actionList = new List<ActionViewModel>();
|
||||||
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, ModuleState.Permissions))
|
|
||||||
{
|
|
||||||
actionList.Add(new ActionViewModel {Icon = Icons.Cog, Name = "Manage Settings", Action = async (u, m) => await Settings(u, m)});
|
|
||||||
|
|
||||||
if (UserSecurity.GetPermissionStrings(ModuleState.Permissions).FirstOrDefault(item => item.PermissionName == PermissionNames.View).Permissions.Split(';').Contains(RoleNames.Everyone))
|
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
||||||
|
{
|
||||||
|
actionList.Add(new ActionViewModel { Icon = Icons.Cog, Name = "Manage Settings", Action = async (u, m) => await Settings(u, m) });
|
||||||
|
|
||||||
|
if (UserSecurity.ContainsRole(ModuleState.Permissions, PermissionNames.View, RoleNames.Everyone))
|
||||||
{
|
{
|
||||||
actionList.Add(new ActionViewModel {Icon=Icons.CircleX, Name = "Unpublish Module", Action = async (s, m) => await Unpublish(s, m) });
|
actionList.Add(new ActionViewModel { Icon = Icons.CircleX, Name = "Unpublish Module", Action = async (s, m) => await Unpublish(s, m) });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
actionList.Add(new ActionViewModel {Icon=Icons.CircleCheck, Name = "Publish Module", Action = async (s, m) => await Publish(s, m) });
|
actionList.Add(new ActionViewModel { Icon = Icons.CircleCheck, Name = "Publish Module", Action = async (s, m) => await Publish(s, m) });
|
||||||
}
|
}
|
||||||
actionList.Add(new ActionViewModel {Icon=Icons.Trash, Name = "Delete Module", Action = async (u, m) => await DeleteModule(u, m) });
|
actionList.Add(new ActionViewModel { Icon = Icons.Trash, Name = "Delete Module", Action = async (u, m) => await DeleteModule(u, m) });
|
||||||
|
|
||||||
if (ModuleState.ModuleDefinition != null && ModuleState.ModuleDefinition.ServerManagerType != "")
|
if (ModuleState.ModuleDefinition != null && ModuleState.ModuleDefinition.ServerManagerType != "")
|
||||||
{
|
{
|
||||||
actionList.Add(new ActionViewModel { Name = "" });
|
actionList.Add(new ActionViewModel { Name = "" });
|
||||||
actionList.Add(new ActionViewModel {Icon=Icons.CloudUpload, Name = "Import Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Import")});
|
actionList.Add(new ActionViewModel { Icon = Icons.CloudUpload, Name = "Import Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Import") });
|
||||||
actionList.Add(new ActionViewModel {Icon = Icons.CloudDownload, Name = "Export Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Export")});
|
actionList.Add(new ActionViewModel { Icon = Icons.CloudDownload, Name = "Export Content", Action = async (u, m) => await EditUrlAsync(u, m.ModuleId, "Export") });
|
||||||
}
|
}
|
||||||
|
|
||||||
actionList.Add(new ActionViewModel {Name = ""});
|
actionList.Add(new ActionViewModel { Name = "" });
|
||||||
|
|
||||||
if (ModuleState.PaneModuleIndex > 0)
|
if (ModuleState.PaneModuleIndex > 0)
|
||||||
{
|
{
|
||||||
actionList.Add(new ActionViewModel {Icon = Icons.DataTransferUpload ,Name = "Move To Top", Action = async (s, m) => await MoveTop(s, m)});
|
actionList.Add(new ActionViewModel { Icon = Icons.DataTransferUpload, Name = "Move To Top", Action = async (s, m) => await MoveTop(s, m) });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ModuleState.PaneModuleIndex > 0)
|
if (ModuleState.PaneModuleIndex > 0)
|
||||||
{
|
{
|
||||||
actionList.Add(new ActionViewModel {Icon = Icons.ArrowThickTop, Name = "Move Up", Action = async (s, m) => await MoveUp(s, m)});
|
actionList.Add(new ActionViewModel { Icon = Icons.ArrowThickTop, Name = "Move Up", Action = async (s, m) => await MoveUp(s, m) });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1))
|
if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1))
|
||||||
{
|
{
|
||||||
actionList.Add(new ActionViewModel {Icon = Icons.ArrowThickBottom, Name = "Move Down", Action = async (s, m) => await MoveDown(s, m)});
|
actionList.Add(new ActionViewModel { Icon = Icons.ArrowThickBottom, Name = "Move Down", Action = async (s, m) => await MoveDown(s, m) });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1))
|
if (ModuleState.PaneModuleIndex < (ModuleState.PaneModuleCount - 1))
|
||||||
{
|
{
|
||||||
actionList.Add(new ActionViewModel {Icon = Icons.DataTransferDownload, Name = "Move To Bottom", Action = async (s, m) => await MoveBottom(s, m)});
|
actionList.Add(new ActionViewModel { Icon = Icons.DataTransferDownload, Name = "Move To Bottom", Action = async (s, m) => await MoveBottom(s, m) });
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (string pane in PageState.Page.Panes)
|
foreach (string pane in PageState.Page.Panes)
|
||||||
{
|
{
|
||||||
if (pane != ModuleState.Pane)
|
if (pane != ModuleState.Pane)
|
||||||
{
|
{
|
||||||
actionList.Add(new ActionViewModel {Icon = Icons.AccountLogin, Name = pane + " Pane", Action = async (s, m) => await MoveToPane(s, pane, m)});
|
actionList.Add(new ActionViewModel { Icon = Icons.AccountLogin, Name = pane + " Pane", Action = async (s, m) => await MoveToPane(s, pane, m) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
|
@using System.ComponentModel
|
||||||
@namespace Oqtane.Themes.Controls
|
@namespace Oqtane.Themes.Controls
|
||||||
@inherits ContainerBase
|
@inherits ContainerBase
|
||||||
@attribute [OqtaneIgnore]
|
@attribute [OqtaneIgnore]
|
||||||
|
@inject SiteState SiteState
|
||||||
|
|
||||||
<span class="app-moduletitle">
|
<span class="app-moduletitle">
|
||||||
<a id="@ModuleState.PageModuleId.ToString()">
|
<a id="@ModuleState.PageModuleId.ToString()">
|
||||||
@ -9,17 +11,39 @@
|
|||||||
</span>
|
</span>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string title = "";
|
private string title = "";
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(ModuleState.ControlTitle))
|
((INotifyPropertyChanged)SiteState.Properties).PropertyChanged += PropertyChanged;
|
||||||
{
|
}
|
||||||
title = ModuleState.ControlTitle;
|
|
||||||
}
|
protected override void OnParametersSet()
|
||||||
else
|
{
|
||||||
{
|
if (!string.IsNullOrEmpty(ModuleState.ControlTitle))
|
||||||
title = ModuleState.Title;
|
{
|
||||||
}
|
title = ModuleState.ControlTitle;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
title = ModuleState.Title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.PropertyName == "ModuleTitle")
|
||||||
|
{
|
||||||
|
if (SiteState.Properties.ModuleTitle.PageModuleId == ModuleState.PageModuleId)
|
||||||
|
{
|
||||||
|
title = SiteState.Properties.ModuleTitle.Title;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
((INotifyPropertyChanged)SiteState.Properties).PropertyChanged -= PropertyChanged;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<LanguageSwitcher />
|
<LanguageSwitcher />
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions) || (PageState.Page.IsPersonalizable && PageState.User != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Registered)))
|
@if (_showEditMode || (PageState.Page.IsPersonalizable && PageState.User != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Registered)))
|
||||||
{
|
{
|
||||||
if (PageState.EditMode)
|
if (PageState.EditMode)
|
||||||
{
|
{
|
||||||
@ -70,7 +70,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row d-flex">
|
<div class="row d-flex">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
@if (UserSecurity.GetPermissionStrings(PageState.Page.Permissions).FirstOrDefault(item => item.PermissionName == PermissionNames.View).Permissions.Split(';').Contains(RoleNames.Everyone))
|
@if (UserSecurity.ContainsRole(PageState.Page.Permissions, PermissionNames.View, RoleNames.Everyone))
|
||||||
{
|
{
|
||||||
<button type="button" class="btn btn-secondary col-12" @onclick=@(async () => Publish("unpublish"))>@Localizer["Page.Unpublish"]</button>
|
<button type="button" class="btn btn-secondary col-12" @onclick=@(async () => Publish("unpublish"))>@Localizer["Page.Unpublish"]</button>
|
||||||
}
|
}
|
||||||
@ -218,6 +218,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code{
|
@code{
|
||||||
|
private bool _showEditMode = false;
|
||||||
private bool _deleteConfirmation = false;
|
private bool _deleteConfirmation = false;
|
||||||
private List<string> _categories = new List<string>();
|
private List<string> _categories = new List<string>();
|
||||||
private List<ModuleDefinition> _allModuleDefinitions;
|
private List<ModuleDefinition> _allModuleDefinitions;
|
||||||
@ -285,8 +286,10 @@
|
|||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
|
_showEditMode = false;
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
||||||
{
|
{
|
||||||
|
_showEditMode = true;
|
||||||
_pages?.Clear();
|
_pages?.Clear();
|
||||||
|
|
||||||
foreach (Page p in PageState.Pages)
|
foreach (Page p in PageState.Pages)
|
||||||
@ -305,6 +308,17 @@
|
|||||||
_moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(Category)).ToList();
|
_moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(Category)).ToList();
|
||||||
_categories = _allModuleDefinitions.SelectMany(m => m.Categories.Split(',')).Distinct().ToList();
|
_categories = _allModuleDefinitions.SelectMany(m => m.Categories.Split(',')).Distinct().ToList();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var module in PageState.Modules.Where(item => item.PageId == PageState.Page.PageId))
|
||||||
|
{
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, module.Permissions))
|
||||||
|
{
|
||||||
|
_showEditMode = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CategoryChanged(ChangeEventArgs e)
|
private void CategoryChanged(ChangeEventArgs e)
|
||||||
@ -405,165 +419,178 @@
|
|||||||
Message = $"<div class=\"alert alert-success mt-2 text-center\" role=\"alert\">{Localizer["Success.Page.ModuleAdd"]}</div>";
|
Message = $"<div class=\"alert alert-success mt-2 text-center\" role=\"alert\">{Localizer["Success.Page.ModuleAdd"]}</div>";
|
||||||
Title = "";
|
Title = "";
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Message = $"<div class=\"alert alert-warning mt-2 text-center\" 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
|
else
|
||||||
{
|
{
|
||||||
Message = $"<div class=\"alert alert-error mt-2 text-center\" role=\"alert\">{Localizer["Error.Authorize.No"]}</div>";
|
Message = $"<div class=\"alert alert-error mt-2 text-center\" role=\"alert\">{Localizer["Error.Authorize.No"]}</div>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ToggleEditMode(bool EditMode)
|
private async Task ToggleEditMode(bool EditMode)
|
||||||
{
|
{
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
if (_showEditMode)
|
||||||
{
|
{
|
||||||
if (EditMode)
|
if (EditMode)
|
||||||
{
|
{
|
||||||
PageState.EditMode = false;
|
PageState.EditMode = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PageState.EditMode = true;
|
PageState.EditMode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "edit=" + ((PageState.EditMode) ? "1" : "0")));
|
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "edit=" + ((PageState.EditMode) ? "1" : "0")));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (PageState.Page.IsPersonalizable && PageState.User != null)
|
if (PageState.Page.IsPersonalizable && PageState.User != null)
|
||||||
{
|
{
|
||||||
await PageService.AddPageAsync(PageState.Page.PageId, PageState.User.UserId);
|
await PageService.AddPageAsync(PageState.Page.PageId, PageState.User.UserId);
|
||||||
PageState.EditMode = true;
|
PageState.EditMode = true;
|
||||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "edit=" + ((PageState.EditMode) ? "1" : "0")));
|
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "edit=" + ((PageState.EditMode) ? "1" : "0")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Navigate(string location)
|
private void Navigate(string location)
|
||||||
{
|
{
|
||||||
//HideControlPanel();
|
Module module;
|
||||||
Module module;
|
switch (location)
|
||||||
switch (location)
|
{
|
||||||
{
|
case "Admin":
|
||||||
case "Admin":
|
// get admin dashboard moduleid
|
||||||
// get admin dashboard moduleid
|
module = PageState.Modules.FirstOrDefault(item => item.ModuleDefinitionName == Constants.AdminDashboardModule);
|
||||||
module = PageState.Modules.FirstOrDefault(item => item.ModuleDefinitionName == Constants.AdminDashboardModule);
|
|
||||||
|
|
||||||
if (module != null)
|
if (module != null)
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(EditUrl(PageState.Page.Path, module.ModuleId, "Index", ""));
|
NavigationManager.NavigateTo(EditUrl(PageState.Page.Path, module.ModuleId, "Index", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "Add":
|
case "Add":
|
||||||
case "Edit":
|
case "Edit":
|
||||||
string url = "";
|
string url = "";
|
||||||
// get page management moduleid
|
// get page management moduleid
|
||||||
module = PageState.Modules.FirstOrDefault(item => item.ModuleDefinitionName == Constants.PageManagementModule);
|
module = PageState.Modules.FirstOrDefault(item => item.ModuleDefinitionName == Constants.PageManagementModule);
|
||||||
|
|
||||||
if (module != null)
|
if (module != null)
|
||||||
{
|
{
|
||||||
switch (location)
|
switch (location)
|
||||||
{
|
{
|
||||||
case "Add":
|
case "Add":
|
||||||
url = EditUrl(PageState.Page.Path, module.ModuleId, location, "cp=" + PageState.Page.PageId);
|
url = EditUrl(PageState.Page.Path, module.ModuleId, location, "cp=" + PageState.Page.PageId);
|
||||||
break;
|
break;
|
||||||
case "Edit":
|
case "Edit":
|
||||||
url = EditUrl(PageState.Page.Path, module.ModuleId, location, "id=" + PageState.Page.PageId.ToString() + "&cp=" + PageState.Page.PageId);
|
url = EditUrl(PageState.Page.Path, module.ModuleId, location, "id=" + PageState.Page.PageId.ToString() + "&cp=" + PageState.Page.PageId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url != "")
|
if (url != "")
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(url);
|
NavigationManager.NavigateTo(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Publish(string action)
|
private async void Publish(string action)
|
||||||
{
|
{
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions))
|
||||||
{
|
{
|
||||||
List<PermissionString> permissions;
|
List<PermissionString> permissions;
|
||||||
|
|
||||||
// publish/unpublish page
|
// publish/unpublish page
|
||||||
var page = PageState.Page;
|
var page = PageState.Page;
|
||||||
permissions = UserSecurity.GetPermissionStrings(page.Permissions);
|
permissions = UserSecurity.GetPermissionStrings(page.Permissions);
|
||||||
foreach (var permissionstring in permissions)
|
foreach (var permissionstring in permissions)
|
||||||
{
|
{
|
||||||
if (permissionstring.PermissionName == PermissionNames.View)
|
if (permissionstring.PermissionName == PermissionNames.View)
|
||||||
{
|
{
|
||||||
List<string> ids = permissionstring.Permissions.Split(';').ToList();
|
List<string> ids = permissionstring.Permissions.Split(';').ToList();
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
case "publish":
|
case "publish":
|
||||||
if (!ids.Contains(RoleNames.Everyone)) ids.Add(RoleNames.Everyone);
|
if (!ids.Contains(RoleNames.Everyone)) ids.Add(RoleNames.Everyone);
|
||||||
if (!ids.Contains(RoleNames.Registered)) ids.Add(RoleNames.Registered);
|
if (!ids.Contains(RoleNames.Registered)) ids.Add(RoleNames.Registered);
|
||||||
break;
|
break;
|
||||||
case "unpublish":
|
case "unpublish":
|
||||||
ids.Remove(RoleNames.Everyone);
|
ids.Remove(RoleNames.Everyone);
|
||||||
ids.Remove(RoleNames.Registered);
|
ids.Remove(RoleNames.Registered);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
permissionstring.Permissions = string.Join(";", ids.ToArray());
|
permissionstring.Permissions = string.Join(";", ids.ToArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
page.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
page.Permissions = UserSecurity.SetPermissionStrings(permissions);
|
||||||
await PageService.UpdatePageAsync(page);
|
await PageService.UpdatePageAsync(page);
|
||||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, true));
|
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConfirmDelete()
|
private void ConfirmDelete()
|
||||||
{
|
{
|
||||||
_deleteConfirmation = !_deleteConfirmation;
|
_deleteConfirmation = !_deleteConfirmation;
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DeletePage()
|
private async Task DeletePage()
|
||||||
{
|
{
|
||||||
ConfirmDelete();
|
ConfirmDelete();
|
||||||
|
|
||||||
var page = PageState.Page;
|
var page = PageState.Page;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (page.UserId == null)
|
if (page.UserId == null)
|
||||||
{
|
{
|
||||||
page.IsDeleted = true;
|
page.IsDeleted = true;
|
||||||
await PageService.UpdatePageAsync(page);
|
await PageService.UpdatePageAsync(page);
|
||||||
await logger.Log(page.PageId, null, PageState.User.UserId, GetType().AssemblyQualifiedName, "ControlPanel", LogFunction.Delete, LogLevel.Information, null, "Page Deleted {Page}", page);
|
await logger.Log(page.PageId, null, PageState.User.UserId, GetType().AssemblyQualifiedName, "ControlPanel", LogFunction.Delete, LogLevel.Information, null, "Page Deleted {Page}", page);
|
||||||
NavigationManager.NavigateTo(NavigateUrl(""));
|
NavigationManager.NavigateTo(NavigateUrl(""));
|
||||||
}
|
}
|
||||||
else // personalized page
|
else // personalized page
|
||||||
{
|
{
|
||||||
await PageService.DeletePageAsync(page.PageId);
|
await PageService.DeletePageAsync(page.PageId);
|
||||||
await logger.Log(page.PageId, null, PageState.User.UserId, GetType().AssemblyQualifiedName, "ControlPanel", LogFunction.Delete, LogLevel.Information, null, "Page Deleted {Page}", page);
|
await logger.Log(page.PageId, null, PageState.User.UserId, GetType().AssemblyQualifiedName, "ControlPanel", LogFunction.Delete, LogLevel.Information, null, "Page Deleted {Page}", page);
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.Log(page.PageId, null, PageState.User.UserId, GetType().AssemblyQualifiedName, "ControlPanel", LogFunction.Delete, LogLevel.Information, ex, "Page Deleted {Page} {Error}", page, ex.Message);
|
await logger.Log(page.PageId, null, PageState.User.UserId, GetType().AssemblyQualifiedName, "ControlPanel", LogFunction.Delete, LogLevel.Information, ex, "Page Deleted {Page} {Error}", page, ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string settingCategory = "CP-category";
|
private string settingCategory = "CP-category";
|
||||||
private string settingPane = "CP-pane";
|
private string settingPane = "CP-pane";
|
||||||
private string _pane = "";
|
private string _pane = "";
|
||||||
|
|
||||||
private async Task LoadSettingsAsync()
|
private async Task LoadSettingsAsync()
|
||||||
{
|
{
|
||||||
Dictionary<string, string> settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
Dictionary<string, string> settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
||||||
_category = SettingService.GetSetting(settings, settingCategory, "Common");
|
_category = SettingService.GetSetting(settings, settingCategory, "Common");
|
||||||
var pane = SettingService.GetSetting(settings, settingPane, "");
|
var pane = SettingService.GetSetting(settings, settingPane, "");
|
||||||
_pane = PageState.Page.Panes.Contains(pane) ? pane : PaneNames.Admin;
|
if (PageState.Page.Panes.Contains(pane))
|
||||||
|
{
|
||||||
|
_pane = pane;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (PageState.Page.Panes.FindIndex(item => item.Equals(PaneNames.Default, StringComparison.OrdinalIgnoreCase)) != -1)
|
||||||
|
{
|
||||||
|
_pane = PaneNames.Default;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_pane = PaneNames.Admin;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateSettingsAsync()
|
private async Task UpdateSettingsAsync()
|
||||||
|
@ -24,13 +24,9 @@
|
|||||||
@code{
|
@code{
|
||||||
private IEnumerable<Culture> _supportedCultures;
|
private IEnumerable<Culture> _supportedCultures;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override void OnParametersSet()
|
||||||
{
|
{
|
||||||
var languages = await LanguageService.GetLanguagesAsync(PageState.Site.SiteId);
|
var languages = PageState.Languages;
|
||||||
var defaultCulture = CultureInfo.GetCultureInfo(Constants.DefaultCulture);
|
|
||||||
|
|
||||||
languages.Add(new Language { Code = defaultCulture.Name, Name = defaultCulture.DisplayName });
|
|
||||||
|
|
||||||
_supportedCultures = languages.Select(l => new Culture { Name = l.Code, DisplayName = l.Name });
|
_supportedCultures = languages.Select(l => new Culture { Name = l.Code, DisplayName = l.Name });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ using System.Threading.Tasks;
|
|||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
using Oqtane.Enums;
|
using Oqtane.Enums;
|
||||||
|
using Oqtane.Providers;
|
||||||
using Oqtane.Security;
|
using Oqtane.Security;
|
||||||
using Oqtane.Services;
|
using Oqtane.Services;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
@ -40,10 +41,21 @@ namespace Oqtane.Themes.Controls
|
|||||||
url = PageState.Alias.Path;
|
url = PageState.Alias.Path;
|
||||||
}
|
}
|
||||||
|
|
||||||
// post to the Logout page to complete the logout process
|
if (PageState.Runtime == Shared.Runtime.Hybrid)
|
||||||
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, returnurl = url };
|
{
|
||||||
var interop = new Interop(jsRuntime);
|
// hybrid apps utilize an interactive logout
|
||||||
await interop.SubmitForm(Utilities.TenantUrl(PageState.Alias, "/pages/logout/"), fields);
|
await UserService.LogoutUserAsync(PageState.User);
|
||||||
|
var authstateprovider = (IdentityAuthenticationStateProvider)ServiceProvider.GetService(typeof(IdentityAuthenticationStateProvider));
|
||||||
|
authstateprovider.NotifyAuthenticationChanged();
|
||||||
|
NavigationManager.NavigateTo(url, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// post to the Logout page to complete the logout process
|
||||||
|
var fields = new { __RequestVerificationToken = SiteState.AntiForgeryToken, returnurl = url };
|
||||||
|
var interop = new Interop(jsRuntime);
|
||||||
|
await interop.SubmitForm(Utilities.TenantUrl(PageState.Alias, "/pages/logout/"), fields);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,11 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<Pane Name="@PaneNames.Admin" />
|
<Pane Name="@PaneNames.Default" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Pane Name="Top Full Width" />
|
<Pane Name="Top Full Width" />
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
@ -102,20 +102,20 @@
|
|||||||
{
|
{
|
||||||
<Pane Name="Footer" />
|
<Pane Name="Footer" />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
public override string Name => "Default Theme";
|
public override string Name => "Default Theme";
|
||||||
|
|
||||||
public override string Panes => PaneNames.Admin + ",Top Full Width,Top 100%,Left 50%,Right 50%,Left 33%,Center 33%,Right 33%,Left Outer 25%,Left Inner 25%,Right Inner 25%,Right Outer 25%,Left 25%,Center 50%,Right 25%,Left Sidebar 66%,Right Sidebar 33%,Left Sidebar 33%,Right Sidebar 66%,Bottom 100%,Bottom Full Width,Footer";
|
public override string Panes => PaneNames.Default + ",Top Full Width,Top 100%,Left 50%,Right 50%,Left 33%,Center 33%,Right 33%,Left Outer 25%,Left Inner 25%,Right Inner 25%,Right Outer 25%,Left 25%,Center 50%,Right 25%,Left Sidebar 66%,Right Sidebar 33%,Left Sidebar 33%,Right Sidebar 66%,Bottom 100%,Bottom Full Width,Footer";
|
||||||
|
|
||||||
public override List<Resource> Resources => new List<Resource>()
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
{
|
{
|
||||||
// obtained from https://cdnjs.com/libraries
|
// obtained from https://cdnjs.com/libraries
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.1.3/cyborg/bootstrap.min.css", Integrity = "sha512-/in5IWTUhb7wOUd6iHotlyrLrZ7+2utJJR8ySzSxeeOMJ9fanjCr4fmyWzDW/ziw56shUNTVClBMWZaA677VhA==", CrossOrigin = "anonymous" },
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.2.0/cyborg/bootstrap.min.css", Integrity = "sha512-d6pZJl/sNcj0GFkp4kTjXtPE14deuUsOqFQtxkj0KyBJQl+4e0qsEyuIDcNqrYuGoauAW3sWyDCQp49mhF4Syw==", CrossOrigin = "anonymous" },
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" },
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" },
|
||||||
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/js/bootstrap.bundle.min.js", Integrity = "sha512-pax4MlgXjHEPfCwcJLQhigY7+N8rt6bVvWLFyUMuxShv170X53TRzGPmPkZmGBhk+jikR8WBM4yl7A9WMHHqvg==", CrossOrigin = "anonymous" }
|
new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.0/js/bootstrap.bundle.min.js", Integrity = "sha512-9GacT4119eY3AcosfWtHMsT5JyZudrexyEVzTBWV3viP/YfB9e2pEy3N7WXL3SV6ASXpTU0vzzSxsbfsuUH4sQ==", CrossOrigin = "anonymous" }
|
||||||
};
|
};
|
||||||
|
|
||||||
private bool _login = true;
|
private bool _login = true;
|
||||||
|
@ -3,6 +3,7 @@ using Microsoft.JSInterop;
|
|||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
using Oqtane.UI;
|
using Oqtane.UI;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -34,7 +35,8 @@ namespace Oqtane.Themes
|
|||||||
var scripts = new List<object>();
|
var scripts = new List<object>();
|
||||||
foreach (Resource resource in Resources.Where(item => item.ResourceType == ResourceType.Script))
|
foreach (Resource resource in Resources.Where(item => item.ResourceType == ResourceType.Script))
|
||||||
{
|
{
|
||||||
scripts.Add(new { href = resource.Url, bundle = resource.Bundle ?? "", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "", es6module = resource.ES6Module });
|
var url = (resource.Url.Contains("://")) ? resource.Url : PageState.Alias.BaseUrl + resource.Url;
|
||||||
|
scripts.Add(new { href = url, bundle = resource.Bundle ?? "", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "", es6module = resource.ES6Module });
|
||||||
}
|
}
|
||||||
if (scripts.Any())
|
if (scripts.Any())
|
||||||
{
|
{
|
||||||
@ -49,7 +51,7 @@ namespace Oqtane.Themes
|
|||||||
|
|
||||||
public string ThemePath()
|
public string ThemePath()
|
||||||
{
|
{
|
||||||
return "Themes/" + GetType().Namespace + "/";
|
return PageState?.Alias.BaseUrl + "/Themes/" + GetType().Namespace + "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
// url methods
|
// url methods
|
||||||
@ -94,14 +96,23 @@ namespace Oqtane.Themes
|
|||||||
return Utilities.EditUrl(PageState.Alias.Path, path, moduleid, action, parameters);
|
return Utilities.EditUrl(PageState.Alias.Path, path, moduleid, action, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ContentUrl(int fileid)
|
public string FileUrl(string folderpath, string filename)
|
||||||
{
|
{
|
||||||
return Utilities.ContentUrl(PageState.Alias, fileid);
|
return FileUrl(folderpath, filename, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ContentUrl(int fileid, bool asAttachment)
|
public string FileUrl(string folderpath, string filename, bool download)
|
||||||
{
|
{
|
||||||
return Utilities.ContentUrl(PageState.Alias, fileid, asAttachment);
|
return Utilities.FileUrl(PageState.Alias, folderpath, filename, download);
|
||||||
|
}
|
||||||
|
public string FileUrl(int fileid)
|
||||||
|
{
|
||||||
|
return FileUrl(fileid, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FileUrl(int fileid, bool download)
|
||||||
|
{
|
||||||
|
return Utilities.FileUrl(PageState.Alias, fileid, download);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ImageUrl(int fileid, int width, int height)
|
public string ImageUrl(int fileid, int width, int height)
|
||||||
@ -118,5 +129,17 @@ namespace Oqtane.Themes
|
|||||||
{
|
{
|
||||||
return Utilities.ImageUrl(PageState.Alias, fileid, width, height, mode, position, background, rotate, recreate);
|
return Utilities.ImageUrl(PageState.Alias, fileid, width, height, mode, position, background, rotate, recreate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete("ContentUrl(int fileId) is deprecated. Use FileUrl(int fileId) instead.", false)]
|
||||||
|
public string ContentUrl(int fileid)
|
||||||
|
{
|
||||||
|
return ContentUrl(fileid, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete("ContentUrl(int fileId, bool asAttachment) is deprecated. Use FileUrl(int fileId, bool download) instead.", false)]
|
||||||
|
public string ContentUrl(int fileid, bool asAttachment)
|
||||||
|
{
|
||||||
|
return Utilities.FileUrl(PageState.Alias, fileid, asAttachment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,26 @@
|
|||||||
|
@using System.ComponentModel
|
||||||
@namespace Oqtane.UI
|
@namespace Oqtane.UI
|
||||||
|
@inject SiteState SiteState
|
||||||
|
|
||||||
<CascadingValue Value="@ModuleState">
|
@if (_visible)
|
||||||
@if (_useadminborder)
|
{
|
||||||
{
|
<CascadingValue Value="@ModuleState">
|
||||||
<div class="app-pane-admin-border">
|
@if (_useadminborder)
|
||||||
@DynamicComponent
|
{
|
||||||
</div>
|
<div class="app-pane-admin-border">
|
||||||
}
|
@DynamicComponent
|
||||||
else
|
</div>
|
||||||
{
|
}
|
||||||
@DynamicComponent
|
else
|
||||||
}
|
{
|
||||||
</CascadingValue>
|
@DynamicComponent
|
||||||
|
}
|
||||||
|
</CascadingValue>
|
||||||
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private bool _useadminborder = false;
|
private bool _visible = true;
|
||||||
|
private bool _useadminborder = false;
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
protected PageState PageState { get; set; }
|
protected PageState PageState { get; set; }
|
||||||
@ -24,7 +30,12 @@
|
|||||||
|
|
||||||
RenderFragment DynamicComponent { get; set; }
|
RenderFragment DynamicComponent { get; set; }
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
((INotifyPropertyChanged)SiteState.Properties).PropertyChanged += PropertyChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnParametersSet()
|
||||||
{
|
{
|
||||||
string container = ModuleState.ContainerType;
|
string container = ModuleState.ContainerType;
|
||||||
if (PageState.ModuleId != -1 && ModuleState.UseAdminContainer)
|
if (PageState.ModuleId != -1 && ModuleState.UseAdminContainer)
|
||||||
@ -53,4 +64,21 @@
|
|||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.PropertyName == "ModuleVisibility")
|
||||||
|
{
|
||||||
|
if (SiteState.Properties.ModuleVisibility.PageModuleId == ModuleState.PageModuleId)
|
||||||
|
{
|
||||||
|
_visible = SiteState.Properties.ModuleVisibility.Visible;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
((INotifyPropertyChanged)SiteState.Properties).PropertyChanged -= PropertyChanged;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Oqtane.UI
|
namespace Oqtane.UI
|
||||||
{
|
{
|
||||||
@ -293,5 +296,91 @@ namespace Oqtane.UI
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ValueTask<int> GetCaretPosition(string id)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return _jsRuntime.InvokeAsync<int>(
|
||||||
|
"Oqtane.Interop.getCaretPosition",
|
||||||
|
id);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return new ValueTask<int>(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task SetIndexedDBItem(string key, object value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_jsRuntime.InvokeVoidAsync(
|
||||||
|
"Oqtane.Interop.manageIndexedDBItems",
|
||||||
|
"put", key, value);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<T> GetIndexedDBItem<T>(string key)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await _jsRuntime.InvokeAsync<T>(
|
||||||
|
"Oqtane.Interop.manageIndexedDBItems",
|
||||||
|
"get", key, null);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return default(T);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<string>> GetIndexedDBKeys()
|
||||||
|
{
|
||||||
|
return await GetIndexedDBKeys("");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<string>> GetIndexedDBKeys(string contains)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var items = await _jsRuntime.InvokeAsync<JsonDocument>(
|
||||||
|
"Oqtane.Interop.manageIndexedDBItems",
|
||||||
|
"getallkeys", null, null);
|
||||||
|
if (!string.IsNullOrEmpty(contains))
|
||||||
|
{
|
||||||
|
return items.Deserialize<List<string>>()
|
||||||
|
.Where(item => item.Contains(contains)).ToList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return items.Deserialize<List<string>>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return new List<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task RemoveIndexedDBItem(string key)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_jsRuntime.InvokeVoidAsync(
|
||||||
|
"Oqtane.Interop.manageIndexedDBItems",
|
||||||
|
"delete", key, null);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml.Linq;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
|
|
||||||
namespace Oqtane.UI
|
namespace Oqtane.UI
|
||||||
@ -8,10 +10,8 @@ namespace Oqtane.UI
|
|||||||
{
|
{
|
||||||
public Alias Alias { get; set; }
|
public Alias Alias { get; set; }
|
||||||
public Site Site { get; set; }
|
public Site Site { get; set; }
|
||||||
public List<Page> Pages { get; set; }
|
|
||||||
public Page Page { get; set; }
|
public Page Page { get; set; }
|
||||||
public User User { get; set; }
|
public User User { get; set; }
|
||||||
public List<Module> Modules { get; set; }
|
|
||||||
public Uri Uri { get; set; }
|
public Uri Uri { get; set; }
|
||||||
public Dictionary<string, string> QueryString { get; set; }
|
public Dictionary<string, string> QueryString { get; set; }
|
||||||
public string UrlParameters { get; set; }
|
public string UrlParameters { get; set; }
|
||||||
@ -19,8 +19,22 @@ namespace Oqtane.UI
|
|||||||
public string Action { get; set; }
|
public string Action { get; set; }
|
||||||
public bool EditMode { get; set; }
|
public bool EditMode { get; set; }
|
||||||
public DateTime LastSyncDate { get; set; }
|
public DateTime LastSyncDate { get; set; }
|
||||||
public Oqtane.Shared.Runtime Runtime { get; set; }
|
public Shared.Runtime Runtime { get; set; }
|
||||||
public int VisitorId { get; set; }
|
public int VisitorId { get; set; }
|
||||||
public string RemoteIPAddress { get; set; }
|
public string RemoteIPAddress { get; set; }
|
||||||
|
public string ReturnUrl { get; set; }
|
||||||
|
|
||||||
|
public List<Page> Pages
|
||||||
|
{
|
||||||
|
get { return Site.Pages.Where(item => !item.IsDeleted).ToList(); }
|
||||||
|
}
|
||||||
|
public List<Module> Modules
|
||||||
|
{
|
||||||
|
get { return Site.Modules.Where(item => !item.IsDeleted).ToList(); }
|
||||||
|
}
|
||||||
|
public List<Language> Languages
|
||||||
|
{
|
||||||
|
get { return Site.Languages; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,46 +17,57 @@ else
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private bool _useadminborder = false;
|
private bool _useadminborder = false;
|
||||||
private string _panetitle = "";
|
private string _panetitle = "";
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
protected PageState PageState { get; set; }
|
protected PageState PageState { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
RenderFragment DynamicComponent { get; set; }
|
RenderFragment DynamicComponent { get; set; }
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
protected override void OnParametersSet()
|
||||||
{
|
{
|
||||||
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions) && PageState.Action == Constants.DefaultAction)
|
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions) && PageState.Action == Constants.DefaultAction)
|
||||||
{
|
{
|
||||||
_useadminborder = true;
|
_useadminborder = true;
|
||||||
_panetitle = "<div class=\"app-pane-admin-title\">" + Name + " Pane</div>";
|
_panetitle = "<div class=\"app-pane-admin-title\">" + Name + " Pane</div>";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_useadminborder = false;
|
_useadminborder = false;
|
||||||
_panetitle = "";
|
_panetitle = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicComponent = builder =>
|
DynamicComponent = builder =>
|
||||||
{
|
{
|
||||||
if (PageState.ModuleId != -1 && PageState.Action != Constants.DefaultAction)
|
if (PageState.ModuleId != -1 && PageState.Action != Constants.DefaultAction)
|
||||||
{
|
{
|
||||||
if (Name.ToLower() == PaneNames.Admin.ToLower())
|
// action route needs to inject module control into specific pane
|
||||||
{
|
string pane = "";
|
||||||
Module module = PageState.Modules.FirstOrDefault(item => item.ModuleId == PageState.ModuleId);
|
if (PageState.Page.Panes.FindIndex(item => item.Equals(PaneNames.Default, StringComparison.OrdinalIgnoreCase)) != -1)
|
||||||
if (module != null)
|
{
|
||||||
{
|
pane = PaneNames.Default;
|
||||||
var moduleType = Type.GetType(module.ModuleType);
|
}
|
||||||
if (moduleType != null)
|
else
|
||||||
{
|
{
|
||||||
bool authorized = false;
|
pane = PaneNames.Admin;
|
||||||
if (Constants.DefaultModuleActions.Contains(PageState.Action))
|
|
||||||
{
|
}
|
||||||
authorized = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions);
|
if (Name.ToLower() == pane.ToLower())
|
||||||
|
{
|
||||||
|
Module module = PageState.Modules.FirstOrDefault(item => item.ModuleId == PageState.ModuleId);
|
||||||
|
if (module != null)
|
||||||
|
{
|
||||||
|
var moduleType = Type.GetType(module.ModuleType);
|
||||||
|
if (moduleType != null)
|
||||||
|
{
|
||||||
|
bool authorized = false;
|
||||||
|
if (Constants.DefaultModuleActions.Contains(PageState.Action))
|
||||||
|
{
|
||||||
|
authorized = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
namespace Oqtane.UI
|
|
||||||
{
|
|
||||||
public enum Refresh
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
Page,
|
|
||||||
Site,
|
|
||||||
Application
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,5 @@
|
|||||||
@using System.Diagnostics.CodeAnalysis
|
@using System.Diagnostics.CodeAnalysis
|
||||||
|
@using System.Net
|
||||||
@namespace Oqtane.UI
|
@namespace Oqtane.UI
|
||||||
@inject AuthenticationStateProvider AuthenticationStateProvider
|
@inject AuthenticationStateProvider AuthenticationStateProvider
|
||||||
@inject SiteState SiteState
|
@inject SiteState SiteState
|
||||||
@ -8,18 +9,23 @@
|
|||||||
@inject ISiteService SiteService
|
@inject ISiteService SiteService
|
||||||
@inject IPageService PageService
|
@inject IPageService PageService
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@inject IModuleService ModuleService
|
|
||||||
@inject IUrlMappingService UrlMappingService
|
@inject IUrlMappingService UrlMappingService
|
||||||
@inject ILogService LogService
|
@inject ILogService LogService
|
||||||
@inject IJSRuntime JSRuntime
|
@inject IJSRuntime JSRuntime
|
||||||
@implements IHandleAfterRender
|
@implements IHandleAfterRender
|
||||||
|
|
||||||
|
@if (!string.IsNullOrEmpty(_error))
|
||||||
|
{
|
||||||
|
<ModuleMessage Message="@_error" Type="@MessageType.Warning" />
|
||||||
|
}
|
||||||
|
|
||||||
@DynamicComponent
|
@DynamicComponent
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string _absoluteUri;
|
private string _absoluteUri;
|
||||||
private bool _navigationInterceptionEnabled;
|
private bool _navigationInterceptionEnabled;
|
||||||
private PageState _pagestate;
|
private PageState _pagestate;
|
||||||
|
private string _error = "";
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Runtime { get; set; }
|
public string Runtime { get; set; }
|
||||||
@ -70,19 +76,23 @@
|
|||||||
private async Task Refresh()
|
private async Task Refresh()
|
||||||
{
|
{
|
||||||
Site site;
|
Site site;
|
||||||
List<Page> pages;
|
|
||||||
Page page;
|
Page page;
|
||||||
User user = null;
|
User user = null;
|
||||||
List<Module> modules;
|
|
||||||
var editmode = false;
|
var editmode = false;
|
||||||
var refresh = UI.Refresh.None;
|
var refresh = false;
|
||||||
var lastsyncdate = DateTime.UtcNow.AddHours(-1);
|
var lastsyncdate = DateTime.UtcNow.AddHours(-1);
|
||||||
var runtime = (Shared.Runtime)Enum.Parse(typeof(Shared.Runtime), Runtime);
|
var runtime = (Shared.Runtime)Enum.Parse(typeof(Shared.Runtime), Runtime);
|
||||||
|
_error = "";
|
||||||
|
|
||||||
Route route = new Route(_absoluteUri, SiteState.Alias.Path);
|
Route route = new Route(_absoluteUri, SiteState.Alias.Path);
|
||||||
int moduleid = (int.TryParse(route.ModuleId, out moduleid)) ? moduleid : -1;
|
int moduleid = (int.TryParse(route.ModuleId, out moduleid)) ? moduleid : -1;
|
||||||
var action = (!string.IsNullOrEmpty(route.Action)) ? route.Action : Constants.DefaultAction;
|
var action = (!string.IsNullOrEmpty(route.Action)) ? route.Action : Constants.DefaultAction;
|
||||||
var querystring = ParseQueryString(route.Query);
|
var querystring = ParseQueryString(route.Query);
|
||||||
|
var returnurl = "";
|
||||||
|
if (querystring.ContainsKey("returnurl"))
|
||||||
|
{
|
||||||
|
returnurl = WebUtility.UrlDecode(querystring["returnurl"]);
|
||||||
|
}
|
||||||
|
|
||||||
// reload the client application from the server if there is a forced reload or the user navigated to a site with a different alias
|
// reload the client application from the server if there is a forced reload or the user navigated to a site with a different alias
|
||||||
if (querystring.ContainsKey("reload") || (!NavigationManager.ToBaseRelativePath(_absoluteUri).ToLower().StartsWith(SiteState.Alias.Path.ToLower()) && !string.IsNullOrEmpty(SiteState.Alias.Path)))
|
if (querystring.ContainsKey("reload") || (!NavigationManager.ToBaseRelativePath(_absoluteUri).ToLower().StartsWith(SiteState.Alias.Path.ToLower()) && !string.IsNullOrEmpty(SiteState.Alias.Path)))
|
||||||
@ -106,7 +116,7 @@
|
|||||||
// the refresh parameter is used to refresh the client-side PageState
|
// the refresh parameter is used to refresh the client-side PageState
|
||||||
if (querystring.ContainsKey("refresh"))
|
if (querystring.ContainsKey("refresh"))
|
||||||
{
|
{
|
||||||
refresh = UI.Refresh.Site;
|
refresh = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PageState != null)
|
if (PageState != null)
|
||||||
@ -115,27 +125,51 @@
|
|||||||
lastsyncdate = PageState.LastSyncDate;
|
lastsyncdate = PageState.LastSyncDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get user
|
||||||
|
if (PageState == null || refresh || PageState.Alias.SiteId != SiteState.Alias.SiteId)
|
||||||
|
{
|
||||||
|
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
||||||
|
if (authState.User.Identity.IsAuthenticated)
|
||||||
|
{
|
||||||
|
user = await UserService.GetUserAsync(authState.User.Identity.Name, SiteState.Alias.SiteId);
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
user.IsAuthenticated = authState.User.Identity.IsAuthenticated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
user = PageState.User;
|
||||||
|
}
|
||||||
|
|
||||||
// process any sync events
|
// process any sync events
|
||||||
var sync = await SyncService.GetSyncAsync(lastsyncdate);
|
var sync = await SyncService.GetSyncAsync(lastsyncdate);
|
||||||
lastsyncdate = sync.SyncDate;
|
lastsyncdate = sync.SyncDate;
|
||||||
if (sync.SyncEvents.Any())
|
if (sync.SyncEvents.Any())
|
||||||
{
|
{
|
||||||
// reload client application if server was restarted or site runtime/rendermode was modified
|
// reload client application if server was restarted or site runtime/rendermode was modified
|
||||||
if (PageState != null && sync.SyncEvents.Exists(item => (item.TenantId == -1 || item.EntityName == EntityNames.Site && item.EntityId == SiteState.Alias.SiteId) && item.Reload))
|
if (PageState != null && sync.SyncEvents.Exists(item => (item.Action == SyncEventActions.Reload)))
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(_absoluteUri, true);
|
NavigationManager.NavigateTo(_absoluteUri, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// when site information has changed the PageState needs to be refreshed
|
||||||
if (sync.SyncEvents.Exists(item => item.EntityName == EntityNames.Site && item.EntityId == SiteState.Alias.SiteId))
|
if (sync.SyncEvents.Exists(item => item.EntityName == EntityNames.Site && item.EntityId == SiteState.Alias.SiteId))
|
||||||
{
|
{
|
||||||
refresh = UI.Refresh.Site;
|
refresh = true;
|
||||||
|
}
|
||||||
|
// when user information has changed the PageState needs to be refreshed as the list of pages/modules may have changed
|
||||||
|
if (user != null && sync.SyncEvents.Exists(item => item.EntityName == EntityNames.User && item.EntityId == user.UserId))
|
||||||
|
{
|
||||||
|
refresh = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refresh == UI.Refresh.Site || PageState == null || PageState.Alias.SiteId != SiteState.Alias.SiteId)
|
if (PageState == null || refresh || PageState.Alias.SiteId != SiteState.Alias.SiteId)
|
||||||
{
|
{
|
||||||
site = await SiteService.GetSiteAsync(SiteState.Alias.SiteId);
|
site = await SiteService.GetSiteAsync(SiteState.Alias.SiteId);
|
||||||
refresh = UI.Refresh.Site;
|
refresh = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -144,96 +178,47 @@
|
|||||||
|
|
||||||
if (site != null)
|
if (site != null)
|
||||||
{
|
{
|
||||||
if (PageState == null || refresh == UI.Refresh.Site)
|
if (PageState == null || refresh || PageState.Page.Path != route.PagePath)
|
||||||
{
|
{
|
||||||
// get user
|
page = site.Pages.FirstOrDefault(item => item.Path.Equals(route.PagePath, StringComparison.OrdinalIgnoreCase));
|
||||||
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
editmode = false;
|
||||||
if (authState.User.Identity.IsAuthenticated)
|
|
||||||
{
|
|
||||||
user = await UserService.GetUserAsync(authState.User.Identity.Name, site.SiteId);
|
|
||||||
if (user != null)
|
|
||||||
{
|
|
||||||
user.IsAuthenticated = authState.User.Identity.IsAuthenticated;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
user = PageState.User;
|
|
||||||
}
|
|
||||||
|
|
||||||
// process any sync events for user
|
|
||||||
if (refresh != UI.Refresh.Site && user != null && sync.SyncEvents.Any())
|
|
||||||
{
|
|
||||||
if (sync.SyncEvents.Exists(item => item.EntityName == EntityNames.User && item.EntityId == user.UserId))
|
|
||||||
{
|
|
||||||
refresh = UI.Refresh.Site;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PageState == null || refresh == UI.Refresh.Site)
|
|
||||||
{
|
|
||||||
pages = await PageService.GetPagesAsync(site.SiteId);
|
|
||||||
pages = pages.Where(item => !item.IsDeleted).ToList();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pages = PageState.Pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PageState == null || refresh == UI.Refresh.Site)
|
|
||||||
{
|
|
||||||
page = pages.FirstOrDefault(item => item.Path.Equals(route.PagePath, StringComparison.OrdinalIgnoreCase));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
page = PageState.Page;
|
page = PageState.Page;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the page if the path has changed
|
if (page == null && route.PagePath == "") // naked path refers to site home page
|
||||||
if (page == null || page.Path != route.PagePath)
|
|
||||||
{
|
{
|
||||||
page = pages.FirstOrDefault(item => item.Path.Equals(route.PagePath, StringComparison.OrdinalIgnoreCase));
|
if (site.HomePageId != null)
|
||||||
// if the home page path does not exist then use the first page in the collection (a future enhancement would allow the admin to specify the home page)
|
|
||||||
if (page == null && route.PagePath == "")
|
|
||||||
{
|
{
|
||||||
page = pages.FirstOrDefault();
|
page = site.Pages.FirstOrDefault(item => item.PageId == site.HomePageId);
|
||||||
|
}
|
||||||
|
if (page == null)
|
||||||
|
{
|
||||||
|
// fallback to use the first page in the collection
|
||||||
|
page = site.Pages.FirstOrDefault();
|
||||||
}
|
}
|
||||||
editmode = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page != null)
|
if (page != null)
|
||||||
{
|
{
|
||||||
if (PageState == null)
|
|
||||||
{
|
|
||||||
editmode = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if user is authorized to view page
|
// check if user is authorized to view page
|
||||||
if (UserSecurity.IsAuthorized(user, PermissionNames.View, page.Permissions))
|
if (UserSecurity.IsAuthorized(user, PermissionNames.View, page.Permissions))
|
||||||
{
|
{
|
||||||
|
// load additional metadata for current page
|
||||||
page = await ProcessPage(page, site, user);
|
page = await ProcessPage(page, site, user);
|
||||||
|
|
||||||
if (PageState == null || refresh == UI.Refresh.Site)
|
// load additional metadata for modules
|
||||||
{
|
(page, site.Modules) = ProcessModules(page, site.Modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType);
|
||||||
modules = await ModuleService.GetModulesAsync(site.SiteId);
|
|
||||||
modules = modules.Where(item => !item.IsDeleted).ToList();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
modules = PageState.Modules;
|
|
||||||
}
|
|
||||||
|
|
||||||
(page, modules) = ProcessModules(page, modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType);
|
|
||||||
|
|
||||||
|
// populate page state (which acts as a client-side cache for subsequent requests)
|
||||||
_pagestate = new PageState
|
_pagestate = new PageState
|
||||||
{
|
{
|
||||||
Alias = SiteState.Alias,
|
Alias = SiteState.Alias,
|
||||||
Site = site,
|
Site = site,
|
||||||
Pages = pages,
|
|
||||||
Page = page,
|
Page = page,
|
||||||
User = user,
|
User = user,
|
||||||
Modules = modules,
|
|
||||||
Uri = new Uri(_absoluteUri, UriKind.Absolute),
|
Uri = new Uri(_absoluteUri, UriKind.Absolute),
|
||||||
QueryString = querystring,
|
QueryString = querystring,
|
||||||
UrlParameters = route.UrlParameters,
|
UrlParameters = route.UrlParameters,
|
||||||
@ -243,7 +228,8 @@
|
|||||||
LastSyncDate = lastsyncdate,
|
LastSyncDate = lastsyncdate,
|
||||||
Runtime = runtime,
|
Runtime = runtime,
|
||||||
VisitorId = VisitorId,
|
VisitorId = VisitorId,
|
||||||
RemoteIPAddress = SiteState.RemoteIPAddress
|
RemoteIPAddress = SiteState.RemoteIPAddress,
|
||||||
|
ReturnUrl = returnurl
|
||||||
};
|
};
|
||||||
|
|
||||||
OnStateChange?.Invoke(_pagestate);
|
OnStateChange?.Invoke(_pagestate);
|
||||||
@ -350,7 +336,7 @@
|
|||||||
page.Panes = new List<string>();
|
page.Panes = new List<string>();
|
||||||
page.Resources = new List<Resource>();
|
page.Resources = new List<Resource>();
|
||||||
|
|
||||||
string panes = PaneNames.Admin;
|
string panes = "";
|
||||||
Type themetype = Type.GetType(page.ThemeType);
|
Type themetype = Type.GetType(page.ThemeType);
|
||||||
if (themetype == null)
|
if (themetype == null)
|
||||||
{
|
{
|
||||||
@ -370,7 +356,19 @@
|
|||||||
page.Resources = ManagePageResources(page.Resources, themeobject.Resources, ResourceLevel.Page);
|
page.Resources = ManagePageResources(page.Resources, themeobject.Resources, ResourceLevel.Page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
page.Panes = panes.Replace(";", ",").Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
if (!string.IsNullOrEmpty(panes))
|
||||||
|
{
|
||||||
|
page.Panes = panes.Replace(";", ",").Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||||
|
if (!page.Panes.Contains(PaneNames.Default) && !page.Panes.Contains(PaneNames.Admin))
|
||||||
|
{
|
||||||
|
_error = "The Current Theme Does Not Contain A Default Or Admin Pane";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
page.Panes.Add(PaneNames.Admin);
|
||||||
|
_error = "The Current Theme Does Not Contain Any Panes";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@ -462,10 +460,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure module's pane exists in current page and if not, assign it to the Admin pane
|
// validate that module's pane exists in current page
|
||||||
if (page.Panes == null || page.Panes.FindIndex(item => item.Equals(module.Pane, StringComparison.OrdinalIgnoreCase)) == -1)
|
if (page.Panes.FindIndex(item => item.Equals(module.Pane, StringComparison.OrdinalIgnoreCase)) == -1)
|
||||||
{
|
{
|
||||||
module.Pane = PaneNames.Admin;
|
// fallback to default pane if it exists
|
||||||
|
if (page.Panes.FindIndex(item => item.Equals(PaneNames.Default, StringComparison.OrdinalIgnoreCase)) != -1)
|
||||||
|
{
|
||||||
|
module.Pane = PaneNames.Default;
|
||||||
|
}
|
||||||
|
else // otherwise admin pane (legacy)
|
||||||
|
{
|
||||||
|
module.Pane = PaneNames.Admin;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate module position within pane
|
// calculate module position within pane
|
||||||
|
@ -36,7 +36,8 @@
|
|||||||
foreach (Resource resource in PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Stylesheet))
|
foreach (Resource resource in PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Stylesheet))
|
||||||
{
|
{
|
||||||
var prefix = "app-stylesheet-" + resource.Level.ToString().ToLower();
|
var prefix = "app-stylesheet-" + resource.Level.ToString().ToLower();
|
||||||
links.Add(new { id = prefix + "-" + batch + "-" + (links.Count + 1).ToString("00"), rel = "stylesheet", href = resource.Url, type = "text/css", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "", insertbefore = prefix });
|
var url = (resource.Url.Contains("://")) ? resource.Url : PageState.Alias.BaseUrl + resource.Url;
|
||||||
|
links.Add(new { id = prefix + "-" + batch + "-" + (links.Count + 1).ToString("00"), rel = "stylesheet", href = url, type = "text/css", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "", insertbefore = prefix });
|
||||||
}
|
}
|
||||||
if (links.Any())
|
if (links.Any())
|
||||||
{
|
{
|
||||||
|
@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Version>3.1.3</Version>
|
<Version>3.2.1</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
<Description>Modular Application Framework for Blazor</Description>
|
<Description>Modular Application Framework for Blazor and MAUI</Description>
|
||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.1.3</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Database.MySQL</id>
|
<id>Oqtane.Database.MySQL</id>
|
||||||
<version>3.1.3</version>
|
<version>3.2.1</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane MySQL Provider</title>
|
<title>Oqtane MySQL Provider</title>
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.1.3</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Version>3.1.3</Version>
|
<Version>3.2.1</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
<Description>Modular Application Framework for Blazor</Description>
|
<Description>Modular Application Framework for Blazor and MAUI</Description>
|
||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.1.3</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Database.PostgreSQL</id>
|
<id>Oqtane.Database.PostgreSQL</id>
|
||||||
<version>3.1.3</version>
|
<version>3.2.1</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane PostgreSQL Provider</title>
|
<title>Oqtane PostgreSQL Provider</title>
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.1.3</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Version>3.1.3</Version>
|
<Version>3.2.1</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
<Description>Modular Application Framework for Blazor</Description>
|
<Description>Modular Application Framework for Blazor and MAUI</Description>
|
||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.1.3</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Database.SqlServer</id>
|
<id>Oqtane.Database.SqlServer</id>
|
||||||
<version>3.1.3</version>
|
<version>3.2.1</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane SQL Server Provider</title>
|
<title>Oqtane SQL Server Provider</title>
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.1.3</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<Version>3.1.3</Version>
|
<Version>3.2.1</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
<Description>Modular Application Framework for Blazor</Description>
|
<Description>Modular Application Framework for Blazor and MAUI</Description>
|
||||||
<Copyright>.NET Foundation</Copyright>
|
<Copyright>.NET Foundation</Copyright>
|
||||||
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
<PackageProjectUrl>https://www.oqtane.org</PackageProjectUrl>
|
||||||
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE</PackageLicenseUrl>
|
||||||
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.1.3</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</PackageReleaseNotes>
|
||||||
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
<RepositoryUrl>https://github.com/oqtane/oqtane.framework</RepositoryUrl>
|
||||||
<RepositoryType>Git</RepositoryType>
|
<RepositoryType>Git</RepositoryType>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Database.Sqlite</id>
|
<id>Oqtane.Database.Sqlite</id>
|
||||||
<version>3.1.3</version>
|
<version>3.2.1</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane SQLite Provider</title>
|
<title>Oqtane SQLite Provider</title>
|
||||||
@ -12,7 +12,7 @@
|
|||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.1.3</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.2.1</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
26
Oqtane.Maui.sln
Normal file
26
Oqtane.Maui.sln
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.0.31611.283
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Oqtane.Maui", "Oqtane.Maui\Oqtane.Maui.csproj", "{5EE64148-2152-4908-A3E7-658EB1D87754}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{5EE64148-2152-4908-A3E7-658EB1D87754}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{5EE64148-2152-4908-A3E7-658EB1D87754}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{5EE64148-2152-4908-A3E7-658EB1D87754}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||||
|
{5EE64148-2152-4908-A3E7-658EB1D87754}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{5EE64148-2152-4908-A3E7-658EB1D87754}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{5EE64148-2152-4908-A3E7-658EB1D87754}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {61F7FB11-1E47-470C-91E2-47F8143E1572}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
26
Oqtane.Maui/App.xaml
Normal file
26
Oqtane.Maui/App.xaml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
xmlns:local="clr-namespace:Oqtane.Maui"
|
||||||
|
x:Class="Oqtane.Maui.App">
|
||||||
|
<Application.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
|
||||||
|
<Color x:Key="PageBackgroundColor">#512bdf</Color>
|
||||||
|
<Color x:Key="PrimaryTextColor">White</Color>
|
||||||
|
|
||||||
|
<Style TargetType="Label">
|
||||||
|
<Setter Property="TextColor" Value="{DynamicResource PrimaryTextColor}" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style TargetType="Button">
|
||||||
|
<Setter Property="TextColor" Value="{DynamicResource PrimaryTextColor}" />
|
||||||
|
<Setter Property="FontFamily" Value="OpenSansRegular" />
|
||||||
|
<Setter Property="BackgroundColor" Value="#2b0b98" />
|
||||||
|
<Setter Property="Padding" Value="14,10" />
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
11
Oqtane.Maui/App.xaml.cs
Normal file
11
Oqtane.Maui/App.xaml.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
namespace Oqtane.Maui;
|
||||||
|
|
||||||
|
public partial class App : Application
|
||||||
|
{
|
||||||
|
public App()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
MainPage = new MainPage();
|
||||||
|
}
|
||||||
|
}
|
18
Oqtane.Maui/Main.razor
Normal file
18
Oqtane.Maui/Main.razor
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<DynamicComponent Type="@ComponentType" Parameters="@Parameters"></DynamicComponent>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
Type ComponentType = Type.GetType("Oqtane.App, Oqtane.Client");
|
||||||
|
private IDictionary<string, object> Parameters { get; set; }
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
Parameters = new Dictionary<string, object>();
|
||||||
|
Parameters.Add(new KeyValuePair<string, object>("AntiForgeryToken", ""));
|
||||||
|
Parameters.Add(new KeyValuePair<string, object>("Runtime", "Hybrid"));
|
||||||
|
Parameters.Add(new KeyValuePair<string, object>("RenderMode", "Hybrid"));
|
||||||
|
Parameters.Add(new KeyValuePair<string, object>("VisitorId", -1));
|
||||||
|
Parameters.Add(new KeyValuePair<string, object>("RemoteIPAddress", ""));
|
||||||
|
Parameters.Add(new KeyValuePair<string, object>("AuthorizationToken", ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user