From 020de788a809d14749cd0e3fc3b58b228700a5a5 Mon Sep 17 00:00:00 2001 From: swapnamol-abraham Date: Thu, 19 Mar 2026 09:26:22 +0000 Subject: [PATCH 1/2] MIB Integration feature changes - TD-6547 # TD-6548 # TD-6549 --- .../Controllers/BaseController.cs | 6 + .../Controllers/CatalogueController.cs | 148 +++-- .../Helpers/TreeBuilderHelper.cs | 44 ++ .../Interfaces/IMoodleBridgeApiService.cs | 19 + .../LearningHub.Nhs.AdminUI.csproj | 2 +- .../LearningHub.Nhs.AdminUI.csproj.user | 2 +- .../ServiceCollectionExtension.cs | 1 + .../Services/MoodleBridgeApiService.cs | 62 ++ .../Views/Catalogue/MoodleCategory.cshtml | 19 +- ...rningHub.Nhs.WebUI.AutomatedUiTests.csproj | 2 +- .../Configuration/MoodleBridgeApiConfig.cs | 33 + .../Controllers/AccountController.cs | 6 +- .../Controllers/Api/MyLearningController.cs | 29 +- .../Controllers/BaseController.cs | 42 ++ .../Controllers/BookmarkController.cs | 6 +- .../Controllers/CatalogueController.cs | 77 ++- .../Controllers/ContributeController.cs | 6 +- .../ContributeResourceController.cs | 4 +- .../Controllers/FileController.cs | 6 +- .../Controllers/HomeController.cs | 10 +- .../Controllers/LoginWizardController.cs | 6 +- .../Controllers/MediaController.cs | 5 +- .../Controllers/MyAccountController.cs | 7 +- .../Controllers/MyLearningController.cs | 13 +- .../Controllers/NotificationController.cs | 4 +- .../Controllers/OfflineController.cs | 6 +- .../Controllers/OpenAthensController.cs | 5 +- .../Controllers/PoliciesController.cs | 6 +- .../Controllers/ReportsController.cs | 17 +- .../Controllers/ResourceController.cs | 5 +- .../Controllers/RoadMapController.cs | 7 +- .../Controllers/SearchController.cs | 4 +- .../Controllers/TrackingController.cs | 5 +- .../Controllers/UserController.cs | 6 +- .../Interfaces/ICategoryService.cs | 6 +- .../Interfaces/IDashboardService.cs | 4 +- .../Interfaces/IMoodleBridgeApiHttpClient.cs | 17 + .../Interfaces/IMoodleBridgeApiService.cs | 22 + .../Interfaces/IMyLearningService.cs | 10 +- .../LearningHub.Nhs.WebUI.csproj | 2 +- .../Catalogue/CatalogueIndexViewModel.cs | 2 +- .../Services/CategoryService.cs | 20 +- .../Services/DashboardService.cs | 18 +- .../Services/MoodleBridgeApiHttpClient.cs | 41 ++ .../Services/MoodleBridgeApiService.cs | 67 ++ .../Services/MyLearningService.cs | 36 +- .../Startup/ServiceMappings.cs | 1 + .../Views/Catalogue/Courses.cshtml | 4 +- .../Views/Catalogue/Index.cshtml | 8 +- .../Configuration/MoodleBridgeConfig.cs | 24 + .../LearningHub.Nhs.OpenApi.Models.csproj | 6 +- ....Nhs.OpenApi.Repositories.Interface.csproj | 2 +- ...earningHub.Nhs.OpenApi.Repositories.csproj | 2 +- .../CatalogueNodeVersionRepository.cs | 11 +- .../HttpClients/IMoodleBridgeHttpClient.cs | 25 + ...gHub.Nhs.OpenApi.Services.Interface.csproj | 2 +- .../Services/ICategoryService.cs | 2 +- .../Services/IDashboardService.cs | 11 +- .../Services/IMoodleBridgeApiService.cs | 82 +++ .../Services/IMyLearningService.cs | 6 +- .../Helpers/MoodleInstanceUsersHelper.cs | 47 ++ .../HttpClients/MoodleBridgeHttpClient.cs | 97 +++ .../LearningHub.Nhs.OpenApi.Services.csproj | 2 +- .../Services/CatalogueService.cs | 6 +- .../Services/CategoryService.cs | 4 +- .../Services/DashboardService.cs | 128 ++-- .../Services/MoodleApiService.cs | 2 +- .../Services/MoodleBridgeApiService.cs | 584 ++++++++++++++++++ .../Services/MyLearningService.cs | 237 +++---- .../Startup.cs | 2 + .../LearningHub.Nhs.OpenApi.Tests.csproj | 2 +- .../Configuration/ConfigurationExtensions.cs | 10 +- .../Controllers/CategoryController.cs | 13 +- .../Controllers/DashboardController.cs | 19 +- .../Controllers/MoodleBridgeController.cs | 51 ++ .../Controllers/MyLearningController.cs | 6 +- .../LearningHub.NHS.OpenAPI.csproj | 2 +- .../LearningHub.Nhs.OpenApi/appsettings.json | 4 + ...ub.Nhs.ReportApi.Services.Interface.csproj | 2 +- ...ub.Nhs.ReportApi.Services.UnitTests.csproj | 2 +- .../LearningHub.Nhs.ReportApi.Services.csproj | 2 +- .../LearningHub.Nhs.ReportApi.Shared.csproj | 2 +- .../LearningHub.Nhs.ReportApi.csproj | 2 +- .../LearningHub.Nhs.Api.csproj | 2 +- .../LearningHub.Nhs.Api.Shared.csproj | 2 +- .../LearningHub.Nhs.Api.UnitTests.csproj | 2 +- .../CatalogueNodeVersionCategoryCreate.sql | 36 +- .../CatalogueNodeVersionCategory.sql | 1 + ...earningHub.Nhs.Repository.Interface.csproj | 2 +- .../LearningHub.Nhs.Repository.csproj | 2 +- .../LearningHub.Nhs.Services.Interface.csproj | 2 +- .../LearningHub.Nhs.Services.UnitTests.csproj | 2 +- .../LearningHub.Nhs.Services.csproj | 2 +- ...earningHub.Nhs.Migration.ConsoleApp.csproj | 2 +- ...LearningHub.Nhs.Migration.Interface.csproj | 2 +- .../LearningHub.Nhs.Migration.Models.csproj | 2 +- ...ub.Nhs.Migration.Staging.Repository.csproj | 2 +- ...LearningHub.Nhs.Migration.UnitTests.csproj | 2 +- .../LearningHub.Nhs.Migration.csproj | 2 +- 99 files changed, 1902 insertions(+), 440 deletions(-) create mode 100644 AdminUI/LearningHub.Nhs.AdminUI/Helpers/TreeBuilderHelper.cs create mode 100644 AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IMoodleBridgeApiService.cs create mode 100644 AdminUI/LearningHub.Nhs.AdminUI/Services/MoodleBridgeApiService.cs create mode 100644 LearningHub.Nhs.WebUI/Configuration/MoodleBridgeApiConfig.cs create mode 100644 LearningHub.Nhs.WebUI/Interfaces/IMoodleBridgeApiHttpClient.cs create mode 100644 LearningHub.Nhs.WebUI/Interfaces/IMoodleBridgeApiService.cs create mode 100644 LearningHub.Nhs.WebUI/Services/MoodleBridgeApiHttpClient.cs create mode 100644 LearningHub.Nhs.WebUI/Services/MoodleBridgeApiService.cs create mode 100644 OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/MoodleBridgeConfig.cs create mode 100644 OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/HttpClients/IMoodleBridgeHttpClient.cs create mode 100644 OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMoodleBridgeApiService.cs create mode 100644 OpenAPI/LearningHub.Nhs.OpenApi.Services/Helpers/MoodleInstanceUsersHelper.cs create mode 100644 OpenAPI/LearningHub.Nhs.OpenApi.Services/HttpClients/MoodleBridgeHttpClient.cs create mode 100644 OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleBridgeApiService.cs create mode 100644 OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MoodleBridgeController.cs diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Controllers/BaseController.cs b/AdminUI/LearningHub.Nhs.AdminUI/Controllers/BaseController.cs index 90fd149ce..f1422eaee 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Controllers/BaseController.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/Controllers/BaseController.cs @@ -1,5 +1,6 @@ namespace LearningHub.Nhs.AdminUI.Controllers { + using LearningHub.Nhs.Models.Extensions; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; @@ -51,6 +52,11 @@ protected string WebRootPath } } + /// + /// Gets the CurrentUserEmail. + /// + protected string CurrentUserEmail => this.User.Identity.GetCurrentEmail(); + /// /// The OnActionExecuting. /// diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Controllers/CatalogueController.cs b/AdminUI/LearningHub.Nhs.AdminUI/Controllers/CatalogueController.cs index 508684668..25aa6cd4c 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Controllers/CatalogueController.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/Controllers/CatalogueController.cs @@ -1,11 +1,19 @@ -namespace LearningHub.Nhs.AdminUI.Controllers +using LearningHub.Nhs.Models.Databricks; +using Microsoft.AspNetCore.Mvc.Rendering; +using System.Net; + +namespace LearningHub.Nhs.AdminUI.Controllers { + using AngleSharp.Io; + using Azure; using LearningHub.Nhs.AdminUI.Configuration; using LearningHub.Nhs.AdminUI.Extensions; + using LearningHub.Nhs.AdminUI.Helpers; using LearningHub.Nhs.AdminUI.Interfaces; using LearningHub.Nhs.AdminUI.Models; using LearningHub.Nhs.Models.Catalogue; using LearningHub.Nhs.Models.Common; + using LearningHub.Nhs.Models.Databricks; using LearningHub.Nhs.Models.Moodle; using LearningHub.Nhs.Models.Paging; using LearningHub.Nhs.Models.Resource; @@ -70,6 +78,11 @@ public class CatalogueController : BaseController /// private readonly IMoodleApiService moodleApiService; + /// + /// Defines the moodleApiService. + /// + private readonly IMoodleBridgeApiService moodleBridgeApiService; + /// /// Defines the _settings. /// @@ -104,6 +117,7 @@ public class CatalogueController : BaseController /// The fileService. /// The providerService. /// The moodleApiService. + /// The moodleApiService. /// The logger. /// The options. /// The websettings. @@ -114,6 +128,7 @@ public CatalogueController( IFileService fileService, IProviderService providerService, IMoodleApiService moodleApiService, + IMoodleBridgeApiService moodleBridgeApiService, ILogger logger, IOptions options, IOptions websettings) @@ -124,6 +139,7 @@ public CatalogueController( this.fileService = fileService; this.providerService = providerService; this.moodleApiService = moodleApiService; + this.moodleBridgeApiService = moodleBridgeApiService; this.logger = logger; this.websettings = websettings; this.settings = options.Value; @@ -277,17 +293,9 @@ public async Task MoodleCategory(int id) return this.RedirectToAction("Error"); } - var categories = await this.moodleApiService.GetAllMoodleCategoriesAsync(); + var categoriesResult = await this.moodleBridgeApiService.GetAllMoodleCategoriesAsync(); - vm.MoodleCategories = categories; - - // Build hierarchical select list - var selectList = BuildList(categories, parentId: null, depth: 0); - foreach (var item in selectList) - { - item.Text = WebUtility.HtmlDecode(item.Text); - } - vm.MoodleCategorySelectList = new SelectList(selectList, "Value", "Text"); + vm.MoodleCategorySelectList = BuildMoodleCategorySelectList(categoriesResult); this.ViewData["CatalogueName"] = vm.Name; this.ViewData["id"] = id; @@ -727,7 +735,7 @@ public async Task AddUserGroupsToCatalogue(int catalogueNodeId, i [Route("AddCategoryToCatalogue")] public async Task AddCategoryToCatalogue(CatalogueViewModel catalogueViewModel) { - if (catalogueViewModel.SelectedCategoryId == 0) + if (string.IsNullOrEmpty(catalogueViewModel.SelectedCategoryId)) { this.ModelState.AddModelError("SelectedCategoryId", "Please select a category."); } @@ -736,17 +744,8 @@ public async Task AddCategoryToCatalogue(CatalogueViewModel catal var vr = await this.catalogueService.AddCategoryToCatalogue(vm); if (vr.Success) { - var categories = await this.moodleApiService.GetAllMoodleCategoriesAsync(); - vm.MoodleCategories = categories; - // Build hierarchical select list - var selectList = BuildList(categories, parentId: null, depth: 0); - - foreach (var item in selectList) - { - item.Text = WebUtility.HtmlDecode(item.Text); - } - - vm.MoodleCategorySelectList = new SelectList(selectList, "Value", "Text"); + var categories = await this.moodleBridgeApiService.GetAllMoodleCategoriesAsync(); + vm.MoodleCategorySelectList = BuildMoodleCategorySelectList(categories); return this.View("MoodleCategory", vm); } else @@ -764,23 +763,16 @@ public async Task AddCategoryToCatalogue(CatalogueViewModel catal /// The . [HttpGet] [Route("RemoveCategoryFromCatalogue/{categoryId}/{catalogueNodeVersionId}")] - public async Task RemoveCategoryFromCatalogue(int categoryId, int catalogueNodeVersionId) + public async Task RemoveCategoryFromCatalogue(string categoryId, int catalogueNodeVersionId) { var vm = await this.catalogueService.GetCatalogueAsync(catalogueNodeVersionId); vm.SelectedCategoryId = categoryId; var vr = await this.catalogueService.RemoveCategoryFromCatalogue(vm); if (vr.Success) { - var categories = await this.moodleApiService.GetAllMoodleCategoriesAsync(); - vm.MoodleCategories = categories; - vm.SelectedCategoryId = 0; - // Build hierarchical select list - var selectList = BuildList(categories, parentId: null, depth: 0); - foreach (var item in selectList) - { - item.Text = WebUtility.HtmlDecode(item.Text); - } - vm.MoodleCategorySelectList = new SelectList(selectList, "Value", "Text"); + var categories = await this.moodleBridgeApiService.GetAllMoodleCategoriesAsync(); + vm.MoodleCategorySelectList = BuildMoodleCategorySelectList(categories); + vm.SelectedCategoryId = null; return this.View("MoodleCategory", vm); } else @@ -1090,33 +1082,91 @@ private void ValidateCatalogueOwnerVm(CatalogueOwnerViewModel vm) } } - private List BuildList(IEnumerable allCategories, int? parentId, int depth) + public static SelectList BuildMoodleCategorySelectList(IEnumerable results) { var selectList = new List(); - // Handle both null and 0 as top-level depending on Moodle data - var children = allCategories - .Where(c => c.Parent == parentId || (parentId == null && (c.Parent == 0 || c.Parent == 0))) - .OrderBy(c => c.Name) - .ToList(); - - foreach (var child in children) + foreach (var result in results) { - // Indent with non-breaking spaces so browser keeps them - string indent = new string('\u00A0', depth * 3); + if (string.IsNullOrWhiteSpace(result.Instance)) + continue; + // Instance header selectList.Add(new SelectListItem { - Value = child.Id.ToString(), - Text = $"{indent}{child.Name}" + Value = "", + Text = result.Instance, + Disabled = true, + Selected = false }); - // Recursively add nested children - selectList.AddRange(BuildList(allCategories, child.Id, depth + 1)); + // Handle instance error + if (result.Error != null) + { + selectList.Add(new SelectListItem + { + Value = "", + Text = "\u00A0\u00A0[Category unavailable]", + Disabled = true, + Selected = false + }); + + continue; + } + + var categories = result.Data?.Categories; + if (categories == null || !categories.Any()) + continue; + + var tree = categories + .GroupBy(c => c.Parent) + .ToDictionary(g => g.Key, g => g.OrderBy(x => x.Name).ToList()); + + TreeBuilderHelper.BuildTree(selectList, tree, 0, 1, result.Instance); + } + + // Decode HTML entities + foreach (var item in selectList) + { + item.Text = WebUtility.HtmlDecode(item.Text); } - return selectList; + return new SelectList(selectList, "Value", "Text"); } + /// + /// + /// + /// + /// + /// + /// + + // Recursive tree builder with indentation + private static void BuildTree( + List selectList, + Dictionary> tree, + int parentId, + int depth, + string instance, + SelectListGroup group) + { + if (!tree.ContainsKey(parentId)) + return; + + foreach (var category in tree[parentId]) + { + string indent = new string('\u00A0', depth * 2); + + selectList.Add(new SelectListItem + { + Value = $"{instance}:{category.Id}", + Text = $"{indent}{category.Name}", + Group = group + }); + + BuildTree(selectList, tree, category.Id, depth + 1, instance, group); + } + } } } diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Helpers/TreeBuilderHelper.cs b/AdminUI/LearningHub.Nhs.AdminUI/Helpers/TreeBuilderHelper.cs new file mode 100644 index 000000000..dae4fc31f --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Helpers/TreeBuilderHelper.cs @@ -0,0 +1,44 @@ +namespace LearningHub.Nhs.AdminUI.Helpers +{ + using LearningHub.Nhs.Models.Moodle; + using Microsoft.AspNetCore.Mvc.Rendering; + using System.Collections.Generic; + + /// + /// Defines the . + /// + public static class TreeBuilderHelper + { + /// + /// BuildSelectListFromCategories. + /// + /// The selectList. + /// The tree. + /// The parentId. + /// The depth. + /// The instance. + public static void BuildTree( + List selectList, + Dictionary> tree, + int parentId, + int depth, + string instance) + { + if (!tree.ContainsKey(parentId)) + return; + + foreach (var category in tree[parentId]) + { + string indent = new string('\u00A0', depth * 2); + + selectList.Add(new SelectListItem + { + Value = $"{instance}:{category.Id}", + Text = $"{indent}{category.Name}" + }); + + BuildTree(selectList, tree, category.Id, depth + 1, instance); + } + } + } +} diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IMoodleBridgeApiService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IMoodleBridgeApiService.cs new file mode 100644 index 000000000..f5e25b1cf --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IMoodleBridgeApiService.cs @@ -0,0 +1,19 @@ +namespace LearningHub.Nhs.AdminUI.Interfaces +{ + using System.Collections.Generic; + using System.Threading.Tasks; + using LearningHub.Nhs.Models.Moodle; + using LearningHub.Nhs.Models.Moodle.API; + + /// + /// IMoodleBridgeApiService. + /// + public interface IMoodleBridgeApiService + { + /// + /// GetAllMoodleCategoriesAsync. + /// + /// List of MoodleCategory. + Task> GetAllMoodleCategoriesAsync(); + } +} diff --git a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj index a42f95f98..a8f070053 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj +++ b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj @@ -89,7 +89,7 @@ - + diff --git a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj.user b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj.user index 75a932fca..a753af4d7 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj.user +++ b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj.user @@ -4,7 +4,7 @@ ProjectDebugger - Local IIS + IIS Local MvcControllerEmptyScaffolder root/Common/MVC/Controller RazorViewEmptyScaffolder diff --git a/AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs b/AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs index 9137a55e7..8db722e30 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs @@ -107,6 +107,7 @@ public static void ConfigureServices(this IServiceCollection services, IConfigur services.AddTransient(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); // Configure Azure Search services.Configure(configuration.GetSection("AzureSearch")); diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Services/MoodleBridgeApiService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Services/MoodleBridgeApiService.cs new file mode 100644 index 000000000..92d0677cb --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Services/MoodleBridgeApiService.cs @@ -0,0 +1,62 @@ +namespace LearningHub.Nhs.AdminUI.Services +{ + using System; + using System.Collections.Generic; + using System.Threading.Tasks; + using LearningHub.Nhs.AdminUI.Configuration; + using LearningHub.Nhs.AdminUI.Interfaces; + using LearningHub.Nhs.Models.Moodle; + using LearningHub.Nhs.Models.Moodle.API; + using Microsoft.Extensions.Options; + using Newtonsoft.Json; + + /// + /// MoodleBridgeApiService. + /// + public class MoodleBridgeApiService : IMoodleBridgeApiService + { + private readonly IOpenApiHttpClient openApiHttpClient; + + /// + /// Initializes a new instance of the class. + /// + /// The Open Api Http Client. + public MoodleBridgeApiService(IOpenApiHttpClient openApiHttpClient) + { + this.openApiHttpClient = openApiHttpClient; + } + + /// + /// GetAllMoodleCategoriesAsync. + /// + /// A representing the result of the asynchronous operation. + public async Task> GetAllMoodleCategoriesAsync() + { + List viewmodel = new List(); + + try + { + var client = await this.openApiHttpClient.GetClientAsync(); + + var request = $"MoodleBridge/GetAllMoodleCategories"; + 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; + } + catch (Exception ex) + { + return viewmodel; + } + } + } +} diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Views/Catalogue/MoodleCategory.cshtml b/AdminUI/LearningHub.Nhs.AdminUI/Views/Catalogue/MoodleCategory.cshtml index 81ea1901d..a2116742b 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Views/Catalogue/MoodleCategory.cshtml +++ b/AdminUI/LearningHub.Nhs.AdminUI/Views/Catalogue/MoodleCategory.cshtml @@ -6,7 +6,8 @@ var page = CatalogueNavPage.Category; ViewData["Title"] = "Manage Category"; var selectedCategoryName = Model.MoodleCategorySelectList - .FirstOrDefault(c => c.Value == Model.SelectedCategoryId.ToString())?.Text; + .FirstOrDefault(c => c.Value == Model.SelectedCategoryId?.ToString())?.Text + ?? string.Empty; var errorHasOccurred = !ViewData.ModelState.IsValid; } @section SideMenu { @@ -40,7 +41,7 @@
- @if (Model.SelectedCategoryId > 0) + @if (Model.SelectedCategoryId != null) {
@@ -53,7 +54,7 @@
} -
+
@if (errorHasOccurred) { @@ -68,8 +69,18 @@
- + *@ + +
diff --git a/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj b/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj index 4c85e0949..23b92859c 100644 --- a/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj +++ b/LearningHub.Nhs.WebUI.AutomatedUiTests/LearningHub.Nhs.WebUI.AutomatedUiTests.csproj @@ -13,7 +13,7 @@ - + diff --git a/LearningHub.Nhs.WebUI/Configuration/MoodleBridgeApiConfig.cs b/LearningHub.Nhs.WebUI/Configuration/MoodleBridgeApiConfig.cs new file mode 100644 index 000000000..2e7e4b566 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Configuration/MoodleBridgeApiConfig.cs @@ -0,0 +1,33 @@ +namespace LearningHub.Nhs.WebUI.Configuration +{ + /// + /// The Moodle Bridge Settings. + /// + public class MoodleBridgeApiConfig + { + /////// + /////// Gets or sets the base url for the Moodle service. + /////// + ////public string BaseUrl { get; set; } = null!; + + /////// + /////// Gets or sets the Web service Rest Format. + /////// + ////public string MoodleWSRestFormat { get; set; } = null!; + + /////// + /////// Gets or sets the token. + /////// + ////public string WSToken { get; set; } = null!; + + /////// + /////// Gets or sets the token. + /////// + ////public string ApiPath { get; set; } = "webservice/rest/server.php"; + + /////// + /////// Gets or sets the token. + /////// + ////public string CoursePath { get; set; } = "course/view.php"; + } +} diff --git a/LearningHub.Nhs.WebUI/Controllers/AccountController.cs b/LearningHub.Nhs.WebUI/Controllers/AccountController.cs index 1309ff694..2d7c2901b 100644 --- a/LearningHub.Nhs.WebUI/Controllers/AccountController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/AccountController.cs @@ -67,6 +67,7 @@ public class AccountController : BaseController /// The specialtyService. /// The locationService. /// The gradeService. + /// The moodleBridgeApiService. public AccountController( IHttpClientFactory httpClientFactory, IWebHostEnvironment hostingEnvironment, @@ -82,8 +83,9 @@ public AccountController( IMultiPageFormService multiPageFormService, ISpecialtyService specialtyService, ILocationService locationService, - IGradeService gradeService) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + IGradeService gradeService, + IMoodleBridgeApiService moodleBridgeApiService) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.authConfig = authConfig; this.userService = userService; diff --git a/LearningHub.Nhs.WebUI/Controllers/Api/MyLearningController.cs b/LearningHub.Nhs.WebUI/Controllers/Api/MyLearningController.cs index 64b6de28d..3d92a22ca 100644 --- a/LearningHub.Nhs.WebUI/Controllers/Api/MyLearningController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/Api/MyLearningController.cs @@ -1,6 +1,7 @@ namespace LearningHub.Nhs.WebUI.Controllers.Api { using System.Threading.Tasks; + using LearningHub.Nhs.Models.Moodle; using LearningHub.Nhs.Models.MyLearning; using LearningHub.Nhs.WebUI.Helpers; using LearningHub.Nhs.WebUI.Interfaces; @@ -44,34 +45,6 @@ public async Task GetActivityDetailed([FromBody] MyLearningRequest return this.Ok(activity); } - /// - /// Gets the detailed activity data. - /// - /// The request model - filter settings. - /// The . - [HttpPost] - [Route("GetUserRecentMyLearningActivities")] - public async Task GetUserRecentMyLearningActivities([FromBody] MyLearningRequestModel requestModel) - { - var activity = await this.myLearningService.GetUserRecentMyLearningActivities(requestModel); - - return this.Ok(activity); - } - - /// - /// Gets the detailed activity data. - /// - /// The request model - filter settings. - /// The . - [HttpPost] - [Route("GetUserLearningHistory")] - public async Task GetUserLearningHistory([FromBody] MyLearningRequestModel requestModel) - { - var activity = await this.myLearningService.GetUserLearningHistory(requestModel); - - return this.Ok(activity); - } - /// /// Gets the played segment data for the progress modal in My Learning screen. /// diff --git a/LearningHub.Nhs.WebUI/Controllers/BaseController.cs b/LearningHub.Nhs.WebUI/Controllers/BaseController.cs index 6b3ad9a20..dd72350ec 100644 --- a/LearningHub.Nhs.WebUI/Controllers/BaseController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/BaseController.cs @@ -1,11 +1,16 @@ namespace LearningHub.Nhs.WebUI.Controllers { + using System.Collections.Generic; using System.Net.Http; + using System.Threading.Tasks; using LearningHub.Nhs.Models.Extensions; + using LearningHub.Nhs.Models.Moodle; + using LearningHub.Nhs.Models.Moodle.API; using LearningHub.Nhs.WebUI.Configuration; using LearningHub.Nhs.WebUI.Extensions; using LearningHub.Nhs.WebUI.Filters; using LearningHub.Nhs.WebUI.Helpers; + using LearningHub.Nhs.WebUI.Interfaces; using LearningHub.Nhs.WebUI.Models; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; @@ -20,25 +25,34 @@ public abstract class BaseController : Controller private readonly IWebHostEnvironment hostingEnvironment; private readonly IHttpClientFactory httpClientFactory; private readonly ILogger logger; + private readonly IMoodleBridgeApiService moodleBridgeApiService; private readonly Settings settings; private TenantViewModel currentTenant; + /// + /// The list of Moodle UserIds. + /// + private MoodleInstanceUserIdsViewModel moodleUserIds; + /// /// Initializes a new instance of the class. /// /// Hosting env. /// Http client factory. /// Logger. + /// moodleBridgeApiService. /// Settings. protected BaseController( IWebHostEnvironment hostingEnv, IHttpClientFactory httpClientFactory, ILogger logger, + IMoodleBridgeApiService moodleBridgeApiService, Settings settings) { this.hostingEnvironment = hostingEnv; this.httpClientFactory = httpClientFactory; this.logger = logger; + this.moodleBridgeApiService = moodleBridgeApiService; this.settings = settings; } @@ -82,6 +96,16 @@ protected BaseController( /// protected int CurrentMoodleUserId => this.User.Identity.GetMoodleUserId(); + /// + /// Gets the CurrentUserEmail. + /// + protected string CurrentUserEmail => this.User.Identity.GetCurrentEmail(); + + /// + /// Gets the MoodleInstanceUserIds. + /// + protected MoodleInstanceUserIdsViewModel MoodleInstanceUserIds => this.GetUserIdsPerInstances().Result; + /// /// The OnActionExecuting. /// @@ -92,6 +116,24 @@ public override void OnActionExecuting(Microsoft.AspNetCore.Mvc.Filters.ActionEx base.OnActionExecuting(context); } + /// + /// The get user ids and instances async. + /// + /// + /// The . + /// + public async Task GetUserIdsPerInstances() + { + if (this.moodleUserIds == null) + { + ////var moodleUserInstances = await this.moodleBridgeApiService.GetUserInstancesByEmail(this.CurrentUserEmail); + var moodleUserInstances = await this.moodleBridgeApiService.GetUserInstancesByEmail("binon.yesudhas@nhs.net"); + this.moodleUserIds = moodleUserInstances; + } + + return this.moodleUserIds; + } + /// /// The Initialise. /// diff --git a/LearningHub.Nhs.WebUI/Controllers/BookmarkController.cs b/LearningHub.Nhs.WebUI/Controllers/BookmarkController.cs index 0d699fe4d..f41f2cb9b 100644 --- a/LearningHub.Nhs.WebUI/Controllers/BookmarkController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/BookmarkController.cs @@ -33,13 +33,15 @@ public partial class BookmarkController : BaseController /// The settings. /// The httpClientFactory. /// bookmarkService. + /// moodleBridgeApiService. public BookmarkController( IWebHostEnvironment hostingEnvironment, ILogger logger, IOptions settings, IHttpClientFactory httpClientFactory, - IBookmarkService bookmarkService) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + IBookmarkService bookmarkService, + IMoodleBridgeApiService moodleBridgeApiService) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.bookmarkService = bookmarkService; } diff --git a/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs b/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs index b6c3e82f6..c8156e23e 100644 --- a/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs @@ -9,6 +9,8 @@ using LearningHub.Nhs.Caching; using LearningHub.Nhs.Models.Catalogue; using LearningHub.Nhs.Models.Dashboard; + using LearningHub.Nhs.Models.Databricks; + using LearningHub.Nhs.Models.Entities.Hierarchy; using LearningHub.Nhs.Models.Enums; using LearningHub.Nhs.Models.Hierarchy; using LearningHub.Nhs.Models.Moodle; @@ -19,6 +21,7 @@ using LearningHub.Nhs.WebUI.Interfaces; using LearningHub.Nhs.WebUI.Models.Catalogue; using LearningHub.Nhs.WebUI.Models.Search; + using LinqToTwitter; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; @@ -42,7 +45,7 @@ public class CatalogueController : BaseController private IUserService userService; private IUserGroupService userGroupService; private IHierarchyService hierarchyService; - private Settings settings; + private Configuration.Settings settings; /// /// Initializes a new instance of the class. @@ -60,21 +63,23 @@ public class CatalogueController : BaseController /// HierarchyService. /// userGroupService. /// categoryService. + /// moodleBridgeApiService. public CatalogueController( IHttpClientFactory httpClientFactory, IWebHostEnvironment hostingEnvironment, ILogger logger, ICatalogueService catalogueService, IUserService userService, - IOptions settings, + IOptions settings, LearningHubAuthServiceConfig authConfig, ISearchService searchService, ICacheService cacheService, IDashboardService dashboardService, IHierarchyService hierarchyService, IUserGroupService userGroupService, - ICategoryService categoryService) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + ICategoryService categoryService, + IMoodleBridgeApiService moodleBridgeApiService) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.authConfig = authConfig; this.catalogueService = catalogueService; @@ -192,13 +197,13 @@ public IActionResult CatalogueWithAuthentication(string reference) /// The tab name to display. /// The nodeId of the current folder. If not supplied, catalogue root contents are displayed. /// The SearchRequestViewModel. - /// The moodleCategoryId. + /// The moodleCategoryId. /// IActionResult. [AllowAnonymous] [ServiceFilter(typeof(SsoLoginFilterAttribute))] [HttpGet] [Route("catalogue/{reference}/{tab?}")] - public async Task IndexAsync(string reference, string tab, int? nodeId, SearchRequestViewModel search, int? moodleCategoryId) + public async Task IndexAsync(string reference, string tab, int? nodeId, SearchRequestViewModel search, string? categoryId) { if (tab == null || (tab == "search" && !this.User.Identity.IsAuthenticated)) { @@ -212,8 +217,9 @@ public async Task IndexAsync(string reference, string tab, int? n this.ViewBag.ActiveTab = tab; var catalogue = await this.catalogueService.GetCatalogueAsync(reference); - var catalogueCategoryId = await this.categoryService.GetCatalogueVersionCategoryAsync(catalogue.Id); - catalogue.SelectedCategoryId = catalogueCategoryId; + var catalogueCategory = await this.categoryService.GetCatalogueVersionCategoryAsync(catalogue.Id); + catalogue.SelectedCategoryId = catalogueCategory != null ? $"{catalogueCategory.InstanceName}:{catalogueCategory.CategoryId}" : null; + if (catalogue == null) { return this.RedirectToAction("Error", "Home"); @@ -270,22 +276,40 @@ public async Task IndexAsync(string reference, string tab, int? n bool includeEmptyFolder = viewModel.UserGroups.Any(x => x.RoleId == (int)RoleEnum.LocalAdmin || x.RoleId == (int)RoleEnum.Editor || x.RoleId == (int)RoleEnum.Previewer) || this.User.IsInRole("Administrator"); var nodeContents = await this.hierarchyService.GetNodeContentsForCatalogueBrowse(nodeId.Value, includeEmptyFolder); viewModel.NodeContents = nodeContents; - - int categoryId = moodleCategoryId ?? await this.categoryService.GetCatalogueVersionCategoryAsync(catalogue.Id); - if (categoryId > 0) + var catalogueNodeVersionCategory = await this.categoryService.GetCatalogueVersionCategoryAsync(catalogue.Id); + string moodleInstanceCategoryId = null; + if (categoryId != null) { - var response = await this.categoryService.GetCoursesByCategoryIdAsync(categoryId); - viewModel.Courses = response.Courses; - - var subCategories = await this.categoryService.GetSubCategoryByCategoryIdAsync(categoryId); - viewModel.SubCategories = subCategories; + moodleInstanceCategoryId = $"{catalogueNodeVersionCategory.InstanceName}:{categoryId}"; + } + else + { + moodleInstanceCategoryId = catalogueNodeVersionCategory != null ? $"{catalogueNodeVersionCategory.InstanceName}:{catalogueNodeVersionCategory.CategoryId}" : null; + } - if (moodleCategoryId.HasValue) + if (!string.IsNullOrEmpty(moodleInstanceCategoryId)) + { + var response = await this.categoryService.GetCoursesByCategoryIdAsync(moodleInstanceCategoryId); + viewModel.Courses = response?.Results? + .Where(r => r.Instance == catalogueNodeVersionCategory.InstanceName) + .SelectMany(r => r.Data?.Courses.Courses ?? new List()) + .ToList(); + + var subCategories = await this.categoryService.GetSubCategoryByCategoryIdAsync(moodleInstanceCategoryId); + viewModel.SubCategories = subCategories + .Where(x => x.Instance == catalogueNodeVersionCategory.InstanceName && + x.Data?.Categories != null && + x.Data.Categories.Count > 0) + .SelectMany(x => x.Data.Categories) + .ToList(); + if (moodleInstanceCategoryId != null) { var moodleCategories = await this.categoryService.GetAllMoodleCategoriesAsync(); + var (moodleInstanceName, moodleCategoryId) = moodleInstanceCategoryId.Split(':') is var p && p.Length == 2 ? (p[0], p[1]) : (null, null); + // Start with the selected category - var breadcrumbCategory = moodleCategories.FirstOrDefault(x => x.Id == moodleCategoryId); + var breadcrumbCategory = moodleCategories.FirstOrDefault(x => x.Id == Convert.ToInt32(moodleCategoryId)); List categories = new List(); categories.Insert(0, new MoodleCategory @@ -299,12 +323,6 @@ public async Task IndexAsync(string reference, string tab, int? n // Add the current category to the breadcrumb list categories.Insert(1, breadcrumbCategory); - // If there's no parent, stop - if (breadcrumbCategory.Parent == 0 || breadcrumbCategory.Parent == catalogueCategoryId) - { - break; - } - // Move up one level breadcrumbCategory = moodleCategories.FirstOrDefault(x => x.Id == breadcrumbCategory.Parent); } @@ -324,7 +342,7 @@ public async Task IndexAsync(string reference, string tab, int? n } else { - viewModel.Catalogue.SelectedCategoryId = 0; + viewModel.Catalogue.SelectedCategoryId = null; } if (tab == "search") @@ -373,9 +391,14 @@ public async Task IndexAsync(string reference, string tab, int? n [Route("GetCourses/{catalogueNodeVerstionId}/{reference}/{tab}")] public async Task GetCourses(int catalogueNodeVerstionId, string reference, string tab) { - var categoryId = await this.categoryService.GetCatalogueVersionCategoryAsync(catalogueNodeVerstionId); + var catalogueCategory = await this.categoryService.GetCatalogueVersionCategoryAsync(catalogueNodeVerstionId); + string categoryId = catalogueCategory.InstanceName + ":" + catalogueCategory.CategoryId; var response = await this.categoryService.GetCoursesByCategoryIdAsync(categoryId); - return this.PartialView("Courses", response.Courses); + var courses = response?.Results? + .Where(r => r.Instance == catalogueCategory.InstanceName) + .SelectMany(r => r.Data?.Courses.Courses ?? new List()) + .ToList(); + return this.PartialView("Courses", courses); } /// diff --git a/LearningHub.Nhs.WebUI/Controllers/ContributeController.cs b/LearningHub.Nhs.WebUI/Controllers/ContributeController.cs index 27ae615ce..e78a2c6b5 100644 --- a/LearningHub.Nhs.WebUI/Controllers/ContributeController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/ContributeController.cs @@ -44,6 +44,7 @@ public class ContributeController : BaseController /// Azure media service. /// Auth config. /// Contribure service. + /// moodleBridgeApiService. public ContributeController( IHttpClientFactory httpClientFactory, IWebHostEnvironment hostingEnvironment, @@ -55,8 +56,9 @@ public ContributeController( IResourceService resourceService, IAzureMediaService azureMediaService, LearningHubAuthServiceConfig authConfig, - IContributeService contributeService) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + IContributeService contributeService, + IMoodleBridgeApiService moodleBridgeApiService) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.authConfig = authConfig; diff --git a/LearningHub.Nhs.WebUI/Controllers/ContributeResourceController.cs b/LearningHub.Nhs.WebUI/Controllers/ContributeResourceController.cs index cd9ec928c..ea546cc5e 100644 --- a/LearningHub.Nhs.WebUI/Controllers/ContributeResourceController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/ContributeResourceController.cs @@ -39,14 +39,16 @@ public class ContributeResourceController : BaseController /// Http client factory. /// Logger. /// Settings. + /// moodleBridgeApiService. public ContributeResourceController( IResourceService resourceService, ICatalogueService catalogueService, IWebHostEnvironment hostingEnv, + IMoodleBridgeApiService moodleBridgeApiService, IHttpClientFactory httpClientFactory, ILogger logger, IOptions settings) - : base(hostingEnv, httpClientFactory, logger, settings.Value) + : base(hostingEnv, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.resourceService = resourceService; this.catalogueService = catalogueService; diff --git a/LearningHub.Nhs.WebUI/Controllers/FileController.cs b/LearningHub.Nhs.WebUI/Controllers/FileController.cs index e314d1525..5106aa645 100644 --- a/LearningHub.Nhs.WebUI/Controllers/FileController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/FileController.cs @@ -25,13 +25,15 @@ public class FileController : BaseController /// The settings. /// The httpClientFactory. /// The fileService. + /// moodleBridgeApiService. public FileController( IWebHostEnvironment hostingEnvironment, ILogger logger, IOptions settings, IHttpClientFactory httpClientFactory, - IFileService fileService) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + IFileService fileService, + IMoodleBridgeApiService moodleBridgeApiService) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.fileService = fileService; } diff --git a/LearningHub.Nhs.WebUI/Controllers/HomeController.cs b/LearningHub.Nhs.WebUI/Controllers/HomeController.cs index 5f4540b57..b9f2967c1 100644 --- a/LearningHub.Nhs.WebUI/Controllers/HomeController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/HomeController.cs @@ -50,6 +50,7 @@ public class HomeController : BaseController /// Http client factory. /// Hosting environment. /// Logger. + /// moodleBridgeApiService. /// Settings. /// User service. /// Resource service. @@ -62,6 +63,7 @@ public class HomeController : BaseController public HomeController( IHttpClientFactory httpClientFactory, IWebHostEnvironment hostingEnvironment, + IMoodleBridgeApiService moodleBridgeApiService, ILogger logger, IOptions settings, IUserService userService, @@ -72,7 +74,7 @@ public HomeController( IFeatureManager featureManager, IUserGroupService userGroupService, Microsoft.Extensions.Configuration.IConfiguration configuration) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.authConfig = authConfig; this.userService = userService; @@ -215,7 +217,7 @@ public async Task Index(string dashboardTrayLearningResourceType 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.GetMyCoursesAndElearning(dashboardTrayLearningResourceType, myLearningDashboard, 1); + var learningTask = this.dashboardService.GetMyCoursesAndElearning(dashboardTrayLearningResourceType, myLearningDashboard, this.CurrentUserEmail, 1); var resourcesTask = this.dashboardService.GetResourcesAsync(resourceDashboard, 1); var cataloguesTask = this.dashboardService.GetCataloguesAsync(catalogueDashboard, 1); var userGroupsTask = this.userGroupService.UserHasCatalogueContributionPermission(); @@ -282,7 +284,7 @@ public async Task LoadPage(string dashboardTrayLearningResourceTy switch (dashBoardTray) { case "my-learning": - model.MyLearnings = await this.dashboardService.GetMyCoursesAndElearning(dashboardTrayLearningResourceType, myLearningDashBoard, pageNumber); + model.MyLearnings = await this.dashboardService.GetMyCoursesAndElearning(dashboardTrayLearningResourceType, myLearningDashBoard, this.CurrentUserEmail, pageNumber); return this.PartialView("_MyCoursesAndElearning", model); case "resources": model.Resources = await this.dashboardService.GetResourcesAsync(resourceDashBoard, pageNumber); @@ -294,7 +296,7 @@ public async Task LoadPage(string dashboardTrayLearningResourceTy } else { - var learningTask = this.dashboardService.GetMyCoursesAndElearning(dashboardTrayLearningResourceType, myLearningDashBoard, dashBoardTray == "my-learning" ? pageNumber : 1); + var learningTask = this.dashboardService.GetMyCoursesAndElearning(dashboardTrayLearningResourceType, myLearningDashBoard, this.CurrentUserEmail, 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); diff --git a/LearningHub.Nhs.WebUI/Controllers/LoginWizardController.cs b/LearningHub.Nhs.WebUI/Controllers/LoginWizardController.cs index 2ffc17e13..f1bc5c20d 100644 --- a/LearningHub.Nhs.WebUI/Controllers/LoginWizardController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/LoginWizardController.cs @@ -60,6 +60,7 @@ public class LoginWizardController : BaseController /// The specialtyService. /// The locationService. /// The gradeService. + /// moodleBridgeApiService. public LoginWizardController( IHttpClientFactory httpClientFactory, IWebHostEnvironment hostingEnvironment, @@ -75,8 +76,9 @@ public LoginWizardController( IMultiPageFormService multiPageFormService, ISpecialtyService specialtyService, ILocationService locationService, - IGradeService gradeService) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + IGradeService gradeService, + IMoodleBridgeApiService moodleBridgeApiService) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.userService = userService; this.termsAndConditionService = termsAndConditionService; diff --git a/LearningHub.Nhs.WebUI/Controllers/MediaController.cs b/LearningHub.Nhs.WebUI/Controllers/MediaController.cs index 4acd69e07..537fb5844 100644 --- a/LearningHub.Nhs.WebUI/Controllers/MediaController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/MediaController.cs @@ -26,8 +26,9 @@ public class MediaController : BaseController /// Settings. /// Http client factory. /// Azure media services. - public MediaController(IWebHostEnvironment hostingEnvironment, ILogger logger, IOptions settings, IHttpClientFactory httpClientFactory, IAzureMediaService azureMediaService) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + /// moodleBridgeApiService. + public MediaController(IWebHostEnvironment hostingEnvironment, ILogger logger, IOptions settings, IHttpClientFactory httpClientFactory, IAzureMediaService azureMediaService, IMoodleBridgeApiService moodleBridgeApiService) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.azureMediaService = azureMediaService; this.logger = logger; diff --git a/LearningHub.Nhs.WebUI/Controllers/MyAccountController.cs b/LearningHub.Nhs.WebUI/Controllers/MyAccountController.cs index a91718384..bb24c03f8 100644 --- a/LearningHub.Nhs.WebUI/Controllers/MyAccountController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/MyAccountController.cs @@ -46,12 +46,14 @@ public partial class MyAccountController : BaseController private readonly ILocationService locationService; private readonly ICacheService cacheService; private readonly IConfiguration configuration; + private readonly IMoodleBridgeApiService moodleBridgeApiService; /// /// Initializes a new instance of the class. /// /// The hostingEnvironment. /// The logger. + /// moodleBridgeApiService. /// The settings. /// The httpClientFactory. /// userService. @@ -80,8 +82,9 @@ public MyAccountController( ILocationService locationService, IMultiPageFormService multiPageFormService, ICacheService cacheService, - IConfiguration configuration) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + IConfiguration configuration, + IMoodleBridgeApiService moodleBridgeApiService) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.userService = userService; this.loginWizardService = loginWizardService; diff --git a/LearningHub.Nhs.WebUI/Controllers/MyLearningController.cs b/LearningHub.Nhs.WebUI/Controllers/MyLearningController.cs index 3dc2fe732..9e8dc29c8 100644 --- a/LearningHub.Nhs.WebUI/Controllers/MyLearningController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/MyLearningController.cs @@ -53,8 +53,9 @@ public class MyLearningController : BaseController /// user Service. /// PDF Report Service. /// fileService. - public MyLearningController(IWebHostEnvironment hostingEnvironment, ILogger logger, IOptions settings, IHttpClientFactory httpClientFactory, IMyLearningService myLearningService, IResourceService resourceService, IHierarchyService hierarchyService, IUserService userService, IPDFReportService pdfReportService, IFileService fileService) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + /// moodleBridgeApiService. + public MyLearningController(IWebHostEnvironment hostingEnvironment, IMoodleBridgeApiService moodleBridgeApiService, ILogger logger, IOptions settings, IHttpClientFactory httpClientFactory, IMyLearningService myLearningService, IResourceService resourceService, IHierarchyService hierarchyService, IUserService userService, IPDFReportService pdfReportService, IFileService fileService) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.myLearningService = myLearningService; this.resourceService = resourceService; @@ -227,7 +228,7 @@ public async Task Index(MyLearningUserActivitiesViewModel learnin break; } - var result = await this.myLearningService.GetUserRecentMyLearningActivities(myLearningRequestModel); + var result = await this.myLearningService.GetUserRecentMyLearningActivities(myLearningRequestModel, this.MoodleInstanceUserIds); var response = new MyLearningUserActivitiesViewModel(myLearningRequestModel); if (result != null) @@ -374,7 +375,7 @@ public async Task LearningHistory(MyLearningUserActivitiesViewMod break; } - var result = await this.myLearningService.GetUserLearningHistory(myLearningRequestModel); + var result = await this.myLearningService.GetUserLearningHistory(myLearningRequestModel, this.MoodleInstanceUserIds); var response = new MyLearningUserActivitiesViewModel(myLearningRequestModel); if (result != null) @@ -457,7 +458,7 @@ public async Task DownloadActivities(MyLearningRequestModel myLea filter.Take = 999; var userDetails = await this.userService.GetCurrentUserBasicDetailsAsync(); var response = new MyLearningUserActivitiesViewModel(); - var result = await this.myLearningService.GetUserLearningHistory(filter); + var result = await this.myLearningService.GetUserLearningHistory(filter, this.MoodleInstanceUserIds); if (result != null) { response.TotalCount = result.TotalCount; @@ -611,7 +612,7 @@ public async Task Certificates(MyLearningUserCertificatesViewMode break; } - var result = await this.myLearningService.GetUserCertificateDetails(myLearningRequestModel); + var result = await this.myLearningService.GetUserCertificateDetails(myLearningRequestModel, this.MoodleInstanceUserIds); var response = new MyLearningUserCertificatesViewModel(myLearningRequestModel); if (result != null) diff --git a/LearningHub.Nhs.WebUI/Controllers/NotificationController.cs b/LearningHub.Nhs.WebUI/Controllers/NotificationController.cs index c5013e07f..627154c03 100644 --- a/LearningHub.Nhs.WebUI/Controllers/NotificationController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/NotificationController.cs @@ -32,13 +32,15 @@ public class NotificationController : BaseController /// Settings. /// Notification service. /// Logger. + /// moodleBridgeApiService. public NotificationController( IHttpClientFactory httpClientFactory, IWebHostEnvironment hostingEnvironment, IOptions settings, INotificationService notificationService, + IMoodleBridgeApiService moodleBridgeApiService, ILogger logger) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.notificationService = notificationService; } diff --git a/LearningHub.Nhs.WebUI/Controllers/OfflineController.cs b/LearningHub.Nhs.WebUI/Controllers/OfflineController.cs index 178fa5c0b..4283d3279 100644 --- a/LearningHub.Nhs.WebUI/Controllers/OfflineController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/OfflineController.cs @@ -26,13 +26,15 @@ public class OfflineController : BaseController /// The logger. /// The settings. /// The internalSystemService. + /// moodleBridgeApiService. public OfflineController( IHttpClientFactory httpClientFactory, IWebHostEnvironment hostingEnvironment, ILogger logger, IOptions settings, - IInternalSystemService internalSystemService) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + IInternalSystemService internalSystemService, + IMoodleBridgeApiService moodleBridgeApiService) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.internalSystemService = internalSystemService; } diff --git a/LearningHub.Nhs.WebUI/Controllers/OpenAthensController.cs b/LearningHub.Nhs.WebUI/Controllers/OpenAthensController.cs index f046d8680..2ec1a4c4f 100644 --- a/LearningHub.Nhs.WebUI/Controllers/OpenAthensController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/OpenAthensController.cs @@ -23,6 +23,7 @@ public class OpenAthensController : BaseController { private readonly IUserService userService; private readonly LearningHubAuthServiceConfig authConfig; + private readonly IMoodleBridgeApiService moodleBridgeApiService; /// /// Initializes a new instance of the class. @@ -33,14 +34,16 @@ public class OpenAthensController : BaseController /// The env. /// The http client factory. /// The settings. + /// moodleBridgeApiService. public OpenAthensController( ILogger logger, IUserService userService, + IMoodleBridgeApiService moodleBridgeApiService, LearningHubAuthServiceConfig authConfig, IWebHostEnvironment env, IHttpClientFactory httpClientFactory, IOptions settings) - : base(env, httpClientFactory, logger, settings.Value) + : base(env, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.userService = userService; this.authConfig = authConfig; diff --git a/LearningHub.Nhs.WebUI/Controllers/PoliciesController.cs b/LearningHub.Nhs.WebUI/Controllers/PoliciesController.cs index 9f619e572..ef5c6e300 100644 --- a/LearningHub.Nhs.WebUI/Controllers/PoliciesController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/PoliciesController.cs @@ -25,13 +25,15 @@ public class PoliciesController : BaseController /// Logger. /// Settings. /// Terms and conditions service. + /// moodleBridgeApiService. public PoliciesController( IHttpClientFactory httpClientFactory, IWebHostEnvironment hostingEnvironment, ILogger logger, IOptions settings, - ITermsAndConditionsService termsAndConditionsService) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + ITermsAndConditionsService termsAndConditionsService, + IMoodleBridgeApiService moodleBridgeApiService) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.termsAndConditionsService = termsAndConditionsService; } diff --git a/LearningHub.Nhs.WebUI/Controllers/ReportsController.cs b/LearningHub.Nhs.WebUI/Controllers/ReportsController.cs index 4cda20cb7..c67c7a6b8 100644 --- a/LearningHub.Nhs.WebUI/Controllers/ReportsController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/ReportsController.cs @@ -37,6 +37,7 @@ public class ReportsController : BaseController private readonly IMultiPageFormService multiPageFormService; private readonly IReportService reportService; private readonly IFileService fileService; + private readonly IMoodleBridgeApiService moodleBridgeApiService; /// /// Initializes a new instance of the class. @@ -50,8 +51,9 @@ public class ReportsController : BaseController /// The hostingEnvironment. /// The logger. /// settings. - public ReportsController(IHttpClientFactory httpClientFactory, IWebHostEnvironment hostingEnvironment, ILogger logger, IOptions settings, ICacheService cacheService, IMultiPageFormService multiPageFormService, IReportService reportService, ICategoryService categoryService, IFileService fileService) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + /// moodleBridgeApiService. + public ReportsController(IHttpClientFactory httpClientFactory, IWebHostEnvironment hostingEnvironment, IMoodleBridgeApiService moodleBridgeApiService, ILogger logger, IOptions settings, ICacheService cacheService, IMultiPageFormService multiPageFormService, IReportService reportService, ICategoryService categoryService, IFileService fileService) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.cacheService = cacheService; this.multiPageFormService = multiPageFormService; @@ -434,14 +436,15 @@ public async Task CourseProgressReport(CourseCompletionViewModel private async Task>> GetCoursesAsync() { - int categoryId = this.Settings.StatMandId; + ////int categoryId = this.Settings.StatMandId; + string categoryId = "test"; var courses = new List>(); var subCategories = await this.categoryService.GetCoursesByCategoryIdAsync(categoryId); - foreach (var subCategory in subCategories.Courses) - { - courses.Add(new KeyValuePair(subCategory.Id.ToString(), UtilityHelper.ConvertToSentenceCase(subCategory.Displayname))); - } + ////foreach (var subCategory in subCategories.Courses) + ////{ + //// courses.Add(new KeyValuePair(subCategory.Id.ToString(), UtilityHelper.ConvertToSentenceCase(subCategory.Displayname))); + ////} return courses; } diff --git a/LearningHub.Nhs.WebUI/Controllers/ResourceController.cs b/LearningHub.Nhs.WebUI/Controllers/ResourceController.cs index 5df61185e..00d1f0f74 100644 --- a/LearningHub.Nhs.WebUI/Controllers/ResourceController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/ResourceController.cs @@ -21,6 +21,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.StaticFiles; + using Microsoft.Azure.Management.Media.Models; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.FeatureManagement; @@ -63,6 +64,7 @@ public class ResourceController : BaseController /// The fileService. /// The cacheService. /// The Feature flag manager. + /// moodleBridgeApiService. public ResourceController( IWebHostEnvironment hostingEnvironment, ILogger logger, @@ -79,8 +81,9 @@ public ResourceController( IHierarchyService hierarchyService, IFileService fileService, ICacheService cacheService, + IMoodleBridgeApiService moodleBridgeApiService, IFeatureManager featureManager) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.azureMediaService = azureMediaService; this.resourceService = resourceService; diff --git a/LearningHub.Nhs.WebUI/Controllers/RoadMapController.cs b/LearningHub.Nhs.WebUI/Controllers/RoadMapController.cs index b9bcf8a22..d34e1f280 100644 --- a/LearningHub.Nhs.WebUI/Controllers/RoadMapController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/RoadMapController.cs @@ -1,6 +1,7 @@ namespace LearningHub.Nhs.WebUI.Controllers { using System.Net.Http; + using LearningHub.Nhs.WebUI.Interfaces; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; @@ -11,6 +12,8 @@ /// public class RoadMapController : BaseController { + private readonly IMoodleBridgeApiService moodleBridgeApiService; + /// /// Initializes a new instance of the class. /// @@ -18,12 +21,14 @@ public class RoadMapController : BaseController /// Http client factory. /// Logger. /// Settings. + /// moodleBridgeApiService. public RoadMapController( IWebHostEnvironment hostingEnvironment, + IMoodleBridgeApiService moodleBridgeApiService, IHttpClientFactory httpClientFactory, ILogger logger, IOptions settings) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { } diff --git a/LearningHub.Nhs.WebUI/Controllers/SearchController.cs b/LearningHub.Nhs.WebUI/Controllers/SearchController.cs index 074bc39ab..3f4cf8766 100644 --- a/LearningHub.Nhs.WebUI/Controllers/SearchController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/SearchController.cs @@ -42,6 +42,7 @@ public class SearchController : BaseController /// The logger. /// The fileService. /// The Feature flag manager. + /// moodleBridgeApiService. public SearchController( IHttpClientFactory httpClientFactory, IWebHostEnvironment hostingEnvironment, @@ -49,8 +50,9 @@ public SearchController( ISearchService searchService, ILogger logger, IFileService fileService, + IMoodleBridgeApiService moodleBridgeApiService, IFeatureManager featureManager) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.searchService = searchService; this.fileService = fileService; diff --git a/LearningHub.Nhs.WebUI/Controllers/TrackingController.cs b/LearningHub.Nhs.WebUI/Controllers/TrackingController.cs index 4463faf73..a65d56864 100644 --- a/LearningHub.Nhs.WebUI/Controllers/TrackingController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/TrackingController.cs @@ -14,6 +14,7 @@ namespace LearningHub.Nhs.WebUI.Controllers public class TrackingController : BaseController { private readonly IJsDetectionLogger jsDetectionLogger; + private readonly IMoodleBridgeApiService moodleBridgeApiService; /// /// Initializes a new instance of the class. @@ -23,13 +24,15 @@ public class TrackingController : BaseController /// The settings. /// The logger. /// The JsDetectionLogger. + /// moodleBridgeApiService. public TrackingController( IHttpClientFactory httpClientFactory, IWebHostEnvironment hostingEnvironment, + IMoodleBridgeApiService moodleBridgeApiService, IOptions settings, ILogger logger, IJsDetectionLogger jsDetectionLogger) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.jsDetectionLogger = jsDetectionLogger; } diff --git a/LearningHub.Nhs.WebUI/Controllers/UserController.cs b/LearningHub.Nhs.WebUI/Controllers/UserController.cs index 284c2a0b9..75307e7fe 100644 --- a/LearningHub.Nhs.WebUI/Controllers/UserController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/UserController.cs @@ -64,6 +64,7 @@ public partial class UserController : BaseController /// countryService. /// regionService. /// The multiPageFormService. + /// moodleBridgeApiService. public UserController( IWebHostEnvironment hostingEnvironment, ILogger logger, @@ -73,8 +74,9 @@ public UserController( ILoginWizardService loginWizardService, ICountryService countryService, IRegionService regionService, - IMultiPageFormService multiPageFormService) - : base(hostingEnvironment, httpClientFactory, logger, settings.Value) + IMultiPageFormService multiPageFormService, + IMoodleBridgeApiService moodleBridgeApiService) + : base(hostingEnvironment, httpClientFactory, logger, moodleBridgeApiService, settings.Value) { this.userService = userService; this.loginWizardService = loginWizardService; diff --git a/LearningHub.Nhs.WebUI/Interfaces/ICategoryService.cs b/LearningHub.Nhs.WebUI/Interfaces/ICategoryService.cs index 37e87d072..d3e0c4c5a 100644 --- a/LearningHub.Nhs.WebUI/Interfaces/ICategoryService.cs +++ b/LearningHub.Nhs.WebUI/Interfaces/ICategoryService.cs @@ -18,21 +18,21 @@ public interface ICategoryService /// /// catalogueNodeVersionId. /// A representing the result of the asynchronous operation. - Task GetCatalogueVersionCategoryAsync(int catalogueNodeVersionId); + Task GetCatalogueVersionCategoryAsync(int catalogueNodeVersionId); /// /// GetCoursesByCategoryIdAsync. /// /// categoryId. /// A representing the result of the asynchronous operation. - Task GetCoursesByCategoryIdAsync(int categoryId); + Task GetCoursesByCategoryIdAsync(string categoryId); /// /// GetSubCategoryByCategoryIdAsync. /// /// categoryId. /// A representing the result of the asynchronous operation. - Task> GetSubCategoryByCategoryIdAsync(int categoryId); + Task> GetSubCategoryByCategoryIdAsync(string categoryId); /// /// GetAllMoodleCategoriesAsync. diff --git a/LearningHub.Nhs.WebUI/Interfaces/IDashboardService.cs b/LearningHub.Nhs.WebUI/Interfaces/IDashboardService.cs index 811dd1133..d4ce69b83 100644 --- a/LearningHub.Nhs.WebUI/Interfaces/IDashboardService.cs +++ b/LearningHub.Nhs.WebUI/Interfaces/IDashboardService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using LearningHub.Nhs.Models.Dashboard; + using LearningHub.Nhs.Models.Moodle; using LearningHub.Nhs.Models.Moodle.API; using LearningHub.Nhs.WebUI.Models; @@ -24,9 +25,10 @@ public interface IDashboardService /// /// The dashboardTrayLearningResource type. /// The dashboard type. + /// The email. /// The page Number. /// A representing the result of the asynchronous operation. - Task GetMyCoursesAndElearning(string dashboardTrayLearningResourceType, string dashboardType, int pageNumber); + Task GetMyCoursesAndElearning(string dashboardTrayLearningResourceType, string dashboardType, string email, int pageNumber); /// /// GetCataloguesAsync. diff --git a/LearningHub.Nhs.WebUI/Interfaces/IMoodleBridgeApiHttpClient.cs b/LearningHub.Nhs.WebUI/Interfaces/IMoodleBridgeApiHttpClient.cs new file mode 100644 index 000000000..bbf712b87 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Interfaces/IMoodleBridgeApiHttpClient.cs @@ -0,0 +1,17 @@ +namespace LearningHub.Nhs.WebUI.Interfaces +{ + using System.Net.Http; + using System.Threading.Tasks; + + /// + /// The OpenApiHttpClient interface. + /// + public interface IMoodleBridgeApiHttpClient + { + /// + /// The get client. + /// + /// The . + Task GetClientAsync(); + } +} diff --git a/LearningHub.Nhs.WebUI/Interfaces/IMoodleBridgeApiService.cs b/LearningHub.Nhs.WebUI/Interfaces/IMoodleBridgeApiService.cs new file mode 100644 index 000000000..e316bbf84 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Interfaces/IMoodleBridgeApiService.cs @@ -0,0 +1,22 @@ +namespace LearningHub.Nhs.WebUI.Interfaces +{ + using System.Collections.Generic; + using System.Threading.Tasks; + using LearningHub.Nhs.Models.Moodle; + using LearningHub.Nhs.Models.Moodle.API; + using LearningHub.Nhs.WebUI.Models; + using MoodleCourseCompletionModel = LearningHub.Nhs.Models.Moodle.API.MoodleCourseCompletionModel; + + /// + /// IMoodleApiService. + /// + public interface IMoodleBridgeApiService + { + /// + /// GetUserInstancesByEmailAsync. + /// + /// The email. + /// A representing the result of the asynchronous operation. + Task GetUserInstancesByEmail(string email); + } +} diff --git a/LearningHub.Nhs.WebUI/Interfaces/IMyLearningService.cs b/LearningHub.Nhs.WebUI/Interfaces/IMyLearningService.cs index e9b584cc4..3a415f9fb 100644 --- a/LearningHub.Nhs.WebUI/Interfaces/IMyLearningService.cs +++ b/LearningHub.Nhs.WebUI/Interfaces/IMyLearningService.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; + using LearningHub.Nhs.Models.Moodle; using LearningHub.Nhs.Models.MyLearning; /// @@ -21,15 +22,17 @@ public interface IMyLearningService /// Gets the user recent my leraning activities.. /// /// The request model. + /// The moodleInstanceUserIds. /// The . - Task GetUserRecentMyLearningActivities(MyLearningRequestModel requestModel); + Task GetUserRecentMyLearningActivities(MyLearningRequestModel requestModel, MoodleInstanceUserIdsViewModel moodleInstanceUserIds); /// /// Gets the user leraning history. /// /// The request model. + /// The moodleInstanceUserIds. /// The . - Task GetUserLearningHistory(MyLearningRequestModel requestModel); + Task GetUserLearningHistory(MyLearningRequestModel requestModel, MoodleInstanceUserIdsViewModel moodleInstanceUserIds); /// /// Gets the played segment data for the progress modal in My Learning screen. @@ -53,8 +56,9 @@ public interface IMyLearningService /// Gets the user certificates. /// /// The request model. + /// The moodleInstanceUserIds. /// The . - Task GetUserCertificateDetails(MyLearningRequestModel requestModel); + Task GetUserCertificateDetails(MyLearningRequestModel requestModel, MoodleInstanceUserIdsViewModel moodleInstanceUserIds); /// /// Gets the resource URL for a given resource reference ID. diff --git a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj index c8016ba86..f0521282a 100644 --- a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj +++ b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj @@ -112,7 +112,7 @@ - + diff --git a/LearningHub.Nhs.WebUI/Models/Catalogue/CatalogueIndexViewModel.cs b/LearningHub.Nhs.WebUI/Models/Catalogue/CatalogueIndexViewModel.cs index 51c66fde4..1d9617c5a 100644 --- a/LearningHub.Nhs.WebUI/Models/Catalogue/CatalogueIndexViewModel.cs +++ b/LearningHub.Nhs.WebUI/Models/Catalogue/CatalogueIndexViewModel.cs @@ -57,7 +57,7 @@ public class CatalogueIndexViewModel /// /// Gets or sets the courses in the catalogue. /// - public List SubCategories { get; set; } + public List SubCategories { get; set; } /// /// Gets or sets the moodle categories. diff --git a/LearningHub.Nhs.WebUI/Services/CategoryService.cs b/LearningHub.Nhs.WebUI/Services/CategoryService.cs index b68a794ca..7179f8c37 100644 --- a/LearningHub.Nhs.WebUI/Services/CategoryService.cs +++ b/LearningHub.Nhs.WebUI/Services/CategoryService.cs @@ -42,18 +42,18 @@ public CategoryService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHtt /// /// The catalogueNodeVersionId. /// A representing the result of the asynchronous operation. - public async Task GetCatalogueVersionCategoryAsync(int catalogueNodeVersionId) + public async Task GetCatalogueVersionCategoryAsync(int catalogueNodeVersionId) { + CatalogueNodeVersionCategory catalogueNodeVersionCategory = new CatalogueNodeVersionCategory { }; var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"category/GetCatalogueVersionCategory/{catalogueNodeVersionId}"; var response = await client.GetAsync(request).ConfigureAwait(false); - var categoryId = 0; if (response.IsSuccessStatusCode) { var result = response.Content.ReadAsStringAsync().Result; - categoryId = Convert.ToInt32(result); + catalogueNodeVersionCategory = JsonConvert.DeserializeObject(result); } else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden) @@ -61,7 +61,7 @@ public async Task GetCatalogueVersionCategoryAsync(int catalogueNodeVersion throw new Exception("AccessDenied"); } - return categoryId; + return catalogueNodeVersionCategory; } /// @@ -69,9 +69,9 @@ public async Task GetCatalogueVersionCategoryAsync(int catalogueNodeVersion /// /// The categoryId. /// A representing the result of the asynchronous operation. - public async Task> GetSubCategoryByCategoryIdAsync(int categoryId) + public async Task> GetSubCategoryByCategoryIdAsync(string categoryId) { - List viewmodel = new List { }; + List viewmodel = new List { }; var client = await this.OpenApiHttpClient.GetClientAsync(); @@ -81,7 +81,7 @@ public async Task> GetSubCategoryByCategory if (response.IsSuccessStatusCode) { var result = response.Content.ReadAsStringAsync().Result; - viewmodel = JsonConvert.DeserializeObject>(result); + viewmodel = JsonConvert.DeserializeObject>(result); } else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden) @@ -97,9 +97,9 @@ public async Task> GetSubCategoryByCategory /// /// The categoryId. /// A representing the result of the asynchronous operation. - public async Task GetCoursesByCategoryIdAsync(int categoryId) + public async Task GetCoursesByCategoryIdAsync(string categoryId) { - MoodleCoursesResponseModel viewmodel = new MoodleCoursesResponseModel { }; + MoodleCourseResultsResponseModel viewmodel = new MoodleCourseResultsResponseModel { }; var client = await this.OpenApiHttpClient.GetClientAsync(); @@ -109,7 +109,7 @@ public async Task GetCoursesByCategoryIdAsync(int ca if (response.IsSuccessStatusCode) { var result = response.Content.ReadAsStringAsync().Result; - viewmodel = JsonConvert.DeserializeObject(result); + viewmodel = JsonConvert.DeserializeObject(result); } else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden) diff --git a/LearningHub.Nhs.WebUI/Services/DashboardService.cs b/LearningHub.Nhs.WebUI/Services/DashboardService.cs index d201da1f2..1412dcc9b 100644 --- a/LearningHub.Nhs.WebUI/Services/DashboardService.cs +++ b/LearningHub.Nhs.WebUI/Services/DashboardService.cs @@ -2,11 +2,14 @@ { using System; using System.Collections.Generic; + using System.Net.Http.Json; using System.Text; using System.Threading.Tasks; using LearningHub.Nhs.Models.Dashboard; using LearningHub.Nhs.Models.Entities.Analytics; + using LearningHub.Nhs.Models.Moodle; using LearningHub.Nhs.Models.Moodle.API; + using LearningHub.Nhs.Models.MyLearning; using LearningHub.Nhs.WebUI.Interfaces; using LearningHub.Nhs.WebUI.Models; using Microsoft.Extensions.Logging; @@ -66,16 +69,25 @@ public async Task GetMyAccessLearningsAsyn /// /// The dashboard Tray Learning Resource type. /// The dashboard type. + /// The email. /// The page Number. /// A representing the result of the asynchronous operation. - public async Task GetMyCoursesAndElearning(string dashboardTrayLearningResourceType, string dashboardType, int pageNumber) + public async Task GetMyCoursesAndElearning(string dashboardTrayLearningResourceType, string dashboardType, string email, int pageNumber) { DashboardMyLearningResponseViewModel viewmodel = new DashboardMyLearningResponseViewModel { }; var client = await this.OpenApiHttpClient.GetClientAsync(); + var request = new GetMyCoursesAndElearningRequestModel + { + DashboardTrayLearningResourceType = dashboardTrayLearningResourceType, + DashboardType = dashboardType, + Email = email, + PageNumber = pageNumber, + }; - var request = $"dashboard/GetMyCoursesAndElearning/{dashboardTrayLearningResourceType}/{dashboardType}/{pageNumber}"; - var response = await client.GetAsync(request).ConfigureAwait(false); + //// var request = $"dashboard/GetMyCoursesAndElearning/{dashboardTrayLearningResourceType}/{dashboardType}/{email}/{pageNumber}"; + //// var response = await client.GetAsync(request).ConfigureAwait(false); + var response = await client.PostAsJsonAsync("dashboard/GetMyCoursesAndElearning", request); if (response.IsSuccessStatusCode) { diff --git a/LearningHub.Nhs.WebUI/Services/MoodleBridgeApiHttpClient.cs b/LearningHub.Nhs.WebUI/Services/MoodleBridgeApiHttpClient.cs new file mode 100644 index 000000000..04f91cdd8 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Services/MoodleBridgeApiHttpClient.cs @@ -0,0 +1,41 @@ +namespace LearningHub.Nhs.WebUI.Services +{ + using System.Net.Http; + using LearningHub.Nhs.Caching; + using LearningHub.Nhs.WebUI.Configuration; + using LearningHub.Nhs.WebUI.Interfaces; + using Microsoft.AspNetCore.Http; + using Microsoft.Extensions.Logging; + using Microsoft.Extensions.Options; + + /// + /// The open api http client. + /// + public class MoodleBridgeApiHttpClient : BaseHttpClient, IOpenApiHttpClient + { + /// + /// Initializes a new instance of the class. + /// + /// The http context accessor. + /// The web settings. + /// The auth config. + /// The http client. + /// The logger. + /// The cache service. + public MoodleBridgeApiHttpClient( + IHttpContextAccessor httpContextAccessor, + IOptions webSettings, + LearningHubAuthServiceConfig authConfig, + HttpClient client, + ILogger logger, + ICacheService cacheService) + : base(httpContextAccessor, webSettings.Value, authConfig, client, logger, cacheService) + { + } + + /// + /// Gets the open api url. + /// + public override string ApiUrl => this.WebSettings.OpenApiUrl; + } +} diff --git a/LearningHub.Nhs.WebUI/Services/MoodleBridgeApiService.cs b/LearningHub.Nhs.WebUI/Services/MoodleBridgeApiService.cs new file mode 100644 index 000000000..f00592e01 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Services/MoodleBridgeApiService.cs @@ -0,0 +1,67 @@ +namespace LearningHub.Nhs.WebUI.Services +{ + using System; + using System.Collections.Generic; + using System.Text.Json; + using System.Threading.Tasks; + using LearningHub.Nhs.Models.Moodle; + using LearningHub.Nhs.Models.Moodle.API; + using LearningHub.Nhs.WebUI.Configuration; + using LearningHub.Nhs.WebUI.Interfaces; + using LearningHub.Nhs.WebUI.Models; + using Microsoft.Extensions.Options; + using Newtonsoft.Json; + + /// + /// MoodleApiService. + /// + public class MoodleBridgeApiService : IMoodleBridgeApiService + { + private readonly IOpenApiHttpClient openApiHttpClient; + //// private readonly MoodleBridgeApiConfig configuration; + + /// + /// Initializes a new instance of the class. + /// + /// The open Api Http Client. + public MoodleBridgeApiService(IOpenApiHttpClient openApiHttpClient) + { + this.openApiHttpClient = openApiHttpClient; + ////this.configuration = configuration.Value; + } + + /// + /// GetUserInstancesByEmailAsync. + /// + /// The email. + /// UserId from Moodle. + public async Task GetUserInstancesByEmail(string email) + { + MoodleInstanceUserIdsViewModel viewmodel = null; + + try + { + var client = await this.openApiHttpClient.GetClientAsync(); + + var request = $"MoodleBridge/GetUserInstancesByEmail/{email}"; + 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; + } + catch (Exception ex) + { + return viewmodel; + } + } + } +} diff --git a/LearningHub.Nhs.WebUI/Services/MyLearningService.cs b/LearningHub.Nhs.WebUI/Services/MyLearningService.cs index cb75f1530..2014a2af0 100644 --- a/LearningHub.Nhs.WebUI/Services/MyLearningService.cs +++ b/LearningHub.Nhs.WebUI/Services/MyLearningService.cs @@ -5,9 +5,11 @@ using System.Net.Http; using System.Text; using System.Threading.Tasks; + using LearningHub.Nhs.Models.Moodle; using LearningHub.Nhs.Models.MyLearning; using LearningHub.Nhs.WebUI.Configuration; using LearningHub.Nhs.WebUI.Interfaces; + using LearningHub.Nhs.WebUI.Models; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Newtonsoft.Json; @@ -68,12 +70,19 @@ public async Task GetActivityDetailed(MyLearningReq /// Gets the user recent my leraning activities. /// /// The request model. + /// The moodleInstanceUserIds. /// The . - public async Task GetUserRecentMyLearningActivities(MyLearningRequestModel requestModel) + public async Task GetUserRecentMyLearningActivities(MyLearningRequestModel requestModel, MoodleInstanceUserIdsViewModel moodleInstanceUserIds) { MyLearningActivitiesDetailedViewModel viewModel = null; - var json = JsonConvert.SerializeObject(requestModel); + var payload = new MyLearningApiRequestViewModel + { + Request = requestModel, + MoodleInstanceUserIds = moodleInstanceUserIds, + }; + + var json = JsonConvert.SerializeObject(payload); var stringContent = new StringContent(json, Encoding.UTF8, "application/json"); var client = await this.OpenApiHttpClient.GetClientAsync(); @@ -83,7 +92,7 @@ public async Task GetUserRecentMyLearning if (response.IsSuccessStatusCode) { - var result = response.Content.ReadAsStringAsync().Result; + var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false); viewModel = JsonConvert.DeserializeObject(result); } else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized @@ -100,12 +109,18 @@ public async Task GetUserRecentMyLearning /// Gets the user recent my leraning activities. /// /// The request model. + /// The moodleInstanceUserIds. /// The . - public async Task GetUserLearningHistory(MyLearningRequestModel requestModel) + public async Task GetUserLearningHistory(MyLearningRequestModel requestModel, MoodleInstanceUserIdsViewModel moodleInstanceUserIds) { MyLearningActivitiesDetailedViewModel viewModel = null; + var payload = new MyLearningApiRequestViewModel + { + Request = requestModel, + MoodleInstanceUserIds = moodleInstanceUserIds, + }; - var json = JsonConvert.SerializeObject(requestModel); + var json = JsonConvert.SerializeObject(payload); var stringContent = new StringContent(json, Encoding.UTF8, "application/json"); var client = await this.OpenApiHttpClient.GetClientAsync(); @@ -192,12 +207,17 @@ public async Task> GetResourceCertif /// Gets the user certificates. /// /// The request model. + /// The moodleInstanceUserIds. /// The . - public async Task GetUserCertificateDetails(MyLearningRequestModel requestModel) + public async Task GetUserCertificateDetails(MyLearningRequestModel requestModel, MoodleInstanceUserIdsViewModel moodleInstanceUserIds) { MyLearningCertificatesDetailedViewModel viewModel = null; - - var json = JsonConvert.SerializeObject(requestModel); + var payload = new MyLearningApiRequestViewModel + { + Request = requestModel, + MoodleInstanceUserIds = moodleInstanceUserIds, + }; + var json = JsonConvert.SerializeObject(payload); var stringContent = new StringContent(json, Encoding.UTF8, "application/json"); var client = await this.OpenApiHttpClient.GetClientAsync(); diff --git a/LearningHub.Nhs.WebUI/Startup/ServiceMappings.cs b/LearningHub.Nhs.WebUI/Startup/ServiceMappings.cs index 60ff5f634..589eea428 100644 --- a/LearningHub.Nhs.WebUI/Startup/ServiceMappings.cs +++ b/LearningHub.Nhs.WebUI/Startup/ServiceMappings.cs @@ -101,6 +101,7 @@ public static void AddLearningHubMappings(this IServiceCollection services, ICon services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddScoped(); services.AddScoped(); diff --git a/LearningHub.Nhs.WebUI/Views/Catalogue/Courses.cshtml b/LearningHub.Nhs.WebUI/Views/Catalogue/Courses.cshtml index f8c67dc63..255049950 100644 --- a/LearningHub.Nhs.WebUI/Views/Catalogue/Courses.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Catalogue/Courses.cshtml @@ -15,12 +15,12 @@

Courses

- @foreach (MoodleSubCategoryResponseModel item in Model.SubCategories) + @foreach (MoodleCategory item in Model.SubCategories) {
diff --git a/LearningHub.Nhs.WebUI/Views/Catalogue/Index.cshtml b/LearningHub.Nhs.WebUI/Views/Catalogue/Index.cshtml index 1384acfb9..d08f7769d 100644 --- a/LearningHub.Nhs.WebUI/Views/Catalogue/Index.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Catalogue/Index.cshtml @@ -57,8 +57,8 @@ if (ViewBag.ActiveTab == "courses") { - if (Model.Catalogue.SelectedCategoryId == 0 || - (Model.Catalogue.SelectedCategoryId > 0 && + if (Model.Catalogue.SelectedCategoryId == null || + (Model.Catalogue.SelectedCategoryId != null && (Model.Courses == null || !Model.Courses.Any()) && (Model.SubCategories == null || !Model.SubCategories.Any()))) { @@ -71,7 +71,7 @@ { breadcrumbs = UtilityHelper.GetBreadcrumbsForFolderNodes(Model.NodePathNodes.SkipLast(1).ToList(), Model.Catalogue.Url); } - else if (ViewBag.ActiveTab == "courses" && Model.Catalogue.SelectedCategoryId > 0) + else if (ViewBag.ActiveTab == "courses" && Model.Catalogue.SelectedCategoryId !=null) { breadcrumbs = UtilityHelper.GetBreadcrumbsForCourses(Model.MoodleCategories, Model.Catalogue.Url); } @@ -205,7 +205,7 @@ Resources } - @if (Model.Catalogue.SelectedCategoryId > 0 && + @if (Model.Catalogue.SelectedCategoryId != null && ( (Model.Courses != null && Model.Courses.Any()) || (Model.SubCategories != null && Model.SubCategories.Any()) diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/MoodleBridgeConfig.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/MoodleBridgeConfig.cs new file mode 100644 index 000000000..4798fabe8 --- /dev/null +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/MoodleBridgeConfig.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LearningHub.Nhs.OpenApi.Models.Configuration +{ + /// + /// The Moodle Bridge Settings. + /// + public class MoodleBridgeAPIConfig + { + /// + /// Gets or sets the base url for the Moodle service. + /// + public string BaseUrl { get; set; } = null!; + + /// + /// Gets or sets the token. + /// + public string Token { get; set; } = null!; + } +} diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj index 16df89013..b147cf34f 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj @@ -17,8 +17,12 @@ - + + + + + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj index cbac27a64..acfceeb83 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories.Interface/LearningHub.Nhs.OpenApi.Repositories.Interface.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj index 6a727dc60..33302f623 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/LearningHub.Nhs.OpenApi.Repositories.csproj @@ -24,7 +24,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/CatalogueNodeVersionRepository.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/CatalogueNodeVersionRepository.cs index 3367b371f..32932e648 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/CatalogueNodeVersionRepository.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Repositories/Repositories/Hierarchy/CatalogueNodeVersionRepository.cs @@ -226,12 +226,14 @@ public async Task AddCategoryToCatalogueAsync(int userId, CatalogueViewModel vm) { try { + var (instanceName, categoryId) = vm.SelectedCategoryId.Split(':') is var p && p.Length == 2 ? (p[0], p[1]) : (null, null); var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = userId }; var param1 = new SqlParameter("@p1", SqlDbType.Int) { Value = vm.CatalogueNodeVersionId }; - var param2 = new SqlParameter("@p2", SqlDbType.Int) { Value = vm.SelectedCategoryId }; - var param3 = new SqlParameter("@p3", SqlDbType.Int) { Value = TimezoneOffsetManager.UserTimezoneOffset ?? (object)DBNull.Value }; + var param2 = new SqlParameter("@p2", SqlDbType.Int) { Value = categoryId }; + var param3 = new SqlParameter("@p3", SqlDbType.VarChar) { Value = instanceName }; + var param4 = new SqlParameter("@p4", SqlDbType.Int) { Value = TimezoneOffsetManager.UserTimezoneOffset ?? (object)DBNull.Value }; - await DbContext.Database.ExecuteSqlRawAsync("hierarchy.CatalogueNodeVersionCategoryCreate @p0, @p1, @p2, @p3", param0, param1, param2, param3); + await DbContext.Database.ExecuteSqlRawAsync("hierarchy.CatalogueNodeVersionCategoryCreate @p0, @p1, @p2, @p3, @p4", param0, param1, param2, param3, param4); } catch (Exception ex) { @@ -249,9 +251,10 @@ public async Task RemoveCategoryFromCatalogueAsync(int userId, CatalogueViewMode { try { + var (instanceName, categoryId) = vm.SelectedCategoryId.Split(':') is var p && p.Length == 2 ? (p[0], p[1]) : (null, null); var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = userId }; var param1 = new SqlParameter("@p1", SqlDbType.Int) { Value = vm.CatalogueNodeVersionId }; - var param2 = new SqlParameter("@p2", SqlDbType.Int) { Value = vm.SelectedCategoryId }; + var param2 = new SqlParameter("@p2", SqlDbType.Int) { Value = categoryId }; var param3 = new SqlParameter("@p3", SqlDbType.Int) { Value = TimezoneOffsetManager.UserTimezoneOffset ?? (object)DBNull.Value }; await DbContext.Database.ExecuteSqlRawAsync("hierarchy.RemoveCatalogueCategory @p0, @p1, @p2, @p3", param0, param1, param2, param3); diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/HttpClients/IMoodleBridgeHttpClient.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/HttpClients/IMoodleBridgeHttpClient.cs new file mode 100644 index 000000000..129d3eec3 --- /dev/null +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/HttpClients/IMoodleBridgeHttpClient.cs @@ -0,0 +1,25 @@ +using System.Net.Http; +using System.Threading.Tasks; + +namespace LearningHub.Nhs.OpenApi.Services.Interface.HttpClients +{ + /// + /// The Moodle Http Client interface. + /// + public interface IMoodleBridgeHttpClient + { + /// + /// The get cient async. + /// + /// The . + Task GetClient(); + + /// + /// GETs data from Databricks API. + /// + /// The URL to make a get call to. + /// Optional authorization header. + /// A representing the result of the asynchronous operation. + Task GetData(string requestUrl, string? authHeader); + } +} diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj index 175ac7fb3..802661079 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj @@ -17,7 +17,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/ICategoryService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/ICategoryService.cs index 5c4a994a4..2ac311640 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/ICategoryService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/ICategoryService.cs @@ -14,6 +14,6 @@ public interface ICategoryService /// /// node version id. /// A representing the result of the asynchronous operation. - Task GetByCatalogueVersionIdAsync(int nodeVersionId); + Task GetByCatalogueVersionIdAsync(int nodeVersionId); } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IDashboardService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IDashboardService.cs index 7897acf90..ff04ae056 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IDashboardService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IDashboardService.cs @@ -21,13 +21,11 @@ public interface IDashboardService /// /// Get My in progress courses and Elearning. /// - /// The dashboardTrayLearningResource type. - /// The dashboard type. - /// The page Number. + /// The requestModel. /// The userId. /// The resourceType. /// A representing the result of the asynchronous operation. - Task GetMyCoursesAndElearning(string dashboardTrayLearningResourceType, string dashboardType, int pageNumber, int userId, string resourceType); + Task GetMyCoursesAndElearning(GetMyCoursesAndElearningRequestModel requestModel, int userId, string resourceType); /// /// Gets the user in progrss my leraning activities.. @@ -35,8 +33,9 @@ public interface IDashboardService /// The dashboardTrayLearningResourceType. /// The pageNumber. /// The user id. + /// The email. /// The . - Task GetMyInprogressLearningAsync(string dashboardTrayLearningResourceType, int pageNumber, int userId); + Task GetMyInprogressLearningAsync(string dashboardTrayLearningResourceType, int pageNumber, int userId, string email); /// /// Gets the resource certificate details. @@ -45,7 +44,7 @@ public interface IDashboardService /// The user id. /// The resourceType. /// The . - Task GetUserCertificateDetailsAsync(string dashboardTrayLearningResourceType, int pageNumber, int userId); + Task GetUserCertificateDetailsAsync(string dashboardTrayLearningResourceType, int pageNumber, int userId, string email); /// /// GetResources. diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMoodleBridgeApiService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMoodleBridgeApiService.cs new file mode 100644 index 000000000..e099e8bb9 --- /dev/null +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMoodleBridgeApiService.cs @@ -0,0 +1,82 @@ + +using System.Collections.Generic; +using System.Threading.Tasks; +using LearningHub.Nhs.Models.Moodle; +using LearningHub.Nhs.Models.Moodle.API; +using LearningHub.Nhs.Models.MyLearning; + +namespace LearningHub.Nhs.OpenApi.Services.Interface.Services +{ + /// + /// IMoodleBridgeApiService. + /// + public interface IMoodleBridgeApiService + { + /// + /// GetUserInstancesByEmailAsync. + /// + /// The current LH User email. + /// A representing the result of the asynchronous operation. + Task GetUserInstancesByEmail(string email); + + /// + /// GetRecentEnrolledCoursesAsync. + /// + /// The moodleUserInstanceUserIds. + /// The requestModel. + /// The month. + /// + Task GetRecentEnrolledCoursesAsync(MoodleInstanceUserIdsViewModel moodleUserInstanceUserIds, MyLearningRequestModel requestModel, int? month = null); + + /// + /// GetAllMoodleCategoriesAsync. + /// + /// A representing the result of the asynchronous operation. + Task> GetAllMoodleCategoriesAsync(); + + /// + /// GetEnrolledCoursesAsync. + /// + /// Moodle Instances user id. + /// MyLearningRequestModel requestModel. + /// A representing the result of the asynchronous operation. + Task GetEnrolledCoursesHistoryAsync(MoodleInstanceUserIdsViewModel moodleUserInstanceUserIds, MyLearningRequestModel requestModel); + + /// + /// GetInProgressEnrolledCoursesAsync. + /// + /// The email. + /// A representing the result of the asynchronous operation. + Task GetInProgressEnrolledCoursesAsync(string email); + + /// + /// GetUserLearningHistory. + /// + /// user email. + /// The filterText. + /// A representing the result of the asynchronous operation. + Task GetUserCertificateAsync(string email, string filterText = ""); + + /// + /// GetUserCertificateFromMoodleInstancesAsync. + /// + /// Moodle Instances user id. + /// MyLearningRequestModel requestModel. + /// A representing the result of the asynchronous operation. + Task GetUserCertificateFromMoodleInstancesAsync(MoodleInstanceUserIdsViewModel moodleUserInstanceUserIds, string filterText = ""); + + /// + /// GetCoursesByCategoryIdAsync. + /// + /// The categoryId. + /// + Task GetCoursesByCategoryIdAsync(string categoryId); + + /// + /// GetSubCategoryByCategoryIdAsync. + /// + /// The categoryId. + /// + Task> GetSubCategoryByCategoryIdAsync(string categoryId); + } +} diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMyLearningService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMyLearningService.cs index 04a68d86f..aabdc0d99 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMyLearningService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMyLearningService.cs @@ -26,7 +26,7 @@ public interface IMyLearningService /// /// The user id. /// The request model. /// The . - Task GetUserRecentMyLearningActivitiesAsync(int userId, MyLearningRequestModel requestModel); + Task GetUserRecentMyLearningActivitiesAsync(int userId, MyLearningApiRequestViewModel requestModel); /// /// Gets history of users my leraning activities. @@ -34,7 +34,7 @@ public interface IMyLearningService /// /// The user id. /// The request model. /// The . - Task GetUserLearningHistoryAsync(int userId, MyLearningRequestModel requestModel); + Task GetUserLearningHistoryAsync(int userId, MyLearningApiRequestViewModel requestModel); /// /// Gets the played segment data for the progress modal in My Learning screen. @@ -69,6 +69,6 @@ public interface IMyLearningService /// The user id. /// The request model /// The . - Task GetUserCertificateDetails(int userId, MyLearningRequestModel requestModel); + Task GetUserCertificateDetails(int userId, MyLearningApiRequestViewModel requestModel); } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Helpers/MoodleInstanceUsersHelper.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Helpers/MoodleInstanceUsersHelper.cs new file mode 100644 index 000000000..de3272ec0 --- /dev/null +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Helpers/MoodleInstanceUsersHelper.cs @@ -0,0 +1,47 @@ +namespace LearningHub.Nhs.OpenApi.Services.Helpers +{ + using System; + using System.Collections.Generic; + using System.Linq; + using LearningHub.Nhs.Models.Enums; + using LearningHub.Nhs.Models.Moodle; + using LearningHub.Nhs.Models.Resource; + using LearningHub.Nhs.Models.Resource.Blocks; + + /// + /// A class containing helper functions for building moodle user instances. + /// + public class MoodleInstanceUsersHelper + { + /// + /// BuildMoodleUserInstances. + /// + /// + /// + public static MoodleInstanceUserIdsViewModel BuildUserIdsByInstance( + IEnumerable mappings) + { + var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); + + foreach (var m in mappings) + { + if (m?.User is null) continue; + if (m.User.Id <= 0) continue; + + var key = string.IsNullOrWhiteSpace(m.Instance) + ? $"instance_{m.User.Id}" + : m.Instance!; + + if (!dict.ContainsKey(key)) + { + dict[key] = m.User.Id; + } + } + + return new MoodleInstanceUserIdsViewModel + { + MoodleInstanceUserIds = dict + }; + } + } +} diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/HttpClients/MoodleBridgeHttpClient.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/HttpClients/MoodleBridgeHttpClient.cs new file mode 100644 index 000000000..e7812294d --- /dev/null +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/HttpClients/MoodleBridgeHttpClient.cs @@ -0,0 +1,97 @@ +using IdentityModel.Client; +using LearningHub.Nhs.Models.Entities.Reporting; +using LearningHub.Nhs.OpenApi.Models.Configuration; +using LearningHub.Nhs.OpenApi.Services.Interface.HttpClients; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading.Tasks; + +namespace LearningHub.Nhs.OpenApi.Services.HttpClients +{ + /// + /// The Moodle Http Client. + /// + public class MoodleBridgeHttpClient : IMoodleBridgeHttpClient, IDisposable + { + private readonly MoodleBridgeAPIConfig moodleBridgeApiConfig; + private readonly HttpClient httpClient = new(); + + private bool initialised = false; + private string moodleBridgeApiUrl; + private string moodleBridgeApiToken; + + /// + /// Initializes a new instance of the class. + /// + /// httpClient. + /// config. + public MoodleBridgeHttpClient(HttpClient httpClient, IOptions moodleBridgeApiConfig) + { + this.moodleBridgeApiConfig = moodleBridgeApiConfig.Value; + this.httpClient = httpClient; + + this.moodleBridgeApiUrl = this.moodleBridgeApiConfig.BaseUrl; + this.moodleBridgeApiToken = this.moodleBridgeApiConfig.Token; + } + + /// + /// The Get Client method. + /// + /// The . + public async Task GetClient() + { + this.Initialise(this.moodleBridgeApiUrl); + return this.httpClient; + } + + + /// + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// The dispoase. + /// + /// disposing. + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + this.httpClient.Dispose(); + } + } + + private void Initialise(string httpClientUrl) + { + if (this.initialised == false) + { + this.httpClient.BaseAddress = new Uri(httpClientUrl); + this.httpClient.DefaultRequestHeaders.Accept.Clear(); + this.httpClient.DefaultRequestHeaders.Accept.Add( + new MediaTypeWithQualityHeaderValue("application/json")); + this.httpClient.DefaultRequestHeaders.Add("X-API-KEY", moodleBridgeApiToken); + this.initialised = true; + } + } + + /// + public async Task GetData(string requestUrl, string? authHeader) + { + if (!string.IsNullOrEmpty(authHeader)) + { + this.httpClient.SetBearerToken(authHeader); + } + + var message = await this.httpClient.GetAsync(requestUrl).ConfigureAwait(false); + return message; + } + } +} diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj index ae8d05738..b99a31373 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj @@ -31,7 +31,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs index 5edfe8cc4..0dfb757e7 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CatalogueService.cs @@ -229,7 +229,11 @@ public async Task GetCatalogueAsync(int id) // Used by the admin screen to inform the admin user if they need to add a user group. vm.HasUserGroup = this.GetRoleUserGroupsForCatalogue(vm.NodeId).Any(); vm.Providers = await this.providerService.GetAllAsync(); - vm.SelectedCategoryId = await this.categoryService.GetByCatalogueVersionIdAsync(vm.CatalogueNodeVersionId); + var cataloguNodeeCategories = await this.categoryService.GetByCatalogueVersionIdAsync(vm.CatalogueNodeVersionId); + if (cataloguNodeeCategories != null) + { + vm.SelectedCategoryId = cataloguNodeeCategories.InstanceName + ":" + cataloguNodeeCategories.CategoryId; + } return vm; } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CategoryService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CategoryService.cs index e950a1d1f..32b5dfdda 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CategoryService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/CategoryService.cs @@ -36,10 +36,10 @@ public CategoryService(ICategoryRepository categoryRepository, IMapper mapper) } /// - public async Task GetByCatalogueVersionIdAsync(int nodeVersionId) + public async Task GetByCatalogueVersionIdAsync(int nodeVersionId) { var category = await categoryRepository.GetCategoryByCatalogueIdAsync(nodeVersionId); - return category != null ? category.CategoryId : 0; + return category; } } } \ No newline at end of file diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/DashboardService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/DashboardService.cs index ad7868baf..5da2bc71b 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/DashboardService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/DashboardService.cs @@ -35,6 +35,11 @@ public class DashboardService : IDashboardService /// private readonly IMoodleApiService moodleApiService; + /// + /// The moodleBridgeApiService. + /// + private readonly IMoodleBridgeApiService moodleBridgeApiService; + /// /// The resourceActivityRepository. /// @@ -54,9 +59,10 @@ public class DashboardService : IDashboardService /// ratingService. /// providerService. /// moodleApiService. + /// moodleBridgeApiService. /// resourceActivityRepository. /// resourceRepository. - public DashboardService(IMapper mapper, IResourceVersionRepository resourceVersionRepository, ICatalogueNodeVersionRepository catalogueNodeVersionRepository, IRatingService ratingService, IProviderService providerService, IMoodleApiService moodleApiService, IResourceActivityRepository resourceActivityRepository, IResourceRepository resourceRepository) + public DashboardService(IMapper mapper, IResourceVersionRepository resourceVersionRepository, ICatalogueNodeVersionRepository catalogueNodeVersionRepository, IRatingService ratingService, IProviderService providerService, IMoodleApiService moodleApiService, IMoodleBridgeApiService moodleBridgeApiService, IResourceActivityRepository resourceActivityRepository, IResourceRepository resourceRepository) { this.mapper = mapper; this.resourceVersionRepository = resourceVersionRepository; @@ -66,6 +72,7 @@ public DashboardService(IMapper mapper, IResourceVersionRepository resourceVersi this.moodleApiService = moodleApiService; this.resourceActivityRepository = resourceActivityRepository; this.resourceRepository = resourceRepository; + this.moodleBridgeApiService = moodleBridgeApiService; } /// @@ -126,28 +133,28 @@ public async Task GetMyAccessLearnings(str /// The userId. /// The resourceType. /// A representing the result of the asynchronous operation. - public async Task GetMyCoursesAndElearning(string dashboardTrayLearningResourceType, string dashboardType, int pageNumber, int userId, string resourceType) + public async Task GetMyCoursesAndElearning(GetMyCoursesAndElearningRequestModel requestModel, int userId, string resourceType) { MyLearningActivitiesDetailedViewModel myInProgressActivities = new(); MyLearningCertificatesDetailedViewModel certificates = new(); List resources = new(); int resourceCount = 0; - if (dashboardType == "my-in-progress") + if (requestModel.DashboardType == "my-in-progress") { - myInProgressActivities = await this.GetMyInprogressLearningAsync(dashboardTrayLearningResourceType, pageNumber, userId); + myInProgressActivities = await this.GetMyInprogressLearningAsync(requestModel.DashboardTrayLearningResourceType, requestModel.PageNumber, userId, requestModel.Email); } - else if (dashboardType == "my-certificates") + else if (requestModel.DashboardType == "my-certificates") { - certificates = await this.GetUserCertificateDetailsAsync(dashboardTrayLearningResourceType, pageNumber, userId); + certificates = await this.GetUserCertificateDetailsAsync(requestModel.DashboardTrayLearningResourceType, requestModel.PageNumber, userId, requestModel.Email); } else { - var result = resourceVersionRepository.GetResources(dashboardType, pageNumber, userId); + var result = resourceVersionRepository.GetResources(requestModel.DashboardType, requestModel.PageNumber, userId); resourceCount = result.resourceCount; resources = result.resources ?? new List(); } - var cataloguesResponse = dashboardType.ToLower() == "my-catalogues" ? catalogueNodeVersionRepository.GetCatalogues(dashboardType, pageNumber, userId) : (TotalCount: 0, Catalogues: new List()); + var cataloguesResponse = requestModel.DashboardType.ToLower() == "my-catalogues" ? catalogueNodeVersionRepository.GetCatalogues(requestModel.DashboardType, requestModel.PageNumber, userId) : (TotalCount: 0, Catalogues: new List()); var catalogueList = cataloguesResponse.Catalogues.Any() ? mapper.Map>(cataloguesResponse.Catalogues) : new List(); if (catalogueList.Any()) @@ -196,19 +203,19 @@ public async Task GetMyCoursesAndElearning var response = new DashboardMyLearningResponseViewModel { - Type = dashboardType, + Type = requestModel.DashboardType, Resources = resourceList, Catalogues = catalogueList, Activities = myInProgressActivities.Activities, UserCertificates = certificates.Certificates, - TotalCount = dashboardType?.ToLower() switch + TotalCount = requestModel.DashboardType?.ToLower() switch { "my-catalogues" => cataloguesResponse.TotalCount, "my-in-progress" => myInProgressActivities?.TotalCount ?? 0, "my-certificates" => certificates?.TotalCount ?? 0, _ => resourceCount }, - CurrentPage = pageNumber, + CurrentPage = requestModel.PageNumber, }; return response; @@ -220,11 +227,12 @@ public async Task GetMyCoursesAndElearning /// The dashboardTrayLearningResourceType. /// The pageNumber. /// The user id. + /// The email. /// The . - public async Task GetMyInprogressLearningAsync(string dashboardTrayLearningResourceType, int pageNumber, int userId) + public async Task GetMyInprogressLearningAsync(string dashboardTrayLearningResourceType, int pageNumber, int userId, string email) { List result = new(); - List entrolledCourses = new(); + MoodleCompletionsApiResponseModel entrolledCourses = new(); List mappedMyLearningActivities = new(); List mappedEnrolledCourses = new(); if (dashboardTrayLearningResourceType != "courses") @@ -234,7 +242,7 @@ public async Task GetMyInprogressLearning if (dashboardTrayLearningResourceType != "elearning") { - entrolledCourses = await this.moodleApiService.GetInProgressEnrolledCoursesAsync(userId); + entrolledCourses = await this.moodleBridgeApiService.GetInProgressEnrolledCoursesAsync(email); } if (result != null) @@ -269,36 +277,39 @@ public async Task GetMyInprogressLearning if (entrolledCourses != null) { - mappedEnrolledCourses = entrolledCourses.Select(course => new MyLearningCombinedActivitiesViewModel - { - UserId = userId, - ResourceId = (int)course.Id, - ResourceVersionId = (int)course.Id, - IsCurrentResourceVersion = true, - ResourceReferenceId = (int)course.Id, - MajorVersion = 1, - MinorVersion = 0, - ResourceType = ResourceTypeEnum.Moodle, - Title = course.DisplayName, - CertificateEnabled = course.CertificateEnabled, - ActivityStatus = (course.Completed == true || course.ProgressPercentage.TrimEnd('%') == "100") ? ActivityStatusEnum.Completed : ActivityStatusEnum.Incomplete, - ActivityDate = course.LastAccessDate.HasValue + mappedEnrolledCourses = entrolledCourses?.Results? + .Where(r => r.Data?.Courses != null) + .SelectMany(r => r.Data.Courses) + .Select(course => new MyLearningCombinedActivitiesViewModel + { + UserId = userId, + ResourceId = (int)course.Id, + ResourceVersionId = (int)course.Id, + IsCurrentResourceVersion = true, + ResourceReferenceId = (int)course.Id, + MajorVersion = 1, + MinorVersion = 0, + ResourceType = ResourceTypeEnum.Moodle, + Title = course.DisplayName, + CertificateEnabled = course.CertificateEnabled, + ActivityStatus = (course.Completed == true || course.ProgressPercentage.TrimEnd('%') == "100") ? ActivityStatusEnum.Completed : ActivityStatusEnum.Incomplete, + ActivityDate = course.LastAccessDate.HasValue ? DateTimeOffset.FromUnixTimeSeconds(course.LastAccessDate.Value) : DateTimeOffset.MinValue, - ScorePercentage = Convert.ToInt32(course.ProgressPercentage.TrimEnd('%')), - TotalActivities = course.TotalActivities, - CompletedActivities = course.CompletedActivities, - IsMostRecent = false, - ResourceDurationMilliseconds = 0, - CompletionPercentage = 0, - ProvidersJson = null, - AssesmentScore = 0, - AssessmentPassMark = 0, - AssessmentType = 0, - CertificateAwardedDate = course.EndDate.HasValue + ScorePercentage = Convert.ToInt32(course.ProgressPercentage.TrimEnd('%')), + TotalActivities = course.TotalActivities, + CompletedActivities = course.CompletedActivities, + IsMostRecent = false, + ResourceDurationMilliseconds = 0, + CompletionPercentage = 0, + ProvidersJson = null, + AssesmentScore = 0, + AssessmentPassMark = 0, + AssessmentType = 0, + CertificateAwardedDate = course.EndDate.HasValue ? DateTimeOffset.FromUnixTimeSeconds(course.EndDate.Value) : DateTimeOffset.MinValue, - }).ToList(); + }).ToList(); } // Combine both result sets @@ -327,16 +338,16 @@ public async Task GetMyInprogressLearning /// The pageNumber. /// The user id. /// The . - public async Task GetUserCertificateDetailsAsync(string dashboardTrayLearningResourceType, int pageNumber, int userId) + public async Task GetUserCertificateDetailsAsync(string dashboardTrayLearningResourceType, int pageNumber, int userId, string email) { try { - Task>? courseCertificatesTask = null; Task>? resourceCertificatesTask = null; + Task? courseCertificatesTask = null; if (dashboardTrayLearningResourceType != "elearning") { - courseCertificatesTask = moodleApiService.GetUserCertificateAsync(userId); + courseCertificatesTask = moodleBridgeApiService.GetUserCertificateAsync(email); } if (dashboardTrayLearningResourceType != "courses") @@ -361,23 +372,24 @@ public async Task GetUserCertificateDet if (courseCertificatesTask != null) { - var courseCertificates = courseCertificatesTask.Result ?? Enumerable.Empty(); - - mappedCourseCertificates = courseCertificates.Select(c => new UserCertificateViewModel - { - Title = string.IsNullOrWhiteSpace(c.ResourceTitle) ? c.ResourceName : c.ResourceTitle, - ResourceTypeId = (int)ResourceTypeEnum.Moodle, - ResourceReferenceId = 0, - MajorVersion = 0, - MinorVersion = 0, - AwardedDate = c.AwardedDate.HasValue + mappedCourseCertificates = courseCertificatesTask.Result?.Results? + .Where(r => r.Data?.Certificates != null) + .SelectMany(r => r.Data.Certificates) + .Select(c => new UserCertificateViewModel + { + Title = string.IsNullOrWhiteSpace(c.ResourceTitle) ? c.ResourceName : c.ResourceTitle, + ResourceTypeId = (int)ResourceTypeEnum.Moodle, + ResourceReferenceId = 0, + MajorVersion = 0, + MinorVersion = 0, + AwardedDate = c.AwardedDate.HasValue ? DateTimeOffset.FromUnixTimeSeconds(c.AwardedDate.Value) : DateTimeOffset.MinValue, - CertificatePreviewUrl = c.PreviewLink, - CertificateDownloadUrl = c.DownloadLink, - ResourceVersionId = 0, - ProvidersJson = null - }); + CertificatePreviewUrl = c.PreviewLink, + CertificateDownloadUrl = c.DownloadLink, + ResourceVersionId = 0, + ProvidersJson = null + }); } var allCertificates = resourceCertificates.Concat(mappedCourseCertificates); diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleApiService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleApiService.cs index 9630ff24d..f868d946a 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleApiService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleApiService.cs @@ -43,7 +43,7 @@ public MoodleApiService(IMoodleHttpClient moodleHttpClient, ILoggerUserId from Moodle. public async Task GetMoodleUserIdByUsernameAsync(int currentUserId) { - var parameters = new Dictionary + var parameters = new Dictionary { { "criteria[0][key]", "username" }, { "criteria[0][value]", currentUserId.ToString() } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleBridgeApiService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleBridgeApiService.cs new file mode 100644 index 000000000..599569673 --- /dev/null +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleBridgeApiService.cs @@ -0,0 +1,584 @@ +namespace LearningHub.Nhs.OpenApi.Services.Services +{ + using LearningHub.Nhs.Models.Moodle; + using LearningHub.Nhs.Models.Moodle.API; + using LearningHub.Nhs.Models.MyLearning; + using LearningHub.Nhs.Models.Report.ReportCreate; + using LearningHub.Nhs.OpenApi.Services.Interface.HttpClients; + using LearningHub.Nhs.OpenApi.Services.Interface.Services; + using Microsoft.Extensions.Logging; + using Newtonsoft.Json; + using System; + using System.Collections.Generic; + using System.Linq; + using System.Net; + using System.Net.Http; + using System.Text; + using System.Text.Json; + using System.Threading.Tasks; + using LearningHub.Nhs.OpenApi.Services.Helpers; + using System.Net.Http.Json; + using static System.Net.WebRequestMethods; + using IdentityModel.Client; + using static Microsoft.EntityFrameworkCore.DbLoggerCategory; + + /// + /// MoodleBridgeApiService. + /// + public class MoodleBridgeApiService : IMoodleBridgeApiService + { + private readonly IMoodleBridgeHttpClient moodleBridgeHttpClient; + private readonly ILogger logger; + + /// + /// Initializes a new instance of the class. + /// + /// moodleHttpClient. + /// logger. + public MoodleBridgeApiService(IMoodleBridgeHttpClient moodleBridgeHttpClient, ILogger logger) + { + this.moodleBridgeHttpClient = moodleBridgeHttpClient; + this.logger = logger; + } + + /// + /// GetUserInstancesByEmailAsync. + /// + /// The email. + /// UserId from Moodle. + public async Task GetUserInstancesByEmail(string email) + { + MoodleUserIdsResponseModel viewmodel = null; + + try + { + var client = await this.moodleBridgeHttpClient.GetClient(); + + var request = $"/api/v1/Users/{Uri.EscapeDataString(email)}/instance-ids"; + var response = await client.GetAsync(request).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadAsStringAsync(); + var options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + }; + + viewmodel = System.Text.Json.JsonSerializer.Deserialize(result, options); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + if (viewmodel?.MoodleUserIds != null) + { + return MoodleInstanceUsersHelper.BuildUserIdsByInstance(viewmodel.MoodleUserIds); + } + else + { + throw new Exception("Failed to retrieve Moodle user IDs."); + } + } + catch (Exception ex) + { + this.logger.LogError(ex, "An error occurred while fetching user instances by email."); + throw; + } + } + + /// + /// GetEnrolledCoursesAsync. + /// + /// Moodle instances user id. + /// MyLearningRequestModel. + /// The months. + /// A representing the result of the asynchronous operation. + public async Task GetRecentEnrolledCoursesAsync(MoodleInstanceUserIdsViewModel moodleUserInstanceUserIds, MyLearningRequestModel requestModel, int? month = null) + { + try + { + if (moodleUserInstanceUserIds?.MoodleInstanceUserIds == null || + !moodleUserInstanceUserIds.MoodleInstanceUserIds.Any()) + { + throw new ArgumentException("UserIds are required."); + } + + if (moodleUserInstanceUserIds.MoodleInstanceUserIds.ContainsKey("moodle-test")) + { + moodleUserInstanceUserIds.MoodleInstanceUserIds["moodle-test"] = 280; + } + + string statusFilter = string.Empty; ; + + if ((requestModel.Incomplete && requestModel.Complete) || (!requestModel.Incomplete && !requestModel.Complete)) + { + statusFilter = string.Empty; ; + } + else if (requestModel.Incomplete) + { + statusFilter = "inprogress"; + } + else + { + statusFilter = "completed"; + } + + var client = await this.moodleBridgeHttpClient.GetClient(); + + var queryParams = new List(); + + if (!string.IsNullOrWhiteSpace(statusFilter)) + queryParams.Add($"statusfilter={statusFilter}"); + + if (month.HasValue) + queryParams.Add($"months={month.Value}"); + + if (!string.IsNullOrWhiteSpace(requestModel?.SearchText)) + { + queryParams.Add($"search={Uri.EscapeDataString(requestModel.SearchText)}"); + } + + var queryString = queryParams.Any() + ? "?" + string.Join("&", queryParams) + : string.Empty; + + + var requestUri = $"api/v1/users/recent-courses{queryString}"; + + var response = await client.PostAsJsonAsync( + requestUri, + moodleUserInstanceUserIds).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + var options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + }; + + var result = System.Text.Json.JsonSerializer.Deserialize(json, options); + + return result ?? new MoodleCompletionsApiResponseModel(); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + throw new Exception($"Request failed with status code {response.StatusCode}"); + } + catch (Exception ex) + { + this.logger.LogError(ex, "An error occurred while fetching user's recent learning activities "); + throw; + } + } + + /// + /// GetEnrolledCoursesAsync. + /// + /// Moodle Instances user id. + /// MyLearningRequestModel requestModel. + /// A representing the result of the asynchronous operation. + public async Task GetEnrolledCoursesHistoryAsync(MoodleInstanceUserIdsViewModel moodleUserInstanceUserIds, MyLearningRequestModel requestModel) + { + try + { + if (moodleUserInstanceUserIds?.MoodleInstanceUserIds == null || + !moodleUserInstanceUserIds.MoodleInstanceUserIds.Any()) + { + throw new ArgumentException("UserIds are required."); + } + + if (moodleUserInstanceUserIds.MoodleInstanceUserIds.ContainsKey("moodle-test")) + { + moodleUserInstanceUserIds.MoodleInstanceUserIds["moodle-test"] = 280; + } + + string statusFilter = string.Empty; ; + + if ((requestModel.Incomplete && requestModel.Complete) || (!requestModel.Incomplete && !requestModel.Complete)) + { + statusFilter = string.Empty; + } + else if (requestModel.Incomplete) + { + statusFilter = "inprogress"; + } + else + { + statusFilter = "completed"; + } + + var client = await this.moodleBridgeHttpClient.GetClient(); + // Build query string (optional params) + var queryParams = new List(); + queryParams.Add($"months=0"); + if (!string.IsNullOrWhiteSpace(statusFilter)) + queryParams.Add($"statusfilter={statusFilter}"); + + if (!string.IsNullOrWhiteSpace(requestModel?.SearchText)) + { + queryParams.Add($"search={Uri.EscapeDataString(requestModel.SearchText)}"); + } + + var queryString = queryParams.Any() + ? "?" + string.Join("&", queryParams) + : string.Empty; + + var requestUri = $"api/v1/users/recent-courses{queryString}"; + + var response = await client.PostAsJsonAsync( + requestUri, + moodleUserInstanceUserIds).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + var options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + }; + + var result = System.Text.Json.JsonSerializer.Deserialize(json, options); + + return result ?? new MoodleCompletionsApiResponseModel(); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + throw new Exception($"Request failed with status code {response.StatusCode}"); + } + catch (Exception ex) + { + return null; + } + } + + /// + /// GetInProgressEnrolledCoursesAsync. + /// + /// user email. + /// A representing the result of the asynchronous operation. + public async Task GetInProgressEnrolledCoursesAsync(string email) + { + try + { + email = "binon.yesudhas@nhs.net"; + var moodleUserInstanceUserIds = await this.GetUserInstancesByEmail(email); + if (moodleUserInstanceUserIds?.MoodleInstanceUserIds == null || + !moodleUserInstanceUserIds.MoodleInstanceUserIds.Any()) + { + throw new ArgumentException("UserIds are required."); + } + if (moodleUserInstanceUserIds.MoodleInstanceUserIds.ContainsKey("moodle-test")) + { + moodleUserInstanceUserIds.MoodleInstanceUserIds["moodle-test"] = 280; + } + + string statusFilter = "inprogress"; + + var client = await this.moodleBridgeHttpClient.GetClient(); + // Build query string (optional params) + var queryParams = new List(); + queryParams.Add($"months=0"); + if (statusFilter != null) + queryParams.Add($"statusfilter={statusFilter}"); + + var queryString = queryParams.Any() + ? "?" + string.Join("&", queryParams) + : string.Empty; + + var requestUri = $"api/v1/users/recent-courses{queryString}"; + + var response = await client.PostAsJsonAsync( + requestUri, + moodleUserInstanceUserIds).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + var options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + }; + + var result = System.Text.Json.JsonSerializer.Deserialize(json, options); + + return result ?? new MoodleCompletionsApiResponseModel(); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + throw new Exception($"Request failed with status code {response.StatusCode}"); + } + catch (Exception ex) + { + return null; + } + } + + /// + /// GetUserLearningHistory. + /// + /// user email. + /// The page Number. + /// A representing the result of the asynchronous operation. + public async Task GetUserCertificateAsync(string email, string filterText = "") + { + try + { + email = "binon.yesudhas@nhs.net"; + var moodleUserInstanceUserIds = await this.GetUserInstancesByEmail(email); + if (moodleUserInstanceUserIds?.MoodleInstanceUserIds == null || + !moodleUserInstanceUserIds.MoodleInstanceUserIds.Any()) + { + throw new ArgumentException("UserIds are required."); + } + if (moodleUserInstanceUserIds.MoodleInstanceUserIds.ContainsKey("moodle-test")) + { + moodleUserInstanceUserIds.MoodleInstanceUserIds["moodle-test"] = 280; + } + var client = await this.moodleBridgeHttpClient.GetClient(); + // Build query string (optional params) + var queryParams = new List(); + if (!string.IsNullOrWhiteSpace(filterText)) + { + queryParams.Add($"searchterm={Uri.EscapeDataString(filterText)}"); + } + + var queryString = queryParams.Any() + ? "?" + string.Join("&", queryParams) + : string.Empty; + + + var requestUri = $"api/v1/Users/certificates{queryString}"; + + var response = await client.PostAsJsonAsync( + requestUri, + moodleUserInstanceUserIds).ConfigureAwait(false); + + + if (response.IsSuccessStatusCode) + { + var options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + }; + + var result = await response.Content + .ReadFromJsonAsync(options) + .ConfigureAwait(false); + + return result ?? new MoodleCertificateResponseModel(); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + throw new Exception($"Request failed with status code {response.StatusCode}"); + } + catch (Exception ex) + { + return null; + } + } + + /// + /// GetUserCertificatefromMoodleInstancesAsync. + /// + /// moodleUserInstanceUserIds. + /// The page Number. + /// A representing the result of the asynchronous operation. + public async Task GetUserCertificateFromMoodleInstancesAsync(MoodleInstanceUserIdsViewModel moodleUserInstanceUserIds, string filterText = "") + { + try + { + if (moodleUserInstanceUserIds?.MoodleInstanceUserIds == null || + !moodleUserInstanceUserIds.MoodleInstanceUserIds.Any()) + { + throw new ArgumentException("UserIds are required."); + } + if (moodleUserInstanceUserIds.MoodleInstanceUserIds.ContainsKey("moodle-test")) + { + moodleUserInstanceUserIds.MoodleInstanceUserIds["moodle-test"] = 280; + } + var client = await this.moodleBridgeHttpClient.GetClient(); + + var queryParams = new List(); + if (!string.IsNullOrWhiteSpace(filterText)) + { + queryParams.Add($"searchterm={Uri.EscapeDataString(filterText)}"); + } + + var queryString = queryParams.Any() + ? "?" + string.Join("&", queryParams) + : string.Empty; + + + var requestUri = $"api/v1/Users/certificates{queryString}"; + + var response = await client.PostAsJsonAsync( + requestUri, + moodleUserInstanceUserIds).ConfigureAwait(false); + + + if (response.IsSuccessStatusCode) + { + var options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + }; + + var result = await response.Content + .ReadFromJsonAsync(options) + .ConfigureAwait(false); + + return result ?? new MoodleCertificateResponseModel(); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + throw new Exception($"Request failed with status code {response.StatusCode}"); + } + catch (Exception ex) + { + return null; + } + } + + /// + /// GetAllMoodleCategoriesAsync. + /// + /// A representing the result of the asynchronous operation. + public async Task> GetAllMoodleCategoriesAsync() + { + MoodleInstancesCategoriesResponseModel viewmodel = null; + + try + { + var client = await this.moodleBridgeHttpClient.GetClient(); + + var request = $"/api/v1/Courses/categories"; + var response = await client.GetAsync(request).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + var options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + }; + + viewmodel = System.Text.Json.JsonSerializer.Deserialize(result, options); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + return viewmodel.Results; + } + catch (Exception ex) + { + this.logger.LogError(ex, "An error occurred while fetching user instances by email."); + throw; // Re-throw the exception to ensure the caller is aware of the failure + } + } + + /// + /// GetCoursesByCategoryIdAsync. + /// + /// The categoryId. + /// + public async Task GetCoursesByCategoryIdAsync(string selectedcategoryId) + { + MoodleCourseResultsResponseModel viewmodel = null; + var (instanceName, categoryId) = selectedcategoryId.Split(':') is var p && p.Length == 2 ? (p[0], p[1]) : (null, null); + + try + { + var client = await this.moodleBridgeHttpClient.GetClient(); + + var request = $"api/v1/Courses/search?value={Uri.EscapeDataString(categoryId.ToString())}" + $"&instance={Uri.EscapeDataString(instanceName)}"; + var response = await client.GetAsync(request).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + + var options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + }; + + viewmodel = System.Text.Json.JsonSerializer + .Deserialize(result, options); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + return viewmodel ?? new MoodleCourseResultsResponseModel(); + } + catch (Exception ex) + { + this.logger.LogError(ex, "An error occurred while fetching Moodle categories."); + throw; + } + } + + /// + /// GetSubCategoryByCategoryIdAsync. + /// + /// The categoryId. + /// + public async Task> GetSubCategoryByCategoryIdAsync(string selectedcategoryId) + { + MoodleInstanceSubCategoryResponseModel subcategories = null; + var (instanceName, categoryId) = selectedcategoryId.Split(':') is var p && p.Length == 2 ? (p[0], p[1]) : (null, null); + + try + { + var client = await this.moodleBridgeHttpClient.GetClient(); + + var request = $"api/v1/Courses/{categoryId}/subcategories?{instanceName}"; + var response = await client.GetAsync(request).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + var options = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + }; + + subcategories = System.Text.Json.JsonSerializer.Deserialize(result, options); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + return subcategories.Results; + } + catch (Exception ex) + { + this.logger.LogError(ex, "An error occurred while fetching sub categories by category id."); + throw; + } + } + } +} diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MyLearningService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MyLearningService.cs index d9c124b89..12d9e42cd 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MyLearningService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MyLearningService.cs @@ -12,8 +12,10 @@ using LearningHub.Nhs.Models.Entities.Activity; using LearningHub.Nhs.Models.Entities.Resource; using LearningHub.Nhs.Models.Enums; + using LearningHub.Nhs.Models.Moodle; using LearningHub.Nhs.Models.Moodle.API; using LearningHub.Nhs.Models.MyLearning; + using LearningHub.Nhs.Models.Resource.AzureMediaAsset; using LearningHub.Nhs.OpenApi.Models.Configuration; using LearningHub.Nhs.OpenApi.Repositories.Helpers; using LearningHub.Nhs.OpenApi.Repositories.Interface.Repositories; @@ -75,6 +77,11 @@ public class MyLearningService : IMyLearningService /// private readonly IMoodleApiService moodleApiService; + /// + /// The moodleBridgeApiService. + /// + private readonly IMoodleBridgeApiService moodleBridgeApiService; + /// /// The mapper. /// @@ -99,6 +106,7 @@ public class MyLearningService : IMyLearningService /// The mediaResourceActivity. /// The resourceActivity /// The moodleApiService. + /// The moodleBridgeApiService. public MyLearningService( IResourceActivityRepository resourceActivityRepository, IMediaResourcePlayedSegmentRepository mediaResourcePlayedSegmentRepository, @@ -110,7 +118,8 @@ public MyLearningService( IScormActivityRepository scormActivityRepository, IMediaResourceActivityRepository mediaResourceActivity, IResourceRepository resourceRepository, - IMoodleApiService moodleApiService) + IMoodleApiService moodleApiService, + IMoodleBridgeApiService moodleBridgeApiService) { this.resourceActivityRepository = resourceActivityRepository; this.mediaResourcePlayedSegmentRepository = mediaResourcePlayedSegmentRepository; @@ -123,6 +132,7 @@ public MyLearningService( this.mediaResourceActivity = mediaResourceActivity; this.resourceRepository = resourceRepository; this.moodleApiService = moodleApiService; + this.moodleBridgeApiService = moodleBridgeApiService; } /// @@ -155,13 +165,12 @@ public async Task GetActivityDetailed(int userId, M /// /// The user id. /// The request model. /// The . - public async Task GetUserRecentMyLearningActivitiesAsync(int userId, MyLearningRequestModel requestModel) + public async Task GetUserRecentMyLearningActivitiesAsync(int userId, MyLearningApiRequestViewModel requestModel) { try { - var result = await resourceActivityRepository.GetUserRecentMyLearningActivities(userId, requestModel); - - var entrolledCourses = await this.moodleApiService.GetRecentEnrolledCoursesAsync(userId, requestModel, 6); + var result = await resourceActivityRepository.GetUserRecentMyLearningActivities(userId, requestModel.Request); + var entrolledCourses = await this.moodleBridgeApiService.GetRecentEnrolledCoursesAsync(requestModel.MoodleInstanceUserIds, requestModel.Request, 6); List mappedMyLearningActivities = new(); List mappedEnrolledCourses = new(); List combainedUserActivities = new(); @@ -208,43 +217,46 @@ public async Task GetUserRecentMyLearning if (entrolledCourses != null) { - mappedEnrolledCourses = entrolledCourses.Select(course => new MyLearningCombinedActivitiesViewModel - { - UserId = userId, - ResourceId = (int)course.Id, - ResourceVersionId = (int)course.Id, - IsCurrentResourceVersion = true, - ResourceReferenceId = (int)course.Id, - MajorVersion = 1, - MinorVersion = 0, - ResourceType = ResourceTypeEnum.Moodle, - Title = course.DisplayName, - CertificateEnabled = course.CertificateEnabled, - ActivityStatus = (course.Completed == true || course.ProgressPercentage.TrimEnd('%') == "100") ? ActivityStatusEnum.Completed : ActivityStatusEnum.Incomplete, - ActivityDate = course.LastAccessDate.HasValue - ? DateTimeOffset.FromUnixTimeSeconds(course.LastAccessDate.Value) - : DateTimeOffset.MinValue, - ScorePercentage = Convert.ToInt32(course.ProgressPercentage.TrimEnd('%')), - TotalActivities = course.TotalActivities, - CompletedActivities = course.CompletedActivities, - IsMostRecent = false, - ResourceDurationMilliseconds = 0, - CompletionPercentage = 0, - ProvidersJson = null, - AssessmentPassMark = 0, - AssessmentType = 0, - AssesmentScore = 0, - CertificateAwardedDate = course.EndDate.HasValue - ? DateTimeOffset.FromUnixTimeSeconds(course.EndDate.Value) - : DateTimeOffset.MinValue, - }).ToList(); + mappedEnrolledCourses = entrolledCourses?.Results? + .Where(r => r.Data?.Courses != null) + .SelectMany(r => r.Data.Courses) + .Select(course => new MyLearningCombinedActivitiesViewModel + { + UserId = userId, + ResourceId = (int)course.Id, + ResourceVersionId = (int)course.Id, + IsCurrentResourceVersion = true, + ResourceReferenceId = (int)course.Id, + MajorVersion = 1, + MinorVersion = 0, + ResourceType = ResourceTypeEnum.Moodle, + Title = course.DisplayName, + CertificateEnabled = course.CertificateEnabled, + ActivityStatus = (course.Completed == true || course.ProgressPercentage.TrimEnd('%') == "100") ? ActivityStatusEnum.Completed : ActivityStatusEnum.Incomplete, + ActivityDate = course.LastAccessDate.HasValue + ? DateTimeOffset.FromUnixTimeSeconds(course.LastAccessDate.Value) + : DateTimeOffset.MinValue, + ScorePercentage = Convert.ToInt32(course.ProgressPercentage.TrimEnd('%')), + TotalActivities = course.TotalActivities, + CompletedActivities = course.CompletedActivities, + IsMostRecent = false, + ResourceDurationMilliseconds = 0, + CompletionPercentage = 0, + ProvidersJson = null, + AssessmentPassMark = 0, + AssessmentType = 0, + AssesmentScore = 0, + CertificateAwardedDate = course.EndDate.HasValue + ? DateTimeOffset.FromUnixTimeSeconds(course.EndDate.Value) + : DateTimeOffset.MinValue, + }).ToList(); } // Combine both result sets combainedUserActivities = mappedMyLearningActivities.Concat(mappedEnrolledCourses).ToList(); - var pagedResults = combainedUserActivities.OrderByDescending(activity => activity.ActivityDate).Skip(requestModel.Skip).Take(requestModel.Take).ToList(); + var pagedResults = combainedUserActivities.OrderByDescending(activity => activity.ActivityDate).Skip(requestModel.Request.Skip).Take(requestModel.Request.Take).ToList(); // Count total records. MyLearningActivitiesDetailedViewModel viewModel = new MyLearningActivitiesDetailedViewModel() @@ -268,29 +280,29 @@ public async Task GetUserRecentMyLearning /// /// The user id. /// The request model. /// The . - public async Task GetUserLearningHistoryAsync(int userId, MyLearningRequestModel requestModel) + public async Task GetUserLearningHistoryAsync(int userId, MyLearningApiRequestViewModel requestModel) { try { - (string strActivityStatus, bool activityStatusEnumFlag) = resourceActivityRepository.GetActivityStatusFilter(requestModel); - (string strResourceTypes, bool resourceTypeFlag) = resourceActivityRepository.ApplyResourceTypesfilters(requestModel); + (string strActivityStatus, bool activityStatusEnumFlag) = resourceActivityRepository.GetActivityStatusFilter(requestModel.Request); + (string strResourceTypes, bool resourceTypeFlag) = resourceActivityRepository.ApplyResourceTypesfilters(requestModel.Request); var result = new List(); if ( - (!activityStatusEnumFlag && !resourceTypeFlag && !requestModel.Courses) || - (activityStatusEnumFlag && resourceTypeFlag && !requestModel.Courses) || - (activityStatusEnumFlag && !resourceTypeFlag && !requestModel.Courses) || - (!activityStatusEnumFlag && resourceTypeFlag && !requestModel.Courses) || - (!activityStatusEnumFlag && resourceTypeFlag && requestModel.Courses) || - (activityStatusEnumFlag && resourceTypeFlag && requestModel.Courses)) + (!activityStatusEnumFlag && !resourceTypeFlag && !requestModel.Request.Courses) || + (activityStatusEnumFlag && resourceTypeFlag && !requestModel.Request.Courses) || + (activityStatusEnumFlag && !resourceTypeFlag && !requestModel.Request.Courses) || + (!activityStatusEnumFlag && resourceTypeFlag && !requestModel.Request.Courses) || + (!activityStatusEnumFlag && resourceTypeFlag && requestModel.Request.Courses) || + (activityStatusEnumFlag && resourceTypeFlag && requestModel.Request.Courses)) { - if (requestModel.SearchText != null) + if (requestModel.Request.SearchText != null) { - result = await resourceActivityRepository.GetUserLearningHistoryBasedonSearchText(userId, requestModel); + result = await resourceActivityRepository.GetUserLearningHistoryBasedonSearchText(userId, requestModel.Request); } else { - result = await resourceActivityRepository.GetUserLearningHistory(userId, requestModel); + result = await resourceActivityRepository.GetUserLearningHistory(userId, requestModel.Request); } } @@ -338,56 +350,60 @@ public async Task GetUserLearningHistoryA }).ToList(); } - List entrolledCourses = new(); + MoodleCompletionsApiResponseModel entrolledCourses = new(); if ( - (!activityStatusEnumFlag && !resourceTypeFlag && !requestModel.Courses) || - (!activityStatusEnumFlag && !resourceTypeFlag && requestModel.Courses) || - (!activityStatusEnumFlag && resourceTypeFlag && requestModel.Courses) || - (activityStatusEnumFlag && resourceTypeFlag && requestModel.Courses) || - (activityStatusEnumFlag && !resourceTypeFlag && requestModel.Courses) || - (activityStatusEnumFlag && !resourceTypeFlag && !requestModel.Courses)) + (!activityStatusEnumFlag && !resourceTypeFlag && !requestModel.Request.Courses) || + (!activityStatusEnumFlag && !resourceTypeFlag && requestModel.Request.Courses) || + (!activityStatusEnumFlag && resourceTypeFlag && requestModel.Request.Courses) || + (activityStatusEnumFlag && resourceTypeFlag && requestModel.Request.Courses) || + (activityStatusEnumFlag && !resourceTypeFlag && requestModel.Request.Courses) || + (activityStatusEnumFlag && !resourceTypeFlag && !requestModel.Request.Courses)) { - entrolledCourses = await this.moodleApiService.GetEnrolledCoursesHistoryAsync(userId, requestModel); + ////entrolledCourses = await this.moodleApiService.GetEnrolledCoursesHistoryAsync(userId, requestModel.Request); + entrolledCourses = await this.moodleBridgeApiService.GetEnrolledCoursesHistoryAsync(requestModel.MoodleInstanceUserIds, requestModel.Request); if (entrolledCourses != null) { - mappedEnrolledCourses = entrolledCourses.Select(course => new MyLearningCombinedActivitiesViewModel - { - UserId = userId, - ResourceId = (int)course.Id, - ResourceVersionId = (int)course.Id, - IsCurrentResourceVersion = true, - ResourceReferenceId = (int)course.Id, - MajorVersion = 1, - MinorVersion = 0, - ResourceType = ResourceTypeEnum.Moodle, - Title = course.DisplayName, - CertificateEnabled = course.CertificateEnabled, - ActivityStatus = (course.Completed == true || course.ProgressPercentage.TrimEnd('%') == "100") ? ActivityStatusEnum.Completed : ActivityStatusEnum.Incomplete, - ActivityDate = course.LastAccessDate.HasValue + mappedEnrolledCourses = entrolledCourses?.Results? + .Where(r => r.Data?.Courses != null) + .SelectMany(r => r.Data.Courses) + .Select(course => new MyLearningCombinedActivitiesViewModel + { + UserId = userId, + ResourceId = (int)course.Id, + ResourceVersionId = (int)course.Id, + IsCurrentResourceVersion = true, + ResourceReferenceId = (int)course.Id, + MajorVersion = 1, + MinorVersion = 0, + ResourceType = ResourceTypeEnum.Moodle, + Title = course.DisplayName, + CertificateEnabled = course.CertificateEnabled, + ActivityStatus = (course.Completed == true || course.ProgressPercentage.TrimEnd('%') == "100") ? ActivityStatusEnum.Completed : ActivityStatusEnum.Incomplete, + ActivityDate = course.LastAccessDate.HasValue ? DateTimeOffset.FromUnixTimeSeconds(course.LastAccessDate.Value) : DateTimeOffset.MinValue, - ScorePercentage = int.TryParse(course.ProgressPercentage.TrimEnd('%'), out var score) ? score : 0, - TotalActivities = course.TotalActivities, - CompletedActivities = course.CompletedActivities, - IsMostRecent = false, - ResourceDurationMilliseconds = 0, - CompletionPercentage = 0, - ProvidersJson = null, - AssessmentPassMark = 0, - AssessmentType = 0, - AssesmentScore = 0, - CertificateAwardedDate = course.EndDate.HasValue + ScorePercentage = int.TryParse(course.ProgressPercentage.TrimEnd('%'), out var score) ? score : 0, + TotalActivities = course.TotalActivities, + CompletedActivities = course.CompletedActivities, + IsMostRecent = false, + ResourceDurationMilliseconds = 0, + CompletionPercentage = 0, + ProvidersJson = null, + AssessmentPassMark = 0, + AssessmentType = 0, + AssesmentScore = 0, + CertificateAwardedDate = course.EndDate.HasValue ? DateTimeOffset.FromUnixTimeSeconds(course.EndDate.Value) : DateTimeOffset.MinValue, - }).ToList(); + }).ToList(); } } // Combine both result sets combainedUserActivities = mappedMyLearningActivities.Concat(mappedEnrolledCourses).ToList(); - var pagedResults = combainedUserActivities.OrderByDescending(activity => activity.ActivityDate).Skip(requestModel.Skip).Take(requestModel.Take).ToList(); + var pagedResults = combainedUserActivities.OrderByDescending(activity => activity.ActivityDate).Skip(requestModel.Request.Skip).Take(requestModel.Request.Take).ToList(); // Count total records. MyLearningActivitiesDetailedViewModel viewModel = new MyLearningActivitiesDetailedViewModel() @@ -702,20 +718,19 @@ public async Task> PopulateMyLearningDetai /// The user id. /// The request model /// The . - public async Task GetUserCertificateDetails(int userId, MyLearningRequestModel requestModel) + public async Task GetUserCertificateDetails(int userId, MyLearningApiRequestViewModel requestModel) { - Task>? courseCertificatesTask = null; - var filteredResource = GetFilteredResourceType(requestModel); + Task? courseCertificatesTask = null; + var filteredResource = GetFilteredResourceType(requestModel.Request); - if (filteredResource.Count() == 0 || (filteredResource.Any() && requestModel.Courses)) + if (filteredResource.Count() == 0 || (filteredResource.Any() && requestModel.Request.Courses)) { - courseCertificatesTask = !string.IsNullOrWhiteSpace(requestModel.SearchText) ? - moodleApiService.GetUserCertificateAsync(userId, requestModel.SearchText) : moodleApiService.GetUserCertificateAsync(userId); - + courseCertificatesTask = !string.IsNullOrWhiteSpace(requestModel.Request.SearchText) ? + moodleBridgeApiService.GetUserCertificateFromMoodleInstancesAsync(requestModel.MoodleInstanceUserIds, requestModel.Request.SearchText) : moodleBridgeApiService.GetUserCertificateFromMoodleInstancesAsync(requestModel.MoodleInstanceUserIds); } - var resourceCertificatesTask = !string.IsNullOrWhiteSpace(requestModel.SearchText) ? - resourceRepository.GetUserCertificateDetails(userId, requestModel.SearchText) : resourceRepository.GetUserCertificateDetails(userId); + var resourceCertificatesTask = !string.IsNullOrWhiteSpace(requestModel.Request.SearchText) ? + resourceRepository.GetUserCertificateDetails(userId, requestModel.Request.SearchText) : resourceRepository.GetUserCertificateDetails(userId); // Await all active tasks in parallel @@ -730,23 +745,24 @@ public async Task GetUserCertificateDet if (courseCertificatesTask != null) { - var courseCertificates = courseCertificatesTask.Result ?? Enumerable.Empty(); - - mappedCourseCertificates = courseCertificates.Select(c => new UserCertificateViewModel - { - Title = string.IsNullOrWhiteSpace(c.ResourceTitle) ? c.ResourceName : c.ResourceTitle, - ResourceTypeId = (int)ResourceTypeEnum.Moodle, - ResourceReferenceId = 0, - MajorVersion = 0, - MinorVersion = 0, - AwardedDate = c.AwardedDate.HasValue + mappedCourseCertificates = courseCertificatesTask.Result?.Results? + .Where(r => r.Data?.Certificates != null) + .SelectMany(r => r.Data.Certificates) + .Select(c => new UserCertificateViewModel + { + Title = string.IsNullOrWhiteSpace(c.ResourceTitle) ? c.ResourceName : c.ResourceTitle, + ResourceTypeId = (int)ResourceTypeEnum.Moodle, + ResourceReferenceId = 0, + MajorVersion = 0, + MinorVersion = 0, + AwardedDate = c.AwardedDate.HasValue ? DateTimeOffset.FromUnixTimeSeconds(c.AwardedDate.Value) : DateTimeOffset.MinValue, - CertificatePreviewUrl = c.PreviewLink, - CertificateDownloadUrl = c.DownloadLink, - ResourceVersionId = 0, - ProvidersJson = null, - }); + CertificatePreviewUrl = c.PreviewLink, + CertificateDownloadUrl = c.DownloadLink, + ResourceVersionId = 0, + ProvidersJson = null, + }); } var allCertificates = resourceCertificates.Concat(mappedCourseCertificates); @@ -764,8 +780,8 @@ public async Task GetUserCertificateDet var totalCount = orderedCertificates.Count(); var pagedResults = orderedCertificates - .Skip(requestModel.Skip) - .Take(requestModel.Take) + .Skip(requestModel.Request.Skip) + .Take(requestModel.Request.Take) .ToList(); return new MyLearningCertificatesDetailedViewModel @@ -775,9 +791,6 @@ public async Task GetUserCertificateDet }; } - - - private IQueryable ApplyFilters(IQueryable query, MyLearningRequestModel requestModel) { // Text filter - Title, Keywords or Description. diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs index 73c887df7..1670bc090 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs @@ -39,6 +39,7 @@ public static void AddServices(this IServiceCollection services, IConfiguration } services.AddHttpClient(); + services.AddHttpClient(); services.AddScoped(); services.AddScoped(); services.AddScoped(); @@ -90,6 +91,7 @@ public static void AddServices(this IServiceCollection services, IConfiguration services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddScoped(); // Register IFindwiseApiFacade based on feature flag diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj index 93461ce2b..27ab96576 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Tests/LearningHub.Nhs.OpenApi.Tests.csproj @@ -11,7 +11,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Configuration/ConfigurationExtensions.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Configuration/ConfigurationExtensions.cs index 309eb8bd5..07c0e431b 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/Configuration/ConfigurationExtensions.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Configuration/ConfigurationExtensions.cs @@ -46,10 +46,16 @@ public static class ConfigurationExtensions public const string AzureSectionName = "Azure"; /// - /// The FindwiseSectionName. + /// The MoodleSectionName. /// public const string MoodleSectionName = "Moodle"; + /// + /// The MoodleBridgeSectionName. + /// + public const string MoodleBridgeSectionName = "MoodleBridgeAPIConfig"; + + /// /// The DatabricksSectionName. /// @@ -83,6 +89,8 @@ public static void AddConfig(this IServiceCollection services, IConfiguration co services.AddOptions().Bind(config.GetSection(MoodleSectionName)); + services.AddOptions().Bind(config.GetSection(MoodleBridgeSectionName)); + services.AddOptions().Bind(config.GetSection(DatabricksSectionName)); services.AddOptions().Bind(config.GetSection(FeatureFlagsSectionName)); diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/CategoryController.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/CategoryController.cs index cc4b65562..f0e11089e 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/CategoryController.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/CategoryController.cs @@ -19,16 +19,19 @@ public class CategoryController : OpenApiControllerBase { private readonly ICategoryService categoryService; private readonly IMoodleApiService moodleApiService; + private readonly IMoodleBridgeApiService moodleBridgeApiService; /// /// Initializes a new instance of the class. /// /// The category service. /// The moodleApi service. - public CategoryController(ICategoryService categoryService, IMoodleApiService moodleApiService) + /// The moodle Bridge Api service. + public CategoryController(ICategoryService categoryService, IMoodleApiService moodleApiService, IMoodleBridgeApiService moodleBridgeApiService) { this.categoryService = categoryService; this.moodleApiService = moodleApiService; + this.moodleBridgeApiService = moodleBridgeApiService; } /// @@ -51,9 +54,9 @@ public async Task GetCatalogueVersionCategory(int catalogueNodeVe /// The catalogue. [HttpGet] [Route("GetCoursesByCategoryId/{categoryId}")] - public async Task GetCoursesByCategoryId(int categoryId) + public async Task GetCoursesByCategoryId(string categoryId) { - var courses = await this.moodleApiService.GetCoursesByCategoryIdAsync(categoryId); + var courses = await this.moodleBridgeApiService.GetCoursesByCategoryIdAsync(categoryId); return this.Ok(courses); } @@ -64,9 +67,9 @@ public async Task GetCoursesByCategoryId(int categoryId) /// The catalogue. [HttpGet] [Route("GetSubCategoryByCategoryId/{categoryId}")] - public async Task GetSubCategoryByCategoryId(int categoryId) + public async Task GetSubCategoryByCategoryId(string categoryId) { - var subCategories = await this.moodleApiService.GetSubCategoryByCategoryIdAsync(categoryId); + var subCategories = await this.moodleBridgeApiService.GetSubCategoryByCategoryIdAsync(categoryId); return this.Ok(subCategories); } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/DashboardController.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/DashboardController.cs index 987904d94..6131a92ec 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/DashboardController.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/DashboardController.cs @@ -1,6 +1,7 @@ namespace LearningHub.NHS.OpenAPI.Controllers { using System.Threading.Tasks; + using LearningHub.Nhs.Models.MyLearning; using LearningHub.Nhs.OpenApi.Services.Interface.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -37,7 +38,7 @@ public DashboardController(IUserService userService, IDashboardService dashboard [Route("resources/{dashboardType}/{pageNumber}")] public async Task GetResources(string dashboardType, int pageNumber = 1) { - var response = await dashboardService.GetResources(dashboardType, pageNumber, this.CurrentUserId.GetValueOrDefault()); + var response = await this.dashboardService.GetResources(dashboardType, pageNumber, this.CurrentUserId.GetValueOrDefault()); return this.Ok(response); } @@ -51,7 +52,7 @@ public async Task GetResources(string dashboardType, int pageNumbe [Route("catalogues/{dashboardType}/{pageNumber}")] public async Task GetCatalogues(string dashboardType, int pageNumber = 1) { - var response = await dashboardService.GetCatalogues(dashboardType, pageNumber, this.CurrentUserId.GetValueOrDefault()); + var response = await this.dashboardService.GetCatalogues(dashboardType, pageNumber, this.CurrentUserId.GetValueOrDefault()); return this.Ok(response); } @@ -65,22 +66,20 @@ public async Task GetCatalogues(string dashboardType, int pageNum [Route("myaccesslearning/{dashboardType}/{pageNumber}")] public async Task GetMyAccessLearnings(string dashboardType, int pageNumber = 1) { - var response = await dashboardService.GetMyAccessLearnings(dashboardType, pageNumber, this.CurrentUserId.GetValueOrDefault()); + var response = await this.dashboardService.GetMyAccessLearnings(dashboardType, pageNumber, this.CurrentUserId.GetValueOrDefault()); return this.Ok(response); } /// /// Gets Catalogues. /// - /// The dashboardTrayLearningResource type. - /// The dashboard type. - /// The page Number. + /// The GetMyCoursesAndElearningRequestModel. /// IActionResult. - [HttpGet] - [Route("GetMyCoursesAndElearning/{dashboardTrayLearningResourceType}/{dashboardType}/{pageNumber}")] - public async Task GetMyCoursesAndElearning(string dashboardTrayLearningResourceType, string dashboardType, int pageNumber = 1) + [HttpPost] + [Route("GetMyCoursesAndElearning")] + public async Task GetMyCoursesAndElearning([FromBody] GetMyCoursesAndElearningRequestModel request) { - var response = await dashboardService.GetMyCoursesAndElearning(dashboardTrayLearningResourceType, dashboardType, pageNumber, this.CurrentUserId.GetValueOrDefault(), "All"); + var response = await this.dashboardService.GetMyCoursesAndElearning(request, this.CurrentUserId.GetValueOrDefault(), "All"); return this.Ok(response); } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MoodleBridgeController.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MoodleBridgeController.cs new file mode 100644 index 000000000..eb39f11cd --- /dev/null +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MoodleBridgeController.cs @@ -0,0 +1,51 @@ +namespace LearningHub.NHS.OpenAPI.Controllers +{ + using Microsoft.AspNetCore.Authorization; + using Microsoft.AspNetCore.Mvc; + using System.Threading.Tasks; + using LearningHub.Nhs.OpenApi.Services.Interface.Services; + /// + /// Moodle Bridge operations. + /// + [Route("MoodleBridge")] + [ApiController] + [Authorize] + public class MoodleBridgeController : Controller + { + private readonly IMoodleBridgeApiService moodleBridgeApiService; + + /// + /// Initializes a new instance of the class. + /// + /// The moodle bridge service. + public MoodleBridgeController(IMoodleBridgeApiService moodleBridgeApiService) + { + this.moodleBridgeApiService = moodleBridgeApiService; + } + + /// + /// The GetMoodle Instances UserIds. + /// + /// The LH user email. + /// The . + [HttpGet] + [Route("GetUserInstancesByEmail/{email}")] + public async Task GetUserInstancesByEmail(string email) + { + var moodleUser = await this.moodleBridgeApiService.GetUserInstancesByEmail(email); + return this.Ok(moodleUser); + } + + /// + /// GetAllMoodleCategoriesAsync. + /// + /// A representing the result of the asynchronous operation. + [HttpGet] + [Route("GetAllMoodleCategories")] + public async Task GetAllMoodleCategoriesAsync() + { + var moodleCategories = await this.moodleBridgeApiService.GetAllMoodleCategoriesAsync(); + return this.Ok(moodleCategories); + } + } +} diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MyLearningController.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MyLearningController.cs index 4763f21cc..fbd05a867 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MyLearningController.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MyLearningController.cs @@ -59,7 +59,7 @@ public async Task GetActivityDetailed([FromBody] MyLearningReques /// The . [HttpPost] [Route("GetUserRecentMyLearningActivities")] - public async Task GetUserRecentMyLearningActivities([FromBody] MyLearningRequestModel requestModel) + public async Task GetUserRecentMyLearningActivities([FromBody] MyLearningApiRequestViewModel requestModel) { var activityModel = await this.myLearningService.GetUserRecentMyLearningActivitiesAsync(this.CurrentUserId.GetValueOrDefault(), requestModel); return this.Ok(activityModel); @@ -72,7 +72,7 @@ public async Task GetUserRecentMyLearningActivities([FromBody] My /// The . [HttpPost] [Route("GetUserLearningHistory")] - public async Task GetUserLearningHistory([FromBody] MyLearningRequestModel requestModel) + public async Task GetUserLearningHistory([FromBody] MyLearningApiRequestViewModel requestModel) { var activityModel = await this.myLearningService.GetUserLearningHistoryAsync(this.CurrentUserId.GetValueOrDefault(), requestModel); return this.Ok(activityModel); @@ -118,7 +118,7 @@ public async Task GetResourceCertificateDetails(int resourceRefer /// A representing the result of the asynchronous operation. [HttpPost] [Route("GetUserCertificateDetails")] - public async Task GetUserCertificateDetails([FromBody] MyLearningRequestModel requestModel) + public async Task GetUserCertificateDetails([FromBody] MyLearningApiRequestViewModel requestModel) { var certificateDetails = await this.myLearningService.GetUserCertificateDetails(this.CurrentUserId.GetValueOrDefault(), requestModel); return this.Ok(certificateDetails); diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj index de5b7a6d7..57eb26f4f 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj +++ b/OpenAPI/LearningHub.Nhs.OpenApi/LearningHub.NHS.OpenAPI.csproj @@ -19,7 +19,7 @@ - + diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json b/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json index 42b84d3b8..3a96c27b9 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json +++ b/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json @@ -156,6 +156,10 @@ "ApiWsRestFormat": "json", "ApiWsToken": "" }, + "MoodleBridgeAPIConfig": { + "BaseUrl": "", + "Token": "" + }, "Databricks": { "InstanceUrl": "", "Token": "", diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj index 2a259d6b2..79f6af7f9 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services.Interface/LearningHub.Nhs.ReportApi.Services.Interface.csproj @@ -16,7 +16,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj index aebb8bb75..c8ca7a2ae 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services.UnitTests/LearningHub.Nhs.ReportApi.Services.UnitTests.csproj @@ -18,7 +18,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj index acfb75739..89bca5ef2 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Services/LearningHub.Nhs.ReportApi.Services.csproj @@ -19,7 +19,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj b/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj index 9d86c24a0..ae1444ed9 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi.Shared/LearningHub.Nhs.ReportApi.Shared.csproj @@ -17,7 +17,7 @@ - + diff --git a/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj b/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj index f31ff35e5..c19afef98 100644 --- a/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj +++ b/ReportAPI/LearningHub.Nhs.ReportApi/LearningHub.Nhs.ReportApi.csproj @@ -20,7 +20,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj b/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj index 3a7660599..0462105ff 100644 --- a/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj +++ b/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj @@ -29,7 +29,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj b/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj index e1b7896b8..8d695c492 100644 --- a/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj +++ b/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj b/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj index 4acbd2e13..100e6600d 100644 --- a/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj +++ b/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj @@ -11,7 +11,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/CatalogueNodeVersionCategoryCreate.sql b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/CatalogueNodeVersionCategoryCreate.sql index cd0fa408f..9818d8f75 100644 --- a/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/CatalogueNodeVersionCategoryCreate.sql +++ b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/CatalogueNodeVersionCategoryCreate.sql @@ -6,12 +6,14 @@ -- Modification History -- -- 14-10-2025 SA Initial Revision. +-- 11-03-2026 SA Added instance name ------------------------------------------------------------------------------- CREATE PROCEDURE [hierarchy].[CatalogueNodeVersionCategoryCreate] ( @userId INT, @CatalogueNodeVersionId INT, - @CategoryId INT, + @categoryId INT, + @instanceName VARCHAR(50), @UserTimezoneOffset int = NULL ) @@ -33,19 +35,21 @@ BEGIN END INSERT INTO [hierarchy].[CatalogueNodeVersionCategory] - ([CatalogueNodeVersionId] - ,[CategoryId] - ,[Deleted] - ,[CreateUserId] - ,[CreateDate] - ,[AmendUserId] - ,[AmendDate]) - VALUES - (@CatalogueNodeVersionId - ,@CategoryId - ,0 - ,@userId - ,@AmendDate - ,@userId - ,@AmendDate) + ([CatalogueNodeVersionId] + ,[CategoryId] + ,[InstanceName] + ,[Deleted] + ,[CreateUserId] + ,[CreateDate] + ,[AmendUserId] + ,[AmendDate]) + VALUES + (@CatalogueNodeVersionId + ,@categoryId + ,@instanceName + ,0 + ,@userId + ,@AmendDate + ,@userId + ,@AmendDate) END \ No newline at end of file diff --git a/WebAPI/LearningHub.Nhs.Database/Tables/Hierarchy/CatalogueNodeVersionCategory.sql b/WebAPI/LearningHub.Nhs.Database/Tables/Hierarchy/CatalogueNodeVersionCategory.sql index c3ddc4832..b5c9f3f15 100644 --- a/WebAPI/LearningHub.Nhs.Database/Tables/Hierarchy/CatalogueNodeVersionCategory.sql +++ b/WebAPI/LearningHub.Nhs.Database/Tables/Hierarchy/CatalogueNodeVersionCategory.sql @@ -2,6 +2,7 @@ [Id] [int] IDENTITY(1,1) NOT NULL, [CatalogueNodeVersionId] [int] NOT NULL, [CategoryId] [int] NOT NULL, + [InstanceName] [varchar](50) NULL, [Deleted] [bit] NOT NULL, [CreateUserId] [int] NOT NULL, [CreateDate] [datetimeoffset](7) NOT NULL, diff --git a/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj b/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj index 5d12c4600..8273e219f 100644 --- a/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj +++ b/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj @@ -10,7 +10,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj b/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj index b7cca29dc..a2628d76c 100644 --- a/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj +++ b/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj b/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj index 6ee630341..73e99b72e 100644 --- a/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj +++ b/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj @@ -16,7 +16,7 @@ - + all diff --git a/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj b/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj index dbb1f6a30..6b02d693a 100644 --- a/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj +++ b/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj @@ -13,7 +13,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj b/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj index 98cec165a..d27db0e89 100644 --- a/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj +++ b/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj @@ -13,7 +13,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj index 3a2cb8961..1a8367ea1 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj @@ -25,7 +25,7 @@ - + all diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj index b275eae94..56c3518c1 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj index a18eb4196..e4a707d63 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj @@ -10,7 +10,7 @@ - + all diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj index bb23ca661..a6d13b605 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj index 82a9b4aa6..2e25b373f 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj @@ -10,7 +10,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj index de745363e..e21f1b8e1 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj @@ -12,7 +12,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From cce3e9dbcce5c8f10500877142674f0eba1fb533 Mon Sep 17 00:00:00 2001 From: swapnamol-abraham Date: Thu, 19 Mar 2026 09:54:14 +0000 Subject: [PATCH 2/2] Removed commented lines and unused files --- .../Configuration/MoodleBridgeApiConfig.cs | 33 ------------------- .../Controllers/BaseController.cs | 3 +- .../Services/IMoodleBridgeApiService.cs | 2 +- .../Services/MoodleBridgeApiService.cs | 26 +-------------- .../Controllers/MoodleBridgeController.cs | 1 + 5 files changed, 4 insertions(+), 61 deletions(-) delete mode 100644 LearningHub.Nhs.WebUI/Configuration/MoodleBridgeApiConfig.cs diff --git a/LearningHub.Nhs.WebUI/Configuration/MoodleBridgeApiConfig.cs b/LearningHub.Nhs.WebUI/Configuration/MoodleBridgeApiConfig.cs deleted file mode 100644 index 2e7e4b566..000000000 --- a/LearningHub.Nhs.WebUI/Configuration/MoodleBridgeApiConfig.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace LearningHub.Nhs.WebUI.Configuration -{ - /// - /// The Moodle Bridge Settings. - /// - public class MoodleBridgeApiConfig - { - /////// - /////// Gets or sets the base url for the Moodle service. - /////// - ////public string BaseUrl { get; set; } = null!; - - /////// - /////// Gets or sets the Web service Rest Format. - /////// - ////public string MoodleWSRestFormat { get; set; } = null!; - - /////// - /////// Gets or sets the token. - /////// - ////public string WSToken { get; set; } = null!; - - /////// - /////// Gets or sets the token. - /////// - ////public string ApiPath { get; set; } = "webservice/rest/server.php"; - - /////// - /////// Gets or sets the token. - /////// - ////public string CoursePath { get; set; } = "course/view.php"; - } -} diff --git a/LearningHub.Nhs.WebUI/Controllers/BaseController.cs b/LearningHub.Nhs.WebUI/Controllers/BaseController.cs index dd72350ec..77fd780ad 100644 --- a/LearningHub.Nhs.WebUI/Controllers/BaseController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/BaseController.cs @@ -126,8 +126,7 @@ public async Task GetUserIdsPerInstances() { if (this.moodleUserIds == null) { - ////var moodleUserInstances = await this.moodleBridgeApiService.GetUserInstancesByEmail(this.CurrentUserEmail); - var moodleUserInstances = await this.moodleBridgeApiService.GetUserInstancesByEmail("binon.yesudhas@nhs.net"); + var moodleUserInstances = await this.moodleBridgeApiService.GetUserInstancesByEmail(this.CurrentUserEmail); this.moodleUserIds = moodleUserInstances; } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMoodleBridgeApiService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMoodleBridgeApiService.cs index e099e8bb9..a3aa57b0d 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMoodleBridgeApiService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMoodleBridgeApiService.cs @@ -61,7 +61,7 @@ public interface IMoodleBridgeApiService /// GetUserCertificateFromMoodleInstancesAsync. /// /// Moodle Instances user id. - /// MyLearningRequestModel requestModel. + /// filterText. /// A representing the result of the asynchronous operation. Task GetUserCertificateFromMoodleInstancesAsync(MoodleInstanceUserIdsViewModel moodleUserInstanceUserIds, string filterText = ""); diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleBridgeApiService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleBridgeApiService.cs index 599569673..57fab7f83 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleBridgeApiService.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleBridgeApiService.cs @@ -105,11 +105,6 @@ public async Task GetRecentEnrolledCoursesAsy throw new ArgumentException("UserIds are required."); } - if (moodleUserInstanceUserIds.MoodleInstanceUserIds.ContainsKey("moodle-test")) - { - moodleUserInstanceUserIds.MoodleInstanceUserIds["moodle-test"] = 280; - } - string statusFilter = string.Empty; ; if ((requestModel.Incomplete && requestModel.Complete) || (!requestModel.Incomplete && !requestModel.Complete)) @@ -193,11 +188,6 @@ public async Task GetEnrolledCoursesHistoryAs throw new ArgumentException("UserIds are required."); } - if (moodleUserInstanceUserIds.MoodleInstanceUserIds.ContainsKey("moodle-test")) - { - moodleUserInstanceUserIds.MoodleInstanceUserIds["moodle-test"] = 280; - } - string statusFilter = string.Empty; ; if ((requestModel.Incomplete && requestModel.Complete) || (!requestModel.Incomplete && !requestModel.Complete)) @@ -269,17 +259,12 @@ public async Task GetInProgressEnrolledCourse { try { - email = "binon.yesudhas@nhs.net"; var moodleUserInstanceUserIds = await this.GetUserInstancesByEmail(email); if (moodleUserInstanceUserIds?.MoodleInstanceUserIds == null || !moodleUserInstanceUserIds.MoodleInstanceUserIds.Any()) { throw new ArgumentException("UserIds are required."); } - if (moodleUserInstanceUserIds.MoodleInstanceUserIds.ContainsKey("moodle-test")) - { - moodleUserInstanceUserIds.MoodleInstanceUserIds["moodle-test"] = 280; - } string statusFilter = "inprogress"; @@ -335,17 +320,12 @@ public async Task GetUserCertificateAsync(string { try { - email = "binon.yesudhas@nhs.net"; var moodleUserInstanceUserIds = await this.GetUserInstancesByEmail(email); if (moodleUserInstanceUserIds?.MoodleInstanceUserIds == null || !moodleUserInstanceUserIds.MoodleInstanceUserIds.Any()) { throw new ArgumentException("UserIds are required."); } - if (moodleUserInstanceUserIds.MoodleInstanceUserIds.ContainsKey("moodle-test")) - { - moodleUserInstanceUserIds.MoodleInstanceUserIds["moodle-test"] = 280; - } var client = await this.moodleBridgeHttpClient.GetClient(); // Build query string (optional params) var queryParams = new List(); @@ -407,10 +387,6 @@ public async Task GetUserCertificateFromMoodleIn { throw new ArgumentException("UserIds are required."); } - if (moodleUserInstanceUserIds.MoodleInstanceUserIds.ContainsKey("moodle-test")) - { - moodleUserInstanceUserIds.MoodleInstanceUserIds["moodle-test"] = 280; - } var client = await this.moodleBridgeHttpClient.GetClient(); var queryParams = new List(); @@ -492,7 +468,7 @@ public async Task> GetAllMoodleCategoriesAsync() catch (Exception ex) { this.logger.LogError(ex, "An error occurred while fetching user instances by email."); - throw; // Re-throw the exception to ensure the caller is aware of the failure + throw; } } diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MoodleBridgeController.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MoodleBridgeController.cs index eb39f11cd..f7a0e11d2 100644 --- a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MoodleBridgeController.cs +++ b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MoodleBridgeController.cs @@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Mvc; using System.Threading.Tasks; using LearningHub.Nhs.OpenApi.Services.Interface.Services; + /// /// Moodle Bridge operations. ///