diff --git a/Oqtane.Client/Modules/Admin/Modules/Settings.razor b/Oqtane.Client/Modules/Admin/Modules/Settings.razor
index a3133216..9798c2f9 100644
--- a/Oqtane.Client/Modules/Admin/Modules/Settings.razor
+++ b/Oqtane.Client/Modules/Admin/Modules/Settings.razor
@@ -14,10 +14,16 @@
@if (_containers != null)
{
+
@@ -104,6 +110,7 @@
private ElementReference form;
private bool validated = false;
private List
_containers = new List();
+ private string _module;
private string _title;
private string _containerType;
private string _allPages = "false";
@@ -125,6 +132,7 @@
protected override void OnInitialized()
{
+ _module = ModuleState.ModuleDefinition.Name;
_title = ModuleState.Title;
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, PageState.Page.ThemeType);
_containerType = ModuleState.ContainerType;
diff --git a/Oqtane.Client/Modules/Admin/UserProfile/Index.razor b/Oqtane.Client/Modules/Admin/UserProfile/Index.razor
index e1eabc2c..2dd1303d 100644
--- a/Oqtane.Client/Modules/Admin/UserProfile/Index.razor
+++ b/Oqtane.Client/Modules/Admin/UserProfile/Index.razor
@@ -144,6 +144,11 @@ else
@if (notifications != null)
{
+
+
@if (filter == "to")
@@ -159,22 +164,41 @@ else
|
|
- @context.FromDisplayName |
- @context.Subject |
- @string.Format("{0:dd-MMM-yyyy HH:mm:ss}", @context.CreatedOn) |
+
+ @if (context.IsRead)
+ {
+ @context.FromDisplayName |
+ @context.Subject |
+ @string.Format("{0:dd-MMM-yyyy HH:mm:ss}", @context.CreatedOn) |
+ }
+ else
+ {
+ @context.FromDisplayName |
+ @context.Subject |
+ @string.Format("{0:dd-MMM-yyyy HH:mm:ss}", @context.CreatedOn) |
+ }
|
@{
- string input = "___";
- if (context.Body.Contains(input))
- {
- context.Body = context.Body.Split(input)[0];
- context.Body = context.Body.Replace("\n", "");
- context.Body = context.Body.Replace("\r", "");
- } }
- @(context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body)
+ string input = "___";
+ if (context.Body.Contains(input))
+ {
+ context.Body = context.Body.Split(input)[0];
+ context.Body = context.Body.Replace("\n", "");
+ context.Body = context.Body.Replace("\r", "");
+ }
+ notificationSummary = context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body;
+ }
+ @if (context.IsRead)
+ {
+ @notificationSummary
+ }
+ else
+ {
+ @notificationSummary
+ }
|
@@ -192,22 +216,42 @@ else
|
|
- @context.ToDisplayName |
- @context.Subject |
- @string.Format("{0:dd-MMM-yyyy HH:mm:ss}", @context.CreatedOn) |
+
+ @if (context.IsRead)
+ {
+ @context.ToDisplayName |
+ @context.Subject |
+ @string.Format("{0:dd-MMM-yyyy HH:mm:ss}", @context.CreatedOn) |
+ }
+ else
+ {
+ @context.ToDisplayName |
+ @context.Subject |
+ @string.Format("{0:dd-MMM-yyyy HH:mm:ss}", @context.CreatedOn) |
+ }
+
|
@{
- string input = "___";
- if (context.Body.Contains(input))
- {
- context.Body = context.Body.Split(input)[0];
- context.Body = context.Body.Replace("\n", "");
- context.Body = context.Body.Replace("\r", "");
- } }
- @(context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body)
+ string input = "___";
+ if (context.Body.Contains(input))
+ {
+ context.Body = context.Body.Split(input)[0];
+ context.Body = context.Body.Replace("\n", "");
+ context.Body = context.Body.Replace("\r", "");
+ }
+ notificationSummary = context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body;
+ }
+ @if (context.IsRead)
+ {
+ @notificationSummary
+ }
+ else
+ {
+ @notificationSummary
+ }
|
@@ -217,11 +261,6 @@ else
}
-
-
}
@@ -246,6 +285,7 @@ else
private string category = string.Empty;
private string filter = "to";
private List notifications;
+ private string notificationSummary = string.Empty;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
diff --git a/Oqtane.Client/Modules/Admin/UserProfile/View.razor b/Oqtane.Client/Modules/Admin/UserProfile/View.razor
index 947a6c7b..58a3d211 100644
--- a/Oqtane.Client/Modules/Admin/UserProfile/View.razor
+++ b/Oqtane.Client/Modules/Admin/UserProfile/View.razor
@@ -118,6 +118,9 @@
Notification notification = await NotificationService.GetNotificationAsync(notificationid);
if (notification != null)
{
+ notification.IsRead = true;
+ notification = await NotificationService.UpdateNotificationAsync(notification);
+
int userid = -1;
if (notification.ToUserId == PageState.User.UserId)
{
diff --git a/Oqtane.Client/Modules/Controls/FileManager.razor b/Oqtane.Client/Modules/Controls/FileManager.razor
index 97363437..2146ead7 100644
--- a/Oqtane.Client/Modules/Controls/FileManager.razor
+++ b/Oqtane.Client/Modules/Controls/FileManager.razor
@@ -219,7 +219,14 @@
if (folder != null)
{
_haseditpermission = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, folder.PermissionList);
- _files = await FileService.GetFilesAsync(FolderId);
+ if (UserSecurity.IsAuthorized(PageState.User, PermissionNames.Browse, folder.PermissionList))
+ {
+ _files = await FileService.GetFilesAsync(FolderId);
+ }
+ else
+ {
+ _files = new List();
+ }
}
else
{
@@ -322,27 +329,29 @@
var folder = (Folder == Constants.PackagesFolder) ? Folder : FolderId.ToString();
await interop.UploadFiles(posturl, folder, _guid, SiteState.AntiForgeryToken);
- // 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
- bool success = false;
- int attempts = 0;
- while (attempts < 5 && !success)
+ // uploading is asynchronous so we need to poll to determine if uploads are completed
+ var success = true;
+ int upload = 0;
+ while (upload < uploads.Length && success)
{
- attempts += 1;
- Thread.Sleep(1000 * attempts); // progressive retry
-
- success = true;
- List files = await FileService.GetFilesAsync(folder);
- if (files.Count > 0)
+ success = false;
+ // note that progressive retry will only wait a maximum of 15 seconds which may not be long enough for very large file uploads
+ int attempts = 0;
+ while (attempts < 5 && !success)
{
- foreach (string upload in uploads)
+ attempts += 1;
+ Thread.Sleep(1000 * attempts); // progressive retry
+
+ var file = await FileService.GetFileAsync(int.Parse(folder), uploads[upload]);
+ if (file != null)
{
- if (!files.Exists(item => item.Name == upload))
- {
- success = false;
- }
+ success = true;
}
}
+ if (success)
+ {
+ upload++;
+ }
}
// reset progress indicators
@@ -372,14 +381,14 @@
else
{
// set FileId to first file in upload collection
- await GetFiles();
- var file = _files.Where(item => item.Name == uploads[0]).FirstOrDefault();
+ var file = await FileService.GetFileAsync(int.Parse(folder), uploads[0]);
if (file != null)
{
FileId = file.FileId;
await SetImage();
await OnUpload.InvokeAsync(FileId);
}
+ await GetFiles();
StateHasChanged();
}
}
diff --git a/Oqtane.Client/Modules/Controls/Section.razor b/Oqtane.Client/Modules/Controls/Section.razor
index 115e352d..928f1edc 100644
--- a/Oqtane.Client/Modules/Controls/Section.razor
+++ b/Oqtane.Client/Modules/Controls/Section.razor
@@ -17,7 +17,10 @@
- @ChildContent
+ @if (ChildContent != null)
+ {
+ @ChildContent
+ }
@code {
@@ -26,7 +29,7 @@
private string _show = string.Empty;
[Parameter]
- public RenderFragment ChildContent { get; set; }
+ public RenderFragment ChildContent { get; set; } = null;
[Parameter]
public string Name { get; set; } // required - the name of the section
diff --git a/Oqtane.Client/Modules/ModuleBase.cs b/Oqtane.Client/Modules/ModuleBase.cs
index 8023da67..f1a086e5 100644
--- a/Oqtane.Client/Modules/ModuleBase.cs
+++ b/Oqtane.Client/Modules/ModuleBase.cs
@@ -9,7 +9,6 @@ using Oqtane.UI;
using System.Collections.Generic;
using Microsoft.JSInterop;
using System.Linq;
-using Oqtane.Themes;
namespace Oqtane.Modules
{
diff --git a/Oqtane.Client/Oqtane.Client.csproj b/Oqtane.Client/Oqtane.Client.csproj
index 19f19354..ae3e2589 100644
--- a/Oqtane.Client/Oqtane.Client.csproj
+++ b/Oqtane.Client/Oqtane.Client.csproj
@@ -4,7 +4,7 @@
net7.0
Exe
Debug;Release
-
4.0.0
+
4.0.1
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/v4.0.0
+
https://github.com/oqtane/oqtane.framework/releases/tag/v4.0.1
https://github.com/oqtane/oqtane.framework
Git
Oqtane
diff --git a/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx b/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx
index 7cd012dd..db947070 100644
--- a/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx
+++ b/Oqtane.Client/Resources/Modules/Admin/Modules/Settings.resx
@@ -150,4 +150,10 @@
A Problem Was Encountered Loading Module {0}. The Module Is Either Invalid Or Does Not Exist.
+
+ The name of the module
+
+
+ Module:
+
\ No newline at end of file
diff --git a/Oqtane.Client/Services/FileService.cs b/Oqtane.Client/Services/FileService.cs
index 3fef5c6e..05d3adff 100644
--- a/Oqtane.Client/Services/FileService.cs
+++ b/Oqtane.Client/Services/FileService.cs
@@ -46,6 +46,11 @@ namespace Oqtane.Services
return await GetJsonAsync
($"{Apiurl}/{fileId}");
}
+ public async Task GetFileAsync(int folderId, string name)
+ {
+ return await GetJsonAsync($"{Apiurl}/name/{name}/{folderId}");
+ }
+
public async Task AddFileAsync(File file)
{
return await PostJsonAsync(Apiurl, file);
diff --git a/Oqtane.Client/Services/Interfaces/IFileService.cs b/Oqtane.Client/Services/Interfaces/IFileService.cs
index 66553b0c..1174947f 100644
--- a/Oqtane.Client/Services/Interfaces/IFileService.cs
+++ b/Oqtane.Client/Services/Interfaces/IFileService.cs
@@ -1,5 +1,6 @@
using Oqtane.Models;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
namespace Oqtane.Services
@@ -33,6 +34,15 @@ namespace Oqtane.Services
///
Task GetFileAsync(int fileId);
+ ///
+ /// Get a based on the and file name.
+ ///
+ /// Reference to the
+ /// name of the file
+ ///
+ ///
+ Task GetFileAsync(int folderId, string name);
+
///
/// Add / store a record.
/// This does not contain the file contents.
diff --git a/Oqtane.Client/Services/Interfaces/INotificationService.cs b/Oqtane.Client/Services/Interfaces/INotificationService.cs
index d1be32a2..a831dd5d 100644
--- a/Oqtane.Client/Services/Interfaces/INotificationService.cs
+++ b/Oqtane.Client/Services/Interfaces/INotificationService.cs
@@ -18,6 +18,27 @@ namespace Oqtane.Services
///
Task> GetNotificationsAsync(int siteId, string direction, int userId);
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task> GetNotificationsAsync(int siteId, string direction, int userId, int count, bool isRead);
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task GetNotificationCountAsync(int siteId, string direction, int userId, bool isRead);
+
///
/// Returns a specific notifications
///
diff --git a/Oqtane.Client/Services/Interfaces/IPackageService.cs b/Oqtane.Client/Services/Interfaces/IPackageService.cs
index f8617439..4ace8cc8 100644
--- a/Oqtane.Client/Services/Interfaces/IPackageService.cs
+++ b/Oqtane.Client/Services/Interfaces/IPackageService.cs
@@ -27,6 +27,17 @@ namespace Oqtane.Services
///
Task> GetPackagesAsync(string type, string search, string price, string package);
+ ///
+ /// Returns a list of packages matching the given parameters
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task> GetPackagesAsync(string type, string search, string price, string package, string sort);
+
///
/// Returns a specific package
///
diff --git a/Oqtane.Client/Services/NotificationService.cs b/Oqtane.Client/Services/NotificationService.cs
index 3368ff0b..f6fd1585 100644
--- a/Oqtane.Client/Services/NotificationService.cs
+++ b/Oqtane.Client/Services/NotificationService.cs
@@ -22,6 +22,20 @@ namespace Oqtane.Services
return notifications.OrderByDescending(item => item.CreatedOn).ToList();
}
+ public async Task> GetNotificationsAsync(int siteId, string direction, int userId, int count, bool isRead)
+ {
+ var notifications = await GetJsonAsync>($"{Apiurl}/read?siteid={siteId}&direction={direction.ToLower()}&userid={userId}&count={count}&isread={isRead}");
+
+ return notifications.OrderByDescending(item => item.CreatedOn).ToList();
+ }
+
+ public async Task GetNotificationCountAsync(int siteId, string direction, int userId, bool isRead)
+ {
+ var notificationCount = await GetJsonAsync($"{Apiurl}/read-count?siteid={siteId}&direction={direction.ToLower()}&userid={userId}&isread={isRead}");
+
+ return notificationCount;
+ }
+
public async Task GetNotificationAsync(int notificationId)
{
return await GetJsonAsync($"{Apiurl}/{notificationId}");
diff --git a/Oqtane.Client/Services/PackageService.cs b/Oqtane.Client/Services/PackageService.cs
index a45c73e6..78752d38 100644
--- a/Oqtane.Client/Services/PackageService.cs
+++ b/Oqtane.Client/Services/PackageService.cs
@@ -23,7 +23,12 @@ namespace Oqtane.Services
public async Task> GetPackagesAsync(string type, string search, string price, string package)
{
- return await GetJsonAsync>($"{Apiurl}?type={type}&search={WebUtility.UrlEncode(search)}&price={price}&package={package}");
+ return await GetPackagesAsync(type, search, price, package, "");
+ }
+
+ public async Task> GetPackagesAsync(string type, string search, string price, string package, string sort)
+ {
+ return await GetJsonAsync>($"{Apiurl}?type={type}&search={WebUtility.UrlEncode(search)}&price={price}&package={package}&sort={sort}");
}
public async Task GetPackageAsync(string packageId, string version)
diff --git a/Oqtane.Client/Services/ServiceBase.cs b/Oqtane.Client/Services/ServiceBase.cs
index a5e7fd26..00b2412a 100644
--- a/Oqtane.Client/Services/ServiceBase.cs
+++ b/Oqtane.Client/Services/ServiceBase.cs
@@ -21,7 +21,7 @@ namespace Oqtane.Services
_siteState = siteState;
}
- private HttpClient GetHttpClient()
+ public HttpClient GetHttpClient()
{
if (!_httpClient.DefaultRequestHeaders.Contains(Constants.AntiForgeryTokenHeaderName) && _siteState != null && !string.IsNullOrEmpty(_siteState.AntiForgeryToken))
{
@@ -206,7 +206,6 @@ namespace Oqtane.Services
Console.WriteLine($"Request: {response.RequestMessage.RequestUri}");
Console.WriteLine($"Response status: {response.StatusCode} {response.ReasonPhrase}");
}
-
return false;
}
diff --git a/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor b/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor
index 4c3f9f0c..d35268a2 100644
--- a/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor
+++ b/Oqtane.Client/Themes/Controls/Theme/ControlPanel.razor
@@ -36,7 +36,7 @@
@if (_canViewAdminDashboard || UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.PermissionList))
{
-
@code {
- private string resourceType = "[Owner].[Module].Settings, [Owner].[Module].Client.Oqtane"; // for localization
+ private string resourceType = "[Owner].Module.[Module].Settings, [Owner].Module.[Module].Client.Oqtane"; // for localization
public override string Title => "[Module] Settings";
string _value;
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/[Owner].Module.[Module].sln b/Oqtane.Server/wwwroot/Modules/Templates/External/[Owner].Module.[Module].sln
index a9cbde70..e8622beb 100644
--- a/Oqtane.Server/wwwroot/Modules/Templates/External/[Owner].Module.[Module].sln
+++ b/Oqtane.Server/wwwroot/Modules/Templates/External/[Owner].Module.[Module].sln
@@ -20,9 +20,7 @@ Global
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Release|Any CPU.Build.0 = Release|Any CPU
{AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Release|Any CPU.ActiveCfg = Release|Any CPU
diff --git a/Oqtane.Server/wwwroot/Packages/Oqtane.Database.MySQL.nupkg.bak b/Oqtane.Server/wwwroot/Packages/Oqtane.Database.MySQL.nupkg.bak
index 72e692cf..47ba984b 100644
Binary files a/Oqtane.Server/wwwroot/Packages/Oqtane.Database.MySQL.nupkg.bak and b/Oqtane.Server/wwwroot/Packages/Oqtane.Database.MySQL.nupkg.bak differ
diff --git a/Oqtane.Server/wwwroot/Packages/Oqtane.Database.PostgreSQL.nupkg.bak b/Oqtane.Server/wwwroot/Packages/Oqtane.Database.PostgreSQL.nupkg.bak
index ab6529ff..ee3324c0 100644
Binary files a/Oqtane.Server/wwwroot/Packages/Oqtane.Database.PostgreSQL.nupkg.bak and b/Oqtane.Server/wwwroot/Packages/Oqtane.Database.PostgreSQL.nupkg.bak differ
diff --git a/Oqtane.Server/wwwroot/Packages/Oqtane.Database.SqlServer.nupkg.bak b/Oqtane.Server/wwwroot/Packages/Oqtane.Database.SqlServer.nupkg.bak
index e9cd97e6..603f3fd1 100644
Binary files a/Oqtane.Server/wwwroot/Packages/Oqtane.Database.SqlServer.nupkg.bak and b/Oqtane.Server/wwwroot/Packages/Oqtane.Database.SqlServer.nupkg.bak differ
diff --git a/Oqtane.Server/wwwroot/Packages/Oqtane.Database.Sqlite.nupkg.bak b/Oqtane.Server/wwwroot/Packages/Oqtane.Database.Sqlite.nupkg.bak
index 054330c8..697d02f4 100644
Binary files a/Oqtane.Server/wwwroot/Packages/Oqtane.Database.Sqlite.nupkg.bak and b/Oqtane.Server/wwwroot/Packages/Oqtane.Database.Sqlite.nupkg.bak differ
diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/[Owner].Theme.[Theme].sln b/Oqtane.Server/wwwroot/Themes/Templates/External/[Owner].Theme.[Theme].sln
index 94aa3841..cd9d50da 100644
--- a/Oqtane.Server/wwwroot/Themes/Templates/External/[Owner].Theme.[Theme].sln
+++ b/Oqtane.Server/wwwroot/Themes/Templates/External/[Owner].Theme.[Theme].sln
@@ -16,9 +16,7 @@ Global
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {3AB6FCC9-EFEB-4C0E-A2CF-8103914C5196}.Release|Any CPU.Build.0 = Release|Any CPU
{AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Release|Any CPU.ActiveCfg = Release|Any CPU
diff --git a/Oqtane.Shared/Models/Notification.cs b/Oqtane.Shared/Models/Notification.cs
index 975b28c8..d7e08c01 100644
--- a/Oqtane.Shared/Models/Notification.cs
+++ b/Oqtane.Shared/Models/Notification.cs
@@ -94,6 +94,10 @@ namespace Oqtane.Models
///
public DateTime? SendOn { get; set; }
+ ///