diff --git a/DigitalLearningSolutions.Data.Tests/DataServices/CourseDataServiceTests.cs b/DigitalLearningSolutions.Data.Tests/DataServices/CourseDataServiceTests.cs index df47de9053..07af4366f4 100644 --- a/DigitalLearningSolutions.Data.Tests/DataServices/CourseDataServiceTests.cs +++ b/DigitalLearningSolutions.Data.Tests/DataServices/CourseDataServiceTests.cs @@ -346,6 +346,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 adb7681fc0..40b4413071 100644 --- a/DigitalLearningSolutions.Data/DataServices/CourseDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/CourseDataService.cs @@ -175,7 +175,7 @@ FROM CustomisationTutorials AS ct private readonly string CourseStatisticsQuery = @$"SELECT 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, @@ -188,7 +188,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..2e151a3410 100644 --- a/DigitalLearningSolutions.Data/Models/Courses/Course.cs +++ b/DigitalLearningSolutions.Data/Models/Courses/Course.cs @@ -6,7 +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; public override bool Equals(object? obj) 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.Data/Services/CourseService.cs b/DigitalLearningSolutions.Data/Services/CourseService.cs index 8f8fbd3a52..6977584f69 100644 --- a/DigitalLearningSolutions.Data/Services/CourseService.cs +++ b/DigitalLearningSolutions.Data/Services/CourseService.cs @@ -351,7 +351,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.Tests/Controllers/TrackingSystem/CourseSetup/CourseSetupControllerTests.cs b/DigitalLearningSolutions.Web.Tests/Controllers/TrackingSystem/CourseSetup/CourseSetupControllerTests.cs index 2fa91396f2..03826bf9da 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 3de4aca091..be1bf08fba 100644 --- a/DigitalLearningSolutions.Web/Helpers/FilterableTagHelper.cs +++ b/DigitalLearningSolutions.Web/Helpers/FilterableTagHelper.cs @@ -96,12 +96,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/Styles/trackingSystem/courseSetup.scss b/DigitalLearningSolutions.Web/Styles/trackingSystem/courseSetup.scss index 5c85db3b5e..c7da489d3e 100644 --- a/DigitalLearningSolutions.Web/Styles/trackingSystem/courseSetup.scss +++ b/DigitalLearningSolutions.Web/Styles/trackingSystem/courseSetup.scss @@ -1,7 +1,16 @@ -@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..911b5e2afa 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 { @@ -16,6 +15,16 @@ 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; } public string NhsTagStyle() 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..a3f548ab81 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DelegateCourses/DelegateCoursesViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DelegateCourses/DelegateCoursesViewModel.cs @@ -19,9 +19,36 @@ 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..44126ea121 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DelegateCourses/SearchableDelegateCourseStatisticsViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/DelegateCourses/SearchableDelegateCourseStatisticsViewModel.cs @@ -19,9 +19,10 @@ 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; + Status = DeriveCourseStatus(courseStatistics); } public int CustomisationId { get; set; } @@ -32,6 +33,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; } @@ -49,5 +51,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/_FilterableTags.cshtml b/DigitalLearningSolutions.Web/Views/Shared/SearchablePage/_FilterableTags.cshtml index 7aaed03192..514a1e076e 100644 --- a/DigitalLearningSolutions.Web/Views/Shared/SearchablePage/_FilterableTags.cshtml +++ b/DigitalLearningSolutions.Web/Views/Shared/SearchablePage/_FilterableTags.cshtml @@ -2,7 +2,8 @@ @model IEnumerable
- @foreach (var tag in Model) { + @foreach (var tag in Model) + {
@tag.DisplayText
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/CourseSetup/_CentreCourseCard.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/CourseSetup/_CentreCourseCard.cshtml index cade51f5d8..506817ce22 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/CourseSetup/_CentreCourseCard.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/CourseSetup/_CentreCourseCard.cshtml @@ -11,7 +11,6 @@
- diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/DelegateCourses/_CentreCourseCard.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/DelegateCourses/_CentreCourseCard.cshtml index d27862da63..d3f21674b3 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,12 +10,14 @@
- + + - @if (Model.HasAdminFields) { + @if (Model.HasAdminFields) + { }