Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup notifications module #14745

Merged
merged 3 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,7 @@ public bool IsHtmlPreferred
}

public override IEnumerable<Outcome> GetPossibleOutcomes(WorkflowExecutionContext workflowContext, ActivityContext activityContext)
{
return Outcomes(S["Done"], S["Failed"], S["Failed: no user found"]);
}
=> Outcomes(S["Done"], S["Failed"], S["Failed: no user found"]);

public override async Task<ActivityExecutionResult> ExecuteAsync(WorkflowExecutionContext workflowContext, ActivityContext activityContext)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Localization;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
Expand All @@ -32,42 +31,43 @@ public class AdminController : Controller, IUpdateModel
{
private readonly IAuthorizationService _authorizationService;
private readonly ISession _session;
protected readonly dynamic New;
private readonly IDisplayManager<Notification> _webNoticiationDisplayManager;
private readonly IDisplayManager<Notification> _notificationDisplayManager;
private readonly INotificationsAdminListQueryService _notificationsAdminListQueryService;
private readonly IDisplayManager<ListNotificationOptions> _notificationOptionsDisplayManager;
private readonly INotifier _notifier;
protected readonly IStringLocalizer S;
protected readonly IHtmlLocalizer H;
private readonly IShapeFactory _shapeFactory;
private readonly PagerOptions _pagerOptions;
private readonly IClock _clock;

protected readonly IStringLocalizer S;
protected readonly IHtmlLocalizer H;

public AdminController(
IAuthorizationService authorizationService,
ISession session,
IShapeFactory shapeFactory,

IOptions<PagerOptions> pagerOptions,
IDisplayManager<Notification> webNoticiationDisplayManager,
IDisplayManager<Notification> notificationDisplayManager,
INotificationsAdminListQueryService notificationsAdminListQueryService,
IDisplayManager<ListNotificationOptions> notificationOptionsDisplayManager,
INotifier notifier,
IClock clock,
IShapeFactory shapeFactory,
IStringLocalizer<AdminController> stringLocalizer,
IHtmlLocalizer<AdminController> htmlLocalizer,
IClock clock)
IHtmlLocalizer<AdminController> htmlLocalizer)
{
_authorizationService = authorizationService;
_session = session;
New = shapeFactory;
_webNoticiationDisplayManager = webNoticiationDisplayManager;
_notificationDisplayManager = notificationDisplayManager;
_notificationsAdminListQueryService = notificationsAdminListQueryService;
_notificationOptionsDisplayManager = notificationOptionsDisplayManager;
_notifier = notifier;
S = stringLocalizer;
H = htmlLocalizer;
_shapeFactory = shapeFactory;
_pagerOptions = pagerOptions.Value;
_clock = clock;

S = stringLocalizer;
H = htmlLocalizer;
}

