Merge pull request #3443 from sbwalker/net8

fixes to notifications UI in user profile
This commit is contained in:
Shaun Walker
2023-10-24 08:41:20 -04:00
committed by GitHub
6 changed files with 146 additions and 123 deletions

View File

@ -2,6 +2,7 @@
@inherits ModuleBase @inherits ModuleBase
@inject NavigationManager NavigationManager @inject NavigationManager NavigationManager
@inject IUserService UserService @inject IUserService UserService
@inject IUserRoleService UserRoleService
@inject INotificationService NotificationService @inject INotificationService NotificationService
@inject IStringLocalizer<Add> Localizer @inject IStringLocalizer<Add> Localizer
@inject IStringLocalizer<SharedResources> SharedLocalizer @inject IStringLocalizer<SharedResources> SharedLocalizer
@ -10,10 +11,10 @@
{ {
<div class="container"> <div class="container">
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="to" HelpText="Enter the username you wish to send a message to" ResourceKey="To">To: </Label> <Label Class="col-sm-3" For="to" HelpText="Enter the user you wish to send a message to" ResourceKey="To">To: </Label>
<div class="col-sm-9"> <div class="col-sm-9">
<input id="to" class="form-control" @bind="@username" /> <AutoComplete OnSearch="GetUsers" Placeholder="@Localizer["Username.Enter"]" @ref="username" />
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="subject" HelpText="Enter the subject of the message" ResourceKey="Subject">Subject: </Label> <Label Class="col-sm-3" For="subject" HelpText="Enter the subject of the message" ResourceKey="Subject">Subject: </Label>
@ -30,11 +31,11 @@
</div> </div>
<br/> <br/>
<button type="button" class="btn btn-primary" @onclick="Send">@SharedLocalizer["Send"]</button> <button type="button" class="btn btn-primary" @onclick="Send">@SharedLocalizer["Send"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink> <NavLink class="btn btn-secondary" href="@PageState.ReturnUrl">@SharedLocalizer["Cancel"]</NavLink>
} }
@code { @code {
private string username = ""; private AutoComplete username;
private string subject = ""; private string subject = "";
private string body = ""; private string body = "";
@ -42,21 +43,35 @@
public override string Title => "Send Notification"; public override string Title => "Send Notification";
private async Task<Dictionary<string, string>> GetUsers(string filter)
{
var users = await UserRoleService.GetUserRolesAsync(PageState.Site.SiteId, RoleNames.Registered);
return users.Where(item => item.User.Username.Contains(filter, StringComparison.OrdinalIgnoreCase))
.ToDictionary(item => item.UserId.ToString(), item => item.User.Username);
}
private async Task Send() private async Task Send()
{ {
try try
{ {
var user = await UserService.GetUserAsync(username, PageState.Site.SiteId); if (!string.IsNullOrEmpty(username.Key) && !string.IsNullOrEmpty(subject))
if (user != null)
{ {
var notification = new Notification(PageState.Site.SiteId, PageState.User, user, subject, body); var user = await UserService.GetUserAsync(int.Parse(username.Key), ModuleState.SiteId);
notification = await NotificationService.AddNotificationAsync(notification); if (user != null)
await logger.LogInformation("Notification Created {NotificationId}", notification.NotificationId); {
NavigationManager.NavigateTo(NavigateUrl()); var notification = new Notification(PageState.Site.SiteId, PageState.User, user, subject, body);
notification = await NotificationService.AddNotificationAsync(notification);
await logger.LogInformation("Notification Created {NotificationId}", notification.NotificationId);
NavigationManager.NavigateTo(PageState.ReturnUrl);
}
else
{
AddModuleMessage(Localizer["Message.User.Invalid"], MessageType.Warning);
}
} }
else else
{ {
AddModuleMessage(Localizer["Message.User.Invalid"], MessageType.Warning); AddModuleMessage(Localizer["Message.Required"], MessageType.Warning);
} }
} }
catch (Exception ex) catch (Exception ex)

View File

@ -153,7 +153,7 @@
<button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button> <button type="button" class="btn btn-secondary" @onclick="Cancel">@SharedLocalizer["Cancel"]</button>
</TabPanel> </TabPanel>
<TabPanel Name="Notifications" ResourceKey="Notifications"> <TabPanel Name="Notifications" ResourceKey="Notifications">
<ActionLink Action="Add" Text="Send Notification" Security="SecurityAccessLevel.View" EditMode="false" ResourceKey="SendNotification" /> <ActionLink Action="Add" Text="Send Notification" Security="SecurityAccessLevel.View" EditMode="false" ResourceKey="SendNotification" ReturnUrl="@NavigateUrl(PageState.Page.Path, "tab=Notifications")" />
<br /> <br />
<br /> <br />
<select class="form-select" @onchange="(e => FilterChanged(e))"> <select class="form-select" @onchange="(e => FilterChanged(e))">
@ -174,7 +174,7 @@
<th>@Localizer["Received"]</th> <th>@Localizer["Received"]</th>
</Header> </Header>
<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" ReturnUrl="@NavigateUrl(PageState.Page.Path, "tab=Notifications")" /></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) @if (context.IsRead)
@ -237,7 +237,7 @@
<th>@Localizer["Sent"]</th> <th>@Localizer["Sent"]</th>
</Header> </Header>
<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" ReturnUrl="@NavigateUrl(PageState.Page.Path, "tab=Notifications")" /></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) @if (context.IsRead)

View File

@ -8,94 +8,71 @@
@if (PageState.User != null) @if (PageState.User != null)
{ {
<div class="container"> @if (title == "From")
<div class="row mb-1 align-items-center"> {
<label Class="col-sm-3">@Localizer["Title"] </label> <div class="container">
@if (title == "From")
{
<div class="col-sm-9">
<input class="form-control" @bind="@username" readonly />
</div>
}
@if (title == "To")
{
<div class="col-sm-9">
<input class="form-control" @bind="@username" />
</div>
}
</div>
<div class="row mb-1 align-items-center">
<label Class="col-sm-3">@Localizer["Subject"] </label>
@if (title == "From")
{
<div class="col-sm-9">
<input class="form-control" @bind="@subject" readonly />
</div>
}
@if (title == "To")
{
<div class="col-sm-9">
<input class="form-control" @bind="@subject" />
</div>
}
</div>
</div>
<div class="container">
@if (title == "From")
{
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<label class="col-sm-3">@Localizer["Date"] </label> <Label Class="col-sm-3" For="username" HelpText="The user who sent the message" ResourceKey="From">From:</Label>
<div class="col-sm-9"> <div class="col-sm-9">
<input class="form-control" @bind="@createdon" readonly /> <input id="username" class="form-control" @bind="@username" readonly />
</div> </div>
</div> </div>
} <div class="row mb-1 align-items-center">
@if (title == "From") <Label Class="col-sm-3" For="subject" HelpText="The subject of the message" ResourceKey="Subject">Subject:</Label>
{ <div class="col-sm-9">
<div class="row mb-1 align-items-center"> <input id="subject" class="form-control" @bind="@subject" readonly />
<label class="col-sm-3">@Localizer["Message"] </label>
<div class="col-sm-9">
<textarea id="txtFrom" class="form-control" @bind="@body" rows="5" readonly />
</div>
</div> </div>
</div>
} <div class="row mb-1 align-items-center">
@if (title == "To") <Label class="col-sm-3" For="date" HelpText="The date the message was sent" ResourceKey="Date">Sent:</Label>
{ <div class="col-sm-9">
<input id="date" class="form-control" @bind="@createdon" readonly />
<div class="row mb-1 align-items-center">
<label class="col-sm-3">@Localizer["Message"] </label>
<div class="col-sm-9">
<textarea id="txtTo" class="form-control" @bind="@body" rows="5" />
</div>
</div> </div>
</div>
} <div class="row mb-1 align-items-center">
<Label class="col-sm-3" For="message" HelpText="The contents of the message" ResourceKey="Message">Message:</Label>
</div> <div class="col-sm-9">
<textarea id="message" class="form-control" @bind="@body" rows="5" readonly />
</div>
@if (reply != string.Empty) </div>
{ </div>
<button type="button" class="btn btn-primary" @onclick="Send">@SharedLocalizer["Send"]</button>
} }
else else
{ {
if (title == "From" && !string.IsNullOrWhiteSpace(username) && username != "System") <div class="container">
{ <div class="row mb-1 align-items-center">
<button type="button" class="btn btn-primary" @onclick="Reply">@Localizer["Reply"]</button> <Label Class="col-sm-3" For="username" HelpText="The user who will be the recipient of the message" ResourceKey="To">To:</Label>
} <div class="col-sm-9">
} <input id="username" class="form-control" @bind="@username" readonly />
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@SharedLocalizer["Cancel"]</NavLink> </div>
<br /> </div>
<br /> <div class="row mb-1 align-items-center">
@if (title == "To") <Label Class="col-sm-3" For="subject" HelpText="The subject of the message" ResourceKey="Subject">Subject:</Label>
{ <div class="col-sm-9">
<div class="control-group"> <input id="subject" class="form-control" @bind="@subject" readonly="@(!reply)" />
<label class="control-label">@Localizer["OriginalMessage"] </label> </div>
<textarea id="txtReply" class="form-control" @bind="@reply" rows="5" readonly /> </div>
<div class="row mb-1 align-items-center">
<Label class="col-sm-3" For="message" HelpText="The content of the message" ResourceKey="Message">Message:</Label>
<div class="col-sm-9">
<textarea id="message" class="form-control" @bind="@body" rows="5" readonly="@(!reply)" />
</div>
</div>
</div> </div>
} }
@if (reply)
{
<button type="button" class="btn btn-primary me-2" @onclick="Send">@SharedLocalizer["Send"]</button>
}
else
{
if (title == "From" && username != Localizer["System"])
{
<button type="button" class="btn btn-primary me-2" @onclick="Reply">@Localizer["Reply"]</button>
}
}
<NavLink class="btn btn-secondary" href="@PageState.ReturnUrl">@SharedLocalizer["Cancel"]</NavLink>
} }
@code { @code {
@ -105,7 +82,7 @@
private string subject = string.Empty; private string subject = string.Empty;
private string createdon = string.Empty; private string createdon = string.Empty;
private string body = string.Empty; private string body = string.Empty;
private string reply = string.Empty; private bool reply = false;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View; public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
public override string Title => "View Notification"; public override string Title => "View Notification";
@ -118,9 +95,6 @@
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)
{ {
@ -148,11 +122,17 @@
} }
if (username == "") if (username == "")
{ {
username = "System"; username = Localizer["System"];
} }
subject = notification.Subject; subject = notification.Subject;
createdon = notification.CreatedOn.ToString(); createdon = notification.CreatedOn.ToString();
body = notification.Body; body = notification.Body;
if (title == "From")
{
notification.IsRead = true;
notification = await NotificationService.UpdateNotificationAsync(notification);
}
} }
} }
catch (Exception ex) catch (Exception ex)
@ -165,12 +145,16 @@
private void Reply() private void Reply()
{ {
title = "To"; title = "To";
if (!subject.Contains("RE:")) if (!subject.Contains(Localizer["RE:"]))
{ {
subject = "RE: " + subject; subject = Localizer["RE"] + " " + subject;
} }
reply = body; body = $"\n\n____________________________________________\n" +
body = "\n\n____________________________________________\nSent: " + createdon + "\nSubject: " + subject + "\n\n" + body; $"{Localizer["From.Text"]} {username}\n" +
$"{Localizer["Date.Text"]} {createdon}\n" +
$"{Localizer["Subject.Text"]} {subject}\n\n" +
body;
reply = true;
StateHasChanged(); StateHasChanged();
} }
@ -184,7 +168,7 @@
var notification = new Notification(PageState.Site.SiteId, PageState.User, user, subject, body, notificationid); var notification = new Notification(PageState.Site.SiteId, PageState.User, user, subject, body, notificationid);
notification = await NotificationService.AddNotificationAsync(notification); notification = await NotificationService.AddNotificationAsync(notification);
await logger.LogInformation("Notification Created {NotificationId}", notification.NotificationId); await logger.LogInformation("Notification Created {NotificationId}", notification.NotificationId);
NavigationManager.NavigateTo(NavigateUrl()); NavigationManager.NavigateTo(PageState.ReturnUrl);
} }
else else
{ {

View File

@ -121,7 +121,7 @@
<value>Message: </value> <value>Message: </value>
</data> </data>
<data name="Message.User.Invalid" xml:space="preserve"> <data name="Message.User.Invalid" xml:space="preserve">
<value>User Does Not Exist. Please Verify That The Username Provided Is Correct.</value> <value>The User Specified Does Not Exist</value>
</data> </data>
<data name="Error.Notification.Add" xml:space="preserve"> <data name="Error.Notification.Add" xml:space="preserve">
<value>Error Adding Notification</value> <value>Error Adding Notification</value>
@ -133,7 +133,7 @@
<value>Enter the subject of the message</value> <value>Enter the subject of the message</value>
</data> </data>
<data name="Message.HelpText" xml:space="preserve"> <data name="Message.HelpText" xml:space="preserve">
<value>Enter the message</value> <value>Enter the message content</value>
</data> </data>
<data name="To.Text" xml:space="preserve"> <data name="To.Text" xml:space="preserve">
<value>To: </value> <value>To: </value>
@ -144,4 +144,10 @@
<data name="Send Notification" xml:space="preserve"> <data name="Send Notification" xml:space="preserve">
<value>Send Notification</value> <value>Send Notification</value>
</data> </data>
<data name="Message.Required" xml:space="preserve">
<value>You Must Enter All Required Information</value>
</data>
<data name="Username.Enter" xml:space="preserve">
<value>Enter Username</value>
</data>
</root> </root>

View File

@ -126,25 +126,43 @@
<data name="Error.Notification.Add" xml:space="preserve"> <data name="Error.Notification.Add" xml:space="preserve">
<value>Error Adding Notification</value> <value>Error Adding Notification</value>
</data> </data>
<data name="Title" xml:space="preserve">
<value>Title:</value>
</data>
<data name="Subject" xml:space="preserve">
<value>Subject:</value>
</data>
<data name="Date" xml:space="preserve">
<value>Date:</value>
</data>
<data name="Message" xml:space="preserve">
<value>Message:</value>
</data>
<data name="Reply" xml:space="preserve">
<value>Reply</value>
</data>
<data name="OriginalMessage" xml:space="preserve">
<value>Original Message</value>
</data>
<data name="View Notification" xml:space="preserve"> <data name="View Notification" xml:space="preserve">
<value>View Notification</value> <value>View Notification</value>
</data> </data>
<data name="Date.HelpText" xml:space="preserve">
<value>The date the message was sent</value>
</data>
<data name="Date.Text" xml:space="preserve">
<value>Sent:</value>
</data>
<data name="From.HelpText" xml:space="preserve">
<value>The user who sent the message</value>
</data>
<data name="From.Text" xml:space="preserve">
<value>From:</value>
</data>
<data name="Message.HelpText" xml:space="preserve">
<value>The content of the message</value>
</data>
<data name="Message.Text" xml:space="preserve">
<value>Message:</value>
</data>
<data name="RE" xml:space="preserve">
<value>RE:</value>
</data>
<data name="Subject.HelpText" xml:space="preserve">
<value>The subject of the message</value>
</data>
<data name="Subject.Text" xml:space="preserve">
<value>Subject:</value>
</data>
<data name="System" xml:space="preserve">
<value>System</value>
</data>
<data name="To.HelpText" xml:space="preserve">
<value>The user who will be the recipient of the message</value>
</data>
<data name="To.Text" xml:space="preserve">
<value>To:</value>
</data>
</root> </root>

View File

@ -179,7 +179,7 @@ namespace Oqtane.Controllers
[Authorize(Roles = RoleNames.Registered)] [Authorize(Roles = RoleNames.Registered)]
public Notification Put(int id, [FromBody] Notification notification) public Notification Put(int id, [FromBody] Notification notification)
{ {
if (ModelState.IsValid && notification.SiteId == _alias.SiteId && _notifications.GetNotification(notification.NotificationId, false) != null && IsAuthorized(notification.FromUserId)) if (ModelState.IsValid && notification.SiteId == _alias.SiteId && _notifications.GetNotification(notification.NotificationId, false) != null && (IsAuthorized(notification.FromUserId) || IsAuthorized(notification.ToUserId)))
{ {
notification = _notifications.UpdateNotification(notification); notification = _notifications.UpdateNotification(notification);
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Notification, notification.NotificationId, SyncEventActions.Update); _syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Notification, notification.NotificationId, SyncEventActions.Update);