Skip to content

Commit

Permalink
MultiCriteriaSortingOptions implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
tomasherceg committed Oct 7, 2023
1 parent e948cff commit c8ce132
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 24 deletions.
21 changes: 21 additions & 0 deletions src/Framework/Core/Controls/GenericGridViewDataSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,26 @@ public void RequestRefresh()
{
IsRefreshRequired = true;
}

/// <summary>
/// Applies the options from the specified <see cref="GridViewDataSetOptions{TFilteringOptions, TSortingOptions, TPagingOptions}" /> to this instance.
/// </summary>
public void ApplyOptions(GridViewDataSetOptions<TFilteringOptions, TSortingOptions, TPagingOptions> options)
{
if (options.FilteringOptions != null)
{
FilteringOptions = options.FilteringOptions;
}

if (options.SortingOptions != null)
{
SortingOptions = options.SortingOptions;
}

if (options.PagingOptions != null)
{
PagingOptions = options.PagingOptions;
}
}
}
}
5 changes: 3 additions & 2 deletions src/Framework/Core/Controls/GridViewDataSetExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ public static void LoadFromQueryable<T>(this IGridViewDataSet<T> dataSet, IQuery
var paged = pagingOptions.ApplyToQueryable(sorted);
dataSet.Items = paged.ToList();

if (pagingOptions is IPagingTotalItemsCountCapability pagingTotalItemsCount)
if (pagingOptions is IPagingOptionsLoadingPostProcessor pagingOptionsLoadingPostProcessor)
{
pagingTotalItemsCount.TotalItemsCount = filtered.Count();
pagingOptionsLoadingPostProcessor.ProcessLoadedItems(filtered, dataSet.Items);
}

dataSet.IsRefreshRequired = false;
Expand Down Expand Up @@ -63,5 +63,6 @@ public static void GoToPageAndRefresh(this IPageableGridViewDataSet<IPagingPageI
dataSet.PagingOptions.GoToPage(pageIndex);
(dataSet as IRefreshableGridViewDataSet)?.RequestRefresh();
}

}
}
2 changes: 1 addition & 1 deletion src/Framework/Core/Controls/IFilterableGridViewDataSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ public interface IFilterableGridViewDataSet : IBaseGridViewDataSet
/// </summary>
IFilteringOptions FilteringOptions { get; }
}
}
}
18 changes: 18 additions & 0 deletions src/Framework/Core/Controls/Options/GridViewDataSetOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace DotVVM.Framework.Controls
{
public class GridViewDataSetOptions<TFilteringOptions, TSortingOptions, TPagingOptions>
where TFilteringOptions : IFilteringOptions
where TSortingOptions : ISortingOptions
where TPagingOptions : IPagingOptions
{
public TFilteringOptions? FilteringOptions { get; set; } = default;

public TSortingOptions? SortingOptions { get; set; } = default;

public TPagingOptions? PagingOptions { get; set; } = default;
}

public class GridViewDataSetOptions : GridViewDataSetOptions<NoFilteringOptions, SortingOptions, PagingOptions>
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Collections.Generic;
using System.Linq;

namespace DotVVM.Framework.Controls;

public interface IPagingOptionsLoadingPostProcessor
{
void ProcessLoadedItems<T>(IQueryable<T> filteredQueryable, IList<T> items);
}
77 changes: 77 additions & 0 deletions src/Framework/Core/Controls/Options/MultiCriteriaSortingOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace DotVVM.Framework.Controls;

public class MultiCriteriaSortingOptions : SortingOptions, ISortingMultipleCriteriaCapability
{
public IList<SortCriterion> Criteria { get; set; } = new List<SortCriterion>();

public int MaxSortCriteriaCount { get; set; } = 3;

public override IQueryable<T> ApplyToQueryable<T>(IQueryable<T> queryable)
{
foreach (var criterion in Criteria.Reverse())
{
queryable = SortingImplementation.ApplySortingToQueryable(queryable, criterion.SortExpression, criterion.SortDescending);
}

return base.ApplyToQueryable(queryable);
}

public override void SetSortExpression(string? sortExpression)
{
if (SortExpression == null)
{
SortExpression = sortExpression;
SortDescending = false;
}
else if (sortExpression == SortExpression)
{
if (!SortDescending)
{
SortDescending = true;
}
else if (Criteria.Any())
{
SortExpression = Criteria[0].SortExpression;
SortDescending = Criteria[0].SortDescending;
Criteria.RemoveAt(0);
}
else
{
SortExpression = null;
SortDescending = false;
}
}
else
{
var index = Criteria.ToList().FindIndex(c => c.SortExpression == sortExpression);
if (index >= 0)
{
if (!Criteria[index].SortDescending)
{
Criteria[index].SortDescending = true;
}
else
{
Criteria.RemoveAt(index);
}
}
else
{
if (Criteria.Count < MaxSortCriteriaCount - 1)
{
Criteria.Add(new SortCriterion() { SortExpression = sortExpression });
}
else
{
SortExpression = sortExpression;
SortDescending = false;
Criteria.Clear();
}
}
}
}
}
7 changes: 6 additions & 1 deletion src/Framework/Core/Controls/Options/PagingOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace DotVVM.Framework.Controls
/// <summary>
/// Represents settings for paging.
/// </summary>
public class PagingOptions : IPagingOptions, IPagingFirstPageCapability, IPagingLastPageCapability, IPagingPreviousPageCapability, IPagingNextPageCapability, IPagingPageIndexCapability, IPagingPageSizeCapability, IPagingTotalItemsCountCapability, IApplyToQueryable
public class PagingOptions : IPagingOptions, IPagingFirstPageCapability, IPagingLastPageCapability, IPagingPreviousPageCapability, IPagingNextPageCapability, IPagingPageIndexCapability, IPagingPageSizeCapability, IPagingTotalItemsCountCapability, IApplyToQueryable, IPagingOptionsLoadingPostProcessor
{
/// <summary>
/// Gets or sets the object that provides a list of page indexes near the current page.
Expand Down Expand Up @@ -114,5 +114,10 @@ public IQueryable<T> ApplyToQueryable<T>(IQueryable<T> queryable)
{
return PagingImplementation.ApplyPagingToQueryable(queryable, this);
}

public void ProcessLoadedItems<T>(IQueryable<T> filteredQueryable, IList<T> items)
{
TotalItemsCount = filteredQueryable.Count();
}
}
}
4 changes: 2 additions & 2 deletions src/Framework/Core/Controls/Options/SortingOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ public virtual void SetSortExpression(string? sortExpression)
/// <summary>
/// Applies the sorting options to the specified IQueryable expression.
/// </summary>
public IQueryable<T> ApplyToQueryable<T>(IQueryable<T> queryable)
public virtual IQueryable<T> ApplyToQueryable<T>(IQueryable<T> queryable)
{
return SortingImplementation.ApplySortingToQueryable(queryable, this);
return SortingImplementation.ApplySortingToQueryable(queryable, SortExpression, SortDescending);
}
}
}
8 changes: 4 additions & 4 deletions src/Framework/Core/Controls/SortingImplementation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ public static class SortingImplementation
/// of items is retrieved.
/// </summary>
/// <param name="queryable">The <see cref="IQueryable{T}" /> to modify.</param>
public static IQueryable<T> ApplySortingToQueryable<T>(IQueryable<T> queryable, ISortingSingleCriterionCapability options)
public static IQueryable<T> ApplySortingToQueryable<T>(IQueryable<T> queryable, string? sortExpression, bool sortDescending)
{
if (options.SortExpression == null)
if (sortExpression == null)
{
return queryable;
}

var parameterExpression = Expression.Parameter(typeof(T), "p");
Expression sortByExpression = parameterExpression;
foreach (var prop in (options.SortExpression ?? "").Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries))
foreach (var prop in sortExpression.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries))
{
var property = sortByExpression.Type.GetProperty(prop);
if (property == null)
Expand All @@ -46,7 +46,7 @@ public static IQueryable<T> ApplySortingToQueryable<T>(IQueryable<T> queryable,
return queryable;
}
var lambdaExpression = Expression.Lambda(sortByExpression, parameterExpression);
var methodCallExpression = Expression.Call(typeof(Queryable), GetSortingMethodName(options.SortDescending),
var methodCallExpression = Expression.Call(typeof(Queryable), GetSortingMethodName(sortDescending),
new[] { parameterExpression.Type, sortByExpression.Type },
queryable.Expression,
Expression.Quote(lambdaExpression));
Expand Down
14 changes: 0 additions & 14 deletions src/Framework/Framework/Controls/GridViewDataSetOptions.cs

This file was deleted.

0 comments on commit c8ce132

Please sign in to comment.