From a0579e7ff920368b1fb4557ccc103ed55266edb7 Mon Sep 17 00:00:00 2001 From: swapnamol-abraham Date: Mon, 15 Sep 2025 23:52:48 +0100 Subject: [PATCH 1/2] TD-6088: Refractor recent activity tray to "My courses and elearning" --- .../Controllers/HomeController.cs | 30 +- .../Interfaces/IDashboardService.cs | 9 + .../DashBoard/DashBoardPagingViewModel.cs | 5 + .../Models/DashboardViewModel.cs | 5 + .../Services/DashboardService.cs | 30 ++ .../Styles/nhsuk/layout.scss | 25 ++ .../Views/Home/Dashboard.cshtml | 2 +- .../Views/Home/_CertificateCard.cshtml | 84 ++++++ .../Views/Home/_DashboardPaging.cshtml | 6 +- .../Views/Home/_LearningActivityCard.cshtml | 113 ++++++++ .../Views/Home/_MyCoursesAndElearning.cshtml | 180 ++++++++++++ .../Views/Home/_ResourceCard.cshtml | 23 +- .../Views/MyLearning/Certificates.cshtml | 2 +- .../Views/MyLearning/Index.cshtml | 37 ++- .../Views/MyLearning/LearningHistory.cshtml | 2 +- .../Activity/IResourceActivityRepository.cs | 8 + .../Activity/ResourceActivityRepository.cs | 14 + .../Resources/ResourceVersionRepository.cs | 12 +- .../Services/IDashboardService.cs | 30 ++ .../Services/IMoodleApiService.cs | 7 + .../Services/DashboardService.cs | 258 +++++++++++++++++- .../Services/MoodleApiService.cs | 37 +++ .../Services/MyLearningService.cs | 90 +++--- .../Controllers/DashboardController.cs | 15 + 24 files changed, 924 insertions(+), 100 deletions(-) create mode 100644 LearningHub.Nhs.WebUI/Views/Home/_CertificateCard.cshtml create mode 100644 LearningHub.Nhs.WebUI/Views/Home/_LearningActivityCard.cshtml create mode 100644 LearningHub.Nhs.WebUI/Views/Home/_MyCoursesAndElearning.cshtml diff --git a/LearningHub.Nhs.WebUI/Controllers/HomeController.cs b/LearningHub.Nhs.WebUI/Controllers/HomeController.cs index 57c170ae6..a23e986e0 100644 --- a/LearningHub.Nhs.WebUI/Controllers/HomeController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/HomeController.cs @@ -203,30 +203,23 @@ public IActionResult HomepageWithAuthentication() /// /// Index. /// + /// The resource type. /// The my learning dashboard type. /// The resource dashboard type. /// The catalogue dashboard type. /// Home page. - public async Task Index(string myLearningDashboard = "my-in-progress", string resourceDashboard = "popular-resources", string catalogueDashboard = "popular-catalogues") + public async Task Index(string dashboardTrayLearningResourceType = "all", string myLearningDashboard = "my-in-progress", string resourceDashboard = "popular-resources", string catalogueDashboard = "popular-catalogues") { if (this.User?.Identity.IsAuthenticated == true) { this.Logger.LogInformation("User is authenticated: User is {fullname} and userId is: {lhuserid}", this.User.Identity.GetCurrentName(), this.User.Identity.GetCurrentUserId()); if (this.User.IsInRole("Administrator") || this.User.IsInRole("BlueUser") || this.User.IsInRole("ReadOnly") || this.User.IsInRole("BasicUser")) { - var learningTask = this.dashboardService.GetMyAccessLearningsAsync(myLearningDashboard, 1); + var learningTask = this.dashboardService.GetMyCoursesAndElearning(dashboardTrayLearningResourceType, myLearningDashboard, 1); var resourcesTask = this.dashboardService.GetResourcesAsync(resourceDashboard, 1); var cataloguesTask = this.dashboardService.GetCataloguesAsync(catalogueDashboard, 1); var userGroupsTask = this.userGroupService.UserHasCatalogueContributionPermission(); - var enrolledCoursesTask = Task.FromResult(new List()); - (bool enableMoodle, int currentMoodleUserId) = await this.GetMoodleFeatureStateAsync(); - - if (enableMoodle && myLearningDashboard == "my-enrolled-courses") - { - enrolledCoursesTask = this.dashboardService.GetEnrolledCoursesFromMoodleAsync(currentMoodleUserId, 1); - } - await Task.WhenAll(learningTask, resourcesTask, cataloguesTask, userGroupsTask); var model = new DashboardViewModel() @@ -234,7 +227,7 @@ public async Task Index(string myLearningDashboard = "my-in-progr MyLearnings = await learningTask, Resources = await resourcesTask, Catalogues = await cataloguesTask, - EnrolledCourses = await enrolledCoursesTask, + DashboardTrayLearningResourceType = dashboardTrayLearningResourceType, }; var userHasContributePermission = await userGroupsTask; this.ViewBag.userHasContributePermission = userHasContributePermission; @@ -261,6 +254,7 @@ public async Task Index(string myLearningDashboard = "my-in-progr /// /// Load the specified dashobard page. /// + /// dashboardTrayLearningResourceType. /// dashBoardTray. /// myLearningDashBoard. /// resourceDashBoard. @@ -268,8 +262,8 @@ public async Task Index(string myLearningDashboard = "my-in-progr /// pageNumber. /// Dashboard page. [Authorize] - [Route("/Home/loadpage/{dashBoardTray}/{myLearningDashBoard}/{resourceDashBoard}/{catalogueDashBoard}/{pageNumber:int}")] - public async Task LoadPage(string dashBoardTray = "my-learning", string myLearningDashBoard = "in-progress", string resourceDashBoard = "popular-resources", string catalogueDashBoard = "recent-catalogues", int pageNumber = 1) + [Route("/Home/loadpage/{dashboardTrayLearningResourceType}/{dashBoardTray}/{myLearningDashBoard}/{resourceDashBoard}/{catalogueDashBoard}/{pageNumber:int}")] + public async Task LoadPage(string dashboardTrayLearningResourceType = "all", string dashBoardTray = "my-learning", string myLearningDashBoard = "in-progress", string resourceDashBoard = "popular-resources", string catalogueDashBoard = "recent-catalogues", int pageNumber = 1) { if (this.User.IsInRole("Administrator") || this.User.IsInRole("BlueUser") || this.User.IsInRole("ReadOnly") || this.User.IsInRole("BasicUser")) { @@ -278,10 +272,9 @@ public async Task LoadPage(string dashBoardTray = "my-learning", MyLearnings = new Nhs.Models.Dashboard.DashboardMyLearningResponseViewModel { Type = myLearningDashBoard }, Resources = new Nhs.Models.Dashboard.DashboardResourceResponseViewModel { Type = resourceDashBoard }, Catalogues = new Nhs.Models.Dashboard.DashboardCatalogueResponseViewModel { Type = catalogueDashBoard }, + DashboardTrayLearningResourceType = dashboardTrayLearningResourceType, }; - (bool enableMoodle, int currentMoodleUserId) = await this.GetMoodleFeatureStateAsync(); - bool isAjax = this.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest"; if (isAjax) @@ -289,8 +282,8 @@ public async Task LoadPage(string dashBoardTray = "my-learning", switch (dashBoardTray) { case "my-learning": - model.MyLearnings = await this.dashboardService.GetMyAccessLearningsAsync(myLearningDashBoard, pageNumber); - return this.PartialView("_MyAccessedLearningTray", model); + model.MyLearnings = await this.dashboardService.GetMyCoursesAndElearning(dashboardTrayLearningResourceType, myLearningDashBoard, pageNumber); + return this.PartialView("_MyCoursesAndElearning", model); case "resources": model.Resources = await this.dashboardService.GetResourcesAsync(resourceDashBoard, pageNumber); return this.PartialView("_ResourceTray", model); @@ -301,13 +294,14 @@ public async Task LoadPage(string dashBoardTray = "my-learning", } else { - var learningTask = this.dashboardService.GetMyAccessLearningsAsync(myLearningDashBoard, dashBoardTray == "my-learning" ? pageNumber : 1); + var learningTask = this.dashboardService.GetMyCoursesAndElearning(dashboardTrayLearningResourceType, myLearningDashBoard, dashBoardTray == "my-learning" ? pageNumber : 1); var resourcesTask = this.dashboardService.GetResourcesAsync(resourceDashBoard, dashBoardTray == "resources" ? pageNumber : 1); var cataloguesTask = this.dashboardService.GetCataloguesAsync(catalogueDashBoard, dashBoardTray == "catalogues" ? pageNumber : 1); await Task.WhenAll(learningTask, resourcesTask, cataloguesTask); model.MyLearnings = await learningTask; model.Resources = await resourcesTask; model.Catalogues = await cataloguesTask; + model.DashboardTrayLearningResourceType = dashboardTrayLearningResourceType; return this.View("Dashboard", model); } } diff --git a/LearningHub.Nhs.WebUI/Interfaces/IDashboardService.cs b/LearningHub.Nhs.WebUI/Interfaces/IDashboardService.cs index 70a39d2fb..811dd1133 100644 --- a/LearningHub.Nhs.WebUI/Interfaces/IDashboardService.cs +++ b/LearningHub.Nhs.WebUI/Interfaces/IDashboardService.cs @@ -19,6 +19,15 @@ public interface IDashboardService /// A representing the result of the asynchronous operation. Task GetMyAccessLearningsAsync(string dashboardType, int pageNumber); + /// + /// GetResourcesAsync. + /// + /// The dashboardTrayLearningResource type. + /// The dashboard type. + /// The page Number. + /// A representing the result of the asynchronous operation. + Task GetMyCoursesAndElearning(string dashboardTrayLearningResourceType, string dashboardType, int pageNumber); + /// /// GetCataloguesAsync. /// diff --git a/LearningHub.Nhs.WebUI/Models/DashBoard/DashBoardPagingViewModel.cs b/LearningHub.Nhs.WebUI/Models/DashBoard/DashBoardPagingViewModel.cs index 7f29f8f86..5b477bae9 100644 --- a/LearningHub.Nhs.WebUI/Models/DashBoard/DashBoardPagingViewModel.cs +++ b/LearningHub.Nhs.WebUI/Models/DashBoard/DashBoardPagingViewModel.cs @@ -50,6 +50,11 @@ public class DashBoardPagingViewModel /// public int TotalCount { get; set; } + /// + /// Gets or sets the dashboard tray Learning resource type. + /// + public string DashboardTrayLearningResourceType { get; set; } + /// /// Gets the display message. /// diff --git a/LearningHub.Nhs.WebUI/Models/DashboardViewModel.cs b/LearningHub.Nhs.WebUI/Models/DashboardViewModel.cs index d7ddeda0c..24677a3c9 100644 --- a/LearningHub.Nhs.WebUI/Models/DashboardViewModel.cs +++ b/LearningHub.Nhs.WebUI/Models/DashboardViewModel.cs @@ -35,5 +35,10 @@ public DashboardViewModel() /// Gets or sets a list of enrolled courses to be displayed in the dashboard. /// public List EnrolledCourses { get; set; } + + /// + /// Gets or sets the dashboard tray Learning resource type. + /// + public string DashboardTrayLearningResourceType { get; set; } } } diff --git a/LearningHub.Nhs.WebUI/Services/DashboardService.cs b/LearningHub.Nhs.WebUI/Services/DashboardService.cs index bde127b81..d201da1f2 100644 --- a/LearningHub.Nhs.WebUI/Services/DashboardService.cs +++ b/LearningHub.Nhs.WebUI/Services/DashboardService.cs @@ -61,6 +61,36 @@ public async Task GetMyAccessLearningsAsyn return viewmodel; } + /// + /// GetCataloguesAsync. + /// + /// The dashboard Tray Learning Resource type. + /// The dashboard type. + /// The page Number. + /// A representing the result of the asynchronous operation. + public async Task GetMyCoursesAndElearning(string dashboardTrayLearningResourceType, string dashboardType, int pageNumber) + { + DashboardMyLearningResponseViewModel viewmodel = new DashboardMyLearningResponseViewModel { }; + + var client = await this.OpenApiHttpClient.GetClientAsync(); + + var request = $"dashboard/GetMyCoursesAndElearning/{dashboardTrayLearningResourceType}/{dashboardType}/{pageNumber}"; + var response = await client.GetAsync(request).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + viewmodel = JsonConvert.DeserializeObject(result); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + return viewmodel; + } + /// /// GetCataloguesAsync. /// diff --git a/LearningHub.Nhs.WebUI/Styles/nhsuk/layout.scss b/LearningHub.Nhs.WebUI/Styles/nhsuk/layout.scss index 196c1e44f..8e7b9a5ba 100644 --- a/LearningHub.Nhs.WebUI/Styles/nhsuk/layout.scss +++ b/LearningHub.Nhs.WebUI/Styles/nhsuk/layout.scss @@ -23,7 +23,32 @@ body { color: $color_nhsuk-white; } +.nhs-item-row { + display: flex; + justify-content: space-between; + align-items: center; +} +.nhs-progress-container { + display: flex; + height: 10px; + overflow: hidden; + line-height: 0; + font-size: 0.75rem; + background-color: #e9ecef; + border-radius: 0.25rem; +} +.nhs-progress-bar { + display: flex; + flex-direction: column; + justify-content: center; + overflow: hidden; + color: #fff; + text-align: center; + white-space: nowrap; + background-color: $nhsuk-green; + transition: width .6s ease; +} .nhsuk-width-container.app-width-container { max-width: px2rem(1208); margin: 0 auto; diff --git a/LearningHub.Nhs.WebUI/Views/Home/Dashboard.cshtml b/LearningHub.Nhs.WebUI/Views/Home/Dashboard.cshtml index e8481a4c7..4acd0c8c7 100644 --- a/LearningHub.Nhs.WebUI/Views/Home/Dashboard.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Home/Dashboard.cshtml @@ -34,7 +34,7 @@
- +
diff --git a/LearningHub.Nhs.WebUI/Views/Home/_CertificateCard.cshtml b/LearningHub.Nhs.WebUI/Views/Home/_CertificateCard.cshtml new file mode 100644 index 000000000..ed6b78ec1 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Views/Home/_CertificateCard.cshtml @@ -0,0 +1,84 @@ +@using LearningHub.Nhs.Models.Dashboard +@using LearningHub.Nhs.Models.Provider +@using LearningHub.Nhs.Models.MyLearning; +@using LearningHub.Nhs.Models.Enums +@using LearningHub.Nhs.WebUI.Extensions +@using LearningHub.Nhs.WebUI.Models +@using System.Linq +@using System.Collections.Generic; +@using LearningHub.Nhs.WebUI.Helpers +@inject LearningHub.Nhs.WebUI.Interfaces.IMoodleApiService moodleApiService; +@model Tuple + +@{ + string cardStyle = Model.Item1.Contains("my-learning") ? "card-provider-details--darkblank" : "card-provider-details--blank"; + var activityDate = Model.Item2.AwardedDate.Date; + var today = DateTime.Today; + var dateTimeText = activityDate == today ? "Today" + : activityDate == today.AddDays(-1) ? "Yesterday" + : activityDate.ToString("dd MMM yyyy"); + string GetMoodleCourseUrl(int courseId) + { + return moodleApiService.GetCourseUrl(courseId); + } +} +@functions { + public string CertificatePreviewUrl(int resourceReferenceId) => + Url.Action("Certificate", "MyLearning", new { resourceReferenceId }); + + public string DownloadCertificateUrl( + int resourceReferenceId, + int? majorVersion = 1, + int? minorVersion = 0 + ) => + Url.Action( + "DownloadCertificate", + "MyLearning", + new + { + resourceReferenceId, + majorVersion, + minorVersion, + } + ); +} +
+
+
+

