Skip to content

Commit

Permalink
Merge branch 'main' into fix/contentful-table-renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
sam-c-dfe authored Jul 4, 2024
2 parents 83ac398 + c1bf075 commit 754c83b
Show file tree
Hide file tree
Showing 34 changed files with 1,805 additions and 90 deletions.
19 changes: 19 additions & 0 deletions src/Dfe.EarlyYearsQualification.Content/Constants/ContentTypes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace Dfe.EarlyYearsQualification.Content.Constants;

public static class ContentTypes
{
public const string StartPage = "startPage";
public const string Qualification = "Qualification";
public const string DetailsPage = "detailsPage";
public const string AdvicePage = "advicePage";
public const string RadioQuestionPage = "radioQuestionPage";
public const string AccessibilityStatementPage = "accessibilityStatementPage";
public const string NavigationLinks = "navigationLinks";
public const string CookiesPage = "cookiesPage";
public const string PhaseBanner = "phaseBanner";
public const string CookiesBanner = "cookiesBanner";
public const string DateQuestionPage = "dateQuestionPage";
public const string DropdownQuestionPage = "dropdownQuestionPage";
public const string QualificationListPage = "qualificationListPage";
public const string ConfirmQualificationPage = "confirmQualificationPage";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace Dfe.EarlyYearsQualification.Content.Entities;

public class ConfirmQualificationPage
{
public string Heading { get; init; } = string.Empty;
public string QualificationLabel { get; init; } = string.Empty;
public string LevelLabel { get; init; } = string.Empty;
public string AwardingOrganisationLabel { get; init; } = string.Empty;
public string DateAddedLabel { get; init; } = string.Empty;
public string RadioHeading { get; init; } = string.Empty;
public List<Option> Options { get; init; } = [];
public string ErrorBannerHeading { get; init; } = string.Empty;
public string ErrorBannerLink { get; init; } = string.Empty;
public string ErrorText { get; init; } = string.Empty;
public string ButtonText { get; init; } = string.Empty;
public NavigationLink? BackButton { get; init; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
using System.Collections.ObjectModel;
using System.Globalization;
using Contentful.Core;
using Contentful.Core.Models;
using Contentful.Core.Search;
using Dfe.EarlyYearsQualification.Content.Constants;
using Dfe.EarlyYearsQualification.Content.Entities;
using Microsoft.Extensions.Logging;

namespace Dfe.EarlyYearsQualification.Content.Services;

public class ContentfulContentFilterService(
IContentfulClient contentfulClient,
ILogger<ContentfulContentFilterService> logger)
: IContentFilterService
{
private const int Day = 28;
private static readonly DateTimeFormatInfo CurrentFormatInfo = CultureInfo.CurrentCulture.DateTimeFormat;

private readonly ReadOnlyDictionary<int, string>
_months = new(
new Dictionary<int, string>
{
{ 1, CurrentFormatInfo.AbbreviatedMonthNames[0] },
{ 2, CurrentFormatInfo.AbbreviatedMonthNames[1] },
{ 3, CurrentFormatInfo.AbbreviatedMonthNames[2] },
{ 4, CurrentFormatInfo.AbbreviatedMonthNames[3] },
{ 5, CurrentFormatInfo.AbbreviatedMonthNames[4] },
{ 6, CurrentFormatInfo.AbbreviatedMonthNames[5] },
{ 7, CurrentFormatInfo.AbbreviatedMonthNames[6] },
{ 8, CurrentFormatInfo.AbbreviatedMonthNames[7] },
{ 9, CurrentFormatInfo.AbbreviatedMonthNames[8] },
{ 10, CurrentFormatInfo.AbbreviatedMonthNames[9] },
{ 11, CurrentFormatInfo.AbbreviatedMonthNames[10] },
{ 12, CurrentFormatInfo.AbbreviatedMonthNames[11] }
});

// Used by the unit tests to inject a mock builder that returns the query params
public QueryBuilder<Qualification> QueryBuilder { get; init; } = QueryBuilder<Qualification>.New;

public async Task<List<Qualification>> GetFilteredQualifications(int? level, int? startDateMonth,
int? startDateYear)
{
logger.LogInformation("Filtering options passed in - level: {Level}, startDateMonth: {StartDateMonth}, startDateYear: {StartDateYear}",
level,
startDateMonth,
startDateYear);

// create query builder
var queryBuilder = QueryBuilder.ContentTypeIs(ContentTypes.Qualification);

if (level is > 0)
{
queryBuilder = queryBuilder.FieldEquals("fields.qualificationLevel", level.Value.ToString());
}

// get qualifications
ContentfulCollection<Qualification>? qualifications;
try
{
qualifications = await contentfulClient.GetEntries(queryBuilder);
}
catch (Exception e)
{
logger.LogError(e, "Error getting qualifications");
return [];
}

if (!startDateMonth.HasValue || !startDateYear.HasValue) return qualifications.ToList();

// apply start date filtering
var results = FilterQualificationsByDate(startDateMonth.Value, startDateYear.Value, qualifications);

return results;
}

private List<Qualification> FilterQualificationsByDate(int startDateMonth, int startDateYear,
ContentfulCollection<Qualification> qualifications)
{
var results = new List<Qualification>();
var enteredStartDate = new DateOnly(startDateYear, startDateMonth, Day);
foreach (var qualification in qualifications)
{
var qualificationStartDate = GetQualificationDate(qualification.FromWhichYear);
var qualificationEndDate = GetQualificationDate(qualification.ToWhichYear);

if (qualificationStartDate is not null
&& qualificationEndDate is not null
&& enteredStartDate >= qualificationStartDate
&& enteredStartDate <= qualificationEndDate)
{
// check start date falls between those dates & add to results
results.Add(qualification);
}
else if (qualificationStartDate is null
&& qualificationEndDate is not null
&& enteredStartDate <= qualificationEndDate)
{
// if qualification start date is null, check entered start date is <= ToWhichYear & add to results
results.Add(qualification);
}
else
{
// if qualification end date is null, check entered start date is >= FromWhichYear & add to results
if (enteredStartDate >= qualificationStartDate)
{
results.Add(qualification);
}
}
}

return results;
}

private DateOnly? GetQualificationDate(string? qualificationDate)
{
if (string.IsNullOrEmpty(qualificationDate) || qualificationDate == "null")
{
return null;
}

return ConvertToDateTime(qualificationDate);
}

private DateOnly? ConvertToDateTime(string qualificationDate)
{
var splitQualificationDate = qualificationDate.Split('-');
if (splitQualificationDate.Length != 2) return null;

var month = _months.FirstOrDefault(x => x.Value == splitQualificationDate[0]).Key;
var year = Convert.ToInt32(splitQualificationDate[1]) + 2000;

return new DateOnly(year, month, Day);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Contentful.Core;
using Contentful.Core.Models;
using Contentful.Core.Search;
using Dfe.EarlyYearsQualification.Content.Constants;
using Dfe.EarlyYearsQualification.Content.Entities;
using Microsoft.Extensions.Logging;

Expand All @@ -15,19 +16,20 @@ public class ContentfulContentService(
private readonly Dictionary<object, string> _contentTypes
= new()
{
{ typeof(StartPage), "startPage" },
{ typeof(Qualification), "Qualification" },
{ typeof(DetailsPage), "detailsPage" },
{ typeof(AdvicePage), "advicePage" },
{ typeof(RadioQuestionPage), "radioQuestionPage" },
{ typeof(AccessibilityStatementPage), "accessibilityStatementPage" },
{ typeof(NavigationLinks), "navigationLinks" },
{ typeof(CookiesPage), "cookiesPage" },
{ typeof(PhaseBanner), "phaseBanner" },
{ typeof(CookiesBanner), "cookiesBanner" },
{ typeof(DateQuestionPage), "dateQuestionPage" },
{ typeof(DropdownQuestionPage), "dropdownQuestionPage" },
{ typeof(QualificationListPage), "qualificationListPage"}
{ typeof(StartPage), ContentTypes.StartPage },
{ typeof(Qualification), ContentTypes.Qualification },
{ typeof(DetailsPage), ContentTypes.DetailsPage },
{ typeof(AdvicePage), ContentTypes.AdvicePage },
{ typeof(RadioQuestionPage), ContentTypes.RadioQuestionPage},
{ typeof(AccessibilityStatementPage), ContentTypes.AccessibilityStatementPage },
{ typeof(NavigationLinks), ContentTypes.NavigationLinks },
{ typeof(CookiesPage), ContentTypes.CookiesPage },
{ typeof(PhaseBanner), ContentTypes.PhaseBanner },
{ typeof(CookiesBanner), ContentTypes.CookiesBanner },
{ typeof(DateQuestionPage), ContentTypes.DateQuestionPage },
{ typeof(DropdownQuestionPage), ContentTypes.DropdownQuestionPage },
{ typeof(QualificationListPage), ContentTypes.QualificationListPage },
{ typeof(ConfirmQualificationPage), ContentTypes.ConfirmQualificationPage},
};

public async Task<StartPage?> GetStartPage()
Expand Down Expand Up @@ -168,6 +170,18 @@ public async Task<List<Qualification>> GetQualifications()
return qualifications!.ToList();
}

public async Task<ConfirmQualificationPage?> GetConfirmQualificationPage()
{
var confirmQualificationEntities = await GetEntriesByType<ConfirmQualificationPage>();
if (confirmQualificationEntities is null || !confirmQualificationEntities.Any())
{
logger.LogWarning("No confirm qualification page entry returned");
return default;
}

return confirmQualificationEntities.First();
}

public async Task<QualificationListPage?> GetQualificationListPage()
{
var qualificationListPageEntities = await GetEntriesByType<QualificationListPage>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Dfe.EarlyYearsQualification.Content.Entities;

namespace Dfe.EarlyYearsQualification.Content.Services;

public interface IContentFilterService
{
Task<List<Qualification>> GetFilteredQualifications(int? level, int? startDateMonth, int? startDateYear);
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,6 @@ public interface IContentService
Task<List<Qualification>> GetQualifications();

Task<QualificationListPage?> GetQualificationListPage();

Task<ConfirmQualificationPage?> GetConfirmQualificationPage();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using Dfe.EarlyYearsQualification.Content.Entities;
using Dfe.EarlyYearsQualification.Content.Services;

namespace Dfe.EarlyYearsQualification.Mock.Content;

public class MockContentfulFilterService : IContentFilterService
{
public Task<List<Qualification>> GetFilteredQualifications(int? level, int? startDateMonth, int? startDateYear)
{
var qualifications = new List<Qualification>
{
CreateQualification("EYQ-100", "CACHE", 2, null, "Aug-19"),
CreateQualification("EYQ-101", "NCFE", 2, "Sep-14", "Aug-19"),
CreateQualification("EYQ-102", "Pearson", 3, "Sep-14", "Aug-19"),
CreateQualification("EYQ-103", "NCFE", 3, "Sep-14", "Aug-19"),
CreateQualification("EYQ-104", "City & Guilds", 4, "Sep-14", "Aug-19"),
CreateQualification("EYQ-105", "Montessori Centre International", 4, "Sep-14", "Aug-19"),
CreateQualification("EYQ-106", "Various Awarding Organisations", 5, "Sep-14", "Aug-19"),
CreateQualification("EYQ-107", "Edexcel (now Pearson Education Ltd)", 5, "Sep-14", "Aug-19"),
CreateQualification("EYQ-108", "Kent Sussex Montessori Centre", 6, "Sep-14", "Aug-19"),
CreateQualification("EYQ-109", "NNEB National Nursery Examination Board", 6, "Sep-14", "Aug-19"),
CreateQualification("EYQ-110", "Various Awarding Organisations", 7, "Sep-14", "Aug-19"),
CreateQualification("EYQ-111", "City & Guilds", 7, "Sep-14", "Aug-19"),
CreateQualification("EYQ-112", "Pearson", 8, "Sep-14", "Aug-19"),
CreateQualification("EYQ-113", "CACHE", 8, "Sep-14", "Aug-19")
};

return Task.FromResult(qualifications.Where(x => x.QualificationLevel == level).ToList());
}

private static Qualification CreateQualification(string qualificationId, string awardingOrganisation, int level, string? startDate, string endDate)
{
return new Qualification(
qualificationId,
$"{qualificationId}-test",
awardingOrganisation,
level,
startDate,
endDate,
"ghi/456/951",
"additional requirements");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ await Task.FromResult(CreateAdvicePage("Qualifications achieved outside the Unit
BackButton = new NavigationLink
{
DisplayText = "TEST",
Href = "/qualifications",
Href = "/confirm-qualification/eyq-240",
OpenInNewTab = false
}
});
Expand Down Expand Up @@ -203,16 +203,52 @@ public Task<List<Qualification>> GetQualifications()

public async Task<QualificationListPage?> GetQualificationListPage()
{
return await Task.FromResult(new QualificationListPage()
{
Header = "Test Header",
BackButton = new NavigationLink()
{
DisplayText = "TEST",
Href = "/questions/what-is-the-awarding-organisation",
OpenInNewTab = false
}
});
return await Task.FromResult(new QualificationListPage
{
Header = "Test Header",
BackButton = new NavigationLink
{
DisplayText = "TEST",
Href = "/questions/what-is-the-awarding-organisation",
OpenInNewTab = false
}
});
}

public async Task<ConfirmQualificationPage?> GetConfirmQualificationPage()
{
return await Task.FromResult(new ConfirmQualificationPage
{
QualificationLabel = "Test qualification label",
BackButton = new NavigationLink
{
DisplayText = "Test back button",
OpenInNewTab = false,
Href = "/qualifications"
},
ErrorText = "Test error text",
ButtonText = "Test button text",
LevelLabel = "Test level label",
DateAddedLabel = "Test date added label",
Heading = "Test heading",
Options =
[
new Option
{
Label = "yes",
Value = "yes"
},
new Option
{
Label = "no",
Value = "no"
}
],
RadioHeading = "Test radio heading",
AwardingOrganisationLabel = "Test awarding organisation label",
ErrorBannerHeading = "Test error banner heading",
ErrorBannerLink = "Test error banner link"
});
}

public async Task<StartPage?> GetStartPage()
Expand Down Expand Up @@ -291,10 +327,12 @@ private static RadioQuestionPage CreateWhatLevelIsTheQualificationPage()
Label = "Level 3", Value = "3"
}
};
return CreateRadioQuestionPage("What level is the qualification?", options, "/questions/when-was-the-qualification-started");
return CreateRadioQuestionPage("What level is the qualification?", options,
"/questions/when-was-the-qualification-started");
}

private static RadioQuestionPage CreateRadioQuestionPage(string question, List<Option> options, string backButtonURL)
private static RadioQuestionPage CreateRadioQuestionPage(string question, List<Option> options,
string backButtonUrl)
{
return new RadioQuestionPage
{
Expand All @@ -305,7 +343,7 @@ private static RadioQuestionPage CreateRadioQuestionPage(string question, List<O
BackButton = new NavigationLink
{
DisplayText = "TEST",
Href = backButtonURL,
Href = backButtonUrl,
OpenInNewTab = false
}
};
Expand Down
Loading

0 comments on commit 754c83b

Please sign in to comment.