public async Task<IActionResult> List(
Expand All @@ -89,44 +89,51 @@ public async Task<IActionResult> List(
// Populate route values to maintain previous route data when generating page links.
options.RouteValues.TryAdd("q", options.FilterResult.ToString());

options.Statuses = new List<SelectListItem>()
{
new SelectListItem(S["Read"], NotificationStatus.Read.ToString()),
new SelectListItem(S["Unread"], NotificationStatus.Unread.ToString()),
};
options.Sorts = new List<SelectListItem>()
{
new SelectListItem(S["Recently created"], NotificationOrder.Latest.ToString()),
new SelectListItem(S["Previously created"], NotificationOrder.Oldest.ToString()),
};
options.BulkActions = new List<SelectListItem>()
{
new SelectListItem(S["Mark as read"], NotificationBulkAction.Read.ToString()),
new SelectListItem(S["Mark as unread"], NotificationBulkAction.Unread.ToString()),
new SelectListItem(S["Remove"], NotificationBulkAction.Remove.ToString()),
};
options.Statuses =
[
new(S["Read"], nameof(NotificationStatus.Read)),
new(S["Unread"], nameof(NotificationStatus.Unread)),
];
options.Sorts =
[
new(S["Recently created"], nameof(NotificationOrder.Latest)),
new(S["Previously created"], nameof(NotificationOrder.Oldest)),
];
options.BulkActions =
[
new(S["Mark as read"], nameof(NotificationBulkAction.Read)),
new(S["Mark as unread"], nameof(NotificationBulkAction.Unread)),
new(S["Remove"], nameof(NotificationBulkAction.Remove)),
];

var routeData = new RouteData(options.RouteValues);
var pager = new Pager(pagerParameters, _pagerOptions.GetPageSize());

var queryResult = await _notificationsAdminListQueryService.QueryAsync(pager.Page, pager.PageSize, options, this);

var pagerShape = (await New.Pager(pager)).TotalItemCount(queryResult.TotalCount).RouteData(routeData);
dynamic pagerShape = await _shapeFactory.CreateAsync("Pager", Arguments.From(new
{
pager.Page,
pager.PageSize,
TotalItemCount = queryResult.TotalCount
}));

pagerShape.RouteData(routeData);

var notificationSummaries = new List<dynamic>();

foreach (var notificaiton in queryResult.Notifications)
foreach (var notification in queryResult.Notifications)
{
dynamic shape = await _webNoticiationDisplayManager.BuildDisplayAsync(notificaiton, this, "SummaryAdmin");
shape.Notification = notificaiton;
dynamic shape = await _notificationDisplayManager.BuildDisplayAsync(notification, this, "SummaryAdmin");
shape.Notification = notification;

notificationSummaries.Add(shape);
}

var startIndex = (pagerShape.Page - 1) * pagerShape.PageSize + 1;
options.StartIndex = startIndex;
options.EndIndex = startIndex + notificationSummaries.Count - 1;
options.NotficationsItemsCount = notificationSummaries.Count;
options.NotificationsCount = notificationSummaries.Count;
options.TotalItemCount = pagerShape.TotalItemCount;

var header = await _notificationOptionsDisplayManager.BuildEditorAsync(options, this, false, string.Empty, string.Empty);
Expand Down Expand Up @@ -165,6 +172,11 @@ public async Task<ActionResult> ListFilterPOST(ListNotificationOptions options)
[FormValueRequired("submit.BulkAction")]
public async Task<ActionResult> ListPOST(ListNotificationOptions options, IEnumerable<string> itemIds)
{
if (!await _authorizationService.AuthorizeAsync(HttpContext.User, NotificationPermissions.ManageNotifications))
{
return Forbid();
}

if (itemIds?.Count() > 0)
{
var notifications = await _session.Query<Notification, NotificationIndex>(x => x.UserId == CurrentUserId() && x.NotificationId.IsIn(itemIds), collection: NotificationConstants.NotificationCollection).ListAsync();
Expand Down Expand Up @@ -320,12 +332,10 @@ public async Task<IActionResult> Delete(string notificationId, string returnUrl)
}

private IActionResult RedirectTo(string returnUrl)
{
return !string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl) ? (IActionResult)this.LocalRedirect(returnUrl, true) : RedirectToAction(nameof(List));
}
=> !string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl)
? (IActionResult)this.LocalRedirect(returnUrl, true)
: RedirectToAction(nameof(List));

private string CurrentUserId()
{
return User.FindFirstValue(ClaimTypes.NameIdentifier);
}
=> User.FindFirstValue(ClaimTypes.NameIdentifier);
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,5 @@ public async Task<IActionResult> Read(ReadNotificationViewModel viewModel)
});
}
private string CurrentUserId()
{
return User.FindFirstValue(ClaimTypes.NameIdentifier);
}
=> User.FindFirstValue(ClaimTypes.NameIdentifier);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace OrchardCore.Notifications.Drivers;

