From 9417bb4d1cdc7593822e7dddc0005947a12d969b Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Wed, 30 Jun 2021 13:46:52 +0100 Subject: [PATCH 01/22] HEEDLS-490 Create AllDelegates controller with CentreAdmin policy; create empty page with delegates sidebar --- .../Delegates/AllDelegatesController.cs | 16 +++++++++ .../Delegates/AllDelegates/Index.cshtml | 34 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs create mode 100644 DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml diff --git a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs new file mode 100644 index 0000000000..2e4f8a86b0 --- /dev/null +++ b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs @@ -0,0 +1,16 @@ +namespace DigitalLearningSolutions.Web.Controllers.TrackingSystem.Delegates +{ + using DigitalLearningSolutions.Web.Helpers; + using Microsoft.AspNetCore.Authorization; + using Microsoft.AspNetCore.Mvc; + + [Authorize(Policy = CustomPolicies.UserCentreAdmin)] + [Route("TrackingSystem/Delegates/All")] + public class AllDelegatesController : Controller + { + public IActionResult Index() + { + return View(); + } + } +} diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml new file mode 100644 index 0000000000..af12cc931c --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml @@ -0,0 +1,34 @@ +@using DigitalLearningSolutions.Web.Models.Enums +@using Microsoft.Extensions.Configuration +@inject IConfiguration Configuration + +@{ + ViewData["Title"] = "Delegates"; + ViewData["Application"] = "Tracking System"; + ViewData["HeaderPath"] = $"{Configuration["AppRootPath"]}/TrackingSystem/Delegates/All"; + ViewData["HeaderPathName"] = "Tracking System"; +} + +@section NavMenuItems { + +} + +
+
+ +
+ +
+
+
+

Delegates

+
+
+ + +
+
From 34711fe6a4c1a802adab57f0cca7821a1174b065 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Wed, 30 Jun 2021 14:49:49 +0100 Subject: [PATCH 02/22] HEEDLS-490 Link to AllDelegates from nav bar, nav sidebar and centre dashboard --- .../Centre/Dashboard/_DashboardTopCardGroup.cshtml | 2 +- .../Delegates/Shared/_DelegatesSideNavMenu.cshtml | 5 +++-- .../Views/TrackingSystem/Shared/_NavMenuItems.cshtml | 10 +++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Dashboard/_DashboardTopCardGroup.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Dashboard/_DashboardTopCardGroup.cshtml index a0b7734af3..f415858e76 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Dashboard/_DashboardTopCardGroup.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Centre/Dashboard/_DashboardTopCardGroup.cshtml @@ -12,7 +12,7 @@

@Model.NumberOfDelegates Delegates

- Delegates + Delegates diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/Shared/_DelegatesSideNavMenu.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/Shared/_DelegatesSideNavMenu.cshtml index 4cb7a51564..e73d03900b 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/Shared/_DelegatesSideNavMenu.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/Shared/_DelegatesSideNavMenu.cshtml @@ -7,8 +7,9 @@

