- @if (!string.IsNullOrEmpty(p.Options))
+ @if (!string.IsNullOrEmpty(p.Options))
{
-
ProfileChanged(e, p.Name))">
- @foreach (var option in p.Options.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
- {
- @if (GetProfileValue(p.Name, "") == option || (GetProfileValue(p.Name, "") == "" && p.DefaultValue == option))
+ @if (!string.IsNullOrEmpty(p.Autocomplete))
+ {
+ ProfileChanged(e, p.Name))" autocomplete="@p.Autocomplete">
+ @foreach (var option in p.Options.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
- @option
+ @if (GetProfileValue(p.Name, "") == option || (GetProfileValue(p.Name, "") == "" && p.DefaultValue == option))
+ {
+ @option
+ }
+ else
+ {
+ @option
+ }
}
- else
+
+ }
+ else
+ {
+ ProfileChanged(e, p.Name))">
+ @foreach (var option in p.Options.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
- @option
+ @if (GetProfileValue(p.Name, "") == option || (GetProfileValue(p.Name, "") == "" && p.DefaultValue == option))
+ {
+ @option
+ }
+ else
+ {
+ @option
+ }
}
- }
-
+
+ }
}
else
{
@if (p.Rows == 1)
{
- @if (p.IsRequired)
+ if (!string.IsNullOrEmpty(p.Autocomplete))
{
-
ProfileChanged(e, p.Name))" />
+ @if (p.IsRequired)
+ {
+
ProfileChanged(e, p.Name))" autocomplete="@p.Autocomplete" />
+ }
+ else
+ {
+
ProfileChanged(e, p.Name))" autocomplete="@p.Autocomplete" />
+ }
}
else
{
-
ProfileChanged(e, p.Name))" />
+ @if (p.IsRequired)
+ {
+
ProfileChanged(e, p.Name))" />
+ }
+ else
+ {
+
ProfileChanged(e, p.Name))" />
+ }
}
}
else
{
- @if (p.IsRequired)
+ if (!string.IsNullOrEmpty(p.Autocomplete))
{
-
+ @if (p.IsRequired)
+ {
+
+ }
+ else
+ {
+
+ }
}
else
{
-
+ @if (p.IsRequired)
+ {
+
+ }
+ else
+ {
+
+ }
}
}
}
@@ -360,10 +407,11 @@
photofileid = -1;
photo = null;
}
- var sitesettings = await SettingService.GetSiteSettingsAsync(SiteState.Alias.SiteId);
- _ImageFiles = SettingService.GetSetting(settings, "ImageFiles", Constants.ImageFiles);
settings = await SettingService.GetUserSettingsAsync(PageState.User.UserId);
+ var sitesettings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
+ _ImageFiles = SettingService.GetSetting(settings, "ImageFiles", Constants.ImageFiles);
+ _ImageFiles = (string.IsNullOrEmpty(_ImageFiles)) ? Constants.ImageFiles : _ImageFiles;
await LoadNotificationsAsync();
@@ -561,12 +609,12 @@
await NotificationService.DeleteNotificationAsync(Notification.NotificationId);
}
await logger.LogInformation("Notification Deleted {Notification}", Notification);
- }
+ }
await logger.LogInformation("Notifications Permanently Deleted");
await LoadNotificationsAsync();
ModuleInstance.HideProgressIndicator();
- StateHasChanged();
+ StateHasChanged();
}
catch (Exception ex)
{
@@ -574,21 +622,19 @@
AddModuleMessage(ex.Message, MessageType.Error);
ModuleInstance.HideProgressIndicator();
}
-
}
private void TogglePassword()
- {
- if (_passwordtype == "password")
- {
- _passwordtype = "text";
- _togglepassword = SharedLocalizer["HidePassword"];
- }
- else
- {
- _passwordtype = "password";
- _togglepassword = SharedLocalizer["ShowPassword"];
- }
- }
-
+ {
+ if (_passwordtype == "password")
+ {
+ _passwordtype = "text";
+ _togglepassword = SharedLocalizer["HidePassword"];
+ }
+ else
+ {
+ _passwordtype = "password";
+ _togglepassword = SharedLocalizer["ShowPassword"];
+ }
+ }
}
diff --git a/Oqtane.Client/Modules/Admin/Users/Roles.razor b/Oqtane.Client/Modules/Admin/Users/Roles.razor
index 8766c46a..8d65480a 100644
--- a/Oqtane.Client/Modules/Admin/Users/Roles.razor
+++ b/Oqtane.Client/Modules/Admin/Users/Roles.razor
@@ -34,13 +34,13 @@ else
@@ -60,8 +60,8 @@ else
@context.Role.Name
- @context.EffectiveDate
- @context.ExpiryDate
+ @Utilities.UtcAsLocalDate(context.EffectiveDate)
+ @Utilities.UtcAsLocalDate(context.ExpiryDate)
@@ -75,8 +75,8 @@ else
private string name = string.Empty;
private List roles;
private int roleid = -1;
- private DateTime? effectivedate = null;
- private DateTime? expirydate = null;
+ private DateTime? _effectivedate = null;
+ private DateTime? _expirydate = null;
private List userroles;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
@@ -92,7 +92,7 @@ else
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
{
roles = await RoleService.GetRolesAsync(PageState.Site.SiteId, true);
- roles.RemoveAll(item => item.Name == RoleNames.Everyone || item.Name == RoleNames.Unauthenticated);
+ roles.RemoveAll(item => item.Name == RoleNames.Everyone || item.Name == RoleNames.Unauthenticated);
}
else
{
@@ -113,6 +113,7 @@ else
try
{
userroles = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, userid);
+
}
catch (Exception ex)
{
@@ -127,11 +128,16 @@ else
{
if (roleid != -1)
{
+ if (!Utilities.ValidateEffectiveExpiryDates(_effectivedate, _expirydate))
+ {
+ AddModuleMessage(SharedLocalizer["Message.EffectiveExpiryDateError"], MessageType.Warning);
+ return;
+ }
var userrole = userroles.Where(item => item.UserId == userid && item.RoleId == roleid).FirstOrDefault();
if (userrole != null)
{
- userrole.EffectiveDate = effectivedate;
- userrole.ExpiryDate = expirydate;
+ userrole.EffectiveDate = _effectivedate;
+ userrole.ExpiryDate = _expirydate;
await UserRoleService.UpdateUserRoleAsync(userrole);
}
else
@@ -139,15 +145,15 @@ else
userrole = new UserRole();
userrole.UserId = userid;
userrole.RoleId = roleid;
- userrole.EffectiveDate = effectivedate;
- userrole.ExpiryDate = expirydate;
+ userrole.EffectiveDate = Utilities.UtcAsLocalDate(_effectivedate);
+ userrole.ExpiryDate = Utilities.UtcAsLocalDate(_expirydate);
await UserRoleService.AddUserRoleAsync(userrole);
}
await logger.LogInformation("User Assigned To Role {UserRole}", userrole);
AddModuleMessage(Localizer["Success.User.AssignRole"], MessageType.Success);
await GetUserRoles();
- StateHasChanged();
+ StateHasChanged();
}
else
{
diff --git a/Oqtane.Client/Modules/Controls/FileManager.razor b/Oqtane.Client/Modules/Controls/FileManager.razor
index 1bbe4581..a6a863aa 100644
--- a/Oqtane.Client/Modules/Controls/FileManager.razor
+++ b/Oqtane.Client/Modules/Controls/FileManager.razor
@@ -4,6 +4,7 @@
@inject IFolderService FolderService
@inject IFileService FileService
@inject ISettingService SettingService
+@inject IUserService UserService
@inject IStringLocalizer Localizer
@inject IStringLocalizer SharedLocalizer
@@ -344,7 +345,7 @@
_message = string.Empty;
var interop = new Interop(JSRuntime);
var uploads = await interop.GetFiles(_fileinputid);
-
+
if (uploads.Length > 0)
{
string restricted = "";
@@ -370,7 +371,12 @@
// upload the files
var posturl = Utilities.TenantUrl(PageState.Alias, "/api/file/upload");
var folder = (Folder == Constants.PackagesFolder) ? Folder : FolderId.ToString();
- await interop.UploadFiles(posturl, folder, _guid, SiteState.AntiForgeryToken);
+ var jwt = "";
+ if (PageState.Runtime == Shared.Runtime.Hybrid)
+ {
+ jwt = await UserService.GetTokenAsync();
+ }
+ await interop.UploadFiles(posturl, folder, _guid, SiteState.AntiForgeryToken, jwt);
// uploading is asynchronous so we need to poll to determine if uploads are completed
var success = true;
diff --git a/Oqtane.Client/Modules/Controls/RichTextEditor.razor b/Oqtane.Client/Modules/Controls/RichTextEditor.razor
index ad7980d1..61672446 100644
--- a/Oqtane.Client/Modules/Controls/RichTextEditor.razor
+++ b/Oqtane.Client/Modules/Controls/RichTextEditor.razor
@@ -162,27 +162,31 @@
_richhtml = Content;
_rawhtml = Content;
_originalrawhtml = _rawhtml; // preserve for comparison later
+ _originalrichhtml = "";
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
- var interop = new RichTextEditorInterop(JSRuntime);
-
- if (firstRender)
+ if (AllowRichText)
{
- await interop.CreateEditor(
- _editorElement,
- _toolBar,
- ReadOnly,
- Placeholder,
- Theme,
- DebugLevel);
+ var interop = new RichTextEditorInterop(JSRuntime);
+
+ if (firstRender)
+ {
+ await interop.CreateEditor(
+ _editorElement,
+ _toolBar,
+ ReadOnly,
+ Placeholder,
+ Theme,
+ DebugLevel);
+ }
await interop.LoadEditorContent(_editorElement, _richhtml);
- if (AllowRichText)
+ if (string.IsNullOrEmpty(_originalrichhtml))
{
// preserve a copy of the rich text content (Quill sanitizes content so we need to retrieve it from the editor)
_originalrichhtml = await interop.GetHtml(_editorElement);
@@ -256,7 +260,8 @@
{
var interop = new RichTextEditorInterop(JSRuntime);
await interop.InsertImage(_editorElement, file.Url, ((!string.IsNullOrEmpty(file.Description)) ? file.Description : file.Name));
- _richfilemanager = false;
+ _richhtml = await interop.GetHtml(_editorElement);
+ _richfilemanager = false;
}
else
{
diff --git a/Oqtane.Client/Modules/HtmlText/Index.razor b/Oqtane.Client/Modules/HtmlText/Index.razor
index 77f7b95d..91efe2bb 100644
--- a/Oqtane.Client/Modules/HtmlText/Index.razor
+++ b/Oqtane.Client/Modules/HtmlText/Index.razor
@@ -15,17 +15,20 @@
}
@code {
- private string content = "";
+ private string content = "";
- protected override async Task OnParametersSetAsync()
- {
- try
+ protected override async Task OnParametersSetAsync()
+ {
+ try
{
- var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId);
- if (htmltext != null)
+ if (ShouldRender())
{
- content = htmltext.Content;
- content = Utilities.FormatContent(content, PageState.Alias, "render");
+ var htmltext = await HtmlTextService.GetHtmlTextAsync(ModuleState.ModuleId);
+ if (htmltext != null)
+ {
+ content = htmltext.Content;
+ content = Utilities.FormatContent(content, PageState.Alias, "render");
+ }
}
}
catch (Exception ex)
diff --git a/Oqtane.Client/Modules/ModuleBase.cs b/Oqtane.Client/Modules/ModuleBase.cs
index f5c0bef7..05281844 100644
--- a/Oqtane.Client/Modules/ModuleBase.cs
+++ b/Oqtane.Client/Modules/ModuleBase.cs
@@ -113,6 +113,11 @@ namespace Oqtane.Modules
}
}
+ protected override bool ShouldRender()
+ {
+ return PageState?.RenderId == ModuleState?.RenderId;
+ }
+
// path method
public string ModulePath()
@@ -266,6 +271,7 @@ namespace Oqtane.Modules
public void AddModuleMessage(string message, MessageType type, string position)
{
+ ClearModuleMessage();
ModuleInstance.AddModuleMessage(message, type, position);
}
diff --git a/Oqtane.Client/Oqtane.Client.csproj b/Oqtane.Client/Oqtane.Client.csproj
index 880f5e1b..c825a93e 100644
--- a/Oqtane.Client/Oqtane.Client.csproj
+++ b/Oqtane.Client/Oqtane.Client.csproj
@@ -4,7 +4,7 @@
net8.0
Exe
Debug;Release
- 5.0.1
+ 5.0.2
Oqtane
Shaun Walker
.NET Foundation
@@ -12,7 +12,7 @@
.NET Foundation
https://www.oqtane.org
https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE
- https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1
+ https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2
https://github.com/oqtane/oqtane.framework
Git
Oqtane
@@ -21,10 +21,10 @@
-
-
-
-
+
+
+
+
diff --git a/Oqtane.Client/Resources/Modules/Admin/Jobs/Edit.resx b/Oqtane.Client/Resources/Modules/Admin/Jobs/Edit.resx
index facc630b..672f5dc9 100644
--- a/Oqtane.Client/Resources/Modules/Admin/Jobs/Edit.resx
+++ b/Oqtane.Client/Resources/Modules/Admin/Jobs/Edit.resx
@@ -192,4 +192,7 @@
Execute Once
+
+ Start Date cannot be after End Date.
+
\ No newline at end of file
diff --git a/Oqtane.Client/Resources/Modules/Admin/ModuleDefinitions/Create.resx b/Oqtane.Client/Resources/Modules/Admin/ModuleDefinitions/Create.resx
index cac13d97..94942a50 100644
--- a/Oqtane.Client/Resources/Modules/Admin/ModuleDefinitions/Create.resx
+++ b/Oqtane.Client/Resources/Modules/Admin/ModuleDefinitions/Create.resx
@@ -130,16 +130,16 @@
Please Note That The Module Creator Is Only Intended To Be Used In A Development Environment
- You Must Provide A Valid Owner Name And Module Name ( ie. No Punctuation Or Spaces And The Values Cannot Be The Same ) And Choose A Template
+ You Must Provide A Valid Owner Name And Module Name ( ie. No Punctuation Or Spaces And The Values Cannot Be The Same Or Contain The Word "Oqtane" ) And Choose A Template
You Must Provide A Valid Description (ie. No Punctuation)
- Enter the name of the organization who is developing this module. It should not contain spaces or punctuation.
+ Enter the name of the organization who is developing this module. It should not contain spaces or punctuation or contain the word "oqtane".
- Enter a name for this module. It should not contain spaces or punctuation.
+ Enter a name for this module. It should not contain spaces or punctuation or contain the word "oqtane".
Enter a short description for the module
@@ -171,4 +171,4 @@
The Source Code For Your Module Has Been Created At The Location Specified Below And Must Be Compiled In Order To Make It Functional. Once It Has Been Compiled You Must <a href={0}>Restart</a> Your Application To Activate The Module.
-
\ No newline at end of file
+
diff --git a/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx b/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx
index 5b7849ec..722fa2f1 100644
--- a/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx
+++ b/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx
@@ -165,4 +165,16 @@
Pane:
+
+ The date that this module is active
+
+
+ Effective Date:
+
+
+ The date that this module expires
+
+
+ Expiry Date:
+
\ No newline at end of file
diff --git a/Oqtane.Client/Resources/Modules/Admin/Pages/Add.resx b/Oqtane.Client/Resources/Modules/Admin/Pages/Add.resx
index 62972b72..9ebed89a 100644
--- a/Oqtane.Client/Resources/Modules/Admin/Pages/Add.resx
+++ b/Oqtane.Client/Resources/Modules/Admin/Pages/Add.resx
@@ -255,4 +255,16 @@
Theme Settings
+
+ The date that this page is active
+
+
+ Effective Date:
+
+
+ The date that this page expires
+
+
+ Expiry Date:
+
\ No newline at end of file
diff --git a/Oqtane.Client/Resources/Modules/Admin/Pages/Edit.resx b/Oqtane.Client/Resources/Modules/Admin/Pages/Edit.resx
index 984e6461..478e7616 100644
--- a/Oqtane.Client/Resources/Modules/Admin/Pages/Edit.resx
+++ b/Oqtane.Client/Resources/Modules/Admin/Pages/Edit.resx
@@ -285,4 +285,16 @@
Please Note That Overriding The Default Site Theme With An Unrelated Page Theme May Result In Compatibility Issues For Your Site
+
+ The date that this page is active
+
+
+ Effective Date:
+
+
+ The date that this page expires
+
+
+ Expiry Date:
+
\ No newline at end of file
diff --git a/Oqtane.Client/Resources/Modules/Admin/Profiles/Edit.resx b/Oqtane.Client/Resources/Modules/Admin/Profiles/Edit.resx
index 973f8719..79a2f0f4 100644
--- a/Oqtane.Client/Resources/Modules/Admin/Profiles/Edit.resx
+++ b/Oqtane.Client/Resources/Modules/Admin/Profiles/Edit.resx
@@ -1,4 +1,4 @@
-
+
Exe
- 5.0.1
+ 5.0.2
Oqtane
Shaun Walker
.NET Foundation
@@ -14,7 +14,7 @@
.NET Foundation
https://www.oqtane.org
https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE
- https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1
+ https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2
https://github.com/oqtane/oqtane.framework
Git
Oqtane.Maui
@@ -31,7 +31,7 @@
0E29FC31-1B83-48ED-B6E0-9F3C67B775D4
- 5.0.1
+ 5.0.2
1
14.2
@@ -65,11 +65,11 @@
-
-
+
+
-
+
diff --git a/Oqtane.Maui/wwwroot/css/app.css b/Oqtane.Maui/wwwroot/css/app.css
index 5da25ceb..c1d0b44b 100644
--- a/Oqtane.Maui/wwwroot/css/app.css
+++ b/Oqtane.Maui/wwwroot/css/app.css
@@ -213,3 +213,18 @@ app {
right: 0.75rem;
top: 0.5rem;
}
+
+/* Oqtane Control Styles */
+
+/* Pager */
+.app-pager-pointer {
+ cursor: pointer;
+}
+
+.app-sort-th {
+ cursor: pointer;
+}
+
+.app-fas {
+ margin-left: 5px;
+}
diff --git a/Oqtane.Maui/wwwroot/js/interop.js b/Oqtane.Maui/wwwroot/js/interop.js
index 8a677952..8305f766 100644
--- a/Oqtane.Maui/wwwroot/js/interop.js
+++ b/Oqtane.Maui/wwwroot/js/interop.js
@@ -27,14 +27,8 @@ Oqtane.Interop = {
document.title = title;
}
},
- includeMeta: function (id, attribute, name, content, key) {
- var meta;
- if (id !== "" && key === "id") {
- meta = document.getElementById(id);
- }
- else {
- meta = document.querySelector("meta[" + attribute + "=\"" + CSS.escape(name) + "\"]");
- }
+ includeMeta: function (id, attribute, name, content) {
+ var meta = document.querySelector("meta[" + attribute + "=\"" + CSS.escape(name) + "\"]");
if (meta === null) {
meta = document.createElement("meta");
meta.setAttribute(attribute, name);
@@ -119,13 +113,26 @@ Oqtane.Interop = {
this.includeLink(links[i].id, links[i].rel, links[i].href, links[i].type, links[i].integrity, links[i].crossorigin, links[i].insertbefore);
}
},
- includeScript: function (id, src, integrity, crossorigin, content, location) {
- var script = document.querySelector("script[src=\"" + CSS.escape(src) + "\"]");
+ includeScript: function (id, src, integrity, crossorigin, type, content, location) {
+ var script;
+ if (src !== "") {
+ script = document.querySelector("script[src=\"" + CSS.escape(src) + "\"]");
+ }
+ else {
+ script = document.getElementById(id);
+ }
+ if (script !== null) {
+ script.remove();
+ script = null;
+ }
if (script === null) {
script = document.createElement("script");
if (id !== "") {
script.id = id;
}
+ if (type !== "") {
+ script.type = type;
+ }
if (src !== "") {
script.src = src;
if (integrity !== "") {
@@ -141,43 +148,22 @@ Oqtane.Interop = {
script.async = false;
this.addScript(script, location)
.then(() => {
- console.log(src + ' loaded');
+ if (src !== "") {
+ console.log(src + ' loaded');
+ }
+ else {
+ console.log(id + ' loaded');
+ }
})
.catch(() => {
- console.error(src + ' failed');
+ if (src !== "") {
+ console.error(src + ' failed');
+ }
+ else {
+ console.error(id + ' failed');
+ }
});
}
- else {
- if (script.id !== id) {
- script.setAttribute('id', id);
- }
- if (src !== "") {
- if (script.src !== this.getAbsoluteUrl(src)) {
- script.removeAttribute('integrity');
- script.removeAttribute('crossorigin');
- script.src = src;
- }
- if (integrity !== "") {
- if (script.integrity !== integrity) {
- script.setAttribute('integrity', integrity);
- }
- } else {
- script.removeAttribute('integrity');
- }
- if (crossorigin !== "") {
- if (script.crossOrigin !== crossorigin) {
- script.setAttribute('crossorigin', crossorigin);
- }
- } else {
- script.removeAttribute('crossorigin');
- }
- }
- else {
- if (script.innerHTML !== content) {
- script.innerHTML = content;
- }
- }
- }
},
addScript: function (script, location) {
if (location === 'head') {
@@ -229,6 +215,10 @@ Oqtane.Interop = {
if (path === scripts[s].href && scripts[s].es6module === true) {
element.type = "module";
}
+ if (path === scripts[s].href && scripts[s].location === 'body') {
+ document.body.appendChild(element);
+ return false; // return false to bypass default DOM insertion mechanism
+ }
}
}
})
@@ -289,19 +279,21 @@ Oqtane.Interop = {
var fileinput = document.getElementById(id);
if (fileinput !== null) {
for (var i = 0; i < fileinput.files.length; i++) {
- files.push(fileinput.files[i].name);
+ files.push(fileinput.files[i].name + ":" + fileinput.files[i].size);
}
}
return files;
},
- uploadFiles: function (posturl, folder, id, antiforgerytoken) {
- var fileinput = document.getElementById(id + 'FileInput');
+ uploadFiles: function (posturl, folder, id, antiforgerytoken, jwt) {
+ var fileinput = document.getElementById('FileInput_' + id);
var files = fileinput.files;
- var progressinfo = document.getElementById(id + 'ProgressInfo');
- var progressbar = document.getElementById(id + 'ProgressBar');
+ var progressinfo = document.getElementById('ProgressInfo_' + id);
+ var progressbar = document.getElementById('ProgressBar_' + id);
- progressinfo.setAttribute("style", "display: inline;");
- progressbar.setAttribute("style", "width: 200px; display: inline;");
+ if (progressinfo !== null && progressbar !== null) {
+ progressinfo.setAttribute("style", "display: inline;");
+ progressbar.setAttribute("style", "width: 100%; display: inline;");
+ }
for (var i = 0; i < files.length; i++) {
var FileChunk = [];
@@ -331,22 +323,34 @@ Oqtane.Interop = {
data.append('formfile', Chunk, FileName);
var request = new XMLHttpRequest();
request.open('POST', posturl, true);
+ if (jwt !== "") {
+ request.setRequestHeader('Authorization', 'Bearer ' + jwt);
+ request.withCredentials = true;
+ }
request.upload.onloadstart = function (e) {
- progressinfo.innerHTML = file.name + ' 0%';
- progressbar.value = 0;
+ if (progressinfo !== null && progressbar !== null) {
+ progressinfo.innerHTML = file.name + ' 0%';
+ progressbar.value = 0;
+ }
};
request.upload.onprogress = function (e) {
- var percent = Math.ceil((e.loaded / e.total) * 100);
- progressinfo.innerHTML = file.name + '[' + PartCount + '] ' + percent + '%';
- progressbar.value = (percent / 100);
+ if (progressinfo !== null && progressbar !== null) {
+ var percent = Math.ceil((e.loaded / e.total) * 100);
+ progressinfo.innerHTML = file.name + '[' + PartCount + '] ' + percent + '%';
+ progressbar.value = (percent / 100);
+ }
};
request.upload.onloadend = function (e) {
- progressinfo.innerHTML = file.name + ' 100%';
- progressbar.value = 1;
+ if (progressinfo !== null && progressbar !== null) {
+ progressinfo.innerHTML = file.name + ' 100%';
+ progressbar.value = 1;
+ }
};
- request.upload.onerror = function () {
- progressinfo.innerHTML = file.name + ' Error: ' + xhr.status;
- progressbar.value = 0;
+ request.upload.onerror = function() {
+ if (progressinfo !== null && progressbar !== null) {
+ progressinfo.innerHTML = file.name + ' Error: ' + request.statusText;
+ progressbar.value = 0;
+ }
};
request.send(data);
}
@@ -356,10 +360,15 @@ Oqtane.Interop = {
}
}
},
- refreshBrowser: function (reload, wait) {
- setInterval(function () {
- window.location.reload(reload);
- }, wait * 1000);
+ refreshBrowser: function (verify, wait) {
+ async function attemptReload (verify) {
+ if (verify) {
+ await fetch('');
+ }
+ window.location.reload();
+ }
+ attemptReload(verify);
+ setInterval(attemptReload, wait * 1000);
},
redirectBrowser: function (url, wait) {
setInterval(function () {
diff --git a/Oqtane.Package/Oqtane.Client.nuspec b/Oqtane.Package/Oqtane.Client.nuspec
index 4c346c87..06250592 100644
--- a/Oqtane.Package/Oqtane.Client.nuspec
+++ b/Oqtane.Package/Oqtane.Client.nuspec
@@ -2,7 +2,7 @@
Oqtane.Client
- 5.0.1
+ 5.0.2
Shaun Walker
.NET Foundation
Oqtane Framework
@@ -12,14 +12,13 @@
false
MIT
https://github.com/oqtane/oqtane.framework
- https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1
+ https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2
icon.png
oqtane
-
\ No newline at end of file
diff --git a/Oqtane.Package/Oqtane.Framework.nuspec b/Oqtane.Package/Oqtane.Framework.nuspec
index 3b0d65b4..671ba15a 100644
--- a/Oqtane.Package/Oqtane.Framework.nuspec
+++ b/Oqtane.Package/Oqtane.Framework.nuspec
@@ -2,7 +2,7 @@
Oqtane.Framework
- 5.0.1
+ 5.0.2
Shaun Walker
.NET Foundation
Oqtane Framework
@@ -11,8 +11,8 @@
.NET Foundation
false
MIT
- https://github.com/oqtane/oqtane.framework/releases/download/v5.0.1/Oqtane.Framework.5.0.1.Upgrade.zip
- https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1
+ https://github.com/oqtane/oqtane.framework/releases/download/v5.0.2/Oqtane.Framework.5.0.2.Upgrade.zip
+ https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2
icon.png
oqtane framework
diff --git a/Oqtane.Package/Oqtane.Server.nuspec b/Oqtane.Package/Oqtane.Server.nuspec
index 65c3d5c4..1b87c609 100644
--- a/Oqtane.Package/Oqtane.Server.nuspec
+++ b/Oqtane.Package/Oqtane.Server.nuspec
@@ -2,7 +2,7 @@
Oqtane.Server
- 5.0.1
+ 5.0.2
Shaun Walker
.NET Foundation
Oqtane Framework
@@ -12,7 +12,7 @@
false
MIT
https://github.com/oqtane/oqtane.framework
- https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1
+ https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2
icon.png
oqtane
diff --git a/Oqtane.Package/Oqtane.Shared.nuspec b/Oqtane.Package/Oqtane.Shared.nuspec
index 8c6be30a..294d5c5c 100644
--- a/Oqtane.Package/Oqtane.Shared.nuspec
+++ b/Oqtane.Package/Oqtane.Shared.nuspec
@@ -2,7 +2,7 @@
Oqtane.Shared
- 5.0.1
+ 5.0.2
Shaun Walker
.NET Foundation
Oqtane Framework
@@ -12,14 +12,13 @@
false
MIT
https://github.com/oqtane/oqtane.framework
- https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1
+ https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2
icon.png
oqtane
-
\ No newline at end of file
diff --git a/Oqtane.Package/Oqtane.Updater.nuspec b/Oqtane.Package/Oqtane.Updater.nuspec
index aee8ee24..e16b7bd9 100644
--- a/Oqtane.Package/Oqtane.Updater.nuspec
+++ b/Oqtane.Package/Oqtane.Updater.nuspec
@@ -2,7 +2,7 @@
Oqtane.Updater
- 5.0.1
+ 5.0.2
Shaun Walker
.NET Foundation
Oqtane Framework
@@ -12,7 +12,7 @@
false
MIT
https://github.com/oqtane/oqtane.framework
- https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1
+ https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2
icon.png
oqtane
diff --git a/Oqtane.Package/install.ps1 b/Oqtane.Package/install.ps1
index 634cf373..3f986170 100644
--- a/Oqtane.Package/install.ps1
+++ b/Oqtane.Package/install.ps1
@@ -1 +1 @@
-Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.0.1.Install.zip" -Force
\ No newline at end of file
+Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.0.2.Install.zip" -Force
\ No newline at end of file
diff --git a/Oqtane.Package/upgrade.ps1 b/Oqtane.Package/upgrade.ps1
index b9538e69..f1fe650e 100644
--- a/Oqtane.Package/upgrade.ps1
+++ b/Oqtane.Package/upgrade.ps1
@@ -1 +1 @@
-Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.0.1.Upgrade.zip" -Force
\ No newline at end of file
+Compress-Archive -Path "..\Oqtane.Server\bin\Release\net8.0\publish\*" -DestinationPath "Oqtane.Framework.5.0.2.Upgrade.zip" -Force
\ No newline at end of file
diff --git a/Oqtane.Server/Controllers/FileController.cs b/Oqtane.Server/Controllers/FileController.cs
index 65cd3fec..7dc5cfb6 100644
--- a/Oqtane.Server/Controllers/FileController.cs
+++ b/Oqtane.Server/Controllers/FileController.cs
@@ -20,6 +20,7 @@ using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Formats.Png;
using System.Net.Http;
+using Microsoft.AspNetCore.Cors;
// ReSharper disable StringIndexOfIsCultureSpecific.1
@@ -288,7 +289,8 @@ namespace Oqtane.Controllers
folder = _folders.GetFolder(FolderId);
}
- var _UploadableFiles = (_settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "UploadableFiles")?.SettingValue ?? Constants.UploadableFiles) ?? Constants.UploadableFiles;
+ var _UploadableFiles = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "UploadableFiles")?.SettingValue;
+ _UploadableFiles = (string.IsNullOrEmpty(_UploadableFiles)) ? Constants.UploadableFiles : _UploadableFiles;
if (folder != null && folder.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.Edit, folder.PermissionList))
{
@@ -357,17 +359,18 @@ namespace Oqtane.Controllers
}
// POST api//upload
+ [EnableCors(Constants.MauiCorsPolicy)]
[HttpPost("upload")]
public async Task UploadFile(string folder, IFormFile formfile)
{
- if (formfile.Length <= 0)
+ if (formfile == null || formfile.Length <= 0)
{
return;
}
// Get the UploadableFiles extensions
- string uploadfilesSetting = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "UploadableFiles")?.SettingValue;
- string _UploadableFiles = uploadfilesSetting ?? Constants.UploadableFiles;
+ string _UploadableFiles = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "UploadableFiles")?.SettingValue;
+ _UploadableFiles = (string.IsNullOrEmpty(_UploadableFiles)) ? Constants.UploadableFiles : _UploadableFiles;
// ensure filename is valid
string token = ".part_";
@@ -612,7 +615,9 @@ namespace Oqtane.Controllers
{
var file = _files.GetFile(id);
- var _ImageFiles = (_settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "ImageFiles")?.SettingValue ?? Constants.ImageFiles) ?? Constants.ImageFiles;
+ var _ImageFiles = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "ImageFiles")?.SettingValue;
+ _ImageFiles = (string.IsNullOrEmpty(_ImageFiles)) ? Constants.ImageFiles : _ImageFiles;
+
if (file != null && file.Folder.SiteId == _alias.SiteId && _userPermissions.IsAuthorized(User, PermissionNames.View, file.Folder.PermissionList))
{
if (_ImageFiles.Split(',').Contains(file.Extension.ToLower()))
@@ -779,7 +784,9 @@ namespace Oqtane.Controllers
private Models.File CreateFile(string filename, int folderid, string filepath)
{
var file = _files.GetFile(folderid, filename);
- var _ImageFiles = (_settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "ImageFiles")?.SettingValue ?? Constants.ImageFiles) ?? Constants.ImageFiles;
+
+ var _ImageFiles = _settingRepository.GetSetting(EntityNames.Site, _alias.SiteId, "ImageFiles")?.SettingValue;
+ _ImageFiles = (string.IsNullOrEmpty(_ImageFiles)) ? Constants.ImageFiles : _ImageFiles;
int size = 0;
var folder = _folders.GetFolder(folderid, false);
diff --git a/Oqtane.Server/Controllers/ModuleController.cs b/Oqtane.Server/Controllers/ModuleController.cs
index f8172db1..8acde463 100644
--- a/Oqtane.Server/Controllers/ModuleController.cs
+++ b/Oqtane.Server/Controllers/ModuleController.cs
@@ -75,6 +75,8 @@ namespace Oqtane.Controllers
module.Pane = pagemodule.Pane;
module.Order = pagemodule.Order;
module.ContainerType = pagemodule.ContainerType;
+ module.EffectiveDate = pagemodule.EffectiveDate;
+ module.ExpiryDate = pagemodule.ExpiryDate;
module.ModuleDefinition = _moduleDefinitions.FilterModuleDefinition(moduledefinitions.Find(item => item.ModuleDefinitionName == module.ModuleDefinitionName));
@@ -169,7 +171,7 @@ namespace Oqtane.Controllers
{
if (!pageModules.Exists(item => item.ModuleId == module.ModuleId && item.PageId == page.PageId) && !page.Path.StartsWith("admin/"))
{
- _pageModules.AddPageModule(new PageModule { PageId = page.PageId, ModuleId = pageModule.ModuleId, Title = pageModule.Title, Pane = pageModule.Pane, Order = pageModule.Order, ContainerType = pageModule.ContainerType });
+ _pageModules.AddPageModule(new PageModule { PageId = page.PageId, ModuleId = pageModule.ModuleId, Title = pageModule.Title, Pane = pageModule.Pane, Order = pageModule.Order, ContainerType = pageModule.ContainerType, EffectiveDate = pageModule.EffectiveDate, ExpiryDate = pageModule.ExpiryDate });
}
}
}
diff --git a/Oqtane.Server/Controllers/SiteController.cs b/Oqtane.Server/Controllers/SiteController.cs
index 4d1b7184..df0384c1 100644
--- a/Oqtane.Server/Controllers/SiteController.cs
+++ b/Oqtane.Server/Controllers/SiteController.cs
@@ -13,6 +13,8 @@ using System.Globalization;
using Microsoft.Extensions.Caching.Memory;
using Oqtane.Extensions;
using System;
+using Oqtane.UI;
+using Microsoft.EntityFrameworkCore.Metadata.Internal;
namespace Oqtane.Controllers
{
@@ -97,7 +99,7 @@ namespace Oqtane.Controllers
site.Pages = new List();
foreach (Page page in _pages.GetPages(site.SiteId))
{
- if (!page.IsDeleted && _userPermissions.IsAuthorized(User, PermissionNames.View, page.PermissionList))
+ if (!page.IsDeleted && _userPermissions.IsAuthorized(User, PermissionNames.View, page.PermissionList) && (Utilities.IsPageModuleVisible(page.EffectiveDate, page.ExpiryDate) || _userPermissions.IsAuthorized(User, PermissionNames.Edit, page.PermissionList)))
{
page.Settings = settings.Where(item => item.EntityId == page.PageId)
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, page.PermissionList))
@@ -105,46 +107,53 @@ namespace Oqtane.Controllers
site.Pages.Add(page);
}
}
+
site.Pages = GetPagesHierarchy(site.Pages);
// modules
List moduledefinitions = _moduleDefinitions.GetModuleDefinitions(site.SiteId).ToList();
settings = _settings.GetSettings(EntityNames.Module).ToList();
site.Modules = new List();
- foreach (PageModule pagemodule in _pageModules.GetPageModules(site.SiteId))
+ foreach (PageModule pagemodule in _pageModules.GetPageModules(site.SiteId).Where(pm => !pm.IsDeleted && _userPermissions.IsAuthorized(User, PermissionNames.View, pm.Module.PermissionList)))
{
- if (!pagemodule.IsDeleted && _userPermissions.IsAuthorized(User, PermissionNames.View, pagemodule.Module.PermissionList))
+ if(Utilities.IsPageModuleVisible(pagemodule.EffectiveDate, pagemodule.ExpiryDate) || _userPermissions.IsAuthorized(User, PermissionNames.Edit, pagemodule.Module.PermissionList))
{
- Module module = new Module();
- module.SiteId = pagemodule.Module.SiteId;
- module.ModuleDefinitionName = pagemodule.Module.ModuleDefinitionName;
- module.AllPages = pagemodule.Module.AllPages;
- module.PermissionList = pagemodule.Module.PermissionList;
- module.CreatedBy = pagemodule.Module.CreatedBy;
- module.CreatedOn = pagemodule.Module.CreatedOn;
- module.ModifiedBy = pagemodule.Module.ModifiedBy;
- module.ModifiedOn = pagemodule.Module.ModifiedOn;
- module.DeletedBy = pagemodule.DeletedBy;
- module.DeletedOn = pagemodule.DeletedOn;
- module.IsDeleted = pagemodule.IsDeleted;
+ Module module = new Module
+ {
+ SiteId = pagemodule.Module.SiteId,
+ ModuleDefinitionName = pagemodule.Module.ModuleDefinitionName,
+ AllPages = pagemodule.Module.AllPages,
+ PermissionList = pagemodule.Module.PermissionList,
+ CreatedBy = pagemodule.Module.CreatedBy,
+ CreatedOn = pagemodule.Module.CreatedOn,
+ ModifiedBy = pagemodule.Module.ModifiedBy,
+ ModifiedOn = pagemodule.Module.ModifiedOn,
+ DeletedBy = pagemodule.DeletedBy,
+ DeletedOn = pagemodule.DeletedOn,
+ IsDeleted = pagemodule.IsDeleted,
- module.PageModuleId = pagemodule.PageModuleId;
- module.ModuleId = pagemodule.ModuleId;
- module.PageId = pagemodule.PageId;
- module.Title = pagemodule.Title;
- module.Pane = pagemodule.Pane;
- module.Order = pagemodule.Order;
- module.ContainerType = pagemodule.ContainerType;
+ PageModuleId = pagemodule.PageModuleId,
+ ModuleId = pagemodule.ModuleId,
+ PageId = pagemodule.PageId,
+ Title = pagemodule.Title,
+ Pane = pagemodule.Pane,
+ Order = pagemodule.Order,
+ ContainerType = pagemodule.ContainerType,
+ EffectiveDate = pagemodule.EffectiveDate,
+ ExpiryDate = pagemodule.ExpiryDate,
- module.ModuleDefinition = _moduleDefinitions.FilterModuleDefinition(moduledefinitions.Find(item => item.ModuleDefinitionName == module.ModuleDefinitionName));
+ ModuleDefinition = _moduleDefinitions.FilterModuleDefinition(moduledefinitions.Find(item => item.ModuleDefinitionName == pagemodule.Module.ModuleDefinitionName)),
- module.Settings = settings.Where(item => item.EntityId == pagemodule.ModuleId)
+ Settings = settings
+ .Where(item => item.EntityId == pagemodule.ModuleId)
.Where(item => !item.IsPrivate || _userPermissions.IsAuthorized(User, PermissionNames.Edit, pagemodule.Module.PermissionList))
- .ToDictionary(setting => setting.SettingName, setting => setting.SettingValue);
+ .ToDictionary(setting => setting.SettingName, setting => setting.SettingValue)
+ };
site.Modules.Add(module);
}
}
+
site.Modules = site.Modules.OrderBy(item => item.PageId).ThenBy(item => item.Pane).ThenBy(item => item.Order).ToList();
// languages
diff --git a/Oqtane.Server/Databases/DatabaseBase.cs b/Oqtane.Server/Databases/DatabaseBase.cs
index a9b91eaf..2342874f 100644
--- a/Oqtane.Server/Databases/DatabaseBase.cs
+++ b/Oqtane.Server/Databases/DatabaseBase.cs
@@ -66,6 +66,11 @@ namespace Oqtane.Databases
return name;
}
+ public virtual string RewriteName(string name, bool isQuery)
+ {
+ return name;
+ }
+
public virtual string RewriteValue(string value, string type)
{
return value;
diff --git a/Oqtane.Server/Databases/Interfaces/IDatabase.cs b/Oqtane.Server/Databases/Interfaces/IDatabase.cs
index 303fbc0f..3c68cf03 100644
--- a/Oqtane.Server/Databases/Interfaces/IDatabase.cs
+++ b/Oqtane.Server/Databases/Interfaces/IDatabase.cs
@@ -28,6 +28,8 @@ namespace Oqtane.Databases.Interfaces
public string RewriteName(string name);
+ public string RewriteName(string name, bool isQuery);
+
public string RewriteValue(string value, string type);
public void UpdateIdentityStoreTableNames(ModelBuilder builder);
diff --git a/Oqtane.Server/Extensions/OqtaneSiteAuthenticationBuilderExtensions.cs b/Oqtane.Server/Extensions/OqtaneSiteAuthenticationBuilderExtensions.cs
index 68a002c7..604270c1 100644
--- a/Oqtane.Server/Extensions/OqtaneSiteAuthenticationBuilderExtensions.cs
+++ b/Oqtane.Server/Extensions/OqtaneSiteAuthenticationBuilderExtensions.cs
@@ -205,6 +205,10 @@ namespace Oqtane.Extensions
{
email = item[emailClaimType].ToString().ToLower();
}
+ else
+ {
+ id = ""; // if email is not valid we will assume id is not valid
+ }
}
}
if (!string.IsNullOrEmpty(id))
@@ -290,6 +294,10 @@ namespace Oqtane.Extensions
{
email = context.Principal.FindFirstValue(emailClaimType);
}
+ else
+ {
+ id = ""; // if email is not valid we will assume id is not valid
+ }
}
// validate user
@@ -610,23 +618,27 @@ namespace Oqtane.Extensions
private static bool EmailValid(string email, string domainfilter)
{
- if (!string.IsNullOrEmpty(email) && email.Contains("@") && email.Contains("."))
+ if (!string.IsNullOrEmpty(email))
{
- var domains = domainfilter.ToLower().Split(',', StringSplitOptions.RemoveEmptyEntries);
- foreach (var domain in domains)
+ if (email.Contains("@") && email.Contains("."))
{
- if (domain.StartsWith("!"))
+ var domains = domainfilter.ToLower().Split(',', StringSplitOptions.RemoveEmptyEntries);
+ foreach (var domain in domains)
{
- if (email.ToLower().Contains(domain.Substring(1))) return false;
- }
- else
- {
- if (!email.ToLower().Contains(domain)) return false;
+ if (domain.StartsWith("!"))
+ {
+ if (email.ToLower().Contains(domain.Substring(1))) return false;
+ }
+ else
+ {
+ if (!email.ToLower().Contains(domain)) return false;
+ }
}
+ return true;
}
- return true;
- }
- return false;
+ return false;
+ }
+ return (string.IsNullOrEmpty(domainfilter)); // email is optional unless domain filter is specified
}
}
}
diff --git a/Oqtane.Server/Infrastructure/DatabaseManager.cs b/Oqtane.Server/Infrastructure/DatabaseManager.cs
index 01138129..d05524ca 100644
--- a/Oqtane.Server/Infrastructure/DatabaseManager.cs
+++ b/Oqtane.Server/Infrastructure/DatabaseManager.cs
@@ -1,10 +1,7 @@
using System;
-using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
-using System.Runtime.Loader;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
@@ -29,16 +26,14 @@ namespace Oqtane.Infrastructure
{
private readonly IConfigManager _config;
private readonly IServiceScopeFactory _serviceScopeFactory;
- private readonly IWebHostEnvironment _environment;
private readonly IMemoryCache _cache;
private readonly IConfigManager _configManager;
private readonly ILogger _filelogger;
- public DatabaseManager(IConfigManager config, IServiceScopeFactory serviceScopeFactory, IWebHostEnvironment environment, IMemoryCache cache, IConfigManager configManager, ILogger filelogger)
+ public DatabaseManager(IConfigManager config, IServiceScopeFactory serviceScopeFactory, IMemoryCache cache, IConfigManager configManager, ILogger filelogger)
{
_config = config;
_serviceScopeFactory = serviceScopeFactory;
- _environment = environment;
_cache = cache;
_configManager = configManager;
_filelogger = filelogger;
@@ -216,19 +211,27 @@ namespace Oqtane.Infrastructure
// get database type
var type = Type.GetType(databaseType);
- // create database object from type
- var database = Activator.CreateInstance(type) as IDatabase;
-
- // create data directory if does not exist
- var dataDirectory = AppDomain.CurrentDomain.GetData(Constants.DataDirectory)?.ToString();
- if (!Directory.Exists(dataDirectory)) Directory.CreateDirectory(dataDirectory ?? String.Empty);
-
- var dbOptions = new DbContextOptionsBuilder().UseOqtaneDatabase(database, NormalizeConnectionString(install.ConnectionString)).Options;
- using (var dbc = new DbContext(dbOptions))
+ if (type != null)
{
- // create empty database if it does not exist
- dbc.Database.EnsureCreated();
- result.Success = true;
+ // create database object from type
+ var database = Activator.CreateInstance(type) as IDatabase;
+
+ // create data directory if does not exist
+ var dataDirectory = AppDomain.CurrentDomain.GetData(Constants.DataDirectory)?.ToString();
+ if (!Directory.Exists(dataDirectory)) Directory.CreateDirectory(dataDirectory ?? String.Empty);
+
+ var dbOptions = new DbContextOptionsBuilder().UseOqtaneDatabase(database, NormalizeConnectionString(install.ConnectionString)).Options;
+ using (var dbc = new DbContext(dbOptions))
+ {
+ // create empty database if it does not exist
+ dbc.Database.EnsureCreated();
+ result.Success = true;
+ }
+ }
+ else
+ {
+ result.Message = $"The Database Provider {databaseType} Does Not Exist. If This Is A Development Environment Please Ensure You Have Performed A Full Compilation Of All Projects In The Oqtane Solution Prior To Running The Application.";
+ _filelogger.LogError(Utilities.LogMessage(this, result.Message));
}
}
catch (Exception ex)
diff --git a/Oqtane.Server/Infrastructure/InstallationManager.cs b/Oqtane.Server/Infrastructure/InstallationManager.cs
index 0d26600b..1307b57f 100644
--- a/Oqtane.Server/Infrastructure/InstallationManager.cs
+++ b/Oqtane.Server/Infrastructure/InstallationManager.cs
@@ -137,16 +137,20 @@ namespace Oqtane.Infrastructure
// register assembly
if (Path.GetExtension(filename) == ".dll")
{
- // if package version was not installed previously
- if (!File.Exists(Path.Combine(sourceFolder, name + ".log")))
+ // do not register licensing assemblies
+ if (!Path.GetFileName(filename).StartsWith("Oqtane.Licensing."))
{
- if (assemblies.ContainsKey(Path.GetFileName(filename)))
+ // if package version was not installed previously
+ if (!File.Exists(Path.Combine(sourceFolder, name + ".log")))
{
- assemblies[Path.GetFileName(filename)] += 1;
- }
- else
- {
- assemblies.Add(Path.GetFileName(filename), 1);
+ if (assemblies.ContainsKey(Path.GetFileName(filename)))
+ {
+ assemblies[Path.GetFileName(filename)] += 1;
+ }
+ else
+ {
+ assemblies.Add(Path.GetFileName(filename), 1);
+ }
}
}
}
@@ -255,22 +259,26 @@ namespace Oqtane.Infrastructure
// delete assets
if (Path.GetExtension(filepath) == ".dll")
{
- // use assembly log to determine if assembly is used in other packages
- if (assemblies.ContainsKey(Path.GetFileName(filepath)))
+ // do not remove licensing assemblies
+ if (!Path.GetFileName(filepath).StartsWith("Oqtane.Licensing."))
{
- if (assemblies[Path.GetFileName(filepath)] == 1)
+ // use assembly log to determine if assembly is used in other packages
+ if (assemblies.ContainsKey(Path.GetFileName(filepath)))
+ {
+ if (assemblies[Path.GetFileName(filepath)] == 1)
+ {
+ DeleteFile(filepath);
+ assemblies.Remove(Path.GetFileName(filepath));
+ }
+ else
+ {
+ assemblies[Path.GetFileName(filepath)] -= 1;
+ }
+ }
+ else // does not exist in assembly log
{
DeleteFile(filepath);
- assemblies.Remove(Path.GetFileName(filepath));
}
- else
- {
- assemblies[Path.GetFileName(filepath)] -= 1;
- }
- }
- else // does not exist in assembly log
- {
- DeleteFile(filepath);
}
}
else // not an assembly
diff --git a/Oqtane.Server/Infrastructure/SiteTemplates/DefaultSiteTemplate.cs b/Oqtane.Server/Infrastructure/SiteTemplates/DefaultSiteTemplate.cs
index 6819277a..e572c5f0 100644
--- a/Oqtane.Server/Infrastructure/SiteTemplates/DefaultSiteTemplate.cs
+++ b/Oqtane.Server/Infrastructure/SiteTemplates/DefaultSiteTemplate.cs
@@ -68,7 +68,7 @@ namespace Oqtane.SiteTemplates
new Permission(PermissionNames.View, RoleNames.Admin, true),
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
},
- Content = "Copyright (c) 2018-2023 .NET Foundation
" +
+ Content = "Copyright (c) 2018-2024 .NET Foundation
" +
"Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
" +
"The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
" +
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"
diff --git a/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs b/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs
index 5bf10e0a..b97a3d60 100644
--- a/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs
+++ b/Oqtane.Server/Migrations/EntityBuilders/BaseEntityBuilder.cs
@@ -50,6 +50,11 @@ namespace Oqtane.Migrations.EntityBuilders
return ActiveDatabase.RewriteName(name);
}
+ private string RewriteName(string name, bool isQuery)
+ {
+ return ActiveDatabase.RewriteName(name, isQuery);
+ }
+
private string RewriteValue(string value, string type)
{
return ActiveDatabase.RewriteValue(value, type);
@@ -394,7 +399,7 @@ namespace Oqtane.Migrations.EntityBuilders
public void UpdateColumn(string columnName, string value, string type, string condition)
{
- var updateSql = $"UPDATE {RewriteSqlEntityTableName(EntityTableName)} SET {RewriteName(columnName)} = {RewriteValue(value, type)} ";
+ var updateSql = $"UPDATE {RewriteSqlEntityTableName(EntityTableName)} SET {RewriteName(columnName, true)} = {RewriteValue(value, type)} ";
if (!string.IsNullOrEmpty(condition))
{
updateSql += $"WHERE {condition}";
diff --git a/Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs b/Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs
index 8379c3e3..87fb34cc 100644
--- a/Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs
+++ b/Oqtane.Server/Migrations/Framework/MultiDatabaseMigration.cs
@@ -14,7 +14,12 @@ namespace Oqtane.Migrations
protected string RewriteName(string name)
{
- return ActiveDatabase.RewriteName(name);
+ return ActiveDatabase.RewriteName(name, false);
+ }
+
+ protected string RewriteName(string name, bool isQuery)
+ {
+ return ActiveDatabase.RewriteName(name, isQuery);
}
}
}
diff --git a/Oqtane.Server/Migrations/Tenant/05010001_AddPageEffectiveExpiryDate.cs b/Oqtane.Server/Migrations/Tenant/05010001_AddPageEffectiveExpiryDate.cs
new file mode 100644
index 00000000..bed22cd2
--- /dev/null
+++ b/Oqtane.Server/Migrations/Tenant/05010001_AddPageEffectiveExpiryDate.cs
@@ -0,0 +1,32 @@
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata.Internal;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Oqtane.Databases.Interfaces;
+using Oqtane.Migrations.EntityBuilders;
+using Oqtane.Repository;
+
+namespace Oqtane.Migrations.Tenant
+{
+ [DbContext(typeof(TenantDBContext))]
+ [Migration("Tenant.05.01.00.01")]
+ public class AddPageEffectiveExpiryDate : MultiDatabaseMigration
+ {
+ public AddPageEffectiveExpiryDate(IDatabase database) : base(database)
+ {
+ }
+
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);;
+ pageEntityBuilder.AddDateTimeColumn("EffectiveDate", true);
+ pageEntityBuilder.AddDateTimeColumn("ExpiryDate", true);
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);
+ pageEntityBuilder.DropColumn("EffectiveDate");
+ pageEntityBuilder.DropColumn("ExpiryDate");
+ }
+ }
+}
diff --git a/Oqtane.Server/Migrations/Tenant/05010002_AddPageModuleEffectiveExpiryDate.cs b/Oqtane.Server/Migrations/Tenant/05010002_AddPageModuleEffectiveExpiryDate.cs
new file mode 100644
index 00000000..f0b9147d
--- /dev/null
+++ b/Oqtane.Server/Migrations/Tenant/05010002_AddPageModuleEffectiveExpiryDate.cs
@@ -0,0 +1,32 @@
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata.Internal;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Oqtane.Databases.Interfaces;
+using Oqtane.Migrations.EntityBuilders;
+using Oqtane.Repository;
+
+namespace Oqtane.Migrations.Tenant
+{
+ [DbContext(typeof(TenantDBContext))]
+ [Migration("Tenant.05.01.00.02")]
+ public class AddPageModuleEffectiveExpiryDate : MultiDatabaseMigration
+ {
+ public AddPageModuleEffectiveExpiryDate(IDatabase database) : base(database)
+ {
+ }
+
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ var pageModuleEntityBuilder = new PageModuleEntityBuilder(migrationBuilder, ActiveDatabase);;
+ pageModuleEntityBuilder.AddDateTimeColumn("EffectiveDate", true);
+ pageModuleEntityBuilder.AddDateTimeColumn("ExpiryDate", true);
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ var pageModuleEntityBuilder = new PageModuleEntityBuilder(migrationBuilder, ActiveDatabase);
+ pageModuleEntityBuilder.DropColumn("EffectiveDate");
+ pageModuleEntityBuilder.DropColumn("ExpiryDate");
+ }
+ }
+}
diff --git a/Oqtane.Server/Migrations/Tenant/05010003_AddProfileAutocomplete.cs b/Oqtane.Server/Migrations/Tenant/05010003_AddProfileAutocomplete.cs
new file mode 100644
index 00000000..6ec00156
--- /dev/null
+++ b/Oqtane.Server/Migrations/Tenant/05010003_AddProfileAutocomplete.cs
@@ -0,0 +1,28 @@
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Oqtane.Databases.Interfaces;
+using Oqtane.Migrations.EntityBuilders;
+using Oqtane.Repository;
+
+namespace Oqtane.Migrations.Tenant
+{
+ [DbContext(typeof(TenantDBContext))]
+ [Migration("Tenant.05.01.00.03")]
+ public class AddProfileAutocomplete : MultiDatabaseMigration
+ {
+ public AddProfileAutocomplete(IDatabase database) : base(database)
+ {
+ }
+
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ var profileEntityBuilder = new ProfileEntityBuilder(migrationBuilder, ActiveDatabase);
+ profileEntityBuilder.AddStringColumn("Autocomplete", 50, true);
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ // not implemented
+ }
+ }
+}
diff --git a/Oqtane.Server/Oqtane.Server.csproj b/Oqtane.Server/Oqtane.Server.csproj
index 3b7d540a..70f59532 100644
--- a/Oqtane.Server/Oqtane.Server.csproj
+++ b/Oqtane.Server/Oqtane.Server.csproj
@@ -3,7 +3,7 @@
net8.0
Debug;Release
- 5.0.1
+ 5.0.2
Oqtane
Shaun Walker
.NET Foundation
@@ -11,7 +11,7 @@
.NET Foundation
https://www.oqtane.org
https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE
- https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1
+ https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2
https://github.com/oqtane/oqtane.framework
Git
Oqtane
@@ -33,21 +33,20 @@
-
-
-
-
-
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
-
+
+
-
diff --git a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs
index 935525ee..075646e4 100644
--- a/Oqtane.Server/Repository/ModuleDefinitionRepository.cs
+++ b/Oqtane.Server/Repository/ModuleDefinitionRepository.cs
@@ -228,7 +228,7 @@ namespace Oqtane.Repository
// build list of scripts for site
if (moduledefinition.Resources != null)
{
- foreach (var resource in moduledefinition.Resources.Where(item => item.Level == ResourceLevel.Site))
+ foreach (var resource in moduledefinition.Resources.Where(item => item.ResourceType == ResourceType.Script && item.Level == ResourceLevel.Site))
{
if (!serverState.Scripts.Contains(resource))
{
diff --git a/Oqtane.Server/Repository/ThemeRepository.cs b/Oqtane.Server/Repository/ThemeRepository.cs
index a650f7d3..86d14d86 100644
--- a/Oqtane.Server/Repository/ThemeRepository.cs
+++ b/Oqtane.Server/Repository/ThemeRepository.cs
@@ -200,7 +200,7 @@ namespace Oqtane.Repository
// build list of scripts for site
if (theme.Resources != null)
{
- foreach (var resource in theme.Resources.Where(item => item.Level == ResourceLevel.Site))
+ foreach (var resource in theme.Resources.Where(item => item.ResourceType == ResourceType.Script && item.Level == ResourceLevel.Site))
{
if (!serverState.Scripts.Contains(resource))
{
diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs
index da191dcc..e777f4ed 100644
--- a/Oqtane.Server/Startup.cs
+++ b/Oqtane.Server/Startup.cs
@@ -131,6 +131,16 @@ namespace Oqtane
.WithSiteIdentity()
.WithSiteAuthentication();
+ services.AddCors(options =>
+ {
+ options.AddPolicy(Constants.MauiCorsPolicy,
+ policy =>
+ {
+ policy.WithOrigins("https://0.0.0.0", "http://0.0.0.0", "app://0.0.0.0")
+ .AllowAnyHeader().AllowCredentials();
+ });
+ });
+
services.AddMvc(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
@@ -180,6 +190,7 @@ namespace Oqtane
app.UseJwtAuthorization();
app.UseBlazorFrameworkFiles();
app.UseRouting();
+ app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Client/[Owner].Module.[Module].Client.csproj b/Oqtane.Server/wwwroot/Modules/Templates/External/Client/[Owner].Module.[Module].Client.csproj
index 32e6c1a1..48bbf770 100644
--- a/Oqtane.Server/wwwroot/Modules/Templates/External/Client/[Owner].Module.[Module].Client.csproj
+++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Client/[Owner].Module.[Module].Client.csproj
@@ -13,10 +13,10 @@
-
-
-
-
+
+
+
+
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Repository/[Module]Context.cs b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Repository/[Module]Context.cs
index a921ca0f..2cce3945 100644
--- a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Repository/[Module]Context.cs
+++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/Repository/[Module]Context.cs
@@ -15,5 +15,12 @@ namespace [Owner].Module.[Module].Repository
{
// ContextBase handles multi-tenant database connections
}
+
+ protected override void OnModelCreating(ModelBuilder builder)
+ {
+ base.OnModelCreating(builder);
+
+ builder.Entity().ToTable(ActiveDatabase.RewriteName("[Owner][Module]"));
+ }
}
}
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/[Owner].Module.[Module].Server.csproj b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/[Owner].Module.[Module].Server.csproj
index 7062f5ac..7411d973 100644
--- a/Oqtane.Server/wwwroot/Modules/Templates/External/Server/[Owner].Module.[Module].Server.csproj
+++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Server/[Owner].Module.[Module].Server.csproj
@@ -19,10 +19,10 @@
-
-
-
-
+
+
+
+
diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/Client/[Owner].Theme.[Theme].Client.csproj b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/[Owner].Theme.[Theme].Client.csproj
index 727b74dd..3ab97068 100644
--- a/Oqtane.Server/wwwroot/Themes/Templates/External/Client/[Owner].Theme.[Theme].Client.csproj
+++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/[Owner].Theme.[Theme].Client.csproj
@@ -12,10 +12,10 @@
-
-
-
-
+
+
+
+
diff --git a/Oqtane.Server/wwwroot/js/interop.js b/Oqtane.Server/wwwroot/js/interop.js
index 7daf41c1..8305f766 100644
--- a/Oqtane.Server/wwwroot/js/interop.js
+++ b/Oqtane.Server/wwwroot/js/interop.js
@@ -284,7 +284,7 @@ Oqtane.Interop = {
}
return files;
},
- uploadFiles: function (posturl, folder, id, antiforgerytoken) {
+ uploadFiles: function (posturl, folder, id, antiforgerytoken, jwt) {
var fileinput = document.getElementById('FileInput_' + id);
var files = fileinput.files;
var progressinfo = document.getElementById('ProgressInfo_' + id);
@@ -323,6 +323,10 @@ Oqtane.Interop = {
data.append('formfile', Chunk, FileName);
var request = new XMLHttpRequest();
request.open('POST', posturl, true);
+ if (jwt !== "") {
+ request.setRequestHeader('Authorization', 'Bearer ' + jwt);
+ request.withCredentials = true;
+ }
request.upload.onloadstart = function (e) {
if (progressinfo !== null && progressbar !== null) {
progressinfo.innerHTML = file.name + ' 0%';
@@ -344,7 +348,7 @@ Oqtane.Interop = {
};
request.upload.onerror = function() {
if (progressinfo !== null && progressbar !== null) {
- progressinfo.innerHTML = file.name + ' Error: ' + xhr.status;
+ progressinfo.innerHTML = file.name + ' Error: ' + request.statusText;
progressbar.value = 0;
}
};
diff --git a/Oqtane.Shared/Documentation/readme.md b/Oqtane.Shared/Documentation/readme.md
index cd55726a..ba715490 100644
--- a/Oqtane.Shared/Documentation/readme.md
+++ b/Oqtane.Shared/Documentation/readme.md
@@ -2,6 +2,6 @@
This folder contains special attributes for the API Code Generator.
-The idea is that only items marked with special attributes are valide public APIs, and only these will be documented in the public docs
+The idea is that only items marked with special attributes are valid public APIs, and only these will be documented in the public docs
-As of 2020, all APIs are documented, and only these marked as `[PrivateApi]` will be excluded. In future, we may reverse this to only document things marked as `[PublicApi]`.
\ No newline at end of file
+As of 2020, all APIs are documented, and only these marked as `[PrivateApi]` will be excluded. In future, we may reverse this to only document things marked as `[PublicApi]`.
diff --git a/Oqtane.Shared/Models/Module.cs b/Oqtane.Shared/Models/Module.cs
index 07c2a507..c0d37b3a 100644
--- a/Oqtane.Shared/Models/Module.cs
+++ b/Oqtane.Shared/Models/Module.cs
@@ -75,16 +75,24 @@ namespace Oqtane.Models
[NotMapped]
public string ContainerType { get; set; }
+ [NotMapped]
+ public DateTime? EffectiveDate { get; set; }
+
+ [NotMapped]
+ public DateTime? ExpiryDate { get; set; }
+
#endregion
#region SiteRouter properties
-
+
[NotMapped]
public string ModuleType { get; set; }
[NotMapped]
public int PaneModuleIndex { get; set; }
[NotMapped]
public int PaneModuleCount { get; set; }
+ [NotMapped]
+ public Guid RenderId { get; set; }
#endregion
diff --git a/Oqtane.Shared/Models/Page.cs b/Oqtane.Shared/Models/Page.cs
index c4c74a9a..a1b6d370 100644
--- a/Oqtane.Shared/Models/Page.cs
+++ b/Oqtane.Shared/Models/Page.cs
@@ -82,6 +82,14 @@ namespace Oqtane.Models
public bool IsNavigation { get; set; }
public bool IsClickable { get; set; }
public int? UserId { get; set; }
+ ///
+ /// Start of when this assignment is valid. See also
+ ///
+ public DateTime? EffectiveDate { get; set; }
+ ///
+ /// End of when this assignment is valid. See also
+ ///
+ public DateTime? ExpiryDate { get; set; }
public bool IsPersonalizable { get; set; }
#region IDeletable Properties
diff --git a/Oqtane.Shared/Models/PageModule.cs b/Oqtane.Shared/Models/PageModule.cs
index e8ff50e5..e3f0adb9 100644
--- a/Oqtane.Shared/Models/PageModule.cs
+++ b/Oqtane.Shared/Models/PageModule.cs
@@ -41,7 +41,14 @@ namespace Oqtane.Models
/// Reference to a Razor Container which wraps this module instance.
///
public string ContainerType { get; set; }
-
+ ///
+ /// Start of when this assignment is valid. See also
+ ///
+ public DateTime? EffectiveDate { get; set; }
+ ///
+ /// End of when this assignment is valid. See also
+ ///
+ public DateTime? ExpiryDate { get; set; }
#region IDeletable Properties
public string DeletedBy { get; set; }
diff --git a/Oqtane.Shared/Models/Profile.cs b/Oqtane.Shared/Models/Profile.cs
index 336cd262..f4db036d 100644
--- a/Oqtane.Shared/Models/Profile.cs
+++ b/Oqtane.Shared/Models/Profile.cs
@@ -78,5 +78,11 @@ namespace Oqtane.Models
/// Optional number of rows (textarea)
///
public int Rows { get; set; }
+
+ ///
+ /// Autocomplete setting for the property.
+ /// If set, enable autocomplete for the corresponding input field.
+ ///
+ public string Autocomplete { get; set; }
}
}
diff --git a/Oqtane.Shared/Oqtane.Shared.csproj b/Oqtane.Shared/Oqtane.Shared.csproj
index 265cc578..d2b161f9 100644
--- a/Oqtane.Shared/Oqtane.Shared.csproj
+++ b/Oqtane.Shared/Oqtane.Shared.csproj
@@ -3,7 +3,7 @@
net8.0
Debug;Release
- 5.0.1
+ 5.0.2
Oqtane
Shaun Walker
.NET Foundation
@@ -11,7 +11,7 @@
.NET Foundation
https://www.oqtane.org
https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE
- https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1
+ https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2
https://github.com/oqtane/oqtane.framework
Git
Oqtane
@@ -19,11 +19,11 @@
-
-
+
+
-
+
diff --git a/Oqtane.Shared/Shared/Constants.cs b/Oqtane.Shared/Shared/Constants.cs
index d0b44394..efef37e3 100644
--- a/Oqtane.Shared/Shared/Constants.cs
+++ b/Oqtane.Shared/Shared/Constants.cs
@@ -1,14 +1,11 @@
using System;
-using Oqtane.Models;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
namespace Oqtane.Shared
{
public class Constants
{
- public static readonly string Version = "5.0.1";
- public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3,3.1.4,3.2.0,3.2.1,3.3.0,3.3.1,3.4.0,3.4.1,3.4.2,3.4.3,4.0.0,4.0.1,4.0.2,4.0.3,4.0.4,4.0.5,4.0.6,5.0.0,5.0.1";
+ public static readonly string Version = "5.0.2";
+ public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3,3.1.4,3.2.0,3.2.1,3.3.0,3.3.1,3.4.0,3.4.1,3.4.2,3.4.3,4.0.0,4.0.1,4.0.2,4.0.3,4.0.4,4.0.5,4.0.6,5.0.0,5.0.1,5.0.2";
public const string PackageId = "Oqtane.Framework";
public const string ClientId = "Oqtane.Client";
public const string UpdaterPackageId = "Oqtane.Updater";
@@ -80,6 +77,8 @@ namespace Oqtane.Shared
public static readonly string MauiUserAgent = "MAUI";
public static readonly string MauiAliasPath = "Alias-Path";
+ public const string MauiCorsPolicy = "MauiCorsPolicy"; // must be a constant to be used with an attribute
+
public static readonly string VisitorCookiePrefix = "APP_VISITOR_";
// Obsolete constants
diff --git a/Oqtane.Shared/Shared/Utilities.cs b/Oqtane.Shared/Shared/Utilities.cs
index 82b32796..c00d8cc8 100644
--- a/Oqtane.Shared/Shared/Utilities.cs
+++ b/Oqtane.Shared/Shared/Utilities.cs
@@ -572,7 +572,55 @@ namespace Oqtane.Shared
return (localDateTime?.Date, localTime);
}
+ public static bool IsPageModuleVisible(DateTime? effectiveDate, DateTime? expiryDate)
+ {
+ DateTime currentUtcTime = DateTime.UtcNow;
+ if (effectiveDate.HasValue && expiryDate.HasValue)
+ {
+ return currentUtcTime >= effectiveDate.Value && currentUtcTime <= expiryDate.Value;
+ }
+ else if (effectiveDate.HasValue)
+ {
+ return currentUtcTime >= effectiveDate.Value;
+ }
+ else if (expiryDate.HasValue)
+ {
+ // Include equality check here
+ return currentUtcTime <= expiryDate.Value;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ public static bool ValidateEffectiveExpiryDates(DateTime? effectiveDate, DateTime? expiryDate)
+ {
+ // Treat DateTime.MinValue as null
+ effectiveDate ??= DateTime.MinValue;
+ expiryDate ??= DateTime.MinValue;
+
+ // Check if both effectiveDate and expiryDate have values
+ if (effectiveDate != DateTime.MinValue && expiryDate != DateTime.MinValue)
+ {
+ return effectiveDate <= expiryDate;
+ }
+ // Check if only effectiveDate has a value
+ else if (effectiveDate != DateTime.MinValue)
+ {
+ return true;
+ }
+ // Check if only expiryDate has a value
+ else if (expiryDate != DateTime.MinValue)
+ {
+ return true;
+ }
+ // If neither effectiveDate nor expiryDate has a value, consider the page/module visible
+ else
+ {
+ return true;
+ }
+ }
[Obsolete("ContentUrl(Alias alias, int fileId) is deprecated. Use FileUrl(Alias alias, int fileId) instead.", false)]
public static string ContentUrl(Alias alias, int fileId)
{
diff --git a/Oqtane.Updater/Oqtane.Updater.csproj b/Oqtane.Updater/Oqtane.Updater.csproj
index bc4faa12..616bc2b9 100644
--- a/Oqtane.Updater/Oqtane.Updater.csproj
+++ b/Oqtane.Updater/Oqtane.Updater.csproj
@@ -3,7 +3,7 @@
net8.0
Exe
- 5.0.1
+ 5.0.2
Oqtane
Shaun Walker
.NET Foundation
@@ -11,7 +11,7 @@
.NET Foundation
https://www.oqtane.org
https://github.com/oqtane/oqtane.framework/blob/dev/LICENSE
- https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1
+ https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.2
https://github.com/oqtane/oqtane.framework
Git
Oqtane
diff --git a/README.md b/README.md
index 7d6922eb..0ba4b8f4 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Latest Release
-[5.0.0](https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.0) was released on Nov 16, 2023 and is a major release targeted at .NET 8. This release includes 45 pull requests by 4 different contributors, pushing the total number of project commits all-time to over 4300. The Oqtane framework continues to evolve at a rapid pace to meet the needs of .NET developers.
+[5.0.1](https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1) was released on Dec 21, 2023 and is a major release targeted at .NET 8. This release includes 67 pull requests by 6 different contributors, pushing the total number of project commits all-time to over 4400. The Oqtane framework continues to evolve at a rapid pace to meet the needs of .NET developers.
[](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Foqtane%2Foqtane.framework%2Fmaster%2Fazuredeploy.json)
@@ -19,10 +19,18 @@ Please note that this project is owned by the .NET Foundation and is governed by
**Using Version 5:**
- Install **[.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet/8.0)**.
-
+
- Install the latest edition (v17.8 or higher) of [Visual Studio 2022](https://visualstudio.microsoft.com/downloads) with the **ASP.NET and web development** workload enabled. Oqtane works with ALL editions of Visual Studio from Community to Enterprise. If you wish to use LocalDB for development ( not a requirement as Oqtane supports SQLite, mySQL, and PostgreSQL ) you must also install the **Data storage and processing**.
-- clone the Oqtane dev branch source code to your local system. Open the **Oqtane.sln** solution file and Build the solution. Make sure you specify Oqtane.Server as the Startup Project and then Run the application.
+- Clone the Oqtane dev branch source code to your local system.
+
+- Open the **Oqtane.sln** solution file.
+
+- **Important:** Build the solution.
+
+- Make sure you specify Oqtane.Server as the Startup Project
+
+- Run the application.
**Installing an official release:**
@@ -39,6 +47,11 @@ Please note that this project is owned by the .NET Foundation and is governed by
- If you are getting started with Oqtane, a [series of videos](https://www.youtube.com/watch?v=JPfUZPlRRCE&list=PLYhXmd7yV0elLNLfQwZBUlM7ZSMYPTZ_f) are available which explain how to install the product, interact with the user interface, and develop custom modules.
+# Oqtane Marketplace
+
+Explore and enhance your Oqtane experience by visiting the Oqtane Marketplace. Discover a variety of modules, themes, and extensions contributed by the community. [Visit Oqtane Marketplace](https://www.oqtane.net)
+
+
# Documentation
There is a separate [Documentation repository](https://github.com/oqtane/oqtane.docs) which contains a variety of types of documentation for Oqtane, including API documentation that is auto generated using Docfx. The contents of the repository is published to Githib Pages and is available at [https://docs.oqtane.org](https://docs.oqtane.org/)
@@ -53,6 +66,9 @@ Backlog (TBD)
5.1.0 (Q1 2024)
- [ ] Full Stack Blazor (Static Server-Side Rendering)
+[5.0.1](https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.1) (Dec 21, 2023)
+- [x] Stabilization improvements
+
[5.0.0](https://github.com/oqtane/oqtane.framework/releases/tag/v5.0.0) (Nov 16, 2023)
- [x] Migration to .NET 8