diff --git a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Base/AbstractSortablePageModel.cs b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Base/AbstractSortablePageModel.cs
new file mode 100644
index 00000000..1eaad5c0
--- /dev/null
+++ b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Base/AbstractSortablePageModel.cs
@@ -0,0 +1,16 @@
+using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Models;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+
+namespace Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Base;
+
+public abstract class AbstractSortablePageModel : PageModel
+{
+ public string SortColumn { get; set; }
+ public SortDirection? SortDirection { get; set; }
+
+ public void ApplySort(string sortColumn, SortDirection? sortDirection)
+ {
+ SortColumn = sortColumn;
+ SortDirection = sortDirection;
+ }
+}
diff --git a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Components/SortableHeaderCell/Default.cshtml b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Components/SortableHeaderCell/Default.cshtml
new file mode 100644
index 00000000..7f3dc27c
--- /dev/null
+++ b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Components/SortableHeaderCell/Default.cshtml
@@ -0,0 +1,13 @@
+@using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Models
+@model Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Components.SortableHeaderCell.SortableHeaderCellViewModel
+
+
+ @Model.DisplayName
+
+ @if (Model.IsActive() && Model.GetSortDirection() != null)
+ {
+
+
+ }
+
\ No newline at end of file
diff --git a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Components/SortableHeaderCell/SortableHeaderCellViewComponent.cs b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Components/SortableHeaderCell/SortableHeaderCellViewComponent.cs
new file mode 100644
index 00000000..94b2a566
--- /dev/null
+++ b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Components/SortableHeaderCell/SortableHeaderCellViewComponent.cs
@@ -0,0 +1,26 @@
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Components.SortableHeaderCell;
+
+public class SortableHeaderCellViewComponent : ViewComponent
+{
+ private readonly IHttpContextAccessor _contextAccessor;
+
+ public SortableHeaderCellViewComponent(IHttpContextAccessor contextAccessor)
+ {
+ _contextAccessor = contextAccessor;
+ }
+
+ public IViewComponentResult Invoke(string key, string displayName)
+ {
+ var context = _contextAccessor.HttpContext;
+
+ return View(new SortableHeaderCellViewModel
+ {
+ QueryString = context?.Request.QueryString.ToString(),
+ Key = key,
+ DisplayName = displayName
+ });
+ }
+}
diff --git a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Components/SortableHeaderCell/SortableHeaderCellViewModel.cs b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Components/SortableHeaderCell/SortableHeaderCellViewModel.cs
new file mode 100644
index 00000000..61075bde
--- /dev/null
+++ b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Components/SortableHeaderCell/SortableHeaderCellViewModel.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Web;
+using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Base;
+using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Models;
+
+namespace Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Components.SortableHeaderCell;
+
+public class SortableHeaderCellViewModel
+{
+ public string DisplayName { get; set; }
+ public string Key { get; set; }
+ public string QueryString { get; set; }
+
+ public SortDirection? GetNextSortDirection()
+ {
+ return GetSortDirection() switch
+ {
+ null => SortDirection.Ascending,
+ SortDirection.Ascending => SortDirection.Descending,
+ SortDirection.Descending => null,
+ _ => throw new ArgumentOutOfRangeException()
+ };
+ }
+
+ public string GetSortColumn()
+ {
+ if (GetNextSortDirection() == null)
+ {
+ return null;
+ }
+
+ return Key;
+ }
+
+ public string GetSortUrl()
+ {
+ var qs = HttpUtility
+ .ParseQueryString(QueryString);
+
+ qs[nameof(AbstractSortablePageModel.SortColumn)] = GetSortColumn();
+ qs[nameof(AbstractSortablePageModel.SortDirection)] = GetNextSortDirection().ToString();
+
+ return $"?{qs}";
+ }
+
+ public bool IsActive()
+ {
+ var sortColumn = HttpUtility
+ .ParseQueryString(QueryString)
+ .Get(nameof(AbstractSortablePageModel.SortColumn));
+
+ return !string.IsNullOrEmpty(sortColumn) && sortColumn == Key;
+ }
+
+ public SortDirection? GetSortDirection()
+ {
+ var sortDirection = HttpUtility
+ .ParseQueryString(QueryString)
+ .Get(nameof(AbstractSortablePageModel.SortDirection));
+
+ return Enum.TryParse(sortDirection, out SortDirection sort) ? sort : null;
+ }
+}
diff --git a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Deleted.cshtml b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Deleted.cshtml
index c247027b..d869f36d 100644
--- a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Deleted.cshtml
+++ b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Deleted.cshtml
@@ -1,4 +1,7 @@
@page "{handler?}"
+@using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Components.SortableHeaderCell
+@using Geta.NotFoundHandler.Core.Providers.RegexRedirects
+@using Microsoft.AspNetCore.Mvc.TagHelpers
@model Geta.NotFoundHandler.Admin.Pages.Geta.NotFoundHandler.Admin.DeletedModel
@await Component.InvokeAsync("Card", new { message = Model.Message })
@@ -7,42 +10,44 @@
@await Component.InvokeAsync(typeof(Geta.NotFoundHandler.Admin.Pages.Geta.NotFoundHandler.Admin.Components.Pager.PagerViewComponent), new { Model.Items })
-
+
\ No newline at end of file
diff --git a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Deleted.cshtml.cs b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Deleted.cshtml.cs
index 6cd5cbe5..ce319cac 100644
--- a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Deleted.cshtml.cs
+++ b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Deleted.cshtml.cs
@@ -1,16 +1,19 @@
+using System.Collections.Generic;
using System.Linq;
+using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Base;
+using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Extensions;
+using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Models;
using Geta.NotFoundHandler.Admin.Pages.Geta.NotFoundHandler.Admin.Models;
using Geta.NotFoundHandler.Core.Redirects;
using Geta.NotFoundHandler.Infrastructure;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.Mvc.RazorPages;
using X.PagedList;
namespace Geta.NotFoundHandler.Admin.Pages.Geta.NotFoundHandler.Admin;
[Authorize(Constants.PolicyName)]
-public class DeletedModel : PageModel
+public class DeletedModel : AbstractSortablePageModel
{
private readonly IRedirectsService _redirectsService;
@@ -29,8 +32,10 @@ public DeletedModel(IRedirectsService redirectsService)
[BindProperty(SupportsGet = true)]
public Paging Paging { get; set; }
- public void OnGet()
+ public void OnGet(string sortColumn, SortDirection? sortDirection)
{
+ ApplySort(sortColumn, sortDirection);
+
Load();
}
@@ -55,9 +60,16 @@ public IActionResult OnPostDelete(string oldUrl)
private void Load()
{
- var items = _redirectsService.GetDeleted().ToPagedList(Paging.PageNumber, Paging.PageSize);
+ var items = FindRedirects().ToPagedList(Paging.PageNumber, Paging.PageSize);
Message =
$"There are currently {items.TotalItemCount} URLs that return a Deleted response. This tells crawlers to remove these URLs from their index.";
Items = items;
}
+
+ private IEnumerable FindRedirects()
+ {
+ return _redirectsService
+ .GetDeleted()
+ .Sort(SortColumn, SortDirection);
+ }
}
diff --git a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Extensions/EnumerableExtensions.cs b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Extensions/EnumerableExtensions.cs
new file mode 100644
index 00000000..49c3956c
--- /dev/null
+++ b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Extensions/EnumerableExtensions.cs
@@ -0,0 +1,45 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Models;
+
+namespace Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Extensions;
+
+public static class EnumerableExtensions
+{
+ public static IEnumerable Sort(this IEnumerable list, string propertyName, SortDirection? sortDirection)
+ {
+ if (!string.IsNullOrEmpty(propertyName))
+ {
+ var prop = typeof(T).GetProperty(propertyName);
+
+ if (prop != null && sortDirection != null)
+ {
+ if (sortDirection == SortDirection.Ascending)
+ {
+ list = list.OrderBy(x => GetValue(prop, x));
+ }
+ else
+ {
+ list = list.OrderByDescending(x => GetValue(prop, x));
+ }
+ }
+ }
+
+ return list;
+ }
+
+ private static object GetValue(PropertyInfo prop, T element)
+ {
+ var value = prop.GetValue(element);
+
+ // Value should be IComparable
+ if (value is Regex regex)
+ {
+ return regex.ToString();
+ }
+
+ return value;
+ }
+}
diff --git a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Ignored.cshtml b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Ignored.cshtml
index 7bdd6aab..588a140c 100644
--- a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Ignored.cshtml
+++ b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Ignored.cshtml
@@ -1,4 +1,6 @@
@page "{handler?}"
+@using Geta.NotFoundHandler.Core.Redirects
+@using Microsoft.AspNetCore.Mvc.TagHelpers
@model Geta.NotFoundHandler.Admin.Pages.Geta.NotFoundHandler.Admin.IgnoredModel
@await Component.InvokeAsync("Card", new { message = Model.Message })
@@ -8,7 +10,9 @@
- URL |
+
+
+ |
|
diff --git a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Ignored.cshtml.cs b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Ignored.cshtml.cs
index f7a6cf42..ff6495c7 100644
--- a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Ignored.cshtml.cs
+++ b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Ignored.cshtml.cs
@@ -1,16 +1,19 @@
+using System.Collections.Generic;
using System.Linq;
+using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Base;
+using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Extensions;
+using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Models;
using Geta.NotFoundHandler.Admin.Pages.Geta.NotFoundHandler.Admin.Models;
using Geta.NotFoundHandler.Core.Redirects;
using Geta.NotFoundHandler.Infrastructure;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.Mvc.RazorPages;
using X.PagedList;
namespace Geta.NotFoundHandler.Admin.Pages.Geta.NotFoundHandler.Admin;
[Authorize(Constants.PolicyName)]
-public class IgnoredModel : PageModel
+public class IgnoredModel : AbstractSortablePageModel
{
private readonly IRedirectsService _redirectsService;
@@ -26,8 +29,10 @@ public IgnoredModel(IRedirectsService redirectsService)
[BindProperty(SupportsGet = true)]
public Paging Paging { get; set; }
- public void OnGet()
+ public void OnGet(string sortColumn, SortDirection? sortDirection)
{
+ ApplySort(sortColumn, sortDirection);
+
Load();
}
@@ -40,8 +45,15 @@ public IActionResult OnPostUnignore(string oldUrl)
private void Load()
{
- var items = _redirectsService.GetIgnored().ToPagedList(Paging.PageNumber, Paging.PageSize);
+ var items = FindRedirects().ToPagedList(Paging.PageNumber, Paging.PageSize);
Message = $"There are currently {items.TotalItemCount} ignored suggestions stored.";
Items = items;
}
+
+ private IEnumerable FindRedirects()
+ {
+ return _redirectsService
+ .GetIgnored()
+ .Sort(SortColumn, SortDirection);
+ }
}
diff --git a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Index.cshtml b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Index.cshtml
index 33ad790e..6979a4ac 100644
--- a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Index.cshtml
+++ b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Index.cshtml
@@ -27,10 +27,18 @@
- Old URL |
- New URL |
- Wildcard |
- Redirect Type |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
|
diff --git a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Index.cshtml.cs b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Index.cshtml.cs
index c4aa129e..789c7b82 100644
--- a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Index.cshtml.cs
+++ b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Index.cshtml.cs
@@ -1,17 +1,19 @@
using System.Collections.Generic;
using System.Linq;
+using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Base;
+using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Extensions;
+using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Models;
using Geta.NotFoundHandler.Admin.Pages.Geta.NotFoundHandler.Admin.Models;
using Geta.NotFoundHandler.Core.Redirects;
using Geta.NotFoundHandler.Infrastructure;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.Mvc.RazorPages;
using X.PagedList;
namespace Geta.NotFoundHandler.Admin.Pages.Geta.NotFoundHandler.Admin;
[Authorize(Constants.PolicyName)]
-public class IndexModel : PageModel
+public class IndexModel : AbstractSortablePageModel
{
private readonly IRedirectsService _redirectsService;
@@ -35,8 +37,10 @@ public IndexModel(IRedirectsService redirectsService)
public bool HasQuery => !string.IsNullOrEmpty(Query);
- public void OnGet()
+ public void OnGet(string sortColumn, SortDirection? sortDirection)
{
+ ApplySort(sortColumn, sortDirection);
+
Load();
}
@@ -73,6 +77,9 @@ private void Load()
private IEnumerable FindRedirects()
{
- return HasQuery ? _redirectsService.Search(Query) : _redirectsService.GetSaved();
+ var result = HasQuery ? _redirectsService.Search(Query) : _redirectsService.GetSaved();
+
+ return result
+ .Sort(SortColumn, SortDirection);
}
}
diff --git a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Models/SortDirection.cs b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Models/SortDirection.cs
new file mode 100644
index 00000000..1cad2fcf
--- /dev/null
+++ b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Models/SortDirection.cs
@@ -0,0 +1,7 @@
+namespace Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Models;
+
+public enum SortDirection
+{
+ Ascending,
+ Descending
+}
diff --git a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Regex.cshtml b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Regex.cshtml
index 63635870..37fd5daf 100644
--- a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Regex.cshtml
+++ b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Regex.cshtml
@@ -1,4 +1,5 @@
@page "{handler?}"
+@using Geta.NotFoundHandler.Core.Providers.RegexRedirects
@using Microsoft.AspNetCore.Mvc.TagHelpers
@model Geta.NotFoundHandler.Admin.Areas.Geta.NotFoundHandler.Admin.RegexModel
@@ -9,9 +10,15 @@
- Order Number |
- Old URL Regex |
- New URL Format |
+
+
+ |
+
+
+ |
+
+
+ |
|
|
diff --git a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Regex.cshtml.cs b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Regex.cshtml.cs
index 544ae5e5..b4904702 100644
--- a/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Regex.cshtml.cs
+++ b/src/Geta.NotFoundHandler.Admin/Areas/GetaNotFoundHandlerAdmin/Pages/Regex.cshtml.cs
@@ -1,18 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Base;
+using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Extensions;
+using Geta.NotFoundHandler.Admin.Areas.GetaNotFoundHandlerAdmin.Pages.Models;
using Geta.NotFoundHandler.Admin.Pages.Geta.NotFoundHandler.Admin.Models;
using Geta.NotFoundHandler.Core.Providers.RegexRedirects;
using Geta.NotFoundHandler.Data;
using Geta.NotFoundHandler.Infrastructure;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Geta.NotFoundHandler.Admin.Areas.Geta.NotFoundHandler.Admin;
[Authorize(Constants.PolicyName)]
-public class RegexModel : PageModel
+public class RegexModel : AbstractSortablePageModel
{
private readonly IRegexRedirectLoader _redirectLoader;
private readonly IRegexRedirectsService _regexRedirectsService;
@@ -34,8 +36,10 @@ public RegexModel(
[BindProperty]
public RegexRedirectModel RegexRedirect { get; set; }
- public void OnGet()
+ public void OnGet(string sortColumn, SortDirection? sortDirection)
{
+ ApplySort(sortColumn, sortDirection);
+
Load();
}
@@ -105,9 +109,11 @@ private void Load()
RegexRedirect = new RegexRedirectModel { OrderNumber = items.Select(x => x.OrderNumber).DefaultIfEmpty().Max() + 1 };
}
- private IList FindRedirects()
+ private IEnumerable FindRedirects()
{
- return _redirectLoader.GetAll().ToList();
+ return _redirectLoader
+ .GetAll()
+ .Sort(SortColumn, SortDirection);
}
public bool IsEditing(Guid? id)