+ + @if ((ResourceTypeEnum)Model.Item2.ResourceTypeId == ResourceTypeEnum.Moodle) + { + @Model.Item2.Title + } + else + { + @Model.Item2.Title + } +

+
+
+ + +
+
+ Type: + + + @UtilityHelper.GetPrettifiedResourceTypeName((ResourceTypeEnum)Model.Item2.ResourceTypeId) + +
+
+
+ + Awarded: + + + + @dateTimeText + +
+
+
+ @*
*@ +
diff --git a/LearningHub.Nhs.WebUI/Views/Home/_DashboardPaging.cshtml b/LearningHub.Nhs.WebUI/Views/Home/_DashboardPaging.cshtml index 0766be7c9..a3b287d72 100644 --- a/LearningHub.Nhs.WebUI/Views/Home/_DashboardPaging.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Home/_DashboardPaging.cshtml @@ -2,9 +2,9 @@ @model DashBoardPagingViewModel; @{ var pagingModel = Model; - var previousUrl = $"/home/loadpage/{@pagingModel.DashboardTrayType}/{@pagingModel.MyLearningDashboard}/{@pagingModel.ResourceDashboard}/{@pagingModel.CatalogueDashboard}/{@Model.PreviousPage}"; - var nextUrl = $"/home/loadpage/{@pagingModel.DashboardTrayType}/{@pagingModel.MyLearningDashboard}/{@pagingModel.ResourceDashboard}/{@pagingModel.CatalogueDashboard}/{@Model.NextPage}"; - var queryParams = $"/?myLearningDashboard={@pagingModel.MyLearningDashboard}&resourceDashboard={@pagingModel.ResourceDashboard}&catalogueDashboard={@pagingModel.CatalogueDashboard}#{@pagingModel.DashboardTrayType}"; + var previousUrl = $"/home/loadpage/{@pagingModel.DashboardTrayLearningResourceType}/{@pagingModel.DashboardTrayType}/{@pagingModel.MyLearningDashboard}/{@pagingModel.ResourceDashboard}/{@pagingModel.CatalogueDashboard}/{@Model.PreviousPage}"; + var nextUrl = $"/home/loadpage/{@pagingModel.DashboardTrayLearningResourceType}/{@pagingModel.DashboardTrayType}/{@pagingModel.MyLearningDashboard}/{@pagingModel.ResourceDashboard}/{@pagingModel.CatalogueDashboard}/{@Model.NextPage}"; + var queryParams = $"/?dashboardTrayLearningResourceType={@pagingModel.DashboardTrayLearningResourceType}&myLearningDashboard={@pagingModel.MyLearningDashboard}&resourceDashboard={@pagingModel.ResourceDashboard}&catalogueDashboard={@pagingModel.CatalogueDashboard}#{@pagingModel.DashboardTrayType}"; }