public class ListNotificationOptionsDisplayDriver : DisplayDriver<ListNotificationOptions>
{
// Maintain the Options prefix for compatability with binding.
// Maintain the Options prefix for compatibility with binding.
protected override void BuildPrefix(ListNotificationOptions model, string htmlFieldPrefix)
{
Prefix = "Options";
Expand All @@ -17,9 +17,12 @@ protected override void BuildPrefix(ListNotificationOptions model, string htmlFi
public override IDisplayResult Display(ListNotificationOptions model)
{
return Combine(
Initialize<ListNotificationOptions>("NotificationsAdminListBulkActions", m => BuildOptionsViewModel(m, model)).Location("BulkActions", "Content:10"),
View("NotificationsAdminFilters_Thumbnail__Status", model).Location("Thumbnail", "Content:30"),
View("NotificationsAdminFilters_Thumbnail__Sort", model).Location("Thumbnail", "Content:40")
Initialize<ListNotificationOptions>("NotificationsAdminListBulkActions", m => BuildOptionsViewModel(m, model))
.Location("BulkActions", "Content:10"),
View("NotificationsAdminFilters_Thumbnail__Status", model)
.Location("Thumbnail", "Content:30"),
View("NotificationsAdminFilters_Thumbnail__Sort", model)
.Location("Thumbnail", "Content:40")
);
}

Expand All @@ -28,12 +31,18 @@ public override IDisplayResult Edit(ListNotificationOptions model)
model.FilterResult.MapTo(model);

return Combine(
Initialize<ListNotificationOptions>("NotificationsAdminListBulkActions", m => BuildOptionsViewModel(m, model)).Location("BulkActions", "Content:10"),
Initialize<ListNotificationOptions>("NotificationsAdminListSearch", m => BuildOptionsViewModel(m, model)).Location("Search:10"),
Initialize<ListNotificationOptions>("NotificationsAdminListActionBarButtons", m => BuildOptionsViewModel(m, model)).Location("ActionBarButtons:10"),
Initialize<ListNotificationOptions>("NotificationsAdminListSummary", m => BuildOptionsViewModel(m, model)).Location("Summary:10"),
Initialize<ListNotificationOptions>("NotificationsAdminListFilters", m => BuildOptionsViewModel(m, model)).Location("Actions:10.1"),
Initialize<ListNotificationOptions>("NotificationsAdminList_Fields_BulkActions", m => BuildOptionsViewModel(m, model)).Location("Actions:10.1")
Initialize<ListNotificationOptions>("NotificationsAdminListBulkActions", m => BuildOptionsViewModel(m, model))
.Location("BulkActions", "Content:10"),
Initialize<ListNotificationOptions>("NotificationsAdminListSearch", m => BuildOptionsViewModel(m, model))
.Location("Search:10"),
Initialize<ListNotificationOptions>("NotificationsAdminListActionBarButtons", m => BuildOptionsViewModel(m, model))
.Location("ActionBarButtons:10"),
Initialize<ListNotificationOptions>("NotificationsAdminListSummary", m => BuildOptionsViewModel(m, model))
.Location("Summary:10"),
Initialize<ListNotificationOptions>("NotificationsAdminListFilters", m => BuildOptionsViewModel(m, model))
.Location("Actions:10.1"),
Initialize<ListNotificationOptions>("NotificationsAdminList_Fields_BulkActions", m => BuildOptionsViewModel(m, model))
.Location("Actions:10.1")
);
}

Expand All @@ -54,9 +63,12 @@ private static void BuildOptionsViewModel(ListNotificationOptions m, ListNotific
m.Sorts = model.Sorts;
m.Statuses = model.Statuses;
m.BulkActions = model.BulkActions;
m.BulkAction = m.BulkAction;
m.StartIndex = model.StartIndex;
m.EndIndex = model.EndIndex;
m.NotificationsCount = model.NotificationsCount;
m.TotalItemCount = model.TotalItemCount;
m.OrderBy = model.OrderBy;
m.FilterResult = model.FilterResult;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ public override IDisplayResult Display(Notification notification)
{
var results = new List<IDisplayResult>()
{
Shape("NotificationsMeta_SummaryAdmin", new NotificationViewModel(notification)).Location("SummaryAdmin", "Meta:20"),
Shape("NotificationsActions_SummaryAdmin", new NotificationViewModel(notification)).Location("SummaryAdmin", "Actions:5"),
Shape("NotificationsButtonActions_SummaryAdmin", new NotificationViewModel(notification)).Location("SummaryAdmin", "ActionsMenu:10"),
Shape("NotificationsMeta_SummaryAdmin", new NotificationViewModel(notification))
.Location("SummaryAdmin", "Meta:20"),
Shape("NotificationsActions_SummaryAdmin", new NotificationViewModel(notification))
.Location("SummaryAdmin", "Actions:5"),
Shape("NotificationsButtonActions_SummaryAdmin", new NotificationViewModel(notification))
.Location("SummaryAdmin", "ActionsMenu:10"),
};

return Combine(results);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ public override IDisplayResult Display(Navbar model)
var userId = _httpContextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
var notifications = (await _session.Query<Notification, NotificationIndex>(x => x.UserId == userId && !x.IsRead, collection: NotificationConstants.NotificationCollection)
.OrderByDescending(x => x.CreatedAtUtc)
.Take(MaxVisibleNotifications + 1)
.ListAsync()).ToList();
.Take(MaxVisibleNotifications + 1)
.ListAsync()).ToList();

model.Notifications = notifications;
model.MaxVisibleNotifications = MaxVisibleNotifications;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,10 @@ protected override void UpdateActivity(TEditViewModel model, TActivity activity)
public override IDisplayResult Display(TActivity activity)
{
return Combine(
Shape($"{typeof(TActivity).Name}_Fields_Thumbnail", new ActivityViewModel<TActivity>(activity)).Location("Thumbnail", "Content"),
Shape($"{typeof(TActivity).Name}_Fields_Design", new ActivityViewModel<TActivity>(activity)).Location("Design", "Content")
Shape($"{typeof(TActivity).Name}_Fields_Thumbnail", new ActivityViewModel<TActivity>(activity))
.Location("Thumbnail", "Content"),
Shape($"{typeof(TActivity).Name}_Fields_Design", new ActivityViewModel<TActivity>(activity))
.Location("Design", "Content")
);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
Expand Down Expand Up @@ -26,8 +25,8 @@ public override Task<IDisplayResult> EditAsync(User user, UserNotificationPrefer
{
var result = Initialize<UserNotificationViewModel>("UserNotificationPreferencesPart_Edit", model =>
{
var sortedMethods = new List<string>(part.Methods ?? Array.Empty<string>());
var optout = part.Optout ?? Array.Empty<string>();
var sortedMethods = new List<string>(part.Methods ?? []);
var optout = part.Optout ?? [];

// By default the use is opted into all available methods until explicitly optout.
model.Methods = _notificationMethodProviders.Select(x => x.Method).Except(optout).ToArray();
Expand Down Expand Up @@ -61,11 +60,11 @@ public override async Task<IDisplayResult> UpdateAsync(User user, UserNotificati

if (await updater.TryUpdateModelAsync(model, Prefix))
{
var sortedMethods = new List<string>(model.SortedMethods ?? Array.Empty<string>());
var sortedMethods = new List<string>(model.SortedMethods ?? []);

if (sortedMethods.Count > 0)
{
// Important to execute this code only when selectedOrdrededMethods has at least one element to avoid exception.
// Important to execute this code only when sortedMethods has at least one element to avoid exception.
// Store all methods in the same order they appear.
part.Methods = _notificationMethodProviders
.OrderBy(provider => sortedMethods.IndexOf(provider.Method))
Expand All @@ -80,7 +79,7 @@ public override async Task<IDisplayResult> UpdateAsync(User user, UserNotificati
.ToArray();
}

var selectedMethods = new List<string>(model.Methods ?? Array.Empty<string>());
var selectedMethods = new List<string>(model.Methods ?? []);

// Store any method that is not selected as an optout.
part.Optout = _notificationMethodProviders.Where(provider => !selectedMethods.Contains(provider.Method))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ public class CoreNotificationEventsHandler : NotificationEventsHandler
{
public override Task CreatingAsync(NotificationContext context)
{
var user = context.Notify as User;

if (user != null)
if (context.Notify is User user)
{
context.Notification.UserId = user.UserId;
}
Expand Down
6 changes: 3 additions & 3 deletions src/OrchardCore.Modules/OrchardCore.Notifications/Manifest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
Name = "Email Notifications",
Description = "Provides a way to send email notifications to users.",
Category = "Notifications",
Dependencies = new[]
{
Dependencies =
[
"OrchardCore.Notifications",
"OrchardCore.Email",
}
]
)]
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using OrchardCore.ContentManagement;

namespace OrchardCore.Notifications.ViewModels;
Expand All @@ -19,5 +18,6 @@ public class UserNotificationMessageViewModel

public string Url { get; set; }

public bool HasBody() => !string.IsNullOrWhiteSpace(Body);
public bool HasBody()
=> !string.IsNullOrWhiteSpace(Body);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
@model ActivityViewModel<NotifyContentOwnerTask>

<header>
<h4><i class="fa-solid fa-envelope" aria-hidden="true"></i>@Model.Activity.GetTitleOrDefault(() => T["Notify user"])</h4>
<h4><i class="fa-solid fa-envelope" aria-hidden="true"></i>@Model.Activity.GetTitleOrDefault(() => T["Notify Content Owner"])</h4>
</header>
<em>&quot;@Model.Activity.Subject&quot;</em>
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
<h4 class="card-title"><i class="fa-solid fa-envelope" aria-hidden="true"></i>@T["Notify owner"]</h4>
<h4 class="card-title"><i class="fa-solid fa-envelope" aria-hidden="true"></i>@T["Notify Content Owner"]</h4>
<p>@T["Notify content owner"]</p>
Loading