Compare commits
308 Commits
Author | SHA1 | Date | |
---|---|---|---|
681321feeb | |||
a637b6d4d0 | |||
5161ade786 | |||
6dd62a164e | |||
3bece7599c | |||
b2f3a53980 | |||
cea31a8573 | |||
ce6647a84a | |||
d54ba9a5c6 | |||
1e18d913e0 | |||
0041c7d3b3 | |||
f6cca5cb35 | |||
fa5abbf96f | |||
2ff365765d | |||
ee31e4a411 | |||
ee4068d671 | |||
5e86c95db6 | |||
6126624631 | |||
a7c5841e76 | |||
0f242a94b4 | |||
8f8a0897e4 | |||
7c6b64123c | |||
55642093ed | |||
5660f40512 | |||
df7cd648ac | |||
2a5713ed67 | |||
de93281f3e | |||
86fbdced1b | |||
43bcfb9a4e | |||
0daf6af3b8 | |||
c3bccbade8 | |||
1e39f48235 | |||
05b5d9da9b | |||
db2aa920e2 | |||
8067b2e634 | |||
273c6d7dee | |||
d9f3db5bf3 | |||
c8a679ecce | |||
3abe47ae9e | |||
fcb05a7834 | |||
02e22df4d5 | |||
8bfca2f10a | |||
6bea9a087c | |||
3f4218f75f | |||
3849f59126 | |||
8ccee87378 | |||
9e518ffc4c | |||
e3233fd19f | |||
d3af9b0f14 | |||
08daca848b | |||
3b0ffde1fb | |||
6ca97e8d5d | |||
34a727b435 | |||
b1b9100600 | |||
bda0943d58 | |||
b21d202c7f | |||
3ea8ea1e3b | |||
ee897a9973 | |||
5f8cfb9977 | |||
d7928a70bf | |||
93568af5a9 | |||
9e86d97253 | |||
84bac0c462 | |||
3c18a258ff | |||
9759c68d58 | |||
f57a190405 | |||
d2eb203aa1 | |||
dd2c2dbe61 | |||
2529592b66 | |||
f248d2fe4e | |||
875bcd8ce2 | |||
726f9375e1 | |||
0c2e200245 | |||
a10db462eb | |||
6df28d8171 | |||
8367f15638 | |||
69456d3569 | |||
3b644338bc | |||
02e29aa22f | |||
88c489a585 | |||
706e73210d | |||
d52809c914 | |||
6058286577 | |||
a271f24157 | |||
2299375aaa | |||
c3290526a4 | |||
a9d871e9af | |||
5eb25796ca | |||
5d650bd276 | |||
b6be519537 | |||
160477d612 | |||
b2bc09be16 | |||
2f5d1cebb0 | |||
e4d144651e | |||
ce56dfc239 | |||
ad4f8fd7a0 | |||
c4070cb603 | |||
602fd7d658 | |||
818fd2fb43 | |||
e4912fcb09 | |||
3692ec49c1 | |||
9a1ea3f375 | |||
10a754642a | |||
bc9de5d094 | |||
9f93476167 | |||
f61492d353 | |||
50cf67546b | |||
41d83ec421 | |||
cc9377b37d | |||
7f986d5f60 | |||
d272bf8a29 | |||
ba5260f5b1 | |||
40c788fc33 | |||
8f147e7de2 | |||
85358c7dd4 | |||
87c7eafb87 | |||
613f4848da | |||
3cb06e4819 | |||
811701ef7f | |||
c14dc67d8a | |||
867767f009 | |||
640216d076 | |||
6b7c61f228 | |||
28ba2c00fc | |||
b56daae321 | |||
b57450398c | |||
c3d884e895 | |||
7a21f96552 | |||
4ccb4c636f | |||
0d5c3a3a0c | |||
b093cbff15 | |||
30cb8ec9c3 | |||
d5e51d6c38 | |||
6f0a6c7f69 | |||
549d71073e | |||
4ad5522f9e | |||
2145c1a48c | |||
0f093b1238 | |||
1aa3fd7056 | |||
cc4c47c3ee | |||
6e3f3fac9d | |||
261adefbc7 | |||
7eafcfd7ad | |||
6183d6a22e | |||
51d42692ba | |||
18a9c059f4 | |||
50a13ffd6d | |||
b360944742 | |||
59d1a47846 | |||
22969d8daa | |||
95ba87945b | |||
da11a86f99 | |||
98c2f012ee | |||
386c6144f8 | |||
666f9c2db9 | |||
f7c49588fb | |||
c0e6f06a5c | |||
31907f2d16 | |||
452d0af8c9 | |||
d13f26dc7e | |||
03374483e4 | |||
b1c0a865a0 | |||
7b0799a6f6 | |||
0de2976933 | |||
20c7bf3c48 | |||
55e090ba2a | |||
ded326c822 | |||
1ee9c2cf0e | |||
e41d9008b3 | |||
1ec24251a2 | |||
2be48c3847 | |||
2137b79f6d | |||
0b8086bd36 | |||
d16659890c | |||
076d150f72 | |||
62deffd017 | |||
f1ec70ff14 | |||
af27c763e0 | |||
7336417634 | |||
cde46c0889 | |||
5da4dadc31 | |||
e32ca089ec | |||
8d2f644177 | |||
a003010be5 | |||
89ada83012 | |||
65fbf6926c | |||
5e652364c9 | |||
8b7c3d6cfa | |||
3b214a0105 | |||
c0c4073bc4 | |||
dbe7324c7f | |||
9316255e87 | |||
7f7dff7019 | |||
961e004a49 | |||
02c1e4fb65 | |||
bcbc2a6e95 | |||
0c749a126c | |||
3698ebad7c | |||
f59a5c90a5 | |||
36e4a69891 | |||
19b560f7c1 | |||
0bec92e87e | |||
a0d02f16cd | |||
4a0f655e1c | |||
91bf65292d | |||
a69d52d688 | |||
79fe224cea | |||
757d8e59a2 | |||
53ec1416b4 | |||
d1b52534de | |||
35edc053b5 | |||
2aa8d3be0f | |||
ec0a5377b3 | |||
b876da069d | |||
f06063d7eb | |||
c6ba4f4bee | |||
89da4ab2a1 | |||
99ac0a3cab | |||
a964c30705 | |||
2334d0297d | |||
e444c6bcf0 | |||
601582fc98 | |||
e939dbe24e | |||
143ad85fd5 | |||
20377e9789 | |||
e4a24df7b4 | |||
e88ca00658 | |||
2312c612d7 | |||
3aee52482d | |||
32248e0be6 | |||
6c18c320bd | |||
e31f32e5aa | |||
a856390566 | |||
64b8291487 | |||
2ebd1310c9 | |||
09118fcb42 | |||
5d5167abbc | |||
bf43dea060 | |||
6ebab830c5 | |||
9a9a78e0bd | |||
418eff7d21 | |||
d39869ca8e | |||
7829168ea7 | |||
dd83e3ee67 | |||
c3ac0e365d | |||
2986625605 | |||
8beaeabf09 | |||
fa9b4b6112 | |||
d81fbe4585 | |||
536c044139 | |||
376531195e | |||
abf4ff71d7 | |||
d25debcea3 | |||
948c186cb5 | |||
ba27e70fe3 | |||
c93d2576af | |||
e0b0156640 | |||
a3ca6a3071 | |||
b20157450b | |||
7e4f0923d7 | |||
e0c2b2982f | |||
9a231c28af | |||
94a02b7bf9 | |||
22c8fb411a | |||
cf46210ff8 | |||
f32d988297 | |||
7fe4577158 | |||
8985dcb4c0 | |||
d346444c51 | |||
ef27a0d6b0 | |||
627158cb5d | |||
648edcabba | |||
0f34c6efc5 | |||
cc3cc55269 | |||
a503a9d5bc | |||
789baf99ff | |||
036279a54c | |||
481f18cf1c | |||
2f1e386554 | |||
1e0c7cf43d | |||
7978c89731 | |||
82221f54c5 | |||
2e23e6e4d5 | |||
3a79fa074a | |||
696c63c6d2 | |||
8f6dc52430 | |||
c8a9ad9807 | |||
a0933d07d8 | |||
6bf61e2008 | |||
36ecc55578 | |||
47065299ca | |||
0f707a7607 | |||
7590c5550f | |||
3d23a5c79a | |||
9aa0374dc2 | |||
058a191673 | |||
5fbb9160f1 | |||
2c3dad0592 | |||
00f039d31e | |||
497ef1750b | |||
7d4cd04ce9 | |||
04c0b9d37d | |||
b9c16c0727 | |||
0a30f2b7e8 | |||
dbb1d53202 | |||
2c88f36e3d | |||
d91dcad774 | |||
6eb4ea2a2d |
@ -1,6 +1,8 @@
|
|||||||
|
@using Microsoft.AspNetCore.Http
|
||||||
@inject IInstallationService InstallationService
|
@inject IInstallationService InstallationService
|
||||||
@inject IJSRuntime JSRuntime
|
@inject IJSRuntime JSRuntime
|
||||||
@inject SiteState SiteState
|
@inject SiteState SiteState
|
||||||
|
@inject IServiceProvider ServiceProvider
|
||||||
|
|
||||||
@if (_initialized)
|
@if (_initialized)
|
||||||
{
|
{
|
||||||
@ -30,35 +32,47 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string AntiForgeryToken { get; set; }
|
public string AntiForgeryToken { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Runtime { get; set; }
|
public string Runtime { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string RenderMode { get; set; }
|
public string RenderMode { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public int VisitorId { get; set; }
|
public int VisitorId { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string RemoteIPAddress { get; set; }
|
public string RemoteIPAddress { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string AuthorizationToken { get; set; }
|
public string AuthorizationToken { get; set; }
|
||||||
|
|
||||||
private bool _initialized = false;
|
private bool _initialized = false;
|
||||||
private string _display = "display: none;";
|
private string _display = "display: none;";
|
||||||
private Installation _installation = new Installation { Success = false, Message = "" };
|
private Installation _installation = new Installation { Success = false, Message = "" };
|
||||||
|
|
||||||
private PageState PageState { get; set; }
|
private PageState PageState { get; set; }
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
private IHttpContextAccessor accessor;
|
||||||
{
|
|
||||||
SiteState.RemoteIPAddress = RemoteIPAddress;
|
protected override async Task OnParametersSetAsync()
|
||||||
SiteState.AntiForgeryToken = AntiForgeryToken;
|
{
|
||||||
SiteState.AuthorizationToken = AuthorizationToken;
|
SiteState.RemoteIPAddress = RemoteIPAddress;
|
||||||
|
SiteState.AntiForgeryToken = AntiForgeryToken;
|
||||||
|
SiteState.AuthorizationToken = AuthorizationToken;
|
||||||
|
|
||||||
|
accessor = (IHttpContextAccessor)ServiceProvider.GetService(typeof(IHttpContextAccessor));
|
||||||
|
if (accessor != null)
|
||||||
|
{
|
||||||
|
SiteState.IsPrerendering = !accessor.HttpContext.Response.HasStarted;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SiteState.IsPrerendering = true;
|
||||||
|
}
|
||||||
|
|
||||||
_installation = await InstallationService.IsInstalled();
|
_installation = await InstallationService.IsInstalled();
|
||||||
if (_installation.Alias != null)
|
if (_installation.Alias != null)
|
||||||
@ -72,6 +86,7 @@
|
|||||||
{
|
{
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
{
|
{
|
||||||
|
// prevents flash on initial page load
|
||||||
_display = "";
|
_display = "";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
64
Oqtane.Client/Head.razor
Normal file
64
Oqtane.Client/Head.razor
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
@using System.ComponentModel
|
||||||
|
@using Oqtane.Shared
|
||||||
|
@inject SiteState SiteState
|
||||||
|
|
||||||
|
@if (!string.IsNullOrEmpty(_title))
|
||||||
|
{
|
||||||
|
@((MarkupString)_title)
|
||||||
|
}
|
||||||
|
@if (!string.IsNullOrEmpty(_content))
|
||||||
|
{
|
||||||
|
@((MarkupString)_content)
|
||||||
|
}
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private string _title = "";
|
||||||
|
private string _content = "";
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
((INotifyPropertyChanged)SiteState.Properties).PropertyChanged += PropertyChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
switch (e.PropertyName)
|
||||||
|
{
|
||||||
|
case "PageTitle":
|
||||||
|
var title = "\n<title>" + SiteState.Properties.PageTitle + "</title>";
|
||||||
|
if (title != _title)
|
||||||
|
{
|
||||||
|
_title = title;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "HeadContent":
|
||||||
|
var content = RemoveScripts(SiteState.Properties.HeadContent) + "\n";
|
||||||
|
if (content != _content)
|
||||||
|
{
|
||||||
|
_content = content;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string RemoveScripts(string headcontent)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(headcontent))
|
||||||
|
{
|
||||||
|
var index = headcontent.IndexOf("<script");
|
||||||
|
while (index >= 0)
|
||||||
|
{
|
||||||
|
headcontent = headcontent.Remove(index, headcontent.IndexOf("</script>") + 9 - index);
|
||||||
|
index = headcontent.IndexOf("<script");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return headcontent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
((INotifyPropertyChanged)SiteState.Properties).PropertyChanged -= PropertyChanged;
|
||||||
|
}
|
||||||
|
}
|
@ -5,15 +5,17 @@
|
|||||||
@inject ISiteService SiteService
|
@inject ISiteService SiteService
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@inject IDatabaseService DatabaseService
|
@inject IDatabaseService DatabaseService
|
||||||
|
@inject ISiteTemplateService SiteTemplateService
|
||||||
@inject IJSRuntime JSRuntime
|
@inject IJSRuntime JSRuntime
|
||||||
@inject IStringLocalizer<Installer> Localizer
|
@inject IStringLocalizer<Installer> Localizer
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
@inject SiteState SiteState
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="mx-auto text-center">
|
<div class="mx-auto text-center">
|
||||||
<img src="oqtane-black.png" />
|
<img src="oqtane-black.png" />
|
||||||
<div style="font-weight: bold">@SharedLocalizer["Version"] @Constants.Version</div>
|
<div style="font-weight: bold">@SharedLocalizer["Version"] @Constants.Version (.NET 7)</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr class="app-rule" />
|
<hr class="app-rule" />
|
||||||
@ -61,7 +63,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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 />
|
||||||
@ -77,7 +79,7 @@
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="password" type="@_passwordType" class="form-control" @bind="@_hostPassword" autocomplete="new-password" />
|
<input id="password" type="@_passwordType" class="form-control" @bind="@_hostPassword" autocomplete="new-password" />
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglePassword</button>
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglePassword</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -86,7 +88,7 @@
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="confirm" type="@_confirmPasswordType" class="form-control" @bind="@_confirmPassword" autocomplete="new-password" />
|
<input id="confirm" type="@_confirmPasswordType" class="form-control" @bind="@_confirmPassword" autocomplete="new-password" />
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@ToggleConfirmPassword">@_toggleConfirmPassword</button>
|
<button type="button" class="btn btn-secondary" @onclick="@ToggleConfirmPassword" tabindex="-1">@_toggleConfirmPassword</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -96,6 +98,20 @@
|
|||||||
<input type="text" class="form-control" @bind="@_hostEmail" />
|
<input type="text" class="form-control" @bind="@_hostEmail" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="template" HelpText="Select a site template" ResourceKey="Template">Template:</Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
@if (_templates != null)
|
||||||
|
{
|
||||||
|
<select id="template" class="form-select" @bind="@_template" required>
|
||||||
|
@foreach (var template in _templates)
|
||||||
|
{
|
||||||
|
<option value="@template.TypeName">@template.Name</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -103,7 +119,13 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="mx-auto text-center">
|
<div class="mx-auto text-center">
|
||||||
<button type="button" class="btn btn-success" @onclick="Install">@Localizer["InstallNow"]</button><br /><br />
|
<button type="button" class="btn btn-success" @onclick="Install">@Localizer["InstallNow"]</button><br /><br />
|
||||||
<ModuleMessage Message="@_message" Type="MessageType.Error"></ModuleMessage>
|
@if (!string.IsNullOrEmpty(_message))
|
||||||
|
{
|
||||||
|
<div class="alert alert-danger alert-dismissible fade show mb-3" role="alert">
|
||||||
|
@((MarkupString)_message)
|
||||||
|
<button type="button" class="btn-close" aria-label="Close" @onclick="DismissModal"></button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="app-progress-indicator" style="@_loadingDisplay"></div>
|
<div class="app-progress-indicator" style="@_loadingDisplay"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -115,29 +137,35 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<Database> _databases;
|
private List<Database> _databases;
|
||||||
private string _databaseName;
|
private string _databaseName;
|
||||||
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 bool _showConnectionString = false;
|
||||||
private string _connectionString = string.Empty;
|
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 List<SiteTemplate> _templates;
|
||||||
|
private string _template = Constants.DefaultSiteTemplate;
|
||||||
|
private bool _register = true;
|
||||||
private string _message = string.Empty;
|
private string _message = string.Empty;
|
||||||
private string _loadingDisplay = "display: none;";
|
private string _loadingDisplay = "display: none;";
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
_togglePassword = SharedLocalizer["ShowPassword"];
|
// include CSS
|
||||||
|
var content = "<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css\" integrity=\"sha512-t4GWSVZO1eC8BM339Xd7Uphw5s17a86tIZIj8qRxhnKub6WoyhnrxeCIMeAqBPgdZGlCcG2PrZjMc+Wr78+5Xg==\" crossorigin=\"anonymous\" type=\"text/css\"/>";
|
||||||
|
SiteState.AppendHeadContent(content);
|
||||||
|
|
||||||
|
_togglePassword = SharedLocalizer["ShowPassword"];
|
||||||
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
|
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
|
||||||
|
|
||||||
_databases = await DatabaseService.GetDatabasesAsync();
|
_databases = await DatabaseService.GetDatabasesAsync();
|
||||||
@ -150,7 +178,9 @@
|
|||||||
_databaseName = "LocalDB";
|
_databaseName = "LocalDB";
|
||||||
}
|
}
|
||||||
LoadDatabaseConfigComponent();
|
LoadDatabaseConfigComponent();
|
||||||
}
|
|
||||||
|
_templates = await SiteTemplateService.GetSiteTemplatesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
private void DatabaseChanged(ChangeEventArgs eventArgs)
|
private void DatabaseChanged(ChangeEventArgs eventArgs)
|
||||||
{
|
{
|
||||||
@ -185,9 +215,9 @@
|
|||||||
{
|
{
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
{
|
{
|
||||||
|
// include JavaScript
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
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.3.0/js/bootstrap.bundle.min.js", "sha512-VK2zcvntEufaimc+efOYi622VN5ZacdnufnmX7zIhCPmjhKnOi9ZDMtg1/ug5l183f19gG1/cBstPO4D8N/Img==", "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");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +259,8 @@
|
|||||||
TenantName = TenantNames.Master,
|
TenantName = TenantNames.Master,
|
||||||
IsNewTenant = true,
|
IsNewTenant = true,
|
||||||
SiteName = Constants.DefaultSite,
|
SiteName = Constants.DefaultSite,
|
||||||
Register = _register
|
Register = _register,
|
||||||
|
SiteTemplate = _template
|
||||||
};
|
};
|
||||||
|
|
||||||
var installation = await InstallationService.Install(config);
|
var installation = await InstallationService.Install(config);
|
||||||
@ -291,4 +322,9 @@
|
|||||||
_showConnectionString = !_showConnectionString;
|
_showConnectionString = !_showConnectionString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DismissModal()
|
||||||
|
{
|
||||||
|
_message = "";
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,32 +4,35 @@
|
|||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
|
||||||
<div class="row">
|
@if (_pages != null)
|
||||||
@foreach (var p in _pages)
|
{
|
||||||
{
|
<div class="row">
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.PermissionList))
|
@foreach (var p in _pages)
|
||||||
{
|
{
|
||||||
string url = NavigateUrl(p.Path);
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.PermissionList))
|
||||||
<div class="col-md-2 mx-auto text-center mb-3">
|
{
|
||||||
<NavLink class="nav-link text-primary" href="@url" Match="NavLinkMatch.All">
|
string url = NavigateUrl(p.Path);
|
||||||
<h2><span class="@p.Icon" aria-hidden="true"></span></h2>@SharedLocalizer[p.Name]
|
<div class="col-md-2 mx-auto text-center mb-3">
|
||||||
</NavLink>
|
<NavLink class="nav-link text-primary" href="@url" Match="NavLinkMatch.All">
|
||||||
</div>
|
<h2><span class="@p.Icon" aria-hidden="true"></span></h2>@SharedLocalizer[p.Name]
|
||||||
|
</NavLink>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
</div>
|
||||||
</div>
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<Page> _pages;
|
private List<Page> _pages;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
var admin = PageState.Pages.FirstOrDefault(item => item.Path == "admin");
|
var admin = PageState.Pages.FirstOrDefault(item => item.Path == "admin");
|
||||||
if (admin != null)
|
if (admin != null)
|
||||||
{
|
{
|
||||||
_pages = PageState.Pages.Where(item => item.ParentId == admin?.PageId).ToList();
|
_pages = PageState.Pages.Where(item => item.ParentId == admin.PageId).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,15 +20,6 @@ else
|
|||||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||||
<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" For="translated" HelpText="Specify If You Wish To Select Languages That Have Translations Installed" ResourceKey="Translated">Translated?</Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="translated" class="form-select" value="@_translated" @onchange="(e => TranslatedChanged(e))" required>
|
|
||||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
|
||||||
<option value="False">@SharedLocalizer["No"]</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="name" HelpText="Name Of The Language" ResourceKey="Name">Name:</Label>
|
<Label Class="col-sm-3" For="name" HelpText="Name Of The Language" ResourceKey="Name">Name:</Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="_code" class="form-select" @bind="@_code" required>
|
<select id="_code" class="form-select" @bind="@_code" required>
|
||||||
@ -57,13 +48,12 @@ else
|
|||||||
<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">Translation: </Label>
|
<Label Class="col-sm-3" HelpText="Upload one or more translations. Once they are uploaded click Install." 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" OnUpload="OnUpload" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn btn-success" @onclick="InstallTranslations">@SharedLocalizer["Install"]</button>
|
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</TabStrip>
|
</TabStrip>
|
||||||
@ -73,7 +63,6 @@ else
|
|||||||
private ElementReference form;
|
private ElementReference form;
|
||||||
private bool validated = false;
|
private bool validated = false;
|
||||||
|
|
||||||
private string _translated = "True";
|
|
||||||
private string _code = "-";
|
private string _code = "-";
|
||||||
private string _default = "False";
|
private string _default = "False";
|
||||||
private List<string> _languages;
|
private List<string> _languages;
|
||||||
@ -91,18 +80,11 @@ else
|
|||||||
|
|
||||||
private async Task LoadCultures()
|
private async Task LoadCultures()
|
||||||
{
|
{
|
||||||
_cultures = await LocalizationService.GetCulturesAsync(bool.Parse(_translated));
|
_cultures = await LocalizationService.GetCulturesAsync(false);
|
||||||
_cultures = _cultures.Where(c => !c.Name.Equals(Constants.DefaultCulture) && !_languages.Contains(c.Name));
|
_cultures = _cultures.Where(c => !c.Name.Equals(Constants.DefaultCulture) && !_languages.Contains(c.Name));
|
||||||
_code = "-";
|
_code = "-";
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void TranslatedChanged(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
_translated = (string)e.Value;
|
|
||||||
await LoadCultures();
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SaveLanguage()
|
private async Task SaveLanguage()
|
||||||
{
|
{
|
||||||
validated = true;
|
validated = true;
|
||||||
@ -136,24 +118,11 @@ else
|
|||||||
AddModuleMessage(Localizer["Error.Language.Add"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.Language.Add"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task InstallTranslations()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await PackageService.InstallPackagesAsync();
|
|
||||||
AddModuleMessage(string.Format(Localizer["Success.Language.Install"], NavigateUrl("admin/system")), MessageType.Success);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Installing Translations");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SetCultureAsync(string culture)
|
private async Task SetCultureAsync(string culture)
|
||||||
{
|
{
|
||||||
@ -166,4 +135,9 @@ else
|
|||||||
NavigationManager.NavigateTo(NavigationManager.Uri, true);
|
NavigationManager.NavigateTo(NavigationManager.Uri, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnUpload()
|
||||||
|
{
|
||||||
|
AddModuleMessage(string.Format(Localizer["Success.Language.Download"], NavigateUrl("admin/system")), MessageType.Success);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,23 +35,27 @@ else
|
|||||||
{
|
{
|
||||||
<td>@((string.IsNullOrEmpty(context.Version)) ? "---" : context.Version)</td>
|
<td>@((string.IsNullOrEmpty(context.Version)) ? "---" : context.Version)</td>
|
||||||
<td>
|
<td>
|
||||||
@switch (TranslationAvailable(context.Code, context.Version))
|
@{
|
||||||
|
var translation = TranslationAvailable(context.Code, context.Version);
|
||||||
|
}
|
||||||
|
@if (translation != null)
|
||||||
{
|
{
|
||||||
case "install":
|
if (string.IsNullOrEmpty(context.Version))
|
||||||
<button type="button" class="btn btn-success" @onclick=@(async () => await GetPackage(context.Code))>@SharedLocalizer["Download"]</button>
|
{
|
||||||
break;
|
<button type="button" class="btn btn-success" @onclick=@(async () => await GetPackage(context.Code, translation.Version))>@SharedLocalizer["Download"]</button>
|
||||||
case "upgrade":
|
}
|
||||||
<button type="button" class="btn btn-success" @onclick=@(async () => await GetPackage(context.Code))>@SharedLocalizer["Upgrade"]</button>
|
else
|
||||||
break;
|
{
|
||||||
|
if (Version.Parse(translation.Version).CompareTo(Version.Parse(context.Version)) > 0)
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-success" @onclick=@(async () => await GetPackage(context.Code, translation.Version))>@SharedLocalizer["Upgrade"]</button>
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</td>
|
</td>
|
||||||
}
|
}
|
||||||
</Row>
|
</Row>
|
||||||
</Pager>
|
</Pager>
|
||||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host) && _install)
|
|
||||||
{
|
|
||||||
<button type="button" class="btn btn-success" @onclick="InstallTranslations">@SharedLocalizer["Install"]</button>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (_package != null)
|
@if (_package != null)
|
||||||
@ -98,7 +102,6 @@ else
|
|||||||
private List<Language> _languages;
|
private List<Language> _languages;
|
||||||
private List<Package> _packages;
|
private List<Package> _packages;
|
||||||
private Package _package;
|
private Package _package;
|
||||||
private bool _install = false;
|
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
|
|
||||||
@ -134,38 +137,16 @@ else
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string TranslationAvailable(string code, string version)
|
private Package TranslationAvailable(string code, string version)
|
||||||
{
|
{
|
||||||
if (_packages != null)
|
return _packages?.FirstOrDefault(item => item.PackageId == (Constants.PackageId + "." + code));
|
||||||
{
|
|
||||||
var package = _packages.Where(item => item.PackageId == (Constants.PackageId + "." + code)).FirstOrDefault();
|
|
||||||
if (package != null)
|
|
||||||
{
|
|
||||||
// package version needs to match current framework version
|
|
||||||
if (Version.Parse(package.Version).CompareTo(Version.Parse(Constants.Version)) == 0)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(version))
|
|
||||||
{
|
|
||||||
return "install";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Version.Parse(package.Version).CompareTo(Version.Parse(version)) > 0)
|
|
||||||
{
|
|
||||||
return "upgrade";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task GetPackage(string code)
|
private async Task GetPackage(string code, string version)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_package = await PackageService.GetPackageAsync(Constants.PackageId + "." + code, Constants.Version);
|
_package = await PackageService.GetPackageAsync(Constants.PackageId + "." + code, version);
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -181,9 +162,8 @@ else
|
|||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(_package.PackageId, _package.Version, Constants.PackagesFolder);
|
await PackageService.DownloadPackageAsync(_package.PackageId, _package.Version, Constants.PackagesFolder);
|
||||||
await logger.LogInformation("Language Package {Name} {Version} Downloaded Successfully", _package.PackageId, _package.Version);
|
await logger.LogInformation("Language Package {Name} {Version} Downloaded Successfully", _package.PackageId, _package.Version);
|
||||||
AddModuleMessage(Localizer["Success.Language.Download"], MessageType.Success);
|
AddModuleMessage(string.Format(Localizer["Success.Language.Download"], NavigateUrl("admin/system")), MessageType.Success);
|
||||||
_package = null;
|
_package = null;
|
||||||
_install = true;
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -198,19 +178,4 @@ else
|
|||||||
_package = null;
|
_package = null;
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task InstallTranslations()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await PackageService.InstallPackagesAsync();
|
|
||||||
AddModuleMessage(string.Format(Localizer["Success.Translation.Install"], NavigateUrl("admin/system")), MessageType.Success);
|
|
||||||
_install = false;
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Installing Translations");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
<Label Class="control-label" For="password" HelpText="Please enter your Password" ResourceKey="Password">Password:</Label>
|
<Label Class="control-label" For="password" HelpText="Please enter your Password" ResourceKey="Password">Password:</Label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="password" type="@_passwordtype" name="Password" class="form-control" placeholder="@Localizer["Password.Placeholder"]" @bind="@_password" required />
|
<input id="password" type="@_passwordtype" name="Password" class="form-control" placeholder="@Localizer["Password.Placeholder"]" @bind="@_password" required />
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group mt-2">
|
<div class="form-group mt-2">
|
||||||
|
@ -195,7 +195,7 @@ else
|
|||||||
if (_owner != "" && _module != "" && _template != "-")
|
if (_owner != "" && _module != "" && _template != "-")
|
||||||
{
|
{
|
||||||
var template = _templates.FirstOrDefault(item => item.Name == _template);
|
var template = _templates.FirstOrDefault(item => item.Name == _template);
|
||||||
_location = template.Location + _owner + "." + _module;
|
_location = template.Location + _owner + ".Module." + _module;
|
||||||
|
|
||||||
}
|
}
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
|
@ -65,13 +65,15 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
<br />
|
||||||
|
<ModuleMessage Type="MessageType.Info" Message="@SharedLocalizer["Oqtane.Marketplace"]" />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel Name="Upload" ResourceKey="Upload">
|
<TabPanel Name="Upload" ResourceKey="Upload">
|
||||||
<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 module packages. Once they are uploaded click Install to complete the installation." ResourceKey="Module">Module: </Label>
|
<Label Class="col-sm-3" HelpText="Upload one or more module packages. Once they are uploaded click Install to complete the installation." ResourceKey="Module">Module: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" />
|
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" OnUpload="OnUpload" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -111,153 +113,140 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<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 _packageid = "";
|
private string _packageid = "";
|
||||||
private string _packagelicense = "";
|
private string _packagelicense = "";
|
||||||
private string _packageversion = "";
|
private string _packageversion = "";
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await LoadModuleDefinitions();
|
await LoadModuleDefinitions();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Loading Packages {Error}", ex.Message);
|
await logger.LogError(ex, "Error Loading Packages {Error}", ex.Message);
|
||||||
AddModuleMessage(Localizer["Error.Package.Load"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.Package.Load"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task LoadModuleDefinitions()
|
private async Task LoadModuleDefinitions()
|
||||||
{
|
{
|
||||||
var moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
|
var moduledefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
|
||||||
_packages = await PackageService.GetPackagesAsync("module", _search, _price, "");
|
_packages = await PackageService.GetPackagesAsync("module", _search, _price, "");
|
||||||
|
|
||||||
if (_packages != null)
|
if (_packages != null)
|
||||||
{
|
{
|
||||||
foreach (Package package in _packages.ToArray())
|
foreach (Package package in _packages.ToArray())
|
||||||
{
|
{
|
||||||
if (moduledefinitions.Exists(item => item.PackageName == package.PackageId))
|
if (moduledefinitions.Exists(item => item.PackageName == package.PackageId))
|
||||||
{
|
{
|
||||||
_packages.Remove(package);
|
_packages.Remove(package);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void PriceChanged(ChangeEventArgs e)
|
private async void PriceChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_price = (string)e.Value;
|
_price = (string)e.Value;
|
||||||
_search = "";
|
_search = "";
|
||||||
await LoadModuleDefinitions();
|
await LoadModuleDefinitions();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error On PriceChanged");
|
await logger.LogError(ex, "Error On PriceChanged");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Search()
|
private async Task Search()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await LoadModuleDefinitions();
|
await LoadModuleDefinitions();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error On Search");
|
await logger.LogError(ex, "Error On Search");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Reset()
|
private async Task Reset()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_search = "";
|
_search = "";
|
||||||
await LoadModuleDefinitions();
|
await LoadModuleDefinitions();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error On Reset");
|
await logger.LogError(ex, "Error On Reset");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HideModal()
|
private void HideModal()
|
||||||
{
|
{
|
||||||
_productname = "";
|
_productname = "";
|
||||||
_packagelicense = "";
|
_packagelicense = "";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task GetPackage(string packageid, string version)
|
private async Task GetPackage(string packageid, string version)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var package = await PackageService.GetPackageAsync(packageid, version);
|
var package = await PackageService.GetPackageAsync(packageid, version);
|
||||||
if (package != null)
|
if (package != null)
|
||||||
{
|
{
|
||||||
_productname = package.Name;
|
_productname = package.Name;
|
||||||
_packageid = package.PackageId;
|
_packageid = package.PackageId;
|
||||||
if (!string.IsNullOrEmpty(package.License))
|
if (!string.IsNullOrEmpty(package.License))
|
||||||
{
|
{
|
||||||
_packagelicense = package.License.Replace("\n", "<br />");
|
_packagelicense = package.License.Replace("\n", "<br />");
|
||||||
}
|
}
|
||||||
_packageversion = package.Version;
|
_packageversion = package.Version;
|
||||||
}
|
}
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Getting Package {PackageId} {Version}", packageid, version);
|
await logger.LogError(ex, "Error Getting Package {PackageId} {Version}", packageid, version);
|
||||||
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.Module.Download"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DownloadPackage()
|
private async Task DownloadPackage()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(_packageid, _packageversion, Constants.PackagesFolder);
|
await PackageService.DownloadPackageAsync(_packageid, _packageversion, Constants.PackagesFolder);
|
||||||
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _packageid, _packageversion);
|
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _packageid, _packageversion);
|
||||||
AddModuleMessage(Localizer["Success.Module.Download"], MessageType.Success);
|
AddModuleMessage(string.Format(Localizer["Success.Module.Download"], NavigateUrl("admin/system")), MessageType.Success);
|
||||||
_productname = "";
|
_productname = "";
|
||||||
_packagelicense = "";
|
_packagelicense = "";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Downloading Package {PackageId} {Version}", _packageid, _packageversion);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task InstallModules()
|
private void OnUpload()
|
||||||
{
|
{
|
||||||
try
|
AddModuleMessage(string.Format(Localizer["Success.Module.Download"], NavigateUrl("admin/system")), MessageType.Success);
|
||||||
{
|
}
|
||||||
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
|
|
||||||
AddModuleMessage(string.Format(Localizer["Success.Module.Install"], NavigateUrl("admin/system")), MessageType.Success);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Installing Modules");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,16 @@
|
|||||||
<input id="categories" class="form-control" @bind="@_categories" maxlength="200" required />
|
<input id="categories" class="form-control" @bind="@_categories" maxlength="200" required />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="isenabled" HelpText="Is module enabled for this site?" ResourceKey="IsEnabled">Enabled? </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="isenabled" class="form-select" @bind="@_isenabled" required>
|
||||||
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<Section Name="Information" ResourceKey="Information">
|
<Section Name="Information" ResourceKey="Information">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@ -131,10 +140,6 @@
|
|||||||
</td>
|
</td>
|
||||||
</Row>
|
</Row>
|
||||||
</Pager>
|
</Pager>
|
||||||
@if (_install)
|
|
||||||
{
|
|
||||||
<button type="button" class="btn btn-success" @onclick="InstallTranslations">@SharedLocalizer["Install"]</button>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -196,114 +201,124 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private bool _initialized = false;
|
private bool _initialized = false;
|
||||||
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 _description = "";
|
private string _description = "";
|
||||||
private string _categories;
|
private string _categories;
|
||||||
private string _moduledefinitionname = "";
|
private string _isenabled;
|
||||||
private string _version;
|
private string _moduledefinitionname = "";
|
||||||
private string _packagename = "";
|
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 List<Permission> _permissions = null;
|
private string _runtimes = "";
|
||||||
private string _createdby;
|
private List<Permission> _permissions = null;
|
||||||
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
|
||||||
|
|
||||||
private List<Package> _packages;
|
private List<Package> _packages;
|
||||||
private List<Language> _languages;
|
private List<Language> _languages;
|
||||||
private Package _package;
|
private Package _package;
|
||||||
private bool _install = false;
|
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_moduleDefinitionId = Int32.Parse(PageState.QueryString["id"]);
|
_moduleDefinitionId = Int32.Parse(PageState.QueryString["id"]);
|
||||||
var moduleDefinition = await ModuleDefinitionService.GetModuleDefinitionAsync(_moduleDefinitionId, ModuleState.SiteId);
|
var moduleDefinition = await ModuleDefinitionService.GetModuleDefinitionAsync(_moduleDefinitionId, ModuleState.SiteId);
|
||||||
if (moduleDefinition != null)
|
if (moduleDefinition != null)
|
||||||
{
|
{
|
||||||
_name = moduleDefinition.Name;
|
_name = moduleDefinition.Name;
|
||||||
_description = moduleDefinition.Description;
|
_description = moduleDefinition.Description;
|
||||||
_categories = moduleDefinition.Categories;
|
_categories = moduleDefinition.Categories;
|
||||||
_moduledefinitionname = moduleDefinition.ModuleDefinitionName;
|
_isenabled = moduleDefinition.IsEnabled.ToString();
|
||||||
_version = moduleDefinition.Version;
|
_moduledefinitionname = moduleDefinition.ModuleDefinitionName;
|
||||||
_packagename = moduleDefinition.PackageName;
|
_version = moduleDefinition.Version;
|
||||||
_owner = moduleDefinition.Owner;
|
_packagename = moduleDefinition.PackageName;
|
||||||
_url = moduleDefinition.Url;
|
_owner = moduleDefinition.Owner;
|
||||||
_contact = moduleDefinition.Contact;
|
_url = moduleDefinition.Url;
|
||||||
_license = moduleDefinition.License;
|
_contact = moduleDefinition.Contact;
|
||||||
_runtimes = moduleDefinition.Runtimes;
|
_license = moduleDefinition.License;
|
||||||
_permissions = moduleDefinition.PermissionList;
|
_runtimes = moduleDefinition.Runtimes;
|
||||||
_createdby = moduleDefinition.CreatedBy;
|
_permissions = moduleDefinition.PermissionList;
|
||||||
_createdon = moduleDefinition.CreatedOn;
|
_createdby = moduleDefinition.CreatedBy;
|
||||||
_modifiedby = moduleDefinition.ModifiedBy;
|
_createdon = moduleDefinition.CreatedOn;
|
||||||
_modifiedon = moduleDefinition.ModifiedOn;
|
_modifiedby = moduleDefinition.ModifiedBy;
|
||||||
|
_modifiedon = moduleDefinition.ModifiedOn;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(_packagename))
|
if (!string.IsNullOrEmpty(_packagename))
|
||||||
{
|
{
|
||||||
_packages = await PackageService.GetPackagesAsync("translation", "", "", _packagename);
|
_packages = await PackageService.GetPackagesAsync("translation", "", "", _packagename);
|
||||||
_languages = await LanguageService.GetLanguagesAsync(-1, _packagename);
|
_languages = await LanguageService.GetLanguagesAsync(-1, _packagename);
|
||||||
foreach (var package in _packages)
|
foreach (var package in _packages)
|
||||||
{
|
{
|
||||||
var code = package.PackageId.Split('.').Last();
|
var code = package.PackageId.Split('.').Last();
|
||||||
if (!_languages.Any(item => item.Code == code))
|
if (!_languages.Any(item => item.Code == code))
|
||||||
{
|
{
|
||||||
_languages.Add(new Language { Code = code, Name = CultureInfo.GetCultureInfo(code).DisplayName, Version = package.Version, IsDefault = true });
|
_languages.Add(new Language { Code = code, Name = CultureInfo.GetCultureInfo(code).DisplayName, Version = package.Version, IsDefault = true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_languages = _languages.OrderBy(item => item.Name).ToList();
|
_languages = _languages.OrderBy(item => item.Name).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Loading ModuleDefinition {ModuleDefinitionId} {Error}", _moduleDefinitionId, ex.Message);
|
await logger.LogError(ex, "Error Loading ModuleDefinition {ModuleDefinitionId} {Error}", _moduleDefinitionId, ex.Message);
|
||||||
AddModuleMessage(Localizer["Error.Module.Load"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.Module.Load"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SaveModuleDefinition()
|
private async Task SaveModuleDefinition()
|
||||||
{
|
{
|
||||||
validated = true;
|
validated = true;
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
if (await interop.FormValid(form))
|
if (await interop.FormValid(form))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var moduledefinition = await ModuleDefinitionService.GetModuleDefinitionAsync(_moduleDefinitionId, ModuleState.SiteId);
|
var moduleDefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
|
||||||
if (moduledefinition.Name != _name)
|
if (!moduleDefinitions.Any(item => item.Name.ToLower() == _name.ToLower() && item.ModuleDefinitionId != _moduleDefinitionId))
|
||||||
{
|
{
|
||||||
moduledefinition.Name = _name;
|
var moduledefinition = await ModuleDefinitionService.GetModuleDefinitionAsync(_moduleDefinitionId, ModuleState.SiteId);
|
||||||
}
|
if (moduledefinition.Name != _name)
|
||||||
if (moduledefinition.Description != _description)
|
{
|
||||||
{
|
moduledefinition.Name = _name;
|
||||||
moduledefinition.Description = _description;
|
}
|
||||||
}
|
if (moduledefinition.Description != _description)
|
||||||
if (moduledefinition.Categories != _categories)
|
{
|
||||||
{
|
moduledefinition.Description = _description;
|
||||||
moduledefinition.Categories = _categories;
|
}
|
||||||
}
|
if (moduledefinition.Categories != _categories)
|
||||||
moduledefinition.PermissionList = _permissionGrid.GetPermissionList();
|
{
|
||||||
await ModuleDefinitionService.UpdateModuleDefinitionAsync(moduledefinition);
|
moduledefinition.Categories = _categories;
|
||||||
await logger.LogInformation("ModuleDefinition Saved {ModuleDefinition}", moduledefinition);
|
}
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
moduledefinition.IsEnabled = (_isenabled == null ? true : bool.Parse(_isenabled));
|
||||||
}
|
moduledefinition.PermissionList = _permissionGrid.GetPermissionList();
|
||||||
|
await ModuleDefinitionService.UpdateModuleDefinitionAsync(moduledefinition);
|
||||||
|
await logger.LogInformation("ModuleDefinition Saved {ModuleDefinition}", moduledefinition);
|
||||||
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddModuleMessage(Localizer["Message.DuplicateName"], MessageType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Saving ModuleDefinition {ModuleDefinitionId} {Error}", _moduleDefinitionId, ex.Message);
|
await logger.LogError(ex, "Error Saving ModuleDefinition {ModuleDefinitionId} {Error}", _moduleDefinitionId, ex.Message);
|
||||||
@ -366,9 +381,8 @@
|
|||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(_package.PackageId, _package.Version, Constants.PackagesFolder);
|
await PackageService.DownloadPackageAsync(_package.PackageId, _package.Version, Constants.PackagesFolder);
|
||||||
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _package.PackageId, _package.Version);
|
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _package.PackageId, _package.Version);
|
||||||
AddModuleMessage(Localizer["Success.Translation.Download"], MessageType.Success);
|
AddModuleMessage(string.Format(Localizer["Success.Translation.Download"], NavigateUrl("admin/system")), MessageType.Success);
|
||||||
_package = null;
|
_package = null;
|
||||||
_install = true;
|
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -377,19 +391,4 @@
|
|||||||
AddModuleMessage(Localizer["Error.Translation.Download"], MessageType.Error);
|
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);
|
|
||||||
_install = false;
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Installing Translations");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ else
|
|||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>@SharedLocalizer["Name"]</th>
|
<th>@SharedLocalizer["Name"]</th>
|
||||||
<th>@SharedLocalizer["Version"]</th>
|
<th>@SharedLocalizer["Version"]</th>
|
||||||
|
<th>@Localizer["Enabled"]</th>
|
||||||
<th>@Localizer["InUse"]</th>
|
<th>@Localizer["InUse"]</th>
|
||||||
<th>@SharedLocalizer["Expires"]</th>
|
<th>@SharedLocalizer["Expires"]</th>
|
||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
@ -57,6 +58,16 @@ else
|
|||||||
</td>
|
</td>
|
||||||
<td>@context.Name</td>
|
<td>@context.Name</td>
|
||||||
<td>@context.Version</td>
|
<td>@context.Version</td>
|
||||||
|
<td>
|
||||||
|
@if (context.IsEnabled)
|
||||||
|
{
|
||||||
|
<span>@SharedLocalizer["Yes"]</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span>@SharedLocalizer["No"]</span>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@if (context.AssemblyName == Constants.ClientId || 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)
|
||||||
{
|
{
|
||||||
@ -149,7 +160,6 @@ else
|
|||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(packagename, version, Constants.PackagesFolder);
|
await PackageService.DownloadPackageAsync(packagename, version, Constants.PackagesFolder);
|
||||||
await logger.LogInformation("Module Downloaded {ModuleDefinitionName} {Version}", packagename, version);
|
await logger.LogInformation("Module Downloaded {ModuleDefinitionName} {Version}", packagename, version);
|
||||||
await ModuleDefinitionService.InstallModuleDefinitionsAsync();
|
|
||||||
AddModuleMessage(string.Format(Localizer["Success.Module.Install"], NavigateUrl("admin/system")), MessageType.Success);
|
AddModuleMessage(string.Format(Localizer["Success.Module.Install"], NavigateUrl("admin/system")), MessageType.Success);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -44,12 +44,20 @@
|
|||||||
<Label Class="col-sm-3" For="page" HelpText="The page that the module is located on" ResourceKey="Page">Page: </Label>
|
<Label Class="col-sm-3" For="page" HelpText="The page that the module is located on" ResourceKey="Page">Page: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="page" class="form-select" @bind="@_pageId" required>
|
<select id="page" class="form-select" @bind="@_pageId" required>
|
||||||
@foreach (Page p in PageState.Pages)
|
@if (PageState.Page.UserId != null)
|
||||||
{
|
{
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.PermissionList))
|
<option value="@PageState.Page.PageId">@(PageState.Page.Name)</option>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (Page p in PageState.Pages)
|
||||||
{
|
{
|
||||||
<option value="@p.PageId">@(new string('-', p.Level * 2))@(p.Name)</option>
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, p.PermissionList))
|
||||||
|
{
|
||||||
|
<option value="@p.PageId">@(new string('-', p.Level * 2))@(p.Name)</option>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@ -90,37 +98,35 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||||
public override string Title => "Module Settings";
|
public override string Title => "Module Settings";
|
||||||
|
|
||||||
private ElementReference form;
|
private ElementReference form;
|
||||||
private bool validated = false;
|
private bool validated = false;
|
||||||
private List<Theme> _themes;
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
private string _title;
|
||||||
private string _title;
|
private string _containerType;
|
||||||
private string _containerType;
|
private string _allPages = "false";
|
||||||
private string _allPages = "false";
|
private string _permissionNames = "";
|
||||||
private string _permissionNames = "";
|
private List<Permission> _permissions = null;
|
||||||
private List<Permission> _permissions = null;
|
private string _pageId;
|
||||||
private string _pageId;
|
private PermissionGrid _permissionGrid;
|
||||||
private PermissionGrid _permissionGrid;
|
private Type _moduleSettingsType;
|
||||||
private Type _moduleSettingsType;
|
private object _moduleSettings;
|
||||||
private object _moduleSettings;
|
private string _moduleSettingsTitle = "Module Settings";
|
||||||
private string _moduleSettingsTitle = "Module Settings";
|
private RenderFragment ModuleSettingsComponent { get; set; }
|
||||||
private RenderFragment ModuleSettingsComponent { get; set; }
|
private Type _containerSettingsType;
|
||||||
private Type _containerSettingsType;
|
private object _containerSettings;
|
||||||
private object _containerSettings;
|
private RenderFragment ContainerSettingsComponent { get; set; }
|
||||||
private RenderFragment ContainerSettingsComponent { get; set; }
|
private string createdby;
|
||||||
private string createdby;
|
private DateTime createdon;
|
||||||
private DateTime createdon;
|
private string modifiedby;
|
||||||
private string modifiedby;
|
private DateTime modifiedon;
|
||||||
private DateTime modifiedon;
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
_title = ModuleState.Title;
|
_title = ModuleState.Title;
|
||||||
_themes = await ThemeService.GetThemesAsync();
|
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, PageState.Page.ThemeType);
|
||||||
_containers = ThemeService.GetContainerControls(_themes, PageState.Page.ThemeType);
|
|
||||||
_containerType = ModuleState.ContainerType;
|
_containerType = ModuleState.ContainerType;
|
||||||
_allPages = ModuleState.AllPages.ToString();
|
_allPages = ModuleState.AllPages.ToString();
|
||||||
_permissions = ModuleState.PermissionList;
|
_permissions = ModuleState.PermissionList;
|
||||||
@ -165,7 +171,7 @@
|
|||||||
AddModuleMessage(string.Format(Localizer["Error.Module.Load"], ModuleState.ModuleDefinitionName), MessageType.Error);
|
AddModuleMessage(string.Format(Localizer["Error.Module.Load"], ModuleState.ModuleDefinitionName), MessageType.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
var theme = _themes.FirstOrDefault(item => item.Containers.Any(themecontrol => themecontrol.TypeName.Equals(_containerType)));
|
var theme = PageState.Site.Themes.FirstOrDefault(item => item.Containers.Any(themecontrol => themecontrol.TypeName.Equals(_containerType)));
|
||||||
if (theme != null && !string.IsNullOrEmpty(theme.ContainerSettingsType))
|
if (theme != null && !string.IsNullOrEmpty(theme.ContainerSettingsType))
|
||||||
{
|
{
|
||||||
_containerSettingsType = Type.GetType(theme.ContainerSettingsType);
|
_containerSettingsType = Type.GetType(theme.ContainerSettingsType);
|
||||||
|
@ -6,12 +6,11 @@
|
|||||||
@inject IStringLocalizer<Add> Localizer
|
@inject IStringLocalizer<Add> Localizer
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
|
||||||
|
@if (_initialized)
|
||||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
{
|
||||||
<TabStrip Refresh="@_refresh">
|
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||||
<TabPanel Name="Settings" ResourceKey="Settings">
|
<TabStrip Refresh="@_refresh">
|
||||||
@if (_themeList != null)
|
<TabPanel Name="Settings" ResourceKey="Settings">
|
||||||
{
|
|
||||||
<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" For="name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label>
|
<Label Class="col-sm-3" For="name" HelpText="Enter the page name" ResourceKey="Name">Name: </Label>
|
||||||
@ -19,42 +18,67 @@
|
|||||||
<input id="name" class="form-control" @bind="@_name" required />
|
<input id="name" class="form-control" @bind="@_name" required />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||||
<Label Class="col-sm-3" For="parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
{
|
||||||
<div class="col-sm-9">
|
<div class="row mb-1 align-items-center">
|
||||||
<select id="parent" class="form-select" @onchange="(e => ParentChanged(e))" required>
|
<Label Class="col-sm-3" For="parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
||||||
<option value="-1"><@Localizer["SiteRoot"]></option>
|
<div class="col-sm-9">
|
||||||
@foreach (Page page in PageState.Pages)
|
<select id="parent" class="form-select" value="@_parentid" @onchange="(e => ParentChanged(e))" required>
|
||||||
{
|
<option value="-1"><@Localizer["SiteRoot"]></option>
|
||||||
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
@foreach (Page page in PageState.Pages)
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="insert" HelpText="Select the location where you would like the page to be inserted in relation to other pages" ResourceKey="Insert">Insert: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="insert" class="form-select" @bind="@_insert" required>
|
|
||||||
<option value="<<">@Localizer["AtBeginning"]</option>
|
|
||||||
@if (_children != null && _children.Count > 0)
|
|
||||||
{
|
|
||||||
<option value="<">@Localizer["Before"]</option>
|
|
||||||
<option value=">">@Localizer["After"]</option>
|
|
||||||
}
|
|
||||||
<option value=">>">@Localizer["AtEnd"]</option>
|
|
||||||
</select>
|
|
||||||
@if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">"))
|
|
||||||
{
|
|
||||||
<select class="form-select" @bind="@_childid">
|
|
||||||
<option value="-1"><@Localizer["Page.Select"]></option>
|
|
||||||
@foreach (Page page in _children)
|
|
||||||
{
|
{
|
||||||
<option value="@(page.PageId)">@(page.Name)</option>
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, page.PermissionList))
|
||||||
|
{
|
||||||
|
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="insert" HelpText="Select the location where you would like the page to be inserted in relation to other pages" ResourceKey="Insert">Insert: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="insert" class="form-select" @bind="@_insert" required>
|
||||||
|
<option value="<<">@Localizer["AtBeginning"]</option>
|
||||||
|
@if (_children != null && _children.Count > 0)
|
||||||
|
{
|
||||||
|
<option value="<">@Localizer["Before"]</option>
|
||||||
|
<option value=">">@Localizer["After"]</option>
|
||||||
|
}
|
||||||
|
<option value=">>">@Localizer["AtEnd"]</option>
|
||||||
|
</select>
|
||||||
|
@if (_children != null && _children.Count > 0 && (_insert == "<" || _insert == ">"))
|
||||||
|
{
|
||||||
|
<select class="form-select" @bind="@_childid">
|
||||||
|
<option value="-1"><@Localizer["Page.Select"]></option>
|
||||||
|
@foreach (Page page in _children)
|
||||||
|
{
|
||||||
|
<option value="@(page.PageId)">@(page.Name)</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="parent" HelpText="Select the parent for the page in the site hierarchy" ResourceKey="Parent">Parent: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="parent" class="form-select" @onchange="(e => ParentChanged(e))" required>
|
||||||
|
<option value="@(_parent.PageId)">@(new string('-', _parent.Level * 2))@(_parent.Name)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="insert" HelpText="Select the location where you would like the page to be inserted in relation to other pages" ResourceKey="Insert">Insert: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="insert" class="form-select" @bind="@_insert" required>
|
||||||
|
<option value=">>">@Localizer["AtEnd"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
|
<Label Class="col-sm-3" For="navigation" HelpText="Select whether the page is part of the site navigation or hidden" ResourceKey="Navigation">Navigation? </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
@ -85,9 +109,24 @@
|
|||||||
<input id="url" class="form-control" @bind="@_url" />
|
<input id="url" class="form-control" @bind="@_url" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="icon" class="form-control" @bind="@_icon" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="personalizable" class="form-select" @bind="@_ispersonalizable" required>
|
||||||
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Section Name="Appearance" ResourceKey="Appearance">
|
<Section Name="Appearance" Heading="Appearance" ResourceKey="Appearance">
|
||||||
<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" For="title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label>
|
<Label Class="col-sm-3" For="title" HelpText="Optionally enter the page title. If you do not provide a page title, the page name will be used." ResourceKey="Title">Title: </Label>
|
||||||
@ -95,16 +134,10 @@
|
|||||||
<input id="title" class="form-control" @bind="@_title" />
|
<input id="title" class="form-control" @bind="@_title" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="meta" HelpText="Optionally enter meta tags (in exactly the form you want them to be included in the page output)." ResourceKey="Meta">Meta: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<textarea id="meta" class="form-control" @bind="@_meta" 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="theme" HelpText="Select the theme for this page" ResourceKey="Theme">Theme: </Label>
|
<Label Class="col-sm-3" For="theme" HelpText="Select the theme for this page" ResourceKey="Theme">Theme: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="theme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))" required>
|
<select id="theme" class="form-select" @bind="@_themetype" required>
|
||||||
@foreach (var theme in _themes)
|
@foreach (var theme in _themes)
|
||||||
{
|
{
|
||||||
<option value="@theme.TypeName">@theme.Name</option>
|
<option value="@theme.TypeName">@theme.Name</option>
|
||||||
@ -116,7 +149,6 @@
|
|||||||
<Label Class="col-sm-3" For="container" HelpText="Select the default container for the page" ResourceKey="DefaultContainer">Default Container: </Label>
|
<Label Class="col-sm-3" For="container" HelpText="Select the default container for the page" ResourceKey="DefaultContainer">Default Container: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="container" class="form-select" @bind="@_containertype" required>
|
<select id="container" class="form-select" @bind="@_containertype" required>
|
||||||
<option value="-"><@Localizer["Container.Select"]></option>
|
|
||||||
@foreach (var container in _containers)
|
@foreach (var container in _containers)
|
||||||
{
|
{
|
||||||
<option value="@container.TypeName">@container.Name</option>
|
<option value="@container.TypeName">@container.Name</option>
|
||||||
@ -124,90 +156,113 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
<Section Name="PageContent" Heading="Page Content" ResourceKey="PageContent">
|
||||||
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label>
|
<Label Class="col-sm-3" For="headcontent" HelpText="Optionally enter content to be included in the page head (ie. meta, link, or script tags)" ResourceKey="HeadContent">Head Content: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="icon" class="form-control" @bind="@_icon" />
|
<textarea id="headcontent" class="form-control" @bind="@_headcontent" rows="3"></textarea>
|
||||||
</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="personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label>
|
<Label Class="col-sm-3" For="bodycontent" HelpText="Optionally enter content to be included in the page body (ie. script tags)" ResourceKey="BodyContent">Body Content: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="personalizable" class="form-select" @bind="@_ispersonalizable" required>
|
<textarea id="bodycontent" class="form-control" @bind="@_bodycontent" rows="3"></textarea>
|
||||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
|
||||||
<option value="False">@SharedLocalizer["No"]</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Section>
|
</Section>
|
||||||
}
|
|
||||||
</TabPanel>
|
|
||||||
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
|
||||||
<div class="container">
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<PermissionGrid EntityName="@EntityNames.Page" Permissions="@_permissions" @ref="_permissionGrid" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</TabPanel>
|
|
||||||
@if (_themeSettingsType != null)
|
|
||||||
{
|
|
||||||
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
|
|
||||||
@ThemeSettingsComponent
|
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
}
|
<TabPanel Name="Permissions" ResourceKey="Permissions">
|
||||||
</TabStrip>
|
<div class="container">
|
||||||
<br />
|
<div class="row mb-1 align-items-center">
|
||||||
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
|
<PermissionGrid EntityName="@EntityNames.Page" Permissions="@_permissions" @ref="_permissionGrid" />
|
||||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
|
</TabPanel>
|
||||||
|
@if (_themeSettingsType != null)
|
||||||
|
{
|
||||||
|
<TabPanel Name="ThemeSettings" Heading="Theme Settings" ResourceKey="ThemeSettings">
|
||||||
|
@ThemeSettingsComponent
|
||||||
|
</TabPanel>
|
||||||
|
}
|
||||||
|
</TabStrip>
|
||||||
|
<br />
|
||||||
|
<button type="button" class="btn btn-success" @onclick="SavePage">@SharedLocalizer["Save"]</button>
|
||||||
|
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
|
||||||
|
</form>
|
||||||
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
|
||||||
|
|
||||||
private List<Theme> _themeList;
|
private bool _initialized = false;
|
||||||
private List<ThemeControl> _themes = new List<ThemeControl>();
|
private ElementReference form;
|
||||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
private bool validated = false;
|
||||||
private string _name;
|
private List<ThemeControl> _themes = new List<ThemeControl>();
|
||||||
private string _title;
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
private string _meta;
|
private int _pageId;
|
||||||
private string _path = string.Empty;
|
private string _name;
|
||||||
private string _parentid = "-1";
|
private string _parentid = "-1";
|
||||||
private string _insert = ">>";
|
private string _insert = ">>";
|
||||||
private List<Page> _children;
|
private List<Page> _children;
|
||||||
private int _childid = -1;
|
private int _childid = -1;
|
||||||
private string _isnavigation = "True";
|
private string _isnavigation = "True";
|
||||||
private string _isclickable = "True";
|
private string _isclickable = "True";
|
||||||
private string _url;
|
private string _path = string.Empty;
|
||||||
private string _ispersonalizable = "False";
|
private string _url;
|
||||||
private string _themetype = string.Empty;
|
private string _ispersonalizable = "False";
|
||||||
private string _containertype = string.Empty;
|
private string _title;
|
||||||
private string _icon = string.Empty;
|
private string _icon = string.Empty;
|
||||||
private string _permissions = null;
|
private string _themetype = string.Empty;
|
||||||
private PermissionGrid _permissionGrid;
|
private string _containertype = string.Empty;
|
||||||
private Type _themeSettingsType;
|
private string _headcontent;
|
||||||
private object _themeSettings;
|
private string _bodycontent;
|
||||||
private RenderFragment ThemeSettingsComponent { get; set; }
|
private string _permissions = null;
|
||||||
private bool _refresh = false;
|
private PermissionGrid _permissionGrid;
|
||||||
private ElementReference form;
|
private Type _themeSettingsType;
|
||||||
private bool validated = false;
|
private object _themeSettings;
|
||||||
|
private RenderFragment ThemeSettingsComponent { get; set; }
|
||||||
|
private bool _refresh = false;
|
||||||
|
protected Page _parent = null;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_themeList = await ThemeService.GetThemesAsync();
|
if (PageState.QueryString.ContainsKey("id"))
|
||||||
_themes = ThemeService.GetThemeControls(_themeList);
|
{
|
||||||
_themetype = PageState.Site.DefaultThemeType;
|
_pageId = Int32.Parse(PageState.QueryString["id"]);
|
||||||
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
_parent = await PageService.GetPageAsync(_pageId);
|
||||||
_containertype = PageState.Site.DefaultContainerType;
|
if (_parent != null)
|
||||||
_children = PageState.Pages.Where(item => item.ParentId == null).ToList();
|
{
|
||||||
ThemeSettings();
|
_parentid = _parent.PageId.ToString();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if admin or user has edit access to parent page
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin) || (_parent != null && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, _parent.PermissionList)))
|
||||||
|
{
|
||||||
|
_themetype = PageState.Site.DefaultThemeType;
|
||||||
|
_themes = ThemeService.GetThemeControls(PageState.Site.Themes, _themetype);
|
||||||
|
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype);
|
||||||
|
_containertype = PageState.Site.DefaultContainerType;
|
||||||
|
_children = PageState.Pages.Where(item => item.ParentId == null).ToList();
|
||||||
|
ThemeSettings();
|
||||||
|
_initialized = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await logger.LogWarning("Error Loading Page {ParentId}", _parentid);
|
||||||
|
AddModuleMessage(Localizer["Error.Page.Load"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Initializing Page {Error}", ex.Message);
|
await logger.LogError(ex, "Error Loading Page {Error}", ex.Message);
|
||||||
AddModuleMessage(Localizer["Error.Page.Initialize"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.Page.Load"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,27 +301,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void ThemeChanged(ChangeEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_themetype = (string)e.Value;
|
|
||||||
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
|
||||||
_containertype = "-";
|
|
||||||
ThemeSettings();
|
|
||||||
StateHasChanged();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Loading Pane Layouts For Theme {ThemeType} {Error}", _themetype, ex.Message);
|
|
||||||
AddModuleMessage(Localizer["Error.Pane.Load"], MessageType.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThemeSettings()
|
private void ThemeSettings()
|
||||||
{
|
{
|
||||||
_themeSettingsType = null;
|
_themeSettingsType = null;
|
||||||
var theme = _themeList.FirstOrDefault(item => item.Themes.Any(themecontrol => themecontrol.TypeName.Equals(_themetype)));
|
var theme = PageState.Site.Themes.FirstOrDefault(item => item.Themes.Any(themecontrol => themecontrol.TypeName.Equals(_themetype)));
|
||||||
if (theme != null && !string.IsNullOrEmpty(theme.ThemeSettingsType))
|
if (theme != null && !string.IsNullOrEmpty(theme.ThemeSettingsType))
|
||||||
{
|
{
|
||||||
_themeSettingsType = Type.GetType(theme.ThemeSettingsType);
|
_themeSettingsType = Type.GetType(theme.ThemeSettingsType);
|
||||||
@ -292,12 +330,11 @@
|
|||||||
Page page = null;
|
Page page = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(_themetype) && _containertype != "-")
|
if (!string.IsNullOrEmpty(_themetype) && !string.IsNullOrEmpty(_containertype))
|
||||||
{
|
{
|
||||||
page = new Page();
|
page = new Page();
|
||||||
page.SiteId = PageState.Page.SiteId;
|
page.SiteId = PageState.Page.SiteId;
|
||||||
page.Name = _name;
|
page.Name = _name;
|
||||||
page.Title = _title;
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(_path))
|
if (string.IsNullOrEmpty(_path))
|
||||||
{
|
{
|
||||||
@ -365,34 +402,42 @@
|
|||||||
|
|
||||||
page.IsNavigation = (_isnavigation == null ? true : Boolean.Parse(_isnavigation));
|
page.IsNavigation = (_isnavigation == null ? true : Boolean.Parse(_isnavigation));
|
||||||
page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
|
page.IsClickable = (_isclickable == null ? true : Boolean.Parse(_isclickable));
|
||||||
page.Url = _url;
|
page.Url = _url;
|
||||||
page.ThemeType = (_themetype != "-") ? _themetype : string.Empty;
|
page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable));
|
||||||
|
page.UserId = null;
|
||||||
|
|
||||||
|
// appearance
|
||||||
|
page.Title = _title;
|
||||||
|
page.Icon = (_icon == null ? string.Empty : _icon);
|
||||||
|
page.ThemeType = _themetype;
|
||||||
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
|
if (!string.IsNullOrEmpty(page.ThemeType) && page.ThemeType == PageState.Site.DefaultThemeType)
|
||||||
{
|
{
|
||||||
page.ThemeType = string.Empty;
|
page.ThemeType = string.Empty;
|
||||||
}
|
}
|
||||||
page.DefaultContainerType = (_containertype != "-") ? _containertype : string.Empty;
|
page.DefaultContainerType = _containertype;
|
||||||
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
|
if (!string.IsNullOrEmpty(page.DefaultContainerType) && page.DefaultContainerType == PageState.Site.DefaultContainerType)
|
||||||
{
|
{
|
||||||
page.DefaultContainerType = string.Empty;
|
page.DefaultContainerType = string.Empty;
|
||||||
}
|
}
|
||||||
page.Icon = (_icon == null ? string.Empty : _icon);
|
|
||||||
|
// page content
|
||||||
|
page.HeadContent = _headcontent;
|
||||||
|
page.BodyContent = _bodycontent;
|
||||||
|
|
||||||
|
// permissions
|
||||||
page.PermissionList = _permissionGrid.GetPermissionList();
|
page.PermissionList = _permissionGrid.GetPermissionList();
|
||||||
page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable));
|
|
||||||
page.UserId = null;
|
|
||||||
page.Meta = _meta;
|
|
||||||
|
|
||||||
page = await PageService.AddPageAsync(page);
|
page = await PageService.AddPageAsync(page);
|
||||||
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId);
|
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId);
|
||||||
|
|
||||||
await logger.LogInformation("Page Added {Page}", page);
|
await logger.LogInformation("Page Added {Page}", page);
|
||||||
if (PageState.QueryString.ContainsKey("cp"))
|
if (!string.IsNullOrEmpty(PageState.ReturnUrl))
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Pages.First(item => item.PageId == int.Parse(PageState.QueryString["cp"])).Path));
|
NavigationManager.NavigateTo(page.Path); // redirect to new page
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(NavigateUrl(page.Path));
|
NavigationManager.NavigateTo(NavigateUrl()); // redirect to page management
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -415,9 +460,9 @@
|
|||||||
|
|
||||||
private void Cancel()
|
private void Cancel()
|
||||||
{
|
{
|
||||||
if (PageState.QueryString.ContainsKey("cp"))
|
if (!string.IsNullOrEmpty(PageState.ReturnUrl))
|
||||||
{
|
{
|
||||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Pages.First(item => item.PageId == int.Parse(PageState.QueryString["cp"])).Path));
|
NavigationManager.NavigateTo(PageState.ReturnUrl);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,7 @@
|
|||||||
@inject IStringLocalizer<Index> Localizer
|
@inject IStringLocalizer<Index> Localizer
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
|
||||||
@if (PageState.Pages != null)
|
@if (PageState.Pages != null && UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||||
{
|
{
|
||||||
<ActionLink Action="Add" Text="Add Page" ResourceKey="AddPage" />
|
<ActionLink Action="Add" Text="Add Page" ResourceKey="AddPage" />
|
||||||
|
|
||||||
|
@ -64,6 +64,12 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="validation" HelpText="Optionally provide a regular expression (RegExp) for validating the value entered" ResourceKey="Validation">Validation: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="validation" class="form-control" @bind="@_validation" maxlength="200" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="private" HelpText="Should this profile item be visible to all users?" ResourceKey="Private">Private? </Label>
|
<Label Class="col-sm-3" For="private" HelpText="Should this profile item be visible to all users?" ResourceKey="Private">Private? </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
@ -97,6 +103,7 @@
|
|||||||
private string _maxlength = "0";
|
private string _maxlength = "0";
|
||||||
private string _defaultvalue = string.Empty;
|
private string _defaultvalue = string.Empty;
|
||||||
private string _options = string.Empty;
|
private string _options = string.Empty;
|
||||||
|
private string _validation = string.Empty;
|
||||||
private string _isrequired = "False";
|
private string _isrequired = "False";
|
||||||
private string _isprivate = "False";
|
private string _isprivate = "False";
|
||||||
private string createdby;
|
private string createdby;
|
||||||
@ -126,6 +133,7 @@
|
|||||||
_maxlength = profile.MaxLength.ToString();
|
_maxlength = profile.MaxLength.ToString();
|
||||||
_defaultvalue = profile.DefaultValue;
|
_defaultvalue = profile.DefaultValue;
|
||||||
_options = profile.Options;
|
_options = profile.Options;
|
||||||
|
_validation = profile.Validation;
|
||||||
_isrequired = profile.IsRequired.ToString();
|
_isrequired = profile.IsRequired.ToString();
|
||||||
_isprivate = profile.IsPrivate.ToString();
|
_isprivate = profile.IsPrivate.ToString();
|
||||||
createdby = profile.CreatedBy;
|
createdby = profile.CreatedBy;
|
||||||
@ -169,6 +177,7 @@
|
|||||||
profile.MaxLength = int.Parse(_maxlength);
|
profile.MaxLength = int.Parse(_maxlength);
|
||||||
profile.DefaultValue = _defaultvalue;
|
profile.DefaultValue = _defaultvalue;
|
||||||
profile.Options = _options;
|
profile.Options = _options;
|
||||||
|
profile.Validation = _validation;
|
||||||
profile.IsRequired = (_isrequired == null ? false : Boolean.Parse(_isrequired));
|
profile.IsRequired = (_isrequired == null ? false : Boolean.Parse(_isrequired));
|
||||||
profile.IsPrivate = (_isprivate == null ? false : Boolean.Parse(_isprivate));
|
profile.IsPrivate = (_isprivate == null ? false : Boolean.Parse(_isprivate));
|
||||||
if (_profileid != -1)
|
if (_profileid != -1)
|
||||||
|
@ -76,8 +76,8 @@ else
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private List<Page> _pages;
|
private List<Page> _pages;
|
||||||
private List<Module> _modules;
|
private List<Module> _modules;
|
||||||
private int _pagePage = 1;
|
private int _pagePage = 1;
|
||||||
private int _pageModule = 1;
|
private int _pageModule = 1;
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
@ -184,13 +184,6 @@ else
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await PageModuleService.DeletePageModuleAsync(module.PageModuleId);
|
await PageModuleService.DeletePageModuleAsync(module.PageModuleId);
|
||||||
|
|
||||||
// check if there are any remaining module instances in the site
|
|
||||||
if (!_modules.Exists (item => item.ModuleId == module.ModuleId && item.PageModuleId != module.PageModuleId))
|
|
||||||
{
|
|
||||||
await ModuleService.DeleteModuleAsync(module.ModuleId);
|
|
||||||
}
|
|
||||||
|
|
||||||
await logger.LogInformation("Module Permanently Deleted {Module}", module);
|
await logger.LogInformation("Module Permanently Deleted {Module}", module);
|
||||||
await Load();
|
await Load();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
@ -210,16 +203,7 @@ else
|
|||||||
foreach (Module module in _modules.Where(item => item.IsDeleted).ToList())
|
foreach (Module module in _modules.Where(item => item.IsDeleted).ToList())
|
||||||
{
|
{
|
||||||
await PageModuleService.DeletePageModuleAsync(module.PageModuleId);
|
await PageModuleService.DeletePageModuleAsync(module.PageModuleId);
|
||||||
|
|
||||||
// DeletePageModuleAsync does not update _modules so remove it.
|
|
||||||
_modules.Remove(module);
|
|
||||||
// check if there are any remaining module instances in the site
|
|
||||||
if (!_modules.Exists(item => item.ModuleId == module.ModuleId && item.PageModuleId != module.PageModuleId))
|
|
||||||
{
|
|
||||||
await ModuleService.DeleteModuleAsync(module.ModuleId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await logger.LogInformation("Modules Permanently Deleted");
|
await logger.LogInformation("Modules Permanently Deleted");
|
||||||
await Load();
|
await Load();
|
||||||
ModuleInstance.HideProgressIndicator();
|
ModuleInstance.HideProgressIndicator();
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@inject IStringLocalizer<Index> Localizer
|
@inject IStringLocalizer<Index> Localizer
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
@inject ISettingService SettingService
|
||||||
|
|
||||||
@if (PageState.Site.AllowRegistration)
|
@if (PageState.Site.AllowRegistration)
|
||||||
{
|
{
|
||||||
@ -15,7 +16,7 @@
|
|||||||
<ModuleMessage Message="@Localizer["Info.Registration.Exists"]" Type="MessageType.Info" />
|
<ModuleMessage Message="@Localizer["Info.Registration.Exists"]" Type="MessageType.Info" />
|
||||||
</Authorized>
|
</Authorized>
|
||||||
<NotAuthorized>
|
<NotAuthorized>
|
||||||
<ModuleMessage Message="@Localizer["Info.Registration.InvalidEmail"]" Type="MessageType.Info" />
|
<ModuleMessage Message="@_passwordconstruction" Type="MessageType.Info" />
|
||||||
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
@ -29,7 +30,7 @@
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" required />
|
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" required />
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -38,7 +39,7 @@
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@_confirm" autocomplete="new-password" required />
|
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@_confirm" autocomplete="new-password" required />
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -68,21 +69,54 @@ else
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string _username = string.Empty;
|
private string _username = string.Empty;
|
||||||
private ElementReference form;
|
private ElementReference form;
|
||||||
private bool validated = false;
|
private bool validated = false;
|
||||||
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 string _email = string.Empty;
|
private string _email = string.Empty;
|
||||||
private string _displayname = string.Empty;
|
private string _displayname = string.Empty;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous;
|
//Password construction
|
||||||
|
private string _minimumlength;
|
||||||
|
private string _uniquecharacters;
|
||||||
|
private bool _requiredigit;
|
||||||
|
private bool _requireupper;
|
||||||
|
private bool _requirelower;
|
||||||
|
private bool _requirepunctuation;
|
||||||
|
private string _passwordconstruction;
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Anonymous;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
|
||||||
|
|
||||||
|
_minimumlength = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredLength", "6");
|
||||||
|
_uniquecharacters = SettingService.GetSetting(settings, "IdentityOptions:Password:RequiredUniqueChars", "1");
|
||||||
|
_requiredigit = bool.Parse(SettingService.GetSetting(settings, "IdentityOptions:Password:RequireDigit", "true"));
|
||||||
|
_requireupper = bool.Parse(SettingService.GetSetting(settings, "IdentityOptions:Password:RequireUppercase", "true"));
|
||||||
|
_requirelower = bool.Parse(SettingService.GetSetting(settings, "IdentityOptions:Password:RequireLowercase", "true"));
|
||||||
|
_requirepunctuation = bool.Parse(SettingService.GetSetting(settings, "IdentityOptions:Password:RequireNonAlphanumeric", "true"));
|
||||||
|
|
||||||
|
// Replace the placeholders with the actual values of the variables
|
||||||
|
string digitRequirement = _requiredigit ? Localizer["Password.DigitRequirement"] + ", " : "";
|
||||||
|
string uppercaseRequirement = _requireupper ? Localizer["Password.UppercaseRequirement"] + ", " : "";
|
||||||
|
string lowercaseRequirement = _requirelower ? Localizer["Password.LowercaseRequirement"] + ", " : "";
|
||||||
|
string punctuationRequirement = _requirepunctuation ? Localizer["Password.PunctuationRequirement"] + ", " : "";
|
||||||
|
|
||||||
|
// Replace the placeholders with the actual values of the variables
|
||||||
|
string passwordValidationCriteriaTemplate = Localizer["Password.ValidationCriteria"];
|
||||||
|
_passwordconstruction = Localizer["Info.Registration.InvalidEmail"] + ". " + string.Format(passwordValidationCriteriaTemplate,
|
||||||
|
_minimumlength, _uniquecharacters, digitRequirement, uppercaseRequirement, lowercaseRequirement, punctuationRequirement);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnParametersSet()
|
||||||
{
|
{
|
||||||
_togglepassword = SharedLocalizer["ShowPassword"];
|
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Register()
|
private async Task Register()
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" required />
|
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" required />
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -27,7 +27,7 @@
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@_confirm" autocomplete="new-password" required />
|
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@_confirm" autocomplete="new-password" required />
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,55 +22,6 @@
|
|||||||
<input id="name" class="form-control" @bind="@_name" maxlength="200" required />
|
<input id="name" class="form-control" @bind="@_name" maxlength="200" required />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="logo" HelpText="Specify a logo for the site" ResourceKey="Logo">Logo: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<FileManager FileId="@_logofileid" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="favicon" HelpText="Specify a Favicon" ResourceKey="FavoriteIcon">Favicon: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<FileManager FileId="@_faviconfileid" Filter="ico" @ref="_faviconfilemanager" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="defaultTheme" HelpText="Select the sites default theme" ResourceKey="DefaultTheme">Default Theme: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="defaultTheme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))" required>
|
|
||||||
<option value="-"><@Localizer["Theme.Select"]></option>
|
|
||||||
@foreach (var theme in _themes)
|
|
||||||
{
|
|
||||||
<option value="@theme.TypeName">@theme.Name</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="defaultContainer" class="form-select" @bind="@_containertype" required>
|
|
||||||
<option value="-"><@Localizer["Container.Select"]></option>
|
|
||||||
@foreach (var container in _containers)
|
|
||||||
{
|
|
||||||
<option value="@container.TypeName">@container.Name</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="defaultAdminContainer" HelpText="Select the default admin container for the site" ResourceKey="DefaultAdminContainer">Default Admin Container: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select id="defaultAdminContainer" class="form-select" @bind="@_admincontainertype" required>
|
|
||||||
<option value="-"><@Localizer["Container.Select"]></option>
|
|
||||||
<option value="@Constants.DefaultAdminContainer"><@Localizer["DefaultAdminContainer"]></option>
|
|
||||||
@foreach (var container in _containers)
|
|
||||||
{
|
|
||||||
<option value="@container.TypeName">@container.Name</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
<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>
|
<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">
|
<div class="col-sm-9">
|
||||||
@ -101,7 +52,80 @@
|
|||||||
<input id="sitemap" class="form-control" @bind="@_sitemap" required disabled />
|
<input id="sitemap" class="form-control" @bind="@_sitemap" required disabled />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="version" HelpText="The site version (for site content migrations)" ResourceKey="Version">Version: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="version" class="form-control" @bind="@_version" required disabled />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<Section Name="Appearance" ResourceKey="Appearance">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="logo" HelpText="Specify a logo for the site" ResourceKey="Logo">Logo: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<FileManager FileId="@_logofileid" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="favicon" HelpText="Specify a Favicon" ResourceKey="FavoriteIcon">Favicon: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<FileManager FileId="@_faviconfileid" Filter="ico,png,gif" @ref="_faviconfilemanager" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="defaultTheme" HelpText="Select the sites default theme" ResourceKey="DefaultTheme">Default Theme: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="defaultTheme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))" required>
|
||||||
|
@foreach (var theme in _themes)
|
||||||
|
{
|
||||||
|
<option value="@theme.TypeName">@theme.Name</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="defaultContainer" class="form-select" @bind="@_containertype" required>
|
||||||
|
@foreach (var container in _containers)
|
||||||
|
{
|
||||||
|
<option value="@container.TypeName">@container.Name</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="defaultAdminContainer" HelpText="Select the default admin container for the site" ResourceKey="DefaultAdminContainer">Default Admin Container: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="defaultAdminContainer" class="form-select" @bind="@_admincontainertype" required>
|
||||||
|
<option value="@Constants.DefaultAdminContainer"><@Localizer["DefaultAdminContainer"]></option>
|
||||||
|
@foreach (var container in _containers)
|
||||||
|
{
|
||||||
|
<option value="@container.TypeName">@container.Name</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
<Section Name="PageContent" Heading="Page Content" ResourceKey="PageContent">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="headcontent" HelpText="Optionally enter content to be included in the page head (ie. meta, link, or script tags)" ResourceKey="HeadContent">Head Content: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea id="headcontent" class="form-control" @bind="@_headcontent" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="bodycontent" HelpText="Optionally enter content to be included in the page body (ie. script tags)" ResourceKey="BodyContent">Body Content: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea id="bodycontent" class="form-control" @bind="@_bodycontent" rows="3"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
<Section Name="SMTP" Heading="SMTP Settings" ResourceKey="SMTPSettings">
|
<Section Name="SMTP" Heading="SMTP Settings" ResourceKey="SMTPSettings">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row mb-1 align-items-center">
|
<div class="row mb-1 align-items-center">
|
||||||
@ -124,9 +148,9 @@
|
|||||||
</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="enabledSSl" HelpText="Specify if SSL is required for your SMTP server" ResourceKey="UseSsl">SSL Enabled: </Label>
|
<Label Class="col-sm-3" For="smtpssl" HelpText="Specify if SSL is required for your SMTP server" ResourceKey="UseSsl">SSL Enabled: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<select id="enabledSSl" class="form-select" @bind="@_smtpssl" >
|
<select id="smtpssl" class="form-select" @bind="@_smtpssl" >
|
||||||
<option value="True">@SharedLocalizer["Yes"]</option>
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
<option value="False">@SharedLocalizer["No"]</option>
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
</select>
|
</select>
|
||||||
@ -143,7 +167,7 @@
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="password" type="@_smtppasswordtype" class="form-control" @bind="@_smtppassword" />
|
<input id="password" type="@_smtppasswordtype" class="form-control" @bind="@_smtppassword" />
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@ToggleSMTPPassword">@_togglesmtppassword</button>
|
<button type="button" class="btn btn-secondary" @onclick="@ToggleSMTPPassword" tabindex="-1">@_togglesmtppassword</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -162,7 +186,16 @@
|
|||||||
</select>
|
</select>
|
||||||
</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="smtpenabled" HelpText="Specify if SMTP is enabled for this site" ResourceKey="SMTPEnabled">Enabled? </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="smtpenabled" class="form-select" @bind="@_smtpenabled">
|
||||||
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
<Label Class="col-sm-3" For="retention" HelpText="Number of days of notifications to retain" ResourceKey="Retention">Retention (Days): </Label>
|
<Label Class="col-sm-3" For="retention" HelpText="Number of days of notifications to retain" ResourceKey="Retention">Retention (Days): </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<input id="retention" class="form-control" @bind="@_retention" />
|
<input id="retention" class="form-control" @bind="@_retention" />
|
||||||
@ -306,222 +339,234 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private ElementReference form;
|
private ElementReference form;
|
||||||
private bool validated = false;
|
private bool validated = false;
|
||||||
private bool _initialized = false;
|
private bool _initialized = false;
|
||||||
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 string _name = string.Empty;
|
||||||
private string _name = string.Empty;
|
private string _homepageid = "-";
|
||||||
private List<Alias> _aliases;
|
private string _isdeleted;
|
||||||
private int _aliasid = -1;
|
private string _sitemap = "";
|
||||||
private string _aliasname;
|
private string _version = "";
|
||||||
private string _defaultalias;
|
private int _logofileid = -1;
|
||||||
private string _runtime = "";
|
private FileManager _logofilemanager;
|
||||||
private string _prerender = "";
|
private int _faviconfileid = -1;
|
||||||
private int _logofileid = -1;
|
private FileManager _faviconfilemanager;
|
||||||
private FileManager _logofilemanager;
|
private string _themetype = "";
|
||||||
private int _faviconfileid = -1;
|
private string _containertype = "";
|
||||||
private FileManager _faviconfilemanager;
|
private string _admincontainertype = "";
|
||||||
private string _themetype = "-";
|
private string _headcontent = string.Empty;
|
||||||
private string _containertype = "-";
|
private string _bodycontent = string.Empty;
|
||||||
private string _admincontainertype = "-";
|
private string _smtphost = string.Empty;
|
||||||
private string _homepageid = "-";
|
private string _smtpport = string.Empty;
|
||||||
private string _sitemap = "";
|
private string _smtpssl = "False";
|
||||||
private string _smtphost = string.Empty;
|
private string _smtpusername = string.Empty;
|
||||||
private string _smtpport = string.Empty;
|
private string _smtppassword = string.Empty;
|
||||||
private string _smtpssl = "False";
|
private string _smtppasswordtype = "password";
|
||||||
private string _smtpusername = string.Empty;
|
private string _togglesmtppassword = string.Empty;
|
||||||
private string _smtppassword = string.Empty;
|
private string _smtpsender = string.Empty;
|
||||||
private string _smtppasswordtype = "password";
|
private string _smtprelay = "False";
|
||||||
private string _togglesmtppassword = string.Empty;
|
private string _smtpenabled = "True";
|
||||||
private string _smtpsender = string.Empty;
|
private string _retention = string.Empty;
|
||||||
private string _smtprelay = "False";
|
private string _pwaisenabled;
|
||||||
private string _retention = string.Empty;
|
private int _pwaappiconfileid = -1;
|
||||||
private string _pwaisenabled;
|
private FileManager _pwaappiconfilemanager;
|
||||||
private int _pwaappiconfileid = -1;
|
private int _pwasplashiconfileid = -1;
|
||||||
private FileManager _pwaappiconfilemanager;
|
private FileManager _pwasplashiconfilemanager;
|
||||||
private int _pwasplashiconfileid = -1;
|
private List<Alias> _aliases;
|
||||||
private FileManager _pwasplashiconfilemanager;
|
private int _aliasid = -1;
|
||||||
private string _tenant = string.Empty;
|
private string _aliasname;
|
||||||
private string _database = string.Empty;
|
private string _defaultalias;
|
||||||
private string _connectionstring = string.Empty;
|
private string _runtime = "";
|
||||||
private string _createdby;
|
private string _prerender = "";
|
||||||
private DateTime _createdon;
|
private string _tenant = string.Empty;
|
||||||
private string _modifiedby;
|
private string _database = string.Empty;
|
||||||
private DateTime _modifiedon;
|
private string _connectionstring = string.Empty;
|
||||||
private string _deletedby;
|
private string _createdby;
|
||||||
private DateTime? _deletedon;
|
private DateTime _createdon;
|
||||||
private string _isdeleted;
|
private string _modifiedby;
|
||||||
|
private DateTime _modifiedon;
|
||||||
|
private string _deletedby;
|
||||||
|
private DateTime? _deletedon;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_themeList = await ThemeService.GetThemesAsync();
|
Site site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
|
||||||
Site site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
|
if (site != null)
|
||||||
if (site != null)
|
{
|
||||||
{
|
_name = site.Name;
|
||||||
_name = site.Name;
|
if (site.HomePageId != null)
|
||||||
_runtime = site.Runtime;
|
{
|
||||||
_prerender = site.RenderMode.Replace(_runtime, "");
|
_homepageid = site.HomePageId.Value.ToString();
|
||||||
_isdeleted = site.IsDeleted.ToString();
|
}
|
||||||
_sitemap = PageState.Alias.Protocol + PageState.Alias.Name + "/pages/sitemap.xml";
|
_isdeleted = site.IsDeleted.ToString();
|
||||||
|
_sitemap = PageState.Alias.Protocol + PageState.Alias.Name + "/pages/sitemap.xml";
|
||||||
|
_version = site.Version;
|
||||||
|
|
||||||
await GetAliases();
|
// appearance
|
||||||
|
if (site.LogoFileId != null)
|
||||||
|
{
|
||||||
|
_logofileid = site.LogoFileId.Value;
|
||||||
|
}
|
||||||
|
|
||||||
if (site.LogoFileId != null)
|
if (site.FaviconFileId != null)
|
||||||
{
|
{
|
||||||
_logofileid = site.LogoFileId.Value;
|
_faviconfileid = site.FaviconFileId.Value;
|
||||||
}
|
}
|
||||||
|
_themes = ThemeService.GetThemeControls(PageState.Site.Themes);
|
||||||
|
_themetype = (!string.IsNullOrEmpty(site.DefaultThemeType)) ? site.DefaultThemeType : Constants.DefaultTheme;
|
||||||
|
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype);
|
||||||
|
_containertype = (!string.IsNullOrEmpty(site.DefaultContainerType)) ? site.DefaultContainerType : Constants.DefaultContainer;
|
||||||
|
_admincontainertype = (!string.IsNullOrEmpty(site.AdminContainerType)) ? site.AdminContainerType : Constants.DefaultAdminContainer;
|
||||||
|
|
||||||
if (site.FaviconFileId != null)
|
// page content
|
||||||
{
|
_headcontent = site.HeadContent;
|
||||||
_faviconfileid = site.FaviconFileId.Value;
|
_bodycontent = site.BodyContent;
|
||||||
}
|
|
||||||
|
|
||||||
_themes = ThemeService.GetThemeControls(_themeList);
|
// PWA
|
||||||
_themetype = (!string.IsNullOrEmpty(site.DefaultThemeType)) ? site.DefaultThemeType : Constants.DefaultTheme;
|
_pwaisenabled = site.PwaIsEnabled.ToString();
|
||||||
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
if (site.PwaAppIconFileId != null)
|
||||||
_containertype = (!string.IsNullOrEmpty(site.DefaultContainerType)) ? site.DefaultContainerType : Constants.DefaultContainer;
|
{
|
||||||
_admincontainertype = (!string.IsNullOrEmpty(site.AdminContainerType)) ? site.AdminContainerType : Constants.DefaultAdminContainer;
|
_pwaappiconfileid = site.PwaAppIconFileId.Value;
|
||||||
|
}
|
||||||
|
if (site.PwaSplashIconFileId != null)
|
||||||
|
{
|
||||||
|
_pwasplashiconfileid = site.PwaSplashIconFileId.Value;
|
||||||
|
}
|
||||||
|
|
||||||
if (site.HomePageId != null)
|
// SMTP
|
||||||
{
|
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
|
||||||
_homepageid = site.HomePageId.Value.ToString();
|
_smtphost = SettingService.GetSetting(settings, "SMTPHost", string.Empty);
|
||||||
}
|
_smtpport = SettingService.GetSetting(settings, "SMTPPort", string.Empty);
|
||||||
|
_smtpssl = SettingService.GetSetting(settings, "SMTPSSL", "False");
|
||||||
|
_smtpusername = SettingService.GetSetting(settings, "SMTPUsername", string.Empty);
|
||||||
|
_smtppassword = SettingService.GetSetting(settings, "SMTPPassword", string.Empty);
|
||||||
|
_togglesmtppassword = SharedLocalizer["ShowPassword"];
|
||||||
|
_smtpsender = SettingService.GetSetting(settings, "SMTPSender", string.Empty);
|
||||||
|
_smtprelay = SettingService.GetSetting(settings, "SMTPRelay", "False");
|
||||||
|
_smtpenabled = SettingService.GetSetting(settings, "SMTPEnabled", "True");
|
||||||
|
_retention = SettingService.GetSetting(settings, "NotificationRetention", "30");
|
||||||
|
|
||||||
_pwaisenabled = site.PwaIsEnabled.ToString();
|
// aliases
|
||||||
if (site.PwaAppIconFileId != null)
|
await GetAliases();
|
||||||
{
|
|
||||||
_pwaappiconfileid = site.PwaAppIconFileId.Value;
|
|
||||||
}
|
|
||||||
if (site.PwaSplashIconFileId != null)
|
|
||||||
{
|
|
||||||
_pwasplashiconfileid = site.PwaSplashIconFileId.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
|
// hosting model
|
||||||
_smtphost = SettingService.GetSetting(settings, "SMTPHost", string.Empty);
|
_runtime = site.Runtime;
|
||||||
_smtpport = SettingService.GetSetting(settings, "SMTPPort", string.Empty);
|
_prerender = site.RenderMode.Replace(_runtime, "");
|
||||||
_smtpssl = SettingService.GetSetting(settings, "SMTPSSL", "False");
|
|
||||||
_smtpusername = SettingService.GetSetting(settings, "SMTPUsername", string.Empty);
|
|
||||||
_smtppassword = SettingService.GetSetting(settings, "SMTPPassword", string.Empty);
|
|
||||||
_togglesmtppassword = SharedLocalizer["ShowPassword"];
|
|
||||||
_smtpsender = SettingService.GetSetting(settings, "SMTPSender", string.Empty);
|
|
||||||
_smtprelay = SettingService.GetSetting(settings, "SMTPRelay", "False");
|
|
||||||
_retention = SettingService.GetSetting(settings, "NotificationRetention", "30");
|
|
||||||
|
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
// database
|
||||||
{
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
var tenants = await TenantService.GetTenantsAsync();
|
{
|
||||||
var _databases = await DatabaseService.GetDatabasesAsync();
|
var tenants = await TenantService.GetTenantsAsync();
|
||||||
var tenant = tenants.Find(item => item.TenantId == site.TenantId);
|
var _databases = await DatabaseService.GetDatabasesAsync();
|
||||||
if (tenant != null)
|
var tenant = tenants.Find(item => item.TenantId == site.TenantId);
|
||||||
{
|
if (tenant != null)
|
||||||
_tenant = tenant.Name;
|
{
|
||||||
_database = _databases.Find(item => item.DBType == tenant.DBType)?.Name;
|
_tenant = tenant.Name;
|
||||||
_connectionstring = tenant.DBConnectionString;
|
_database = _databases.Find(item => item.DBType == tenant.DBType)?.Name;
|
||||||
}
|
_connectionstring = tenant.DBConnectionString;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_createdby = site.CreatedBy;
|
// audit
|
||||||
_createdon = site.CreatedOn;
|
_createdby = site.CreatedBy;
|
||||||
_modifiedby = site.ModifiedBy;
|
_createdon = site.CreatedOn;
|
||||||
_modifiedon = site.ModifiedOn;
|
_modifiedby = site.ModifiedBy;
|
||||||
_deletedby = site.DeletedBy;
|
_modifiedon = site.ModifiedOn;
|
||||||
_deletedon = site.DeletedOn;
|
_deletedby = site.DeletedBy;
|
||||||
|
_deletedon = site.DeletedOn;
|
||||||
|
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Loading Site {SiteId} {Error}", PageState.Site.SiteId, ex.Message);
|
await logger.LogError(ex, "Error Loading Site {SiteId} {Error}", PageState.Site.SiteId, ex.Message);
|
||||||
AddModuleMessage(ex.Message, MessageType.Error);
|
AddModuleMessage(ex.Message, MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void ThemeChanged(ChangeEventArgs e)
|
private async void ThemeChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_themetype = (string)e.Value;
|
_themetype = (string)e.Value;
|
||||||
if (_themetype != "-")
|
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype);
|
||||||
{
|
_containertype = _containers.First().TypeName;
|
||||||
_containers = ThemeService.GetContainerControls(_themeList, _themetype);
|
_admincontainertype = Constants.DefaultAdminContainer;
|
||||||
}
|
StateHasChanged();
|
||||||
else
|
}
|
||||||
{
|
catch (Exception ex)
|
||||||
_containers = new List<ThemeControl>();
|
{
|
||||||
}
|
await logger.LogError(ex, "Error Loading Containers For Theme {ThemeType} {Error}", _themetype, ex.Message);
|
||||||
_containertype = "-";
|
AddModuleMessage(Localizer["Error.Theme.LoadPane"], MessageType.Error);
|
||||||
_admincontainertype = Constants.DefaultAdminContainer;
|
}
|
||||||
StateHasChanged();
|
}
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Loading Containers For Theme {ThemeType} {Error}", _themetype, ex.Message);
|
|
||||||
AddModuleMessage(Localizer["Error.Theme.LoadPane"], MessageType.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SaveSite()
|
private async Task SaveSite()
|
||||||
{
|
{
|
||||||
validated = true;
|
validated = true;
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
if (await interop.FormValid(form))
|
if (await interop.FormValid(form))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (_name != string.Empty && _themetype != "-" && _containertype != "-")
|
if (_name != string.Empty && _themetype != "-" && _containertype != "-")
|
||||||
{
|
{
|
||||||
var site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
|
var site = await SiteService.GetSiteAsync(PageState.Site.SiteId);
|
||||||
if (site != null)
|
if (site != null)
|
||||||
{
|
{
|
||||||
bool refresh = false;
|
bool refresh = false;
|
||||||
bool reload = false;
|
bool reload = false;
|
||||||
|
|
||||||
site.Name = _name;
|
site.Name = _name;
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
site.HomePageId = (_homepageid != "-" ? int.Parse(_homepageid) : null);
|
||||||
{
|
site.IsDeleted = (_isdeleted == null ? true : Boolean.Parse(_isdeleted));
|
||||||
if (site.Runtime != _runtime || site.RenderMode != _runtime + _prerender)
|
|
||||||
{
|
|
||||||
site.Runtime = _runtime;
|
|
||||||
site.RenderMode = _runtime + _prerender;
|
|
||||||
reload = true; // needs to be reloaded on server
|
|
||||||
}
|
|
||||||
}
|
|
||||||
site.IsDeleted = (_isdeleted == null ? true : Boolean.Parse(_isdeleted));
|
|
||||||
|
|
||||||
site.LogoFileId = null;
|
// appearance
|
||||||
var logofileid = _logofilemanager.GetFileId();
|
site.LogoFileId = null;
|
||||||
if (logofileid != -1)
|
var logofileid = _logofilemanager.GetFileId();
|
||||||
{
|
if (logofileid != -1)
|
||||||
site.LogoFileId = logofileid;
|
{
|
||||||
}
|
site.LogoFileId = logofileid;
|
||||||
int? faviconFieldId = _faviconfilemanager.GetFileId();
|
}
|
||||||
if (faviconFieldId == -1) faviconFieldId = null;
|
int? faviconFieldId = _faviconfilemanager.GetFileId();
|
||||||
if (site.FaviconFileId != faviconFieldId)
|
if (faviconFieldId == -1) faviconFieldId = null;
|
||||||
{
|
if (site.FaviconFileId != faviconFieldId)
|
||||||
site.FaviconFileId = faviconFieldId;
|
{
|
||||||
reload = true; // needs to be reloaded on server
|
site.FaviconFileId = faviconFieldId;
|
||||||
}
|
reload = true; // needs to be reloaded on server
|
||||||
if (site.DefaultThemeType != _themetype)
|
}
|
||||||
{
|
if (site.DefaultThemeType != _themetype)
|
||||||
site.DefaultThemeType = _themetype;
|
{
|
||||||
refresh = true; // needs to be refreshed on client
|
site.DefaultThemeType = _themetype;
|
||||||
}
|
refresh = true; // needs to be refreshed on client
|
||||||
if (site.DefaultContainerType != _containertype)
|
}
|
||||||
{
|
if (site.DefaultContainerType != _containertype)
|
||||||
site.DefaultContainerType = _containertype;
|
{
|
||||||
refresh = true; // needs to be refreshed on client
|
site.DefaultContainerType = _containertype;
|
||||||
}
|
refresh = true; // needs to be refreshed on client
|
||||||
site.AdminContainerType = _admincontainertype;
|
}
|
||||||
site.HomePageId = (_homepageid != "-" ? int.Parse(_homepageid) : null);
|
site.AdminContainerType = _admincontainertype;
|
||||||
|
|
||||||
|
// page content
|
||||||
|
if (site.HeadContent != _headcontent)
|
||||||
|
{
|
||||||
|
site.HeadContent = _headcontent;
|
||||||
|
reload = true;
|
||||||
|
}
|
||||||
|
if (site.BodyContent != _bodycontent)
|
||||||
|
{
|
||||||
|
site.BodyContent = _bodycontent;
|
||||||
|
reload = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PWA
|
||||||
if (site.PwaIsEnabled.ToString() != _pwaisenabled)
|
if (site.PwaIsEnabled.ToString() != _pwaisenabled)
|
||||||
{
|
{
|
||||||
site.PwaIsEnabled = Boolean.Parse(_pwaisenabled);
|
site.PwaIsEnabled = Boolean.Parse(_pwaisenabled);
|
||||||
@ -542,8 +587,20 @@
|
|||||||
reload = true; // needs to be reloaded on server
|
reload = true; // needs to be reloaded on server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hosting model
|
||||||
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
|
||||||
|
{
|
||||||
|
if (site.Runtime != _runtime || site.RenderMode != _runtime + _prerender)
|
||||||
|
{
|
||||||
|
site.Runtime = _runtime;
|
||||||
|
site.RenderMode = _runtime + _prerender;
|
||||||
|
reload = true; // needs to be reloaded on server
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
site = await SiteService.UpdateSiteAsync(site);
|
site = await SiteService.UpdateSiteAsync(site);
|
||||||
|
|
||||||
|
// SMTP
|
||||||
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
|
var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
|
||||||
settings = SettingService.SetSetting(settings, "SMTPHost", _smtphost, true);
|
settings = SettingService.SetSetting(settings, "SMTPHost", _smtphost, true);
|
||||||
settings = SettingService.SetSetting(settings, "SMTPPort", _smtpport, true);
|
settings = SettingService.SetSetting(settings, "SMTPPort", _smtpport, true);
|
||||||
@ -552,7 +609,8 @@
|
|||||||
settings = SettingService.SetSetting(settings, "SMTPPassword", _smtppassword, true);
|
settings = SettingService.SetSetting(settings, "SMTPPassword", _smtppassword, true);
|
||||||
settings = SettingService.SetSetting(settings, "SMTPSender", _smtpsender, true);
|
settings = SettingService.SetSetting(settings, "SMTPSender", _smtpsender, true);
|
||||||
settings = SettingService.SetSetting(settings, "SMTPRelay", _smtprelay, true);
|
settings = SettingService.SetSetting(settings, "SMTPRelay", _smtprelay, true);
|
||||||
settings = SettingService.SetSetting(settings, "NotificationRetention", _retention, true);
|
settings = SettingService.SetSetting(settings, "SMTPEnabled", _smtpenabled, true);
|
||||||
|
settings = SettingService.SetSetting(settings, "NotificationRetention", _retention, true);
|
||||||
await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId);
|
await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId);
|
||||||
|
|
||||||
await logger.LogInformation("Site Settings Saved {Site}", site);
|
await logger.LogInformation("Site Settings Saved {Site}", site);
|
||||||
@ -564,8 +622,8 @@
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddModuleMessage(Localizer["Success.Settings.SaveSite"], MessageType.Success);
|
AddModuleMessage(Localizer["Success.Settings.SaveSite"], MessageType.Success);
|
||||||
await interop.ScrollTo(0, 0, "smooth");
|
await ScrollToPageTop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -633,9 +691,8 @@
|
|||||||
|
|
||||||
await NotificationService.AddNotificationAsync(new Notification(PageState.Site.SiteId, PageState.User, PageState.Site.Name + " SMTP Configuration Test", "SMTP Server Is Configured Correctly."));
|
await NotificationService.AddNotificationAsync(new Notification(PageState.Site.SiteId, PageState.User, PageState.Site.Name + " SMTP Configuration Test", "SMTP Server Is Configured Correctly."));
|
||||||
AddModuleMessage(Localizer["Info.Smtp.SaveSettings"], MessageType.Info);
|
AddModuleMessage(Localizer["Info.Smtp.SaveSettings"], MessageType.Info);
|
||||||
var interop = new Interop(JSRuntime);
|
await ScrollToPageTop();
|
||||||
await interop.ScrollTo(0, 0, "smooth");
|
}
|
||||||
}
|
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Testing SMTP Configuration");
|
await logger.LogError(ex, "Error Testing SMTP Configuration");
|
||||||
|
@ -65,13 +65,15 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
<br />
|
||||||
|
<ModuleMessage Type="MessageType.Info" Message="@SharedLocalizer["Oqtane.Marketplace"]" />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel Name="Upload" ResourceKey="Upload">
|
<TabPanel Name="Upload" ResourceKey="Upload">
|
||||||
<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 theme packages. Once they are uploaded click Install to complete the installation." ResourceKey="Theme">Theme: </Label>
|
<Label Class="col-sm-3" HelpText="Upload one or more theme packages. Once they are uploaded click Install to complete the installation." ResourceKey="Theme">Theme: </Label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" />
|
<FileManager Folder="@Constants.PackagesFolder" UploadMultiple="true" OnUpload="OnUpload" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -111,13 +113,8 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<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";
|
||||||
@ -236,7 +233,7 @@
|
|||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(_packageid, _version, Constants.PackagesFolder);
|
await PackageService.DownloadPackageAsync(_packageid, _version, Constants.PackagesFolder);
|
||||||
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _packageid, _version);
|
await logger.LogInformation("Package {PackageId} {Version} Downloaded Successfully", _packageid, _version);
|
||||||
AddModuleMessage(Localizer["Success.Theme.Download"], MessageType.Success);
|
AddModuleMessage(string.Format(Localizer["Success.Theme.Download"], NavigateUrl("admin/system")), MessageType.Success);
|
||||||
_productname = "";
|
_productname = "";
|
||||||
_license = "";
|
_license = "";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
@ -248,16 +245,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task InstallThemes()
|
private void OnUpload()
|
||||||
{
|
{
|
||||||
try
|
AddModuleMessage(string.Format(Localizer["Success.Theme.Download"], NavigateUrl("admin/system")), MessageType.Success);
|
||||||
{
|
|
||||||
await ThemeService.InstallThemesAsync();
|
|
||||||
AddModuleMessage(string.Format(Localizer["Success.Theme.Install"], NavigateUrl("admin/system")), MessageType.Success);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Installing Theme");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@
|
|||||||
if (_owner != "" && _theme != "" && _template != "-")
|
if (_owner != "" && _theme != "" && _template != "-")
|
||||||
{
|
{
|
||||||
var template = _templates.FirstOrDefault(item => item.Name == _template);
|
var template = _templates.FirstOrDefault(item => item.Name == _template);
|
||||||
_location = template.Location + _owner + "." + _theme;
|
_location = template.Location + _owner + ".Theme." + _theme;
|
||||||
|
|
||||||
}
|
}
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
|
162
Oqtane.Client/Modules/Admin/Themes/Edit.razor
Normal file
162
Oqtane.Client/Modules/Admin/Themes/Edit.razor
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
@namespace Oqtane.Modules.Admin.Themes
|
||||||
|
@using System.Net
|
||||||
|
@inherits ModuleBase
|
||||||
|
@inject IThemeService ThemeService
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
@inject IStringLocalizer<Edit> Localizer
|
||||||
|
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
||||||
|
|
||||||
|
@if (_initialized)
|
||||||
|
{
|
||||||
|
<form @ref="form" class="@(validated ? "was-validated" : "needs-validation")" novalidate>
|
||||||
|
<div class="container">
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="name" HelpText="The name of the module" ResourceKey="Name">Name: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="name" class="form-control" @bind="@_name" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="isenabled" HelpText="Is theme enabled for this site?" ResourceKey="IsEnabled">Enabled? </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select id="isenabled" class="form-select" @bind="@_isenabled" required>
|
||||||
|
<option value="True">@SharedLocalizer["Yes"]</option>
|
||||||
|
<option value="False">@SharedLocalizer["No"]</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<Section Name="Information" ResourceKey="Information">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="themename" HelpText="The internal name of the module" ResourceKey="InternalName">Internal Name: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="themename" class="form-control" @bind="@_themeName" disabled />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="version" HelpText="The version of the theme" ResourceKey="Version">Version: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="version" class="form-control" @bind="@_version" disabled />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<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>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="owner" class="form-control" @bind="@_owner" disabled />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="url" HelpText="The reference url of the theme" ResourceKey="ReferenceUrl">Reference Url: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="url" class="form-control" @bind="@_url" disabled />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="contact" HelpText="The contact for the theme" ResourceKey="Contact">Contact: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input id="contact" class="form-control" @bind="@_contact" disabled />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-1 align-items-center">
|
||||||
|
<Label Class="col-sm-3" For="license" HelpText="The license of the theme" ResourceKey="License">License: </Label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea id="license" class="form-control" @bind="@_license" rows="5" disabled></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Section>
|
||||||
|
<br />
|
||||||
|
<button type="button" class="btn btn-success" @onclick="SaveTheme">@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>
|
||||||
|
}
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private bool _initialized = false;
|
||||||
|
private ElementReference form;
|
||||||
|
private bool validated = false;
|
||||||
|
private int _themeId;
|
||||||
|
private string _themeName = "";
|
||||||
|
private string _isenabled;
|
||||||
|
private string _name;
|
||||||
|
private string _version;
|
||||||
|
private string _packagename;
|
||||||
|
private string _owner = "";
|
||||||
|
private string _url = "";
|
||||||
|
private string _contact = "";
|
||||||
|
private string _license = "";
|
||||||
|
private string _createdby;
|
||||||
|
private DateTime _createdon;
|
||||||
|
private string _modifiedby;
|
||||||
|
private DateTime _modifiedon;
|
||||||
|
|
||||||
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_themeId = Int32.Parse(PageState.QueryString["id"]);
|
||||||
|
var theme = await ThemeService.GetThemeAsync(_themeId, ModuleState.SiteId);
|
||||||
|
if (theme != null)
|
||||||
|
{
|
||||||
|
_name = theme.Name;
|
||||||
|
_isenabled =theme.IsEnabled.ToString();
|
||||||
|
_version = theme.Version;
|
||||||
|
_packagename = theme.PackageName;
|
||||||
|
_owner = theme.Owner;
|
||||||
|
_url = theme.Url;
|
||||||
|
_contact = theme.Contact;
|
||||||
|
_license = theme.License;
|
||||||
|
_createdby = theme.CreatedBy;
|
||||||
|
_createdon = theme.CreatedOn;
|
||||||
|
_modifiedby = theme.ModifiedBy;
|
||||||
|
_modifiedon = theme.ModifiedOn;
|
||||||
|
|
||||||
|
_initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Loading Theme {ThemeName} {Error}", _themeName, ex.Message);
|
||||||
|
AddModuleMessage(Localizer["Error.Theme.Loading"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SaveTheme()
|
||||||
|
{
|
||||||
|
validated = true;
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
if (await interop.FormValid(form))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var theme = await ThemeService.GetThemeAsync(_themeId, ModuleState.SiteId);
|
||||||
|
theme.Name = _name;
|
||||||
|
theme.IsEnabled = (_isenabled == null ? true : bool.Parse(_isenabled));
|
||||||
|
await ThemeService.UpdateThemeAsync(theme);
|
||||||
|
await logger.LogInformation("Theme Saved {Theme}", theme);
|
||||||
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Saving Theme {ThemeId} {Error}", _themeId, ex.Message);
|
||||||
|
AddModuleMessage(Localizer["Error.Module.Save"], MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,11 +23,12 @@ else
|
|||||||
<th style="width: 1px;"> </th>
|
<th style="width: 1px;"> </th>
|
||||||
<th>@SharedLocalizer["Name"]</th>
|
<th>@SharedLocalizer["Name"]</th>
|
||||||
<th>@SharedLocalizer["Version"]</th>
|
<th>@SharedLocalizer["Version"]</th>
|
||||||
|
<th>@Localizer["Enabled"]</th>
|
||||||
<th>@SharedLocalizer["Expires"]</th>
|
<th>@SharedLocalizer["Expires"]</th>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
</Header>
|
</Header>
|
||||||
<Row>
|
<Row>
|
||||||
<td><ActionLink Action="View" Parameters="@($"name=" + WebUtility.UrlEncode(context.ThemeName))" ResourceKey="ViewTheme" /></td>
|
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.ThemeId.ToString())" ResourceKey="EditModule" /></td>
|
||||||
<td>
|
<td>
|
||||||
@if (context.AssemblyName != Constants.ClientId)
|
@if (context.AssemblyName != Constants.ClientId)
|
||||||
{
|
{
|
||||||
@ -36,6 +37,16 @@ else
|
|||||||
</td>
|
</td>
|
||||||
<td>@context.Name</td>
|
<td>@context.Name</td>
|
||||||
<td>@context.Version</td>
|
<td>@context.Version</td>
|
||||||
|
<td>
|
||||||
|
@if (context.IsEnabled)
|
||||||
|
{
|
||||||
|
<span>@SharedLocalizer["Yes"]</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span>@SharedLocalizer["No"]</span>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@((MarkupString)PurchaseLink(context.PackageName))
|
@((MarkupString)PurchaseLink(context.PackageName))
|
||||||
</td>
|
</td>
|
||||||
@ -116,7 +127,6 @@ else
|
|||||||
{
|
{
|
||||||
await PackageService.DownloadPackageAsync(packagename, version, Constants.PackagesFolder);
|
await PackageService.DownloadPackageAsync(packagename, version, Constants.PackagesFolder);
|
||||||
await logger.LogInformation("Theme Downloaded {ThemeName} {Version}", packagename, version);
|
await logger.LogInformation("Theme Downloaded {ThemeName} {Version}", packagename, version);
|
||||||
await ThemeService.InstallThemesAsync();
|
|
||||||
AddModuleMessage(string.Format(Localizer["Success.Theme.Install"], NavigateUrl("admin/system")), MessageType.Success);
|
AddModuleMessage(string.Format(Localizer["Success.Theme.Install"], NavigateUrl("admin/system")), MessageType.Success);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -1,97 +0,0 @@
|
|||||||
@namespace Oqtane.Modules.Admin.Themes
|
|
||||||
@using System.Net
|
|
||||||
@inherits ModuleBase
|
|
||||||
@inject IThemeService ThemeService
|
|
||||||
@inject NavigationManager NavigationManager
|
|
||||||
@inject IStringLocalizer<View> Localizer
|
|
||||||
@inject IStringLocalizer<SharedResources> SharedLocalizer
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="name" HelpText="The name of the theme" ResourceKey="Name">Name: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="name" class="form-control" @bind="@_name" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="themename" HelpText="The internal name of the module" ResourceKey="InternalName">Internal Name: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="themename" class="form-control" @bind="@_themeName" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="version" HelpText="The version of the theme" ResourceKey="Version">Version: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="version" class="form-control" @bind="@_version" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<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>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="owner" class="form-control" @bind="@_owner" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="url" HelpText="The reference url of the theme" ResourceKey="ReferenceUrl">Reference Url: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="url" class="form-control" @bind="@_url" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="contact" HelpText="The contact for the theme" ResourceKey="Contact">Contact: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input id="contact" class="form-control" @bind="@_contact" disabled />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-1 align-items-center">
|
|
||||||
<Label Class="col-sm-3" For="license" HelpText="The license of the theme" ResourceKey="License">License: </Label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<textarea id="license" class="form-control" @bind="@_license" rows="5" disabled></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink>
|
|
||||||
|
|
||||||
@code {
|
|
||||||
private string _themeName = "";
|
|
||||||
private string _name;
|
|
||||||
private string _version;
|
|
||||||
private string _packagename;
|
|
||||||
private string _owner = "";
|
|
||||||
private string _url = "";
|
|
||||||
private string _contact = "";
|
|
||||||
private string _license = "";
|
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_themeName = WebUtility.UrlDecode(PageState.QueryString["name"]);
|
|
||||||
var themes = await ThemeService.GetThemesAsync();
|
|
||||||
var theme = themes.FirstOrDefault(item => item.ThemeName == _themeName);
|
|
||||||
if (theme != null)
|
|
||||||
{
|
|
||||||
_name = theme.Name;
|
|
||||||
_version = theme.Version;
|
|
||||||
_packagename = theme.PackageName;
|
|
||||||
_owner = theme.Owner;
|
|
||||||
_url = theme.Url;
|
|
||||||
_contact = theme.Contact;
|
|
||||||
_license = theme.License;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await logger.LogError(ex, "Error Loading Theme {ThemeName} {Error}", _themeName, ex.Message);
|
|
||||||
AddModuleMessage(Localizer["Error.Theme.Loading"], MessageType.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,5 @@
|
|||||||
@namespace Oqtane.Modules.Admin.UserProfile
|
@namespace Oqtane.Modules.Admin.UserProfile
|
||||||
|
@using System.Text.RegularExpressions;
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@ -34,7 +35,7 @@ else
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" />
|
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" />
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -43,7 +44,7 @@ else
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@confirm" autocomplete="new-password" />
|
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@confirm" autocomplete="new-password" />
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -227,140 +228,140 @@ else
|
|||||||
<br /><br />
|
<br /><br />
|
||||||
|
|
||||||
@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";
|
||||||
private string email = string.Empty;
|
private string email = string.Empty;
|
||||||
private string displayname = string.Empty;
|
private string displayname = string.Empty;
|
||||||
private FileManager filemanager;
|
private FileManager filemanager;
|
||||||
private int folderid = -1;
|
private int folderid = -1;
|
||||||
private int photofileid = -1;
|
private int photofileid = -1;
|
||||||
private File photo = null;
|
private File photo = null;
|
||||||
private List<Profile> profiles;
|
private List<Profile> profiles;
|
||||||
private Dictionary<string, string> settings;
|
private Dictionary<string, string> settings;
|
||||||
private string category = string.Empty;
|
private string category = string.Empty;
|
||||||
private string filter = "to";
|
private string filter = "to";
|
||||||
private List<Notification> notifications;
|
private List<Notification> notifications;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_togglepassword = SharedLocalizer["ShowPassword"];
|
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||||
|
|
||||||
if (PageState.Site.Settings.ContainsKey("LoginOptions:TwoFactor") && !string.IsNullOrEmpty(PageState.Site.Settings["LoginOptions:TwoFactor"]))
|
if (PageState.Site.Settings.ContainsKey("LoginOptions:TwoFactor") && !string.IsNullOrEmpty(PageState.Site.Settings["LoginOptions:TwoFactor"]))
|
||||||
{
|
{
|
||||||
allowtwofactor = (PageState.Site.Settings["LoginOptions:TwoFactor"] == "true");
|
allowtwofactor = (PageState.Site.Settings["LoginOptions:TwoFactor"] == "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PageState.User != null)
|
if (PageState.User != null)
|
||||||
{
|
{
|
||||||
username = PageState.User.Username;
|
username = PageState.User.Username;
|
||||||
twofactor = PageState.User.TwoFactorRequired.ToString();
|
twofactor = PageState.User.TwoFactorRequired.ToString();
|
||||||
email = PageState.User.Email;
|
email = PageState.User.Email;
|
||||||
displayname = PageState.User.DisplayName;
|
displayname = PageState.User.DisplayName;
|
||||||
|
|
||||||
// get user folder
|
// get user folder
|
||||||
var folder = await FolderService.GetFolderAsync(ModuleState.SiteId, PageState.User.FolderPath);
|
var folder = await FolderService.GetFolderAsync(ModuleState.SiteId, PageState.User.FolderPath);
|
||||||
if (folder != null)
|
if (folder != null)
|
||||||
{
|
{
|
||||||
folderid = folder.FolderId;
|
folderid = folder.FolderId;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PageState.User.PhotoFileId != null)
|
if (PageState.User.PhotoFileId != null)
|
||||||
{
|
{
|
||||||
photofileid = PageState.User.PhotoFileId.Value;
|
photofileid = PageState.User.PhotoFileId.Value;
|
||||||
photo = await FileService.GetFileAsync(photofileid);
|
photo = await FileService.GetFileAsync(photofileid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
photofileid = -1;
|
photofileid = -1;
|
||||||
photo = null;
|
photo = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
|
profiles = await ProfileService.GetProfilesAsync(ModuleState.SiteId);
|
||||||
settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
|
||||||
|
|
||||||
await LoadNotificationsAsync();
|
await LoadNotificationsAsync();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddModuleMessage(Localizer["Message.User.NoLogIn"], MessageType.Warning);
|
AddModuleMessage(Localizer["Message.User.NoLogIn"], MessageType.Warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Loading User Profile {Error}", ex.Message);
|
await logger.LogError(ex, "Error Loading User Profile {Error}", ex.Message);
|
||||||
AddModuleMessage(Localizer["Error.Profile.Load"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.Profile.Load"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task LoadNotificationsAsync()
|
private async Task LoadNotificationsAsync()
|
||||||
{
|
{
|
||||||
notifications = await NotificationService.GetNotificationsAsync(PageState.Site.SiteId, filter, PageState.User.UserId);
|
notifications = await NotificationService.GetNotificationsAsync(PageState.Site.SiteId, filter, PageState.User.UserId);
|
||||||
notifications = notifications.Where(item => item.DeletedBy != PageState.User.Username).ToList();
|
notifications = notifications.Where(item => item.DeletedBy != PageState.User.Username).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetProfileValue(string SettingName, string DefaultValue)
|
private string GetProfileValue(string SettingName, string DefaultValue)
|
||||||
{
|
{
|
||||||
string value = SettingService.GetSetting(settings, SettingName, DefaultValue);
|
string value = SettingService.GetSetting(settings, SettingName, DefaultValue);
|
||||||
if (value.Contains("]"))
|
if (value.Contains("]"))
|
||||||
{
|
{
|
||||||
value = value.Substring(value.IndexOf("]") + 1);
|
value = value.Substring(value.IndexOf("]") + 1);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Save()
|
private async Task Save()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (username != string.Empty && email != string.Empty && ValidateProfiles())
|
if (username != string.Empty && email != string.Empty && ValidateProfiles())
|
||||||
{
|
{
|
||||||
if (_password == confirm)
|
if (_password == confirm)
|
||||||
{
|
{
|
||||||
var user = PageState.User;
|
var user = PageState.User;
|
||||||
user.Username = username;
|
user.Username = username;
|
||||||
user.Password = _password;
|
user.Password = _password;
|
||||||
user.TwoFactorRequired = bool.Parse(twofactor);
|
user.TwoFactorRequired = bool.Parse(twofactor);
|
||||||
user.Email = email;
|
user.Email = email;
|
||||||
user.DisplayName = (displayname == string.Empty ? username : displayname);
|
user.DisplayName = (displayname == string.Empty ? username : displayname);
|
||||||
user.PhotoFileId = filemanager.GetFileId();
|
user.PhotoFileId = filemanager.GetFileId();
|
||||||
if (user.PhotoFileId == -1)
|
if (user.PhotoFileId == -1)
|
||||||
{
|
{
|
||||||
user.PhotoFileId = null;
|
user.PhotoFileId = null;
|
||||||
}
|
}
|
||||||
if (user.PhotoFileId != null)
|
if (user.PhotoFileId != null)
|
||||||
{
|
{
|
||||||
photofileid = user.PhotoFileId.Value;
|
photofileid = user.PhotoFileId.Value;
|
||||||
photo = await FileService.GetFileAsync(photofileid);
|
photo = await FileService.GetFileAsync(photofileid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
photofileid = -1;
|
photofileid = -1;
|
||||||
photo = null;
|
photo = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
user = await UserService.UpdateUserAsync(user);
|
user = await UserService.UpdateUserAsync(user);
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
|
await SettingService.UpdateUserSettingsAsync(settings, PageState.User.UserId);
|
||||||
await logger.LogInformation("User Profile Saved");
|
await logger.LogInformation("User Profile Saved");
|
||||||
|
|
||||||
AddModuleMessage(Localizer["Success.Profile.Update"], MessageType.Success);
|
AddModuleMessage(Localizer["Success.Profile.Update"], MessageType.Success);
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddModuleMessage(Localizer["Message.Password.Complexity"], MessageType.Error);
|
AddModuleMessage(Localizer["Message.Password.Complexity"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddModuleMessage(Localizer["Message.Password.Invalid"], MessageType.Warning);
|
AddModuleMessage(Localizer["Message.Password.Invalid"], MessageType.Warning);
|
||||||
@ -370,6 +371,8 @@ else
|
|||||||
{
|
{
|
||||||
AddModuleMessage(Localizer["Message.Required.ProfileInfo"], MessageType.Warning);
|
AddModuleMessage(Localizer["Message.Required.ProfileInfo"], MessageType.Warning);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await ScrollToPageTop();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -389,10 +392,15 @@ else
|
|||||||
}
|
}
|
||||||
if (!profile.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
if (!profile.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||||
{
|
{
|
||||||
if (profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)))
|
if (valid == true && profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)))
|
||||||
{
|
{
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
|
if (valid == true && !string.IsNullOrEmpty(profile.Validation))
|
||||||
|
{
|
||||||
|
Regex regex = new Regex(profile.Validation);
|
||||||
|
valid = regex.Match(SettingService.GetSetting(settings, profile.Name, string.Empty)).Success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return valid;
|
return valid;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
@namespace Oqtane.Modules.Admin.Users
|
@namespace Oqtane.Modules.Admin.Users
|
||||||
|
@using System.Text.RegularExpressions;
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@ -23,7 +24,7 @@
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" required />
|
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" required />
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -32,7 +33,7 @@
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@confirm" autocomplete="new-password" required />
|
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@confirm" autocomplete="new-password" required />
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -95,8 +96,8 @@
|
|||||||
@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 string email = string.Empty;
|
private string email = string.Empty;
|
||||||
private string displayname = string.Empty;
|
private string displayname = string.Empty;
|
||||||
@ -121,15 +122,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetProfileValue(string SettingName, string DefaultValue)
|
private string GetProfileValue(string SettingName, string DefaultValue)
|
||||||
{
|
{
|
||||||
string value = SettingService.GetSetting(settings, SettingName, DefaultValue);
|
string value = SettingService.GetSetting(settings, SettingName, DefaultValue);
|
||||||
if (value.Contains("]"))
|
if (value.Contains("]"))
|
||||||
{
|
{
|
||||||
value = value.Substring(value.IndexOf("]") + 1);
|
value = value.Substring(value.IndexOf("]") + 1);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SaveUser()
|
private async Task SaveUser()
|
||||||
{
|
{
|
||||||
@ -195,9 +196,17 @@
|
|||||||
{
|
{
|
||||||
settings = SettingService.SetSetting(settings, profile.Name, profile.DefaultValue);
|
settings = SettingService.SetSetting(settings, profile.Name, profile.DefaultValue);
|
||||||
}
|
}
|
||||||
if (profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)))
|
if (!profile.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||||
{
|
{
|
||||||
valid = false;
|
if (valid == true && profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)))
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
if (valid == true && !string.IsNullOrEmpty(profile.Validation))
|
||||||
|
{
|
||||||
|
Regex regex = new Regex(profile.Validation);
|
||||||
|
valid = regex.Match(SettingService.GetSetting(settings, profile.Name, string.Empty)).Success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return valid;
|
return valid;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
@namespace Oqtane.Modules.Admin.Users
|
@namespace Oqtane.Modules.Admin.Users
|
||||||
|
@using System.Text.RegularExpressions;
|
||||||
@inherits ModuleBase
|
@inherits ModuleBase
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IUserService UserService
|
@inject IUserService UserService
|
||||||
@ -32,7 +33,7 @@ else
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" />
|
<input id="password" type="@_passwordtype" class="form-control" @bind="@_password" autocomplete="new-password" />
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -41,7 +42,7 @@ else
|
|||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@confirm" autocomplete="new-password" />
|
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@confirm" autocomplete="new-password" />
|
||||||
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button>
|
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword" tabindex="-1">@_togglepassword</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -148,124 +149,124 @@ else
|
|||||||
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon" DeletedBy="@deletedby" DeletedOn="@deletedon"></AuditInfo>
|
<AuditInfo CreatedBy="@createdby" CreatedOn="@createdon" ModifiedBy="@modifiedby" ModifiedOn="@modifiedon" DeletedBy="@deletedby" DeletedOn="@deletedon"></AuditInfo>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private int userid;
|
private int userid;
|
||||||
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 string email = string.Empty;
|
private string email = string.Empty;
|
||||||
private string displayname = string.Empty;
|
private string displayname = string.Empty;
|
||||||
private FileManager filemanager;
|
private FileManager filemanager;
|
||||||
private int photofileid = -1;
|
private int photofileid = -1;
|
||||||
private File photo = null;
|
private File photo = null;
|
||||||
private string isdeleted;
|
private string isdeleted;
|
||||||
private string lastlogin;
|
private string lastlogin;
|
||||||
private string lastipaddress;
|
private string lastipaddress;
|
||||||
|
|
||||||
private List<Profile> profiles;
|
private List<Profile> profiles;
|
||||||
private Dictionary<string, string> settings;
|
private Dictionary<string, string> settings;
|
||||||
private string category = string.Empty;
|
private string category = string.Empty;
|
||||||
|
|
||||||
private string createdby;
|
private string createdby;
|
||||||
private DateTime createdon;
|
private DateTime createdon;
|
||||||
private string modifiedby;
|
private string modifiedby;
|
||||||
private DateTime modifiedon;
|
private DateTime modifiedon;
|
||||||
private string deletedby;
|
private string deletedby;
|
||||||
private DateTime? deletedon;
|
private DateTime? deletedon;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (PageState.QueryString.ContainsKey("id"))
|
if (PageState.QueryString.ContainsKey("id"))
|
||||||
{
|
{
|
||||||
_togglepassword = SharedLocalizer["ShowPassword"];
|
_togglepassword = SharedLocalizer["ShowPassword"];
|
||||||
profiles = await ProfileService.GetProfilesAsync(PageState.Site.SiteId);
|
profiles = await ProfileService.GetProfilesAsync(PageState.Site.SiteId);
|
||||||
userid = Int32.Parse(PageState.QueryString["id"]);
|
userid = Int32.Parse(PageState.QueryString["id"]);
|
||||||
var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
username = user.Username;
|
username = user.Username;
|
||||||
email = user.Email;
|
email = user.Email;
|
||||||
displayname = user.DisplayName;
|
displayname = user.DisplayName;
|
||||||
if (user.PhotoFileId != null)
|
if (user.PhotoFileId != null)
|
||||||
{
|
{
|
||||||
photofileid = user.PhotoFileId.Value;
|
photofileid = user.PhotoFileId.Value;
|
||||||
photo = await FileService.GetFileAsync(photofileid);
|
photo = await FileService.GetFileAsync(photofileid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
photofileid = -1;
|
photofileid = -1;
|
||||||
photo = null;
|
photo = null;
|
||||||
}
|
}
|
||||||
isdeleted = user.IsDeleted.ToString();
|
isdeleted = user.IsDeleted.ToString();
|
||||||
lastlogin = string.Format("{0:MMM dd yyyy HH:mm:ss}", user.LastLoginOn);
|
lastlogin = string.Format("{0:MMM dd yyyy HH:mm:ss}", user.LastLoginOn);
|
||||||
lastipaddress = user.LastIPAddress;
|
lastipaddress = user.LastIPAddress;
|
||||||
|
|
||||||
settings = await SettingService.GetUserSettingsAsync(user.UserId);
|
settings = await SettingService.GetUserSettingsAsync(user.UserId);
|
||||||
createdby = user.CreatedBy;
|
createdby = user.CreatedBy;
|
||||||
createdon = user.CreatedOn;
|
createdon = user.CreatedOn;
|
||||||
modifiedby = user.ModifiedBy;
|
modifiedby = user.ModifiedBy;
|
||||||
modifiedon = user.ModifiedOn;
|
modifiedon = user.ModifiedOn;
|
||||||
deletedby = user.DeletedBy;
|
deletedby = user.DeletedBy;
|
||||||
deletedon = user.DeletedOn;
|
deletedon = user.DeletedOn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Loading User {UserId} {Error}", userid, ex.Message);
|
await logger.LogError(ex, "Error Loading User {UserId} {Error}", userid, ex.Message);
|
||||||
AddModuleMessage(Localizer["Error.User.Load"], MessageType.Error);
|
AddModuleMessage(Localizer["Error.User.Load"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetProfileValue(string SettingName, string DefaultValue)
|
private string GetProfileValue(string SettingName, string DefaultValue)
|
||||||
{
|
{
|
||||||
string value = SettingService.GetSetting(settings, SettingName, DefaultValue);
|
string value = SettingService.GetSetting(settings, SettingName, DefaultValue);
|
||||||
if (value.Contains("]"))
|
if (value.Contains("]"))
|
||||||
{
|
{
|
||||||
value = value.Substring(value.IndexOf("]") + 1);
|
value = value.Substring(value.IndexOf("]") + 1);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SaveUser()
|
private async Task SaveUser()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (username != string.Empty && email != string.Empty && ValidateProfiles())
|
if (username != string.Empty && email != string.Empty && ValidateProfiles())
|
||||||
{
|
{
|
||||||
if (_password == confirm)
|
if (_password == confirm)
|
||||||
{
|
{
|
||||||
var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
var user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
|
||||||
user.SiteId = PageState.Site.SiteId;
|
user.SiteId = PageState.Site.SiteId;
|
||||||
user.Username = username;
|
user.Username = username;
|
||||||
user.Password = _password;
|
user.Password = _password;
|
||||||
user.Email = email;
|
user.Email = email;
|
||||||
user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname;
|
user.DisplayName = string.IsNullOrWhiteSpace(displayname) ? username : displayname;
|
||||||
user.PhotoFileId = null;
|
user.PhotoFileId = null;
|
||||||
user.PhotoFileId = filemanager.GetFileId();
|
user.PhotoFileId = filemanager.GetFileId();
|
||||||
if (user.PhotoFileId == -1)
|
if (user.PhotoFileId == -1)
|
||||||
{
|
{
|
||||||
user.PhotoFileId = null;
|
user.PhotoFileId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
user.IsDeleted = (isdeleted == null ? true : Boolean.Parse(isdeleted));
|
user.IsDeleted = (isdeleted == null ? true : Boolean.Parse(isdeleted));
|
||||||
|
|
||||||
user = await UserService.UpdateUserAsync(user);
|
user = await UserService.UpdateUserAsync(user);
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
await SettingService.UpdateUserSettingsAsync(settings, user.UserId);
|
await SettingService.UpdateUserSettingsAsync(settings, user.UserId);
|
||||||
await logger.LogInformation("User Saved {User}", user);
|
await logger.LogInformation("User Saved {User}", user);
|
||||||
NavigationManager.NavigateTo(NavigateUrl());
|
NavigationManager.NavigateTo(NavigateUrl());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AddModuleMessage(Localizer["Message.Password.Complexity"], MessageType.Error);
|
AddModuleMessage(Localizer["Message.Password.Complexity"], MessageType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -293,9 +294,17 @@ else
|
|||||||
{
|
{
|
||||||
settings = SettingService.SetSetting(settings, profile.Name, profile.DefaultValue);
|
settings = SettingService.SetSetting(settings, profile.Name, profile.DefaultValue);
|
||||||
}
|
}
|
||||||
if (profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)))
|
if (!profile.IsPrivate || UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
||||||
{
|
{
|
||||||
valid = false;
|
if (valid == true && profile.IsRequired && string.IsNullOrEmpty(SettingService.GetSetting(settings, profile.Name, string.Empty)))
|
||||||
|
{
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
if (valid == true && !string.IsNullOrEmpty(profile.Validation))
|
||||||
|
{
|
||||||
|
Regex regex = new Regex(profile.Validation);
|
||||||
|
valid = regex.Match(SettingService.GetSetting(settings, profile.Name, string.Empty)).Success;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return valid;
|
return valid;
|
||||||
|
@ -87,299 +87,306 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private bool _initialized = false;
|
private bool _initialized = false;
|
||||||
private List<Folder> _folders;
|
private List<Folder> _folders;
|
||||||
private List<File> _files = new List<File>();
|
private List<File> _files = new List<File>();
|
||||||
private string _fileinputid = string.Empty;
|
private string _fileinputid = string.Empty;
|
||||||
private string _progressinfoid = string.Empty;
|
private string _progressinfoid = string.Empty;
|
||||||
private string _progressbarid = string.Empty;
|
private string _progressbarid = string.Empty;
|
||||||
private string _filter = "*";
|
private string _filter = "*";
|
||||||
private bool _haseditpermission = false;
|
private bool _haseditpermission = false;
|
||||||
private string _image = string.Empty;
|
private string _image = string.Empty;
|
||||||
private File _file = null;
|
private File _file = null;
|
||||||
private string _guid;
|
private string _guid;
|
||||||
private string _message = string.Empty;
|
private string _message = string.Empty;
|
||||||
private MessageType _messagetype;
|
private MessageType _messagetype;
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Id { get; set; } // optional - for setting the id of the FileManager component for accessibility
|
public string Id { get; set; } // optional - for setting the id of the FileManager component for accessibility
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public int FolderId { get; set; } = -1; // optional - for setting a specific default folder by folderid
|
public int FolderId { get; set; } = -1; // optional - for setting a specific default folder by folderid
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Folder { get; set; } = ""; // optional - for setting a specific default folder by folder path
|
public string Folder { get; set; } = ""; // optional - for setting a specific default folder by folder path
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public int FileId { get; set; } = -1; // optional - for selecting a specific file by default
|
public int FileId { get; set; } = -1; // optional - for selecting a specific file by default
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Filter { get; set; } // optional - comma delimited list of file types that can be selected or uploaded ie. "jpg,gif"
|
public string Filter { get; set; } // optional - comma delimited list of file types that can be selected or uploaded ie. "jpg,gif"
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool ShowFiles { get; set; } = true; // optional - for indicating whether a list of files should be displayed - default is true
|
public bool ShowFiles { get; set; } = true; // optional - for indicating whether a list of files should be displayed - default is true
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool ShowUpload { get; set; } = true; // optional - for indicating whether a Upload controls should be displayed - default is true
|
public bool ShowUpload { get; set; } = true; // optional - for indicating whether a Upload controls should be displayed - default is true
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool ShowFolders { get; set; } = true; // optional - for indicating whether a list of folders should be displayed - default is true
|
public bool ShowFolders { get; set; } = true; // optional - for indicating whether a list of folders should be displayed - default is true
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool ShowImage { get; set; } = true; // optional - for indicating whether an image thumbnail should be displayed - default is true
|
public bool ShowImage { get; set; } = true; // optional - for indicating whether an image thumbnail should be displayed - default is true
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool ShowSuccess { get; set; } = false; // optional - for indicating whether a success message should be displayed upon successful upload - default is false
|
public bool ShowSuccess { get; set; } = false; // optional - for indicating whether a success message should be displayed upon successful upload - default is false
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool UploadMultiple { get; set; } = false; // optional - enable multiple file uploads - default false
|
public bool UploadMultiple { get; set; } = false; // optional - enable multiple file uploads - default false
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public EventCallback<int> OnUpload { get; set; } // optional - executes a method in the calling component when a file is uploaded
|
public EventCallback<int> OnUpload { get; set; } // optional - executes a method in the calling component when a file is uploaded
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public EventCallback<int> OnSelect { get; set; } // optional - executes a method in the calling component when a file is selected
|
public EventCallback<int> OnSelect { get; set; } // optional - executes a method in the calling component when a file is selected
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public EventCallback<int> OnDelete { get; set; } // optional - executes a method in the calling component when a file is deleted
|
public EventCallback<int> OnDelete { get; set; } // optional - executes a method in the calling component when a file is deleted
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
// packages folder is a framework folder for uploading installable nuget packages
|
// packages folder is a framework folder for uploading installable nuget packages
|
||||||
if (Folder == Constants.PackagesFolder)
|
if (Folder == Constants.PackagesFolder)
|
||||||
{
|
{
|
||||||
ShowFiles = false;
|
ShowFiles = false;
|
||||||
ShowFolders = false;
|
ShowFolders = false;
|
||||||
Filter = "nupkg";
|
Filter = "nupkg";
|
||||||
ShowSuccess = true;
|
ShowSuccess = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ShowFiles)
|
if (!ShowFiles)
|
||||||
{
|
{
|
||||||
ShowImage = false;
|
ShowImage = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_folders = await FolderService.GetFoldersAsync(ModuleState.SiteId);
|
_folders = await FolderService.GetFoldersAsync(ModuleState.SiteId);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Folder) && Folder != Constants.PackagesFolder)
|
if (!string.IsNullOrEmpty(Folder) && Folder != Constants.PackagesFolder)
|
||||||
{
|
{
|
||||||
Folder folder = await FolderService.GetFolderAsync(ModuleState.SiteId, Folder);
|
Folder folder = await FolderService.GetFolderAsync(ModuleState.SiteId, Folder);
|
||||||
if (folder != null)
|
if (folder != null)
|
||||||
{
|
{
|
||||||
FolderId = folder.FolderId;
|
FolderId = folder.FolderId;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FolderId = -1;
|
FolderId = -1;
|
||||||
_message = "Folder Path " + Folder + "Does Not Exist";
|
_message = "Folder Path " + Folder + "Does Not Exist";
|
||||||
_messagetype = MessageType.Error;
|
_messagetype = MessageType.Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FileId != -1)
|
if (FileId != -1)
|
||||||
{
|
{
|
||||||
File file = await FileService.GetFileAsync(FileId);
|
File file = await FileService.GetFileAsync(FileId);
|
||||||
if (file != null)
|
if (file != null)
|
||||||
{
|
{
|
||||||
FolderId = file.FolderId;
|
FolderId = file.FolderId;
|
||||||
await OnSelect.InvokeAsync(FileId);
|
await OnSelect.InvokeAsync(FileId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FileId = -1; // file does not exist
|
FileId = -1; // file does not exist
|
||||||
_message = "FileId " + FileId.ToString() + "Does Not Exist";
|
_message = "FileId " + FileId.ToString() + "Does Not Exist";
|
||||||
_messagetype = MessageType.Error;
|
_messagetype = MessageType.Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await SetImage();
|
await SetImage();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Filter))
|
if (!string.IsNullOrEmpty(Filter))
|
||||||
{
|
{
|
||||||
_filter = "." + Filter.Replace(",", ",.");
|
_filter = "." + Filter.Replace(",", ",.");
|
||||||
}
|
}
|
||||||
|
|
||||||
await GetFiles();
|
await GetFiles();
|
||||||
|
|
||||||
// create unique id for component
|
// create unique id for component
|
||||||
_guid = Guid.NewGuid().ToString("N");
|
_guid = Guid.NewGuid().ToString("N");
|
||||||
_fileinputid = "FileInput_" + _guid;
|
_fileinputid = "FileInput_" + _guid;
|
||||||
_progressinfoid = "ProgressInfo_" + _guid;
|
_progressinfoid = "ProgressInfo_" + _guid;
|
||||||
_progressbarid = "ProgressBar_" + _guid;
|
_progressbarid = "ProgressBar_" + _guid;
|
||||||
|
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task GetFiles()
|
private async Task GetFiles()
|
||||||
{
|
{
|
||||||
_haseditpermission = false;
|
_haseditpermission = false;
|
||||||
if (Folder == Constants.PackagesFolder)
|
if (Folder == Constants.PackagesFolder)
|
||||||
{
|
{
|
||||||
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, RoleNames.Host);
|
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, RoleNames.Host);
|
||||||
_files = new List<File>();
|
_files = new List<File>();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Folder folder = _folders.FirstOrDefault(item => item.FolderId == FolderId);
|
Folder folder = _folders.FirstOrDefault(item => item.FolderId == FolderId);
|
||||||
if (folder != null)
|
if (folder != null)
|
||||||
{
|
{
|
||||||
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, folder.PermissionList);
|
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, folder.PermissionList);
|
||||||
_files = await FileService.GetFilesAsync(FolderId);
|
_files = await FileService.GetFilesAsync(FolderId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_haseditpermission = false;
|
_haseditpermission = false;
|
||||||
_files = new List<File>();
|
_files = new List<File>();
|
||||||
}
|
}
|
||||||
}
|
if (_filter != "*")
|
||||||
if (_filter != "*")
|
{
|
||||||
{
|
List<File> filtered = new List<File>();
|
||||||
List<File> filtered = new List<File>();
|
foreach (File file in _files)
|
||||||
foreach (File file in _files)
|
{
|
||||||
{
|
if (_filter.ToUpper().IndexOf("." + file.Extension.ToUpper()) != -1)
|
||||||
if (_filter.ToUpper().IndexOf("." + file.Extension.ToUpper()) != -1)
|
{
|
||||||
{
|
filtered.Add(file);
|
||||||
filtered.Add(file);
|
}
|
||||||
}
|
}
|
||||||
}
|
_files = filtered;
|
||||||
_files = filtered;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task FolderChanged(ChangeEventArgs e)
|
private async Task FolderChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
_message = string.Empty;
|
_message = string.Empty;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
FolderId = int.Parse((string)e.Value);
|
FolderId = int.Parse((string)e.Value);
|
||||||
await GetFiles();
|
await GetFiles();
|
||||||
FileId = -1;
|
FileId = -1;
|
||||||
_file = null;
|
_file = null;
|
||||||
_image = string.Empty;
|
_image = string.Empty;
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await logger.LogError(ex, "Error Loading Files {Error}", ex.Message);
|
await logger.LogError(ex, "Error Loading Files {Error}", ex.Message);
|
||||||
_message = Localizer["Error.File.Load"];
|
_message = Localizer["Error.File.Load"];
|
||||||
_messagetype = MessageType.Error;
|
_messagetype = MessageType.Error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task FileChanged(ChangeEventArgs e)
|
private async Task FileChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
_message = string.Empty;
|
_message = string.Empty;
|
||||||
FileId = int.Parse((string)e.Value);
|
FileId = int.Parse((string)e.Value);
|
||||||
if (FileId != -1)
|
if (FileId != -1)
|
||||||
{
|
{
|
||||||
await OnSelect.InvokeAsync(FileId);
|
await OnSelect.InvokeAsync(FileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
await SetImage();
|
await SetImage();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SetImage()
|
private async Task SetImage()
|
||||||
{
|
{
|
||||||
_image = string.Empty;
|
_image = string.Empty;
|
||||||
_file = null;
|
_file = null;
|
||||||
if (FileId != -1)
|
if (FileId != -1)
|
||||||
{
|
{
|
||||||
_file = await FileService.GetFileAsync(FileId);
|
_file = await FileService.GetFileAsync(FileId);
|
||||||
if (_file != null && ShowImage && _file.ImageHeight != 0 && _file.ImageWidth != 0)
|
if (_file != null && ShowImage && _file.ImageHeight != 0 && _file.ImageWidth != 0)
|
||||||
{
|
{
|
||||||
var maxwidth = 200;
|
var maxwidth = 200;
|
||||||
var maxheight = 200;
|
var maxheight = 200;
|
||||||
|
|
||||||
var ratioX = (double)maxwidth / (double)_file.ImageWidth;
|
var ratioX = (double)maxwidth / (double)_file.ImageWidth;
|
||||||
var ratioY = (double)maxheight / (double)_file.ImageHeight;
|
var ratioY = (double)maxheight / (double)_file.ImageHeight;
|
||||||
var ratio = ratioX < ratioY ? ratioX : ratioY;
|
var ratio = ratioX < ratioY ? ratioX : ratioY;
|
||||||
|
|
||||||
_image = "<img src=\"" + _file.Url + "\" alt=\"" + _file.Name +
|
_image = "<img src=\"" + _file.Url + "\" alt=\"" + _file.Name +
|
||||||
"\" width=\"" + Convert.ToInt32(_file.ImageWidth * ratio).ToString() +
|
"\" width=\"" + Convert.ToInt32(_file.ImageWidth * ratio).ToString() +
|
||||||
"\" height=\"" + Convert.ToInt32(_file.ImageHeight * ratio).ToString() + "\" />";
|
"\" height=\"" + Convert.ToInt32(_file.ImageHeight * ratio).ToString() + "\" />";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UploadFiles()
|
private async Task UploadFiles()
|
||||||
{
|
{
|
||||||
_message = string.Empty;
|
_message = string.Empty;
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
var uploads = await interop.GetFiles(_fileinputid);
|
var uploads = await interop.GetFiles(_fileinputid);
|
||||||
if (uploads.Length > 0)
|
if (uploads.Length > 0)
|
||||||
{
|
{
|
||||||
string restricted = "";
|
string restricted = "";
|
||||||
foreach (var upload in uploads)
|
foreach (var upload in uploads)
|
||||||
{
|
{
|
||||||
var extension = (upload.LastIndexOf(".") != -1) ? upload.Substring(upload.LastIndexOf(".") + 1) : "";
|
var extension = (upload.LastIndexOf(".") != -1) ? upload.Substring(upload.LastIndexOf(".") + 1) : "";
|
||||||
if (!Constants.UploadableFiles.Split(',').Contains(extension.ToLower()))
|
if (!Constants.UploadableFiles.Split(',').Contains(extension.ToLower()))
|
||||||
{
|
{
|
||||||
restricted += (restricted == "" ? "" : ",") + extension;
|
restricted += (restricted == "" ? "" : ",") + extension;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (restricted == "")
|
if (restricted == "")
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// upload the files
|
// upload the files
|
||||||
var posturl = Utilities.TenantUrl(PageState.Alias, "/api/file/upload");
|
var posturl = Utilities.TenantUrl(PageState.Alias, "/api/file/upload");
|
||||||
var folder = (Folder == Constants.PackagesFolder) ? Folder : FolderId.ToString();
|
var folder = (Folder == Constants.PackagesFolder) ? Folder : FolderId.ToString();
|
||||||
await interop.UploadFiles(posturl, folder, _guid, SiteState.AntiForgeryToken);
|
await interop.UploadFiles(posturl, folder, _guid, SiteState.AntiForgeryToken);
|
||||||
|
|
||||||
// uploading is asynchronous so we need to wait for the uploads to complete
|
// uploading is asynchronous so we need to wait for the uploads to complete
|
||||||
// note that this will only wait a maximum of 15 seconds which may not be long enough for very large file uploads
|
// note that this will only wait a maximum of 15 seconds which may not be long enough for very large file uploads
|
||||||
bool success = false;
|
bool success = false;
|
||||||
int attempts = 0;
|
int attempts = 0;
|
||||||
while (attempts < 5 && !success)
|
while (attempts < 5 && !success)
|
||||||
{
|
{
|
||||||
attempts += 1;
|
attempts += 1;
|
||||||
Thread.Sleep(1000 * attempts); // progressive retry
|
Thread.Sleep(1000 * attempts); // progressive retry
|
||||||
|
|
||||||
success = true;
|
success = true;
|
||||||
List<File> files = await FileService.GetFilesAsync(folder);
|
List<File> files = await FileService.GetFilesAsync(folder);
|
||||||
if (files.Count > 0)
|
if (files.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (string upload in uploads)
|
foreach (string upload in uploads)
|
||||||
{
|
{
|
||||||
if (!files.Exists(item => item.Name == upload))
|
if (!files.Exists(item => item.Name == upload))
|
||||||
{
|
{
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset progress indicators
|
// reset progress indicators
|
||||||
await interop.SetElementAttribute(_guid + "ProgressInfo", "style", "display: none;");
|
await interop.SetElementAttribute(_guid + "ProgressInfo", "style", "display: none;");
|
||||||
await interop.SetElementAttribute(_guid + "ProgressBar", "style", "display: none;");
|
await interop.SetElementAttribute(_guid + "ProgressBar", "style", "display: none;");
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
await logger.LogInformation("File Upload Succeeded {Files}", uploads);
|
await logger.LogInformation("File Upload Succeeded {Files}", uploads);
|
||||||
if (ShowSuccess)
|
if (ShowSuccess)
|
||||||
{
|
{
|
||||||
_message = Localizer["Success.File.Upload"];
|
_message = Localizer["Success.File.Upload"];
|
||||||
_messagetype = MessageType.Success;
|
_messagetype = MessageType.Success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await logger.LogInformation("File Upload Failed Or Is Still In Progress {Files}", uploads);
|
await logger.LogInformation("File Upload Failed Or Is Still In Progress {Files}", uploads);
|
||||||
_message = Localizer["Error.File.Upload"];
|
_message = Localizer["Error.File.Upload"];
|
||||||
_messagetype = MessageType.Error;
|
_messagetype = MessageType.Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set FileId to first file in upload collection
|
if (Folder == Constants.PackagesFolder)
|
||||||
await GetFiles();
|
{
|
||||||
var file = _files.Where(item => item.Name == uploads[0]).FirstOrDefault();
|
await OnUpload.InvokeAsync(-1);
|
||||||
if (file != null)
|
}
|
||||||
{
|
else
|
||||||
FileId = file.FileId;
|
{
|
||||||
await SetImage();
|
// set FileId to first file in upload collection
|
||||||
await OnUpload.InvokeAsync(FileId);
|
await GetFiles();
|
||||||
}
|
var file = _files.Where(item => item.Name == uploads[0]).FirstOrDefault();
|
||||||
StateHasChanged();
|
if (file != null)
|
||||||
|
{
|
||||||
|
FileId = file.FileId;
|
||||||
|
await SetImage();
|
||||||
|
await OnUpload.InvokeAsync(FileId);
|
||||||
|
}
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -53,7 +53,6 @@
|
|||||||
|
|
||||||
public override List<Resource> Resources => new List<Resource>()
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
{
|
{
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" },
|
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill.bubble.css" },
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill.bubble.css" },
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill.snow.css" }
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill.snow.css" }
|
||||||
};
|
};
|
||||||
|
@ -15,11 +15,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
public override List<Resource> Resources => new List<Resource>()
|
|
||||||
{
|
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
|
|
||||||
};
|
|
||||||
|
|
||||||
private string content = "";
|
private string content = "";
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
using Oqtane.Documentation;
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Modules.HtmlText
|
namespace Oqtane.Modules.HtmlText
|
||||||
{
|
{
|
||||||
@ -13,7 +15,11 @@ namespace Oqtane.Modules.HtmlText
|
|||||||
Version = "1.0.1",
|
Version = "1.0.1",
|
||||||
ServerManagerType = "Oqtane.Modules.HtmlText.Manager.HtmlTextManager, Oqtane.Server",
|
ServerManagerType = "Oqtane.Modules.HtmlText.Manager.HtmlTextManager, Oqtane.Server",
|
||||||
ReleaseVersions = "1.0.0,1.0.1",
|
ReleaseVersions = "1.0.0,1.0.1",
|
||||||
SettingsType = "Oqtane.Modules.HtmlText.Settings, Oqtane.Client"
|
SettingsType = "Oqtane.Modules.HtmlText.Settings, Oqtane.Client",
|
||||||
|
Resources = new List<Resource>()
|
||||||
|
{
|
||||||
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "~/Module.css" }
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ using Oqtane.UI;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Oqtane.Themes;
|
||||||
|
|
||||||
namespace Oqtane.Modules
|
namespace Oqtane.Modules
|
||||||
{
|
{
|
||||||
@ -70,17 +71,33 @@ namespace Oqtane.Modules
|
|||||||
{
|
{
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
{
|
{
|
||||||
if (Resources != null && Resources.Exists(item => item.ResourceType == ResourceType.Script))
|
List<Resource> resources = null;
|
||||||
|
var type = GetType();
|
||||||
|
if (type.BaseType == typeof(ModuleBase))
|
||||||
|
{
|
||||||
|
if (PageState.Page.Resources != null)
|
||||||
|
{
|
||||||
|
resources = PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Script && item.Level != ResourceLevel.Site && item.Namespace == type.Namespace).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // modulecontrolbase
|
||||||
|
{
|
||||||
|
if (Resources != null)
|
||||||
|
{
|
||||||
|
resources = Resources.Where(item => item.ResourceType == ResourceType.Script).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resources != null &&resources.Any())
|
||||||
{
|
{
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
var scripts = new List<object>();
|
var scripts = new List<object>();
|
||||||
var inline = 0;
|
var inline = 0;
|
||||||
foreach (Resource resource in Resources.Where(item => item.ResourceType == ResourceType.Script))
|
foreach (Resource resource in resources)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(resource.Url))
|
if (!string.IsNullOrEmpty(resource.Url))
|
||||||
{
|
{
|
||||||
var url = (resource.Url.Contains("://")) ? resource.Url : PageState.Alias.BaseUrl + resource.Url;
|
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 });
|
scripts.Add(new { href = url, bundle = resource.Bundle ?? "", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "", es6module = resource.ES6Module, location = resource.Location.ToString().ToLower() });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -104,6 +121,7 @@ namespace Oqtane.Modules
|
|||||||
}
|
}
|
||||||
|
|
||||||
// url methods
|
// url methods
|
||||||
|
|
||||||
public string NavigateUrl()
|
public string NavigateUrl()
|
||||||
{
|
{
|
||||||
return NavigateUrl(PageState.Page.Path);
|
return NavigateUrl(PageState.Page.Path);
|
||||||
@ -273,6 +291,33 @@ namespace Oqtane.Modules
|
|||||||
SiteState.Properties.ModuleVisibility = obj;
|
SiteState.Properties.ModuleVisibility = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetPageTitle(string title)
|
||||||
|
{
|
||||||
|
SiteState.Properties.PageTitle = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
// note - only supports links and meta tags - not scripts
|
||||||
|
public void AddHeadContent(string content)
|
||||||
|
{
|
||||||
|
SiteState.AppendHeadContent(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddScript(Resource resource)
|
||||||
|
{
|
||||||
|
resource.ResourceType = ResourceType.Script;
|
||||||
|
if (Resources == null) Resources = new List<Resource>();
|
||||||
|
if (!Resources.Any(item => (!string.IsNullOrEmpty(resource.Url) && item.Url == resource.Url) || (!string.IsNullOrEmpty(resource.Content) && item.Content == resource.Content)))
|
||||||
|
{
|
||||||
|
Resources.Add(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ScrollToPageTop()
|
||||||
|
{
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
await interop.ScrollTo(0, 0, "smooth");
|
||||||
|
}
|
||||||
|
|
||||||
// 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)
|
||||||
{
|
{
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
|
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RazorLangVersion>3.0</RazorLangVersion>
|
<RazorLangVersion>3.0</RazorLangVersion>
|
||||||
<Configurations>Debug;Release</Configurations>
|
<Configurations>Debug;Release</Configurations>
|
||||||
<Version>3.4.1</Version>
|
<Version>4.0.0</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
<Description>Modular Application Framework for Blazor and MAUI</Description>
|
<Description>CMS and Application Framework for Blazor and .NET 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.4.1</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.0</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>
|
||||||
@ -22,13 +22,13 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.3" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.5" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.3" PrivateAssets="all" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.5" PrivateAssets="all" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="6.0.3" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="7.0.5" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Localization" Version="7.0.5" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
|
||||||
|
<PackageReference Include="System.Net.Http.Json" Version="7.0.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Localization" Version="2.2.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Localization" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="6.0.3" />
|
|
||||||
<PackageReference Include="System.Net.Http.Json" Version="6.0.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -16,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
|
||||||
@ -198,23 +197,37 @@ namespace Oqtane.Client
|
|||||||
private static void RegisterModuleServices(Assembly assembly, IServiceCollection services)
|
private static void RegisterModuleServices(Assembly assembly, IServiceCollection services)
|
||||||
{
|
{
|
||||||
// dynamically register module scoped services
|
// dynamically register module scoped services
|
||||||
var implementationTypes = assembly.GetInterfaces<IService>();
|
try
|
||||||
foreach (var implementationType in implementationTypes)
|
|
||||||
{
|
{
|
||||||
if (implementationType.AssemblyQualifiedName != null)
|
var implementationTypes = assembly.GetInterfaces<IService>();
|
||||||
|
foreach (var implementationType in implementationTypes)
|
||||||
{
|
{
|
||||||
var serviceType = Type.GetType(implementationType.AssemblyQualifiedName.Replace(implementationType.Name, $"I{implementationType.Name}"));
|
if (implementationType.AssemblyQualifiedName != null)
|
||||||
services.AddScoped(serviceType ?? implementationType, implementationType);
|
{
|
||||||
|
var serviceType = Type.GetType(implementationType.AssemblyQualifiedName.Replace(implementationType.Name, $"I{implementationType.Name}"));
|
||||||
|
services.AddScoped(serviceType ?? implementationType, implementationType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// could not interrogate assembly - likely missing dependencies
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void RegisterClientStartups(Assembly assembly, IServiceCollection services)
|
private static void RegisterClientStartups(Assembly assembly, IServiceCollection services)
|
||||||
{
|
{
|
||||||
var startUps = assembly.GetInstances<IClientStartup>();
|
try
|
||||||
foreach (var startup in startUps)
|
|
||||||
{
|
{
|
||||||
startup.ConfigureServices(services);
|
var startUps = assembly.GetInstances<IClientStartup>();
|
||||||
|
foreach (var startup in startUps)
|
||||||
|
{
|
||||||
|
startup.ConfigureServices(services);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// could not interrogate assembly - likely missing dependencies
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@
|
|||||||
<value>Database:</value>
|
<value>Database:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ApplicationAdmin" xml:space="preserve">
|
<data name="ApplicationAdmin" xml:space="preserve">
|
||||||
<value>Application Administrator</value>
|
<value>Application Administration</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="InstallNow" xml:space="preserve">
|
<data name="InstallNow" xml:space="preserve">
|
||||||
<value>Install Now</value>
|
<value>Install Now</value>
|
||||||
@ -180,4 +180,7 @@
|
|||||||
<data name="EnterConnectionString" xml:space="preserve">
|
<data name="EnterConnectionString" xml:space="preserve">
|
||||||
<value>Enter Connection String</value>
|
<value>Enter Connection String</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Template" xml:space="preserve">
|
||||||
|
<value>Select a site template</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -120,29 +120,23 @@
|
|||||||
<data name="Error.Language.Add" xml:space="preserve">
|
<data name="Error.Language.Add" xml:space="preserve">
|
||||||
<value>Error Adding Language</value>
|
<value>Error Adding Language</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Translated.HelpText" xml:space="preserve">
|
|
||||||
<value>Specify If You Wish To Select Languages That Have Translations Installed</value>
|
|
||||||
</data>
|
|
||||||
<data name="Name.HelpText" xml:space="preserve">
|
<data name="Name.HelpText" xml:space="preserve">
|
||||||
<value>Name Of The Langauage</value>
|
<value>Name Of The Langauage</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IsDefault.HelpText" xml:space="preserve">
|
<data name="IsDefault.HelpText" xml:space="preserve">
|
||||||
<value>Indicates Whether Or Not This Language Is The Default For The Site</value>
|
<value>Indicates Whether Or Not This Language Is The Default For The Site</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Translated.Text" xml:space="preserve">
|
|
||||||
<value>Translated?</value>
|
|
||||||
</data>
|
|
||||||
<data name="Name.Text" xml:space="preserve">
|
<data name="Name.Text" xml:space="preserve">
|
||||||
<value>Name:</value>
|
<value>Name:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="IsDefault.Text" xml:space="preserve">
|
<data name="IsDefault.Text" xml:space="preserve">
|
||||||
<value>Default?</value>
|
<value>Default?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Success.Language.Install" xml:space="preserve">
|
<data name="Success.Language.Download" xml:space="preserve">
|
||||||
<value>Translations Installed Successfully. You Must <a href={0}>Restart</a> Your Application To Apply These Changes.</value>
|
<value>Translation Package Saved Successfully. You Must <a href={0}>Restart</a> To Complete The Installation.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LanguageUpload.HelpText" xml:space="preserve">
|
<data name="LanguageUpload.HelpText" xml:space="preserve">
|
||||||
<value>Upload one or more translation packages. Once they are uploaded click Install to complete the installation.</value>
|
<value>Upload one or more translation packages.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LanguageUpload.Text" xml:space="preserve">
|
<data name="LanguageUpload.Text" xml:space="preserve">
|
||||||
<value>Translation</value>
|
<value>Translation</value>
|
||||||
|
@ -132,12 +132,12 @@
|
|||||||
<data name="DeleteLanguage.Header" xml:space="preserve">
|
<data name="DeleteLanguage.Header" xml:space="preserve">
|
||||||
<value>Delete Language</value>
|
<value>Delete Language</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Success.Language.Download" xml:space="preserve">
|
||||||
|
<value>Translation Package Saved Successfully. You Must <a href={0}>Restart</a> Your Application To Complete The Installation.</value>
|
||||||
|
</data>
|
||||||
<data name="Error.Language.Download" xml:space="preserve">
|
<data name="Error.Language.Download" xml:space="preserve">
|
||||||
<value>Error Downloading Translation</value>
|
<value>Error Downloading Translation</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Success.Language.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="Default" xml:space="preserve">
|
<data name="Default" xml:space="preserve">
|
||||||
<value>Default</value>
|
<value>Default</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -123,17 +123,14 @@
|
|||||||
<data name="Error.Package.Load" xml:space="preserve">
|
<data name="Error.Package.Load" xml:space="preserve">
|
||||||
<value>Error Loading Packages</value>
|
<value>Error Loading Packages</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Success.Module.Install" xml:space="preserve">
|
|
||||||
<value>Module Installed Successfully. You Must <a href={0}>Restart</a> Your Application To Apply These Changes.</value>
|
|
||||||
</data>
|
|
||||||
<data name="Success.Module.Download" xml:space="preserve">
|
<data name="Success.Module.Download" xml:space="preserve">
|
||||||
<value>Module Downloaded Successfully. Click Install To Complete Installation.</value>
|
<value>Module Package Saved Successfully. You Must <a href={0}>Restart</a> Your Application To Complete The Installation.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Error.Module.Download" xml:space="preserve">
|
<data name="Error.Module.Download" xml:space="preserve">
|
||||||
<value>Error Downloading Module</value>
|
<value>Error Downloading Module</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Module.HelpText" xml:space="preserve">
|
<data name="Module.HelpText" xml:space="preserve">
|
||||||
<value>Upload one or more module packages. Once they are uploaded click Install to complete the installation.</value>
|
<value>Upload one or more module packages.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Search.NoResults" xml:space="preserve">
|
<data name="Search.NoResults" xml:space="preserve">
|
||||||
<value>No Modules Match The Criteria Provided Or Package Service Is Disabled</value>
|
<value>No Modules Match The Criteria Provided Or Package Service Is Disabled</value>
|
||||||
|
@ -211,12 +211,18 @@
|
|||||||
<value>No Translations Exist For This Module Or Package Service Is Disabled</value>
|
<value>No Translations Exist For This Module Or Package Service Is Disabled</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Success.Translation.Download" xml:space="preserve">
|
<data name="Success.Translation.Download" xml:space="preserve">
|
||||||
<value>Translation Downloaded Successfully. Click Install To Complete Installation.</value>
|
<value>Translation Package Saved Successfully. You Must <a href={0}>Restart</a> Your Application To Complete The 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>
|
||||||
<data name="Translations.Heading" xml:space="preserve">
|
<data name="Translations.Heading" xml:space="preserve">
|
||||||
<value>Translations</value>
|
<value>Translations</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Message.DuplicateName" xml:space="preserve">
|
||||||
|
<value>A Module With The Name Specified Already Exists</value>
|
||||||
|
</data>
|
||||||
|
<data name="IsEnabled.HelpText" xml:space="preserve">
|
||||||
|
<value>Is module enabled for this site?</value>
|
||||||
|
</data>
|
||||||
|
<data name="IsEnabled.Text" xml:space="preserve">
|
||||||
|
<value>Enabled?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -145,7 +145,7 @@
|
|||||||
<value>Delete Module</value>
|
<value>Delete Module</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="InUse" xml:space="preserve">
|
<data name="InUse" xml:space="preserve">
|
||||||
<value>In Use</value>
|
<value>In Use?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditModule.Text" xml:space="preserve">
|
<data name="EditModule.Text" xml:space="preserve">
|
||||||
<value>Edit</value>
|
<value>Edit</value>
|
||||||
@ -153,4 +153,7 @@
|
|||||||
<data name="Modules" xml:space="preserve">
|
<data name="Modules" xml:space="preserve">
|
||||||
<value>Modules</value>
|
<value>Modules</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Enabled" xml:space="preserve">
|
||||||
|
<value>Enabled?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -150,8 +150,8 @@
|
|||||||
<data name="Container.Select" xml:space="preserve">
|
<data name="Container.Select" xml:space="preserve">
|
||||||
<value>Select Container</value>
|
<value>Select Container</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Error.Page.Initialize" xml:space="preserve">
|
<data name="Error.Page.Load" xml:space="preserve">
|
||||||
<value>Error Initializing Page</value>
|
<value>Error Loading Page</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Error.ChildPage.Load" xml:space="preserve">
|
<data name="Error.ChildPage.Load" xml:space="preserve">
|
||||||
<value>Error Loading Child Pages For Parent</value>
|
<value>Error Loading Child Pages For Parent</value>
|
||||||
@ -228,13 +228,22 @@
|
|||||||
<data name="Appearance.Name" xml:space="preserve">
|
<data name="Appearance.Name" xml:space="preserve">
|
||||||
<value>Appearance</value>
|
<value>Appearance</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Meta.HelpText" xml:space="preserve">
|
<data name="HeadContent.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 content to be included in the page head (ie. meta, link, or script tags)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Meta.Text" xml:space="preserve">
|
<data name="HeadContent.Text" xml:space="preserve">
|
||||||
<value>Meta:</value>
|
<value>Head Content:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Message.Page.Reserved" xml:space="preserve">
|
<data name="Message.Page.Reserved" xml:space="preserve">
|
||||||
<value>The page name {0} is reserved. Please enter a different name for your page.</value>
|
<value>The page name {0} is reserved. Please enter a different name for your page.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="BodyContent.HelpText" xml:space="preserve">
|
||||||
|
<value>Optionally enter content to be included in the page body (ie. script tags)</value>
|
||||||
|
</data>
|
||||||
|
<data name="BodyContent.Text" xml:space="preserve">
|
||||||
|
<value>Body Content:</value>
|
||||||
|
</data>
|
||||||
|
<data name="PageContent.Heading" xml:space="preserve">
|
||||||
|
<value>Page Content</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -264,13 +264,22 @@
|
|||||||
<data name="Clickable.Text" xml:space="preserve">
|
<data name="Clickable.Text" xml:space="preserve">
|
||||||
<value>Clickable?</value>
|
<value>Clickable?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Meta.HelpText" xml:space="preserve">
|
<data name="HeadContent.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 content to be included in the page head (ie. meta, link, or script tags)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Meta.Text" xml:space="preserve">
|
<data name="HeadContent.Text" xml:space="preserve">
|
||||||
<value>Meta:</value>
|
<value>Head Content:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Message.Page.Reserved" xml:space="preserve">
|
<data name="Message.Page.Reserved" xml:space="preserve">
|
||||||
<value>The page name {0} is reserved. Please enter a different name for your page.</value>
|
<value>The page name {0} is reserved. Please enter a different name for your page.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="BodyContent.HelpText" xml:space="preserve">
|
||||||
|
<value>Optionally enter content to be included in the page body (ie. script tags)</value>
|
||||||
|
</data>
|
||||||
|
<data name="BodyContent.Text" xml:space="preserve">
|
||||||
|
<value>Body Content:</value>
|
||||||
|
</data>
|
||||||
|
<data name="PageContent.Heading" xml:space="preserve">
|
||||||
|
<value>Page Content</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -183,4 +183,10 @@
|
|||||||
<data name="Private.Text" xml:space="preserve">
|
<data name="Private.Text" xml:space="preserve">
|
||||||
<value>Private? </value>
|
<value>Private? </value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Validation.HelpText" xml:space="preserve">
|
||||||
|
<value>Optionally provide a regular expression (RegExp) for validating the value entered</value>
|
||||||
|
</data>
|
||||||
|
<data name="Validation.Text" xml:space="preserve">
|
||||||
|
<value>Validation:</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,7 +166,7 @@
|
|||||||
<value>Email:</value>
|
<value>Email:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Password.HelpText" xml:space="preserve">
|
<data name="Password.HelpText" xml:space="preserve">
|
||||||
<value>Please choose a sufficiently secure password and enter it here</value>
|
<value>Please enter a sufficiently secure password which meets the password complexity requirements</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Password.Text" xml:space="preserve">
|
<data name="Password.Text" xml:space="preserve">
|
||||||
<value>Password:</value>
|
<value>Password:</value>
|
||||||
@ -177,4 +177,19 @@
|
|||||||
<data name="Username.Text" xml:space="preserve">
|
<data name="Username.Text" xml:space="preserve">
|
||||||
<value>Username:</value>
|
<value>Username:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Password.ValidationCriteria" xml:space="preserve">
|
||||||
|
<value>Passwords Must Have A Minimum Length Of {0} Characters, Including At Least {1} Unique Character(s), {2}{3}{4}{5} To Satisfy Password Compexity Requirements For This Site.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Password.DigitRequirement" xml:space="preserve">
|
||||||
|
<value>At Least One Digit</value>
|
||||||
|
</data>
|
||||||
|
<data name="Password.LowercaseRequirement" xml:space="preserve">
|
||||||
|
<value>At Least One Lowercase Letter</value>
|
||||||
|
</data>
|
||||||
|
<data name="Password.PunctuationRequirement" xml:space="preserve">
|
||||||
|
<value>At Least One Punctuation Mark</value>
|
||||||
|
</data>
|
||||||
|
<data name="Password.UppercaseRequirement" xml:space="preserve">
|
||||||
|
<value>At Least One Uppercase Letter</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -175,7 +175,7 @@
|
|||||||
<value>Specify a logo for the site</value>
|
<value>Specify a logo for the site</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FavoriteIcon.HelpText" xml:space="preserve">
|
<data name="FavoriteIcon.HelpText" xml:space="preserve">
|
||||||
<value>Specify a Favicon</value>
|
<value>Specify a Favicon. The format for the image must be 16×16, 32×32, 48×48, or 64×64 pixels in size, and 8-bit, 24-bit, or 32-bit in color depth. The format of the image must be ICO, PNG, or GIF.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DefaultTheme.HelpText" xml:space="preserve">
|
<data name="DefaultTheme.HelpText" xml:space="preserve">
|
||||||
<value>Select the sites default theme</value>
|
<value>Select the sites default theme</value>
|
||||||
@ -351,4 +351,34 @@
|
|||||||
<data name="SiteMap.Text" xml:space="preserve">
|
<data name="SiteMap.Text" xml:space="preserve">
|
||||||
<value>Site Map:</value>
|
<value>Site Map:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Appearance.Heading" xml:space="preserve">
|
||||||
|
<value>Appearance</value>
|
||||||
|
</data>
|
||||||
|
<data name="HeadContent.HelpText" xml:space="preserve">
|
||||||
|
<value>Optionally enter content to be included in the page head (ie. meta, link, or script tags)</value>
|
||||||
|
</data>
|
||||||
|
<data name="HeadContent.Text" xml:space="preserve">
|
||||||
|
<value>Head Content:</value>
|
||||||
|
</data>
|
||||||
|
<data name="BodyContent.HelpText" xml:space="preserve">
|
||||||
|
<value>Optionally enter content to be included in the page body (ie. script tags)</value>
|
||||||
|
</data>
|
||||||
|
<data name="BodyContent.Text" xml:space="preserve">
|
||||||
|
<value>Body Content:</value>
|
||||||
|
</data>
|
||||||
|
<data name="PageContent.Heading" xml:space="preserve">
|
||||||
|
<value>Page Content</value>
|
||||||
|
</data>
|
||||||
|
<data name="SMTPEnabled.HelpText" xml:space="preserve">
|
||||||
|
<value>Specify if SMTP is enabled for this site</value>
|
||||||
|
</data>
|
||||||
|
<data name="SMTPEnabled.Text" xml:space="preserve">
|
||||||
|
<value>Enabled?</value>
|
||||||
|
</data>
|
||||||
|
<data name="Version.HelpText" xml:space="preserve">
|
||||||
|
<value>The site version (for site content migrations)</value>
|
||||||
|
</data>
|
||||||
|
<data name="Version.Text" xml:space="preserve">
|
||||||
|
<value>Version:</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -123,17 +123,14 @@
|
|||||||
<data name="Theme.Text" xml:space="preserve">
|
<data name="Theme.Text" xml:space="preserve">
|
||||||
<value>Theme: </value>
|
<value>Theme: </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Success.Theme.Install" xml:space="preserve">
|
|
||||||
<value>Theme Installed Successfully. You Must <a href={0}>Restart</a> Your Application To Apply These Changes.</value>
|
|
||||||
</data>
|
|
||||||
<data name="Success.Theme.Download" xml:space="preserve">
|
<data name="Success.Theme.Download" xml:space="preserve">
|
||||||
<value>Theme Downloaded Successfully. Click Install To Complete Installation.</value>
|
<value>Theme Package Saved Successfully. You Must <a href={0}>Restart</a> Your Application To Complete The Installation.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Error.Theme.Download" xml:space="preserve">
|
<data name="Error.Theme.Download" xml:space="preserve">
|
||||||
<value>Error Downloading Theme</value>
|
<value>Error Downloading Theme</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Theme.HelpText" xml:space="preserve">
|
<data name="Theme.HelpText" xml:space="preserve">
|
||||||
<value>Upload one or more theme packages. Once they are uploaded click Install to complete the installation.</value>
|
<value>Upload one or more theme packages.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Search.NoResults" xml:space="preserve">
|
<data name="Search.NoResults" xml:space="preserve">
|
||||||
<value>No Themes Match The Criteria Provided Or Package Service Is Disabled</value>
|
<value>No Themes Match The Criteria Provided Or Package Service Is Disabled</value>
|
||||||
|
@ -168,4 +168,13 @@
|
|||||||
<data name="PackageName.Text" xml:space="preserve">
|
<data name="PackageName.Text" xml:space="preserve">
|
||||||
<value>Package Name:</value>
|
<value>Package Name:</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Information.Heading" xml:space="preserve">
|
||||||
|
<value>Information</value>
|
||||||
|
</data>
|
||||||
|
<data name="IsEnabled.HelpText" xml:space="preserve">
|
||||||
|
<value>Is theme enabled for this site?</value>
|
||||||
|
</data>
|
||||||
|
<data name="IsEnabled.Text" xml:space="preserve">
|
||||||
|
<value>Enabled?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -144,4 +144,7 @@
|
|||||||
<data name="ViewTheme.Text" xml:space="preserve">
|
<data name="ViewTheme.Text" xml:space="preserve">
|
||||||
<value>View</value>
|
<value>View</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Enabled" xml:space="preserve">
|
||||||
|
<value>Enabled?</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -340,6 +340,48 @@
|
|||||||
<value>Visitor Management</value>
|
<value>Visitor Management</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Oqtane.Marketplace" xml:space="preserve">
|
<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>
|
<value>Please note that third party extensions are 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>
|
||||||
|
<data name="Home" xml:space="preserve">
|
||||||
|
<value>Home</value>
|
||||||
|
</data>
|
||||||
|
<data name="Close" xml:space="preserve">
|
||||||
|
<value>Close</value>
|
||||||
|
</data>
|
||||||
|
<data name="OK" xml:space="preserve">
|
||||||
|
<value>OK</value>
|
||||||
|
</data>
|
||||||
|
<data name="Apply" xml:space="preserve">
|
||||||
|
<value>Apply</value>
|
||||||
|
</data>
|
||||||
|
<data name="Select" xml:space="preserve">
|
||||||
|
<value>Select</value>
|
||||||
|
</data>
|
||||||
|
<data name="Next" xml:space="preserve">
|
||||||
|
<value>Next</value>
|
||||||
|
</data>
|
||||||
|
<data name="Previous" xml:space="preserve">
|
||||||
|
<value>Previous</value>
|
||||||
|
</data>
|
||||||
|
<data name="Submit" xml:space="preserve">
|
||||||
|
<value>Submit</value>
|
||||||
|
</data>
|
||||||
|
<data name="Refresh" xml:space="preserve">
|
||||||
|
<value>Refresh</value>
|
||||||
|
</data>
|
||||||
|
<data name="Back" xml:space="preserve">
|
||||||
|
<value>Back</value>
|
||||||
|
</data>
|
||||||
|
<data name="Return" xml:space="preserve">
|
||||||
|
<value>Return</value>
|
||||||
|
</data>
|
||||||
|
<data name="New" xml:space="preserve">
|
||||||
|
<value>New</value>
|
||||||
|
</data>
|
||||||
|
<data name="View" xml:space="preserve">
|
||||||
|
<value>View</value>
|
||||||
|
</data>
|
||||||
|
<data name="Confirm" xml:space="preserve">
|
||||||
|
<value>Confirm</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
@ -29,9 +30,9 @@ namespace Oqtane.Services
|
|||||||
|
|
||||||
public async Task<List<File>> GetFilesAsync(int siteId, string folderPath)
|
public async Task<List<File>> GetFilesAsync(int siteId, string folderPath)
|
||||||
{
|
{
|
||||||
if (!(folderPath.EndsWith(System.IO.Path.DirectorySeparatorChar) || folderPath.EndsWith(System.IO.Path.AltDirectorySeparatorChar)))
|
if (!(string.IsNullOrEmpty(folderPath) || folderPath.EndsWith(System.IO.Path.DirectorySeparatorChar) || folderPath.EndsWith(System.IO.Path.AltDirectorySeparatorChar)))
|
||||||
{
|
{
|
||||||
folderPath = Utilities.PathCombine(folderPath, System.IO.Path.DirectorySeparatorChar.ToString());
|
folderPath = Utilities.UrlCombine(folderPath) + "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
var path = WebUtility.UrlEncode(folderPath);
|
var path = WebUtility.UrlEncode(folderPath);
|
||||||
|
@ -33,13 +33,6 @@ namespace Oqtane.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task UpdateModuleDefinitionAsync(ModuleDefinition moduleDefinition);
|
Task UpdateModuleDefinitionAsync(ModuleDefinition moduleDefinition);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Installs all module definitions located in //TODO: 2dm where?
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task InstallModuleDefinitionsAsync();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deletes a module definition
|
/// Deletes a module definition
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -23,14 +23,6 @@ namespace Oqtane.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<Page> GetPageAsync(int pageId);
|
Task<Page> GetPageAsync(int pageId);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns a specific page personalized for the given user
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pageId"></param>
|
|
||||||
/// <param name="userId"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
Task<Page> GetPageAsync(int pageId, int userId);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a specific page by its defined path
|
/// Returns a specific page by its defined path
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -16,6 +16,22 @@ namespace Oqtane.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<List<Theme>> GetThemesAsync();
|
Task<List<Theme>> GetThemesAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a specific thenme
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="themeId"></param>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<Theme> GetThemeAsync(int themeId, int siteId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a theme <see cref="ThemeControl"/>s containing a specific theme control type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="themes"></param>
|
||||||
|
/// <param name="themeControlType"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Theme GetTheme(List<Theme> themes, string themeControlType);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a list of <see cref="ThemeControl"/>s from the given themes
|
/// Returns a list of <see cref="ThemeControl"/>s from the given themes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -24,26 +40,27 @@ namespace Oqtane.Services
|
|||||||
List<ThemeControl> GetThemeControls(List<Theme> themes);
|
List<ThemeControl> GetThemeControls(List<Theme> themes);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a list of layouts (<see cref="ThemeControl"/>) from the given themes with a matching theme name
|
/// Returns a list of <see cref="ThemeControl"/>s for a theme containing a specific theme control type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="themes"></param>
|
/// <param name="themes"></param>
|
||||||
/// <param name="themeName"></param>
|
/// <param name="themeControlType"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
List<ThemeControl> GetLayoutControls(List<Theme> themes, string themeName);
|
List<ThemeControl> GetThemeControls(List<Theme> themes, string themeControlType);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a list of containers (<see cref="ThemeControl"/>) from the given themes with a matching theme name
|
/// Returns a list of containers (<see cref="ThemeControl"/>) for a theme containing a specific theme control type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="themes"></param>
|
/// <param name="themes"></param>
|
||||||
/// <param name="themeName"></param>
|
/// <param name="themeControlType"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
List<ThemeControl> GetContainerControls(List<Theme> themes, string themeName);
|
List<ThemeControl> GetContainerControls(List<Theme> themes, string themeControlType);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Installs all themes located in //TODO: 2dm where?
|
/// Updates a existing theem
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="theme"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task InstallThemesAsync();
|
Task UpdateThemeAsync(Theme theme);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deletes a theme
|
/// Deletes a theme
|
||||||
@ -64,5 +81,14 @@ namespace Oqtane.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<List<Template>> GetThemeTemplatesAsync();
|
Task<List<Template>> GetThemeTemplatesAsync();
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a list of layouts (<see cref="ThemeControl"/>) from the given themes with a matching theme name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="themes"></param>
|
||||||
|
/// <param name="themeName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<ThemeControl> GetLayoutControls(List<Theme> themes, string themeName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,11 +34,6 @@ namespace Oqtane.Services
|
|||||||
await PutJsonAsync($"{Apiurl}/{moduleDefinition.ModuleDefinitionId}", moduleDefinition);
|
await PutJsonAsync($"{Apiurl}/{moduleDefinition.ModuleDefinitionId}", moduleDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InstallModuleDefinitionsAsync()
|
|
||||||
{
|
|
||||||
await GetJsonAsync<List<string>>($"{Apiurl}/install");
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteModuleDefinitionAsync(int moduleDefinitionId, int siteId)
|
public async Task DeleteModuleDefinitionAsync(int moduleDefinitionId, int siteId)
|
||||||
{
|
{
|
||||||
await DeleteAsync($"{Apiurl}/{moduleDefinitionId}?siteid={siteId}");
|
await DeleteAsync($"{Apiurl}/{moduleDefinitionId}?siteid={siteId}");
|
||||||
|
@ -18,11 +18,7 @@ namespace Oqtane.Services
|
|||||||
|
|
||||||
public async Task<List<Module>> GetModulesAsync(int siteId)
|
public async Task<List<Module>> GetModulesAsync(int siteId)
|
||||||
{
|
{
|
||||||
List<Module> modules = await GetJsonAsync<List<Module>>($"{Apiurl}?siteid={siteId}");
|
return await GetJsonAsync<List<Module>>($"{Apiurl}?siteid={siteId}");
|
||||||
modules = modules
|
|
||||||
.OrderBy(item => item.Order)
|
|
||||||
.ToList();
|
|
||||||
return modules;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Module> GetModuleAsync(int moduleId)
|
public async Task<Module> GetModuleAsync(int moduleId)
|
||||||
|
@ -25,11 +25,6 @@ namespace Oqtane.Services
|
|||||||
return await GetJsonAsync<Page>($"{Apiurl}/{pageId}");
|
return await GetJsonAsync<Page>($"{Apiurl}/{pageId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Page> GetPageAsync(int pageId, int userId)
|
|
||||||
{
|
|
||||||
return await GetJsonAsync<Page>($"{Apiurl}/{pageId}?userid={userId}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Page> GetPageAsync(string path, int siteId)
|
public async Task<Page> GetPageAsync(string path, int siteId)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -5,6 +5,7 @@ using System.Threading.Tasks;
|
|||||||
using Oqtane.Documentation;
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
|
using Oqtane.UI;
|
||||||
|
|
||||||
namespace Oqtane.Services
|
namespace Oqtane.Services
|
||||||
{
|
{
|
||||||
@ -20,27 +21,35 @@ namespace Oqtane.Services
|
|||||||
List<Theme> themes = await GetJsonAsync<List<Theme>>(ApiUrl);
|
List<Theme> themes = await GetJsonAsync<List<Theme>>(ApiUrl);
|
||||||
return themes.OrderBy(item => item.Name).ToList();
|
return themes.OrderBy(item => item.Name).ToList();
|
||||||
}
|
}
|
||||||
|
public async Task<Theme> GetThemeAsync(int themeId, int siteId)
|
||||||
|
{
|
||||||
|
return await GetJsonAsync<Theme>($"{ApiUrl}/{themeId}?siteid={siteId}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Theme GetTheme(List<Theme> themes, string themeControlType)
|
||||||
|
{
|
||||||
|
return themes.FirstOrDefault(item => item.Themes.Any(item => item.TypeName == themeControlType));
|
||||||
|
}
|
||||||
|
|
||||||
public List<ThemeControl> GetThemeControls(List<Theme> themes)
|
public List<ThemeControl> GetThemeControls(List<Theme> themes)
|
||||||
{
|
{
|
||||||
return themes.SelectMany(item => item.Themes).ToList();
|
return themes.SelectMany(item => item.Themes).OrderBy(item => item.Name).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
//[Obsolete("This method is deprecated.", false)]
|
public List<ThemeControl> GetThemeControls(List<Theme> themes, string themeControlType)
|
||||||
public List<ThemeControl> GetLayoutControls(List<Theme> themes, string themeName)
|
|
||||||
{
|
{
|
||||||
return null;
|
return GetTheme(themes, themeControlType)?.Themes.OrderBy(item => item.Name).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ThemeControl> GetContainerControls(List<Theme> themes, string themeName)
|
|
||||||
|
public List<ThemeControl> GetContainerControls(List<Theme> themes, string themeControlType)
|
||||||
{
|
{
|
||||||
return themes.Where(item => Utilities.GetTypeName(themeName).StartsWith(Utilities.GetTypeName(item.ThemeName)))
|
return GetTheme(themes, themeControlType)?.Containers.OrderBy(item => item.Name).ToList();
|
||||||
.SelectMany(item => item.Containers).ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InstallThemesAsync()
|
public async Task UpdateThemeAsync(Theme theme)
|
||||||
{
|
{
|
||||||
await GetJsonAsync<List<string>>($"{ApiUrl}/install");
|
await PutJsonAsync($"{ApiUrl}/{theme.ThemeId}", theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteThemeAsync(string themeName)
|
public async Task DeleteThemeAsync(string themeName)
|
||||||
@ -58,5 +67,11 @@ namespace Oqtane.Services
|
|||||||
List<Template> templates = await GetJsonAsync<List<Template>>($"{ApiUrl}/templates");
|
List<Template> templates = await GetJsonAsync<List<Template>>($"{ApiUrl}/templates");
|
||||||
return templates;
|
return templates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//[Obsolete("This method is deprecated.", false)]
|
||||||
|
public List<ThemeControl> GetLayoutControls(List<Theme> themes, string themeName)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.2.0/css/bootstrap.min.css", Integrity = "sha512-XWTTruHZEYJsxV3W/lSXG1n3Q39YIWOstqvmFsdNEEQfHoZ6vm6E9GK2OrF6DSJSpIbRbi+Nn0WDPID9O7xB2Q==", CrossOrigin = "anonymous" },
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css", Integrity = "sha512-t4GWSVZO1eC8BM339Xd7Uphw5s17a86tIZIj8qRxhnKub6WoyhnrxeCIMeAqBPgdZGlCcG2PrZjMc+Wr78+5Xg==", 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.2.0/js/bootstrap.bundle.min.js", Integrity = "sha512-9GacT4119eY3AcosfWtHMsT5JyZudrexyEVzTBWV3viP/YfB9e2pEy3N7WXL3SV6ASXpTU0vzzSxsbfsuUH4sQ==", CrossOrigin = "anonymous" }
|
new Resource { ResourceType = ResourceType.Script, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.bundle.min.js", Integrity = "sha512-VK2zcvntEufaimc+efOYi622VN5ZacdnufnmX7zIhCPmjhKnOi9ZDMtg1/ug5l183f19gG1/cBstPO4D8N/Img==", CrossOrigin = "anonymous" }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -2,12 +2,9 @@
|
|||||||
@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()">
|
@((MarkupString)title)
|
||||||
@((MarkupString)title)
|
|
||||||
</a>
|
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
@using System.Net
|
||||||
@namespace Oqtane.Themes.Controls
|
@namespace Oqtane.Themes.Controls
|
||||||
@inherits ThemeControlBase
|
@inherits ThemeControlBase
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@ -55,7 +56,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<hr class="app-rule" />
|
<hr class="app-rule" />
|
||||||
}
|
}
|
||||||
@if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
@if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.PermissionList))
|
||||||
{
|
{
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-center">
|
<div class="col text-center">
|
||||||
@ -64,7 +65,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row d-flex mb-2">
|
<div class="row d-flex mb-2">
|
||||||
<div class="col d-flex justify-content-between">
|
<div class="col d-flex justify-content-between">
|
||||||
<button type="button" class="btn btn-secondary col me-1" data-bs-dismiss="offcanvas" @onclick=@(async () => Navigate("Add"))>@SharedLocalizer["Add"]</button>
|
@if (PageState.Page.UserId == null)
|
||||||
|
{
|
||||||
|
<button type="button" class="btn btn-secondary col me-1" data-bs-dismiss="offcanvas" @onclick=@(async () => Navigate("Add"))>@SharedLocalizer["Add"]</button>
|
||||||
|
}
|
||||||
<button type="button" class="btn btn-secondary col" data-bs-dismiss="offcanvas" @onclick=@(async () => Navigate("Edit"))>@SharedLocalizer["Edit"]</button>
|
<button type="button" class="btn btn-secondary col" data-bs-dismiss="offcanvas" @onclick=@(async () => Navigate("Edit"))>@SharedLocalizer["Edit"]</button>
|
||||||
<button type="button" class="btn btn-danger col ms-1" @onclick="ConfirmDelete">@SharedLocalizer["Delete"]</button>
|
<button type="button" class="btn btn-danger col ms-1" @onclick="ConfirmDelete">@SharedLocalizer["Delete"]</button>
|
||||||
</div>
|
</div>
|
||||||
@ -144,7 +148,7 @@
|
|||||||
}
|
}
|
||||||
@foreach (var moduledefinition in _moduleDefinitions)
|
@foreach (var moduledefinition in _moduleDefinitions)
|
||||||
{
|
{
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Utilize, moduledefinition.PermissionList))
|
if (moduledefinition.IsEnabled && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Utilize, moduledefinition.PermissionList))
|
||||||
{
|
{
|
||||||
if (moduledefinition.Runtimes == "" || moduledefinition.Runtimes.Contains(PageState.Runtime.ToString()))
|
if (moduledefinition.Runtimes == "" || moduledefinition.Runtimes.Contains(PageState.Runtime.ToString()))
|
||||||
{
|
{
|
||||||
@ -223,270 +227,274 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@code{
|
@code{
|
||||||
private bool _canViewAdminDashboard = false;
|
private bool _canViewAdminDashboard = false;
|
||||||
private bool _showEditMode = false;
|
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;
|
||||||
private List<ModuleDefinition> _moduleDefinitions;
|
private List<ModuleDefinition> _moduleDefinitions;
|
||||||
private List<Page> _pages = new List<Page>();
|
private List<Page> _pages = new List<Page>();
|
||||||
private List<Module> _modules = new List<Module>();
|
private List<Module> _modules = new List<Module>();
|
||||||
private List<ThemeControl> _containers = new List<ThemeControl>();
|
private List<ThemeControl> _containers = new List<ThemeControl>();
|
||||||
private string _category = "Common";
|
private string _category = "Common";
|
||||||
|
|
||||||
protected string PageId { get; private set; } = "-";
|
protected string PageId { get; private set; } = "-";
|
||||||
protected string ModuleId { get; private set; } = "-";
|
protected string ModuleId { get; private set; } = "-";
|
||||||
protected string ModuleType { get; private set; } = "new";
|
protected string ModuleType { get; private set; } = "new";
|
||||||
protected string ModuleDefinitionName { get; private set; } = "-";
|
protected string ModuleDefinitionName { get; private set; } = "-";
|
||||||
|
|
||||||
protected string Category
|
protected string Category
|
||||||
{
|
{
|
||||||
get => _category;
|
get => _category;
|
||||||
private set
|
private set
|
||||||
{
|
{
|
||||||
if (_category != value)
|
if (_category != value)
|
||||||
{
|
{
|
||||||
_category = value;
|
_category = value;
|
||||||
_moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(Category)).ToList();
|
_moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(Category)).ToList();
|
||||||
ModuleDefinitionName = "-";
|
ModuleDefinitionName = "-";
|
||||||
Message = "";
|
Message = "";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
_ = UpdateSettingsAsync();
|
_ = UpdateSettingsAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string Pane
|
protected string Pane
|
||||||
{
|
{
|
||||||
get => _pane;
|
get => _pane;
|
||||||
private set
|
private set
|
||||||
{
|
{
|
||||||
if (_pane != value)
|
if (_pane != value)
|
||||||
{
|
{
|
||||||
_pane = value;
|
_pane = value;
|
||||||
_ = UpdateSettingsAsync();
|
_ = UpdateSettingsAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string Title { get; private set; } = "";
|
protected string Title { get; private set; } = "";
|
||||||
protected string ContainerType { get; private set; } = "";
|
protected string ContainerType { get; private set; } = "";
|
||||||
protected string Visibility { get; private set; } = "view";
|
protected string Visibility { get; private set; } = "view";
|
||||||
protected string Message { get; private set; } = "";
|
protected string Message { get; private set; } = "";
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string ButtonClass { get; set; } = "btn-outline-secondary";
|
public string ButtonClass { get; set; } = "btn-outline-secondary";
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string ContainerClass { get; set; } = "offcanvas offcanvas-end";
|
public string ContainerClass { get; set; } = "offcanvas offcanvas-end";
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string HeaderClass { get; set; } = "offcanvas-header";
|
public string HeaderClass { get; set; } = "offcanvas-header";
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string BodyClass { get; set; } = "offcanvas-body overflow-auto";
|
public string BodyClass { get; set; } = "offcanvas-body overflow-auto";
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public bool ShowLanguageSwitcher { get; set; } = true;
|
public bool ShowLanguageSwitcher { get; set; } = true;
|
||||||
|
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
_canViewAdminDashboard = CanViewAdminDashboard();
|
_canViewAdminDashboard = CanViewAdminDashboard();
|
||||||
_showEditMode = false;
|
_showEditMode = false;
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.PermissionList))
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.PermissionList))
|
||||||
{
|
{
|
||||||
_showEditMode = true;
|
_showEditMode = true;
|
||||||
_pages?.Clear();
|
_pages?.Clear();
|
||||||
|
|
||||||
foreach (Page p in PageState.Pages)
|
foreach (Page p in PageState.Pages)
|
||||||
{
|
{
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.PermissionList))
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, p.PermissionList))
|
||||||
{
|
{
|
||||||
_pages.Add(p);
|
_pages.Add(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await LoadSettingsAsync();
|
await LoadSettingsAsync();
|
||||||
|
|
||||||
var themes = await ThemeService.GetThemesAsync();
|
var themes = await ThemeService.GetThemesAsync();
|
||||||
_containers = ThemeService.GetContainerControls(themes, PageState.Page.ThemeType);
|
_containers = ThemeService.GetContainerControls(themes, PageState.Page.ThemeType);
|
||||||
ContainerType = PageState.Site.DefaultContainerType;
|
ContainerType = PageState.Site.DefaultContainerType;
|
||||||
_allModuleDefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
|
_allModuleDefinitions = await ModuleDefinitionService.GetModuleDefinitionsAsync(PageState.Site.SiteId);
|
||||||
_moduleDefinitions = _allModuleDefinitions.Where(item => item.Categories.Contains(Category)).ToList();
|
_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
|
else
|
||||||
{
|
{
|
||||||
foreach (var module in PageState.Modules.Where(item => item.PageId == PageState.Page.PageId))
|
foreach (var module in PageState.Modules.Where(item => item.PageId == PageState.Page.PageId))
|
||||||
{
|
{
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, module.PermissionList))
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, module.PermissionList))
|
||||||
{
|
{
|
||||||
_showEditMode = true;
|
_showEditMode = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CanViewAdminDashboard()
|
private bool CanViewAdminDashboard()
|
||||||
{
|
{
|
||||||
var admin = PageState.Pages.FirstOrDefault(item => item.Path == "admin");
|
var admin = PageState.Pages.FirstOrDefault(item => item.Path == "admin");
|
||||||
if (admin != null)
|
if (admin != null)
|
||||||
{
|
{
|
||||||
foreach (var page in PageState.Pages.Where(item => item.ParentId == admin?.PageId))
|
foreach (var page in PageState.Pages.Where(item => item.ParentId == admin?.PageId))
|
||||||
{
|
{
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, page.PermissionList))
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, page.PermissionList))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CategoryChanged(ChangeEventArgs e)
|
private void CategoryChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
Category = (string)e.Value;
|
Category = (string)e.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ModuleChanged(ChangeEventArgs e)
|
private void ModuleChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
ModuleDefinitionName = (string)e.Value;
|
ModuleDefinitionName = (string)e.Value;
|
||||||
if (ModuleDefinitionName != "-")
|
if (ModuleDefinitionName != "-")
|
||||||
{
|
{
|
||||||
var moduleDefinition = _moduleDefinitions.FirstOrDefault(item => item.ModuleDefinitionName == ModuleDefinitionName);
|
var moduleDefinition = _moduleDefinitions.FirstOrDefault(item => item.ModuleDefinitionName == ModuleDefinitionName);
|
||||||
Message = "<div class=\"alert alert-info mt-2 text-center\" role=\"alert\">" + moduleDefinition.Description + "</div>";
|
Message = "<div class=\"alert alert-info mt-2 text-center\" role=\"alert\">" + moduleDefinition.Description + "</div>";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Message = "";
|
Message = "";
|
||||||
}
|
}
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PageChanged(ChangeEventArgs e)
|
private void PageChanged(ChangeEventArgs e)
|
||||||
{
|
{
|
||||||
PageId = (string)e.Value;
|
PageId = (string)e.Value;
|
||||||
if (PageId != "-")
|
if (PageId != "-")
|
||||||
{
|
{
|
||||||
_modules = PageState.Modules
|
_modules = PageState.Modules
|
||||||
.Where(module => module.PageId == int.Parse(PageId) &&
|
.Where(module => module.PageId == int.Parse(PageId) &&
|
||||||
UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.PermissionList))
|
UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.PermissionList))
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
ModuleId = "-";
|
ModuleId = "-";
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task AddModule()
|
private async Task AddModule()
|
||||||
{
|
{
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.PermissionList))
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.PermissionList))
|
||||||
{
|
{
|
||||||
if ((ModuleType == "new" && ModuleDefinitionName != "-") || (ModuleType != "new" && ModuleId != "-"))
|
if ((ModuleType == "new" && ModuleDefinitionName != "-") || (ModuleType != "new" && ModuleId != "-"))
|
||||||
{
|
{
|
||||||
if (ModuleType == "new")
|
if (ModuleType == "new")
|
||||||
{
|
{
|
||||||
Module module = new Module();
|
Module module = new Module();
|
||||||
module.SiteId = PageState.Site.SiteId;
|
module.SiteId = PageState.Site.SiteId;
|
||||||
module.PageId = PageState.Page.PageId;
|
module.PageId = PageState.Page.PageId;
|
||||||
module.ModuleDefinitionName = ModuleDefinitionName;
|
module.ModuleDefinitionName = ModuleDefinitionName;
|
||||||
module.AllPages = false;
|
module.AllPages = false;
|
||||||
|
|
||||||
var permissions = new List<Permission>();
|
var permissions = new List<Permission>();
|
||||||
if (Visibility == "view")
|
if (Visibility == "view")
|
||||||
{
|
{
|
||||||
// set module view permissions to page view permissions
|
// set module view permissions to page view permissions
|
||||||
permissions = SetPermissions(permissions, module.SiteId, PermissionNames.View, PermissionNames.View);
|
permissions = SetPermissions(permissions, module.SiteId, PermissionNames.View, PermissionNames.View);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// set module view permissions to page edit permissions
|
// set module view permissions to page edit permissions
|
||||||
permissions = SetPermissions(permissions, module.SiteId, PermissionNames.View, PermissionNames.Edit);
|
permissions = SetPermissions(permissions, module.SiteId, PermissionNames.View, PermissionNames.Edit);
|
||||||
}
|
}
|
||||||
// set module edit permissions to page edit permissions
|
// set module edit permissions to page edit permissions
|
||||||
permissions = SetPermissions(permissions, module.SiteId, PermissionNames.Edit, PermissionNames.Edit);
|
permissions = SetPermissions(permissions, module.SiteId, PermissionNames.Edit, PermissionNames.Edit);
|
||||||
module.PermissionList = permissions;
|
module.PermissionList = permissions;
|
||||||
|
|
||||||
module = await ModuleService.AddModuleAsync(module);
|
module = await ModuleService.AddModuleAsync(module);
|
||||||
ModuleId = module.ModuleId.ToString();
|
ModuleId = module.ModuleId.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
var pageModule = new PageModule
|
var pageModule = new PageModule
|
||||||
{
|
{
|
||||||
PageId = PageState.Page.PageId,
|
PageId = PageState.Page.PageId,
|
||||||
ModuleId = int.Parse(ModuleId),
|
ModuleId = int.Parse(ModuleId),
|
||||||
Title = Title
|
Title = Title
|
||||||
};
|
};
|
||||||
if (pageModule.Title == "")
|
if (pageModule.Title == "")
|
||||||
{
|
{
|
||||||
if (ModuleType == "new")
|
if (ModuleType == "new")
|
||||||
{
|
{
|
||||||
pageModule.Title = _moduleDefinitions.FirstOrDefault(item => item.ModuleDefinitionName == ModuleDefinitionName)?.Name;
|
pageModule.Title = _moduleDefinitions.FirstOrDefault(item => item.ModuleDefinitionName == ModuleDefinitionName)?.Name;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pageModule.Title = _modules.FirstOrDefault(item => item.ModuleId == int.Parse(ModuleId))?.Title;
|
pageModule.Title = _modules.FirstOrDefault(item => item.ModuleId == int.Parse(ModuleId))?.Title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pageModule.Pane = Pane;
|
pageModule.Pane = Pane;
|
||||||
pageModule.Order = int.MaxValue;
|
pageModule.Order = int.MaxValue;
|
||||||
pageModule.ContainerType = ContainerType;
|
pageModule.ContainerType = ContainerType;
|
||||||
|
|
||||||
if (pageModule.ContainerType == PageState.Site.DefaultContainerType)
|
if (pageModule.ContainerType == PageState.Site.DefaultContainerType)
|
||||||
{
|
{
|
||||||
pageModule.ContainerType = "";
|
pageModule.ContainerType = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
await PageModuleService.AddPageModuleAsync(pageModule);
|
await PageModuleService.AddPageModuleAsync(pageModule);
|
||||||
await PageModuleService.UpdatePageModuleOrderAsync(pageModule.PageId, pageModule.Pane);
|
await PageModuleService.UpdatePageModuleOrderAsync(pageModule.PageId, pageModule.Pane);
|
||||||
|
|
||||||
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 List<Permission> SetPermissions(List<Permission> permissions, int siteId, string modulePermission, string pagePermission)
|
private List<Permission> SetPermissions(List<Permission> permissions, int siteId, string modulePermission, string pagePermission)
|
||||||
{
|
{
|
||||||
foreach (var permission in PageState.Page.PermissionList.Where(item => item.PermissionName == pagePermission))
|
foreach (var permission in PageState.Page.PermissionList.Where(item => item.PermissionName == pagePermission))
|
||||||
{
|
{
|
||||||
permissions.Add(new Permission { SiteId = siteId, EntityName = EntityNames.Module, PermissionName = modulePermission, RoleId = permission.RoleId, UserId = permission.UserId, IsAuthorized = permission.IsAuthorized });
|
permissions.Add(new Permission { SiteId = siteId, EntityName = EntityNames.Module, PermissionName = modulePermission, RoleId = permission.RoleId, UserId = permission.UserId, IsAuthorized = permission.IsAuthorized });
|
||||||
}
|
}
|
||||||
return permissions;
|
return permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ToggleEditMode(bool EditMode)
|
private async Task ToggleEditMode(bool EditMode)
|
||||||
{
|
{
|
||||||
if (_showEditMode)
|
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) ? "true" : "false")));
|
// preserve other querystring parameters
|
||||||
|
if (PageState.QueryString.ContainsKey("edit")) PageState.QueryString.Remove("edit");
|
||||||
|
PageState.QueryString.Add("edit", PageState.EditMode.ToString().ToLower());
|
||||||
|
var url = PageState.Route.AbsolutePath + Utilities.CreateQueryString(PageState.QueryString);
|
||||||
|
NavigationManager.NavigateTo(url);
|
||||||
}
|
}
|
||||||
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);
|
var page = await PageService.AddPageAsync(PageState.Page.PageId, PageState.User.UserId);
|
||||||
PageState.EditMode = true;
|
PageState.EditMode = true;
|
||||||
NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, "edit=" + ((PageState.EditMode) ? "true" : "false")));
|
NavigationManager.NavigateTo(NavigateUrl(page.Path, "edit=" + ((PageState.EditMode) ? "true" : "false")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -501,7 +509,7 @@
|
|||||||
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("admin", module.ModuleId, "Index", "returnurl=" + WebUtility.UrlEncode(PageState.Route.PathAndQuery)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "Add":
|
case "Add":
|
||||||
@ -515,10 +523,10 @@
|
|||||||
switch (location)
|
switch (location)
|
||||||
{
|
{
|
||||||
case "Add":
|
case "Add":
|
||||||
url = EditUrl(PageState.Page.Path, module.ModuleId, location, "cp=" + PageState.Page.PageId);
|
url = EditUrl("admin/pages", module.ModuleId, location, $"id={PageState.Page.PageId}&returnurl={WebUtility.UrlEncode(PageState.Route.PathAndQuery)}");
|
||||||
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("admin/pages", module.ModuleId, location, $"id={PageState.Page.PageId}&returnurl={WebUtility.UrlEncode(PageState.Route.PathAndQuery)}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ namespace Oqtane.Themes.Controls
|
|||||||
[Inject] public IUserService UserService { get; set; }
|
[Inject] public IUserService UserService { get; set; }
|
||||||
[Inject] public IJSRuntime jsRuntime { get; set; }
|
[Inject] public IJSRuntime jsRuntime { get; set; }
|
||||||
[Inject] public IServiceProvider ServiceProvider { get; set; }
|
[Inject] public IServiceProvider ServiceProvider { get; set; }
|
||||||
[Inject] public SiteState SiteState { get; set; }
|
|
||||||
[Inject] public ILogService LoggingService { get; set; }
|
[Inject] public ILogService LoggingService { get; set; }
|
||||||
|
|
||||||
protected void LoginUser()
|
protected void LoginUser()
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
<div class="app-menu navbar-expand-md">
|
<div class="app-menu navbar-expand-md">
|
||||||
<div class="collapse navbar-collapse" id="Menu">
|
<div class="collapse navbar-collapse navbar-nav-scroll" id="Menu">
|
||||||
<MenuItemsHorizontal ParentPage="null" Pages="MenuPages" />
|
<MenuItemsHorizontal ParentPage="null" Pages="MenuPages" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
using Oqtane.Documentation;
|
using Oqtane.Documentation;
|
||||||
using Oqtane.Models;
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
namespace Oqtane.Themes.OqtaneTheme
|
namespace Oqtane.Themes.OqtaneTheme
|
||||||
{
|
{
|
||||||
@ -11,7 +13,13 @@ namespace Oqtane.Themes.OqtaneTheme
|
|||||||
Name = "Oqtane Theme",
|
Name = "Oqtane Theme",
|
||||||
Version = "1.0.0",
|
Version = "1.0.0",
|
||||||
ThemeSettingsType = "Oqtane.Themes.OqtaneTheme.ThemeSettings, Oqtane.Client",
|
ThemeSettingsType = "Oqtane.Themes.OqtaneTheme.ThemeSettings, Oqtane.Client",
|
||||||
ContainerSettingsType = "Oqtane.Themes.OqtaneTheme.ContainerSettings, Oqtane.Client"
|
ContainerSettingsType = "Oqtane.Themes.OqtaneTheme.ContainerSettings, Oqtane.Client",
|
||||||
|
Resources = new List<Resource>()
|
||||||
|
{
|
||||||
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootswatch/5.3.0/cyborg/bootstrap.min.css", Integrity = "sha512-jwIqEv8o/kTBMJVtbNCBrDqhBojl0YSUam+EFpLjVOC86Ci6t4ZciTnIkelFNOik+dEQVymKGcQLiaJZNAfWRg==", CrossOrigin = "anonymous" },
|
||||||
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "~/Theme.css" },
|
||||||
|
new Resource { ResourceType = ResourceType.Script, Url = "https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.bundle.min.js", Integrity = "sha512-VK2zcvntEufaimc+efOYi622VN5ZacdnufnmX7zIhCPmjhKnOi9ZDMtg1/ug5l183f19gG1/cBstPO4D8N/Img==", CrossOrigin = "anonymous" }
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,14 +110,6 @@
|
|||||||
|
|
||||||
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 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>()
|
|
||||||
{
|
|
||||||
// obtained from https://cdnjs.com/libraries
|
|
||||||
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.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;
|
||||||
private bool _register = true;
|
private bool _register = true;
|
||||||
private bool _footer = false;
|
private bool _footer = false;
|
||||||
|
@ -52,17 +52,23 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string resourceType = "Oqtane.Themes.OqtaneTheme.ThemeSettings, Oqtane.Client"; // for localization
|
private int pageId = -1;
|
||||||
private string _scope = "page";
|
private string resourceType = "Oqtane.Themes.OqtaneTheme.ThemeSettings, Oqtane.Client"; // for localization
|
||||||
private string _login = "-";
|
private string _scope = "page";
|
||||||
private string _register = "-";
|
private string _login = "-";
|
||||||
private string _footer = "-";
|
private string _register = "-";
|
||||||
|
private string _footer = "-";
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
if (PageState.QueryString.ContainsKey("id"))
|
||||||
{
|
{
|
||||||
await LoadSettings();
|
pageId = int.Parse(PageState.QueryString["id"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await LoadSettings();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -82,7 +88,8 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var settings = SettingService.MergeSettings(PageState.Site.Settings, PageState.Page.Settings);
|
var settings = await SettingService.GetPageSettingsAsync(pageId);
|
||||||
|
settings = SettingService.MergeSettings(PageState.Site.Settings, settings);
|
||||||
_login = SettingService.GetSetting(settings, GetType().Namespace + ":Login", "-");
|
_login = SettingService.GetSetting(settings, GetType().Namespace + ":Login", "-");
|
||||||
_register = SettingService.GetSetting(settings, GetType().Namespace + ":Register", "-");
|
_register = SettingService.GetSetting(settings, GetType().Namespace + ":Register", "-");
|
||||||
_footer = SettingService.GetSetting(settings, GetType().Namespace + ":Footer", "-");
|
_footer = SettingService.GetSetting(settings, GetType().Namespace + ":Footer", "-");
|
||||||
@ -128,7 +135,7 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var settings = await SettingService.GetPageSettingsAsync(PageState.Page.PageId);
|
var settings = await SettingService.GetPageSettingsAsync(pageId);
|
||||||
if (_login != "-")
|
if (_login != "-")
|
||||||
{
|
{
|
||||||
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Login", _login);
|
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Login", _login);
|
||||||
@ -141,7 +148,7 @@
|
|||||||
{
|
{
|
||||||
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Footer", _footer);
|
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Footer", _footer);
|
||||||
}
|
}
|
||||||
await SettingService.UpdatePageSettingsAsync(settings, PageState.Page.PageId);
|
await SettingService.UpdatePageSettingsAsync(settings, pageId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -6,6 +6,7 @@ using Oqtane.UI;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Oqtane.Themes
|
namespace Oqtane.Themes
|
||||||
@ -15,10 +16,13 @@ namespace Oqtane.Themes
|
|||||||
[Inject]
|
[Inject]
|
||||||
protected IJSRuntime JSRuntime { get; set; }
|
protected IJSRuntime JSRuntime { get; set; }
|
||||||
|
|
||||||
// optional interface properties
|
[Inject]
|
||||||
|
protected SiteState SiteState { get; set; }
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
protected PageState PageState { get; set; }
|
protected PageState PageState { get; set; }
|
||||||
|
|
||||||
|
// optional interface properties
|
||||||
public virtual string Name { get; set; }
|
public virtual string Name { get; set; }
|
||||||
public virtual string Thumbnail { get; set; }
|
public virtual string Thumbnail { get; set; }
|
||||||
public virtual string Panes { get; set; }
|
public virtual string Panes { get; set; }
|
||||||
@ -30,17 +34,33 @@ namespace Oqtane.Themes
|
|||||||
{
|
{
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
{
|
{
|
||||||
if (Resources != null && Resources.Exists(item => item.ResourceType == ResourceType.Script))
|
List<Resource> resources = null;
|
||||||
|
var type = GetType();
|
||||||
|
if (type.BaseType == typeof(ThemeBase))
|
||||||
|
{
|
||||||
|
if (PageState.Page.Resources != null)
|
||||||
|
{
|
||||||
|
resources = PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Script && item.Level != ResourceLevel.Site && item.Namespace == type.Namespace).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // themecontrolbase, containerbase
|
||||||
|
{
|
||||||
|
if (Resources != null)
|
||||||
|
{
|
||||||
|
resources = Resources.Where(item => item.ResourceType == ResourceType.Script).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resources != null && resources.Any())
|
||||||
{
|
{
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
var scripts = new List<object>();
|
var scripts = new List<object>();
|
||||||
var inline = 0;
|
var inline = 0;
|
||||||
foreach (Resource resource in Resources.Where(item => item.ResourceType == ResourceType.Script))
|
foreach (Resource resource in resources)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(resource.Url))
|
if (!string.IsNullOrEmpty(resource.Url))
|
||||||
{
|
{
|
||||||
var url = (resource.Url.Contains("://")) ? resource.Url : PageState.Alias.BaseUrl + resource.Url;
|
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 });
|
scripts.Add(new { href = url, bundle = resource.Bundle ?? "", integrity = resource.Integrity ?? "", crossorigin = resource.CrossOrigin ?? "", es6module = resource.ES6Module, location = resource.Location.ToString().ToLower() });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -139,6 +159,33 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetPageTitle(string title)
|
||||||
|
{
|
||||||
|
SiteState.Properties.PageTitle = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
// note - only supports links and meta tags - not scripts
|
||||||
|
public void AddHeadContent(string content)
|
||||||
|
{
|
||||||
|
SiteState.AppendHeadContent(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddScript(Resource resource)
|
||||||
|
{
|
||||||
|
resource.ResourceType = ResourceType.Script;
|
||||||
|
if (Resources == null) Resources = new List<Resource>();
|
||||||
|
if (!Resources.Any(item => (!string.IsNullOrEmpty(resource.Url) && item.Url == resource.Url) || (!string.IsNullOrEmpty(resource.Content) && item.Content == resource.Content)))
|
||||||
|
{
|
||||||
|
Resources.Add(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ScrollToPageTop()
|
||||||
|
{
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
await interop.ScrollTo(0, 0, "smooth");
|
||||||
|
}
|
||||||
|
|
||||||
[Obsolete("ContentUrl(int fileId) is deprecated. Use FileUrl(int fileId) instead.", false)]
|
[Obsolete("ContentUrl(int fileId) is deprecated. Use FileUrl(int fileId) instead.", false)]
|
||||||
public string ContentUrl(int fileid)
|
public string ContentUrl(int fileid)
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
|
|
||||||
@if (_visible)
|
@if (_visible)
|
||||||
{
|
{
|
||||||
<CascadingValue Value="@ModuleState">
|
<a id="@ModuleState.PageModuleId.ToString()"></a>
|
||||||
|
<CascadingValue Value="@ModuleState">
|
||||||
@if (_useadminborder)
|
@if (_useadminborder)
|
||||||
{
|
{
|
||||||
<div class="app-pane-admin-border">
|
<div class="app-pane-admin-border">
|
||||||
@ -16,6 +17,7 @@
|
|||||||
@DynamicComponent
|
@DynamicComponent
|
||||||
}
|
}
|
||||||
</CascadingValue>
|
</CascadingValue>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
@ -38,7 +40,7 @@
|
|||||||
protected override void OnParametersSet()
|
protected override void OnParametersSet()
|
||||||
{
|
{
|
||||||
string container = ModuleState.ContainerType;
|
string container = ModuleState.ContainerType;
|
||||||
if (PageState.ModuleId != -1 && ModuleState.UseAdminContainer)
|
if (PageState.ModuleId != -1 && PageState.Route.Action != "" && ModuleState.UseAdminContainer)
|
||||||
{
|
{
|
||||||
container = (!string.IsNullOrEmpty(PageState.Site.AdminContainerType)) ? PageState.Site.AdminContainerType : Constants.DefaultAdminContainer;
|
container = (!string.IsNullOrEmpty(PageState.Site.AdminContainerType)) ? PageState.Site.AdminContainerType : Constants.DefaultAdminContainer;
|
||||||
}
|
}
|
||||||
|
@ -96,7 +96,7 @@ namespace Oqtane.UI
|
|||||||
{
|
{
|
||||||
_jsRuntime.InvokeVoidAsync(
|
_jsRuntime.InvokeVoidAsync(
|
||||||
"Oqtane.Interop.includeLinks",
|
"Oqtane.Interop.includeLinks",
|
||||||
(object) links);
|
(object)links);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@ -107,12 +107,17 @@ namespace Oqtane.UI
|
|||||||
|
|
||||||
// external scripts need to specify src, inline scripts need to specify id and content
|
// external scripts need to specify src, inline scripts need to specify id and content
|
||||||
public Task IncludeScript(string id, string src, string integrity, string crossorigin, string content, string location)
|
public Task IncludeScript(string id, string src, string integrity, string crossorigin, string content, string location)
|
||||||
|
{
|
||||||
|
return IncludeScript(id, src, integrity, crossorigin, "", content, location);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task IncludeScript(string id, string src, string integrity, string crossorigin, string type, string content, string location)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_jsRuntime.InvokeVoidAsync(
|
_jsRuntime.InvokeVoidAsync(
|
||||||
"Oqtane.Interop.includeScript",
|
"Oqtane.Interop.includeScript",
|
||||||
id, src, integrity, crossorigin, content, location);
|
id, src, integrity, crossorigin, type, content, location);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
|
@ -13,6 +13,7 @@ namespace Oqtane.UI
|
|||||||
public Page Page { get; set; }
|
public Page Page { get; set; }
|
||||||
public User User { get; set; }
|
public User User { get; set; }
|
||||||
public Uri Uri { get; set; }
|
public Uri Uri { get; set; }
|
||||||
|
public Route Route { 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; }
|
||||||
public int ModuleId { get; set; }
|
public int ModuleId { get; set; }
|
||||||
@ -23,6 +24,7 @@ namespace Oqtane.UI
|
|||||||
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 string ReturnUrl { get; set; }
|
||||||
|
public bool IsInternalNavigation { get; set; }
|
||||||
|
|
||||||
public List<Page> Pages
|
public List<Page> Pages
|
||||||
{
|
{
|
||||||
|
@ -17,57 +17,59 @@ 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.PermissionList) && PageState.Action == Constants.DefaultAction)
|
if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.PermissionList) && 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)
|
foreach (Module module in PageState.Modules.Where(item => item.PageId == PageState.Page.PageId))
|
||||||
{
|
{
|
||||||
// action route needs to inject module control into specific pane
|
var pane = module.Pane;
|
||||||
string pane = "";
|
if (module.ModuleId == PageState.ModuleId && PageState.Action != Constants.DefaultAction)
|
||||||
if (PageState.Page.Panes.FindIndex(item => item.Equals(PaneNames.Default, StringComparison.OrdinalIgnoreCase)) != -1)
|
{
|
||||||
{
|
if (PageState.Page.Panes.FindIndex(item => item.Equals(PaneNames.Default, StringComparison.OrdinalIgnoreCase)) != -1)
|
||||||
pane = PaneNames.Default;
|
{
|
||||||
}
|
pane = PaneNames.Default;
|
||||||
else
|
}
|
||||||
{
|
else
|
||||||
pane = PaneNames.Admin;
|
{
|
||||||
|
pane = PaneNames.Admin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
// pane matches current pane
|
||||||
if (Name.ToLower() == pane.ToLower())
|
if (Name.ToLower() == pane.ToLower())
|
||||||
{
|
{
|
||||||
Module module = PageState.Modules.FirstOrDefault(item => item.ModuleId == PageState.ModuleId);
|
if (module.ModuleId == PageState.ModuleId && PageState.Action != Constants.DefaultAction)
|
||||||
if (module != null)
|
{
|
||||||
{
|
var moduleType = Type.GetType(module.ModuleType);
|
||||||
var moduleType = Type.GetType(module.ModuleType);
|
if (moduleType != null)
|
||||||
if (moduleType != null)
|
{
|
||||||
{
|
bool authorized = false;
|
||||||
bool authorized = false;
|
if (Constants.DefaultModuleActions.Contains(PageState.Action))
|
||||||
if (Constants.DefaultModuleActions.Contains(PageState.Action))
|
{
|
||||||
{
|
authorized = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.PermissionList);
|
||||||
authorized = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.PermissionList);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -96,35 +98,16 @@ else
|
|||||||
CreateComponent(builder, module);
|
CreateComponent(builder, module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// module type does not exist
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (PageState.ModuleId != -1)
|
|
||||||
{
|
|
||||||
Module module = PageState.Modules.FirstOrDefault(item => item.ModuleId == PageState.ModuleId);
|
|
||||||
if (module != null && module.Pane.ToLower() == Name.ToLower())
|
|
||||||
{
|
{
|
||||||
// check if user is authorized to view module
|
if (PageState.ModuleId == -1 || PageState.ModuleId == module.ModuleId)
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.PermissionList))
|
|
||||||
{
|
{
|
||||||
CreateComponent(builder, module);
|
// check if user is authorized to view module
|
||||||
}
|
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.PermissionList))
|
||||||
}
|
{
|
||||||
}
|
CreateComponent(builder, module);
|
||||||
else
|
}
|
||||||
{
|
|
||||||
foreach (Module module in PageState.Modules.Where(item => item.PageId == PageState.Page.PageId && item.Pane.ToLower() == Name.ToLower()).OrderBy(x => x.Order).ToArray())
|
|
||||||
{
|
|
||||||
// check if user is authorized to view module
|
|
||||||
if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, module.PermissionList))
|
|
||||||
{
|
|
||||||
CreateComponent(builder, module);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,207 +22,243 @@
|
|||||||
@DynamicComponent
|
@DynamicComponent
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private string _absoluteUri;
|
private string _absoluteUri;
|
||||||
private bool _navigationInterceptionEnabled;
|
private bool _isInternalNavigation = false;
|
||||||
private PageState _pagestate;
|
private bool _navigationInterceptionEnabled;
|
||||||
private string _error = "";
|
private PageState _pagestate;
|
||||||
|
private string _error = "";
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Runtime { get; set; }
|
public string Runtime { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string RenderMode { get; set; }
|
public string RenderMode { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public int VisitorId { get; set; }
|
public int VisitorId { get; set; }
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
PageState PageState { get; set; }
|
PageState PageState { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public Action<PageState> OnStateChange { get; set; }
|
public Action<PageState> OnStateChange { get; set; }
|
||||||
|
|
||||||
private RenderFragment DynamicComponent { get; set; }
|
private RenderFragment DynamicComponent { get; set; }
|
||||||
|
|
||||||
protected override void OnInitialized()
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
_absoluteUri = NavigationManager.Uri;
|
_absoluteUri = NavigationManager.Uri;
|
||||||
NavigationManager.LocationChanged += LocationChanged;
|
NavigationManager.LocationChanged += LocationChanged;
|
||||||
|
|
||||||
DynamicComponent = builder =>
|
DynamicComponent = builder =>
|
||||||
{
|
{
|
||||||
if (PageState != null)
|
if (PageState != null)
|
||||||
{
|
{
|
||||||
builder.OpenComponent(0, Type.GetType(Constants.PageComponent));
|
builder.OpenComponent(0, Type.GetType(Constants.PageComponent));
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
NavigationManager.LocationChanged -= LocationChanged;
|
NavigationManager.LocationChanged -= LocationChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
if (PageState == null)
|
if (PageState == null)
|
||||||
{
|
{
|
||||||
await Refresh();
|
await Refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[SuppressMessage("ReSharper", "StringIndexOfIsCultureSpecific.1")]
|
private async void LocationChanged(object sender, LocationChangedEventArgs args)
|
||||||
private async Task Refresh()
|
{
|
||||||
{
|
_absoluteUri = args.Location;
|
||||||
Site site;
|
_isInternalNavigation = true;
|
||||||
Page page;
|
await Refresh();
|
||||||
User user = null;
|
}
|
||||||
var editmode = false;
|
|
||||||
var refresh = false;
|
|
||||||
var lastsyncdate = DateTime.UtcNow.AddHours(-1);
|
|
||||||
var runtime = (Shared.Runtime)Enum.Parse(typeof(Shared.Runtime), Runtime);
|
|
||||||
_error = "";
|
|
||||||
|
|
||||||
Route route = new Route(_absoluteUri, SiteState.Alias.Path);
|
Task IHandleAfterRender.OnAfterRenderAsync()
|
||||||
int moduleid = (int.TryParse(route.ModuleId, out moduleid)) ? moduleid : -1;
|
{
|
||||||
var action = (!string.IsNullOrEmpty(route.Action)) ? route.Action : Constants.DefaultAction;
|
if (!_navigationInterceptionEnabled)
|
||||||
var querystring = ParseQueryString(route.Query);
|
{
|
||||||
var returnurl = "";
|
_navigationInterceptionEnabled = true;
|
||||||
if (querystring.ContainsKey("returnurl"))
|
return NavigationInterception.EnableNavigationInterceptionAsync();
|
||||||
{
|
}
|
||||||
returnurl = WebUtility.UrlDecode(querystring["returnurl"]);
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reload the client application from the server if there is a forced reload or the user navigated to a site with a different alias
|
[SuppressMessage("ReSharper", "StringIndexOfIsCultureSpecific.1")]
|
||||||
if (querystring.ContainsKey("reload") || (!NavigationManager.ToBaseRelativePath(_absoluteUri).ToLower().StartsWith(SiteState.Alias.Path.ToLower()) && !string.IsNullOrEmpty(SiteState.Alias.Path)))
|
private async Task Refresh()
|
||||||
{
|
{
|
||||||
if (querystring.ContainsKey("reload") && querystring["reload"] == "post")
|
Site site;
|
||||||
{
|
Page page;
|
||||||
// post back so that the cookies are set correctly - required on any change to the principal
|
User user = null;
|
||||||
var interop = new Interop(JSRuntime);
|
var editmode = false;
|
||||||
var fields = new { returnurl = "/" + NavigationManager.ToBaseRelativePath(_absoluteUri) };
|
var refresh = false;
|
||||||
string url = Utilities.TenantUrl(SiteState.Alias, "/pages/external/");
|
var lastsyncdate = DateTime.UtcNow.AddHours(-1);
|
||||||
await interop.SubmitForm(url, fields);
|
var runtime = (Shared.Runtime)Enum.Parse(typeof(Shared.Runtime), Runtime);
|
||||||
return;
|
_error = "";
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NavigationManager.NavigateTo(_absoluteUri.Replace("?reload", ""), true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// the refresh parameter is used to refresh the client-side PageState
|
Route route = new Route(_absoluteUri, SiteState.Alias.Path);
|
||||||
if (querystring.ContainsKey("refresh"))
|
int moduleid = (int.TryParse(route.ModuleId, out moduleid)) ? moduleid : -1;
|
||||||
{
|
var action = (!string.IsNullOrEmpty(route.Action)) ? route.Action : Constants.DefaultAction;
|
||||||
refresh = true;
|
var querystring = Utilities.ParseQueryString(route.Query);
|
||||||
}
|
var returnurl = "";
|
||||||
|
if (querystring.ContainsKey("returnurl"))
|
||||||
|
{
|
||||||
|
returnurl = WebUtility.UrlDecode(querystring["returnurl"]);
|
||||||
|
}
|
||||||
|
|
||||||
if (PageState != null)
|
// 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)))
|
||||||
editmode = PageState.EditMode;
|
{
|
||||||
lastsyncdate = PageState.LastSyncDate;
|
if (querystring.ContainsKey("reload") && querystring["reload"] == "post")
|
||||||
}
|
{
|
||||||
if (PageState?.Page.Path != route.PagePath)
|
// post back so that the cookies are set correctly - required on any change to the principal
|
||||||
{
|
var interop = new Interop(JSRuntime);
|
||||||
editmode = false; // reset edit mode when navigating to different page
|
var fields = new { returnurl = "/" + NavigationManager.ToBaseRelativePath(_absoluteUri) };
|
||||||
}
|
string url = Utilities.TenantUrl(SiteState.Alias, "/pages/external/");
|
||||||
|
await interop.SubmitForm(url, fields);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NavigationManager.NavigateTo(_absoluteUri.Replace("?reload", ""), true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// get user
|
// the refresh parameter is used to refresh the client-side PageState
|
||||||
if (PageState == null || refresh || PageState.Alias.SiteId != SiteState.Alias.SiteId)
|
if (querystring.ContainsKey("refresh"))
|
||||||
{
|
{
|
||||||
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
refresh = true;
|
||||||
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
|
if (PageState != null)
|
||||||
var sync = await SyncService.GetSyncAsync(lastsyncdate);
|
{
|
||||||
lastsyncdate = sync.SyncDate;
|
editmode = PageState.EditMode;
|
||||||
if (sync.SyncEvents.Any())
|
lastsyncdate = PageState.LastSyncDate;
|
||||||
{
|
}
|
||||||
// reload client application if server was restarted or site runtime/rendermode was modified
|
if (PageState?.Page.Path != route.PagePath)
|
||||||
if (PageState != null && sync.SyncEvents.Exists(item => (item.Action == SyncEventActions.Reload)))
|
{
|
||||||
{
|
editmode = false; // reset edit mode when navigating to different page
|
||||||
NavigationManager.NavigateTo(_absoluteUri, true);
|
}
|
||||||
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))
|
|
||||||
{
|
|
||||||
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 (PageState == null || refresh || PageState.Alias.SiteId != SiteState.Alias.SiteId)
|
// get user
|
||||||
{
|
if (PageState == null || refresh || PageState.Alias.SiteId != SiteState.Alias.SiteId)
|
||||||
site = await SiteService.GetSiteAsync(SiteState.Alias.SiteId);
|
{
|
||||||
refresh = true;
|
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
|
||||||
}
|
if (authState.User.Identity.IsAuthenticated)
|
||||||
else
|
{
|
||||||
{
|
user = await UserService.GetUserAsync(authState.User.Identity.Name, SiteState.Alias.SiteId);
|
||||||
site = PageState.Site;
|
if (user != null)
|
||||||
}
|
{
|
||||||
|
user.IsAuthenticated = authState.User.Identity.IsAuthenticated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
user = PageState.User;
|
||||||
|
}
|
||||||
|
|
||||||
if (site != null)
|
// process any sync events
|
||||||
{
|
var sync = await SyncService.GetSyncAsync(lastsyncdate);
|
||||||
if (PageState == null || refresh || PageState.Page.Path != route.PagePath)
|
lastsyncdate = sync.SyncDate;
|
||||||
{
|
if (sync.SyncEvents.Any())
|
||||||
page = site.Pages.FirstOrDefault(item => item.Path.Equals(route.PagePath, StringComparison.OrdinalIgnoreCase));
|
{
|
||||||
}
|
// reload client application if server was restarted or site runtime/rendermode was modified
|
||||||
else
|
if (PageState != null && sync.SyncEvents.Exists(item => (item.Action == SyncEventActions.Reload)))
|
||||||
{
|
{
|
||||||
page = PageState.Page;
|
NavigationManager.NavigateTo(_absoluteUri, true);
|
||||||
}
|
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))
|
||||||
|
{
|
||||||
|
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 (page == null && route.PagePath == "") // naked path refers to site home page
|
if (PageState == null || refresh || PageState.Alias.SiteId != SiteState.Alias.SiteId)
|
||||||
{
|
{
|
||||||
if (site.HomePageId != null)
|
site = await SiteService.GetSiteAsync(SiteState.Alias.SiteId);
|
||||||
{
|
refresh = true;
|
||||||
page = site.Pages.FirstOrDefault(item => item.PageId == site.HomePageId);
|
}
|
||||||
}
|
else
|
||||||
if (page == null)
|
{
|
||||||
{
|
site = PageState.Site;
|
||||||
// fallback to use the first page in the collection
|
}
|
||||||
page = site.Pages.FirstOrDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (page != null)
|
if (site != null)
|
||||||
{
|
{
|
||||||
// check if user is authorized to view page
|
if (PageState == null || refresh || PageState.Page.Path != route.PagePath)
|
||||||
if (UserSecurity.IsAuthorized(user, PermissionNames.View, page.PermissionList))
|
{
|
||||||
{
|
page = site.Pages.FirstOrDefault(item => item.Path.Equals(route.PagePath, StringComparison.OrdinalIgnoreCase));
|
||||||
// load additional metadata for current page
|
}
|
||||||
page = await ProcessPage(page, site, user);
|
else
|
||||||
|
{
|
||||||
|
page = PageState.Page;
|
||||||
|
}
|
||||||
|
|
||||||
// load additional metadata for modules
|
if (page == null && route.PagePath == "") // naked path refers to site home page
|
||||||
(page, site.Modules) = ProcessModules(page, site.Modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType);
|
{
|
||||||
|
if (site.HomePageId != null)
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (page == null)
|
||||||
|
{
|
||||||
|
// look for personalized page
|
||||||
|
page = await PageService.GetPageAsync(route.PagePath, site.SiteId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (user != null && page.IsPersonalizable)
|
||||||
|
{
|
||||||
|
var personalized = await PageService.GetPageAsync(route.PagePath + "/" + user.Username, site.SiteId);
|
||||||
|
if (personalized != null)
|
||||||
|
{
|
||||||
|
// redirect to the personalized page
|
||||||
|
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, personalized.Path, ""), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// populate page state (which acts as a client-side cache for subsequent requests)
|
if (page != null)
|
||||||
_pagestate = new PageState
|
{
|
||||||
|
// check if user is authorized to view page
|
||||||
|
if (UserSecurity.IsAuthorized(user, PermissionNames.View, page.PermissionList))
|
||||||
|
{
|
||||||
|
// load additional metadata for current page
|
||||||
|
page = ProcessPage(page, site, user, SiteState.Alias);
|
||||||
|
|
||||||
|
// load additional metadata for modules
|
||||||
|
(page, site.Modules) = ProcessModules(page, site.Modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType, SiteState.Alias);
|
||||||
|
|
||||||
|
// populate page state (which acts as a client-side cache for subsequent requests)
|
||||||
|
_pagestate = new PageState
|
||||||
{
|
{
|
||||||
Alias = SiteState.Alias,
|
Alias = SiteState.Alias,
|
||||||
Site = site,
|
Site = site,
|
||||||
Page = page,
|
Page = page,
|
||||||
User = user,
|
User = user,
|
||||||
Uri = new Uri(_absoluteUri, UriKind.Absolute),
|
Uri = new Uri(_absoluteUri, UriKind.Absolute),
|
||||||
|
Route = route,
|
||||||
QueryString = querystring,
|
QueryString = querystring,
|
||||||
UrlParameters = route.UrlParameters,
|
UrlParameters = route.UrlParameters,
|
||||||
ModuleId = moduleid,
|
ModuleId = moduleid,
|
||||||
@ -232,300 +268,270 @@
|
|||||||
Runtime = runtime,
|
Runtime = runtime,
|
||||||
VisitorId = VisitorId,
|
VisitorId = VisitorId,
|
||||||
RemoteIPAddress = SiteState.RemoteIPAddress,
|
RemoteIPAddress = SiteState.RemoteIPAddress,
|
||||||
ReturnUrl = returnurl
|
ReturnUrl = returnurl,
|
||||||
|
IsInternalNavigation = _isInternalNavigation
|
||||||
};
|
};
|
||||||
|
|
||||||
OnStateChange?.Invoke(_pagestate);
|
OnStateChange?.Invoke(_pagestate);
|
||||||
await ScrollToFragment(_pagestate.Uri);
|
await ScrollToFragment(_pagestate.Uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // page not found
|
else // page not found
|
||||||
{
|
{
|
||||||
// look for url mapping
|
// look for url mapping
|
||||||
var urlMapping = await UrlMappingService.GetUrlMappingAsync(site.SiteId, route.PagePath);
|
var urlMapping = await UrlMappingService.GetUrlMappingAsync(site.SiteId, route.PagePath);
|
||||||
if (urlMapping != null && !string.IsNullOrEmpty(urlMapping.MappedUrl))
|
if (urlMapping != null && !string.IsNullOrEmpty(urlMapping.MappedUrl))
|
||||||
{
|
{
|
||||||
var url = (urlMapping.MappedUrl.StartsWith("http")) ? urlMapping.MappedUrl : route.SiteUrl + "/" + urlMapping.MappedUrl;
|
var url = (urlMapping.MappedUrl.StartsWith("http")) ? urlMapping.MappedUrl : route.SiteUrl + "/" + urlMapping.MappedUrl;
|
||||||
NavigationManager.NavigateTo(url, false);
|
NavigationManager.NavigateTo(url, false);
|
||||||
}
|
}
|
||||||
else // not mapped
|
else // not mapped
|
||||||
{
|
{
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
// redirect to login page if user not logged in as they may need to be authenticated
|
// redirect to login page if user not logged in as they may need to be authenticated
|
||||||
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "login", "?returnurl=" + WebUtility.UrlEncode(route.PathAndQuery)));
|
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "login", "?returnurl=" + WebUtility.UrlEncode(route.PathAndQuery)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (route.PagePath != "404")
|
if (route.PagePath != "404")
|
||||||
{
|
{
|
||||||
// redirect to 404 page
|
// redirect to 404 page
|
||||||
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "404", ""));
|
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "404", ""));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// redirect to home page as a fallback
|
// redirect to home page as a fallback
|
||||||
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "", ""));
|
NavigationManager.NavigateTo(Utilities.NavigateUrl(SiteState.Alias.Path, "", ""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// site does not exist
|
// site does not exist
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void LocationChanged(object sender, LocationChangedEventArgs args)
|
private Page ProcessPage(Page page, Site site, User user, Alias alias)
|
||||||
{
|
{
|
||||||
_absoluteUri = args.Location;
|
try
|
||||||
await Refresh();
|
{
|
||||||
}
|
page.Panes = new List<string>();
|
||||||
|
page.Resources = new List<Resource>();
|
||||||
|
|
||||||
Task IHandleAfterRender.OnAfterRenderAsync()
|
// validate theme
|
||||||
{
|
if (string.IsNullOrEmpty(page.ThemeType))
|
||||||
if (!_navigationInterceptionEnabled)
|
{
|
||||||
{
|
page.ThemeType = site.DefaultThemeType;
|
||||||
_navigationInterceptionEnabled = true;
|
}
|
||||||
return NavigationInterception.EnableNavigationInterceptionAsync();
|
var theme = site.Themes.FirstOrDefault(item => item.Themes.Any(item => item.TypeName == page.ThemeType));
|
||||||
}
|
Type themetype = Type.GetType(page.ThemeType);
|
||||||
return Task.CompletedTask;
|
if (themetype == null || theme == null)
|
||||||
}
|
{
|
||||||
|
// fallback to default Oqtane theme
|
||||||
|
page.ThemeType = Constants.DefaultTheme;
|
||||||
|
themetype = Type.GetType(Constants.DefaultTheme);
|
||||||
|
theme = site.Themes.FirstOrDefault(item => item.Themes.Any(item => item.TypeName == page.ThemeType));
|
||||||
|
}
|
||||||
|
|
||||||
private Dictionary<string, string> ParseQueryString(string query)
|
string panes = "";
|
||||||
{
|
if (themetype != null && theme != null)
|
||||||
Dictionary<string, string> querystring = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); // case insensistive keys
|
{
|
||||||
if (!string.IsNullOrEmpty(query))
|
// get resources for theme (ITheme)
|
||||||
{
|
page.Resources = ManagePageResources(page.Resources, theme.Resources, ResourceLevel.Page, alias, "Themes", Utilities.GetTypeName(theme.ThemeName));
|
||||||
if (query.StartsWith("?"))
|
|
||||||
{
|
|
||||||
query = query.Substring(1); // ignore "?"
|
|
||||||
}
|
|
||||||
foreach (string kvp in query.Split('&', StringSplitOptions.RemoveEmptyEntries))
|
|
||||||
{
|
|
||||||
if (kvp != "")
|
|
||||||
{
|
|
||||||
if (kvp.Contains("="))
|
|
||||||
{
|
|
||||||
string[] pair = kvp.Split('=');
|
|
||||||
if (!querystring.ContainsKey(pair[0]))
|
|
||||||
{
|
|
||||||
querystring.Add(pair[0], pair[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!querystring.ContainsKey(kvp))
|
|
||||||
{
|
|
||||||
querystring.Add(kvp, "true"); // default parameter when no value is provided
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return querystring;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<Page> ProcessPage(Page page, Site site, User user)
|
var themeobject = Activator.CreateInstance(themetype) as IThemeControl;
|
||||||
{
|
if (themeobject != null)
|
||||||
try
|
{
|
||||||
{
|
if (!string.IsNullOrEmpty(themeobject.Panes))
|
||||||
if (page.IsPersonalizable && user != null)
|
{
|
||||||
{
|
panes = themeobject.Panes;
|
||||||
// load the personalized page
|
}
|
||||||
page = await PageService.GetPageAsync(page.PageId, user.UserId);
|
// get resources for theme control
|
||||||
}
|
page.Resources = ManagePageResources(page.Resources, themeobject.Resources, ResourceLevel.Page, alias, "Themes", themetype.Namespace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(page.ThemeType))
|
if (!string.IsNullOrEmpty(panes))
|
||||||
{
|
{
|
||||||
page.ThemeType = site.DefaultThemeType;
|
page.Panes = panes.Replace(";", ",").Split(',', 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
|
||||||
|
{
|
||||||
|
// error loading theme or layout
|
||||||
|
}
|
||||||
|
|
||||||
page.Panes = new List<string>();
|
return page;
|
||||||
page.Resources = new List<Resource>();
|
}
|
||||||
|
|
||||||
string panes = "";
|
private (Page Page, List<Module> Modules) ProcessModules(Page page, List<Module> modules, int moduleid, string action, string defaultcontainertype, Alias alias)
|
||||||
Type themetype = Type.GetType(page.ThemeType);
|
{
|
||||||
if (themetype == null)
|
var paneindex = new Dictionary<string, int>();
|
||||||
{
|
foreach (Module module in modules)
|
||||||
// fallback
|
{
|
||||||
page.ThemeType = Constants.DefaultTheme;
|
// initialize module control properties
|
||||||
themetype = Type.GetType(Constants.DefaultTheme);
|
module.SecurityAccessLevel = SecurityAccessLevel.Host;
|
||||||
}
|
module.ControlTitle = "";
|
||||||
if (themetype != null)
|
module.Actions = "";
|
||||||
{
|
module.UseAdminContainer = false;
|
||||||
var themeobject = Activator.CreateInstance(themetype) as IThemeControl;
|
module.PaneModuleIndex = -1;
|
||||||
if (themeobject != null)
|
module.PaneModuleCount = 0;
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(themeobject.Panes))
|
|
||||||
{
|
|
||||||
panes = themeobject.Panes;
|
|
||||||
}
|
|
||||||
page.Resources = ManagePageResources(page.Resources, themeobject.Resources, ResourceLevel.Page);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(panes))
|
|
||||||
{
|
|
||||||
page.Panes = panes.Replace(";", ",").Split(',', 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
|
|
||||||
{
|
|
||||||
// error loading theme or layout
|
|
||||||
}
|
|
||||||
|
|
||||||
return page;
|
if ((module.PageId == page.PageId || module.ModuleId == moduleid))
|
||||||
}
|
{
|
||||||
|
var typename = Constants.ErrorModule;
|
||||||
|
|
||||||
private (Page Page, List<Module> Modules) ProcessModules(Page page, List<Module> modules, int moduleid, string action, string defaultcontainertype)
|
if (module.ModuleDefinition != null && (module.ModuleDefinition.Runtimes == "" || module.ModuleDefinition.Runtimes.Contains(Runtime)))
|
||||||
{
|
{
|
||||||
var paneindex = new Dictionary<string, int>();
|
typename = module.ModuleDefinition.ControlTypeTemplate;
|
||||||
foreach (Module module in modules)
|
|
||||||
{
|
|
||||||
// initialize module control properties
|
|
||||||
module.SecurityAccessLevel = SecurityAccessLevel.Host;
|
|
||||||
module.ControlTitle = "";
|
|
||||||
module.Actions = "";
|
|
||||||
module.UseAdminContainer = false;
|
|
||||||
module.PaneModuleIndex = -1;
|
|
||||||
module.PaneModuleCount = 0;
|
|
||||||
|
|
||||||
if ((module.PageId == page.PageId || module.ModuleId == moduleid))
|
// handle default action
|
||||||
{
|
if (action == Constants.DefaultAction && !string.IsNullOrEmpty(module.ModuleDefinition.DefaultAction))
|
||||||
var typename = Constants.ErrorModule;
|
{
|
||||||
if (module.ModuleDefinition != null && (module.ModuleDefinition.Runtimes == "" || module.ModuleDefinition.Runtimes.Contains(Runtime)))
|
action = module.ModuleDefinition.DefaultAction;
|
||||||
{
|
}
|
||||||
typename = module.ModuleDefinition.ControlTypeTemplate;
|
|
||||||
|
|
||||||
// handle default action
|
// check if the module defines custom action routes
|
||||||
if (action == Constants.DefaultAction && !string.IsNullOrEmpty(module.ModuleDefinition.DefaultAction))
|
if (module.ModuleDefinition.ControlTypeRoutes != "")
|
||||||
{
|
{
|
||||||
action = module.ModuleDefinition.DefaultAction;
|
foreach (string route in module.ModuleDefinition.ControlTypeRoutes.Split(';', StringSplitOptions.RemoveEmptyEntries))
|
||||||
}
|
{
|
||||||
|
if (route.StartsWith(action + "="))
|
||||||
|
{
|
||||||
|
typename = route.Replace(action + "=", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check if the module defines custom action routes
|
// get module resources
|
||||||
if (module.ModuleDefinition.ControlTypeRoutes != "")
|
page.Resources = ManagePageResources(page.Resources, module.ModuleDefinition.Resources, ResourceLevel.Module, alias, "Modules", Utilities.GetTypeName(module.ModuleDefinition.ModuleDefinitionName));
|
||||||
{
|
}
|
||||||
foreach (string route in module.ModuleDefinition.ControlTypeRoutes.Split(';', StringSplitOptions.RemoveEmptyEntries))
|
|
||||||
{
|
|
||||||
if (route.StartsWith(action + "="))
|
|
||||||
{
|
|
||||||
typename = route.Replace(action + "=", "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure component exists and implements IModuleControl
|
// ensure component exists and implements IModuleControl
|
||||||
module.ModuleType = "";
|
module.ModuleType = "";
|
||||||
if (Constants.DefaultModuleActions.Contains(action, StringComparer.OrdinalIgnoreCase))
|
if (Constants.DefaultModuleActions.Contains(action, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
typename = Constants.DefaultModuleActionsTemplate.Replace(Constants.ActionToken, action);
|
typename = Constants.DefaultModuleActionsTemplate.Replace(Constants.ActionToken, action);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
typename = typename.Replace(Constants.ActionToken, action);
|
typename = typename.Replace(Constants.ActionToken, action);
|
||||||
}
|
}
|
||||||
Type moduletype = Type.GetType(typename, false, true); // case insensitive
|
Type moduletype = Type.GetType(typename, false, true); // case insensitive
|
||||||
if (moduletype != null && moduletype.GetInterfaces().Contains(typeof(IModuleControl)))
|
if (moduletype != null && moduletype.GetInterfaces().Contains(typeof(IModuleControl)))
|
||||||
{
|
{
|
||||||
module.ModuleType = Utilities.GetFullTypeName(moduletype.AssemblyQualifiedName); // get actual type name
|
module.ModuleType = Utilities.GetFullTypeName(moduletype.AssemblyQualifiedName); // get actual type name
|
||||||
}
|
}
|
||||||
|
|
||||||
// get additional metadata from IModuleControl interface
|
// get additional metadata from IModuleControl interface
|
||||||
if (moduletype != null && module.ModuleType != "")
|
if (moduletype != null && module.ModuleType != "")
|
||||||
{
|
{
|
||||||
// retrieve module component resources
|
// retrieve module component resources
|
||||||
var moduleobject = Activator.CreateInstance(moduletype) as IModuleControl;
|
var moduleobject = Activator.CreateInstance(moduletype) as IModuleControl;
|
||||||
page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module);
|
page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace);
|
||||||
if (action.ToLower() == "settings" && module.ModuleDefinition != null)
|
if (action.ToLower() == "settings" && module.ModuleDefinition != null)
|
||||||
{
|
{
|
||||||
// settings components are embedded within a framework settings module
|
// settings components are embedded within a framework settings module
|
||||||
moduletype = Type.GetType(module.ModuleDefinition.ControlTypeTemplate.Replace(Constants.ActionToken, action), false, true);
|
moduletype = Type.GetType(module.ModuleDefinition.ControlTypeTemplate.Replace(Constants.ActionToken, action), false, true);
|
||||||
if (moduletype != null)
|
if (moduletype != null)
|
||||||
{
|
{
|
||||||
moduleobject = Activator.CreateInstance(moduletype) as IModuleControl;
|
moduleobject = Activator.CreateInstance(moduletype) as IModuleControl;
|
||||||
page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module);
|
page.Resources = ManagePageResources(page.Resources, moduleobject.Resources, ResourceLevel.Module, alias, "Modules", moduletype.Namespace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// additional metadata needed for admin components
|
// additional metadata needed for admin components
|
||||||
if (module.ModuleId == moduleid && action != "")
|
if (module.ModuleId == moduleid && action != "")
|
||||||
{
|
{
|
||||||
module.SecurityAccessLevel = moduleobject.SecurityAccessLevel;
|
module.SecurityAccessLevel = moduleobject.SecurityAccessLevel;
|
||||||
module.ControlTitle = moduleobject.Title;
|
module.ControlTitle = moduleobject.Title;
|
||||||
module.Actions = moduleobject.Actions;
|
module.Actions = moduleobject.Actions;
|
||||||
module.UseAdminContainer = moduleobject.UseAdminContainer;
|
module.UseAdminContainer = moduleobject.UseAdminContainer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate that module's pane exists in current page
|
// validate that module's pane exists in current page
|
||||||
if (page.Panes.FindIndex(item => item.Equals(module.Pane, StringComparison.OrdinalIgnoreCase)) == -1)
|
if (page.Panes.FindIndex(item => item.Equals(module.Pane, StringComparison.OrdinalIgnoreCase)) == -1)
|
||||||
{
|
{
|
||||||
// fallback to default pane if it exists
|
// fallback to default pane if it exists
|
||||||
if (page.Panes.FindIndex(item => item.Equals(PaneNames.Default, StringComparison.OrdinalIgnoreCase)) != -1)
|
if (page.Panes.FindIndex(item => item.Equals(PaneNames.Default, StringComparison.OrdinalIgnoreCase)) != -1)
|
||||||
{
|
{
|
||||||
module.Pane = PaneNames.Default;
|
module.Pane = PaneNames.Default;
|
||||||
}
|
}
|
||||||
else // otherwise admin pane (legacy)
|
else // otherwise admin pane (legacy)
|
||||||
{
|
{
|
||||||
module.Pane = PaneNames.Admin;
|
module.Pane = PaneNames.Admin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate module position within pane
|
// calculate module position within pane
|
||||||
if (paneindex.ContainsKey(module.Pane.ToLower()))
|
if (paneindex.ContainsKey(module.Pane.ToLower()))
|
||||||
{
|
{
|
||||||
paneindex[module.Pane.ToLower()] += 1;
|
paneindex[module.Pane.ToLower()] += 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
paneindex.Add(module.Pane.ToLower(), 0);
|
paneindex.Add(module.Pane.ToLower(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.PaneModuleIndex = paneindex[module.Pane.ToLower()];
|
module.PaneModuleIndex = paneindex[module.Pane.ToLower()];
|
||||||
|
|
||||||
// container fallback
|
// container fallback
|
||||||
if (string.IsNullOrEmpty(module.ContainerType))
|
if (string.IsNullOrEmpty(module.ContainerType))
|
||||||
{
|
{
|
||||||
module.ContainerType = defaultcontainertype;
|
module.ContainerType = defaultcontainertype;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Module module in modules.Where(item => item.PageId == page.PageId))
|
foreach (Module module in modules.Where(item => item.PageId == page.PageId))
|
||||||
{
|
{
|
||||||
if (paneindex.ContainsKey(module.Pane.ToLower()))
|
if (paneindex.ContainsKey(module.Pane.ToLower()))
|
||||||
{
|
{
|
||||||
module.PaneModuleCount = paneindex[module.Pane.ToLower()] + 1;
|
module.PaneModuleCount = paneindex[module.Pane.ToLower()] + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (page, modules);
|
return (page, modules);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Resource> ManagePageResources(List<Resource> pageresources, List<Resource> resources, ResourceLevel level)
|
private List<Resource> ManagePageResources(List<Resource> pageresources, List<Resource> resources, ResourceLevel level, Alias alias, string type, string name)
|
||||||
{
|
{
|
||||||
if (resources != null)
|
if (resources != null)
|
||||||
{
|
{
|
||||||
foreach (var resource in resources)
|
foreach (var resource in resources)
|
||||||
{
|
{
|
||||||
// ensure resource does not exist already
|
if (resource.Level != ResourceLevel.Site)
|
||||||
if (pageresources.Find(item => item.Url == resource.Url) == null)
|
{
|
||||||
{
|
if (resource.Url.StartsWith("~"))
|
||||||
resource.Level = level;
|
{
|
||||||
pageresources.Add(resource);
|
resource.Url = resource.Url.Replace("~", "/" + type + "/" + name + "/").Replace("//", "/");
|
||||||
}
|
}
|
||||||
|
if (!resource.Url.Contains("://") && alias.BaseUrl != "" && !resource.Url.StartsWith(alias.BaseUrl))
|
||||||
|
{
|
||||||
|
resource.Url = alias.BaseUrl + resource.Url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure resource does not exist already
|
||||||
|
if (!pageresources.Exists(item => item.Url.ToLower() == resource.Url.ToLower()))
|
||||||
|
{
|
||||||
|
resource.Level = level;
|
||||||
|
resource.Namespace = name;
|
||||||
|
pageresources.Add(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pageresources;
|
return pageresources;
|
||||||
|
@ -1,59 +1,186 @@
|
|||||||
@namespace Oqtane.UI
|
@namespace Oqtane.UI
|
||||||
@inject IJSRuntime JsRuntime
|
@inject IJSRuntime JSRuntime
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
|
@inject SiteState SiteState
|
||||||
|
|
||||||
@DynamicComponent
|
@DynamicComponent
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[CascadingParameter] PageState PageState { get; set; }
|
[CascadingParameter] PageState PageState { get; set; }
|
||||||
|
|
||||||
RenderFragment DynamicComponent { get; set; }
|
RenderFragment DynamicComponent { get; set; }
|
||||||
|
|
||||||
protected override void OnParametersSet()
|
protected override void OnParametersSet()
|
||||||
{
|
{
|
||||||
// handle page redirection
|
// handle page redirection
|
||||||
if (!string.IsNullOrEmpty(PageState.Page.Url))
|
if (!string.IsNullOrEmpty(PageState.Page.Url))
|
||||||
{
|
|
||||||
NavigationManager.NavigateTo(PageState.Page.Url);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicComponent = builder =>
|
|
||||||
{
|
|
||||||
var themeType = Type.GetType(PageState.Page.ThemeType);
|
|
||||||
builder.OpenComponent(0, themeType);
|
|
||||||
builder.CloseComponent();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
||||||
{
|
|
||||||
var interop = new Interop(JsRuntime);
|
|
||||||
|
|
||||||
// manage stylesheets for this page
|
|
||||||
string batch = DateTime.UtcNow.ToString("yyyyMMddHHmmssfff");
|
|
||||||
var links = new List<object>();
|
|
||||||
foreach (Resource resource in PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Stylesheet))
|
|
||||||
{
|
|
||||||
var prefix = "app-stylesheet-" + resource.Level.ToString().ToLower();
|
|
||||||
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())
|
|
||||||
{
|
{
|
||||||
await interop.IncludeLinks(links.ToArray());
|
NavigationManager.NavigateTo(PageState.Page.Url);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
await interop.RemoveElementsById("app-stylesheet-page-", "", "app-stylesheet-page-" + batch + "-00");
|
|
||||||
await interop.RemoveElementsById("app-stylesheet-module-", "", "app-stylesheet-module-" + batch + "-00");
|
|
||||||
|
|
||||||
// set page title
|
// set page title
|
||||||
if (!string.IsNullOrEmpty(PageState.Page.Title))
|
if (!string.IsNullOrEmpty(PageState.Page.Title))
|
||||||
{
|
{
|
||||||
await interop.UpdateTitle(PageState.Page.Title);
|
SiteState.Properties.PageTitle = PageState.Page.Title;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await interop.UpdateTitle(PageState.Site.Name + " - " + PageState.Page.Name);
|
SiteState.Properties.PageTitle = PageState.Site.Name + " - " + PageState.Page.Name;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// set page head content
|
||||||
|
var headcontent = "";
|
||||||
|
|
||||||
|
// favicon
|
||||||
|
var favicon = "favicon.ico";
|
||||||
|
var favicontype = "x-icon";
|
||||||
|
if (PageState.Site.FaviconFileId != null)
|
||||||
|
{
|
||||||
|
favicon = Utilities.FileUrl(PageState.Alias, PageState.Site.FaviconFileId.Value);
|
||||||
|
favicontype = favicon.Substring(favicon.LastIndexOf(".") + 1);
|
||||||
|
}
|
||||||
|
headcontent += $"<link id=\"app-favicon\" rel=\"shortcut icon\" type=\"image/{favicontype}\" href=\"{favicon}\" />\n";
|
||||||
|
|
||||||
|
// head content
|
||||||
|
AddHeadContent(headcontent, PageState.Site.HeadContent);
|
||||||
|
if (!string.IsNullOrEmpty(PageState.Site.HeadContent))
|
||||||
|
{
|
||||||
|
headcontent = AddHeadContent(headcontent, PageState.Site.HeadContent);
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(PageState.Page.HeadContent))
|
||||||
|
{
|
||||||
|
headcontent = AddHeadContent(headcontent, PageState.Page.HeadContent);
|
||||||
|
}
|
||||||
|
SiteState.Properties.HeadContent = headcontent;
|
||||||
|
|
||||||
|
DynamicComponent = builder =>
|
||||||
|
{
|
||||||
|
var themeType = Type.GetType(PageState.Page.ThemeType);
|
||||||
|
builder.OpenComponent(0, themeType);
|
||||||
|
builder.CloseComponent();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private string AddHeadContent(string headcontent, string content)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(content))
|
||||||
|
{
|
||||||
|
// format head content, remove scripts, and filter duplicate elements
|
||||||
|
var elements = (">" + content.Replace("\n", "") + "<").Split("><");
|
||||||
|
foreach (var element in elements)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(element) && !element.Contains("script"))
|
||||||
|
{
|
||||||
|
if (!headcontent.Contains("<" + element + ">"))
|
||||||
|
{
|
||||||
|
headcontent += "<" + element + ">" + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return headcontent;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (!firstRender)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(PageState.Page.HeadContent) && PageState.Page.HeadContent.Contains("<script"))
|
||||||
|
{
|
||||||
|
await InjectScripts(PageState.Page.HeadContent, ResourceLocation.Head);
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(PageState.Page.BodyContent) && PageState.Page.BodyContent.Contains("<script"))
|
||||||
|
{
|
||||||
|
await InjectScripts(PageState.Page.BodyContent, ResourceLocation.Body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// style sheets
|
||||||
|
if (PageState.Page.Resources != null && PageState.Page.Resources.Exists(item => item.ResourceType == ResourceType.Stylesheet))
|
||||||
|
{
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
string batch = DateTime.UtcNow.ToString("yyyyMMddHHmmssfff");
|
||||||
|
var links = new List<object>();
|
||||||
|
foreach (Resource resource in PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Stylesheet))
|
||||||
|
{
|
||||||
|
var prefix = "app-stylesheet-" + resource.Level.ToString().ToLower();
|
||||||
|
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())
|
||||||
|
{
|
||||||
|
await interop.IncludeLinks(links.ToArray());
|
||||||
|
}
|
||||||
|
await interop.RemoveElementsById("app-stylesheet-page-", "", "app-stylesheet-page-" + batch + "-00");
|
||||||
|
await interop.RemoveElementsById("app-stylesheet-module-", "", "app-stylesheet-module-" + batch + "-00");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task InjectScripts(string content, ResourceLocation location)
|
||||||
|
{
|
||||||
|
// inject scripts into page dynamically
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
var scripts = new List<object>();
|
||||||
|
var count = 0;
|
||||||
|
var index = content.IndexOf("<script");
|
||||||
|
while (index >= 0)
|
||||||
|
{
|
||||||
|
var script = content.Substring(index, content.IndexOf("</script>", index) + 9 - index);
|
||||||
|
// get script attributes
|
||||||
|
var attributes = script.Substring(0, script.IndexOf(">")).Replace("\"", "").Split(" ");
|
||||||
|
string id = "";
|
||||||
|
string src = "";
|
||||||
|
string integrity = "";
|
||||||
|
string crossorigin = "";
|
||||||
|
string type = "";
|
||||||
|
foreach (var attribute in attributes)
|
||||||
|
{
|
||||||
|
if (attribute.Contains("="))
|
||||||
|
{
|
||||||
|
var value = attribute.Split("=");
|
||||||
|
switch (value[0])
|
||||||
|
{
|
||||||
|
case "id":
|
||||||
|
id = value[1];
|
||||||
|
break;
|
||||||
|
case "src":
|
||||||
|
src = value[1];
|
||||||
|
break;
|
||||||
|
case "integrity":
|
||||||
|
integrity = value[1];
|
||||||
|
break;
|
||||||
|
case "crossorigin":
|
||||||
|
crossorigin = value[1];
|
||||||
|
break;
|
||||||
|
case "type":
|
||||||
|
type = value[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// inject script
|
||||||
|
if (!string.IsNullOrEmpty(src))
|
||||||
|
{
|
||||||
|
src = (src.Contains("://")) ? src : PageState.Alias.BaseUrl + src;
|
||||||
|
scripts.Add(new { href = src, bundle = "", integrity = integrity, crossorigin = crossorigin, es6module = (type == "module"), location = location });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// inline script must have an id attribute
|
||||||
|
if (id == "")
|
||||||
|
{
|
||||||
|
count += 1;
|
||||||
|
id = $"page{PageState.Page.PageId}-script{count}";
|
||||||
|
}
|
||||||
|
index = script.IndexOf(">") + 1;
|
||||||
|
await interop.IncludeScript(id, "", "", "", "", script.Substring(index, script.IndexOf("</script>") - index), location.ToString().ToLower());
|
||||||
|
}
|
||||||
|
index = content.IndexOf("<script", index + 1);
|
||||||
|
}
|
||||||
|
if (scripts.Any())
|
||||||
|
{
|
||||||
|
await interop.IncludeScripts(scripts.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<Version>3.4.1</Version>
|
<Version>4.0.0</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
@ -10,7 +10,7 @@
|
|||||||
<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.4.1</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.0</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>
|
||||||
@ -29,7 +29,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MySql.EntityFrameworkCore" Version="6.0.0" />
|
<PackageReference Include="MySql.EntityFrameworkCore" Version="7.0.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -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.4.1</version>
|
<version>4.0.0</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,15 +12,15 @@
|
|||||||
<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.4.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.0</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
<file src="bin\net6.0\Oqtane.Database.MySQL.dll" target="lib\net6.0" />
|
<file src="bin\net7.0\Oqtane.Database.MySQL.dll" target="lib\net7.0" />
|
||||||
<file src="bin\net6.0\Oqtane.Database.MySQL.pdb" target="lib\net6.0" />
|
<file src="bin\net7.0\Oqtane.Database.MySQL.pdb" target="lib\net7.0" />
|
||||||
<file src="bin\net6.0\Mysql.EntityFrameworkCore.dll" target="lib\net6.0" />
|
<file src="bin\net7.0\Mysql.EntityFrameworkCore.dll" target="lib\net7.0" />
|
||||||
<file src="bin\net6.0\Mysql.Data.dll" target="lib\net6.0" />
|
<file src="bin\net7.0\Mysql.Data.dll" target="lib\net7.0" />
|
||||||
<file src="icon.png" target="" />
|
<file src="icon.png" target="" />
|
||||||
</files>
|
</files>
|
||||||
</package>
|
</package>
|
@ -1,8 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<Version>3.4.1</Version>
|
<Version>4.0.0</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
@ -10,7 +10,7 @@
|
|||||||
<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.4.1</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.0</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>
|
||||||
@ -29,9 +29,9 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="EFCore.NamingConventions" Version="6.0.0" />
|
<PackageReference Include="EFCore.NamingConventions" Version="7.0.2" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.3" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="7.0.5" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.3" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -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.4.1</version>
|
<version>4.0.0</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,16 +12,16 @@
|
|||||||
<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.4.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.0</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
<file src="bin\net6.0\Oqtane.Database.PostgreSQL.dll" target="lib\net6.0" />
|
<file src="bin\net7.0\Oqtane.Database.PostgreSQL.dll" target="lib\net7.0" />
|
||||||
<file src="bin\net6.0\Oqtane.Database.PostgreSQL.pdb" target="lib\net6.0" />
|
<file src="bin\net7.0\Oqtane.Database.PostgreSQL.pdb" target="lib\net7.0" />
|
||||||
<file src="bin\net6.0\EFCore.NamingConventions.dll" target="lib\net6.0" />
|
<file src="bin\net7.0\EFCore.NamingConventions.dll" target="lib\net7.0" />
|
||||||
<file src="bin\net6.0\Npgsql.EntityFrameworkCore.PostgreSQL.dll" target="lib\net6.0" />
|
<file src="bin\net7.0\Npgsql.EntityFrameworkCore.PostgreSQL.dll" target="lib\net7.0" />
|
||||||
<file src="bin\net6.0\Npgsql.dll" target="lib\net6.0" />
|
<file src="bin\net7.0\Npgsql.dll" target="lib\net7.0" />
|
||||||
<file src="icon.png" target="" />
|
<file src="icon.png" target="" />
|
||||||
</files>
|
</files>
|
||||||
</package>
|
</package>
|
@ -1,8 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<Version>3.4.1</Version>
|
<Version>4.0.0</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
@ -10,7 +10,7 @@
|
|||||||
<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.4.1</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.0</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>
|
||||||
@ -29,7 +29,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.3" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.5" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -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.4.1</version>
|
<version>4.0.0</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,14 +12,14 @@
|
|||||||
<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.4.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.0</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
<file src="bin\net6.0\Oqtane.Database.SqlServer.dll" target="lib\net6.0" />
|
<file src="bin\net7.0\Oqtane.Database.SqlServer.dll" target="lib\net7.0" />
|
||||||
<file src="bin\net6.0\Oqtane.Database.SqlServer.pdb" target="lib\net6.0" />
|
<file src="bin\net7.0\Oqtane.Database.SqlServer.pdb" target="lib\net7.0" />
|
||||||
<file src="bin\net6.0\Microsoft.EntityFrameworkCore.SqlServer.dll" target="lib\net6.0" />
|
<file src="bin\net7.0\Microsoft.EntityFrameworkCore.SqlServer.dll" target="lib\net7.0" />
|
||||||
<file src="icon.png" target="" />
|
<file src="icon.png" target="" />
|
||||||
</files>
|
</files>
|
||||||
</package>
|
</package>
|
@ -1,8 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<Version>3.4.1</Version>
|
<Version>4.0.0</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
@ -10,7 +10,7 @@
|
|||||||
<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.4.1</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.0</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>
|
||||||
@ -29,7 +29,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.3" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.5" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -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.4.1</version>
|
<version>4.0.0</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,14 +12,14 @@
|
|||||||
<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.4.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.0</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
<file src="bin\net6.0\Oqtane.Database.Sqlite.dll" target="lib\net6.0" />
|
<file src="bin\net7.0\Oqtane.Database.Sqlite.dll" target="lib\net7.0" />
|
||||||
<file src="bin\net6.0\Oqtane.Database.Sqlite.pdb" target="lib\net6.0" />
|
<file src="bin\net7.0\Oqtane.Database.Sqlite.pdb" target="lib\net7.0" />
|
||||||
<file src="bin\net6.0\Microsoft.EntityFrameworkCore.Sqlite.dll" target="lib\net6.0" />
|
<file src="bin\net7.0\Microsoft.EntityFrameworkCore.Sqlite.dll" target="lib\net7.0" />
|
||||||
<file src="icon.png" target="" />
|
<file src="icon.png" target="" />
|
||||||
</files>
|
</files>
|
||||||
</package>
|
</package>
|
6
Oqtane.Maui/Head.razor
Normal file
6
Oqtane.Maui/Head.razor
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<DynamicComponent Type="@ComponentType"></DynamicComponent>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
Type ComponentType = Type.GetType("Oqtane.Head, Oqtane.Client");
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
<BlazorWebView HostPage="wwwroot/index.html">
|
<BlazorWebView HostPage="wwwroot/index.html">
|
||||||
<BlazorWebView.RootComponents>
|
<BlazorWebView.RootComponents>
|
||||||
|
<RootComponent Selector="head::after" ComponentType="{x:Type local:Head}" />
|
||||||
<RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
|
<RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
|
||||||
</BlazorWebView.RootComponents>
|
</BlazorWebView.RootComponents>
|
||||||
</BlazorWebView>
|
</BlazorWebView>
|
||||||
|
@ -12,8 +12,8 @@ namespace Oqtane.Maui;
|
|||||||
public static class MauiProgram
|
public static class MauiProgram
|
||||||
{
|
{
|
||||||
// the API service url
|
// the API service url
|
||||||
static string apiurl = "https://www.dnfprojects.com"; // for testing
|
//static string apiurl = "https://www.dnfprojects.com"; // for testing
|
||||||
//static string apiurl = "http://localhost:44357"; // for local development (Oqtane.Server must be already running for MAUI client to connect)
|
static string apiurl = "http://localhost:44357"; // for local development (Oqtane.Server must be already running for MAUI client to connect)
|
||||||
|
|
||||||
public static MauiApp CreateMauiApp()
|
public static MauiApp CreateMauiApp()
|
||||||
{
|
{
|
||||||
@ -212,23 +212,37 @@ public static class MauiProgram
|
|||||||
private static void RegisterModuleServices(Assembly assembly, IServiceCollection services)
|
private static void RegisterModuleServices(Assembly assembly, IServiceCollection services)
|
||||||
{
|
{
|
||||||
// dynamically register module scoped services
|
// dynamically register module scoped services
|
||||||
var implementationTypes = assembly.GetInterfaces<IService>();
|
try
|
||||||
foreach (var implementationType in implementationTypes)
|
|
||||||
{
|
{
|
||||||
if (implementationType.AssemblyQualifiedName != null)
|
var implementationTypes = assembly.GetInterfaces<IService>();
|
||||||
|
foreach (var implementationType in implementationTypes)
|
||||||
{
|
{
|
||||||
var serviceType = Type.GetType(implementationType.AssemblyQualifiedName.Replace(implementationType.Name, $"I{implementationType.Name}"));
|
if (implementationType.AssemblyQualifiedName != null)
|
||||||
services.AddScoped(serviceType ?? implementationType, implementationType);
|
{
|
||||||
|
var serviceType = Type.GetType(implementationType.AssemblyQualifiedName.Replace(implementationType.Name, $"I{implementationType.Name}"));
|
||||||
|
services.AddScoped(serviceType ?? implementationType, implementationType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// could not interrogate assembly - likely missing dependencies
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void RegisterClientStartups(Assembly assembly, IServiceCollection services)
|
private static void RegisterClientStartups(Assembly assembly, IServiceCollection services)
|
||||||
{
|
{
|
||||||
var startUps = assembly.GetInstances<IClientStartup>();
|
try
|
||||||
foreach (var startup in startUps)
|
|
||||||
{
|
{
|
||||||
startup.ConfigureServices(services);
|
var startUps = assembly.GetInstances<IClientStartup>();
|
||||||
|
foreach (var startup in startUps)
|
||||||
|
{
|
||||||
|
startup.ConfigureServices(services);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// could not interrogate assembly - likely missing dependencies
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net6.0-android;net6.0-ios;net6.0-maccatalyst</TargetFrameworks>
|
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net7.0-windows10.0.19041.0</TargetFrameworks>
|
||||||
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net6.0-windows10.0.19041.0</TargetFrameworks>
|
|
||||||
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
|
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
|
||||||
<!-- <TargetFrameworks>$(TargetFrameworks);net6.0-tizen</TargetFrameworks> -->
|
<!-- <TargetFrameworks>net7.0-android;net7.0-ios;net7.0-maccatalyst</TargetFrameworks> -->
|
||||||
|
<!-- <TargetFrameworks>$(TargetFrameworks);net7.0-tizen</TargetFrameworks> -->
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<Version>3.4.1</Version>
|
<Version>4.0.0</Version>
|
||||||
<Product>Oqtane</Product>
|
<Product>Oqtane</Product>
|
||||||
<Authors>Shaun Walker</Authors>
|
<Authors>Shaun Walker</Authors>
|
||||||
<Company>.NET Foundation</Company>
|
<Company>.NET Foundation</Company>
|
||||||
@ -14,7 +14,7 @@
|
|||||||
<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.4.1</PackageReleaseNotes>
|
<PackageReleaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.0</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.Maui</RootNamespace>
|
<RootNamespace>Oqtane.Maui</RootNamespace>
|
||||||
@ -31,7 +31,7 @@
|
|||||||
<ApplicationIdGuid>0E29FC31-1B83-48ED-B6E0-9F3C67B775D4</ApplicationIdGuid>
|
<ApplicationIdGuid>0E29FC31-1B83-48ED-B6E0-9F3C67B775D4</ApplicationIdGuid>
|
||||||
|
|
||||||
<!-- Versions -->
|
<!-- Versions -->
|
||||||
<ApplicationDisplayVersion>3.4.1</ApplicationDisplayVersion>
|
<ApplicationDisplayVersion>4.0.0</ApplicationDisplayVersion>
|
||||||
<ApplicationVersion>1</ApplicationVersion>
|
<ApplicationVersion>1</ApplicationVersion>
|
||||||
|
|
||||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
|
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
|
||||||
@ -65,14 +65,21 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="6.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="7.0.5" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.8" />
|
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.5" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Localization" Version="2.2.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Localization" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="6.0.3" />
|
<PackageReference Include="Microsoft.Extensions.Localization" Version="7.0.5" />
|
||||||
<PackageReference Include="System.Net.Http.Json" Version="6.0.0" />
|
<PackageReference Include="System.Net.Http.Json" Version="7.0.1" />
|
||||||
<PackageReference Include="Oqtane.Client" Version="3.4.1" />
|
</ItemGroup>
|
||||||
<PackageReference Include="Oqtane.Shared" Version="3.4.1" />
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Oqtane.Client">
|
||||||
|
<HintPath>..\Oqtane.Server\bin\Debug\net7.0\Oqtane.Client.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Oqtane.Shared">
|
||||||
|
<HintPath>..\Oqtane.Server\bin\Debug\net7.0\Oqtane.Shared.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
15
Oqtane.Maui/Resources/Raw/AboutAssets.txt
Normal file
15
Oqtane.Maui/Resources/Raw/AboutAssets.txt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
Any raw assets you want to be deployed with your application can be placed in
|
||||||
|
this directory (and child directories). Deployment of the asset to your application
|
||||||
|
is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
|
||||||
|
|
||||||
|
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
|
||||||
|
|
||||||
|
These files will be deployed with you package and will be accessible using Essentials:
|
||||||
|
|
||||||
|
async Task LoadMauiAsset()
|
||||||
|
{
|
||||||
|
using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
|
||||||
|
using var reader = new StreamReader(stream);
|
||||||
|
|
||||||
|
var contents = reader.ReadToEnd();
|
||||||
|
}
|
@ -9,8 +9,8 @@
|
|||||||
<script src="js/app.js"></script>
|
<script src="js/app.js"></script>
|
||||||
<script src="js/loadjs.min.js"></script>
|
<script src="js/loadjs.min.js"></script>
|
||||||
<link rel="stylesheet" href="css/app.css" />
|
<link rel="stylesheet" href="css/app.css" />
|
||||||
<link id="app-stylesheet-page" rel="stylesheet" href="css/empty.css" disabled />
|
<link id="app-stylesheet-page" />
|
||||||
<link id="app-stylesheet-module" rel="stylesheet" href="css/empty.css" disabled />
|
<link id="app-stylesheet-module" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -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.Client</id>
|
<id>Oqtane.Client</id>
|
||||||
<version>3.4.1</version>
|
<version>4.0.0</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane Framework</title>
|
<title>Oqtane Framework</title>
|
||||||
@ -12,13 +12,13 @@
|
|||||||
<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.4.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.0</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
<file src="..\Oqtane.Client\bin\Release\net6.0\Oqtane.Client.dll" target="lib\net6.0" />
|
<file src="..\Oqtane.Client\bin\Release\net7.0\Oqtane.Client.dll" target="lib\net7.0" />
|
||||||
<file src="..\Oqtane.Client\bin\Release\net6.0\Oqtane.Client.pdb" target="lib\net6.0" />
|
<file src="..\Oqtane.Client\bin\Release\net7.0\Oqtane.Client.pdb" target="lib\net7.0" />
|
||||||
<file src="icon.png" target="" />
|
<file src="icon.png" target="" />
|
||||||
</files>
|
</files>
|
||||||
</package>
|
</package>
|
@ -2,7 +2,7 @@
|
|||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Framework</id>
|
<id>Oqtane.Framework</id>
|
||||||
<version>3.4.1</version>
|
<version>4.0.0</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane Framework</title>
|
<title>Oqtane Framework</title>
|
||||||
@ -11,8 +11,8 @@
|
|||||||
<copyright>.NET Foundation</copyright>
|
<copyright>.NET Foundation</copyright>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<license type="expression">MIT</license>
|
<license type="expression">MIT</license>
|
||||||
<projectUrl>https://github.com/oqtane/oqtane.framework/releases/download/v3.4.1/Oqtane.Framework.3.4.1.Upgrade.zip</projectUrl>
|
<projectUrl>https://github.com/oqtane/oqtane.framework/releases/download/v4.0.0/Oqtane.Framework.4.0.0.Upgrade.zip</projectUrl>
|
||||||
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v3.4.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.0</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane framework</tags>
|
<tags>oqtane framework</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
@ -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.Server</id>
|
<id>Oqtane.Server</id>
|
||||||
<version>3.4.1</version>
|
<version>4.0.0</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane Framework</title>
|
<title>Oqtane Framework</title>
|
||||||
@ -12,13 +12,13 @@
|
|||||||
<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.4.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.0</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
<file src="..\Oqtane.Server\bin\Release\net6.0\Oqtane.Server.dll" target="lib\net6.0" />
|
<file src="..\Oqtane.Server\bin\Release\net7.0\Oqtane.Server.dll" target="lib\net7.0" />
|
||||||
<file src="..\Oqtane.Server\bin\Release\net6.0\Oqtane.Server.pdb" target="lib\net6.0" />
|
<file src="..\Oqtane.Server\bin\Release\net7.0\Oqtane.Server.pdb" target="lib\net7.0" />
|
||||||
<file src="icon.png" target="" />
|
<file src="icon.png" target="" />
|
||||||
</files>
|
</files>
|
||||||
</package>
|
</package>
|
@ -2,7 +2,7 @@
|
|||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Shared</id>
|
<id>Oqtane.Shared</id>
|
||||||
<version>3.4.1</version>
|
<version>4.0.0</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane Framework</title>
|
<title>Oqtane Framework</title>
|
||||||
@ -12,13 +12,13 @@
|
|||||||
<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.4.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.0</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
<file src="..\Oqtane.Shared\bin\Release\net6.0\Oqtane.Shared.dll" target="lib\net6.0" />
|
<file src="..\Oqtane.Shared\bin\Release\net7.0\Oqtane.Shared.dll" target="lib\net7.0" />
|
||||||
<file src="..\Oqtane.Shared\bin\Release\net6.0\Oqtane.Shared.pdb" target="lib\net6.0" />
|
<file src="..\Oqtane.Shared\bin\Release\net7.0\Oqtane.Shared.pdb" target="lib\net7.0" />
|
||||||
<file src="icon.png" target="" />
|
<file src="icon.png" target="" />
|
||||||
</files>
|
</files>
|
||||||
</package>
|
</package>
|
@ -2,7 +2,7 @@
|
|||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>Oqtane.Updater</id>
|
<id>Oqtane.Updater</id>
|
||||||
<version>3.4.1</version>
|
<version>4.0.0</version>
|
||||||
<authors>Shaun Walker</authors>
|
<authors>Shaun Walker</authors>
|
||||||
<owners>.NET Foundation</owners>
|
<owners>.NET Foundation</owners>
|
||||||
<title>Oqtane Framework</title>
|
<title>Oqtane Framework</title>
|
||||||
@ -12,12 +12,12 @@
|
|||||||
<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.4.1</releaseNotes>
|
<releaseNotes>https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.0</releaseNotes>
|
||||||
<icon>icon.png</icon>
|
<icon>icon.png</icon>
|
||||||
<tags>oqtane</tags>
|
<tags>oqtane</tags>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
<file src="..\Oqtane.Updater\bin\Release\net6.0\publish\*.*" target="lib\net6.0" />
|
<file src="..\Oqtane.Updater\bin\Release\net7.0\publish\*.*" target="lib\net7.0" />
|
||||||
<file src="icon.png" target="" />
|
<file src="icon.png" target="" />
|
||||||
</files>
|
</files>
|
||||||
</package>
|
</package>
|
@ -1 +1 @@
|
|||||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net6.0\publish\*" -DestinationPath "Oqtane.Framework.3.4.1.Install.zip" -Force
|
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net7.0\publish\*" -DestinationPath "Oqtane.Framework.4.0.0.Install.zip" -Force
|
@ -8,14 +8,14 @@ nuget.exe pack Oqtane.Client.nuspec
|
|||||||
nuget.exe pack Oqtane.Server.nuspec
|
nuget.exe pack Oqtane.Server.nuspec
|
||||||
nuget.exe pack Oqtane.Shared.nuspec
|
nuget.exe pack Oqtane.Shared.nuspec
|
||||||
nuget.exe pack Oqtane.Framework.nuspec
|
nuget.exe pack Oqtane.Framework.nuspec
|
||||||
del /F/Q/S "..\Oqtane.Server\bin\Release\net6.0\publish" > NUL
|
del /F/Q/S "..\Oqtane.Server\bin\Release\net7.0\publish" > NUL
|
||||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\net6.0\publish"
|
rmdir /Q/S "..\Oqtane.Server\bin\Release\net7.0\publish"
|
||||||
dotnet publish ..\Oqtane.Server\Oqtane.Server.csproj /p:Configuration=Release
|
dotnet publish ..\Oqtane.Server\Oqtane.Server.csproj /p:Configuration=Release
|
||||||
del /F/Q/S "..\Oqtane.Server\bin\Release\net6.0\publish\wwwroot\Content" > NUL
|
del /F/Q/S "..\Oqtane.Server\bin\Release\net7.0\publish\wwwroot\Content" > NUL
|
||||||
rmdir /Q/S "..\Oqtane.Server\bin\Release\net6.0\publish\wwwroot\Content"
|
rmdir /Q/S "..\Oqtane.Server\bin\Release\net7.0\publish\wwwroot\Content"
|
||||||
setlocal ENABLEDELAYEDEXPANSION
|
setlocal ENABLEDELAYEDEXPANSION
|
||||||
set retain=Oqtane.Modules.Admin.Login,Oqtane.Modules.HtmlText,Templates
|
set retain=Oqtane.Modules.Admin.Login,Oqtane.Modules.HtmlText,Templates
|
||||||
for /D %%i in ("..\Oqtane.Server\bin\Release\net6.0\publish\wwwroot\Modules\*") do (
|
for /D %%i in ("..\Oqtane.Server\bin\Release\net7.0\publish\wwwroot\Modules\*") do (
|
||||||
set /A found=0
|
set /A found=0
|
||||||
for %%j in (%retain%) do (
|
for %%j in (%retain%) do (
|
||||||
if "%%~nxi" == "%%j" set /A found=1
|
if "%%~nxi" == "%%j" set /A found=1
|
||||||
@ -23,18 +23,18 @@ if "%%~nxi" == "%%j" set /A found=1
|
|||||||
if not !found! == 1 rmdir /Q/S "%%i"
|
if not !found! == 1 rmdir /Q/S "%%i"
|
||||||
)
|
)
|
||||||
set retain=Oqtane.Themes.BlazorTheme,Oqtane.Themes.OqtaneTheme,Templates
|
set retain=Oqtane.Themes.BlazorTheme,Oqtane.Themes.OqtaneTheme,Templates
|
||||||
for /D %%i in ("..\Oqtane.Server\bin\Release\net6.0\publish\wwwroot\Themes\*") do (
|
for /D %%i in ("..\Oqtane.Server\bin\Release\net7.0\publish\wwwroot\Themes\*") do (
|
||||||
set /A found=0
|
set /A found=0
|
||||||
for %%j in (%retain%) do (
|
for %%j in (%retain%) do (
|
||||||
if "%%~nxi" == "%%j" set /A found=1
|
if "%%~nxi" == "%%j" set /A found=1
|
||||||
)
|
)
|
||||||
if not !found! == 1 rmdir /Q/S "%%i"
|
if not !found! == 1 rmdir /Q/S "%%i"
|
||||||
)
|
)
|
||||||
del "..\Oqtane.Server\bin\Release\net6.0\publish\appsettings.json"
|
del "..\Oqtane.Server\bin\Release\net7.0\publish\appsettings.json"
|
||||||
ren "..\Oqtane.Server\bin\Release\net6.0\publish\appsettings.release.json" "appsettings.json"
|
ren "..\Oqtane.Server\bin\Release\net7.0\publish\appsettings.release.json" "appsettings.json"
|
||||||
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ".\install.ps1"
|
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ".\install.ps1"
|
||||||
del "..\Oqtane.Server\bin\Release\net6.0\publish\appsettings.json"
|
del "..\Oqtane.Server\bin\Release\net7.0\publish\appsettings.json"
|
||||||
del "..\Oqtane.Server\bin\Release\net6.0\publish\web.config"
|
del "..\Oqtane.Server\bin\Release\net7.0\publish\web.config"
|
||||||
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ".\upgrade.ps1"
|
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ".\upgrade.ps1"
|
||||||
dotnet clean -c Release ..\Oqtane.Updater.sln
|
dotnet clean -c Release ..\Oqtane.Updater.sln
|
||||||
dotnet build -c Release ..\Oqtane.Updater.sln
|
dotnet build -c Release ..\Oqtane.Updater.sln
|
||||||
|
@ -1 +1 @@
|
|||||||
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net6.0\publish\*" -DestinationPath "Oqtane.Framework.3.4.1.Upgrade.zip" -Force
|
Compress-Archive -Path "..\Oqtane.Server\bin\Release\net7.0\publish\*" -DestinationPath "Oqtane.Framework.4.0.0.Upgrade.zip" -Force
|
@ -33,8 +33,10 @@ namespace Oqtane.Controllers
|
|||||||
private readonly IHttpContextAccessor _accessor;
|
private readonly IHttpContextAccessor _accessor;
|
||||||
private readonly IAliasRepository _aliases;
|
private readonly IAliasRepository _aliases;
|
||||||
private readonly ILogger<InstallationController> _filelogger;
|
private readonly ILogger<InstallationController> _filelogger;
|
||||||
|
private readonly ITenantManager _tenantManager;
|
||||||
|
private readonly ServerStateManager _serverState;
|
||||||
|
|
||||||
public InstallationController(IConfigManager configManager, IInstallationManager installationManager, IDatabaseManager databaseManager, ILocalizationManager localizationManager, IMemoryCache cache, IHttpContextAccessor accessor, IAliasRepository aliases, ILogger<InstallationController> filelogger)
|
public InstallationController(IConfigManager configManager, IInstallationManager installationManager, IDatabaseManager databaseManager, ILocalizationManager localizationManager, IMemoryCache cache, IHttpContextAccessor accessor, IAliasRepository aliases, ILogger<InstallationController> filelogger, ITenantManager tenantManager, ServerStateManager serverState)
|
||||||
{
|
{
|
||||||
_configManager = configManager;
|
_configManager = configManager;
|
||||||
_installationManager = installationManager;
|
_installationManager = installationManager;
|
||||||
@ -44,6 +46,8 @@ namespace Oqtane.Controllers
|
|||||||
_accessor = accessor;
|
_accessor = accessor;
|
||||||
_aliases = aliases;
|
_aliases = aliases;
|
||||||
_filelogger = filelogger;
|
_filelogger = filelogger;
|
||||||
|
_tenantManager = tenantManager;
|
||||||
|
_serverState = serverState;
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST api/<controller>
|
// POST api/<controller>
|
||||||
@ -115,82 +119,56 @@ namespace Oqtane.Controllers
|
|||||||
|
|
||||||
private List<ClientAssembly> GetAssemblyList()
|
private List<ClientAssembly> GetAssemblyList()
|
||||||
{
|
{
|
||||||
return _cache.GetOrCreate("assemblieslist", entry =>
|
int siteId = _tenantManager.GetAlias().SiteId;
|
||||||
|
|
||||||
|
return _cache.GetOrCreate($"assemblieslist:{siteId}", entry =>
|
||||||
{
|
{
|
||||||
var binFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
var binFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
||||||
var assemblyList = new List<ClientAssembly>();
|
var assemblyList = new List<ClientAssembly>();
|
||||||
|
|
||||||
// get list of assemblies which should be downloaded to client
|
// testmode setting is used for validating that the API is downloading the appropriate assemblies to the client
|
||||||
var assemblies = AppDomain.CurrentDomain.GetOqtaneClientAssemblies();
|
bool hashfilename = true;
|
||||||
var list = assemblies.Select(a => a.GetName().Name).ToList();
|
if (_configManager.GetSetting($"{SettingKeys.TestModeKey}", "false") == "true")
|
||||||
|
|
||||||
// populate assemblies
|
|
||||||
for (int i = 0; i < list.Count; i++)
|
|
||||||
{
|
{
|
||||||
assemblyList.Add(new ClientAssembly(Path.Combine(binFolder, list[i] + ".dll")));
|
hashfilename = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get site assemblies which should be downloaded to client
|
||||||
|
var assemblies = _serverState.GetServerState(siteId).Assemblies;
|
||||||
|
|
||||||
|
// populate assembly list
|
||||||
|
foreach (var assembly in assemblies)
|
||||||
|
{
|
||||||
|
if (assembly != Constants.ClientId)
|
||||||
|
{
|
||||||
|
var filepath = Path.Combine(binFolder, assembly) + ".dll";
|
||||||
|
if (System.IO.File.Exists(filepath))
|
||||||
|
{
|
||||||
|
assemblyList.Add(new ClientAssembly(Path.Combine(binFolder, assembly + ".dll"), hashfilename));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert satellite assemblies at beginning of list
|
// insert satellite assemblies at beginning of list
|
||||||
foreach (var culture in _localizationManager.GetInstalledCultures())
|
foreach (var culture in _localizationManager.GetInstalledCultures())
|
||||||
{
|
{
|
||||||
var assembliesFolderPath = Path.Combine(binFolder, culture);
|
if (culture != Constants.DefaultCulture)
|
||||||
if (culture == Constants.DefaultCulture)
|
|
||||||
{
|
{
|
||||||
continue;
|
var assembliesFolderPath = Path.Combine(binFolder, culture);
|
||||||
}
|
if (Directory.Exists(assembliesFolderPath))
|
||||||
|
|
||||||
if (Directory.Exists(assembliesFolderPath))
|
|
||||||
{
|
|
||||||
foreach (var resourceFile in Directory.EnumerateFiles(assembliesFolderPath))
|
|
||||||
{
|
{
|
||||||
assemblyList.Insert(0, new ClientAssembly(resourceFile));
|
foreach (var assembly in assemblies)
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_filelogger.LogError(Utilities.LogMessage(this, $"The Satellite Assembly Folder For {culture} Does Not Exist"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert module and theme dependencies at beginning of list
|
|
||||||
foreach (var assembly in assemblies)
|
|
||||||
{
|
|
||||||
foreach (var type in assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(IModule))))
|
|
||||||
{
|
|
||||||
var instance = Activator.CreateInstance(type) as IModule;
|
|
||||||
foreach (string name in instance.ModuleDefinition.Dependencies.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Reverse())
|
|
||||||
{
|
|
||||||
var filepath = Path.Combine(binFolder, name + ".dll");
|
|
||||||
if (System.IO.File.Exists(filepath))
|
|
||||||
{
|
{
|
||||||
if (!assemblyList.Exists(item => item.FilePath == filepath))
|
var filepath = Path.Combine(assembliesFolderPath, assembly) + ".resources.dll";
|
||||||
|
if (System.IO.File.Exists(filepath))
|
||||||
{
|
{
|
||||||
assemblyList.Insert(0, new ClientAssembly(filepath));
|
assemblyList.Insert(0, new ClientAssembly(Path.Combine(assembliesFolderPath, assembly + ".resources.dll"), hashfilename));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
_filelogger.LogError(Utilities.LogMessage(this, $"Module {instance.ModuleDefinition.ModuleDefinitionName} Dependency {name}.dll Does Not Exist"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
foreach (var type in assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(ITheme))))
|
|
||||||
{
|
|
||||||
var instance = Activator.CreateInstance(type) as ITheme;
|
|
||||||
foreach (string name in instance.Theme.Dependencies.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Reverse())
|
|
||||||
{
|
{
|
||||||
var filepath = Path.Combine(binFolder, name + ".dll");
|
_filelogger.LogError(Utilities.LogMessage(this, $"The Satellite Assembly Folder For {culture} Does Not Exist"));
|
||||||
if (System.IO.File.Exists(filepath))
|
|
||||||
{
|
|
||||||
if (!assemblyList.Exists(item => item.FilePath == filepath))
|
|
||||||
{
|
|
||||||
assemblyList.Insert(0, new ClientAssembly(filepath));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_filelogger.LogError(Utilities.LogMessage(this, $"Theme {instance.Theme.ThemeName} Dependency {name}.dll Does Not Exist"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -233,21 +211,24 @@ namespace Oqtane.Controllers
|
|||||||
{
|
{
|
||||||
foreach (var assembly in assemblies)
|
foreach (var assembly in assemblies)
|
||||||
{
|
{
|
||||||
if (System.IO.File.Exists(assembly.FilePath))
|
if (Path.GetFileNameWithoutExtension(assembly.FilePath) != Constants.ClientId)
|
||||||
{
|
{
|
||||||
using (var filestream = new FileStream(assembly.FilePath, FileMode.Open, FileAccess.Read))
|
if (System.IO.File.Exists(assembly.FilePath))
|
||||||
using (var entrystream = archive.CreateEntry(assembly.HashedName).Open())
|
|
||||||
{
|
{
|
||||||
filestream.CopyTo(entrystream);
|
using (var filestream = new FileStream(assembly.FilePath, FileMode.Open, FileAccess.Read))
|
||||||
|
using (var entrystream = archive.CreateEntry(assembly.HashedName).Open())
|
||||||
|
{
|
||||||
|
filestream.CopyTo(entrystream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
var pdb = assembly.FilePath.Replace(".dll", ".pdb");
|
||||||
var pdb = assembly.FilePath.Replace(".dll", ".pdb");
|
if (System.IO.File.Exists(pdb))
|
||||||
if (System.IO.File.Exists(pdb))
|
|
||||||
{
|
|
||||||
using (var filestream = new FileStream(pdb, FileMode.Open, FileAccess.Read))
|
|
||||||
using (var entrystream = archive.CreateEntry(assembly.HashedName.Replace(".dll", ".pdb")).Open())
|
|
||||||
{
|
{
|
||||||
filestream.CopyTo(entrystream);
|
using (var filestream = new FileStream(pdb, FileMode.Open, FileAccess.Read))
|
||||||
|
using (var entrystream = archive.CreateEntry(assembly.HashedName.Replace(".dll", ".pdb")).Open())
|
||||||
|
{
|
||||||
|
filestream.CopyTo(entrystream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -285,11 +266,18 @@ namespace Oqtane.Controllers
|
|||||||
|
|
||||||
public struct ClientAssembly
|
public struct ClientAssembly
|
||||||
{
|
{
|
||||||
public ClientAssembly(string filepath)
|
public ClientAssembly(string filepath, bool hashfilename)
|
||||||
{
|
{
|
||||||
FilePath = filepath;
|
FilePath = filepath;
|
||||||
DateTime lastwritetime = System.IO.File.GetLastWriteTime(filepath);
|
DateTime lastwritetime = System.IO.File.GetLastWriteTime(filepath);
|
||||||
HashedName = GetDeterministicHashCode(filepath).ToString("X8") + "." + lastwritetime.ToString("yyyyMMddHHmmss") + Path.GetExtension(filepath);
|
if (hashfilename)
|
||||||
|
{
|
||||||
|
HashedName = GetDeterministicHashCode(filepath).ToString("X8") + "." + lastwritetime.ToString("yyyyMMddHHmmss") + Path.GetExtension(filepath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HashedName = Path.GetFileNameWithoutExtension(filepath) + "." + lastwritetime.ToString("yyyyMMddHHmmss") + Path.GetExtension(filepath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string FilePath { get; private set; }
|
public string FilePath { get; private set; }
|
||||||
|
@ -9,6 +9,7 @@ using Oqtane.Infrastructure;
|
|||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
using Oqtane.Security;
|
using Oqtane.Security;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Security.Policy;
|
||||||
|
|
||||||
namespace Oqtane.Controllers
|
namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
@ -75,7 +76,7 @@ namespace Oqtane.Controllers
|
|||||||
module.Order = pagemodule.Order;
|
module.Order = pagemodule.Order;
|
||||||
module.ContainerType = pagemodule.ContainerType;
|
module.ContainerType = pagemodule.ContainerType;
|
||||||
|
|
||||||
module.ModuleDefinition = FilterModuleDefinition(moduledefinitions.Find(item => item.ModuleDefinitionName == module.ModuleDefinitionName));
|
module.ModuleDefinition = _moduleDefinitions.FilterModuleDefinition(moduledefinitions.Find(item => item.ModuleDefinitionName == module.ModuleDefinitionName));
|
||||||
|
|
||||||
module.Settings = settings.Where(item => item.EntityId == pagemodule.ModuleId)
|
module.Settings = settings.Where(item => item.EntityId == pagemodule.ModuleId)
|
||||||
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, pagemodule.Module.PermissionList))
|
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, pagemodule.Module.PermissionList))
|
||||||
@ -83,6 +84,7 @@ namespace Oqtane.Controllers
|
|||||||
|
|
||||||
modules.Add(module);
|
modules.Add(module);
|
||||||
}
|
}
|
||||||
|
modules = modules.OrderBy(item => item.PageId).ThenBy(item => item.Pane).ThenBy(item => item.Order).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -95,29 +97,6 @@ namespace Oqtane.Controllers
|
|||||||
return modules;
|
return modules;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ModuleDefinition FilterModuleDefinition(ModuleDefinition moduleDefinition)
|
|
||||||
{
|
|
||||||
if (moduleDefinition != null)
|
|
||||||
{
|
|
||||||
moduleDefinition.Description = "";
|
|
||||||
moduleDefinition.Categories = "";
|
|
||||||
moduleDefinition.Version = "";
|
|
||||||
moduleDefinition.Owner = "";
|
|
||||||
moduleDefinition.Url = "";
|
|
||||||
moduleDefinition.Contact = "";
|
|
||||||
moduleDefinition.License = "";
|
|
||||||
moduleDefinition.Dependencies = "";
|
|
||||||
moduleDefinition.PermissionNames = "";
|
|
||||||
moduleDefinition.ServerManagerType = "";
|
|
||||||
moduleDefinition.ReleaseVersions = "";
|
|
||||||
moduleDefinition.PackageName = "";
|
|
||||||
moduleDefinition.AssemblyName = "";
|
|
||||||
moduleDefinition.PermissionList = null;
|
|
||||||
moduleDefinition.Template = "";
|
|
||||||
}
|
|
||||||
return moduleDefinition;
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET api/<controller>/5
|
// GET api/<controller>/5
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
public Module Get(int id)
|
public Module Get(int id)
|
||||||
@ -126,7 +105,7 @@ namespace Oqtane.Controllers
|
|||||||
if (module != null && module.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User,PermissionNames.View, module.PermissionList))
|
if (module != null && module.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User,PermissionNames.View, module.PermissionList))
|
||||||
{
|
{
|
||||||
List<ModuleDefinition> moduledefinitions = _moduleDefinitions.GetModuleDefinitions(module.SiteId).ToList();
|
List<ModuleDefinition> moduledefinitions = _moduleDefinitions.GetModuleDefinitions(module.SiteId).ToList();
|
||||||
module.ModuleDefinition = FilterModuleDefinition(moduledefinitions.Find(item => item.ModuleDefinitionName == module.ModuleDefinitionName));
|
module.ModuleDefinition = _moduleDefinitions.FilterModuleDefinition(moduledefinitions.Find(item => item.ModuleDefinitionName == module.ModuleDefinitionName));
|
||||||
module.Settings = _settings.GetSettings(EntityNames.Module, id)
|
module.Settings = _settings.GetSettings(EntityNames.Module, id)
|
||||||
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, module.PermissionList))
|
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, module.PermissionList))
|
||||||
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
|
.ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
|
||||||
|
@ -123,14 +123,14 @@ namespace Oqtane.Controllers
|
|||||||
if (moduleDefinition.Template.ToLower().Contains("internal"))
|
if (moduleDefinition.Template.ToLower().Contains("internal"))
|
||||||
{
|
{
|
||||||
rootPath = Utilities.PathCombine(rootFolder.FullName, Path.DirectorySeparatorChar.ToString());
|
rootPath = Utilities.PathCombine(rootFolder.FullName, Path.DirectorySeparatorChar.ToString());
|
||||||
moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + ", Oqtane.Client";
|
moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + ".Module." + moduleDefinition.Name + ", Oqtane.Client";
|
||||||
moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + ".Manager." + moduleDefinition.Name + "Manager, Oqtane.Server";
|
moduleDefinition.ServerManagerType = moduleDefinition.Owner + ".Module." + moduleDefinition.Name + ".Manager." + moduleDefinition.Name + "Manager, Oqtane.Server";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rootPath = Utilities.PathCombine(rootFolder.Parent.FullName, moduleDefinition.Owner + "." + moduleDefinition.Name, Path.DirectorySeparatorChar.ToString());
|
rootPath = Utilities.PathCombine(rootFolder.Parent.FullName, moduleDefinition.Owner + ".Module." + moduleDefinition.Name, Path.DirectorySeparatorChar.ToString());
|
||||||
moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + ", " + moduleDefinition.Owner + "." + moduleDefinition.Name + ".Client.Oqtane";
|
moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + ".Module." + moduleDefinition.Name + ", " + moduleDefinition.Owner + ".Module." + moduleDefinition.Name + ".Client.Oqtane";
|
||||||
moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + ".Manager." + moduleDefinition.Name + "Manager, " + moduleDefinition.Owner + "." + moduleDefinition.Name + ".Server.Oqtane";
|
moduleDefinition.ServerManagerType = moduleDefinition.Owner + ".Module." + moduleDefinition.Name + ".Manager." + moduleDefinition.Name + "Manager, " + moduleDefinition.Owner + ".Module." + moduleDefinition.Name + ".Server.Oqtane";
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessTemplatesRecursively(new DirectoryInfo(templatePath), rootPath, rootFolder.Name, templatePath, moduleDefinition);
|
ProcessTemplatesRecursively(new DirectoryInfo(templatePath), rootPath, rootFolder.Name, templatePath, moduleDefinition);
|
||||||
@ -255,10 +255,10 @@ namespace Oqtane.Controllers
|
|||||||
_modules.DeleteModule(moduleToRemove.ModuleId);
|
_modules.DeleteModule(moduleToRemove.ModuleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// remove module definition
|
// remove module definition
|
||||||
_moduleDefinitions.DeleteModuleDefinition(id);
|
_moduleDefinitions.DeleteModuleDefinition(id);
|
||||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.ModuleDefinition, moduledefinition.ModuleDefinitionId, SyncEventActions.Delete);
|
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.ModuleDefinition, moduledefinition.ModuleDefinitionId, SyncEventActions.Delete);
|
||||||
|
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, moduledefinition.SiteId, SyncEventActions.Refresh);
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Definition {ModuleDefinitionName} Deleted", moduledefinition.Name);
|
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Module Definition {ModuleDefinitionName} Deleted", moduledefinition.Name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -268,14 +268,6 @@ namespace Oqtane.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("install")]
|
|
||||||
[Authorize(Roles = RoleNames.Host)]
|
|
||||||
public void InstallModules()
|
|
||||||
{
|
|
||||||
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Modules Installed");
|
|
||||||
_installationManager.InstallPackages();
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET: api/<controller>/templates
|
// GET: api/<controller>/templates
|
||||||
[HttpGet("templates")]
|
[HttpGet("templates")]
|
||||||
[Authorize(Roles = RoleNames.Host)]
|
[Authorize(Roles = RoleNames.Host)]
|
||||||
@ -339,9 +331,9 @@ namespace Oqtane.Controllers
|
|||||||
if (moduleDefinition.Version == "local")
|
if (moduleDefinition.Version == "local")
|
||||||
{
|
{
|
||||||
text = text.Replace("[FrameworkVersion]", Constants.Version);
|
text = text.Replace("[FrameworkVersion]", Constants.Version);
|
||||||
text = text.Replace("[ClientReference]", $"<Reference Include=\"Oqtane.Client\"><HintPath>..\\..\\{rootFolder}\\Oqtane.Server\\bin\\Debug\\net6.0\\Oqtane.Client.dll</HintPath></Reference>");
|
text = text.Replace("[ClientReference]", $"<Reference Include=\"Oqtane.Client\"><HintPath>..\\..\\{rootFolder}\\Oqtane.Server\\bin\\Debug\\net7.0\\Oqtane.Client.dll</HintPath></Reference>");
|
||||||
text = text.Replace("[ServerReference]", $"<Reference Include=\"Oqtane.Server\"><HintPath>..\\..\\{rootFolder}\\Oqtane.Server\\bin\\Debug\\net6.0\\Oqtane.Server.dll</HintPath></Reference>");
|
text = text.Replace("[ServerReference]", $"<Reference Include=\"Oqtane.Server\"><HintPath>..\\..\\{rootFolder}\\Oqtane.Server\\bin\\Debug\\net7.0\\Oqtane.Server.dll</HintPath></Reference>");
|
||||||
text = text.Replace("[SharedReference]", $"<Reference Include=\"Oqtane.Shared\"><HintPath>..\\..\\{rootFolder}\\Oqtane.Server\\bin\\Debug\\net6.0\\Oqtane.Shared.dll</HintPath></Reference>");
|
text = text.Replace("[SharedReference]", $"<Reference Include=\"Oqtane.Shared\"><HintPath>..\\..\\{rootFolder}\\Oqtane.Server\\bin\\Debug\\net7.0\\Oqtane.Shared.dll</HintPath></Reference>");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -10,6 +10,8 @@ using Oqtane.Enums;
|
|||||||
using Oqtane.Extensions;
|
using Oqtane.Extensions;
|
||||||
using Oqtane.Infrastructure;
|
using Oqtane.Infrastructure;
|
||||||
using Oqtane.Repository;
|
using Oqtane.Repository;
|
||||||
|
using Oqtane.Modules.Admin.Users;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace Oqtane.Controllers
|
namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
@ -73,20 +75,12 @@ namespace Oqtane.Controllers
|
|||||||
return pages;
|
return pages;
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET api/<controller>/5?userid=x
|
// GET api/<controller>/5
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
public Page Get(int id, string userid)
|
public Page Get(int id)
|
||||||
{
|
{
|
||||||
Page page = null;
|
var page = _pages.GetPage(id);
|
||||||
if (string.IsNullOrEmpty(userid))
|
if (page != null && page.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.View, page.PermissionList))
|
||||||
{
|
|
||||||
page = _pages.GetPage(id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
page = _pages.GetPage(id, int.Parse(userid));
|
|
||||||
}
|
|
||||||
if (page != null && page.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User,PermissionNames.View, page.PermissionList))
|
|
||||||
{
|
{
|
||||||
page.Settings = _settings.GetSettings(EntityNames.Page, page.PageId)
|
page.Settings = _settings.GetSettings(EntityNames.Page, page.PageId)
|
||||||
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, page.PermissionList))
|
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, page.PermissionList))
|
||||||
@ -95,7 +89,7 @@ namespace Oqtane.Controllers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Page Get Attempt {PageId} {UserId}", id, userid);
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Page Get Attempt {PageId}", id);
|
||||||
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -140,7 +134,7 @@ namespace Oqtane.Controllers
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_userPermissions.IsAuthorized(User,PermissionNames.Edit, permissions))
|
if (_userPermissions.IsAuthorized(User, PermissionNames.Edit, permissions))
|
||||||
{
|
{
|
||||||
page = _pages.AddPage(page);
|
page = _pages.AddPage(page);
|
||||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Page, page.PageId, SyncEventActions.Create);
|
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Page, page.PageId, SyncEventActions.Create);
|
||||||
@ -180,29 +174,30 @@ namespace Oqtane.Controllers
|
|||||||
{
|
{
|
||||||
Page page = null;
|
Page page = null;
|
||||||
Page parent = _pages.GetPage(id);
|
Page parent = _pages.GetPage(id);
|
||||||
if (parent != null && parent.SiteId == _alias.SiteId && parent.IsPersonalizable && _userPermissions.GetUser(User).UserId == int.Parse(userid))
|
User user = _userPermissions.GetUser(User);
|
||||||
|
if (parent != null && parent.SiteId == _alias.SiteId && parent.IsPersonalizable && user.UserId == int.Parse(userid))
|
||||||
{
|
{
|
||||||
page = new Page();
|
page = new Page();
|
||||||
page.SiteId = parent.SiteId;
|
page.SiteId = parent.SiteId;
|
||||||
page.Name = parent.Name;
|
|
||||||
page.Title = parent.Title;
|
|
||||||
page.Path = parent.Path;
|
|
||||||
page.ParentId = parent.PageId;
|
page.ParentId = parent.PageId;
|
||||||
|
page.Name = user.Username;
|
||||||
|
page.Path = parent.Path + "/" + page.Name;
|
||||||
|
page.Title = parent.Name + " - " + page.Name;
|
||||||
page.Order = 0;
|
page.Order = 0;
|
||||||
page.IsNavigation = false;
|
page.IsNavigation = false;
|
||||||
page.Url = "";
|
page.Url = "";
|
||||||
page.ThemeType = parent.ThemeType;
|
page.ThemeType = parent.ThemeType;
|
||||||
page.DefaultContainerType = parent.DefaultContainerType;
|
page.DefaultContainerType = parent.DefaultContainerType;
|
||||||
page.Icon = parent.Icon;
|
page.Icon = parent.Icon;
|
||||||
page.PermissionList = new List<Permission> {
|
page.PermissionList = new List<Permission>()
|
||||||
|
{
|
||||||
new Permission(PermissionNames.View, int.Parse(userid), true),
|
new Permission(PermissionNames.View, int.Parse(userid), true),
|
||||||
|
new Permission(PermissionNames.View, RoleNames.Everyone, true),
|
||||||
new Permission(PermissionNames.Edit, int.Parse(userid), true)
|
new Permission(PermissionNames.Edit, int.Parse(userid), true)
|
||||||
};
|
};
|
||||||
page.IsPersonalizable = false;
|
page.IsPersonalizable = false;
|
||||||
page.UserId = int.Parse(userid);
|
page.UserId = int.Parse(userid);
|
||||||
page = _pages.AddPage(page);
|
page = _pages.AddPage(page);
|
||||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Page, page.PageId, SyncEventActions.Create);
|
|
||||||
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, page.SiteId, SyncEventActions.Refresh);
|
|
||||||
|
|
||||||
// copy modules
|
// copy modules
|
||||||
List<PageModule> pagemodules = _pageModules.GetPageModules(page.SiteId).ToList();
|
List<PageModule> pagemodules = _pageModules.GetPageModules(page.SiteId).ToList();
|
||||||
@ -213,8 +208,10 @@ namespace Oqtane.Controllers
|
|||||||
module.PageId = page.PageId;
|
module.PageId = page.PageId;
|
||||||
module.ModuleDefinitionName = pm.Module.ModuleDefinitionName;
|
module.ModuleDefinitionName = pm.Module.ModuleDefinitionName;
|
||||||
module.AllPages = false;
|
module.AllPages = false;
|
||||||
module.PermissionList = new List<Permission> {
|
module.PermissionList = new List<Permission>()
|
||||||
|
{
|
||||||
new Permission(PermissionNames.View, int.Parse(userid), true),
|
new Permission(PermissionNames.View, int.Parse(userid), true),
|
||||||
|
new Permission(PermissionNames.View, RoleNames.Everyone, true),
|
||||||
new Permission(PermissionNames.Edit, int.Parse(userid), true)
|
new Permission(PermissionNames.Edit, int.Parse(userid), true)
|
||||||
};
|
};
|
||||||
module = _modules.AddModule(module);
|
module = _modules.AddModule(module);
|
||||||
@ -235,6 +232,9 @@ namespace Oqtane.Controllers
|
|||||||
|
|
||||||
_pageModules.AddPageModule(pagemodule);
|
_pageModules.AddPageModule(pagemodule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Page, page.PageId, SyncEventActions.Create);
|
||||||
|
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, page.SiteId, SyncEventActions.Refresh);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -284,7 +284,7 @@ namespace Oqtane.Controllers
|
|||||||
{
|
{
|
||||||
var modulePermissions = _permissionRepository.GetPermissions(pageModule.Module.SiteId, EntityNames.Module, pageModule.Module.ModuleId).ToList();
|
var modulePermissions = _permissionRepository.GetPermissions(pageModule.Module.SiteId, EntityNames.Module, pageModule.Module.ModuleId).ToList();
|
||||||
// permissions added
|
// permissions added
|
||||||
foreach(Permission permission in added)
|
foreach (Permission permission in added)
|
||||||
{
|
{
|
||||||
if (!modulePermissions.Any(item => item.PermissionName == permission.PermissionName
|
if (!modulePermissions.Any(item => item.PermissionName == permission.PermissionName
|
||||||
&& item.RoleId == permission.RoleId && item.UserId == permission.UserId && item.IsAuthorized == permission.IsAuthorized))
|
&& item.RoleId == permission.RoleId && item.UserId == permission.UserId && item.IsAuthorized == permission.IsAuthorized))
|
||||||
@ -345,7 +345,7 @@ namespace Oqtane.Controllers
|
|||||||
[Authorize(Roles = RoleNames.Registered)]
|
[Authorize(Roles = RoleNames.Registered)]
|
||||||
public void Put(int siteid, int pageid, int? parentid)
|
public void Put(int siteid, int pageid, int? parentid)
|
||||||
{
|
{
|
||||||
if (siteid == _alias.SiteId && siteid == _alias.SiteId && _pages.GetPage(pageid, false) != null && _userPermissions.IsAuthorized(User, siteid, EntityNames.Page, pageid, PermissionNames.Edit))
|
if (siteid == _alias.SiteId && _pages.GetPage(pageid, false) != null && _userPermissions.IsAuthorized(User, siteid, EntityNames.Page, pageid, PermissionNames.Edit))
|
||||||
{
|
{
|
||||||
int order = 1;
|
int order = 1;
|
||||||
List<Page> pages = _pages.GetPages(siteid).ToList();
|
List<Page> pages = _pages.GetPages(siteid).ToList();
|
||||||
|
@ -200,6 +200,8 @@ namespace Oqtane.Controllers
|
|||||||
case EntityNames.Tenant:
|
case EntityNames.Tenant:
|
||||||
case EntityNames.ModuleDefinition:
|
case EntityNames.ModuleDefinition:
|
||||||
case EntityNames.Host:
|
case EntityNames.Host:
|
||||||
|
case EntityNames.Job:
|
||||||
|
case EntityNames.Theme:
|
||||||
if (permissionName == PermissionNames.Edit)
|
if (permissionName == PermissionNames.Edit)
|
||||||
{
|
{
|
||||||
authorized = User.IsInRole(RoleNames.Host);
|
authorized = User.IsInRole(RoleNames.Host);
|
||||||
@ -262,6 +264,8 @@ namespace Oqtane.Controllers
|
|||||||
case EntityNames.Tenant:
|
case EntityNames.Tenant:
|
||||||
case EntityNames.ModuleDefinition:
|
case EntityNames.ModuleDefinition:
|
||||||
case EntityNames.Host:
|
case EntityNames.Host:
|
||||||
|
case EntityNames.Job:
|
||||||
|
case EntityNames.Theme:
|
||||||
filter = !User.IsInRole(RoleNames.Host);
|
filter = !User.IsInRole(RoleNames.Host);
|
||||||
break;
|
break;
|
||||||
case EntityNames.Site:
|
case EntityNames.Site:
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user