Delegates

    - diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Shared/_NavMenuItems.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Shared/_NavMenuItems.cshtml index efcf472149..78863eda52 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Shared/_NavMenuItems.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Shared/_NavMenuItems.cshtml @@ -7,19 +7,19 @@
  • Centre - +
  • - + Delegates - +
  • Course setup - +
  • } @@ -27,7 +27,7 @@
  • Admin - +
  • } From 9384f41394d36462d1317134c1b05969639be774 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Wed, 30 Jun 2021 17:03:52 +0100 Subject: [PATCH 03/22] HEEDLS-490 Add register/email/upload/download buttons and style --- .../Styles/trackingSystem/allDelegates.scss | 31 +++++++++++++++++++ .../Delegates/AllDelegates/Index.cshtml | 18 ++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 DigitalLearningSolutions.Web/Styles/trackingSystem/allDelegates.scss diff --git a/DigitalLearningSolutions.Web/Styles/trackingSystem/allDelegates.scss b/DigitalLearningSolutions.Web/Styles/trackingSystem/allDelegates.scss new file mode 100644 index 0000000000..f86152ce9d --- /dev/null +++ b/DigitalLearningSolutions.Web/Styles/trackingSystem/allDelegates.scss @@ -0,0 +1,31 @@ +@import "~nhsuk-frontend/packages/core/all"; + +.all-delegates-button-group { + text-align: right; + + @media (max-width: 64em) { + width: 100%; + text-align: unset; + margin-bottom: nhsuk-spacing(4); + } +} + +.all-delegates-button { + padding-top: nhsuk-spacing(2); + padding-bottom: nhsuk-spacing(2); + + @media (max-width: 64em) { + padding-top: nhsuk-spacing(1); + padding-bottom: nhsuk-spacing(1); + margin-top: nhsuk-spacing(1); + margin-bottom: nhsuk-spacing(1); + } + + @media (max-width: 32em) { + width: calc(50% - 4px); + } + + @media (max-width: 20em) { + width: 100%; + } +} diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml index af12cc931c..f5453b1ff5 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml @@ -2,6 +2,8 @@ @using Microsoft.Extensions.Configuration @inject IConfiguration Configuration + + @{ ViewData["Title"] = "Delegates"; ViewData["Application"] = "Tracking System"; @@ -22,9 +24,23 @@
    -
    +

    Delegates

    +
    + + + + +
    +
    +
    + @if (!Model.Delegates.Any()) { + + } else { +
    + @foreach (var delegateModel in Model.Delegates) { + + } +
    + } +
    +
    + diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml new file mode 100644 index 0000000000..409c30c774 --- /dev/null +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml @@ -0,0 +1,18 @@ +@using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates +@model SearchableDelegateViewModel + +@*TODO: Search and sort functionality is part of HEEDLS-491. + Filename includes 'Searchable' to avoid having to change name later*@ + +
    +
    + + + @Model.Name (@Model.CandidateNumber) + + +
    + +
    +
    +
    From e7231bd3cf80a9346456c3fae2f5dc2e637b6ba2 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Wed, 30 Jun 2021 18:27:03 +0100 Subject: [PATCH 06/22] HEEDLS-490 Update controller to fetch and display delegate cards --- .../DataServices/UserDataService.cs | 34 +++++++++++++++++++ .../Delegates/AllDelegatesController.cs | 14 +++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/DigitalLearningSolutions.Data/DataServices/UserDataService.cs b/DigitalLearningSolutions.Data/DataServices/UserDataService.cs index 71a5a5661e..fa9f4da23e 100644 --- a/DigitalLearningSolutions.Data/DataServices/UserDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/UserDataService.cs @@ -12,6 +12,7 @@ public interface IUserDataService public AdminUser? GetAdminUserById(int id); public DelegateUser? GetDelegateUserById(int id); public List GetAdminUsersByCentreId(int centreId); + public List GetDelegateUsersByCentreId(int centreId); public AdminUser? GetAdminUserByUsername(string username); public List GetDelegateUsersByUsername(string username); public AdminUser? GetAdminUserByEmailAddress(string emailAddress); @@ -175,6 +176,39 @@ FROM AdminUsers AS au return users; } + public List GetDelegateUsersByCentreId(int centreId) + { + var users = connection.Query( + @"SELECT + cd.CandidateID AS Id, + cd.CandidateNumber, + ct.CentreName, + cd.CentreID, + cd.DateRegistered, + ct.Active AS CentreActive, + cd.EmailAddress, + cd.FirstName, + cd.LastName, + cd.Password, + cd.Approved, + cd.ProfileImage, + cd.Answer1, + cd.Answer2, + cd.Answer3, + cd.Answer4, + cd.Answer5, + cd.Answer6, + jg.JobGroupName + FROM Candidates AS cd + INNER JOIN Centres AS ct ON ct.CentreID = cd.CentreID + INNER JOIN JobGroups AS jg ON jg.JobGroupID = cd.JobGroupID + WHERE cd.CentreId = @centreId AND cd.Approved = 1", + new { centreId } + ).ToList(); + + return users; + } + public AdminUser? GetAdminUserByUsername(string username) { var user = connection.Query( diff --git a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs index 2e4f8a86b0..6a4dd56a67 100644 --- a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs +++ b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs @@ -1,6 +1,8 @@ namespace DigitalLearningSolutions.Web.Controllers.TrackingSystem.Delegates { + using DigitalLearningSolutions.Data.DataServices; using DigitalLearningSolutions.Web.Helpers; + using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -8,9 +10,19 @@ [Route("TrackingSystem/Delegates/All")] public class AllDelegatesController : Controller { + private readonly IUserDataService userDataService; + + public AllDelegatesController(IUserDataService userDataService) + { + this.userDataService = userDataService; + } + public IActionResult Index() { - return View(); + var delegateUsers = userDataService.GetDelegateUsersByCentreId(User.GetCentreId()).GetRange(0, 10); + var model = new AllDelegatesViewModel(delegateUsers); + + return View(model); } } } From 6d7adec70a67fbb32577023e58f17a9320a12c55 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Thu, 1 Jul 2021 12:10:22 +0100 Subject: [PATCH 07/22] HEEDLS-490 Create DelegateUserCard subclass; update dataservice method to populate with additional info --- .../DataServices/UserDataService.cs | 16 +++++++++++----- .../Models/User/DelegateUserCard.cs | 10 ++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 DigitalLearningSolutions.Data/Models/User/DelegateUserCard.cs diff --git a/DigitalLearningSolutions.Data/DataServices/UserDataService.cs b/DigitalLearningSolutions.Data/DataServices/UserDataService.cs index fa9f4da23e..fe1d820bbd 100644 --- a/DigitalLearningSolutions.Data/DataServices/UserDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/UserDataService.cs @@ -12,7 +12,7 @@ public interface IUserDataService public AdminUser? GetAdminUserById(int id); public DelegateUser? GetDelegateUserById(int id); public List GetAdminUsersByCentreId(int centreId); - public List GetDelegateUsersByCentreId(int centreId); + public List GetDelegateUserCardsByCentreId(int centreId); public AdminUser? GetAdminUserByUsername(string username); public List GetDelegateUsersByUsername(string username); public AdminUser? GetAdminUserByEmailAddress(string emailAddress); @@ -176,9 +176,9 @@ FROM AdminUsers AS au return users; } - public List GetDelegateUsersByCentreId(int centreId) + public List GetDelegateUserCardsByCentreId(int centreId) { - var users = connection.Query( + var users = connection.Query( @"SELECT cd.CandidateID AS Id, cd.CandidateNumber, @@ -191,14 +191,20 @@ public List GetDelegateUsersByCentreId(int centreId) cd.LastName, cd.Password, cd.Approved, - cd.ProfileImage, cd.Answer1, cd.Answer2, cd.Answer3, cd.Answer4, cd.Answer5, cd.Answer6, - jg.JobGroupName + jg.JobGroupName, + cd.SelfReg, + cd.ExternalReg, + cd.Active, + (SELECT AdminID + FROM AdminUsers au + WHERE au.Email = cd.EmailAddress AND au.CentreID = cd.CentreID + ) FROM Candidates AS cd INNER JOIN Centres AS ct ON ct.CentreID = cd.CentreID INNER JOIN JobGroups AS jg ON jg.JobGroupID = cd.JobGroupID diff --git a/DigitalLearningSolutions.Data/Models/User/DelegateUserCard.cs b/DigitalLearningSolutions.Data/Models/User/DelegateUserCard.cs new file mode 100644 index 0000000000..a59101e3cc --- /dev/null +++ b/DigitalLearningSolutions.Data/Models/User/DelegateUserCard.cs @@ -0,0 +1,10 @@ +namespace DigitalLearningSolutions.Data.Models.User +{ + public class DelegateUserCard : DelegateUser + { + public bool SelfReg { get; set; } + public bool ExternalReg { get; set; } + public bool Active { get; set; } + public int? AdminId { get; set; } + } +} From 8b2932510f391270a5534e06f083f2c4a0c9de5c Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Thu, 1 Jul 2021 12:30:00 +0100 Subject: [PATCH 08/22] HEEDLS-490 Add SelfReg/Active/Admin/PasswordSet tags to DelegateCard --- .../Delegates/AllDelegatesController.cs | 2 +- .../Delegates/AllDelegatesViewModel.cs | 2 +- .../Delegates/SearchableDelegateViewModel.cs | 15 ++++++++++++--- .../AllDelegates/_SearchableDelegateCard.cshtml | 13 ++++++++++++- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs index 6a4dd56a67..dc65e7d13c 100644 --- a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs +++ b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs @@ -19,7 +19,7 @@ public AllDelegatesController(IUserDataService userDataService) public IActionResult Index() { - var delegateUsers = userDataService.GetDelegateUsersByCentreId(User.GetCentreId()).GetRange(0, 10); + var delegateUsers = userDataService.GetDelegateUserCardsByCentreId(User.GetCentreId()).GetRange(0, 10); var model = new AllDelegatesViewModel(delegateUsers); return View(model); diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/AllDelegatesViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/AllDelegatesViewModel.cs index 01738751fe..304db75a03 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/AllDelegatesViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/AllDelegatesViewModel.cs @@ -6,7 +6,7 @@ public class AllDelegatesViewModel { - public AllDelegatesViewModel(IEnumerable delegateUsers) + public AllDelegatesViewModel(IEnumerable delegateUsers) { Delegates = delegateUsers.Select(delegateUser => new SearchableDelegateViewModel(delegateUser)); } diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs index bd8f0d5507..435f570a5f 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs @@ -7,17 +7,26 @@ Filename includes 'Searchable' to avoid having to change name later */ public class SearchableDelegateViewModel { - public SearchableDelegateViewModel(DelegateUser delegateUser) + public SearchableDelegateViewModel(DelegateUserCard delegateUser) { Id = delegateUser.Id; Name = delegateUser.SearchableName; CandidateNumber = delegateUser.CandidateNumber; + IsSelfReg = delegateUser.SelfReg; + IsExternalReg = delegateUser.ExternalReg; + IsActive = delegateUser.Active; + IsAdmin = delegateUser.AdminId.HasValue; + IsPasswordSet = delegateUser.Password != null; } public int Id { get; set; } - public string Name { get; set; } - public string CandidateNumber { get; set; } + + public bool IsSelfReg { get; set; } + public bool IsExternalReg { get; set; } + public bool IsActive { get; set; } + public bool IsAdmin { get; set; } + public bool IsPasswordSet { get; set; } } } diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml index 409c30c774..ca6f0a5969 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml @@ -1,5 +1,11 @@ @using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates @model SearchableDelegateViewModel +@{ + var activeTagCss = Model.IsActive ? "nhsuk-tag" : "nhsuk-tag nhsuk-tag--grey"; + var selfRegTagCss = "nhsuk-tag nhsuk-tag--pink"; + var adminTagCss = "nhsuk-tag--blue"; + var passwordTagCss = Model.IsPasswordSet ? "nhsuk-tag nhsuk-tag--green" : "nhsuk-tag nhsuk-tag--red"; +} @*TODO: Search and sort functionality is part of HEEDLS-491. Filename includes 'Searchable' to avoid having to change name later*@ @@ -12,7 +18,12 @@
    - + @(Model.IsActive ? "Active" : "Inactive") + @(Model.IsSelfReg ? "Self registered" + (Model.IsExternalReg ? " (External)" : "") : "Registered by centre") + @if (Model.IsAdmin) { + Admin + } + @(Model.IsPasswordSet ? "Password set" : "Password not set")
    From f2bcd95176722c5c9b6b9879b7d743900f010905 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Thu, 1 Jul 2021 13:15:31 +0100 Subject: [PATCH 09/22] HEEDLS-490 Add Name/Id/Email/RegDate/JobGroup to DelegateCard --- .../Delegates/SearchableDelegateViewModel.cs | 12 ++++++ .../_SearchableDelegateCard.cshtml | 43 ++++++++++++++++--- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs index 435f570a5f..7a62a67519 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs @@ -12,11 +12,19 @@ public SearchableDelegateViewModel(DelegateUserCard delegateUser) Id = delegateUser.Id; Name = delegateUser.SearchableName; CandidateNumber = delegateUser.CandidateNumber; + IsSelfReg = delegateUser.SelfReg; IsExternalReg = delegateUser.ExternalReg; IsActive = delegateUser.Active; IsAdmin = delegateUser.AdminId.HasValue; IsPasswordSet = delegateUser.Password != null; + + Email = delegateUser.EmailAddress; + JobGroup = delegateUser.JobGroupName; + if (delegateUser.DateRegistered.HasValue) + { + RegistrationDate = delegateUser.DateRegistered.Value.ToShortDateString(); + } } public int Id { get; set; } @@ -28,5 +36,9 @@ public SearchableDelegateViewModel(DelegateUserCard delegateUser) public bool IsActive { get; set; } public bool IsAdmin { get; set; } public bool IsPasswordSet { get; set; } + + public string? Email { get; set; } + public string? JobGroup { get; set; } + public string? RegistrationDate { get; set; } } } diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml index ca6f0a5969..2af542ba65 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml @@ -17,13 +17,44 @@ @Model.Name (@Model.CandidateNumber) +
    - @(Model.IsActive ? "Active" : "Inactive") - @(Model.IsSelfReg ? "Self registered" + (Model.IsExternalReg ? " (External)" : "") : "Registered by centre") - @if (Model.IsAdmin) { - Admin - } - @(Model.IsPasswordSet ? "Password set" : "Password not set") +
    + @(Model.IsActive ? "Active" : "Inactive") + @(Model.IsSelfReg ? "Self registered" + (Model.IsExternalReg ? " (External)" : "") : "Registered by centre") + @if (Model.IsAdmin) { + Admin + } + @(Model.IsPasswordSet ? "Password set" : "Password not set") +
    + +
    +
    +
    Name
    +
    @Model.Name
    +
    + +
    +
    Email
    +
    @Model.Email
    +
    + +
    +
    ID
    +
    @Model.CandidateNumber
    +
    + +
    +
    Registration date
    +
    @Model.RegistrationDate
    +
    + +
    +
    Job group
    +
    @Model.JobGroup
    +
    +
    + From 4338e46c32ff852fb7b82addd616269c2741e7b6 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Thu, 1 Jul 2021 13:27:48 +0100 Subject: [PATCH 10/22] HEEDLS-490 Add buttons at bottom of DelegateCard --- .../_SearchableDelegateCard.cshtml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml index 2af542ba65..b06462fe48 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml @@ -19,7 +19,7 @@
    -
    +
    @(Model.IsActive ? "Active" : "Inactive") @(Model.IsSelfReg ? "Self registered" + (Model.IsExternalReg ? " (External)" : "") : "Registered by centre") @if (Model.IsAdmin) { @@ -28,33 +28,35 @@ @(Model.IsPasswordSet ? "Password set" : "Password not set")
    -
    -
    +
    +
    Name
    @Model.Name
    -
    +
    Email
    @Model.Email
    -
    +
    ID
    @Model.CandidateNumber
    -
    +
    Registration date
    @Model.RegistrationDate
    -
    +
    Job group
    @Model.JobGroup
    -
    + + +
    From 01829f96a4a59b88f0a88c33eebf25ac5513191a Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Thu, 1 Jul 2021 14:00:42 +0100 Subject: [PATCH 11/22] HEEDLS-490 Add custom prompt fields to DelegateCard --- .../Delegates/AllDelegatesController.cs | 10 ++++--- .../Delegates/AllDelegatesViewModel.cs | 27 ++++++++++++++++--- .../Delegates/SearchableDelegateViewModel.cs | 8 +++++- .../_SearchableDelegateCard.cshtml | 10 ++++++- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs index dc65e7d13c..42804941a1 100644 --- a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs +++ b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs @@ -10,17 +10,21 @@ [Route("TrackingSystem/Delegates/All")] public class AllDelegatesController : Controller { + private readonly CustomPromptHelper customPromptHelper; private readonly IUserDataService userDataService; - public AllDelegatesController(IUserDataService userDataService) + public AllDelegatesController(IUserDataService userDataService, CustomPromptHelper customPromptHelper) { this.userDataService = userDataService; + this.customPromptHelper = customPromptHelper; } public IActionResult Index() { - var delegateUsers = userDataService.GetDelegateUserCardsByCentreId(User.GetCentreId()).GetRange(0, 10); - var model = new AllDelegatesViewModel(delegateUsers); + var centreId = User.GetCentreId(); + var delegateUsers = userDataService.GetDelegateUserCardsByCentreId(centreId).GetRange(0, 10); + + var model = new AllDelegatesViewModel(centreId, delegateUsers, customPromptHelper); return View(model); } diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/AllDelegatesViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/AllDelegatesViewModel.cs index 304db75a03..592a7c2b42 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/AllDelegatesViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/AllDelegatesViewModel.cs @@ -3,14 +3,35 @@ using System.Collections.Generic; using System.Linq; using DigitalLearningSolutions.Data.Models.User; + using DigitalLearningSolutions.Web.Helpers; public class AllDelegatesViewModel { - public AllDelegatesViewModel(IEnumerable delegateUsers) + public AllDelegatesViewModel( + int centreId, + IEnumerable delegateUsers, + CustomPromptHelper helper + ) { - Delegates = delegateUsers.Select(delegateUser => new SearchableDelegateViewModel(delegateUser)); + CentreId = centreId; + Delegates = delegateUsers.Select( + delegateUser => + { + var customFields = helper.GetCustomFieldViewModelsForCentre( + centreId, + delegateUser.Answer1, + delegateUser.Answer2, + delegateUser.Answer3, + delegateUser.Answer4, + delegateUser.Answer5, + delegateUser.Answer6 + ); + return new SearchableDelegateViewModel(delegateUser, customFields); + } + ); } - public IEnumerable Delegates { get; } + public int CentreId { get; set; } + public IEnumerable Delegates { get; set; } } } diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs index 7a62a67519..525ae60c49 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs @@ -1,13 +1,15 @@ namespace DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates { + using System.Collections.Generic; using DigitalLearningSolutions.Data.Models.User; + using DigitalLearningSolutions.Web.ViewModels.Common; /* TODO: Search and sort functionality is part of HEEDLS-491. Filename includes 'Searchable' to avoid having to change name later */ public class SearchableDelegateViewModel { - public SearchableDelegateViewModel(DelegateUserCard delegateUser) + public SearchableDelegateViewModel(DelegateUserCard delegateUser, List customFields) { Id = delegateUser.Id; Name = delegateUser.SearchableName; @@ -25,6 +27,8 @@ public SearchableDelegateViewModel(DelegateUserCard delegateUser) { RegistrationDate = delegateUser.DateRegistered.Value.ToShortDateString(); } + + CustomFields = customFields; } public int Id { get; set; } @@ -40,5 +44,7 @@ public SearchableDelegateViewModel(DelegateUserCard delegateUser) public string? Email { get; set; } public string? JobGroup { get; set; } public string? RegistrationDate { get; set; } + + public List CustomFields { get; set; } } } diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml index b06462fe48..3c8af03baa 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml @@ -1,4 +1,5 @@ -@using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates +@using DigitalLearningSolutions.Web.ViewModels.Common +@using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates @model SearchableDelegateViewModel @{ var activeTagCss = Model.IsActive ? "nhsuk-tag" : "nhsuk-tag nhsuk-tag--grey"; @@ -53,6 +54,13 @@
    Job group
    @Model.JobGroup
    + + @foreach (CustomFieldViewModel customField in Model.CustomFields) { +
    +
    @customField.CustomPrompt
    +
    @customField.Answer
    +
    + } From ed2214f205cba5155470ac62ce3145187f6a7093 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Mon, 5 Jul 2021 10:53:32 +0100 Subject: [PATCH 12/22] HEEDLS-490 Fix bug with admin tag; change tag colour and ordering --- .../DataServices/UserDataService.cs | 2 +- .../AllDelegates/_SearchableDelegateCard.cshtml | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/DigitalLearningSolutions.Data/DataServices/UserDataService.cs b/DigitalLearningSolutions.Data/DataServices/UserDataService.cs index fe1d820bbd..bf529ac50e 100644 --- a/DigitalLearningSolutions.Data/DataServices/UserDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/UserDataService.cs @@ -204,7 +204,7 @@ public List GetDelegateUserCardsByCentreId(int centreId) (SELECT AdminID FROM AdminUsers au WHERE au.Email = cd.EmailAddress AND au.CentreID = cd.CentreID - ) + ) AS AdminID FROM Candidates AS cd INNER JOIN Centres AS ct ON ct.CentreID = cd.CentreID INNER JOIN JobGroups AS jg ON jg.JobGroupID = cd.JobGroupID diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml index 3c8af03baa..2aaa060168 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml @@ -3,8 +3,8 @@ @model SearchableDelegateViewModel @{ var activeTagCss = Model.IsActive ? "nhsuk-tag" : "nhsuk-tag nhsuk-tag--grey"; - var selfRegTagCss = "nhsuk-tag nhsuk-tag--pink"; - var adminTagCss = "nhsuk-tag--blue"; + var selfRegTagCss = "nhsuk-tag nhsuk-tag--grey"; + var adminTagCss = "nhsuk-tag nhsuk-tag--green"; var passwordTagCss = Model.IsPasswordSet ? "nhsuk-tag nhsuk-tag--green" : "nhsuk-tag nhsuk-tag--red"; } @@ -23,10 +23,11 @@
    @(Model.IsActive ? "Active" : "Inactive") @(Model.IsSelfReg ? "Self registered" + (Model.IsExternalReg ? " (External)" : "") : "Registered by centre") - @if (Model.IsAdmin) { + @(Model.IsPasswordSet ? "Password set" : "Password not set") + @if (Model.IsAdmin) + { Admin } - @(Model.IsPasswordSet ? "Password set" : "Password not set")
    From 3e40f39c648ba0e13562b5b619d81e3cd1bde552 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 6 Jul 2021 13:23:21 +0100 Subject: [PATCH 13/22] HEEDLS-490 Use styled links instead of buttons; update sass; remove role/aria-level --- .../Styles/trackingSystem/allDelegates.scss | 10 ++++------ .../Delegates/AllDelegates/Index.cshtml | 16 ++++++++-------- .../AllDelegates/_SearchableDelegateCard.cshtml | 9 ++++----- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/DigitalLearningSolutions.Web/Styles/trackingSystem/allDelegates.scss b/DigitalLearningSolutions.Web/Styles/trackingSystem/allDelegates.scss index f86152ce9d..228a4d421a 100644 --- a/DigitalLearningSolutions.Web/Styles/trackingSystem/allDelegates.scss +++ b/DigitalLearningSolutions.Web/Styles/trackingSystem/allDelegates.scss @@ -3,7 +3,7 @@ .all-delegates-button-group { text-align: right; - @media (max-width: 64em) { + @media (max-width: 1024px) { width: 100%; text-align: unset; margin-bottom: nhsuk-spacing(4); @@ -14,18 +14,16 @@ padding-top: nhsuk-spacing(2); padding-bottom: nhsuk-spacing(2); - @media (max-width: 64em) { - padding-top: nhsuk-spacing(1); - padding-bottom: nhsuk-spacing(1); + @media (max-width: 1024px) { margin-top: nhsuk-spacing(1); margin-bottom: nhsuk-spacing(1); } - @media (max-width: 32em) { + @media (max-width: 425px) { width: calc(50% - 4px); } - @media (max-width: 20em) { + @media (max-width: 375px) { width: 100%; } } diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml index f9bc7c8f25..c869c9c9be 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml @@ -30,18 +30,18 @@

    Delegates

    diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml index 2aaa060168..5dd396a422 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml @@ -14,7 +14,7 @@
    - + @Model.Name (@Model.CandidateNumber) @@ -24,8 +24,7 @@ @(Model.IsActive ? "Active" : "Inactive") @(Model.IsSelfReg ? "Self registered" + (Model.IsExternalReg ? " (External)" : "") : "Registered by centre") @(Model.IsPasswordSet ? "Password set" : "Password not set") - @if (Model.IsAdmin) - { + @if (Model.IsAdmin) { Admin }
    @@ -64,8 +63,8 @@ }
    - - + Manage delegate + Set password From 3234e8002bc17a3738524a22f606e891096d8775 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 6 Jul 2021 16:03:15 +0100 Subject: [PATCH 14/22] HEEDLS-490 Change tag colours, HeaderPath, and other minor changes --- DigitalLearningSolutions.Data/DataServices/UserDataService.cs | 4 +--- .../TrackingSystem/Delegates/AllDelegatesController.cs | 3 ++- .../Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml | 2 +- .../Delegates/AllDelegates/_SearchableDelegateCard.cshtml | 4 ++-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/DigitalLearningSolutions.Data/DataServices/UserDataService.cs b/DigitalLearningSolutions.Data/DataServices/UserDataService.cs index bf529ac50e..350d2c62b4 100644 --- a/DigitalLearningSolutions.Data/DataServices/UserDataService.cs +++ b/DigitalLearningSolutions.Data/DataServices/UserDataService.cs @@ -178,7 +178,7 @@ FROM AdminUsers AS au public List GetDelegateUserCardsByCentreId(int centreId) { - var users = connection.Query( + return connection.Query( @"SELECT cd.CandidateID AS Id, cd.CandidateNumber, @@ -211,8 +211,6 @@ FROM Candidates AS cd WHERE cd.CentreId = @centreId AND cd.Approved = 1", new { centreId } ).ToList(); - - return users; } public AdminUser? GetAdminUserByUsername(string username) diff --git a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs index 42804941a1..15ed0aa85e 100644 --- a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs +++ b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs @@ -1,5 +1,6 @@ namespace DigitalLearningSolutions.Web.Controllers.TrackingSystem.Delegates { + using System.Linq; using DigitalLearningSolutions.Data.DataServices; using DigitalLearningSolutions.Web.Helpers; using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates; @@ -22,7 +23,7 @@ public AllDelegatesController(IUserDataService userDataService, CustomPromptHelp public IActionResult Index() { var centreId = User.GetCentreId(); - var delegateUsers = userDataService.GetDelegateUserCardsByCentreId(centreId).GetRange(0, 10); + var delegateUsers = userDataService.GetDelegateUserCardsByCentreId(centreId).Take(10); var model = new AllDelegatesViewModel(centreId, delegateUsers, customPromptHelper); diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml index c869c9c9be..00e6641f16 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/Index.cshtml @@ -9,7 +9,7 @@ @{ ViewData["Title"] = "Delegates"; ViewData["Application"] = "Tracking System"; - ViewData["HeaderPath"] = $"{Configuration["AppRootPath"]}/TrackingSystem/Delegates/All"; + ViewData["HeaderPath"] = $"{Configuration["AppRootPath"]}/TrackingSystem/Centre/Dashboard"; ViewData["HeaderPathName"] = "Tracking System"; } diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml index 5dd396a422..8bbd3cfe9e 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml @@ -2,9 +2,9 @@ @using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates @model SearchableDelegateViewModel @{ - var activeTagCss = Model.IsActive ? "nhsuk-tag" : "nhsuk-tag nhsuk-tag--grey"; + var activeTagCss = Model.IsActive ? "nhsuk-tag nhsuk-tag--green" : "nhsuk-tag nhsuk-tag--red"; var selfRegTagCss = "nhsuk-tag nhsuk-tag--grey"; - var adminTagCss = "nhsuk-tag nhsuk-tag--green"; + var adminTagCss = "nhsuk-tag nhsuk-tag--grey"; var passwordTagCss = Model.IsPasswordSet ? "nhsuk-tag nhsuk-tag--green" : "nhsuk-tag nhsuk-tag--red"; } From 11fc107781b95904194b8f0dbe219ad1ea484768 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 6 Jul 2021 16:41:43 +0100 Subject: [PATCH 15/22] HEEDLS-490 Move tag name logic into viewmodel; test --- .../SearchableDelegateViewModelTests.cs | 77 +++++++++++++++++++ .../Delegates/SearchableDelegateViewModel.cs | 5 ++ .../_SearchableDelegateCard.cshtml | 6 +- 3 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/AllDelegates/SearchableDelegateViewModelTests.cs diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/AllDelegates/SearchableDelegateViewModelTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/AllDelegates/SearchableDelegateViewModelTests.cs new file mode 100644 index 0000000000..452a98f168 --- /dev/null +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/AllDelegates/SearchableDelegateViewModelTests.cs @@ -0,0 +1,77 @@ +namespace DigitalLearningSolutions.Web.Tests.ViewModels.TrackingSystem.Delegates.AllDelegates +{ + using System; + using System.Collections.Generic; + using DigitalLearningSolutions.Data.Models.User; + using DigitalLearningSolutions.Web.ViewModels.Common; + using DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates; + using FluentAssertions; + using NUnit.Framework; + + public class SearchableDelegateViewModelTests + { + [Test] + public void SearchableDelegateViewModel_sets_active_tag_name_correctly() + { + var activeModel = new SearchableDelegateViewModel( + new DelegateUserCard { Active = true }, + new List() + ); + var inactiveModel = new SearchableDelegateViewModel( + new DelegateUserCard { Active = false }, + new List() + ); + + activeModel.ActiveTagName.Should().Be("Active"); + inactiveModel.ActiveTagName.Should().Be("Inactive"); + } + + [Test] + public void SearchableDelegateViewModel_sets_password_tag_name_correctly() + { + var pwSetModel = new SearchableDelegateViewModel( + new DelegateUserCard { Password = "pw" }, + new List() + ); + var pwNotSetModel = new SearchableDelegateViewModel( + new DelegateUserCard { Password = null }, + new List() + ); + + pwSetModel.PasswordTagName.Should().Be("Password set"); + pwNotSetModel.PasswordTagName.Should().Be("Password not set"); + } + + [Test] + public void SearchableDelegateViewModel_sets_regstatus_tag_name_correctly() + { + var selfRegModel = new SearchableDelegateViewModel( + new DelegateUserCard { SelfReg = true, ExternalReg = false }, + new List() + ); + var selfRegExternalModel = new SearchableDelegateViewModel( + new DelegateUserCard { SelfReg = true, ExternalReg = true }, + new List() + ); + var centreRegModel = new SearchableDelegateViewModel( + new DelegateUserCard { SelfReg = false }, + new List() + ); + + selfRegModel.RegStatusTagName.Should().Be("Self registered"); + selfRegExternalModel.RegStatusTagName.Should().Be("Self registered (External)"); + centreRegModel.RegStatusTagName.Should().Be("Registered by centre"); + } + + [Test] + public void SearchableDelegateViewModel_sets_reg_date_string_correctly() + { + var model = new SearchableDelegateViewModel( + new DelegateUserCard { DateRegistered = new DateTime(2021, 05, 13) }, + new List() + ); + + model.RegistrationDate.Should().Be("13/05/2021"); + } + } +} diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs index 525ae60c49..d0ddab985a 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs @@ -41,6 +41,11 @@ public SearchableDelegateViewModel(DelegateUserCard delegateUser, List + IsSelfReg ? "Self registered" + (IsExternalReg ? " (External)" : "") : "Registered by centre"; + public string ActiveTagName => IsActive ? "Active" : "Inactive"; + public string PasswordTagName => IsPasswordSet ? "Password set" : "Password not set"; + public string? Email { get; set; } public string? JobGroup { get; set; } public string? RegistrationDate { get; set; } diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml index 8bbd3cfe9e..9c957d6934 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml @@ -21,9 +21,9 @@
    - @(Model.IsActive ? "Active" : "Inactive") - @(Model.IsSelfReg ? "Self registered" + (Model.IsExternalReg ? " (External)" : "") : "Registered by centre") - @(Model.IsPasswordSet ? "Password set" : "Password not set") + @(Model.ActiveTagName) + @(Model.RegStatusTagName) + @(Model.PasswordTagName) @if (Model.IsAdmin) { Admin } From 7dd943a66eb1edfbf0b7c6168ed5338038f87a8c Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 6 Jul 2021 16:51:40 +0100 Subject: [PATCH 16/22] HEEDLS-490 Perform DelegateUserCard to SearchableDelegateViewModels mapping in controller --- .../Delegates/AllDelegatesController.cs | 10 +++++++-- .../Helpers/CustomPromptHelper.cs | 14 ++++++++++++ .../Delegates/AllDelegatesViewModel.cs | 22 ++----------------- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs index 15ed0aa85e..ac32c287e9 100644 --- a/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs +++ b/DigitalLearningSolutions.Web/Controllers/TrackingSystem/Delegates/AllDelegatesController.cs @@ -24,8 +24,14 @@ public IActionResult Index() { var centreId = User.GetCentreId(); var delegateUsers = userDataService.GetDelegateUserCardsByCentreId(centreId).Take(10); - - var model = new AllDelegatesViewModel(centreId, delegateUsers, customPromptHelper); + var searchableDelegateViewModels = delegateUsers.Select( + delegateUser => + { + var customFields = customPromptHelper.GetCustomFieldViewModelsForCentre(centreId, delegateUser); + return new SearchableDelegateViewModel(delegateUser, customFields); + } + ); + var model = new AllDelegatesViewModel(centreId, searchableDelegateViewModels); return View(model); } diff --git a/DigitalLearningSolutions.Web/Helpers/CustomPromptHelper.cs b/DigitalLearningSolutions.Web/Helpers/CustomPromptHelper.cs index 9689152191..be5ff28d55 100644 --- a/DigitalLearningSolutions.Web/Helpers/CustomPromptHelper.cs +++ b/DigitalLearningSolutions.Web/Helpers/CustomPromptHelper.cs @@ -2,6 +2,7 @@ { using System.Collections.Generic; using System.Linq; + using DigitalLearningSolutions.Data.Models.User; using DigitalLearningSolutions.Data.Services; using DigitalLearningSolutions.Web.ViewModels.Common; using Microsoft.AspNetCore.Mvc.ModelBinding; @@ -62,6 +63,19 @@ public List GetCustomFieldViewModelsForCentre( ).ToList(); } + public List GetCustomFieldViewModelsForCentre(int centreId, DelegateUser delegateUser) + { + return GetCustomFieldViewModelsForCentre( + centreId, + delegateUser.Answer1, + delegateUser.Answer2, + delegateUser.Answer3, + delegateUser.Answer4, + delegateUser.Answer5, + delegateUser.Answer6 + ); + } + public void ValidateCustomPrompts( int centreId, string? answer1, diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/AllDelegatesViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/AllDelegatesViewModel.cs index 592a7c2b42..dd2045ce83 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/AllDelegatesViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/AllDelegatesViewModel.cs @@ -1,34 +1,16 @@ namespace DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates { using System.Collections.Generic; - using System.Linq; - using DigitalLearningSolutions.Data.Models.User; - using DigitalLearningSolutions.Web.Helpers; public class AllDelegatesViewModel { public AllDelegatesViewModel( int centreId, - IEnumerable delegateUsers, - CustomPromptHelper helper + IEnumerable searchableDelegateViewModels ) { CentreId = centreId; - Delegates = delegateUsers.Select( - delegateUser => - { - var customFields = helper.GetCustomFieldViewModelsForCentre( - centreId, - delegateUser.Answer1, - delegateUser.Answer2, - delegateUser.Answer3, - delegateUser.Answer4, - delegateUser.Answer5, - delegateUser.Answer6 - ); - return new SearchableDelegateViewModel(delegateUser, customFields); - } - ); + Delegates = searchableDelegateViewModels; } public int CentreId { get; set; } From e522ddb686a26e7aacde427200bea9aebc8fb992 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 6 Jul 2021 17:08:49 +0100 Subject: [PATCH 17/22] HEEDLS-490 Minor refactor and add comments in SearchableDelegateViewModel Tests --- .../SearchableDelegateViewModelTests.cs | 66 ++++++++++--------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/AllDelegates/SearchableDelegateViewModelTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/AllDelegates/SearchableDelegateViewModelTests.cs index 452a98f168..1eef3938af 100644 --- a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/AllDelegates/SearchableDelegateViewModelTests.cs +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/AllDelegates/SearchableDelegateViewModelTests.cs @@ -10,18 +10,20 @@ public class SearchableDelegateViewModelTests { + private readonly List customFields = new List(); + [Test] public void SearchableDelegateViewModel_sets_active_tag_name_correctly() { - var activeModel = new SearchableDelegateViewModel( - new DelegateUserCard { Active = true }, - new List() - ); - var inactiveModel = new SearchableDelegateViewModel( - new DelegateUserCard { Active = false }, - new List() - ); + // Given + var activeUser = new DelegateUserCard { Active = true }; + var inactiveUser = new DelegateUserCard { Active = false }; + + // When + var activeModel = new SearchableDelegateViewModel(activeUser, customFields); + var inactiveModel = new SearchableDelegateViewModel(inactiveUser, customFields); + // Then activeModel.ActiveTagName.Should().Be("Active"); inactiveModel.ActiveTagName.Should().Be("Inactive"); } @@ -29,15 +31,15 @@ public void SearchableDelegateViewModel_sets_active_tag_name_correctly() [Test] public void SearchableDelegateViewModel_sets_password_tag_name_correctly() { - var pwSetModel = new SearchableDelegateViewModel( - new DelegateUserCard { Password = "pw" }, - new List() - ); - var pwNotSetModel = new SearchableDelegateViewModel( - new DelegateUserCard { Password = null }, - new List() - ); + // Given + var pwSetUser = new DelegateUserCard { Password = "pw" }; + var pwNotSetUser = new DelegateUserCard { Password = null }; + + // When + var pwSetModel = new SearchableDelegateViewModel(pwSetUser, customFields); + var pwNotSetModel = new SearchableDelegateViewModel(pwNotSetUser, customFields); + // Then pwSetModel.PasswordTagName.Should().Be("Password set"); pwNotSetModel.PasswordTagName.Should().Be("Password not set"); } @@ -45,19 +47,17 @@ public void SearchableDelegateViewModel_sets_password_tag_name_correctly() [Test] public void SearchableDelegateViewModel_sets_regstatus_tag_name_correctly() { - var selfRegModel = new SearchableDelegateViewModel( - new DelegateUserCard { SelfReg = true, ExternalReg = false }, - new List() - ); - var selfRegExternalModel = new SearchableDelegateViewModel( - new DelegateUserCard { SelfReg = true, ExternalReg = true }, - new List() - ); - var centreRegModel = new SearchableDelegateViewModel( - new DelegateUserCard { SelfReg = false }, - new List() - ); + // Given + var selfRegUser = new DelegateUserCard { SelfReg = true, ExternalReg = false }; + var selfRegExternalUser = new DelegateUserCard { SelfReg = true, ExternalReg = true }; + var centreRegUser = new DelegateUserCard { SelfReg = false }; + // When + var selfRegModel = new SearchableDelegateViewModel(selfRegUser, customFields); + var selfRegExternalModel = new SearchableDelegateViewModel(selfRegExternalUser, customFields); + var centreRegModel = new SearchableDelegateViewModel(centreRegUser, customFields); + + // Then selfRegModel.RegStatusTagName.Should().Be("Self registered"); selfRegExternalModel.RegStatusTagName.Should().Be("Self registered (External)"); centreRegModel.RegStatusTagName.Should().Be("Registered by centre"); @@ -66,11 +66,13 @@ public void SearchableDelegateViewModel_sets_regstatus_tag_name_correctly() [Test] public void SearchableDelegateViewModel_sets_reg_date_string_correctly() { - var model = new SearchableDelegateViewModel( - new DelegateUserCard { DateRegistered = new DateTime(2021, 05, 13) }, - new List() - ); + // Given + var user = new DelegateUserCard { DateRegistered = new DateTime(2021, 05, 13) }; + + // When + var model = new SearchableDelegateViewModel(user, customFields); + // Then model.RegistrationDate.Should().Be("13/05/2021"); } } From c159ea13f801a4c251a2e09abaf2c3510c405934 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 6 Jul 2021 17:22:49 +0100 Subject: [PATCH 18/22] HEEDLS-490 Write tests for GetDelegateUserCardsByCentreId; add AllDelegates accessibility test --- .../DataServices/UserDataServiceTests.cs | 35 +++++++++++++++++++ .../BasicAccessibilityTests.cs | 1 + 2 files changed, 36 insertions(+) diff --git a/DigitalLearningSolutions.Data.Tests/DataServices/UserDataServiceTests.cs b/DigitalLearningSolutions.Data.Tests/DataServices/UserDataServiceTests.cs index 1cf090ee11..2d0c81cf7b 100644 --- a/DigitalLearningSolutions.Data.Tests/DataServices/UserDataServiceTests.cs +++ b/DigitalLearningSolutions.Data.Tests/DataServices/UserDataServiceTests.cs @@ -367,5 +367,40 @@ public void GetNumberOfActiveApprovedDelegatesAtCentre_returns_expected_count() // Then count.Should().Be(3420); } + + [Test] + public void GetDelegateUserCardsByCentreId_populates_DelegateUser_fields_correctly() + { + // Given + var expected = UserTestHelper.GetDefaultDelegateUser( + dateRegistered: DateTime.Parse("2010-09-22 06:52:09.080"), + jobGroupName: "Nursing / midwifery" + ); + + // When + var userCards = userDataService.GetDelegateUserCardsByCentreId(2); + + // Then + var userCard = userCards.Single(user => user.Id == 2); + userCard.Should().BeEquivalentTo(expected); + userCard.Active.Should().BeTrue(); + userCard.SelfReg.Should().BeFalse(); + userCard.ExternalReg.Should().BeFalse(); + userCard.AdminId.Should().BeNull(); + } + + [Test] + public void GetDelegateUserCardsByCentreId_populates_DelegateUserCard_fields_correctly() + { + // When + var userCards = userDataService.GetDelegateUserCardsByCentreId(279); + + // Then + var userCard = userCards.Single(user => user.Id == 97055); + userCard.Active.Should().BeTrue(); + userCard.SelfReg.Should().BeTrue(); + userCard.ExternalReg.Should().BeFalse(); + userCard.AdminId.Should().Be(74); + } } } diff --git a/DigitalLearningSolutions.Web.AutomatedUiTests/AccessibilityTests/BasicAccessibilityTests.cs b/DigitalLearningSolutions.Web.AutomatedUiTests/AccessibilityTests/BasicAccessibilityTests.cs index d7f3235836..3ba139fa8b 100644 --- a/DigitalLearningSolutions.Web.AutomatedUiTests/AccessibilityTests/BasicAccessibilityTests.cs +++ b/DigitalLearningSolutions.Web.AutomatedUiTests/AccessibilityTests/BasicAccessibilityTests.cs @@ -36,6 +36,7 @@ public void Page_has_no_accessibility_errors(string url, string pageTitle) [InlineData("/TrackingSystem/CentreConfiguration/RegistrationPrompts", "Manage delegate registration prompts")] [InlineData("/TrackingSystem/CentreConfiguration/RegistrationPrompts/1/Remove", "Remove delegate registration prompt")] [InlineData("/TrackingSystem/Centre/Reports", "Centre reports")] + [InlineData("/TrackingSystem/Delegates/All", "Delegates")] [InlineData("/TrackingSystem/Delegates/Approve", "Approve delegate registrations")] [InlineData("/NotificationPreferences", "Notification preferences")] [InlineData("/NotificationPreferences/Edit/AdminUser", "Update notification preferences")] From ee1292a8d195182b04c03725ce7e8236d58fb67d Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 6 Jul 2021 17:35:09 +0100 Subject: [PATCH 19/22] HEEDLS-490 Inline reg status/admin tag css strings --- .../Delegates/AllDelegates/_SearchableDelegateCard.cshtml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml index 9c957d6934..d0bacf2832 100644 --- a/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml +++ b/DigitalLearningSolutions.Web/Views/TrackingSystem/Delegates/AllDelegates/_SearchableDelegateCard.cshtml @@ -3,8 +3,6 @@ @model SearchableDelegateViewModel @{ var activeTagCss = Model.IsActive ? "nhsuk-tag nhsuk-tag--green" : "nhsuk-tag nhsuk-tag--red"; - var selfRegTagCss = "nhsuk-tag nhsuk-tag--grey"; - var adminTagCss = "nhsuk-tag nhsuk-tag--grey"; var passwordTagCss = Model.IsPasswordSet ? "nhsuk-tag nhsuk-tag--green" : "nhsuk-tag nhsuk-tag--red"; } @@ -22,10 +20,10 @@
    @(Model.ActiveTagName) - @(Model.RegStatusTagName) + @(Model.RegStatusTagName) @(Model.PasswordTagName) @if (Model.IsAdmin) { - Admin + Admin }
    From 2f846f27d905524c60734911e5e8c8da5cc4be0e Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Tue, 6 Jul 2021 17:44:44 +0100 Subject: [PATCH 20/22] HEEDLS-490 Fix SearchableDelegateViewModel date test --- .../AllDelegates/SearchableDelegateViewModelTests.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/AllDelegates/SearchableDelegateViewModelTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/AllDelegates/SearchableDelegateViewModelTests.cs index 1eef3938af..d7f33bbbd2 100644 --- a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/AllDelegates/SearchableDelegateViewModelTests.cs +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/AllDelegates/SearchableDelegateViewModelTests.cs @@ -67,13 +67,14 @@ public void SearchableDelegateViewModel_sets_regstatus_tag_name_correctly() public void SearchableDelegateViewModel_sets_reg_date_string_correctly() { // Given - var user = new DelegateUserCard { DateRegistered = new DateTime(2021, 05, 13) }; + var date = new DateTime(2021, 05, 13); + var user = new DelegateUserCard { DateRegistered = date }; // When var model = new SearchableDelegateViewModel(user, customFields); // Then - model.RegistrationDate.Should().Be("13/05/2021"); + model.RegistrationDate.Should().BeOneOf("13/05/2021", "05/13/2021").And.Be(date.ToShortDateString()); } } } From afba14c743f41ff73569ac52c22e6c5272590639 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Wed, 7 Jul 2021 13:41:57 +0100 Subject: [PATCH 21/22] HEEDLS-490 Rename test for clarity --- .../DataServices/UserDataServiceTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DigitalLearningSolutions.Data.Tests/DataServices/UserDataServiceTests.cs b/DigitalLearningSolutions.Data.Tests/DataServices/UserDataServiceTests.cs index 2d0c81cf7b..c08f4644c5 100644 --- a/DigitalLearningSolutions.Data.Tests/DataServices/UserDataServiceTests.cs +++ b/DigitalLearningSolutions.Data.Tests/DataServices/UserDataServiceTests.cs @@ -390,7 +390,7 @@ public void GetDelegateUserCardsByCentreId_populates_DelegateUser_fields_correct } [Test] - public void GetDelegateUserCardsByCentreId_populates_DelegateUserCard_fields_correctly() + public void GetDelegateUserCardsByCentreId_populates_DelegateUserCard_admin_fields_correctly() { // When var userCards = userDataService.GetDelegateUserCardsByCentreId(279); From 1c483ae185844205ceabab01870259a7bf1b1525 Mon Sep 17 00:00:00 2001 From: Ibrahim Munir-Zubair Date: Wed, 7 Jul 2021 16:19:46 +0100 Subject: [PATCH 22/22] HEEDLS-490 Display date string in en-gb format --- .../AllDelegates/SearchableDelegateViewModelTests.cs | 2 +- .../TrackingSystem/Delegates/SearchableDelegateViewModel.cs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/AllDelegates/SearchableDelegateViewModelTests.cs b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/AllDelegates/SearchableDelegateViewModelTests.cs index d7f33bbbd2..d0625b03d1 100644 --- a/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/AllDelegates/SearchableDelegateViewModelTests.cs +++ b/DigitalLearningSolutions.Web.Tests/ViewModels/TrackingSystem/Delegates/AllDelegates/SearchableDelegateViewModelTests.cs @@ -74,7 +74,7 @@ public void SearchableDelegateViewModel_sets_reg_date_string_correctly() var model = new SearchableDelegateViewModel(user, customFields); // Then - model.RegistrationDate.Should().BeOneOf("13/05/2021", "05/13/2021").And.Be(date.ToShortDateString()); + model.RegistrationDate.Should().Be("13/05/2021"); } } } diff --git a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs index d0ddab985a..ad10620c25 100644 --- a/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/TrackingSystem/Delegates/SearchableDelegateViewModel.cs @@ -1,6 +1,7 @@ namespace DigitalLearningSolutions.Web.ViewModels.TrackingSystem.Delegates { using System.Collections.Generic; + using System.Globalization; using DigitalLearningSolutions.Data.Models.User; using DigitalLearningSolutions.Web.ViewModels.Common; @@ -25,7 +26,10 @@ public SearchableDelegateViewModel(DelegateUserCard delegateUser, List