From f474f37ec91e9dea6734d961f8a9fbbd30f5127e Mon Sep 17 00:00:00 2001 From: Alex Jackson Date: Tue, 15 Jun 2021 16:30:59 +0100 Subject: [PATCH 1/5] HEEDLS-468 Add centre ranking page --- .../Centre/Ranking/RankingController.cs | 17 +++++++ .../Helpers/CustomClaimHelper.cs | 5 ++ .../Styles/trackingSystem/centreRanking.scss | 15 ++++++ .../Centre/Ranking/CentreRankViewModel.cs | 18 +++++++ .../Centre/Ranking/CentreRankingViewModel.cs | 32 +++++++++++++ .../_DashboardBottomCardGroup.cshtml | 2 +- .../Centre/Ranking/Index.cshtml | 48 +++++++++++++++++++ .../Ranking/_RankingStandardUserTable.cshtml | 29 +++++++++++ .../Ranking/_RankingSuperAdminTable.cshtml | 46 ++++++++++++++++++ 9 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Ranking/RankingController.cs create mode 100644 DigitalLearningSolutions.Web/Styles/trackingSystem/centreRanking.scss create mode 100644 DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankViewModel.cs create mode 100644 DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankingViewModel.cs create mode 100644 DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/Index.cshtml create mode 100644 DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingStandardUserTable.cshtml create mode 100644 DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingSuperAdminTable.cshtml diff --git a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Ranking/RankingController.cs b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Ranking/RankingController.cs new file mode 100644 index 0000000000..0027debe72 --- /dev/null +++ b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Ranking/RankingController.cs @@ -0,0 +1,17 @@ +namespace DigitalLearningSolutions.Web.Controllers.TrackingSystem.Centre.Ranking +{ + using DigitalLearningSolutions.Web.Helpers; + using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Centre.Ranking; + using Microsoft.AspNetCore.Authorization; + using Microsoft.AspNetCore.Mvc; + + [Authorize(Policy = CustomPolicies.UserCentreAdmin)] + [Route("/TrackingSystem/Centre/Ranking")] + public class RankingController : Controller + { + public IActionResult Index() + { + return View(new CentreRankingViewModel()); + } + } +} diff --git a/DigitalLearningSolutions.Web/Helpers/CustomClaimHelper.cs b/DigitalLearningSolutions.Web/Helpers/CustomClaimHelper.cs index 4eadf8dd4c..f359f122cf 100644 --- a/DigitalLearningSolutions.Web/Helpers/CustomClaimHelper.cs +++ b/DigitalLearningSolutions.Web/Helpers/CustomClaimHelper.cs @@ -86,5 +86,10 @@ public static bool HasCentreManagerPermissions(this ClaimsPrincipal user) return (user.GetCustomClaimAsBool(CustomClaimTypes.UserCentreManager) ?? false) || (user.GetCustomClaimAsBool(CustomClaimTypes.UserUserAdmin) ?? false); } + + public static bool HasSuperAdminPermissions(this ClaimsPrincipal user) + { + return user.GetCustomClaimAsBool(CustomClaimTypes.UserUserAdmin) ?? false; + } } } diff --git a/DigitalLearningSolutions.Web/Styles/trackingSystem/centreRanking.scss b/DigitalLearningSolutions.Web/Styles/trackingSystem/centreRanking.scss new file mode 100644 index 0000000000..08caa40990 --- /dev/null +++ b/DigitalLearningSolutions.Web/Styles/trackingSystem/centreRanking.scss @@ -0,0 +1,15 @@ +@import "~nhsuk-frontend/packages/core/all"; + +.current-centre { + background-color: $color_nhsuk-grey-3; +} + +.cell-left-padding { + padding-left: nhsuk-spacing(2); +} + +.cell-right-padding { + @include govuk-media-query($until: desktop) { + padding-right: nhsuk-spacing(2) !important; + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankViewModel.cs new file mode 100644 index 0000000000..486ff94e30 --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankViewModel.cs @@ -0,0 +1,18 @@ +namespace DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Centre.Ranking +{ + public class CentreRankViewModel + { + public CentreRankViewModel(int rank, string centreName, int sum) + { + Rank = rank; + CentreName = centreName; + Sum = sum; + } + + public int Rank { get; set; } + + public string CentreName { get; set; } + + public int Sum { get; set; } + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankingViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankingViewModel.cs new file mode 100644 index 0000000000..21d7541de0 --- /dev/null +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankingViewModel.cs @@ -0,0 +1,32 @@ +namespace DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Centre.Ranking +{ + using System.Collections.Generic; + using System.Linq; + + public class CentreRankingViewModel + { + public CentreRankingViewModel() + { + CurrentCentre = new CentreRankViewModel(23, "Test Centre 13", 123); + TopTenCentres = new[] + { + new CentreRankViewModel(1, "Test Centre 1", 9000), + new CentreRankViewModel(2, "Test Centre 2", 8000), + new CentreRankViewModel(3, "Test Centre 3", 7000), + new CentreRankViewModel(4, "Test Centre 4", 6000), + new CentreRankViewModel(5, "Test Centre 5", 5000), + new CentreRankViewModel(6, "Test Centre 6", 4000), + new CentreRankViewModel(7, "Test Centre 7", 3000), + new CentreRankViewModel(8, "Test Centre 8", 2000), + new CentreRankViewModel(9, "Test Centre 9", 1000), + new CentreRankViewModel(10, "Test Centre 10", 500) + }; + } + + public IEnumerable TopTenCentres { get; set; } + + public CentreRankViewModel CurrentCentre { get; set; } + + public bool IsCurrentCentreInTopTen => TopTenCentres.Contains(CurrentCentre); + } +} diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Dashboard/_DashboardBottomCardGroup.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Dashboard/_DashboardBottomCardGroup.cshtml index 739a02bd5b..5471d18df9 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Dashboard/_DashboardBottomCardGroup.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Dashboard/_DashboardBottomCardGroup.cshtml @@ -40,7 +40,7 @@

- Centre ranking + Centre ranking

See centre rankings by week, month, or year

diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/Index.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/Index.cshtml new file mode 100644 index 0000000000..040c18ce81 --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/Index.cshtml @@ -0,0 +1,48 @@ +@inject IConfiguration Configuration + +@using DigitalLearningSolutions.Web.Helpers +@using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Centre.Ranking +@using Microsoft.Extensions.Configuration +@model CentreRankingViewModel + + + +@{ + ViewData["Title"] = "Centre ranking"; + ViewData["Application"] = "Tracking System"; + ViewData["HeaderPath"] = $"{Configuration["AppRootPath"]}/TrackingSystem/Centre/Dashboard"; + ViewData["HeaderPathName"] = "Tracking System"; +} + +@section NavMenuItems { + +} + +@section NavBreadcrumbs { + +} + +
+
+

Centre ranking

+ +

The top ten Digital Learning Solutions centres by learner course launches.

+ + @if (User.HasSuperAdminPermissions()) { + + } else { + + } +
+
diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingStandardUserTable.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingStandardUserTable.cshtml new file mode 100644 index 0000000000..73a632100f --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingStandardUserTable.cshtml @@ -0,0 +1,29 @@ +@using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Centre.Ranking +@model CentreRankingViewModel + + + + + + + + + + @foreach (var centre in Model.TopTenCentres) { + + + + + } + @if (!Model.IsCurrentCentreInTopTen) { + + + + + } + +
+ Rank + + Centre +
@centre.Rank@centre.CentreName
@Model.CurrentCentre.Rank@Model.CurrentCentre.CentreName
diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingSuperAdminTable.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingSuperAdminTable.cshtml new file mode 100644 index 0000000000..a964ae0552 --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingSuperAdminTable.cshtml @@ -0,0 +1,46 @@ +@using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Centre.Ranking +@model CentreRankingViewModel + + + + + + + + + + + @foreach (var centre in Model.TopTenCentres) { + + + + + + } + @if (!Model.IsCurrentCentreInTopTen) { + + + + + + } + +
+ Rank + + Centre + + Sum +
+ Rank @centre.Rank + + Centre @centre.CentreName + + Sum @centre.Sum +
+ Rank @Model.CurrentCentre.Rank + + Centre @Model.CurrentCentre.CentreName + + Sum @Model.CurrentCentre.Sum +
From e03c2e3e4fdb94e50aad8dcfe7a41392703dcc6f Mon Sep 17 00:00:00 2001 From: Alex Jackson Date: Wed, 16 Jun 2021 15:49:29 +0100 Subject: [PATCH 2/5] HEEDLS-468 Add Centre ranking page backend logic --- .../Services/CentresServiceTests.cs | 92 ++++++++++++++++++ .../TestHelpers/CentreTestHelper.cs | 12 +++ .../DataServices/CentresDataService.cs | 60 +++++++----- .../Models/DbModels/CentreRank.cs | 13 +++ .../Services/CentresService.cs | 50 ++++++++++ .../BasicAccessibilityTests.cs | 4 +- .../Centre/CentreRankingViewModelTests.cs | 95 +++++++++++++++++++ .../DashboardCentreDetailsViewModelTests.cs | 3 +- .../Centre/DashboardController.cs | 16 ++-- .../Centre/Ranking/RankingController.cs | 13 ++- DigitalLearningSolutions.Web/Startup.cs | 1 + .../Styles/trackingSystem/centreRanking.scss | 8 +- .../Dashboard/CentreDashboardViewModel.cs | 5 +- .../DashboardCentreDetailsViewModel.cs | 5 +- .../Centre/Ranking/CentreRankingViewModel.cs | 29 +++--- .../Dashboard/_DashboardCentreDetails.cshtml | 9 ++ .../Ranking/_RankingStandardUserTable.cshtml | 10 +- .../Ranking/_RankingSuperAdminTable.cshtml | 13 ++- 18 files changed, 380 insertions(+), 58 deletions(-) create mode 100644 DigitalLearningSolutions.Data.Tests/Services/CentresServiceTests.cs create mode 100644 DigitalLearningSolutions.Data/Models/DbModels/CentreRank.cs create mode 100644 DigitalLearningSolutions.Data/Services/CentresService.cs create mode 100644 DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/CentreRankingViewModelTests.cs diff --git a/DigitalLearningSolutions.Data.Tests/Services/CentresServiceTests.cs b/DigitalLearningSolutions.Data.Tests/Services/CentresServiceTests.cs new file mode 100644 index 0000000000..8454481812 --- /dev/null +++ b/DigitalLearningSolutions.Data.Tests/Services/CentresServiceTests.cs @@ -0,0 +1,92 @@ +namespace DigitalLearningSolutions.Data.Tests.Services +{ + using System; + using System.Linq; + using DigitalLearningSolutions.Data.DataServices; + using DigitalLearningSolutions.Data.Services; + using DigitalLearningSolutions.Data.Tests.TestHelpers; + using FakeItEasy; + using FluentAssertions; + using NUnit.Framework; + + public class CentresServiceTests + { + private ICentresDataService centresDataService = null!; + private ICentresService centresService = null!; + + [SetUp] + public void Setup() + { + centresDataService = A.Fake(); + centresService = new CentresService(centresDataService); + + A.CallTo(() => centresDataService.GetCentreRanks(A._, A._)).Returns( + new[] + { + CentreTestHelper.GetCentreRank(1), + CentreTestHelper.GetCentreRank(2), + CentreTestHelper.GetCentreRank(3), + CentreTestHelper.GetCentreRank(4), + CentreTestHelper.GetCentreRank(5), + CentreTestHelper.GetCentreRank(6), + CentreTestHelper.GetCentreRank(7), + CentreTestHelper.GetCentreRank(8), + CentreTestHelper.GetCentreRank(9), + CentreTestHelper.GetCentreRank(10), + CentreTestHelper.GetCentreRank(11), + CentreTestHelper.GetCentreRank(12) + } + ); + } + + [Test] + public void GetCentreRanks_returns_expected_list_when_centre_in_top_ten() + { + // When + var result = centresService.GetCentreRanks(3, 14, -1); + + // Then + result.Count().Should().Be(10); + } + + [Test] + public void GetCentreRanks_returns_expected_list_when_centre_is_not_in_top_ten() + { + // When + var result = centresService.GetCentreRanks(12, 14, -1); + + // Then + result.Count().Should().Be(11); + } + + [Test] + public void GetCentreRanks_returns_expected_list_when_centre_has_no_data() + { + // When + var result = centresService.GetCentreRanks(20, 14, -1); + + // Then + result.Count().Should().Be(10); + } + + [Test] + public void GetCentreRankForCentre_returns_expected_value() + { + // When + var result = centresService.GetCentreRankForCentre(3); + + // Then + result.Should().Be(3); + } + + [Test] + public void GetCentreRankForCentre_returns_negative_one_with_no_data_for_centre() + { + // When + var result = centresService.GetCentreRankForCentre(20); + + // Then + result.Should().Be(-1); + } + } +} diff --git a/DigitalLearningSolutions.Data.Tests/TestHelpers/CentreTestHelper.cs b/DigitalLearningSolutions.Data.Tests/TestHelpers/CentreTestHelper.cs index 2ea1710815..8ede357d5a 100644 --- a/DigitalLearningSolutions.Data.Tests/TestHelpers/CentreTestHelper.cs +++ b/DigitalLearningSolutions.Data.Tests/TestHelpers/CentreTestHelper.cs @@ -1,6 +1,7 @@ namespace DigitalLearningSolutions.Data.Tests.TestHelpers { using DigitalLearningSolutions.Data.Models; + using DigitalLearningSolutions.Data.Models.DbModels; public static class CentreTestHelper { @@ -66,5 +67,16 @@ public static Centre GetDefaultCentre ContractType = contractType }; } + + public static CentreRank GetCentreRank(int rank) + { + return new CentreRank + { + CentreId = rank, + Rank = rank, + CentreName = $"Centre {rank}", + Sum = 10000-rank*10 + }; + } } } diff --git a/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs b/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs index 5927db2938..9b88c06c72 100644 --- a/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs @@ -5,6 +5,7 @@ using System.Data; using Dapper; using DigitalLearningSolutions.Data.Models; + using DigitalLearningSolutions.Data.Models.DbModels; using Microsoft.Extensions.Logging; public interface ICentresDataService @@ -14,8 +15,7 @@ public interface ICentresDataService IEnumerable<(int, string)> GetActiveCentresAlphabetical(); Centre? GetCentreDetailsById(int centreId); - void UpdateCentreManagerDetails - ( + void UpdateCentreManagerDetails( int centreId, string firstName, string lastName, @@ -23,8 +23,7 @@ void UpdateCentreManagerDetails string? telephone ); - void UpdateCentreWebsiteDetails - ( + void UpdateCentreWebsiteDetails( int centreId, string postcode, bool showOnMap, @@ -39,6 +38,8 @@ void UpdateCentreWebsiteDetails (string firstName, string lastName, string email) GetCentreManagerDetails(int centreId); string[] GetCentreIpPrefixes(int centreId); + + IEnumerable GetCentreRanks(DateTime dateSince, int regionId); } public class CentresDataService : ICentresDataService @@ -54,8 +55,7 @@ public CentresDataService(IDbConnection connection, ILogger public string? GetBannerText(int centreId) { - return connection.QueryFirstOrDefault - ( + return connection.QueryFirstOrDefault( @"SELECT BannerText FROM Centres WHERE CentreID = @centreId", @@ -65,8 +65,7 @@ FROM Centres public string? GetCentreName(int centreId) { - var name = connection.QueryFirstOrDefault - ( + var name = connection.QueryFirstOrDefault( @"SELECT CentreName FROM Centres WHERE CentreID = @centreId", @@ -97,8 +96,7 @@ ORDER BY CentreName" public Centre? GetCentreDetailsById(int centreId) { - var centre = connection.QueryFirstOrDefault - ( + var centre = connection.QueryFirstOrDefault( @"SELECT c.CentreID, c.CentreName, c.RegionID, @@ -147,8 +145,7 @@ FROM Centres AS c return centre; } - public void UpdateCentreManagerDetails - ( + public void UpdateCentreManagerDetails( int centreId, string firstName, string lastName, @@ -156,8 +153,7 @@ public void UpdateCentreManagerDetails string? telephone ) { - connection.Execute - ( + connection.Execute( @"UPDATE Centres SET ContactForename = @firstName, ContactSurname = @lastName, @@ -168,8 +164,7 @@ public void UpdateCentreManagerDetails ); } - public void UpdateCentreWebsiteDetails - ( + public void UpdateCentreWebsiteDetails( int centreId, string postcode, bool showOnMap, @@ -182,8 +177,7 @@ public void UpdateCentreWebsiteDetails string? otherInformation = null ) { - connection.Execute - ( + connection.Execute( @"UPDATE Centres SET pwTelephone = @telephone, pwEmail = @email, @@ -213,8 +207,7 @@ public void UpdateCentreWebsiteDetails public (string firstName, string lastName, string email) GetCentreManagerDetails(int centreId) { - var info = connection.QueryFirstOrDefault<(string, string, string)> - ( + var info = connection.QueryFirstOrDefault<(string, string, string)>( @"SELECT ContactForename, ContactSurname, ContactEmail FROM Centres WHERE CentreID = @centreId", @@ -225,8 +218,7 @@ FROM Centres public string[] GetCentreIpPrefixes(int centreId) { - var ipPrefixString = connection.QueryFirstOrDefault - ( + var ipPrefixString = connection.QueryFirstOrDefault( @"SELECT IPPrefix FROM Centres WHERE CentreID = @centreId", @@ -236,5 +228,29 @@ FROM Centres var ipPrefixes = ipPrefixString?.Split(',', StringSplitOptions.RemoveEmptyEntries); return ipPrefixes ?? new string[0]; } + + public IEnumerable GetCentreRanks(DateTime dateSince, int regionId) + { + return connection.Query( + @"SELECT + RANK() over (ORDER BY tc.CentreIDCount DESC) as [Rank], + c.CentreID, + c.CentreName, + tc.CentreIDCount as [Sum] + FROM + ( + SELECT + Count(c.CentreID) as CentreIDCount, + c.CentreID + FROM [Sessions] s + INNER JOIN Candidates c on s.CandidateID = c.CandidateID + INNER JOIN Centres ct on c.CentreID = ct.CentreID + WHERE s.LoginTime > @dateSince AND c.CentreID <> 101 AND (ct.RegionID = @RegionID OR @RegionID = -1) + GROUP BY c.CentreID + ) as tc + INNER JOIN Centres c ON tc.CentreID = c.CentreID", + new { dateSince, regionId } + ); + } } } diff --git a/DigitalLearningSolutions.Data/Models/DbModels/CentreRank.cs b/DigitalLearningSolutions.Data/Models/DbModels/CentreRank.cs new file mode 100644 index 0000000000..3622760693 --- /dev/null +++ b/DigitalLearningSolutions.Data/Models/DbModels/CentreRank.cs @@ -0,0 +1,13 @@ +namespace DigitalLearningSolutions.Data.Models.DbModels +{ + public class CentreRank + { + public int CentreId { get; set; } + + public int Rank { get; set; } + + public string CentreName { get; set; } + + public int Sum { get; set; } + } +} diff --git a/DigitalLearningSolutions.Data/Services/CentresService.cs b/DigitalLearningSolutions.Data/Services/CentresService.cs new file mode 100644 index 0000000000..9da9862ebd --- /dev/null +++ b/DigitalLearningSolutions.Data/Services/CentresService.cs @@ -0,0 +1,50 @@ +namespace DigitalLearningSolutions.Data.Services +{ + using System; + using System.Collections.Generic; + using System.Linq; + using DigitalLearningSolutions.Data.DataServices; + using DigitalLearningSolutions.Data.Models.DbModels; + + public interface ICentresService + { + IEnumerable GetCentreRanks(int centreId, int numberOfDays, int regionId); + + int GetCentreRankForCentre(int centreId); + } + + public class CentresService : ICentresService + { + private readonly ICentresDataService centresDataService; + + public CentresService(ICentresDataService centresDataService) + { + this.centresDataService = centresDataService; + } + + public IEnumerable GetCentreRanks(int centreId, int numberOfDays, int regionId) + { + var dateSince = DateTime.UtcNow.AddDays(-numberOfDays); + + var centreRanks = centresDataService.GetCentreRanks(dateSince, regionId).OrderBy(cr => cr.Rank).ToList(); + + var topTenCentres = centreRanks.Take(10).ToList(); + + var currentCentreRank = centreRanks.SingleOrDefault(cr => cr.CentreId == centreId); + + if (currentCentreRank == null) + { + return topTenCentres; + } + + return topTenCentres.Contains(currentCentreRank) ? topTenCentres : topTenCentres.Append(currentCentreRank); + } + + public int GetCentreRankForCentre(int centreId) + { + var centreRanks = centresDataService.GetCentreRanks(DateTime.UtcNow.AddDays(-14), -1); + var centreRank = centreRanks.SingleOrDefault(cr => cr.CentreId == centreId); + return centreRank?.Rank ?? -1; + } + } +} diff --git a/DigitalLearningSolutions.Web.AutomatedUiTests/AccessibilityTests/BasicAccessibilityTests.cs b/DigitalLearningSolutions.Web.AutomatedUiTests/AccessibilityTests/BasicAccessibilityTests.cs index fd3ef0cd81..3a9c1ae312 100644 --- a/DigitalLearningSolutions.Web.AutomatedUiTests/AccessibilityTests/BasicAccessibilityTests.cs +++ b/DigitalLearningSolutions.Web.AutomatedUiTests/AccessibilityTests/BasicAccessibilityTests.cs @@ -1,9 +1,6 @@ namespace DigitalLearningSolutions.Web.AutomatedUiTests.AccessibilityTests { using DigitalLearningSolutions.Web.AutomatedUiTests.TestHelpers; - using FluentAssertions; - using OpenQA.Selenium; - using Selenium.Axe; using Xunit; public class BasicAccessibilityTests : AccessibilityTestsBase @@ -31,6 +28,7 @@ public void Page_has_no_accessibility_errors(string url, string pageTitle) [InlineData("/MyAccount/EditDetails", "Edit details")] [InlineData("/TrackingSystem/Centre/Administrators", "Centre administrators")] [InlineData("/TrackingSystem/Centre/Dashboard", "Centre dashboard")] + [InlineData("/TrackingSystem/Centre/Ranking", "Centre ranking")] [InlineData("/TrackingSystem/CentreConfiguration", "Centre configuration")] [InlineData("/TrackingSystem/CentreConfiguration/EditCentreManagerDetails", "Edit centre manager details")] [InlineData("/TrackingSystem/CentreConfiguration/EditCentreWebsiteDetails", "Edit centre content on DLS website")] diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/CentreRankingViewModelTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/CentreRankingViewModelTests.cs new file mode 100644 index 0000000000..248309f23c --- /dev/null +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/CentreRankingViewModelTests.cs @@ -0,0 +1,95 @@ +namespace DigitalLearningSolutions.Web.Tests.ViewModels.TrackingSystem.Centre +{ + using System.Linq; + using DigitalLearningSolutions.Data.Models.DbModels; + using DigitalLearningSolutions.Data.Tests.TestHelpers; + using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Centre.Ranking; + using FluentAssertions; + using FluentAssertions.Execution; + using NUnit.Framework; + + public class CentreRankingViewModelTests + { + private readonly CentreRank[] centreRankings = + { + CentreTestHelper.GetCentreRank(1), + CentreTestHelper.GetCentreRank(2), + CentreTestHelper.GetCentreRank(3), + CentreTestHelper.GetCentreRank(4), + CentreTestHelper.GetCentreRank(5), + CentreTestHelper.GetCentreRank(6), + CentreTestHelper.GetCentreRank(7), + CentreTestHelper.GetCentreRank(8), + CentreTestHelper.GetCentreRank(9), + CentreTestHelper.GetCentreRank(10) + }; + + [Test] + public void CentreRankingViewModelViewModel_populates_expected_values_from_centre_ranks_with_centre_in_top_ten() + { + // When + var result = new CentreRankingViewModel(centreRankings, 3); + + // Then + using (new AssertionScope()) + { + result.TopTenCentres.Count().Should().Be(10); + result.CurrentCentre!.Rank.Should().Be(3); + result.IsCurrentCentreInTopTen.Should().BeTrue(); + } + } + + [Test] + public void + CentreRankingViewModelViewModel_populates_expected_values_from_centre_ranks_with_centre_not_in_top_ten() + { + // Given + var centreRankingsWithExtraCentre = centreRankings.Append(CentreTestHelper.GetCentreRank(20)); + + // When + var result = new CentreRankingViewModel(centreRankingsWithExtraCentre, 20); + + // Then + using (new AssertionScope()) + { + result.TopTenCentres.Count().Should().Be(10); + result.CurrentCentre!.Rank.Should().Be(20); + result.IsCurrentCentreInTopTen.Should().BeFalse(); + } + } + + [Test] + public void + CentreRankingViewModelViewModel_populates_expected_values_from_centre_ranks_when_centre_has_no_data() + { + // When + var result = new CentreRankingViewModel(centreRankings, 20); + + // Then + using (new AssertionScope()) + { + result.TopTenCentres.Count().Should().Be(10); + result.CurrentCentre.Should().BeNull(); + result.IsCurrentCentreInTopTen.Should().BeFalse(); + } + } + + [Test] + public void CentreRankingViewModelViewModel_populates_expected_values_from_centre_ranks_with_less_data() + { + // Given + var shortedCentreRankings = centreRankings.Take(5); + + // When + var result = new CentreRankingViewModel(shortedCentreRankings, 20); + + // Then + using (new AssertionScope()) + { + result.TopTenCentres.Count().Should().Be(5); + result.CurrentCentre.Should().BeNull(); + result.IsCurrentCentreInTopTen.Should().BeFalse(); + } + } + } +} diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/DashboardCentreDetailsViewModelTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/DashboardCentreDetailsViewModelTests.cs index 651bceefde..95b92bb8c4 100644 --- a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/DashboardCentreDetailsViewModelTests.cs +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/DashboardCentreDetailsViewModelTests.cs @@ -14,7 +14,7 @@ public void DashboardCentreDetailsViewModel_populates_expected_values_from_centr const string userIp = "1.1.1.1"; var centre = CentreTestHelper.GetDefaultCentre(); - var viewModel = new DashboardCentreDetailsViewModel(centre, userIp); + var viewModel = new DashboardCentreDetailsViewModel(centre, userIp, 12); // Then using (new AssertionScope()) @@ -29,6 +29,7 @@ public void DashboardCentreDetailsViewModel_populates_expected_values_from_centr viewModel.ApprovedIps.Should().BeEquivalentTo(centre.IpPrefix); viewModel.Telephone.Should().BeEquivalentTo(centre.ContactTelephone); viewModel.Email.Should().BeEquivalentTo(centre.ContactEmail); + viewModel.CentreRank.Should().Be(12); } } } diff --git a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/DashboardController.cs b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/DashboardController.cs index a46551b6c0..f35e684844 100644 --- a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/DashboardController.cs +++ b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/DashboardController.cs @@ -12,22 +12,24 @@ public class DashboardController : Controller { private readonly ICentresDataService centresDataService; - private readonly IUserDataService userDataService; + private readonly ICentresService centresService; private readonly ICourseService courseService; private readonly ISupportTicketDataService ticketDataService; + private readonly IUserDataService userDataService; - public DashboardController - ( + public DashboardController( IUserDataService userDataService, ICentresDataService centresDataService, ICourseService courseService, - ISupportTicketDataService ticketDataService + ISupportTicketDataService ticketDataService, + ICentresService centresService ) { this.userDataService = userDataService; this.centresDataService = centresDataService; this.courseService = courseService; this.ticketDataService = ticketDataService; + this.centresService = centresService; } public IActionResult Index() @@ -39,7 +41,8 @@ public IActionResult Index() var courseCount = courseService.GetNumberOfActiveCoursesAtCentreForCategory(centreId, adminUser.CategoryId); var adminCount = userDataService.GetNumberOfActiveAdminsAtCentre(centreId); var supportTicketCount = ticketDataService.GetNumberOfUnarchivedTicketsForCentreId(centreId); - + var centreRank = centresService.GetCentreRankForCentre(User.GetCentreId()); + var model = new CentreDashboardViewModel( centre, adminUser.FirstName, @@ -48,7 +51,8 @@ public IActionResult Index() delegateCount, courseCount, adminCount, - supportTicketCount + supportTicketCount, + centreRank ); return View(model); diff --git a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Ranking/RankingController.cs b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Ranking/RankingController.cs index 0027debe72..32382e60c4 100644 --- a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Ranking/RankingController.cs +++ b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Ranking/RankingController.cs @@ -1,5 +1,6 @@ namespace DigitalLearningSolutions.Web.Controllers.TrackingSystem.Centre.Ranking { + using DigitalLearningSolutions.Data.Services; using DigitalLearningSolutions.Web.Helpers; using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Centre.Ranking; using Microsoft.AspNetCore.Authorization; @@ -9,9 +10,19 @@ [Route("/TrackingSystem/Centre/Ranking")] public class RankingController : Controller { + private readonly ICentresService centresService; + + public RankingController(ICentresService centresService) + { + this.centresService = centresService; + } + public IActionResult Index() { - return View(new CentreRankingViewModel()); + // TODO: HEEDLS-469 Populate these numbers from filters + var centreRankings = centresService.GetCentreRanks(User.GetCentreId(), 14, -1); + + return View(new CentreRankingViewModel(centreRankings, User.GetCentreId())); } } } diff --git a/DigitalLearningSolutions.Web/Startup.cs b/DigitalLearningSolutions.Web/Startup.cs index e23d36f3c0..07b598eb94 100644 --- a/DigitalLearningSolutions.Web/Startup.cs +++ b/DigitalLearningSolutions.Web/Startup.cs @@ -102,6 +102,7 @@ public void ConfigureServices(IServiceCollection services) services.AddScoped(_ => new SqlConnection(defaultConnectionString)); // Register services. + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/DigitalLearningSolutions.Web/Styles/trackingSystem/centreRanking.scss b/DigitalLearningSolutions.Web/Styles/trackingSystem/centreRanking.scss index 08caa40990..2d447462da 100644 --- a/DigitalLearningSolutions.Web/Styles/trackingSystem/centreRanking.scss +++ b/DigitalLearningSolutions.Web/Styles/trackingSystem/centreRanking.scss @@ -1,7 +1,13 @@ @import "~nhsuk-frontend/packages/core/all"; +$current-centre-highlight: $color_nhsuk-pale-yellow; + .current-centre { - background-color: $color_nhsuk-grey-3; + background-color: $current-centre-highlight; + + &:hover { + background-color: $current-centre-highlight; + } } .cell-left-padding { diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Dashboard/CentreDashboardViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Dashboard/CentreDashboardViewModel.cs index af4c67c3d7..bf302c6810 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Dashboard/CentreDashboardViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Dashboard/CentreDashboardViewModel.cs @@ -13,10 +13,11 @@ public CentreDashboardViewModel int delegates, int courses, int admins, - int supportTickets + int supportTickets, + int centreRank ) { - CentreDetails = new DashboardCentreDetailsViewModel(centre, userIpAddress); + CentreDetails = new DashboardCentreDetailsViewModel(centre, userIpAddress, centreRank); FirstName = string.IsNullOrWhiteSpace(firstName) ? "User" : firstName; CourseCategory = categoryName ?? "all"; NumberOfDelegates = delegates; diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Dashboard/DashboardCentreDetailsViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Dashboard/DashboardCentreDetailsViewModel.cs index dad8f2da69..43ec900d78 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Dashboard/DashboardCentreDetailsViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Dashboard/DashboardCentreDetailsViewModel.cs @@ -4,7 +4,7 @@ public class DashboardCentreDetailsViewModel { - public DashboardCentreDetailsViewModel(Centre centre, string userIpAddress) + public DashboardCentreDetailsViewModel(Centre centre, string userIpAddress, int centreRank) { CentreName = centre.CentreName; CentreId = centre.CentreId; @@ -16,6 +16,7 @@ public DashboardCentreDetailsViewModel(Centre centre, string userIpAddress) BannerText = centre.BannerText; IpAddress = userIpAddress; ApprovedIps = centre.IpPrefix; + CentreRank = centreRank; } public string CentreName { get; set; } @@ -37,5 +38,7 @@ public DashboardCentreDetailsViewModel(Centre centre, string userIpAddress) public string IpAddress { get; set; } public string? ApprovedIps { get; set; } + + public int CentreRank { get; set; } } } diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankingViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankingViewModel.cs index 21d7541de0..4a6f6d6225 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankingViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankingViewModel.cs @@ -2,31 +2,26 @@ { using System.Collections.Generic; using System.Linq; + using DigitalLearningSolutions.Data.Models.DbModels; public class CentreRankingViewModel { - public CentreRankingViewModel() + public CentreRankingViewModel(IEnumerable centreRanks, int centreId) { - CurrentCentre = new CentreRankViewModel(23, "Test Centre 13", 123); - TopTenCentres = new[] - { - new CentreRankViewModel(1, "Test Centre 1", 9000), - new CentreRankViewModel(2, "Test Centre 2", 8000), - new CentreRankViewModel(3, "Test Centre 3", 7000), - new CentreRankViewModel(4, "Test Centre 4", 6000), - new CentreRankViewModel(5, "Test Centre 5", 5000), - new CentreRankViewModel(6, "Test Centre 6", 4000), - new CentreRankViewModel(7, "Test Centre 7", 3000), - new CentreRankViewModel(8, "Test Centre 8", 2000), - new CentreRankViewModel(9, "Test Centre 9", 1000), - new CentreRankViewModel(10, "Test Centre 10", 500) - }; + var centreRanksList = centreRanks.ToList(); + + CurrentCentre = centreRanksList.Where(cr => cr.CentreId == centreId) + .Select(cr => new CentreRankViewModel(cr.Rank, cr.CentreName, cr.Sum)) + .SingleOrDefault(); + + TopTenCentres = centreRanksList.OrderBy(cr => cr.Rank).Take(10) + .Select(cr => new CentreRankViewModel(cr.Rank, cr.CentreName, cr.Sum)); } public IEnumerable TopTenCentres { get; set; } - public CentreRankViewModel CurrentCentre { get; set; } + public CentreRankViewModel? CurrentCentre { get; set; } - public bool IsCurrentCentreInTopTen => TopTenCentres.Contains(CurrentCentre); + public bool IsCurrentCentreInTopTen => CurrentCentre?.Rank <= 10; } } diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Dashboard/_DashboardCentreDetails.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Dashboard/_DashboardCentreDetails.cshtml index ca1e50ae03..846d91eadf 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Dashboard/_DashboardCentreDetails.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Dashboard/_DashboardCentreDetails.cshtml @@ -12,6 +12,15 @@
+
+
+ Centre ranking +
+
+ @(Model.CentreDetails.CentreRank != -1 ? Model.CentreDetails.CentreRank.ToString() : "No activity") +
+
+
Centre name diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingStandardUserTable.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingStandardUserTable.cshtml index 73a632100f..f9605bd17b 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingStandardUserTable.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingStandardUserTable.cshtml @@ -14,16 +14,22 @@ @foreach (var centre in Model.TopTenCentres) { - + @centre.Rank @centre.CentreName } - @if (!Model.IsCurrentCentreInTopTen) { + @if (!Model.IsCurrentCentreInTopTen && Model.CurrentCentre != null) { @Model.CurrentCentre.Rank @Model.CurrentCentre.CentreName } + @if (Model.CurrentCentre == null) { + + + Your centre overall rank: no activity + + } diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingSuperAdminTable.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingSuperAdminTable.cshtml index a964ae0552..eb400bca45 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingSuperAdminTable.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingSuperAdminTable.cshtml @@ -17,7 +17,7 @@ @foreach (var centre in Model.TopTenCentres) { - + Rank @centre.Rank @@ -29,7 +29,7 @@ } - @if (!Model.IsCurrentCentreInTopTen) { + @if (!Model.IsCurrentCentreInTopTen && Model.CurrentCentre != null) { Rank @Model.CurrentCentre.Rank @@ -42,5 +42,14 @@ } + @if (Model.CurrentCentre == null) { + + + + Your centre overall rank: no activity + + + + } From c8e201e483ef934c170a86246aff3a50bd765555 Mon Sep 17 00:00:00 2001 From: Alex Jackson Date: Wed, 23 Jun 2021 12:04:11 +0100 Subject: [PATCH 3/5] HEEDLS-468 Review markups --- .../Services/CentresServiceTests.cs | 6 +++--- .../DataServices/CentresDataService.cs | 14 +++++++------- .../Services/CentresService.cs | 4 ++-- .../Centre/Ranking/RankingController.cs | 2 +- .../Helpers/CustomClaimHelper.cs | 5 ++--- .../Helpers/CustomPolicies.cs | 3 +-- .../TrackingSystem/Shared/_NavMenuItems.cshtml | 2 +- 7 files changed, 17 insertions(+), 19 deletions(-) diff --git a/DigitalLearningSolutions.Data.Tests/Services/CentresServiceTests.cs b/DigitalLearningSolutions.Data.Tests/Services/CentresServiceTests.cs index 8454481812..c2514e6a2c 100644 --- a/DigitalLearningSolutions.Data.Tests/Services/CentresServiceTests.cs +++ b/DigitalLearningSolutions.Data.Tests/Services/CentresServiceTests.cs @@ -43,7 +43,7 @@ public void Setup() public void GetCentreRanks_returns_expected_list_when_centre_in_top_ten() { // When - var result = centresService.GetCentreRanks(3, 14, -1); + var result = centresService.GetTopCentreRanks(3, 14, -1); // Then result.Count().Should().Be(10); @@ -53,7 +53,7 @@ public void GetCentreRanks_returns_expected_list_when_centre_in_top_ten() public void GetCentreRanks_returns_expected_list_when_centre_is_not_in_top_ten() { // When - var result = centresService.GetCentreRanks(12, 14, -1); + var result = centresService.GetTopCentreRanks(12, 14, -1); // Then result.Count().Should().Be(11); @@ -63,7 +63,7 @@ public void GetCentreRanks_returns_expected_list_when_centre_is_not_in_top_ten() public void GetCentreRanks_returns_expected_list_when_centre_has_no_data() { // When - var result = centresService.GetCentreRanks(20, 14, -1); + var result = centresService.GetTopCentreRanks(20, 14, -1); // Then result.Count().Should().Be(10); diff --git a/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs b/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs index 9b88c06c72..7af9433437 100644 --- a/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs @@ -126,7 +126,7 @@ ORDER BY CentreName" ct.ContractType FROM Centres AS c INNER JOIN Regions AS r ON r.RegionID = c.RegionID - INNER JOIN ContractTypes as ct on ct.ContractTypeID = c.ContractTypeId + INNER JOIN ContractTypes AS ct ON ct.ContractTypeID = c.ContractTypeId WHERE CentreID = @centreId", new { centreId } ); @@ -233,21 +233,21 @@ public IEnumerable GetCentreRanks(DateTime dateSince, int regionId) { return connection.Query( @"SELECT - RANK() over (ORDER BY tc.CentreIDCount DESC) as [Rank], + RANK() OVER (ORDER BY tc.CentreIDCount DESC) AS [Rank], c.CentreID, c.CentreName, - tc.CentreIDCount as [Sum] + tc.CentreIDCount AS [Sum] FROM ( SELECT - Count(c.CentreID) as CentreIDCount, + Count(c.CentreID) AS CentreIDCount, c.CentreID FROM [Sessions] s - INNER JOIN Candidates c on s.CandidateID = c.CandidateID - INNER JOIN Centres ct on c.CentreID = ct.CentreID + INNER JOIN Candidates c ON s.CandidateID = c.CandidateID + INNER JOIN Centres ct ON c.CentreID = ct.CentreID WHERE s.LoginTime > @dateSince AND c.CentreID <> 101 AND (ct.RegionID = @RegionID OR @RegionID = -1) GROUP BY c.CentreID - ) as tc + ) AS tc INNER JOIN Centres c ON tc.CentreID = c.CentreID", new { dateSince, regionId } ); diff --git a/DigitalLearningSolutions.Data/Services/CentresService.cs b/DigitalLearningSolutions.Data/Services/CentresService.cs index 9da9862ebd..d5c63ddffa 100644 --- a/DigitalLearningSolutions.Data/Services/CentresService.cs +++ b/DigitalLearningSolutions.Data/Services/CentresService.cs @@ -8,7 +8,7 @@ public interface ICentresService { - IEnumerable GetCentreRanks(int centreId, int numberOfDays, int regionId); + IEnumerable GetTopCentreRanks(int centreId, int numberOfDays, int regionId); int GetCentreRankForCentre(int centreId); } @@ -22,7 +22,7 @@ public CentresService(ICentresDataService centresDataService) this.centresDataService = centresDataService; } - public IEnumerable GetCentreRanks(int centreId, int numberOfDays, int regionId) + public IEnumerable GetTopCentreRanks(int centreId, int numberOfDays, int regionId) { var dateSince = DateTime.UtcNow.AddDays(-numberOfDays); diff --git a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Ranking/RankingController.cs b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Ranking/RankingController.cs index 32382e60c4..40206668b7 100644 --- a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Ranking/RankingController.cs +++ b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Ranking/RankingController.cs @@ -20,7 +20,7 @@ public RankingController(ICentresService centresService) public IActionResult Index() { // TODO: HEEDLS-469 Populate these numbers from filters - var centreRankings = centresService.GetCentreRanks(User.GetCentreId(), 14, -1); + var centreRankings = centresService.GetTopCentreRanks(User.GetCentreId(), 14, -1); return View(new CentreRankingViewModel(centreRankings, User.GetCentreId())); } diff --git a/DigitalLearningSolutions.Web/Helpers/CustomClaimHelper.cs b/DigitalLearningSolutions.Web/Helpers/CustomClaimHelper.cs index f359f122cf..0331a46fe3 100644 --- a/DigitalLearningSolutions.Web/Helpers/CustomClaimHelper.cs +++ b/DigitalLearningSolutions.Web/Helpers/CustomClaimHelper.cs @@ -77,14 +77,13 @@ public static bool IsDelegateOnlyAccount(this ClaimsPrincipal user) public static bool HasCentreAdminPermissions(this ClaimsPrincipal user) { return (user.GetCustomClaimAsBool(CustomClaimTypes.UserCentreAdmin) ?? false) || - (user.GetCustomClaimAsBool(CustomClaimTypes.UserCentreManager) ?? false) || - (user.GetCustomClaimAsBool(CustomClaimTypes.UserUserAdmin) ?? false); + user.HasCentreManagerPermissions(); } public static bool HasCentreManagerPermissions(this ClaimsPrincipal user) { return (user.GetCustomClaimAsBool(CustomClaimTypes.UserCentreManager) ?? false) || - (user.GetCustomClaimAsBool(CustomClaimTypes.UserUserAdmin) ?? false); + user.HasSuperAdminPermissions(); } public static bool HasSuperAdminPermissions(this ClaimsPrincipal user) diff --git a/DigitalLearningSolutions.Web/Helpers/CustomPolicies.cs b/DigitalLearningSolutions.Web/Helpers/CustomPolicies.cs index 40e23aed80..50da249cc9 100644 --- a/DigitalLearningSolutions.Web/Helpers/CustomPolicies.cs +++ b/DigitalLearningSolutions.Web/Helpers/CustomPolicies.cs @@ -42,8 +42,7 @@ AuthorizationPolicyBuilder policy { return policy.RequireAssertion( context => context.User.GetCustomClaimAsInt(CustomClaimTypes.UserAdminId) != null && - (context.User.GetCustomClaimAsBool(CustomClaimTypes.UserCentreManager) == true || - context.User.GetCustomClaimAsBool(CustomClaimTypes.UserUserAdmin) == true) + context.User.HasCentreManagerPermissions() ); } } diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Shared/_NavMenuItems.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Shared/_NavMenuItems.cshtml index b6f4efbc9e..71d59000ef 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Shared/_NavMenuItems.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Shared/_NavMenuItems.cshtml @@ -22,7 +22,7 @@ } -@if (User.GetCustomClaimAsBool(CustomClaimTypes.UserUserAdmin) ?? false) { +@if (User.HasSuperAdminPermissions()) {
  • Admin From 2e7249853fe07ffa45c267c45b38fca3165e577c Mon Sep 17 00:00:00 2001 From: Alex Jackson Date: Mon, 28 Jun 2021 10:51:11 +0100 Subject: [PATCH 4/5] HEEDLS-468 Review markups --- .../Services/CentresServiceTests.cs | 59 +++++++------------ .../TestHelpers/CentreTestHelper.cs | 8 +-- .../DataServices/CentresDataService.cs | 48 ++++++++++----- .../{CentreRank.cs => CentreRanking.cs} | 6 +- .../Services/CentresService.cs | 37 +++++------- .../Centre/CentreRankingViewModelTests.cs | 22 +++---- .../DashboardCentreDetailsViewModelTests.cs | 2 +- .../{ => Dashboard}/DashboardController.cs | 4 +- .../RankingController.cs | 7 ++- .../Dashboard/CentreDashboardViewModel.cs | 2 +- .../DashboardCentreDetailsViewModel.cs | 6 +- .../Centre/Ranking/CentreRankViewModel.cs | 5 +- .../Centre/Ranking/CentreRankingViewModel.cs | 23 ++++---- .../Dashboard/_DashboardCentreDetails.cshtml | 2 +- .../Centre/Ranking/Index.cshtml | 19 ++---- .../Ranking/_RankingStandardUserTable.cshtml | 18 +----- .../Ranking/_RankingSuperAdminTable.cshtml | 26 +------- .../Shared/_CentreDashboardBreadcrumbs.cshtml | 12 ++++ 18 files changed, 135 insertions(+), 171 deletions(-) rename DigitalLearningSolutions.Data/Models/DbModels/{CentreRank.cs => CentreRanking.cs} (54%) rename DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/{ => Dashboard}/DashboardController.cs (96%) rename DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/{Ranking => Dashboard}/RankingController.cs (80%) create mode 100644 DigitalLearningSolutions.Web/Views/TrackingSystem/Shared/_CentreDashboardBreadcrumbs.cshtml diff --git a/DigitalLearningSolutions.Data.Tests/Services/CentresServiceTests.cs b/DigitalLearningSolutions.Data.Tests/Services/CentresServiceTests.cs index c2514e6a2c..8a2733dc22 100644 --- a/DigitalLearningSolutions.Data.Tests/Services/CentresServiceTests.cs +++ b/DigitalLearningSolutions.Data.Tests/Services/CentresServiceTests.cs @@ -12,58 +12,39 @@ public class CentresServiceTests { private ICentresDataService centresDataService = null!; + private IClockService clockService = null!; private ICentresService centresService = null!; [SetUp] public void Setup() { centresDataService = A.Fake(); - centresService = new CentresService(centresDataService); + clockService = A.Fake(); + centresService = new CentresService(centresDataService, clockService); - A.CallTo(() => centresDataService.GetCentreRanks(A._, A._)).Returns( + A.CallTo(() => clockService.UtcNow).Returns(new DateTime(2021, 1, 1)); + A.CallTo(() => centresDataService.GetCentreRanks(A._, A._, 10, A._)).Returns( new[] - { - CentreTestHelper.GetCentreRank(1), - CentreTestHelper.GetCentreRank(2), - CentreTestHelper.GetCentreRank(3), - CentreTestHelper.GetCentreRank(4), - CentreTestHelper.GetCentreRank(5), - CentreTestHelper.GetCentreRank(6), - CentreTestHelper.GetCentreRank(7), - CentreTestHelper.GetCentreRank(8), - CentreTestHelper.GetCentreRank(9), - CentreTestHelper.GetCentreRank(10), - CentreTestHelper.GetCentreRank(11), - CentreTestHelper.GetCentreRank(12) - } + { + CentreTestHelper.GetCentreRank(1), + CentreTestHelper.GetCentreRank(2), + CentreTestHelper.GetCentreRank(3), + CentreTestHelper.GetCentreRank(4), + CentreTestHelper.GetCentreRank(5), + CentreTestHelper.GetCentreRank(6), + CentreTestHelper.GetCentreRank(7), + CentreTestHelper.GetCentreRank(8), + CentreTestHelper.GetCentreRank(9), + CentreTestHelper.GetCentreRank(10) + } ); } [Test] - public void GetCentreRanks_returns_expected_list_when_centre_in_top_ten() + public void GetCentreRanks_returns_expected_list() { // When - var result = centresService.GetTopCentreRanks(3, 14, -1); - - // Then - result.Count().Should().Be(10); - } - - [Test] - public void GetCentreRanks_returns_expected_list_when_centre_is_not_in_top_ten() - { - // When - var result = centresService.GetTopCentreRanks(12, 14, -1); - - // Then - result.Count().Should().Be(11); - } - - [Test] - public void GetCentreRanks_returns_expected_list_when_centre_has_no_data() - { - // When - var result = centresService.GetTopCentreRanks(20, 14, -1); + var result = centresService.GetCentresForCentreRankingPage(3, 14, -1); // Then result.Count().Should().Be(10); @@ -86,7 +67,7 @@ public void GetCentreRankForCentre_returns_negative_one_with_no_data_for_centre( var result = centresService.GetCentreRankForCentre(20); // Then - result.Should().Be(-1); + result.Should().BeNull(); } } } diff --git a/DigitalLearningSolutions.Data.Tests/TestHelpers/CentreTestHelper.cs b/DigitalLearningSolutions.Data.Tests/TestHelpers/CentreTestHelper.cs index 8ede357d5a..1427f64216 100644 --- a/DigitalLearningSolutions.Data.Tests/TestHelpers/CentreTestHelper.cs +++ b/DigitalLearningSolutions.Data.Tests/TestHelpers/CentreTestHelper.cs @@ -68,14 +68,14 @@ public static Centre GetDefaultCentre }; } - public static CentreRank GetCentreRank(int rank) + public static CentreRanking GetCentreRank(int rank) { - return new CentreRank + return new CentreRanking { CentreId = rank, - Rank = rank, + Ranking = rank, CentreName = $"Centre {rank}", - Sum = 10000-rank*10 + DelegateSessionCount = 10000-rank*10 }; } } diff --git a/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs b/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs index 7af9433437..ee5a6940ad 100644 --- a/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/CentresDataService.cs @@ -39,7 +39,7 @@ void UpdateCentreWebsiteDetails( (string firstName, string lastName, string email) GetCentreManagerDetails(int centreId); string[] GetCentreIpPrefixes(int centreId); - IEnumerable GetCentreRanks(DateTime dateSince, int regionId); + IEnumerable GetCentreRanks(DateTime dateSince, int? regionId, int resultsCount, int centreId); } public class CentresDataService : ICentresDataService @@ -229,27 +229,43 @@ FROM Centres return ipPrefixes ?? new string[0]; } - public IEnumerable GetCentreRanks(DateTime dateSince, int regionId) + public IEnumerable GetCentreRanks( + DateTime dateSince, + int? regionId, + int resultsCount, + int centreId + ) { - return connection.Query( - @"SELECT - RANK() OVER (ORDER BY tc.CentreIDCount DESC) AS [Rank], - c.CentreID, - c.CentreName, - tc.CentreIDCount AS [Sum] - FROM - ( + return connection.Query( + @"WITH SessionsCount AS + ( SELECT - Count(c.CentreID) AS CentreIDCount, - c.CentreID + Count(c.CentreID) AS DelegateSessionCount, + c.CentreID FROM [Sessions] s INNER JOIN Candidates c ON s.CandidateID = c.CandidateID INNER JOIN Centres ct ON c.CentreID = ct.CentreID - WHERE s.LoginTime > @dateSince AND c.CentreID <> 101 AND (ct.RegionID = @RegionID OR @RegionID = -1) + WHERE + s.LoginTime > @dateSince + AND c.CentreID <> 101 AND c.CentreID <> 374 + AND (ct.RegionID = @RegionID OR @RegionID IS NULL) GROUP BY c.CentreID - ) AS tc - INNER JOIN Centres c ON tc.CentreID = c.CentreID", - new { dateSince, regionId } + ), + Rankings AS + ( + SELECT + RANK() OVER (ORDER BY sc.DelegateSessionCount DESC) AS Ranking, + c.CentreID, + c.CentreName, + sc.DelegateSessionCount + FROM SessionsCount sc + INNER JOIN Centres c ON sc.CentreID = c.CentreID + ) + SELECT * + FROM Rankings + WHERE Ranking <= @resultsCount OR CentreID = @centreId + ORDER BY Ranking", + new { dateSince, regionId, resultsCount, centreId } ); } } diff --git a/DigitalLearningSolutions.Data/Models/DbModels/CentreRank.cs b/DigitalLearningSolutions.Data/Models/DbModels/CentreRanking.cs similarity index 54% rename from DigitalLearningSolutions.Data/Models/DbModels/CentreRank.cs rename to DigitalLearningSolutions.Data/Models/DbModels/CentreRanking.cs index 3622760693..22825569db 100644 --- a/DigitalLearningSolutions.Data/Models/DbModels/CentreRank.cs +++ b/DigitalLearningSolutions.Data/Models/DbModels/CentreRanking.cs @@ -1,13 +1,13 @@ namespace DigitalLearningSolutions.Data.Models.DbModels { - public class CentreRank + public class CentreRanking { public int CentreId { get; set; } - public int Rank { get; set; } + public int Ranking { get; set; } public string CentreName { get; set; } - public int Sum { get; set; } + public int DelegateSessionCount { get; set; } } } diff --git a/DigitalLearningSolutions.Data/Services/CentresService.cs b/DigitalLearningSolutions.Data/Services/CentresService.cs index d5c63ddffa..b6ec4d4560 100644 --- a/DigitalLearningSolutions.Data/Services/CentresService.cs +++ b/DigitalLearningSolutions.Data/Services/CentresService.cs @@ -1,6 +1,5 @@ namespace DigitalLearningSolutions.Data.Services { - using System; using System.Collections.Generic; using System.Linq; using DigitalLearningSolutions.Data.DataServices; @@ -8,43 +7,37 @@ public interface ICentresService { - IEnumerable GetTopCentreRanks(int centreId, int numberOfDays, int regionId); + IEnumerable GetCentresForCentreRankingPage(int centreId, int numberOfDays, int? regionId); - int GetCentreRankForCentre(int centreId); + int? GetCentreRankForCentre(int centreId); } public class CentresService : ICentresService { + private const int NumberOfCentresToDisplay = 10; + private const int DefaultNumberOfDaysFilter = 14; private readonly ICentresDataService centresDataService; + private readonly IClockService clockService; - public CentresService(ICentresDataService centresDataService) + public CentresService(ICentresDataService centresDataService, IClockService clockService) { this.centresDataService = centresDataService; + this.clockService = clockService; } - public IEnumerable GetTopCentreRanks(int centreId, int numberOfDays, int regionId) + public IEnumerable GetCentresForCentreRankingPage(int centreId, int numberOfDays, int? regionId) { - var dateSince = DateTime.UtcNow.AddDays(-numberOfDays); + var dateSince = clockService.UtcNow.AddDays(-numberOfDays); - var centreRanks = centresDataService.GetCentreRanks(dateSince, regionId).OrderBy(cr => cr.Rank).ToList(); - - var topTenCentres = centreRanks.Take(10).ToList(); - - var currentCentreRank = centreRanks.SingleOrDefault(cr => cr.CentreId == centreId); - - if (currentCentreRank == null) - { - return topTenCentres; - } - - return topTenCentres.Contains(currentCentreRank) ? topTenCentres : topTenCentres.Append(currentCentreRank); + return centresDataService.GetCentreRanks(dateSince, regionId, NumberOfCentresToDisplay, centreId).ToList(); } - public int GetCentreRankForCentre(int centreId) + public int? GetCentreRankForCentre(int centreId) { - var centreRanks = centresDataService.GetCentreRanks(DateTime.UtcNow.AddDays(-14), -1); - var centreRank = centreRanks.SingleOrDefault(cr => cr.CentreId == centreId); - return centreRank?.Rank ?? -1; + var dateSince = clockService.UtcNow.AddDays(-DefaultNumberOfDaysFilter); + var centreRankings = centresDataService.GetCentreRanks(dateSince, null, NumberOfCentresToDisplay, centreId); + var centreRanking = centreRankings.SingleOrDefault(cr => cr.CentreId == centreId); + return centreRanking?.Ranking; } } } diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/CentreRankingViewModelTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/CentreRankingViewModelTests.cs index 248309f23c..c88948374a 100644 --- a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/CentreRankingViewModelTests.cs +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/CentreRankingViewModelTests.cs @@ -10,7 +10,7 @@ public class CentreRankingViewModelTests { - private readonly CentreRank[] centreRankings = + private readonly CentreRanking[] centreRankings = { CentreTestHelper.GetCentreRank(1), CentreTestHelper.GetCentreRank(2), @@ -33,9 +33,8 @@ public void CentreRankingViewModelViewModel_populates_expected_values_from_centr // Then using (new AssertionScope()) { - result.TopTenCentres.Count().Should().Be(10); - result.CurrentCentre!.Rank.Should().Be(3); - result.IsCurrentCentreInTopTen.Should().BeTrue(); + result.Centres.Count().Should().Be(10); + result.CentreHasNoActivity.Should().BeFalse(); } } @@ -52,9 +51,8 @@ public void // Then using (new AssertionScope()) { - result.TopTenCentres.Count().Should().Be(10); - result.CurrentCentre!.Rank.Should().Be(20); - result.IsCurrentCentreInTopTen.Should().BeFalse(); + result.Centres.Count().Should().Be(11); + result.CentreHasNoActivity.Should().BeFalse(); } } @@ -68,9 +66,8 @@ public void // Then using (new AssertionScope()) { - result.TopTenCentres.Count().Should().Be(10); - result.CurrentCentre.Should().BeNull(); - result.IsCurrentCentreInTopTen.Should().BeFalse(); + result.Centres.Count().Should().Be(10); + result.CentreHasNoActivity.Should().BeTrue(); } } @@ -86,9 +83,8 @@ public void CentreRankingViewModelViewModel_populates_expected_values_from_centr // Then using (new AssertionScope()) { - result.TopTenCentres.Count().Should().Be(5); - result.CurrentCentre.Should().BeNull(); - result.IsCurrentCentreInTopTen.Should().BeFalse(); + result.Centres.Count().Should().Be(5); + result.CentreHasNoActivity.Should().BeTrue(); } } } diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/DashboardCentreDetailsViewModelTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/DashboardCentreDetailsViewModelTests.cs index 95b92bb8c4..3ff17911c1 100644 --- a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/DashboardCentreDetailsViewModelTests.cs +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/DashboardCentreDetailsViewModelTests.cs @@ -29,7 +29,7 @@ public void DashboardCentreDetailsViewModel_populates_expected_values_from_centr viewModel.ApprovedIps.Should().BeEquivalentTo(centre.IpPrefix); viewModel.Telephone.Should().BeEquivalentTo(centre.ContactTelephone); viewModel.Email.Should().BeEquivalentTo(centre.ContactEmail); - viewModel.CentreRank.Should().Be(12); + viewModel.CentreRank.Should().Be("12"); } } } diff --git a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/DashboardController.cs b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Dashboard/DashboardController.cs similarity index 96% rename from DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/DashboardController.cs rename to DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Dashboard/DashboardController.cs index f35e684844..ae144c96ba 100644 --- a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/DashboardController.cs +++ b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Dashboard/DashboardController.cs @@ -1,4 +1,4 @@ -namespace DigitalLearningSolutions.Web.Controllers.TrackingSystem.Centre +namespace DigitalLearningSolutions.Web.Controllers.TrackingSystem.Centre.Dashboard { using DigitalLearningSolutions.Data.DataServices; using DigitalLearningSolutions.Data.Services; @@ -41,7 +41,7 @@ public IActionResult Index() var courseCount = courseService.GetNumberOfActiveCoursesAtCentreForCategory(centreId, adminUser.CategoryId); var adminCount = userDataService.GetNumberOfActiveAdminsAtCentre(centreId); var supportTicketCount = ticketDataService.GetNumberOfUnarchivedTicketsForCentreId(centreId); - var centreRank = centresService.GetCentreRankForCentre(User.GetCentreId()); + var centreRank = centresService.GetCentreRankForCentre(centreId); var model = new CentreDashboardViewModel( centre, diff --git a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Ranking/RankingController.cs b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Dashboard/RankingController.cs similarity index 80% rename from DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Ranking/RankingController.cs rename to DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Dashboard/RankingController.cs index 40206668b7..de094bdae0 100644 --- a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Ranking/RankingController.cs +++ b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Centre/Dashboard/RankingController.cs @@ -1,4 +1,4 @@ -namespace DigitalLearningSolutions.Web.Controllers.TrackingSystem.Centre.Ranking +namespace DigitalLearningSolutions.Web.Controllers.TrackingSystem.Centre.Dashboard { using DigitalLearningSolutions.Data.Services; using DigitalLearningSolutions.Web.Helpers; @@ -19,10 +19,11 @@ public RankingController(ICentresService centresService) public IActionResult Index() { + var centreId = User.GetCentreId(); // TODO: HEEDLS-469 Populate these numbers from filters - var centreRankings = centresService.GetTopCentreRanks(User.GetCentreId(), 14, -1); + var centreRankings = centresService.GetCentresForCentreRankingPage(centreId, 14, null); - return View(new CentreRankingViewModel(centreRankings, User.GetCentreId())); + return View(new CentreRankingViewModel(centreRankings, centreId)); } } } diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Dashboard/CentreDashboardViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Dashboard/CentreDashboardViewModel.cs index bf302c6810..6409a0d516 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Dashboard/CentreDashboardViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Dashboard/CentreDashboardViewModel.cs @@ -14,7 +14,7 @@ public CentreDashboardViewModel int courses, int admins, int supportTickets, - int centreRank + int? centreRank ) { CentreDetails = new DashboardCentreDetailsViewModel(centre, userIpAddress, centreRank); diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Dashboard/DashboardCentreDetailsViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Dashboard/DashboardCentreDetailsViewModel.cs index 43ec900d78..8962d8e055 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Dashboard/DashboardCentreDetailsViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Dashboard/DashboardCentreDetailsViewModel.cs @@ -4,7 +4,7 @@ public class DashboardCentreDetailsViewModel { - public DashboardCentreDetailsViewModel(Centre centre, string userIpAddress, int centreRank) + public DashboardCentreDetailsViewModel(Centre centre, string userIpAddress, int? centreRank) { CentreName = centre.CentreName; CentreId = centre.CentreId; @@ -16,7 +16,7 @@ public DashboardCentreDetailsViewModel(Centre centre, string userIpAddress, int BannerText = centre.BannerText; IpAddress = userIpAddress; ApprovedIps = centre.IpPrefix; - CentreRank = centreRank; + CentreRank = centreRank?.ToString() ?? "No activity"; } public string CentreName { get; set; } @@ -39,6 +39,6 @@ public DashboardCentreDetailsViewModel(Centre centre, string userIpAddress, int public string? ApprovedIps { get; set; } - public int CentreRank { get; set; } + public string CentreRank { get; set; } } } diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankViewModel.cs index 486ff94e30..159ed89931 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankViewModel.cs @@ -2,11 +2,12 @@ { public class CentreRankViewModel { - public CentreRankViewModel(int rank, string centreName, int sum) + public CentreRankViewModel(int rank, string centreName, int sum,bool isHighlighted) { Rank = rank; CentreName = centreName; Sum = sum; + IsHighlighted = isHighlighted; } public int Rank { get; set; } @@ -14,5 +15,7 @@ public CentreRankViewModel(int rank, string centreName, int sum) public string CentreName { get; set; } public int Sum { get; set; } + + public bool IsHighlighted { get; set; } } } diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankingViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankingViewModel.cs index 4a6f6d6225..8ee9d21b0d 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankingViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankingViewModel.cs @@ -6,22 +6,25 @@ public class CentreRankingViewModel { - public CentreRankingViewModel(IEnumerable centreRanks, int centreId) + public CentreRankingViewModel(IEnumerable centreRanks, int centreId) { var centreRanksList = centreRanks.ToList(); - CurrentCentre = centreRanksList.Where(cr => cr.CentreId == centreId) - .Select(cr => new CentreRankViewModel(cr.Rank, cr.CentreName, cr.Sum)) - .SingleOrDefault(); + Centres = centreRanksList.OrderBy(cr => cr.Ranking) + .Select( + cr => new CentreRankViewModel( + cr.Ranking, + cr.CentreName, + cr.DelegateSessionCount, + cr.CentreId == centreId + ) + ); - TopTenCentres = centreRanksList.OrderBy(cr => cr.Rank).Take(10) - .Select(cr => new CentreRankViewModel(cr.Rank, cr.CentreName, cr.Sum)); + CentreHasNoActivity = centreRanksList.All(cr => cr.CentreId != centreId); } - public IEnumerable TopTenCentres { get; set; } + public IEnumerable Centres { get; set; } - public CentreRankViewModel? CurrentCentre { get; set; } - - public bool IsCurrentCentreInTopTen => CurrentCentre?.Rank <= 10; + public bool CentreHasNoActivity { get; set; } } } diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Dashboard/_DashboardCentreDetails.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Dashboard/_DashboardCentreDetails.cshtml index 846d91eadf..f193f650bc 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Dashboard/_DashboardCentreDetails.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Dashboard/_DashboardCentreDetails.cshtml @@ -17,7 +17,7 @@ Centre ranking
  • - @(Model.CentreDetails.CentreRank != -1 ? Model.CentreDetails.CentreRank.ToString() : "No activity") + @Model.CentreDetails.CentreRank
    diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/Index.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/Index.cshtml index 040c18ce81..7bd08113ca 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/Index.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/Index.cshtml @@ -19,23 +19,12 @@ } @section NavBreadcrumbs { - + }
    -

    Centre ranking

    +

    Centre ranking

    The top ten Digital Learning Solutions centres by learner course launches.

    @@ -44,5 +33,9 @@ } else { } + + @if (Model.CentreHasNoActivity) { +

    Your centre overall rank: no activity

    + }
    diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingStandardUserTable.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingStandardUserTable.cshtml index f9605bd17b..bac2dd9427 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingStandardUserTable.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingStandardUserTable.cshtml @@ -7,29 +7,17 @@ Rank - + Centre - @foreach (var centre in Model.TopTenCentres) { - + @foreach (var centre in Model.Centres) { + @centre.Rank @centre.CentreName } - @if (!Model.IsCurrentCentreInTopTen && Model.CurrentCentre != null) { - - @Model.CurrentCentre.Rank - @Model.CurrentCentre.CentreName - - } - @if (Model.CurrentCentre == null) { - - - Your centre overall rank: no activity - - } diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingSuperAdminTable.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingSuperAdminTable.cshtml index eb400bca45..b53ef13863 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingSuperAdminTable.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingSuperAdminTable.cshtml @@ -16,8 +16,8 @@ - @foreach (var centre in Model.TopTenCentres) { - + @foreach (var centre in Model.Centres) { + Rank @centre.Rank @@ -29,27 +29,5 @@ } - @if (!Model.IsCurrentCentreInTopTen && Model.CurrentCentre != null) { - - - Rank @Model.CurrentCentre.Rank - - - Centre @Model.CurrentCentre.CentreName - - - Sum @Model.CurrentCentre.Sum - - - } - @if (Model.CurrentCentre == null) { - - - - Your centre overall rank: no activity - - - - } diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Shared/_CentreDashboardBreadcrumbs.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Shared/_CentreDashboardBreadcrumbs.cshtml new file mode 100644 index 0000000000..71ac9e063d --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Shared/_CentreDashboardBreadcrumbs.cshtml @@ -0,0 +1,12 @@ + From ee0dd9ae400fe7e84653ce633b593883f2a6aac6 Mon Sep 17 00:00:00 2001 From: Alex Jackson Date: Mon, 28 Jun 2021 13:34:12 +0100 Subject: [PATCH 5/5] HEEDLS-468 Review markups --- .../Services/CentresServiceTests.cs | 4 +-- .../Centre/CentreRankingViewModelTests.cs | 8 +++--- .../DashboardCentreDetailsViewModelTests.cs | 25 +++++++++++++++++++ .../Styles/trackingSystem/centreRanking.scss | 4 --- .../Centre/Ranking/CentreRankViewModel.cs | 2 +- .../Centre/Ranking/Index.cshtml | 2 +- .../Ranking/_RankingStandardUserTable.cshtml | 4 +-- .../Ranking/_RankingSuperAdminTable.cshtml | 12 ++++----- 8 files changed, 41 insertions(+), 20 deletions(-) diff --git a/DigitalLearningSolutions.Data.Tests/Services/CentresServiceTests.cs b/DigitalLearningSolutions.Data.Tests/Services/CentresServiceTests.cs index 8a2733dc22..42a2cf381e 100644 --- a/DigitalLearningSolutions.Data.Tests/Services/CentresServiceTests.cs +++ b/DigitalLearningSolutions.Data.Tests/Services/CentresServiceTests.cs @@ -44,7 +44,7 @@ public void Setup() public void GetCentreRanks_returns_expected_list() { // When - var result = centresService.GetCentresForCentreRankingPage(3, 14, -1); + var result = centresService.GetCentresForCentreRankingPage(3, 14, null); // Then result.Count().Should().Be(10); @@ -61,7 +61,7 @@ public void GetCentreRankForCentre_returns_expected_value() } [Test] - public void GetCentreRankForCentre_returns_negative_one_with_no_data_for_centre() + public void GetCentreRankForCentre_returns_null_with_no_data_for_centre() { // When var result = centresService.GetCentreRankForCentre(20); diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/CentreRankingViewModelTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/CentreRankingViewModelTests.cs index c88948374a..95437af2c4 100644 --- a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/CentreRankingViewModelTests.cs +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/CentreRankingViewModelTests.cs @@ -25,7 +25,7 @@ public class CentreRankingViewModelTests }; [Test] - public void CentreRankingViewModelViewModel_populates_expected_values_from_centre_ranks_with_centre_in_top_ten() + public void CentreRankingViewModel_populates_expected_values_from_centre_ranks_with_centre_in_top_ten() { // When var result = new CentreRankingViewModel(centreRankings, 3); @@ -40,7 +40,7 @@ public void CentreRankingViewModelViewModel_populates_expected_values_from_centr [Test] public void - CentreRankingViewModelViewModel_populates_expected_values_from_centre_ranks_with_centre_not_in_top_ten() + CentreRankingViewModel_populates_expected_values_from_centre_ranks_with_centre_not_in_top_ten() { // Given var centreRankingsWithExtraCentre = centreRankings.Append(CentreTestHelper.GetCentreRank(20)); @@ -58,7 +58,7 @@ public void [Test] public void - CentreRankingViewModelViewModel_populates_expected_values_from_centre_ranks_when_centre_has_no_data() + CentreRankingViewModel_populates_expected_values_from_centre_ranks_when_centre_has_no_data() { // When var result = new CentreRankingViewModel(centreRankings, 20); @@ -72,7 +72,7 @@ public void } [Test] - public void CentreRankingViewModelViewModel_populates_expected_values_from_centre_ranks_with_less_data() + public void CentreRankingViewModel_populates_expected_values_from_centre_ranks_with_less_data() { // Given var shortedCentreRankings = centreRankings.Take(5); diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/DashboardCentreDetailsViewModelTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/DashboardCentreDetailsViewModelTests.cs index 3ff17911c1..7aaf2f249c 100644 --- a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/DashboardCentreDetailsViewModelTests.cs +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Centre/DashboardCentreDetailsViewModelTests.cs @@ -32,5 +32,30 @@ public void DashboardCentreDetailsViewModel_populates_expected_values_from_centr viewModel.CentreRank.Should().Be("12"); } } + + [Test] + public void DashboardCentreDetailsViewModel_populates_expected_values_from_centre_with_null_centre_rank() + { + const string userIp = "1.1.1.1"; + var centre = + CentreTestHelper.GetDefaultCentre(); + var viewModel = new DashboardCentreDetailsViewModel(centre, userIp, null); + + // Then + using (new AssertionScope()) + { + viewModel.CentreId.Should().Be(centre.CentreId); + viewModel.CentreName.Should().BeEquivalentTo(centre.CentreName); + viewModel.Region.Should().BeEquivalentTo(centre.RegionName); + viewModel.ContractType.Should().BeEquivalentTo(centre.ContractType); + viewModel.BannerText.Should().BeEquivalentTo(centre.BannerText); + viewModel.CentreManager.Should().BeEquivalentTo("xxxxx xxxx"); + viewModel.IpAddress.Should().BeEquivalentTo(userIp); + viewModel.ApprovedIps.Should().BeEquivalentTo(centre.IpPrefix); + viewModel.Telephone.Should().BeEquivalentTo(centre.ContactTelephone); + viewModel.Email.Should().BeEquivalentTo(centre.ContactEmail); + viewModel.CentreRank.Should().Be("No activity"); + } + } } } diff --git a/DigitalLearningSolutions.Web/Styles/trackingSystem/centreRanking.scss b/DigitalLearningSolutions.Web/Styles/trackingSystem/centreRanking.scss index 2d447462da..6cf96b8297 100644 --- a/DigitalLearningSolutions.Web/Styles/trackingSystem/centreRanking.scss +++ b/DigitalLearningSolutions.Web/Styles/trackingSystem/centreRanking.scss @@ -10,10 +10,6 @@ $current-centre-highlight: $color_nhsuk-pale-yellow; } } -.cell-left-padding { - padding-left: nhsuk-spacing(2); -} - .cell-right-padding { @include govuk-media-query($until: desktop) { padding-right: nhsuk-spacing(2) !important; diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankViewModel.cs index 159ed89931..06dea9a82d 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Centre/Ranking/CentreRankViewModel.cs @@ -2,7 +2,7 @@ { public class CentreRankViewModel { - public CentreRankViewModel(int rank, string centreName, int sum,bool isHighlighted) + public CentreRankViewModel(int rank, string centreName, int sum, bool isHighlighted) { Rank = rank; CentreName = centreName; diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/Index.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/Index.cshtml index 7bd08113ca..36589b79da 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/Index.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/Index.cshtml @@ -35,7 +35,7 @@ } @if (Model.CentreHasNoActivity) { -

    Your centre overall rank: no activity

    +

    Your centre overall rank: no activity

    }
    diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingStandardUserTable.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingStandardUserTable.cshtml index bac2dd9427..c9b62bf71c 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingStandardUserTable.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingStandardUserTable.cshtml @@ -4,7 +4,7 @@ - @foreach (var centre in Model.Centres) { - + } diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingSuperAdminTable.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingSuperAdminTable.cshtml index b53ef13863..df4faad5f6 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingSuperAdminTable.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Ranking/_RankingSuperAdminTable.cshtml @@ -4,13 +4,13 @@
    + Rank @@ -15,7 +15,7 @@
    @centre.Rank@centre.Rank @centre.CentreName
    - - - @@ -18,13 +18,13 @@ @foreach (var centre in Model.Centres) { - - -
    + Rank + Centre + Sum
    + Rank @centre.Rank + Centre @centre.CentreName + Sum @centre.Sum