From 43fa5ec216754eb96aa29f273340632a83d2fa1b Mon Sep 17 00:00:00 2001 From: martinfoster-hee Date: Wed, 11 Jan 2023 12:00:09 +0000 Subject: [PATCH 1/3] Implemented archived/inactive tag. --- .../DataServices/CourseDataServiceTests.cs | 1 + .../DataServices/CourseDataService.cs | 4 +- .../Models/Courses/Course.cs | 1 + ...eStatisticsWithAdminFieldResponseCounts.cs | 1 + .../CourseSetup/CourseSetupControllerTests.cs | 1 + ...seStatisticsViewModelFilterOptionsTests.cs | 2 +- ...esStatisticsViewModelFilterOptionsTests.cs | 2 +- .../FilterOptions/CourseFilterOptions.cs | 10 +++-- .../Helpers/FilterableTagHelper.cs | 42 ++++++++++++++++--- .../Services/CourseService.cs | 2 +- .../Styles/trackingSystem/courseSetup.scss | 10 +++++ .../Styles/trackingSystem/viewDelegate.scss | 8 ++++ .../SearchablePage/SearchableTagViewModel.cs | 10 ++++- .../SearchableCourseStatisticsViewModel.cs | 1 + .../DelegateCoursesViewModel.cs | 26 ++++++++++++ ...chableDelegateCourseStatisticsViewModel.cs | 18 +++++++- .../Shared/SearchablePage/_StatusTags.cshtml | 10 +++++ .../DelegateCourses/_CentreCourseCard.cshtml | 6 +-- 18 files changed, 137 insertions(+), 18 deletions(-) create mode 100644 DigitalLearningSolutions.Web/Views/Shared/SearchablePage/_StatusTags.cshtml diff --git a/DigitalLearningSolutions.Data.Tests/DataServices/CourseDataServiceTests.cs b/DigitalLearningSolutions.Data.Tests/DataServices/CourseDataServiceTests.cs index ecc2737a87..1d800553a5 100644 --- a/DigitalLearningSolutions.Data.Tests/DataServices/CourseDataServiceTests.cs +++ b/DigitalLearningSolutions.Data.Tests/DataServices/CourseDataServiceTests.cs @@ -347,6 +347,7 @@ public void GetCourseStatisticsAtCentreFilteredByCategory_should_return_course_s CategoryName = "Office 2007", CourseTopic = "Microsoft Office", LearningMinutes = "N/A", + Archived = false, }; result.Should().HaveCount(259); diff --git a/DigitalLearningSolutions.Data/DataServices/CourseDataService.cs b/DigitalLearningSolutions.Data/DataServices/CourseDataService.cs index 3d7707fd26..941a5d13af 100644 --- a/DigitalLearningSolutions.Data/DataServices/CourseDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/CourseDataService.cs @@ -177,6 +177,7 @@ FROM CustomisationTutorials AS ct cu.CustomisationID, cu.CentreID, cu.Active, + CASE WHEN ap.ArchivedDate IS NOT NULL THEN 0 ELSE cu.Active END AS Active, cu.AllCentres, ap.ApplicationId, ap.ApplicationName, @@ -189,7 +190,8 @@ FROM CustomisationTutorials AS ct cc.CategoryName, ct.CourseTopic, cu.LearningTimeMins AS LearningMinutes, - cu.IsAssessed + cu.IsAssessed, + CASE WHEN ap.ArchivedDate IS NOT NULL THEN 1 ELSE 0 END AS Archived FROM dbo.Customisations AS cu INNER JOIN dbo.CentreApplications AS ca ON ca.ApplicationID = cu.ApplicationID INNER JOIN dbo.Applications AS ap ON ap.ApplicationID = ca.ApplicationID diff --git a/DigitalLearningSolutions.Data/Models/Courses/Course.cs b/DigitalLearningSolutions.Data/Models/Courses/Course.cs index 3383d00d52..673deca9f6 100644 --- a/DigitalLearningSolutions.Data/Models/Courses/Course.cs +++ b/DigitalLearningSolutions.Data/Models/Courses/Course.cs @@ -6,6 +6,7 @@ public class Course : CourseNameInfo public int CentreId { get; set; } public int ApplicationId { get; set; } public bool Active { get; set; } + public bool Archived { get; set; } public string CourseNameWithInactiveFlag => !Active ? "Inactive - " + CourseName : CourseName; diff --git a/DigitalLearningSolutions.Data/Models/Courses/CourseStatisticsWithAdminFieldResponseCounts.cs b/DigitalLearningSolutions.Data/Models/Courses/CourseStatisticsWithAdminFieldResponseCounts.cs index 177e143c85..d59f91aec2 100644 --- a/DigitalLearningSolutions.Data/Models/Courses/CourseStatisticsWithAdminFieldResponseCounts.cs +++ b/DigitalLearningSolutions.Data/Models/Courses/CourseStatisticsWithAdminFieldResponseCounts.cs @@ -30,6 +30,7 @@ IEnumerable adminFieldsWithResponses Active = courseStatistics.Active; CustomisationName = courseStatistics.CustomisationName; ApplicationName = courseStatistics.ApplicationName; + Archived = courseStatistics.Archived; } public IEnumerable AdminFieldsWithResponses { get; set; } diff --git a/DigitalLearningSolutions.Web.Tests/Controllers/TrackingSystem/CourseSetup/CourseSetupControllerTests.cs b/DigitalLearningSolutions.Web.Tests/Controllers/TrackingSystem/CourseSetup/CourseSetupControllerTests.cs index 22b34dfa36..d64888f63a 100644 --- a/DigitalLearningSolutions.Web.Tests/Controllers/TrackingSystem/CourseSetup/CourseSetupControllerTests.cs +++ b/DigitalLearningSolutions.Web.Tests/Controllers/TrackingSystem/CourseSetup/CourseSetupControllerTests.cs @@ -81,6 +81,7 @@ public class CourseSetupControllerTests HideInLearnerPortal = true, DelegateCount = 1, CompletedCount = 1, + Archived = false, }, } ) diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/CourseSetup/CourseStatisticsViewModelFilterOptionsTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/CourseSetup/CourseStatisticsViewModelFilterOptionsTests.cs index d4564b834a..77d3b497e0 100644 --- a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/CourseSetup/CourseStatisticsViewModelFilterOptionsTests.cs +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/CourseSetup/CourseStatisticsViewModelFilterOptionsTests.cs @@ -38,7 +38,7 @@ public class CourseStatisticsViewModelFilterOptionsTests new[] { new FilterOptionModel( - "Inactive", + "Inactive/archived", "Status" + FilteringHelper.Separator + "Active" + FilteringHelper.Separator + "false", FilterStatus.Warning diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/DelegateCourses/DelegateCoursesStatisticsViewModelFilterOptionsTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/DelegateCourses/DelegateCoursesStatisticsViewModelFilterOptionsTests.cs index c81c652e75..9a3a330b6b 100644 --- a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/DelegateCourses/DelegateCoursesStatisticsViewModelFilterOptionsTests.cs +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/DelegateCourses/DelegateCoursesStatisticsViewModelFilterOptionsTests.cs @@ -38,7 +38,7 @@ public class DelegateCoursesStatisticsViewModelFilterOptionsTests new[] { new FilterOptionModel( - "Inactive", + "Inactive/archived", "Status" + FilteringHelper.Separator + "Active" + FilteringHelper.Separator + "false", FilterStatus.Warning diff --git a/DigitalLearningSolutions.Web/Helpers/FilterOptions/CourseFilterOptions.cs b/DigitalLearningSolutions.Web/Helpers/FilterOptions/CourseFilterOptions.cs index b19fdf3f57..5161abf43a 100644 --- a/DigitalLearningSolutions.Web/Helpers/FilterOptions/CourseFilterOptions.cs +++ b/DigitalLearningSolutions.Web/Helpers/FilterOptions/CourseFilterOptions.cs @@ -4,15 +4,13 @@ using DigitalLearningSolutions.Data.Helpers; using DigitalLearningSolutions.Data.Models.Courses; using DigitalLearningSolutions.Data.Models.SearchSortFilterPaginate; - using DigitalLearningSolutions.Web.Models.Enums; - using DigitalLearningSolutions.Web.ViewModels.Common.SearchablePage; public static class CourseStatusFilterOptions { private const string Group = "Status"; public static readonly FilterOptionModel IsInactive = new FilterOptionModel( - "Inactive", + "Inactive/archived", FilteringHelper.BuildFilterValueString(Group, nameof(CourseStatistics.Active), "false"), FilterStatus.Warning ); @@ -22,6 +20,12 @@ public static class CourseStatusFilterOptions FilteringHelper.BuildFilterValueString(Group, nameof(CourseStatistics.Active), "true"), FilterStatus.Success ); + + public static readonly FilterOptionModel IsArchived = new FilterOptionModel( + "Archived", + FilteringHelper.BuildFilterValueString(Group, nameof(CourseStatistics.Archived), "true"), + FilterStatus.Default + ); } public static class CourseVisibilityFilterOptions diff --git a/DigitalLearningSolutions.Web/Helpers/FilterableTagHelper.cs b/DigitalLearningSolutions.Web/Helpers/FilterableTagHelper.cs index c0abe255fd..9ae5e52e19 100644 --- a/DigitalLearningSolutions.Web/Helpers/FilterableTagHelper.cs +++ b/DigitalLearningSolutions.Web/Helpers/FilterableTagHelper.cs @@ -97,12 +97,44 @@ public static IEnumerable GetCurrentTagsForDelegateCours CourseStatistics courseStatistics ) { - return new List + var tags = new List(); + + if (courseStatistics.Archived) { - courseStatistics.Active - ? new SearchableTagViewModel(CourseStatusFilterOptions.IsActive) - : new SearchableTagViewModel(CourseStatusFilterOptions.IsInactive), - }; + tags.Add(new SearchableTagViewModel(CourseStatusFilterOptions.IsArchived)); + } + else if (courseStatistics.Active) + { + tags.Add(new SearchableTagViewModel(CourseStatusFilterOptions.IsActive)); + } + else + { + tags.Add(new SearchableTagViewModel(CourseStatusFilterOptions.IsInactive)); + } + + return tags; + } + + public static IEnumerable GetCurrentStatusTagsForDelegateCourses( + CourseStatistics courseStatistics + ) + { + var tags = new List(); + + if (courseStatistics.Archived) + { + tags.Add(new SearchableTagViewModel("Archived", string.Empty, CourseStatusFilterOptions.IsArchived.TagStatus)); + } + else if (courseStatistics.Active) + { + tags.Add(new SearchableTagViewModel("Active", string.Empty, CourseStatusFilterOptions.IsActive.TagStatus)); + } + else + { + tags.Add(new SearchableTagViewModel("Inactive", string.Empty, CourseStatusFilterOptions.IsInactive.TagStatus)); + } + + return tags; } public static IEnumerable GetCurrentTagsForCourseDelegate(CourseDelegate courseDelegate) diff --git a/DigitalLearningSolutions.Web/Services/CourseService.cs b/DigitalLearningSolutions.Web/Services/CourseService.cs index 6cf8e6da68..85ae3250a4 100644 --- a/DigitalLearningSolutions.Web/Services/CourseService.cs +++ b/DigitalLearningSolutions.Web/Services/CourseService.cs @@ -352,7 +352,7 @@ public IEnumerable GetTopicsForCentreAndCentrallyManagedCourses(int cent public CentreCourseDetails GetCentreCourseDetails(int centreId, int? categoryId) { var (courses, categories, topics) = ( - GetNonArchivedCentreSpecificCourseStatisticsWithAdminFieldResponseCounts(centreId, categoryId), + GetCentreSpecificCourseStatisticsWithAdminFieldResponseCounts(centreId, categoryId), courseCategoriesDataService.GetCategoriesForCentreAndCentrallyManagedCourses(centreId) .Select(c => c.CategoryName), courseTopicsDataService.GetCourseTopicsAvailableAtCentre(centreId).Select(c => c.CourseTopic)); diff --git a/DigitalLearningSolutions.Web/Styles/trackingSystem/courseSetup.scss b/DigitalLearningSolutions.Web/Styles/trackingSystem/courseSetup.scss index 5c85db3b5e..9d587649fb 100644 --- a/DigitalLearningSolutions.Web/Styles/trackingSystem/courseSetup.scss +++ b/DigitalLearningSolutions.Web/Styles/trackingSystem/courseSetup.scss @@ -1,7 +1,17 @@ @use "../shared/cardWithButtons"; +@use "nhsuk-frontend/packages/core/all" as *; +@use "../shared/cardWithButtons"; @use "../shared/searchableElements/searchableElements"; @use "../shared/headingButtons.scss"; .admin-field-count { width: 10%; } + +.status-inactive { + border-left: 6px solid tint($color_nhsuk-red, 80); +} + +.status-archived { + border-left: 6px solid $color_nhsuk-grey-2; +} diff --git a/DigitalLearningSolutions.Web/Styles/trackingSystem/viewDelegate.scss b/DigitalLearningSolutions.Web/Styles/trackingSystem/viewDelegate.scss index 6b018d664a..f66b4c3cdb 100644 --- a/DigitalLearningSolutions.Web/Styles/trackingSystem/viewDelegate.scss +++ b/DigitalLearningSolutions.Web/Styles/trackingSystem/viewDelegate.scss @@ -61,3 +61,11 @@ border-left: 6px solid $color_nhsuk-grey-2; } } + +.status-inactive { + border-left: 6px solid tint($color_nhsuk-red, 80); +} + +.status-archived { + border-left: 6px solid $color_nhsuk-grey-2; +} diff --git a/DigitalLearningSolutions.Web/ViewModels/Common/SearchablePage/SearchableTagViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/Common/SearchablePage/SearchableTagViewModel.cs index 4f09ed4bc2..462dd343ef 100644 --- a/DigitalLearningSolutions.Web/ViewModels/Common/SearchablePage/SearchableTagViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/Common/SearchablePage/SearchableTagViewModel.cs @@ -2,7 +2,6 @@ { using DigitalLearningSolutions.Data.Enums; using DigitalLearningSolutions.Data.Models.SearchSortFilterPaginate; - using DigitalLearningSolutions.Web.Models.Enums; public class SearchableTagViewModel : FilterOptionModel { @@ -15,6 +14,15 @@ public SearchableTagViewModel(FilterOptionModel filterOption, bool hidden = fals { Hidden = hidden; } + public SearchableTagViewModel(string displayText, string filterValue, FilterStatus tagStatus, bool hidden = false) + : base( + displayText, + filterValue, + tagStatus + ) + { + Hidden = hidden; + } public bool Hidden { get; set; } diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/CourseSetup/SearchableCourseStatisticsViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/CourseSetup/SearchableCourseStatisticsViewModel.cs index a836001b06..e5e4ffd0b2 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/CourseSetup/SearchableCourseStatisticsViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/CourseSetup/SearchableCourseStatisticsViewModel.cs @@ -38,6 +38,7 @@ public SearchableCourseStatisticsViewModel(CourseStatisticsWithAdminFieldRespons public string CourseTopic { get; set; } public string LearningMinutes { get; set; } public bool Assessed { get; set; } + public string? Status { get; set; } public IEnumerable AdminFieldWithResponseCounts { get; set; } public bool HasAdminFields => AdminFieldWithResponseCounts.Any(); diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DelegateCourses/DelegateCoursesViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DelegateCourses/DelegateCoursesViewModel.cs index 543420698d..f9a98ea036 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DelegateCourses/DelegateCoursesViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DelegateCourses/DelegateCoursesViewModel.cs @@ -19,9 +19,35 @@ IEnumerable availableFilters "Search courses" ) { + UpdateCourseActiveFlags(result); + Courses = result.ItemsToDisplay.Select(c => new SearchableDelegateCourseStatisticsViewModel(c)); } + private static void UpdateCourseActiveFlags(SearchSortFilterPaginationResult result) + { + foreach (var course in result.ItemsToDisplay) + { + if (course.Active && !course.Archived) + { + course.Active = true; + } + else + { + course.Active = false; + } + + if (course.Archived) + { + course.Archived = true; + } + else + { + course.Archived = false; + } + } + } + public IEnumerable Courses { get; set; } public override IEnumerable<(string, string)> SortOptions { get; } = new[] diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DelegateCourses/SearchableDelegateCourseStatisticsViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DelegateCourses/SearchableDelegateCourseStatisticsViewModel.cs index 9089aba228..02fc0cee2d 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DelegateCourses/SearchableDelegateCourseStatisticsViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DelegateCourses/SearchableDelegateCourseStatisticsViewModel.cs @@ -19,7 +19,7 @@ public SearchableDelegateCourseStatisticsViewModel(CourseStatisticsWithAdminFiel CategoryName = courseStatistics.CategoryName; CourseTopic = courseStatistics.CourseTopic; LearningMinutes = courseStatistics.LearningMinutes; - Tags = FilterableTagHelper.GetCurrentTagsForDelegateCourses(courseStatistics); + Tags = FilterableTagHelper.GetCurrentStatusTagsForDelegateCourses(courseStatistics); Assessed = courseStatistics.IsAssessed; AdminFieldWithResponseCounts = courseStatistics.AdminFieldsWithResponses; } @@ -32,7 +32,7 @@ public SearchableDelegateCourseStatisticsViewModel(CourseStatisticsWithAdminFiel public string CourseTopic { get; set; } public string LearningMinutes { get; set; } public bool Assessed { get; set; } - + public string? Status { get; set; } public IEnumerable AdminFieldWithResponseCounts { get; set; } public bool HasAdminFields => AdminFieldWithResponseCounts.Any(); @@ -49,5 +49,19 @@ public SearchableDelegateCourseStatisticsViewModel(CourseStatisticsWithAdminFiel FilteringHelper.Separator + nameof(CourseStatisticsWithAdminFieldResponseCounts.HasAdminFields) + FilteringHelper.Separator + HasAdminFields.ToString().ToLowerInvariant(); + private static string DeriveCourseStatus(Course courseStatistics) + { + if (courseStatistics.Archived) + { + return "archived"; + } + else switch (courseStatistics.Active) + { + case true: + return "active"; + case false: + return "inactive"; + } + } } } diff --git a/DigitalLearningSolutions.Web/Views/Shared/SearchablePage/_StatusTags.cshtml b/DigitalLearningSolutions.Web/Views/Shared/SearchablePage/_StatusTags.cshtml new file mode 100644 index 0000000000..fdc27a2438 --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/Shared/SearchablePage/_StatusTags.cshtml @@ -0,0 +1,10 @@ +@using DigitalLearningSolutions.Web.ViewModels.Common.SearchablePage +@model IEnumerable + +
+ @foreach (var tag in Model) { +
+ @tag.DisplayText +
+ } +
diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/DelegateCourses/_CentreCourseCard.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/DelegateCourses/_CentreCourseCard.cshtml index d27862da63..c235fda1c9 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/DelegateCourses/_CentreCourseCard.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/DelegateCourses/_CentreCourseCard.cshtml @@ -1,7 +1,7 @@ @using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates.DelegateCourses @model SearchableDelegateCourseStatisticsViewModel -
+
@@ -10,8 +10,8 @@
- - + + From 4b49f65b8bed21c9820497b9829866b9f177f01f Mon Sep 17 00:00:00 2001 From: martinfoster-hee Date: Wed, 11 Jan 2023 14:11:52 +0000 Subject: [PATCH 2/3] Removed duplicate css include. --- .../Styles/trackingSystem/courseSetup.scss | 1 - 1 file changed, 1 deletion(-) diff --git a/DigitalLearningSolutions.Web/Styles/trackingSystem/courseSetup.scss b/DigitalLearningSolutions.Web/Styles/trackingSystem/courseSetup.scss index 9d587649fb..3eb14000b9 100644 --- a/DigitalLearningSolutions.Web/Styles/trackingSystem/courseSetup.scss +++ b/DigitalLearningSolutions.Web/Styles/trackingSystem/courseSetup.scss @@ -1,6 +1,5 @@ @use "../shared/cardWithButtons"; @use "nhsuk-frontend/packages/core/all" as *; -@use "../shared/cardWithButtons"; @use "../shared/searchableElements/searchableElements"; @use "../shared/headingButtons.scss"; From f7865b9c81bc5e06118d9ed67443a900078c6fe8 Mon Sep 17 00:00:00 2001 From: martinfoster-hee Date: Wed, 11 Jan 2023 15:51:30 +0000 Subject: [PATCH 3/3] Added missing status calculation method call. --- .../SearchableDelegateCourseStatisticsViewModel.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DelegateCourses/SearchableDelegateCourseStatisticsViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DelegateCourses/SearchableDelegateCourseStatisticsViewModel.cs index 02fc0cee2d..31951e626b 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DelegateCourses/SearchableDelegateCourseStatisticsViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DelegateCourses/SearchableDelegateCourseStatisticsViewModel.cs @@ -22,6 +22,7 @@ public SearchableDelegateCourseStatisticsViewModel(CourseStatisticsWithAdminFiel Tags = FilterableTagHelper.GetCurrentStatusTagsForDelegateCourses(courseStatistics); Assessed = courseStatistics.IsAssessed; AdminFieldWithResponseCounts = courseStatistics.AdminFieldsWithResponses; + Status = DeriveCourseStatus(courseStatistics); } public int CustomisationId { get; set; }