Skip to content

Commit

Permalink
Merge pull request #963 from DFE-Digital/feature/spike-filter-component
Browse files Browse the repository at this point in the history
Feature/spike filter component
  • Loading branch information
paullocknimble authored Jan 3, 2024
2 parents 032a73d + 23989da commit 8c12eb6
Show file tree
Hide file tree
Showing 17 changed files with 469 additions and 236 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public async Task<HttpResponseMessage> GetAllProjectsAsync(AcademyConversionSear
{
return await AcademisationClient.PostAsync(PathFor.GetAllProjects, JsonContent.Create(searchModel));
}
public async Task<HttpResponseMessage> DownloadProjectExport(AcademyConversionSearchModel searchModel)
public async Task<HttpResponseMessage> DownloadProjectExport(AcademyConversionSearchModelV2 searchModel)
{
return await AcademisationClient.PostAsync(PathFor.DownloadProjectExport, JsonContent.Create(searchModel));
}
Expand Down Expand Up @@ -70,4 +70,9 @@ public async Task<HttpResponseMessage> SetProjectExternalApplicationForm(int id,

return await AcademisationClient.PutAsync(string.Format(PathFor.SetExternalApplicationForm, id), JsonContent.Create(payload));
}

public async Task<HttpResponseMessage> GetAllProjectsV2Async(AcademyConversionSearchModelV2 searchModel)
{
return await AcademisationClient.PostAsync(PathFor.GetAllProjectsV2, JsonContent.Create(searchModel));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ namespace Dfe.PrepareConversions.Data.Features;
public interface IApiClient
{
Task<HttpResponseMessage> GetAllProjectsAsync(AcademyConversionSearchModel searchModel);
Task<HttpResponseMessage> DownloadProjectExport(AcademyConversionSearchModel searchModel);
Task<HttpResponseMessage> DownloadProjectExport(AcademyConversionSearchModelV2 searchModel);
Task<HttpResponseMessage> GetAllProjectsV2Async(AcademyConversionSearchModelV2 searchModel);
Task<HttpResponseMessage> GetProjectByIdAsync(int id);
Task<HttpResponseMessage> UpdateProjectAsync(int id, UpdateAcademyConversionProject updateProject);
Task<HttpResponseMessage> GetFilterParametersAsync();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ public PathFor(IFeatureManager features)
public static string GetFilterParameters => "/legacy/projects/status";
public static string AddProjectNote => "/legacy/project/{0}/notes";
public static string SetExternalApplicationForm => "/conversion-project/{0}/setExternalApplicationForm";

public static string GetAllProjectsV2 => "/conversion-project/projects";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.Collections.Generic;

namespace Dfe.PrepareConversions.Data.Models;

public class AcademyConversionSearchModelV2
{
public int Page { get; set; }
public int Count { get; set; }
public string TitleFilter { get; set; }
public IEnumerable<string> DeliveryOfficerQueryString { get; set; }
public IEnumerable<string> RegionQueryString { get; set; }
public IEnumerable<string> StatusQueryString { get; set; }
public IEnumerable<string> LocalAuthoritiesQueryString { get; set; }
public IEnumerable<string> AdvisoryBoardDatesQueryString { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ public class ProjectFilterParameters
public List<string> Statuses { get; set; } = new();
public List<string> AssignedUsers { get; set; } = new();
public List<string> Regions { get; set; } = new();
public List<string> LocalAuthorities { get; set; } = new();
public List<string> AdvisoryBoardDates { get; set; } = new();
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,9 @@ public async Task<ApiResponse<FileStreamResult>> DownloadProjectExport(
IEnumerable<string> regionsFilter = default,
IEnumerable<string> applicationReferences = default)
{
AcademyConversionSearchModel searchModel = new() { TitleFilter = titleFilter, Page = page, Count = count };
AcademyConversionSearchModelV2 searchModel = new() { TitleFilter = titleFilter, Page = page, Count = count };

ProcessFilters(statusFilters, deliveryOfficerFilter, searchModel, regionsFilter, applicationReferences);
ProcessFiltersV2(statusFilters, deliveryOfficerFilter, searchModel, regionsFilter, applicationReferences);

HttpResponseMessage response = await _apiClient.DownloadProjectExport(searchModel);
if (!response.IsSuccessStatusCode)
Expand Down Expand Up @@ -188,6 +188,41 @@ private void ProcessFilters(IEnumerable<string> statusFilters,
}
}

private void ProcessFiltersV2(IEnumerable<string> statusFilters,
IEnumerable<string> deliveryOfficerFilter,
AcademyConversionSearchModelV2 searchModel,
IEnumerable<string> regionsFilter = default,
IEnumerable<string> localAuthoritiesFilter = default,
IEnumerable<string> advisoryBoardDateFilter = default
)
{
if (deliveryOfficerFilter != default)
{
searchModel.DeliveryOfficerQueryString = deliveryOfficerFilter;
}
if (statusFilters != null)
{
IEnumerable<string> projectedStatuses = statusFilters.SelectMany(x =>
_invertedAliasedStatuses.ContainsKey(x.ToLowerInvariant())
? new[] { x, _invertedAliasedStatuses[x.ToLowerInvariant()] }
: new[] { x });

searchModel.StatusQueryString = projectedStatuses.ToArray();
}
if (regionsFilter != default)
{
searchModel.RegionQueryString = regionsFilter.Select(x => x.ToLower()).ToList();
}
if (localAuthoritiesFilter != default)
{
searchModel.LocalAuthoritiesQueryString = localAuthoritiesFilter.Select(x => x.ToLower()).ToList();
}
if (advisoryBoardDateFilter != default)
{
searchModel.AdvisoryBoardDatesQueryString = advisoryBoardDateFilter.Select(x => x.ToLower()).ToList();
}
}

private async Task<T> ReadFromJsonAndThrowIfNull<T>(HttpContent content)
{
T responseObj = await content.ReadFromJsonAsync<T>();
Expand All @@ -203,4 +238,22 @@ public async Task SetProjectExternalApplicationForm(int id, bool externalApplica
HttpResponseMessage result = await _apiClient.SetProjectExternalApplicationForm(id, externalApplicationFormSaved, externalApplicationFormUrl);
if (result.IsSuccessStatusCode is false) throw new ApiResponseException($"Request to Api failed | StatusCode - {result.StatusCode}");
}

public async Task<ApiResponse<ApiV2Wrapper<IEnumerable<AcademyConversionProject>>>> GetAllProjectsV2(int page, int count, string titleFilter = "", IEnumerable<string> statusFilters = null, IEnumerable<string> deliveryOfficerFilter = null, IEnumerable<string> regionsFilter = null, IEnumerable<string> localAuthoritiesFilter = null, IEnumerable<string> advisoryBoardDatesFilter = null)
{
AcademyConversionSearchModelV2 searchModel = new() { TitleFilter = titleFilter, Page = page, Count = count };

ProcessFiltersV2(statusFilters, deliveryOfficerFilter, searchModel, regionsFilter, localAuthoritiesFilter, advisoryBoardDatesFilter);

HttpResponseMessage response = await _apiClient.GetAllProjectsV2Async(searchModel);
if (!response.IsSuccessStatusCode)
{
return new ApiResponse<ApiV2Wrapper<IEnumerable<AcademyConversionProject>>>(response.StatusCode,
new ApiV2Wrapper<IEnumerable<AcademyConversionProject>> { Data = Enumerable.Empty<AcademyConversionProject>() });
}

ApiV2Wrapper<IEnumerable<AcademyConversionProject>> outerResponse = await response.Content.ReadFromJsonAsync<ApiV2Wrapper<IEnumerable<AcademyConversionProject>>>();

return new ApiResponse<ApiV2Wrapper<IEnumerable<AcademyConversionProject>>>(response.StatusCode, outerResponse);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@ Task<ApiResponse<FileStreamResult>> DownloadProjectExport(
IEnumerable<string> applicationReferences = default
);

Task<ApiResponse<ApiV2Wrapper<IEnumerable<AcademyConversionProject>>>> GetAllProjectsV2(
int page,
int count,
string titleFilter = "",
IEnumerable<string> statusFilters = default,
IEnumerable<string> deliveryOfficerFilter = default,
IEnumerable<string> regionsFilter = default,
IEnumerable<string> localAuthoritiesFilter = default,
IEnumerable<string> advisoryBoardDatesFilter = default
);

Task<ApiResponse<AcademyConversionProject>> GetProjectById(int id);
Task<ApiResponse<AcademyConversionProject>> UpdateProject(int id, UpdateAcademyConversionProject updateProject);
Task CreateProject(CreateNewProject newProject);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public abstract partial class BaseIntegrationTests

protected IEnumerable<AcademyConversionProject> AddGetProjects(Action<AcademyConversionProject> postSetup = null,
int? recordCount = null,
AcademyConversionSearchModel searchModel = null)
AcademyConversionSearchModelV2 searchModel = null)
{
List<AcademyConversionProject> projects = _fixture
.Build<AcademyConversionProject>()
Expand All @@ -41,17 +41,19 @@ protected IEnumerable<AcademyConversionProject> AddGetProjects(Action<AcademyCon
Paging = new ApiV2PagingInfo { RecordCount = recordCount ?? projects.Count, Page = 0 }
};

searchModel ??= new AcademyConversionSearchModel
searchModel ??= new AcademyConversionSearchModelV2
{
Page = 1,
Count = 10,
TitleFilter = null,
StatusQueryString = Array.Empty<string>(),
DeliveryOfficerQueryString = Array.Empty<string>(),
RegionQueryString = Array.Empty<string>()
RegionQueryString = Array.Empty<string>(),
LocalAuthoritiesQueryString = Array.Empty<string>(),
AdvisoryBoardDatesQueryString = Array.Empty<string>()
};

_factory.AddPostWithJsonRequest(PathFor.GetAllProjects, searchModel, response);
_factory.AddPostWithJsonRequest(PathFor.GetAllProjectsV2, searchModel, response);
return projects;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,6 @@ public void Should_display_all_projects_by_default()
FilterCount.TextContent.Should().NotContainEquivalentOf("Filtered projects");
}

[Fact]
public void Should_not_display_the_filter_options_by_default()
{
FilterOptions.HasAttribute("open").Should().BeFalse();
}

[Fact]
public async Task Should_display_filtered_banner_when_filter_is_active()
{
Expand All @@ -70,26 +64,19 @@ public async Task Should_display_filtered_banner_when_filter_is_active()
FilterBanner.InnerHtml.Should().ContainEquivalentOf("Projects filtered.");
}

[Fact]
public async Task Should_keep_filter_options_visible_when_filter_is_active()
{
FilterStatuses.First().IsChecked = true;
await FilterApply.SubmitAsync();

FilterOptions.HasAttribute("open").Should().BeTrue();
}

[Fact]
public async Task Should_display_filtered_projects_in_place_of_all_projects_when_filter_is_active()
{
AcademyConversionSearchModel searchModel = new()
AcademyConversionSearchModelV2 searchModel = new()
{
Page = 1,
Count = 10,
StatusQueryString = new[] { "Accepted" },
TitleFilter = string.Empty,
DeliveryOfficerQueryString = Array.Empty<string>(),
RegionQueryString = Array.Empty<string>()
RegionQueryString = Array.Empty<string>(),
LocalAuthoritiesQueryString = Array.Empty<string>(),
AdvisoryBoardDatesQueryString = Array.Empty<string>(),
};
AddGetProjects(recordCount: _recordCount, searchModel: searchModel);

Expand All @@ -106,7 +93,7 @@ public async Task Should_keep_the_filter_options_visible_when_title_filter_is_sp
FilterTitle.Value = "something";
await FilterApply.SubmitAsync();

FilterOptions.HasAttribute("open").Should().BeTrue();

FilterTitle.Value.Should().Be("something");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,18 @@ public class ProjectListFilters
public const string FilterStatuses = nameof(FilterStatuses);
public const string FilterOfficers = nameof(FilterOfficers);
public const string FilterRegions = nameof(FilterRegions);
public const string FilterLocalAuthorities = nameof(FilterLocalAuthorities);
public const string FilterAdvisoryBoardDates = nameof(FilterAdvisoryBoardDates);

private IDictionary<string, object?> _store = null!;

public List<string> AvailableStatuses { get; set; } = new();
public List<string> AvailableDeliveryOfficers { get; set; } = new();
public List<string> AvailableRegions { get; set; } = new();

public List<string> AvailableLocalAuthorities { get; set; } = new();
public List<string> AvailableAdvisoryBoardDates { get; set; } = new();

[BindProperty]
public string? Title { get; set; }

Expand All @@ -33,10 +38,18 @@ public class ProjectListFilters
[BindProperty]
public string[] SelectedRegions { get; set; } = Array.Empty<string>();

[BindProperty]
public string[] SelectedLocalAuthorities { get; set; } = Array.Empty<string>();

[BindProperty]
public string[] SelectedAdvisoryBoardDates { get; set; } = Array.Empty<string>();

public bool IsVisible => string.IsNullOrWhiteSpace(Title) is false ||
SelectedStatuses.Length > 0 ||
SelectedOfficers.Length > 0 ||
SelectedRegions.Length > 0;
SelectedRegions.Length > 0 ||
SelectedLocalAuthorities.Length > 0 ||
SelectedAdvisoryBoardDates.Length > 0;

public ProjectListFilters PersistUsing(IDictionary<string, object?> store)
{
Expand All @@ -46,6 +59,8 @@ public ProjectListFilters PersistUsing(IDictionary<string, object?> store)
SelectedStatuses = Get(FilterStatuses);
SelectedOfficers = Get(FilterOfficers);
SelectedRegions = Get(FilterRegions);
SelectedLocalAuthorities = Get(FilterLocalAuthorities);
SelectedAdvisoryBoardDates = Get(FilterAdvisoryBoardDates);

return this;
}
Expand All @@ -62,28 +77,36 @@ public void PopulateFrom(IEnumerable<KeyValuePair<string, StringValues>> request
SelectedStatuses = Array.Empty<string>();
SelectedOfficers = Array.Empty<string>();
SelectedRegions = Array.Empty<string>();
SelectedLocalAuthorities = Array.Empty<string>();
SelectedAdvisoryBoardDates = Array.Empty<string>();

return;
}

bool activeFilterChanges = query.ContainsKey(nameof(Title)) ||
query.ContainsKey(nameof(SelectedStatuses)) ||
query.ContainsKey(nameof(SelectedOfficers)) ||
query.ContainsKey(nameof(SelectedRegions));
query.ContainsKey(nameof(SelectedRegions)) ||
query.ContainsKey(nameof(SelectedLocalAuthorities)) ||
query.ContainsKey(nameof(SelectedAdvisoryBoardDates));

if (activeFilterChanges)
{
Title = Cache(FilterTitle, GetFromQuery(nameof(Title))).FirstOrDefault()?.Trim();
SelectedStatuses = Cache(FilterStatuses, GetFromQuery(nameof(SelectedStatuses)));
SelectedOfficers = Cache(FilterOfficers, GetFromQuery(nameof(SelectedOfficers)));
SelectedRegions = Cache(FilterRegions, GetFromQuery(nameof(SelectedRegions)));
SelectedLocalAuthorities = Cache(FilterLocalAuthorities, GetFromQuery(nameof(SelectedLocalAuthorities)));
SelectedAdvisoryBoardDates = Cache(FilterAdvisoryBoardDates, GetFromQuery(nameof(SelectedAdvisoryBoardDates)));
}
else
{
Title = Get(FilterTitle, true).FirstOrDefault()?.Trim();
SelectedStatuses = Get(FilterStatuses, true);
SelectedOfficers = Get(FilterOfficers, true);
SelectedRegions = Get(FilterRegions, true);
SelectedLocalAuthorities = Get(FilterLocalAuthorities, true);
SelectedAdvisoryBoardDates = Get(FilterAdvisoryBoardDates, true);
}

string[] GetFromQuery(string key)
Expand Down Expand Up @@ -118,6 +141,8 @@ private void ClearFilters()
Cache(FilterStatuses, default);
Cache(FilterOfficers, default);
Cache(FilterRegions, default);
Cache(FilterLocalAuthorities, default);
Cache(FilterAdvisoryBoardDates, default);
}

/// <summary>
Expand Down
Loading

0 comments on commit 8c12eb6

Please sign in to comment.