[ENHANCE] - Added IsRead property to Notifications
Fixed Version to Tenant.04.00.01.01 and reverted the Program.cs back to the way it was This reverts commit 82fef82c4f29115a3c9f2ffefbae355ce24605e6. [ENHANCE] - Added API to get Count of New Notifications based on IsRead Fixed Typo in Notification Controller [ENHANCE] - Added API to get Notifications by Count and IsRead
This commit is contained in:
parent
563695cdfa
commit
b7de4b81a6
@ -159,9 +159,19 @@ else
|
|||||||
<Row>
|
<Row>
|
||||||
<td><ActionLink Action="View" Parameters="@($"id=" + context.NotificationId.ToString())" Security="SecurityAccessLevel.View" EditMode="false" ResourceKey="ViewNotification" /></td>
|
<td><ActionLink Action="View" Parameters="@($"id=" + context.NotificationId.ToString())" Security="SecurityAccessLevel.View" EditMode="false" ResourceKey="ViewNotification" /></td>
|
||||||
<td><ActionDialog Header="Delete Notification" Message="Are You Sure You Wish To Delete This Notification?" Action="Delete" Security="SecurityAccessLevel.View" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" EditMode="false" ResourceKey="DeleteNotification" /></td>
|
<td><ActionDialog Header="Delete Notification" Message="Are You Sure You Wish To Delete This Notification?" Action="Delete" Security="SecurityAccessLevel.View" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" EditMode="false" ResourceKey="DeleteNotification" /></td>
|
||||||
|
|
||||||
|
@if (context.IsRead)
|
||||||
|
{
|
||||||
<td>@context.FromDisplayName</td>
|
<td>@context.FromDisplayName</td>
|
||||||
<td>@context.Subject</td>
|
<td>@context.Subject</td>
|
||||||
<td>@string.Format("{0:dd-MMM-yyyy HH:mm:ss}", @context.CreatedOn)</td>
|
<td>@string.Format("{0:dd-MMM-yyyy HH:mm:ss}", @context.CreatedOn)</td>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<td><b>@context.FromDisplayName</b></td>
|
||||||
|
<td><b>@context.Subject</b></td>
|
||||||
|
<td><b>@string.Format("{0:dd-MMM-yyyy HH:mm:ss}", @context.CreatedOn)</b></td>
|
||||||
|
}
|
||||||
</Row>
|
</Row>
|
||||||
<Detail>
|
<Detail>
|
||||||
<td colspan="2"></td>
|
<td colspan="2"></td>
|
||||||
@ -173,8 +183,17 @@ else
|
|||||||
context.Body = context.Body.Split(input)[0];
|
context.Body = context.Body.Split(input)[0];
|
||||||
context.Body = context.Body.Replace("\n", "");
|
context.Body = context.Body.Replace("\n", "");
|
||||||
context.Body = context.Body.Replace("\r", "");
|
context.Body = context.Body.Replace("\r", "");
|
||||||
} }
|
}
|
||||||
@(context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body)
|
notificationSummary = context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body;
|
||||||
|
}
|
||||||
|
@if (context.IsRead)
|
||||||
|
{
|
||||||
|
@notificationSummary
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<b>@notificationSummary</b>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</Detail>
|
</Detail>
|
||||||
</Pager>
|
</Pager>
|
||||||
@ -192,9 +211,20 @@ else
|
|||||||
<Row>
|
<Row>
|
||||||
<td><ActionLink Action="View" Parameters="@($"id=" + context.NotificationId.ToString())" Security="SecurityAccessLevel.View" EditMode="false" ResourceKey="ViewNotification" /></td>
|
<td><ActionLink Action="View" Parameters="@($"id=" + context.NotificationId.ToString())" Security="SecurityAccessLevel.View" EditMode="false" ResourceKey="ViewNotification" /></td>
|
||||||
<td><ActionDialog Header="Delete Notification" Message="Are You Sure You Wish To Delete This Notification?" Action="Delete" Security="SecurityAccessLevel.View" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" EditMode="false" ResourceKey="DeleteNotification" /></td>
|
<td><ActionDialog Header="Delete Notification" Message="Are You Sure You Wish To Delete This Notification?" Action="Delete" Security="SecurityAccessLevel.View" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" EditMode="false" ResourceKey="DeleteNotification" /></td>
|
||||||
|
|
||||||
|
@if (context.IsRead)
|
||||||
|
{
|
||||||
<td>@context.ToDisplayName</td>
|
<td>@context.ToDisplayName</td>
|
||||||
<td>@context.Subject</td>
|
<td>@context.Subject</td>
|
||||||
<td>@string.Format("{0:dd-MMM-yyyy HH:mm:ss}", @context.CreatedOn)</td>
|
<td>@string.Format("{0:dd-MMM-yyyy HH:mm:ss}", @context.CreatedOn)</td>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<td><b>@context.ToDisplayName</b></td>
|
||||||
|
<td><b>@context.Subject</b></td>
|
||||||
|
<td><b>@string.Format("{0:dd-MMM-yyyy HH:mm:ss}", @context.CreatedOn)</b></td>
|
||||||
|
}
|
||||||
|
|
||||||
</Row>
|
</Row>
|
||||||
<Detail>
|
<Detail>
|
||||||
<td colspan="2"></td>
|
<td colspan="2"></td>
|
||||||
@ -206,8 +236,17 @@ else
|
|||||||
context.Body = context.Body.Split(input)[0];
|
context.Body = context.Body.Split(input)[0];
|
||||||
context.Body = context.Body.Replace("\n", "");
|
context.Body = context.Body.Replace("\n", "");
|
||||||
context.Body = context.Body.Replace("\r", "");
|
context.Body = context.Body.Replace("\r", "");
|
||||||
} }
|
}
|
||||||
@(context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body)
|
notificationSummary = context.Body.Length > 100 ? (context.Body.Substring(0, 97) + "...") : context.Body;
|
||||||
|
}
|
||||||
|
@if (context.IsRead)
|
||||||
|
{
|
||||||
|
@notificationSummary
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<b>@notificationSummary</b>
|
||||||
|
}
|
||||||
</td>
|
</td>
|
||||||
</Detail>
|
</Detail>
|
||||||
</Pager>
|
</Pager>
|
||||||
@ -246,6 +285,7 @@ else
|
|||||||
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;
|
||||||
|
private string notificationSummary = string.Empty;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
|
||||||
|
|
||||||
|
@ -118,6 +118,9 @@
|
|||||||
Notification notification = await NotificationService.GetNotificationAsync(notificationid);
|
Notification notification = await NotificationService.GetNotificationAsync(notificationid);
|
||||||
if (notification != null)
|
if (notification != null)
|
||||||
{
|
{
|
||||||
|
notification.IsRead = true;
|
||||||
|
notification = await NotificationService.UpdateNotificationAsync(notification);
|
||||||
|
|
||||||
int userid = -1;
|
int userid = -1;
|
||||||
if (notification.ToUserId == PageState.User.UserId)
|
if (notification.ToUserId == PageState.User.UserId)
|
||||||
{
|
{
|
||||||
|
@ -18,6 +18,27 @@ namespace Oqtane.Services
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<List<Notification>> GetNotificationsAsync(int siteId, string direction, int userId);
|
Task<List<Notification>> GetNotificationsAsync(int siteId, string direction, int userId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="direction"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="count"></param>
|
||||||
|
/// <param name="isRead"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<List<Notification>> GetNotificationsAsync(int siteId, string direction, int userId, int count, bool isRead);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="siteId"></param>
|
||||||
|
/// <param name="direction"></param>
|
||||||
|
/// <param name="userId"></param>
|
||||||
|
/// <param name="isRead"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<int> GetNotificationCountAsync(int siteId, string direction, int userId, bool isRead);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a specific notifications
|
/// Returns a specific notifications
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -22,6 +22,20 @@ namespace Oqtane.Services
|
|||||||
return notifications.OrderByDescending(item => item.CreatedOn).ToList();
|
return notifications.OrderByDescending(item => item.CreatedOn).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<List<Notification>> GetNotificationsAsync(int siteId, string direction, int userId, int count, bool isRead)
|
||||||
|
{
|
||||||
|
var notifications = await GetJsonAsync<List<Notification>>($"{Apiurl}/read?siteid={siteId}&direction={direction.ToLower()}&userid={userId}&count={count}&isread={isRead}");
|
||||||
|
|
||||||
|
return notifications.OrderByDescending(item => item.CreatedOn).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> GetNotificationCountAsync(int siteId, string direction, int userId, bool isRead)
|
||||||
|
{
|
||||||
|
var notificationCount = await GetJsonAsync<int>($"{Apiurl}/read-count?siteid={siteId}&direction={direction.ToLower()}&userid={userId}&isread={isRead}");
|
||||||
|
|
||||||
|
return notificationCount;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<Notification> GetNotificationAsync(int notificationId)
|
public async Task<Notification> GetNotificationAsync(int notificationId)
|
||||||
{
|
{
|
||||||
return await GetJsonAsync<Notification>($"{Apiurl}/{notificationId}");
|
return await GetJsonAsync<Notification>($"{Apiurl}/{notificationId}");
|
||||||
|
@ -9,6 +9,9 @@ using Oqtane.Repository;
|
|||||||
using Oqtane.Security;
|
using Oqtane.Security;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Reflection.Metadata;
|
using System.Reflection.Metadata;
|
||||||
|
using Microsoft.Extensions.Localization;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Oqtane.Controllers
|
namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
@ -30,6 +33,72 @@ namespace Oqtane.Controllers
|
|||||||
_alias = tenantManager.GetAlias();
|
_alias = tenantManager.GetAlias();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GET: api/<controller>/read?siteid=x&direction=to&userid=1&count=5&isread=false
|
||||||
|
[HttpGet("read")]
|
||||||
|
[Authorize(Roles = RoleNames.Registered)]
|
||||||
|
public IEnumerable<Notification> Get(string siteid, string direction, string userid, string count, string isread)
|
||||||
|
{
|
||||||
|
IEnumerable<Notification> notifications = null;
|
||||||
|
|
||||||
|
int SiteId;
|
||||||
|
int UserId;
|
||||||
|
int Count;
|
||||||
|
bool IsRead;
|
||||||
|
if (int.TryParse(siteid, out SiteId) && SiteId == _alias.SiteId && int.TryParse(userid, out UserId) && int.TryParse(count, out Count) && bool.TryParse(isread, out IsRead) && IsAuthorized(UserId))
|
||||||
|
{
|
||||||
|
if (direction == "to")
|
||||||
|
{
|
||||||
|
notifications = _notifications.GetNotifications(SiteId, -1, UserId, Count, IsRead);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
notifications = _notifications.GetNotifications(SiteId, UserId, -1, Count, IsRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Notification Get Attempt {SiteId} {Direction} {UserId} {Count} {isRead}", siteid, direction, userid, count, isread);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
|
notifications = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return notifications;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET: api/<controller>/read?siteid=x&direction=to&userid=1&count=5&isread=false
|
||||||
|
[HttpGet("read-count")]
|
||||||
|
[Authorize(Roles = RoleNames.Registered)]
|
||||||
|
public int Get(string siteid, string direction, string userid, string isread)
|
||||||
|
{
|
||||||
|
int notificationsCount = 0;
|
||||||
|
|
||||||
|
int SiteId;
|
||||||
|
int UserId;
|
||||||
|
bool IsRead;
|
||||||
|
if (int.TryParse(siteid, out SiteId) && SiteId == _alias.SiteId && int.TryParse(userid, out UserId) && bool.TryParse(isread, out IsRead) && IsAuthorized(UserId))
|
||||||
|
{
|
||||||
|
if (direction == "to")
|
||||||
|
{
|
||||||
|
notificationsCount = _notifications.GetNotificationCount(SiteId, -1, UserId, IsRead);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
notificationsCount = _notifications.GetNotificationCount(SiteId, UserId, -1, IsRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Notification Get Attempt {SiteId} {Direction} {UserId} {isRead}", siteid, direction, userid, isread);
|
||||||
|
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
|
||||||
|
notificationsCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return notificationsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// GET: api/<controller>?siteid=x&type=y&userid=z
|
// GET: api/<controller>?siteid=x&type=y&userid=z
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
[Authorize(Roles = RoleNames.Registered)]
|
[Authorize(Roles = RoleNames.Registered)]
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Oqtane.Databases.Interfaces;
|
||||||
|
using Oqtane.Migrations.EntityBuilders;
|
||||||
|
using Oqtane.Repository;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
namespace Oqtane.Migrations.Tenant
|
||||||
|
{
|
||||||
|
[DbContext(typeof(TenantDBContext))]
|
||||||
|
[Migration("Tenant.04.00.01.01")]
|
||||||
|
public class AddNotificationIsRead : MultiDatabaseMigration
|
||||||
|
{
|
||||||
|
|
||||||
|
public AddNotificationIsRead(IDatabase database) : base(database)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
notificationEntityBuilder.AddBooleanColumn("IsRead", false);
|
||||||
|
notificationEntityBuilder.UpdateColumn("IsRead", "1", "bool", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
var notificationEntityBuilder = new NotificationEntityBuilder(migrationBuilder, ActiveDatabase);
|
||||||
|
notificationEntityBuilder.DropColumn("IsPublic");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -6,6 +6,8 @@ namespace Oqtane.Repository
|
|||||||
public interface INotificationRepository
|
public interface INotificationRepository
|
||||||
{
|
{
|
||||||
IEnumerable<Notification> GetNotifications(int siteId, int fromUserId, int toUserId);
|
IEnumerable<Notification> GetNotifications(int siteId, int fromUserId, int toUserId);
|
||||||
|
IEnumerable<Notification> GetNotifications(int siteId, int fromUserId, int toUserId, int count, bool isRead);
|
||||||
|
int GetNotificationCount(int siteId, int fromUserId, int toUserId, bool isRead);
|
||||||
Notification AddNotification(Notification notification);
|
Notification AddNotification(Notification notification);
|
||||||
Notification UpdateNotification(Notification notification);
|
Notification UpdateNotification(Notification notification);
|
||||||
Notification GetNotification(int notificationId);
|
Notification GetNotification(int notificationId);
|
||||||
|
@ -33,6 +33,52 @@ namespace Oqtane.Repository
|
|||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Notification> GetNotifications(int siteId, int fromUserId, int toUserId, int count, bool isRead)
|
||||||
|
{
|
||||||
|
if (toUserId == -1 && fromUserId == -1)
|
||||||
|
{
|
||||||
|
return _db.Notification
|
||||||
|
.Where(item => item.SiteId == siteId)
|
||||||
|
.Where(item => item.IsDelivered == false && item.IsDeleted == false)
|
||||||
|
.Where(item => item.SendOn == null || item.SendOn < System.DateTime.UtcNow)
|
||||||
|
.Where(item => item.IsRead == isRead)
|
||||||
|
.ToList()
|
||||||
|
.Take(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _db.Notification
|
||||||
|
.Where(item => item.SiteId == siteId)
|
||||||
|
.Where(item => item.ToUserId == toUserId || toUserId == -1)
|
||||||
|
.Where(item => item.FromUserId == fromUserId || fromUserId == -1)
|
||||||
|
.Where(item => item.IsRead == isRead)
|
||||||
|
.ToList()
|
||||||
|
.Take(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetNotificationCount(int siteId, int fromUserId, int toUserId, bool isRead)
|
||||||
|
{
|
||||||
|
if (toUserId == -1 && fromUserId == -1)
|
||||||
|
{
|
||||||
|
return _db.Notification
|
||||||
|
.Where(item => item.SiteId == siteId)
|
||||||
|
.Where(item => item.IsDelivered == false && item.IsDeleted == false)
|
||||||
|
.Where(item => item.SendOn == null || item.SendOn < System.DateTime.UtcNow)
|
||||||
|
.Where(item => item.IsRead == isRead)
|
||||||
|
.ToList()
|
||||||
|
.Count();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return _db.Notification
|
||||||
|
.Where(item => item.SiteId == siteId)
|
||||||
|
.Where(item => item.ToUserId == toUserId || toUserId == -1)
|
||||||
|
.Where(item => item.FromUserId == fromUserId || fromUserId == -1)
|
||||||
|
.Where(item => item.IsRead == isRead)
|
||||||
|
.ToList()
|
||||||
|
.Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Notification AddNotification(Notification notification)
|
public Notification AddNotification(Notification notification)
|
||||||
{
|
{
|
||||||
_db.Notification.Add(notification);
|
_db.Notification.Add(notification);
|
||||||
|
@ -94,6 +94,10 @@ namespace Oqtane.Models
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime? SendOn { get; set; }
|
public DateTime? SendOn { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If it has been read. See also <see cref="IsDelivered" />
|
||||||
|
/// </summary>
|
||||||
|
public bool IsRead { get; set; }
|
||||||
|
|
||||||
// constructors
|
// constructors
|
||||||
public Notification() {}
|
public Notification() {}
|
||||||
@ -174,6 +178,7 @@ namespace Oqtane.Models
|
|||||||
}
|
}
|
||||||
IsDelivered = false;
|
IsDelivered = false;
|
||||||
DeliveredOn = null;
|
DeliveredOn = null;
|
||||||
|
IsRead = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user