diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Configuration/WebSettings.cs b/AdminUI/LearningHub.Nhs.AdminUI/Configuration/WebSettings.cs index f8e3c1565..5c8ab554f 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Configuration/WebSettings.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/Configuration/WebSettings.cs @@ -27,6 +27,11 @@ public class WebSettings /// public string LearningHubApiUrl { get; set; } + /// + /// Gets or sets the OpenApiUrl. + /// + public string OpenApiUrl { get; set; } + /// /// Gets or sets the user api url. /// diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Helpers/IOpenApiFacade.cs b/AdminUI/LearningHub.Nhs.AdminUI/Helpers/IOpenApiFacade.cs new file mode 100644 index 000000000..2bcded72b --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Helpers/IOpenApiFacade.cs @@ -0,0 +1,59 @@ +namespace LearningHub.Nhs.AdminUI.Helpers +{ + using System.Threading.Tasks; + using LearningHub.Nhs.Models.Common; + + /// + /// Defines the . + /// + public interface IOpenApiFacade + { + /// + /// The GetAsync. + /// + /// The type. + /// The url. + /// The . + Task GetAsync(string url) + where T : class, new(); + + /// + /// The PostAsync. + /// + /// The type. + /// The url. + /// The body. + /// The . + Task PostAsync(string url, T body) + where T : class, new(); + + /// + /// The PostAsync. + /// + /// The type. + /// . + /// The url. + /// The body. + /// The . + Task PostAsync(string url, TBody body) + where T : class, new() + where TBody : class, new(); + + /// + /// The PutAsync. + /// + /// The url. + /// The . + Task PutAsync(string url); + + /// + /// The PutAsync. + /// + /// . + /// The url. + /// The body. + /// The . + Task PutAsync(string url, T body) + where T : class, new(); + } +} diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Helpers/OpenApiFacade.cs b/AdminUI/LearningHub.Nhs.AdminUI/Helpers/OpenApiFacade.cs new file mode 100644 index 000000000..6169d8e6b --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Helpers/OpenApiFacade.cs @@ -0,0 +1,241 @@ +namespace LearningHub.Nhs.AdminUI.Helpers +{ + using System; + using System.Net.Http; + using System.Text; + using System.Threading.Tasks; + using LearningHub.Nhs.AdminUI.Interfaces; + using LearningHub.Nhs.Models.Common; + using Newtonsoft.Json; + + /// + /// Defines the . + /// + public class OpenApiFacade : IOpenApiFacade + { + /// + /// Defines the _client. + /// + private readonly IOpenApiHttpClient client; + + /// + /// Initializes a new instance of the class. + /// + /// The client. + public OpenApiFacade(IOpenApiHttpClient client) + { + this.client = client; + } + + /// + /// The GetAsync. + /// + /// . + /// The url. + /// The . + public async Task GetAsync(string url) + where T : class, new() + { + var client = await this.client.GetClientAsync(); + + var vm = new T(); + + var response = await client.GetAsync(url).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + vm = JsonConvert.DeserializeObject(result); + + return vm; + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized + || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + else + { + throw new Exception($"Exception HttpStatusCode={response.StatusCode}"); + } + } + + /// + /// The PostAsync. + /// + /// . + /// The url. + /// The body. + /// The . + public async Task PostAsync(string url, T body) + where T : class, new() + { + var client = await this.client.GetClientAsync(); + + var content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json"); + var response = await client.PostAsync(url, content).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + return; + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized + || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + else + { + throw new Exception($"Exception HttpStatusCode={response.StatusCode}"); + } + } + + /// + /// The PostAsync. + /// + /// The return type. + /// The type of body parameter. + /// The url. + /// The body. + /// The . + public async Task PostAsync(string url, TBody body) + where TBody : class, new() + where T : class, new() + { + var client = await this.client.GetClientAsync(); + + var vm = new T(); + var content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json"); + var response = await client.PostAsync(url, content).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + var apiResponse = JsonConvert.DeserializeObject(result); + if (apiResponse.Success) + { + return apiResponse; + } + else + { + string details = string.Empty; + if (apiResponse.ValidationResult != null) + { + if (apiResponse.ValidationResult.Details != null) + { + details = $"::ValidationResult: {string.Join(",", apiResponse.ValidationResult.Details)}"; + } + } + + throw new Exception($"PostAsync ApiResponse returned False: {details}"); + } + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized + || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("Access Denied"); + } + else + { + throw new Exception($"Exception HttpStatusCode={response.StatusCode}"); + } + } + + /// + /// The PutAsync. + /// + /// The url. + /// The . + public async Task PutAsync(string url) + { + var client = await this.client.GetClientAsync(); + + var response = await client.PutAsync(url, null).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + var apiResponse = JsonConvert.DeserializeObject(result); + if (apiResponse.Success) + { + return apiResponse; + } + else + { + string details = string.Empty; + if (apiResponse.ValidationResult != null) + { + if (apiResponse.ValidationResult.Details != null) + { + details = $"::ValidationResult: {string.Join(",", apiResponse.ValidationResult.Details)}"; + } + } + + throw new Exception($"PutAsync ApiResponse returned False: {details}"); + } + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized + || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("Access Denied"); + } + else + { + throw new Exception($"Exception HttpStatusCode={response.StatusCode}"); + } + } + + /// + /// The PutAsync. + /// + /// . + /// The url. + /// The body. + /// The . + public async Task PutAsync(string url, T body) + where T : class, new() + { + var client = await this.client.GetClientAsync(); + + var content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json"); + var response = await client.PutAsync(url, content).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + var apiResponse = JsonConvert.DeserializeObject(result); + if (apiResponse.Success) + { + return apiResponse; + } + else + { + string details = string.Empty; + if (apiResponse.ValidationResult != null) + { + if (apiResponse.ValidationResult.Details != null) + { + details = $"::ValidationResult: {string.Join(",", apiResponse.ValidationResult.Details)}"; + } + } + + throw new Exception($"PutAsync ApiResponse returned False: {details}"); + } + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized + || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("Access Denied"); + } + else + { + throw new Exception($"Exception HttpStatusCode={response.StatusCode}"); + } + } + } +} diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IOpenApiHttpClient.cs b/AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IOpenApiHttpClient.cs new file mode 100644 index 000000000..34c488767 --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IOpenApiHttpClient.cs @@ -0,0 +1,17 @@ +namespace LearningHub.Nhs.AdminUI.Interfaces +{ + using System.Net.Http; + using System.Threading.Tasks; + + /// + /// The OpenApiHttpClient interface. + /// + public interface IOpenApiHttpClient + { + /// + /// The get client. + /// + /// The . + Task GetClientAsync(); + } +} diff --git a/AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs b/AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs index 81867365f..1039a3673 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs @@ -86,6 +86,7 @@ public static void ConfigureServices(this IServiceCollection services, IConfigur services.AddSingleton(configuration); services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); @@ -132,11 +133,19 @@ public static void ConfigureServices(this IServiceCollection services, IConfigur ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator, }); + services.AddHttpClient() + .ConfigurePrimaryHttpMessageHandler( + () => new HttpClientHandler + { + ServerCertificateCustomValidationCallback = + HttpClientHandler.DangerousAcceptAnyServerCertificateValidator, + }); } else { services.AddHttpClient(); services.AddHttpClient(); + services.AddHttpClient(); } services.AddTransient(); diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Services/BaseService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Services/BaseService.cs index ab2a377e8..c164b5691 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Services/BaseService.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/Services/BaseService.cs @@ -12,6 +12,11 @@ public class BaseService /// private ILearningHubHttpClient learningHubHttpClient; + /// + /// Defines the openApiHttpClient. + /// + private IOpenApiHttpClient openApiHttpClient; + /// /// Initializes a new instance of the class. /// @@ -21,9 +26,25 @@ protected BaseService(ILearningHubHttpClient learningHubHttpClient) this.learningHubHttpClient = learningHubHttpClient; } + /// + /// Initializes a new instance of the class. + /// + /// The learningHubHttpClient. + /// The openApiHttpClient. + protected BaseService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient) + { + this.learningHubHttpClient = learningHubHttpClient; + this.openApiHttpClient = openApiHttpClient; + } + /// /// Gets the LearningHubHttpClient. /// protected ILearningHubHttpClient LearningHubHttpClient => this.learningHubHttpClient; + + /// + /// Gets the OpenApiHttpClient. + /// + protected IOpenApiHttpClient OpenApiHttpClient => this.openApiHttpClient; } } diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Services/CatalogueService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Services/CatalogueService.cs index 1fa44df2b..2ac0088d9 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Services/CatalogueService.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/Services/CatalogueService.cs @@ -19,19 +19,21 @@ public class CatalogueService : BaseService, ICatalogueService /// /// Defines the _facade. /// - private readonly ILearningHubApiFacade facade; + private readonly IOpenApiFacade facade; /// /// Initializes a new instance of the class. /// /// The learningHubHttpClient. - /// The learningHubApiFacade. + /// The Open Api Http Client. + /// The openApiFacade. public CatalogueService( ILearningHubHttpClient learningHubHttpClient, - ILearningHubApiFacade learningHubApiFacade) + IOpenApiHttpClient openApiHttpClient, + IOpenApiFacade openApiFacade) : base(learningHubHttpClient) { - this.facade = learningHubApiFacade; + this.facade = openApiFacade; } /// diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Services/ContentService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Services/ContentService.cs index d49cd8422..ec983fffd 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Services/ContentService.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/Services/ContentService.cs @@ -27,15 +27,17 @@ public class ContentService : BaseService, IContentService /// private readonly IFileService fileService; private readonly IAzureMediaService azureMediaService; + private readonly IOpenApiHttpClient openApiHttpClient; /// /// Initializes a new instance of the class. /// /// The learningHubHttpClient. + /// The openApiHttpClient. /// The fileService. /// azureMediaService. - public ContentService(ILearningHubHttpClient learningHubHttpClient, IFileService fileService, IAzureMediaService azureMediaService) - : base(learningHubHttpClient) + public ContentService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, IFileService fileService, IAzureMediaService azureMediaService) + : base(learningHubHttpClient, openApiHttpClient) { this.fileService = fileService; this.azureMediaService = azureMediaService; @@ -48,7 +50,7 @@ public ContentService(ILearningHubHttpClient learningHubHttpClient, IFileService /// The . public async Task DiscardAsync(int pageId) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"content/discard/{pageId}"; var response = await client.PutAsync(request, null).ConfigureAwait(false); if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || @@ -68,7 +70,7 @@ public async Task GetPageByIdAsync(int id, bool includeHidden = f { PageViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = !includeHidden ? $"content/page/{id}" : $"content/page-all/{id}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -97,7 +99,7 @@ public async Task GetPageSectionDetailByIdAsync(int { PageSectionDetailViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"content/page-section-detail/{id}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -126,7 +128,7 @@ public async Task GetEditablePageSectionDetailByIdAs { PageSectionDetailViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"content/editable-page-section-detail/{pageSectionId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -154,7 +156,7 @@ public async Task GetPagesAsync() { PageResultViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"content/pages"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -181,7 +183,7 @@ public async Task GetPagesAsync() /// The . public async Task PublishAsync(int pageId) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"content/publish/{pageId}"; var response = await client.PutAsync(request, null).ConfigureAwait(false); if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || @@ -214,7 +216,7 @@ public async Task UpdatePageImageSectionDetailAsync(int pageId, PageImageSection var json = JsonConvert.SerializeObject(model); var stringContent = new StringContent(json, Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"content/page-image-section-detail/{pageId}"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -232,7 +234,7 @@ public async Task UpdatePageImageSectionDetailAsync(int pageId, PageImageSection /// The . public async Task ChangeOrderAsync(UpdatePageSectionOrderModel requestViewModel) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = "content/change-order/"; var content = new StringContent( JsonConvert.SerializeObject(requestViewModel), @@ -259,7 +261,7 @@ public async Task ChangeOrderAsync(UpdatePageSectionOrderModel requestViewModel) /// The . public async Task CloneAsync(int pageSectionId) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"content/clone/{pageSectionId}"; var response = await client.PutAsync(request, null).ConfigureAwait(false); if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || @@ -276,7 +278,7 @@ public async Task CloneAsync(int pageSectionId) /// The . public async Task HideAsync(int pageSectionId) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"content/hide/{pageSectionId}"; var response = await client.PutAsync(request, null).ConfigureAwait(false); if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || @@ -293,7 +295,7 @@ public async Task HideAsync(int pageSectionId) /// The . public async Task UnHideAsync(int pageSectionId) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"content/unhide/{pageSectionId}"; var response = await client.PutAsync(request, null).ConfigureAwait(false); if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || @@ -310,7 +312,7 @@ public async Task UnHideAsync(int pageSectionId) /// The . public async Task DeleteAsync(int pageSectionId) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"content/delete/{pageSectionId}"; var response = await client.PutAsync(request, null).ConfigureAwait(false); if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || @@ -376,7 +378,7 @@ public async Task> GetFileTypeAsync() { List fileTypeList = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetFileTypes"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -459,7 +461,7 @@ public async Task SaveAttributeFileDetailsAsync(FileCreateRequestViewModel var json = JsonConvert.SerializeObject(fileCreateRequestViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"content/save-attribute-file"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -493,7 +495,7 @@ public async Task SaveVideoAssetAsync(FileCreateRequestViewModel fileCreate var json = JsonConvert.SerializeObject(fileCreateRequestViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"content/save-video-asset"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -593,7 +595,7 @@ public async Task GetFileChunkDetail(int fileChunkDeta { FileChunkDetailViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetFileChunkDetail/{fileChunkDetailId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -624,7 +626,7 @@ public async Task SaveFileChunkDetailsAsync(FileChunkDetailViewModel fileCh var json = JsonConvert.SerializeObject(fileChunkDetailCreateRequestViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/SaveFileChunkDetail"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -682,7 +684,7 @@ public async Task RegisterChunkedFileAsync(FileChunkRegisterMo public async Task DeleteFileChunkDetailAsync(int fileChunkDetailId) { ApiResponse apiResponse = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/DeleteFileChunkDetail/{fileChunkDetailId}"; var response = await client.DeleteAsync(request).ConfigureAwait(false); @@ -814,7 +816,7 @@ public async Task UpdateVideoAssetAsync(VideoAssetViewModel model) var json = JsonConvert.SerializeObject(model); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"content/update-video-asset"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -844,7 +846,7 @@ public async Task UpdateVideoAssetAsync(VideoAssetViewModel model) /// The . public async Task CreatePageSectionAsync(PageSectionViewModel requestViewModel) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = "content/create-page-section/"; var content = new StringContent( JsonConvert.SerializeObject(requestViewModel), @@ -874,7 +876,7 @@ public async Task CreatePageSectionAsync(PageSectionViewModel requestViewMo /// The . public async Task UpdatePageSectionDetailAsync(PageSectionDetailViewModel updateViewModel) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = "content/update-page-section-detail/"; var content = new StringContent( JsonConvert.SerializeObject(updateViewModel), @@ -899,7 +901,7 @@ public async Task GetPageSectionDetailVideoAssetById { PageSectionDetailViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"content/page-section-detail-video/{id}"; var response = await client.GetAsync(request).ConfigureAwait(false); diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Services/EventService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Services/EventService.cs index 000fce940..db61e47e3 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Services/EventService.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/Services/EventService.cs @@ -18,8 +18,9 @@ public class EventService : BaseService, IEventService /// Initializes a new instance of the class. /// /// The learningHubHttpClient. - public EventService(ILearningHubHttpClient learningHubHttpClient) - : base(learningHubHttpClient) + /// The openApiHttpClient. + public EventService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient) + : base(learningHubHttpClient, openApiHttpClient) { } @@ -30,7 +31,7 @@ public async Task Create(Event eventEntity) var json = JsonConvert.SerializeObject(eventEntity); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Event/Create"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Services/HierarchyService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Services/HierarchyService.cs index b408cb637..17b37999b 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Services/HierarchyService.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/Services/HierarchyService.cs @@ -16,21 +16,21 @@ public class HierarchyService : BaseService, IHierarchyService /// /// Defines the _facade. /// - private readonly ILearningHubApiFacade facade; + private readonly IOpenApiFacade facade; /// /// Initializes a new instance of the class. /// /// The learning hub http client. - /// The learningHubApiFacade. + /// The openApiFacade. /// The logger. public HierarchyService( ILearningHubHttpClient learningHubHttpClient, - ILearningHubApiFacade learningHubApiFacade, + IOpenApiFacade openApiFacade, ILogger logger) : base(learningHubHttpClient) { - this.facade = learningHubApiFacade; + this.facade = openApiFacade; } /// diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Services/OpenApiHttpClient.cs b/AdminUI/LearningHub.Nhs.AdminUI/Services/OpenApiHttpClient.cs new file mode 100644 index 000000000..5e8463cad --- /dev/null +++ b/AdminUI/LearningHub.Nhs.AdminUI/Services/OpenApiHttpClient.cs @@ -0,0 +1,39 @@ +namespace LearningHub.Nhs.AdminUI.Services +{ + using System.Net.Http; + using LearningHub.Nhs.AdminUI.Configuration; + using LearningHub.Nhs.AdminUI.Interfaces; + using LearningHub.Nhs.Caching; + using Microsoft.AspNetCore.Http; + using Microsoft.Extensions.Logging; + using Microsoft.Extensions.Options; + + /// + /// The open api http client. + /// + public class OpenApiHttpClient : BaseHttpClient, IOpenApiHttpClient + { + /// + /// Initializes a new instance of the class. + /// + /// The http context accessor. + /// The web settings. + /// The http client. + /// The logger. + /// The cache service. + public OpenApiHttpClient( + IHttpContextAccessor httpContextAccessor, + IOptions webSettings, + HttpClient client, + ILogger logger, + ICacheService cacheService) + : base(httpContextAccessor, webSettings.Value, client, logger, cacheService) + { + } + + /// + /// Gets the open api url. + /// + public override string ApiUrl => this.WebSettings.OpenApiUrl; + } +} diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Services/ProviderService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Services/ProviderService.cs index eeb6976f9..cfdc4050b 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Services/ProviderService.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/Services/ProviderService.cs @@ -24,19 +24,20 @@ public class ProviderService : BaseService, IProviderService /// /// Defines the _facade. /// - private readonly ILearningHubApiFacade facade; + private readonly IOpenApiFacade facade; /// /// Initializes a new instance of the class. /// /// The cache service. /// Learning hub http client. - /// The learningHubApiFacade. - public ProviderService(ICacheService cacheService, ILearningHubHttpClient learningHubHttpClient, ILearningHubApiFacade learningHubApiFacade) + /// open api http client. + /// The openApiFacade. + public ProviderService(ICacheService cacheService, ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, IOpenApiFacade openApiFacade) : base(learningHubHttpClient) { this.cacheService = cacheService; - this.facade = learningHubApiFacade; + this.facade = openApiFacade; } /// diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Services/ResourceService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Services/ResourceService.cs index 4c6e3fe46..038681c64 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Services/ResourceService.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/Services/ResourceService.cs @@ -24,8 +24,9 @@ public class ResourceService : BaseService, IResourceService /// Initializes a new instance of the class. /// /// The learningHubHttpClient. - public ResourceService(ILearningHubHttpClient learningHubHttpClient) - : base(learningHubHttpClient) + /// The openApiHttpClient. + public ResourceService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient) + : base(learningHubHttpClient, openApiHttpClient) { } @@ -50,7 +51,7 @@ public async Task> GetResourc var filter = JsonConvert.SerializeObject(pagingRequestModel.Filter); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var json = JsonConvert.SerializeObject(pagingRequestModel); var stringContent = new StringContent(json, Encoding.UTF8, "application/json"); @@ -82,7 +83,7 @@ public async Task> GetResourceVersionEventsA { List viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetResourceVersionEvents/{resourceVersionId.ToString()}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -111,7 +112,7 @@ public async Task GetResourceVersionVa { ResourceVersionValidationResultViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetResourceVersionValidationResult/{resourceVersionId.ToString()}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -140,7 +141,7 @@ public async Task GetResourceVersionDevIdDetailsA { ResourceVersionDevIdViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetResourceVersionDevIdDetails/{resourceVersionId.ToString()}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -167,7 +168,7 @@ public async Task GetResourceVersionDevIdDetailsA /// The . public async Task DoesDevIdExistsAsync(string devId) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/DoesDevIdExists/{devId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -198,7 +199,7 @@ public async Task UpdateDevIdDetailsAsync(ResourceVersionDevIdViewModel model) var json = JsonConvert.SerializeObject(model); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/UpdateDevId"; var response = await client.PutAsync(request, stringContent).ConfigureAwait(false); @@ -223,7 +224,7 @@ public async Task GetResourceVersionExtendedVi { ResourceVersionExtendedViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetResourceVersionExtendedViewModel/{resourceVersionId.ToString()}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -252,7 +253,7 @@ public async Task> GetResourceVersionsAsync(int r { List viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetResourceVersions/{resourceId.ToString()}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -283,7 +284,7 @@ public async Task RevertToDraft(int resourceVersion var json = JsonConvert.SerializeObject(new { resourceVersionId }); var stringContent = new StringContent(resourceVersionId.ToString(), Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/RevertToDraft"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -335,7 +336,7 @@ public async Task TransferResourceOwnership(int res var json = JsonConvert.SerializeObject(vm); var stringContent = new StringContent(json, Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/TransferResourceOwnership"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -382,7 +383,7 @@ public async Task UnpublishResourceVersionAsync(int var json = JsonConvert.SerializeObject(vm); var stringContent = new StringContent(json, Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/UnpublishResourceVersion"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -433,7 +434,7 @@ public async Task CreateResourceVersionEvent(int re var json = JsonConvert.SerializeObject(vm); var stringContent = new StringContent(json, Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/CreateResourceVersionEvent"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Services/UserGroupService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Services/UserGroupService.cs index 45dff59de..0a941c761 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Services/UserGroupService.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/Services/UserGroupService.cs @@ -32,15 +32,17 @@ public class UserGroupService : BaseService, IUserGroupService /// Initializes a new instance of the class. /// /// The learningHubHttpClient. + /// The Open Api Http Client. /// The http context accessor. /// The cacheService. /// The roleService. public UserGroupService( ILearningHubHttpClient learningHubHttpClient, + IOpenApiHttpClient openApiHttpClient, ICacheService cacheService, IRoleService roleService, IHttpContextAccessor contextAccessor) - : base(learningHubHttpClient) + : base(learningHubHttpClient, openApiHttpClient) { this.contextAccessor = contextAccessor; this.cacheService = cacheService; @@ -112,7 +114,7 @@ public async Task GetUserGroupAdminDetailbyIdAsyn { UserGroupAdminDetailViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserGroup/GetUserGroupAdminDetailById/{id}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -141,7 +143,7 @@ public async Task> GetUserGroupAdminRoleDetailByIdA { List viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserGroup/GetUserGroupAdminRoleDetailById/{id}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -171,7 +173,7 @@ public async Task CreateUserGroup(UserGroupAdminDet var json = JsonConvert.SerializeObject(userGroup); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserGroup/CreateUserGroup"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -214,7 +216,7 @@ public async Task UpdateUserGroup(UserGroupAdminDet var json = JsonConvert.SerializeObject(userGroup); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserGroup/UpdateUserGroup"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -258,7 +260,7 @@ public async Task DeleteUserGroup(int userGroupId) var json = JsonConvert.SerializeObject(userGroup); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserGroup/DeleteUserGroup"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -308,7 +310,7 @@ public async Task AddUsersToUserGroup(int userGroup var json = JsonConvert.SerializeObject(userUserGroups); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserGroup/AddUserUserGroups"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -359,7 +361,7 @@ public async Task AddUserGroupsToCatalogue(int cata var json = JsonConvert.SerializeObject(roleUserGroups); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserGroup/AddRoleUserGroups"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -403,7 +405,7 @@ public async Task DeleteUserUserGroup(int userUserG var json = JsonConvert.SerializeObject(userGroup); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserGroup/DeleteUserUserGroup"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -447,7 +449,7 @@ public async Task DeleteRoleUserGroup(int roleUserG var json = JsonConvert.SerializeObject(roleUserGroupUpdate); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserGroup/DeleteRoleUserGroup"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -502,7 +504,7 @@ public async Task> GetUserUserGroupPageAs var filter = JsonConvert.SerializeObject(pagingRequestModel.Filter); var presetFilter = JsonConvert.SerializeObject(pagingRequestModel.PresetFilter); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserGroup/GetUserUserGroupAdminFilteredPage" + $"/{pagingRequestModel.Page}" @@ -551,7 +553,7 @@ public async Task> GetRoleUserGroupPageAs var filter = JsonConvert.SerializeObject(pagingRequestModel.Filter); var presetFilter = JsonConvert.SerializeObject(pagingRequestModel.PresetFilter); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserGroup/GetRoleUserGroupAdminFilteredPage" + $"/{pagingRequestModel.Page}" @@ -598,7 +600,7 @@ private async Task> FetchRoleUserGroupDetailAsync() { List viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserGroup/GetUserGroupRoleDetail"; var response = await client.GetAsync(request).ConfigureAwait(false); diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Services/UserService.cs b/AdminUI/LearningHub.Nhs.AdminUI/Services/UserService.cs index 7c64fd2c0..c84dbc2f2 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Services/UserService.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/Services/UserService.cs @@ -31,10 +31,11 @@ public class UserService : BaseService, IUserService /// Initializes a new instance of the class. /// /// The learningHubHttpClient. + /// The openApiHttpClient . /// The CacheService . /// The userApiHttpClient . - public UserService(ILearningHubHttpClient learningHubHttpClient, ICacheService cacheService, IUserApiHttpClient userApiHttpClient) - : base(learningHubHttpClient) + public UserService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ICacheService cacheService, IUserApiHttpClient userApiHttpClient) + : base(learningHubHttpClient, openApiHttpClient) { this.cacheService = cacheService; this.userApiHttpClient = userApiHttpClient; @@ -166,7 +167,7 @@ public async Task GetEmailAddressRegistrationStatusAsyn var filter = JsonConvert.SerializeObject(pagingRequestModel.Filter); var presetFilter = JsonConvert.SerializeObject(pagingRequestModel.PresetFilter); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"User/GetLHUserAdminBasicFilteredPage" + $"/{pagingRequestModel.Page}" @@ -274,7 +275,7 @@ public async Task> GetUserCon var modelString = JsonConvert.SerializeObject(pagingRequestModel); var content = new StringContent(modelString, Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetResourceAdminSearchFilteredPage"; @@ -459,7 +460,7 @@ public async Task AddUserGroupsToUser(int userId, s var json = JsonConvert.SerializeObject(userUserGroups); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserGroup/AddUserUserGroups"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -565,7 +566,7 @@ public async Task> GetUserLearni var filter = JsonConvert.SerializeObject(pagingRequestModel.Filter); var presetFilter = JsonConvert.SerializeObject(pagingRequestModel.PresetFilter); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserLearningRecord/GetUserLearningRecords" + $"/{pagingRequestModel.Page}" diff --git a/AdminUI/LearningHub.Nhs.AdminUI/appsettings.json b/AdminUI/LearningHub.Nhs.AdminUI/appsettings.json index b3a5c0f9c..95a04b8bc 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/appsettings.json +++ b/AdminUI/LearningHub.Nhs.AdminUI/appsettings.json @@ -17,6 +17,7 @@ "ELfhHubUrl": "", "LearningHubApiUrl": "", "UserApiUrl": "", + "OpenApiUrl": "", "LearningHubAdminUrl": "", "LogConfigDir": "D:\\learningHub\\NLog", "AuthenticationServiceUrl": "", diff --git a/LearningHub.Nhs.Shared/Interfaces/Http/IOpenAPIHttpClient.cs b/LearningHub.Nhs.Shared/Interfaces/Http/IOpenAPIHttpClient.cs new file mode 100644 index 000000000..d20a3eab2 --- /dev/null +++ b/LearningHub.Nhs.Shared/Interfaces/Http/IOpenAPIHttpClient.cs @@ -0,0 +1,21 @@ +namespace LearningHub.Nhs.Shared.Interfaces.Http +{ + /// + /// Marker interface for the Open API HttpClient. + /// + /// + /// Inherits from to enable + /// dependency injection of a specific implementation configured with + /// a user-related API endpoint or settings. + /// + /// + /// + /// This interface is currently empty and used solely to differentiate + /// implementations that connect to different endpoints via configuration. + /// It may be extended in the future with user-specific functionality or properties. + /// + /// + public interface IOpenApiHttpClient : IAPIHttpClient + { + } +} diff --git a/LearningHub.Nhs.Shared/Services/BaseService.cs b/LearningHub.Nhs.Shared/Services/BaseService.cs index 7078f9838..f0a1c07ed 100644 --- a/LearningHub.Nhs.Shared/Services/BaseService.cs +++ b/LearningHub.Nhs.Shared/Services/BaseService.cs @@ -11,6 +11,7 @@ public abstract class BaseService { private readonly ILogger logger; private readonly ILearningHubHttpClient learningHubHttpClient; + private readonly IOpenApiHttpClient openApiHttpClient; /// /// Initializes a new instance of the class. @@ -23,11 +24,29 @@ protected BaseService(ILearningHubHttpClient learningHubHttpClient, ILogger l this.logger = logger; } + /// + /// Initializes a new instance of the class. + /// + /// The learningHubHttpClient. + /// The openApiHttpClient. + /// The logger. + protected BaseService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger) + { + this.learningHubHttpClient = learningHubHttpClient; + this.openApiHttpClient = openApiHttpClient; + this.logger = logger; + } + /// /// Gets the LearningHubHttpClient. /// protected ILearningHubHttpClient LearningHubHttpClient => this.learningHubHttpClient; + /// + /// Gets the OpenApiHttpClient. + /// + protected IOpenApiHttpClient OpenApiHttpClient => this.openApiHttpClient; + /// /// Gets the Logger. /// diff --git a/LearningHub.Nhs.Shared/Services/ProviderService.cs b/LearningHub.Nhs.Shared/Services/ProviderService.cs index c2c31b4b1..a4d56ed47 100644 --- a/LearningHub.Nhs.Shared/Services/ProviderService.cs +++ b/LearningHub.Nhs.Shared/Services/ProviderService.cs @@ -23,9 +23,10 @@ public class ProviderService : BaseService, IProviderService /// /// The cache service. /// Learning hub http client. + /// The Open Api Http Client. /// Logger. - public ProviderService(ICacheService cacheService, ILearningHubHttpClient learningHubHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + public ProviderService(ICacheService cacheService, ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.cacheService = cacheService; } @@ -48,7 +49,7 @@ public async Task> GetProvidersForUserAsync(int userId) { List viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Provider/GetProvidersByUserId/{userId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -77,7 +78,7 @@ public async Task> GetProvidersForResourceAsync(int reso { List viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Provider/GetProvidersByResource/{resourceVersionId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -112,7 +113,7 @@ private async Task> GetAllProviders() { List viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Provider/all"; var response = await client.GetAsync(request).ConfigureAwait(false); diff --git a/LearningHub.Nhs.Shared/Services/SearchService.cs b/LearningHub.Nhs.Shared/Services/SearchService.cs index 613a287fb..cc83dd26b 100644 --- a/LearningHub.Nhs.Shared/Services/SearchService.cs +++ b/LearningHub.Nhs.Shared/Services/SearchService.cs @@ -37,13 +37,11 @@ public class SearchService : BaseService, ISearchService /// Initializes a new instance of the class. /// /// Learning hub http client. + /// The Open Api Http Client. /// Provider service. /// Logger. /// Settings. - public SearchService(ILearningHubHttpClient learningHubHttpClient, - IProviderService providerService, - ILogger logger, - IOptions publicSettings) + public SearchService(ILearningHubHttpClient learningHubHttpClient, IProviderService providerService, ILogger logger, IOptions publicSettings) : base(learningHubHttpClient, logger) { this.publicSettings = publicSettings.Value; @@ -351,7 +349,7 @@ public async Task CreateResourceSearchActionAsync(SearchActionResourceModel try { int createId = 0; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var json = JsonConvert.SerializeObject(searchActionResourceModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); @@ -394,7 +392,7 @@ public async Task CreateCatalogueSearchActionAsync(SearchActionCatalogueMod try { int createId = 0; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var json = JsonConvert.SerializeObject(searchActionCatalogueModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); @@ -433,7 +431,7 @@ public async Task CreateSearchTermEventAsync(SearchRequestModel searchReque try { int createId = 0; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var json = JsonConvert.SerializeObject(searchRequestModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); @@ -473,7 +471,7 @@ public async Task GetSearchResultAsync(SearchRequestModel searc try { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); searchRequestModel.SearchText = this.DecodeProblemCharacters(searchRequestModel.SearchText); @@ -553,7 +551,7 @@ public async Task GetCatalogueSearchResultAsync(Catalo try { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); catalogueSearchRequestModel.SearchText = this.DecodeProblemCharacters(catalogueSearchRequestModel.SearchText); @@ -599,7 +597,7 @@ public async Task CreateCatalogueSearchTermEventAsync(CatalogueSearchReques try { int createId = 0; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var json = JsonConvert.SerializeObject(catalogueSearchRequestModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); @@ -643,7 +641,7 @@ public async Task GetAllCatalogueSearchResultAsync( try { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); catalogueSearchRequestModel.SearchText = this.DecodeProblemCharacters(catalogueSearchRequestModel.SearchText); @@ -686,7 +684,7 @@ public async Task GetAllCatalogueSearchResultAsync( /// The auto suggestion list. public async Task GetAutoSuggestionList(string term) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Search/GetAutoSuggestionResult/{term}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -713,7 +711,7 @@ public async Task SendAutoSuggestionClickActionAsync(AutoSuggestionClickPayloadM { try { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var json = JsonConvert.SerializeObject(clickPayloadModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); diff --git a/LearningHub.Nhs.WebUI/Configuration/BFFPathValidationOptions.cs b/LearningHub.Nhs.WebUI/Configuration/BFFPathValidationOptions.cs new file mode 100644 index 000000000..6da85a403 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Configuration/BFFPathValidationOptions.cs @@ -0,0 +1,25 @@ +namespace LearningHub.Nhs.WebUI.Configuration +{ + using System.Collections.Generic; + + /// + /// Configuration options for validating BFF paths. + /// + public class BFFPathValidationOptions + { + /// + /// Gets the section name for BFF path validation options. + /// + public const string SectionName = "BFFPathValidation"; + + /// + /// Gets or sets fine tuning. Allows for fine tuning of what paths the BFF can be used to access and what not to. + /// + public List AllowedPathPrefixes { get; set; } = new List(); + + /// + /// Gets or sets fine tuning of what paths the BFF can be used to access and what not to. + /// + public List BlockedPathSegments { get; set; } = new List(); + } +} diff --git a/LearningHub.Nhs.WebUI/Configuration/Settings.cs b/LearningHub.Nhs.WebUI/Configuration/Settings.cs index 3e6116565..e16e7e231 100644 --- a/LearningHub.Nhs.WebUI/Configuration/Settings.cs +++ b/LearningHub.Nhs.WebUI/Configuration/Settings.cs @@ -32,6 +32,11 @@ public Settings() /// public string LearningHubApiUrl { get; set; } + /// + /// Gets or sets the OpenApiUrl. + /// + public string OpenApiUrl { get; set; } + /// /// Gets or sets the UserApiUrl. /// diff --git a/LearningHub.Nhs.WebUI/Controllers/Api/BFFController.cs b/LearningHub.Nhs.WebUI/Controllers/Api/BFFController.cs new file mode 100644 index 000000000..7c6255499 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Controllers/Api/BFFController.cs @@ -0,0 +1,245 @@ +namespace LearningHub.Nhs.WebUI.Controllers.Api +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Net.Http; + using System.Net.Http.Headers; + using System.Threading.Tasks; + using LearningHub.Nhs.Shared.Interfaces.Http; + using LearningHub.Nhs.WebUI.Configuration; + using Microsoft.AspNetCore.Authorization; + using Microsoft.AspNetCore.Mvc; + using Microsoft.Extensions.Logging; + using Microsoft.Extensions.Options; + + /// + /// This controller allows proxying of requests to different APIs using same site cookie authentication. + /// It uses the http clients registered in the DI container. + /// The BFF (Backend for Frontend) pattern is used to simplify client-side code and centralize API access. + /// Unauthorized requests will be redirected to the login page so 302s are expected when unauthorized, and redirecting for using a Blazor island component for example may not be desireable so these responses need to be handled by the caller. + /// This controller is designed to be used with a clientside calls i.e. Blazor utilizing the BFF pattern, which enables same site cookie authentication and avoid the necessity of storing tokens in client storage + /// The bff prefix is followed by the API name (e.g. "learninghub", "userapi") and the path to the specific endpoint to enable easy routing to different APIs. + /// See confluence for more details on the BFF pattern and how to use this controller. + /// + /// The authorize same site cookie is used for security between client and server. API calls relying on policys such as AuthorizeOrCallFromLH may not be proxied as they require the Authorization header to be present. + [Authorize] + [Route("bff/{apiName}/{**path}")] + [ApiController] + public class BFFController : BaseApiController + { + private readonly IOptions bffPathValidationOptions; + + /// + /// The list of API clients that can be used to proxy requests. + /// + private List apiClients; + + /// + /// Initializes a new instance of the class. + /// + /// The logger instance used for logging. + /// The HTTP client for the Learning Hub API. + /// The HTTP client for the User API. + /// The HTTP client for the Open API. + /// The options for validating BFF paths. + public BFFController( + ILogger logger, + ILearningHubHttpClient learningHubClient, + IUserApiHttpClient userAPIClient, + IOpenApiHttpClient openAPIClient, + IOptions bffPathValidationOptions) + : base(logger) + { + // Clients the BFF is being given access to, these are the only clients that can be used to proxy requests. + this.apiClients = new List() + { + learningHubClient, + userAPIClient, + openAPIClient, + }; + + this.bffPathValidationOptions = bffPathValidationOptions; + } + + /// + /// Takes an API name and a path, and proxies the request to the appropriate API provided that api is part of the client list and the path is allowed and not blocked. + /// + /// The name of the API to which the request should be proxied. + /// The path of the endpoint within the specified API. + /// An representing the result of the proxied request. + [HttpGet] + [HttpPost] + [HttpPut] + [HttpDelete] + [HttpPatch] + public async Task ProxyRequest(string apiName, string path) + { + string sanitizedPath = path?.Trim('/').ToLowerInvariant() ?? string.Empty; + string sanitizedApiName = apiName?.Trim('/').ToLowerInvariant() ?? string.Empty; + + IAPIHttpClient apiClient; + try + { + apiClient = this.apiClients.Single(x => + { + try + { + var uri = new Uri(x.ApiUrl); + return uri.Host.ToLowerInvariant() == sanitizedApiName; + } + catch + { + return false; + } + }); + } + catch (Exception e) + { + this.Logger.LogError(e, "Failed to find API client for {ApiName}", sanitizedApiName); + return this.BadRequest($"Unknown API alias: {sanitizedApiName}"); + } + + if (!this.IsPathAllowed(sanitizedPath)) + { + return this.Forbid("This path is not allowed via BFF proxy."); + } + + var client = await apiClient.GetClientAsync(); + string targetUrl = $"{apiClient.ApiUrl.TrimEnd('/')}/{path}"; + + // Add query parameters from the original request + if (this.Request.QueryString.HasValue) + { + targetUrl += this.Request.QueryString.Value; + } + + /* + No headers for Auth, host, connection, user agent, added becaue all security is handled by serverside httpclients via baseclient + BaseHttpClient should handle content-type, timezone and tokens. + Note: We do not forward the Authorization header as the BFF pattern uses same-site cookies for authentication. + This means the BFF controller is responsible for handling authentication and authorization. + We also do not forward the Host header as it may not match the target API's expected host. + Header copying would only be needed if: APIs start checking for custom client headers (X-Custom-Header, X-Correlation-Id, etc.) + */ + + // Copy body if necessary (for POST, PUT, PATCH, etc.) + var method = new HttpMethod(this.Request.Method); + var requestMessage = new HttpRequestMessage(method, targetUrl); + + if (this.Request.ContentLength > 0 && + !string.Equals(this.Request.Method, "GET", StringComparison.OrdinalIgnoreCase) && + !string.Equals(this.Request.Method, "HEAD", StringComparison.OrdinalIgnoreCase)) + { + requestMessage.Content = new StreamContent(this.Request.Body); + if (!string.IsNullOrEmpty(this.Request.ContentType)) + { + requestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue(this.Request.ContentType); + } + } + + try + { + var response = await client.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead); + + // Handle redirects with token preservation + if (response.StatusCode == System.Net.HttpStatusCode.Redirect || + response.StatusCode == System.Net.HttpStatusCode.Found || + response.StatusCode == System.Net.HttpStatusCode.TemporaryRedirect || + response.StatusCode == System.Net.HttpStatusCode.PermanentRedirect) + { + return await this.HandleRedirect(response, apiClient); + } + + var content = await response.Content.ReadAsStringAsync(); + var contentType = response.Content.Headers.ContentType?.MediaType ?? "application/json"; + + return new ContentResult + { + Content = content, + ContentType = contentType, + StatusCode = (int)response.StatusCode, + }; + } + catch (HttpRequestException ex) + { + this.Logger.LogError(ex, "Error proxying request to {TargetUrl}", targetUrl); + return this.StatusCode(500, "An error occurred while processing the request."); + } + } + + /* + Handle redirects with token preservation + if we are redirected the client may not handle it as it isnt the token holder so we need to continue using the bff until we get the outcome + if the BFF caller is not expecting redirects but only data they should handle the 302 response and redirect themselves. + E.g. A compontent that uses the BFF to fetch data may not be appropriate for redirecting to a specific page so the consuming client may need to have a way of handling page redirects. + */ + private async Task HandleRedirect(HttpResponseMessage response, IAPIHttpClient apiClient) + { + var location = response.Headers.Location?.ToString(); + + if (string.IsNullOrEmpty(location)) + { + return this.StatusCode((int)response.StatusCode, "Redirect location not found"); + } + + // Check if the redirect location is relative or absolute + string redirectUrl; + if (Uri.IsWellFormedUriString(location, UriKind.Absolute)) + { + redirectUrl = location; + } + else + { + // Handle relative redirects + var baseUri = new Uri(apiClient.ApiUrl); + redirectUrl = new Uri(baseUri, location).ToString(); + } + + // Create a new request for the redirect + var redirectRequest = new HttpRequestMessage(HttpMethod.Get, redirectUrl); + + // Add authentication token to the redirect request (apiClient handles this) + // No additional headers needed - apiClient is already configured + try + { + var client = await apiClient.GetClientAsync(); + var redirectResponse = await client.SendAsync(redirectRequest); + var content = await redirectResponse.Content.ReadAsStringAsync(); + + // Our data apis are expected to return JSON, but we can handle other content types if necessary. + var contentType = redirectResponse.Content.Headers.ContentType?.MediaType ?? "application/json"; + + return new ContentResult + { + Content = content, + ContentType = contentType, + StatusCode = (int)redirectResponse.StatusCode, + }; + } + catch (HttpRequestException ex) + { + this.Logger.LogError(ex, "Error following redirect to {RedirectUrl}", redirectUrl); + return this.StatusCode(500, "An error occurred while following the redirect."); + } + } + + /// + /// Validates the path against allowed and blocked segments. + /// + private bool IsPathAllowed(string path) + { + var normalizedPath = path?.Trim('/').ToLowerInvariant() ?? string.Empty; + + // Check blacklist first + if (this.bffPathValidationOptions.Value.BlockedPathSegments.Any(blocked => normalizedPath.Contains(blocked.ToLowerInvariant()))) + { + this.Logger.LogError(" Black listed path {path} was requested and blocked", normalizedPath); + return false; + } + + // Check whitelist + return this.bffPathValidationOptions.Value.AllowedPathPrefixes.Any(prefix => normalizedPath.StartsWith(prefix.ToLowerInvariant())); + } + } +} diff --git a/LearningHub.Nhs.WebUI/Controllers/SearchController.cs b/LearningHub.Nhs.WebUI/Controllers/SearchController.cs index 9d92a4277..cada3e014 100644 --- a/LearningHub.Nhs.WebUI/Controllers/SearchController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/SearchController.cs @@ -83,7 +83,7 @@ public async Task Index(SearchRequestViewModel search, bool noSor if (filterApplied) { - await this.searchService.RegisterSearchEventsAsync(search, SearchFormActionTypeEnum.ApplyFilter, searchResult.ResourceSearchResult.TotalHits); + await this.searchService.RegisterSearchEventsAsync(search, SearchFormActionTypeEnum.ApplyFilter, searchResult.ResourceSearchResult?.TotalHits ?? 0); } if (noSortFilterError) diff --git a/LearningHub.Nhs.WebUI/Helpers/IOpenApiFacade.cs b/LearningHub.Nhs.WebUI/Helpers/IOpenApiFacade.cs new file mode 100644 index 000000000..a603461c7 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Helpers/IOpenApiFacade.cs @@ -0,0 +1,59 @@ +namespace LearningHub.Nhs.WebUI.Helpers +{ + using System.Threading.Tasks; + using LearningHub.Nhs.Models.Common; + + /// + /// Defines the . + /// + public interface IOpenApiFacade + { + /// + /// The GetAsync. + /// + /// The type. + /// The url. + /// The . + Task GetAsync(string url) + where T : class, new(); + + /// + /// The PostAsync. + /// + /// The type. + /// The url. + /// The body. + /// The . + Task PostAsync(string url, T body) + where T : class, new(); + + /// + /// The PostAsync. + /// + /// The type. + /// . + /// The url. + /// The body. + /// The . + Task PostAsync(string url, TBody body) + where T : class, new() + where TBody : class, new(); + + /// + /// The PutAsync. + /// + /// The url. + /// The . + Task PutAsync(string url); + + /// + /// The PutAsync. + /// + /// . + /// The url. + /// The body. + /// The . + Task PutAsync(string url, T body) + where T : class, new(); + } +} diff --git a/LearningHub.Nhs.WebUI/Helpers/OpenApiFacade.cs b/LearningHub.Nhs.WebUI/Helpers/OpenApiFacade.cs new file mode 100644 index 000000000..3627bc4a8 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Helpers/OpenApiFacade.cs @@ -0,0 +1,241 @@ +namespace LearningHub.Nhs.WebUI.Helpers +{ + using System; + using System.Net.Http; + using System.Text; + using System.Threading.Tasks; + using LearningHub.Nhs.Models.Common; + using LearningHub.Nhs.Shared.Interfaces.Http; + using Newtonsoft.Json; + + /// + /// Defines the . + /// + public class OpenApiFacade : IOpenApiFacade + { + /// + /// Defines the _client. + /// + private readonly IOpenApiHttpClient client; + + /// + /// Initializes a new instance of the class. + /// + /// The client. + public OpenApiFacade(IOpenApiHttpClient client) + { + this.client = client; + } + + /// + /// The GetAsync. + /// + /// . + /// The url. + /// The . + public async Task GetAsync(string url) + where T : class, new() + { + var client = await this.client.GetClientAsync(); + + var vm = new T(); + + var response = await client.GetAsync(url).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + vm = JsonConvert.DeserializeObject(result); + + return vm; + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized + || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + else + { + throw new Exception($"Exception HttpStatusCode={response.StatusCode}"); + } + } + + /// + /// The PostAsync. + /// + /// . + /// The url. + /// The body. + /// The . + public async Task PostAsync(string url, T body) + where T : class, new() + { + var client = await this.client.GetClientAsync(); + + var content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json"); + var response = await client.PostAsync(url, content).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + return; + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized + || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + else + { + throw new Exception($"Exception HttpStatusCode={response.StatusCode}"); + } + } + + /// + /// The PostAsync. + /// + /// The return type. + /// The type of body parameter. + /// The url. + /// The body. + /// The . + public async Task PostAsync(string url, TBody body) + where TBody : class, new() + where T : class, new() + { + var client = await this.client.GetClientAsync(); + + var vm = new T(); + var content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json"); + var response = await client.PostAsync(url, content).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + var apiResponse = JsonConvert.DeserializeObject(result); + if (apiResponse.Success) + { + return apiResponse; + } + else + { + string details = string.Empty; + if (apiResponse.ValidationResult != null) + { + if (apiResponse.ValidationResult.Details != null) + { + details = $"::ValidationResult: {string.Join(",", apiResponse.ValidationResult.Details)}"; + } + } + + throw new Exception($"PostAsync ApiResponse returned False: {details}"); + } + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized + || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("Access Denied"); + } + else + { + throw new Exception($"Exception HttpStatusCode={response.StatusCode}"); + } + } + + /// + /// The PutAsync. + /// + /// The url. + /// The . + public async Task PutAsync(string url) + { + var client = await this.client.GetClientAsync(); + + var response = await client.PutAsync(url, null).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + var apiResponse = JsonConvert.DeserializeObject(result); + if (apiResponse.Success) + { + return apiResponse; + } + else + { + string details = string.Empty; + if (apiResponse.ValidationResult != null) + { + if (apiResponse.ValidationResult.Details != null) + { + details = $"::ValidationResult: {string.Join(",", apiResponse.ValidationResult.Details)}"; + } + } + + throw new Exception($"PutAsync ApiResponse returned False: {details}"); + } + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized + || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("Access Denied"); + } + else + { + throw new Exception($"Exception HttpStatusCode={response.StatusCode}"); + } + } + + /// + /// The PutAsync. + /// + /// . + /// The url. + /// The body. + /// The . + public async Task PutAsync(string url, T body) + where T : class, new() + { + var client = await this.client.GetClientAsync(); + + var content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json"); + var response = await client.PutAsync(url, content).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + var apiResponse = JsonConvert.DeserializeObject(result); + if (apiResponse.Success) + { + return apiResponse; + } + else + { + string details = string.Empty; + if (apiResponse.ValidationResult != null) + { + if (apiResponse.ValidationResult.Details != null) + { + details = $"::ValidationResult: {string.Join(",", apiResponse.ValidationResult.Details)}"; + } + } + + throw new Exception($"PutAsync ApiResponse returned False: {details}"); + } + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized + || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("Access Denied"); + } + else + { + throw new Exception($"Exception HttpStatusCode={response.StatusCode}"); + } + } + } +} diff --git a/LearningHub.Nhs.WebUI/Services/ActivityService.cs b/LearningHub.Nhs.WebUI/Services/ActivityService.cs index f3e24b67e..963c246ac 100644 --- a/LearningHub.Nhs.WebUI/Services/ActivityService.cs +++ b/LearningHub.Nhs.WebUI/Services/ActivityService.cs @@ -23,9 +23,10 @@ public class ActivityService : BaseService, IActivityService /// Initializes a new instance of the class. /// /// Learning hub http client. + /// OpenApiHttpClient http client. /// Logger. - public ActivityService(ILearningHubHttpClient learningHubHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + public ActivityService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { } diff --git a/LearningHub.Nhs.WebUI/Services/BoomarkService.cs b/LearningHub.Nhs.WebUI/Services/BoomarkService.cs index 9428b3b95..e18d467a1 100644 --- a/LearningHub.Nhs.WebUI/Services/BoomarkService.cs +++ b/LearningHub.Nhs.WebUI/Services/BoomarkService.cs @@ -21,16 +21,17 @@ public class BoomarkService : BaseService, IBookmarkService /// Initializes a new instance of the class. /// /// The learningHubHttpClient. + /// The openApiHttpClient. /// The logger. - public BoomarkService(ILearningHubHttpClient learningHubHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + public BoomarkService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { } /// public async Task Create(UserBookmarkViewModel bookmarkViewModel) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = "bookmark/Create"; var content = new StringContent( JsonConvert.SerializeObject(bookmarkViewModel), @@ -58,7 +59,7 @@ public async Task Create(UserBookmarkViewModel bookmarkViewModel) /// public async Task Edit(UserBookmarkViewModel bookmarkViewModel) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = "bookmark/Edit"; var content = new StringContent( JsonConvert.SerializeObject(bookmarkViewModel), @@ -86,7 +87,7 @@ public async Task Edit(UserBookmarkViewModel bookmarkViewModel) /// public async Task DeleteFolder(int bookmarkId) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"bookmark/deletefolder/{bookmarkId}"; var response = await client.DeleteAsync(request).ConfigureAwait(false); if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized @@ -100,7 +101,7 @@ public async Task DeleteFolder(int bookmarkId) /// public async Task> GetAllByParent(int? parentId, bool? all = false) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"bookmark/GetAllByParent/{parentId}?all={all}"; var response = await client.GetAsync(request).ConfigureAwait(false); if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized @@ -122,7 +123,7 @@ public async Task> GetAllByParent(int? parent /// public async Task Toggle(UserBookmarkViewModel bookmarkViewModel) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = "bookmark/toggle"; var content = new StringContent( JsonConvert.SerializeObject(bookmarkViewModel), diff --git a/LearningHub.Nhs.WebUI/Services/CardService.cs b/LearningHub.Nhs.WebUI/Services/CardService.cs index e87c2a2ff..f641a921c 100644 --- a/LearningHub.Nhs.WebUI/Services/CardService.cs +++ b/LearningHub.Nhs.WebUI/Services/CardService.cs @@ -21,9 +21,10 @@ public class CardService : BaseService, ICardService /// Initializes a new instance of the class. /// /// The Learning Hub Http Client. + /// The Open Api Http Client. /// The logger. - public CardService(ILearningHubHttpClient learningHubHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + public CardService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { } @@ -36,7 +37,7 @@ public async Task GetMyContributionsTotalsAsync( { MyContributionsTotalsViewModel totals = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetMyContributionsTotals/{catalogueId.ToString()}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -65,7 +66,7 @@ public async Task> GetContributionsAsync( { List myContributionCards = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var json = JsonConvert.SerializeObject(resourceContributionsRequestViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); @@ -96,7 +97,7 @@ public async Task GetMyResourceViewModelAsync() { MyResourceViewModel myresourcecards = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetMyResourceViewModel"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -125,7 +126,7 @@ public async Task GetResourceCardExtendedViewMode { ResourceCardExtendedViewModel resourceCardExtendedViewModel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/ResourceCardExtendedViewModel/{id.ToString()}"; var response = await client.GetAsync(request).ConfigureAwait(false); diff --git a/LearningHub.Nhs.WebUI/Services/CatalogueService.cs b/LearningHub.Nhs.WebUI/Services/CatalogueService.cs index b711e7c2b..08885adc1 100644 --- a/LearningHub.Nhs.WebUI/Services/CatalogueService.cs +++ b/LearningHub.Nhs.WebUI/Services/CatalogueService.cs @@ -27,10 +27,11 @@ public class CatalogueService : BaseService, ICatalogueService /// Initializes a new instance of the class. /// /// The learning hub http client. + /// The Open Api Http Client. /// The logger. /// The cacheService. - public CatalogueService(ILearningHubHttpClient learningHubHttpClient, ILogger logger, ICacheService cacheService) - : base(learningHubHttpClient, logger) + public CatalogueService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger, ICacheService cacheService) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.cacheService = cacheService; } @@ -43,7 +44,7 @@ public async Task> GetCataloguesForUserAsync() { List viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Catalogue/GetForCurrentUser"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -72,7 +73,7 @@ public async Task GetCatalogueAsync(string reference) { CatalogueViewModel viewmodel = new CatalogueViewModel { }; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"catalogue/catalogue/{reference}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -100,7 +101,7 @@ public async Task GetCatalogueAsync(int catalogueNodeVersion { CatalogueViewModel viewmodel = new CatalogueViewModel { }; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"catalogue/catalogues/{catalogueNodeVersionId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -128,7 +129,7 @@ public async Task GetCatalogueRecordedAsync(string reference { CatalogueViewModel viewmodel = new CatalogueViewModel { }; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"catalogue/catalogue-recorded/{reference}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -156,7 +157,7 @@ public async Task GetResourcesAsync(Catalogu { CatalogueResourceResponseViewModel viewmodel = new CatalogueResourceResponseViewModel { }; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var json = JsonConvert.SerializeObject(requestViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); @@ -187,7 +188,7 @@ public async Task CanCurrentUserEditCatalogue(int catalogueId) { var request = $"Catalogue/CanCurrentUserEditCatalogue/{catalogueId}"; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var response = await client.GetAsync(request).ConfigureAwait(false); var catalogueIsEditable = false; @@ -215,7 +216,7 @@ public async Task AccessDetailsAsync(string ref { var request = $"Catalogue/AccessDetails/{reference}"; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var response = await client.GetAsync(request).ConfigureAwait(false); var accessDetails = new CatalogueAccessDetailsViewModel(); @@ -243,7 +244,7 @@ public async Task GetLatestCatalogueAccessReque { var request = $"Catalogue/GetLatestCatalogueAccessRequest/{catalogueNodeId}"; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var response = await client.GetAsync(request).ConfigureAwait(false); var car = new CatalogueAccessRequestViewModel(); @@ -277,7 +278,7 @@ public async Task RequestAccessAsync(string referen { var request = $"Catalogue/RequestAccess/{reference}/{accessType}"; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var content = new StringContent(JsonConvert.SerializeObject(vm), Encoding.UTF8, "application/json"); var response = await client.PostAsync(request, content).ConfigureAwait(false); var catalogueAccessRequested = false; @@ -310,7 +311,7 @@ public async Task InviteUserAsync(RestrictedCatalog { var request = $"Catalogue/InviteUser"; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var content = new StringContent(JsonConvert.SerializeObject(vm), Encoding.UTF8, "application/json"); var response = await client.PostAsync(request, content).ConfigureAwait(false); var catalogueAccessRequested = false; @@ -346,7 +347,7 @@ public async Task> GetRestricted var json = JsonConvert.SerializeObject(requestModel); var stringContent = new StringContent(json, Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Catalogue/GetRestrictedCatalogueAccessRequests"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -379,7 +380,7 @@ public async Task GetRestrictedCatalogueSum { var viewmodel = new RestrictedCatalogueSummaryViewModel(); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"catalogue/GetRestrictedCatalogueSummary/{catalogueNodeId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -414,7 +415,7 @@ public async Task GetRestrictedCatalogueUsers var json = JsonConvert.SerializeObject(requestModel); var stringContent = new StringContent(json, Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Catalogue/GetRestrictedCatalogueUsers"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -448,7 +449,7 @@ public async Task AcceptAccessRequestAsync(int acce { var request = $"Catalogue/AcceptAccessRequest/{accessRequestId}"; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var content = new StringContent(JsonConvert.SerializeObject(new { })); var response = await client.PostAsync(request, content).ConfigureAwait(false); var catalogueAccessRequested = new LearningHubValidationResult(); @@ -480,7 +481,7 @@ public async Task RejectAccessRequestAsync(int acce { var request = $"Catalogue/RejectAccessRequest/{accessRequestId}"; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var content = new StringContent(JsonConvert.SerializeObject(new CatalogueAccessRejectionViewModel { RejectionReason = rejectionReason }), Encoding.UTF8, "application/json"); var response = await client.PostAsync(request, content).ConfigureAwait(false); var vr = new LearningHubValidationResult(); @@ -509,7 +510,7 @@ public async Task DismissAccessRequestAsync(int cat { var request = $"Catalogue/DismissAccessRequest/{catalogueNodeId}"; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var content = new StringContent(JsonConvert.SerializeObject(new { })); var response = await client.PostAsync(request, content).ConfigureAwait(false); var vr = new LearningHubValidationResult(false); @@ -538,7 +539,7 @@ public async Task GetCatalogueAccessRequestAsyn { var request = $"Catalogue/AccessRequest/{catalogueAccessRequestId}"; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var response = await client.GetAsync(request).ConfigureAwait(false); var catalogueAccessRequest = new CatalogueAccessRequestViewModel(); @@ -572,7 +573,7 @@ public async Task RemoveUserFromRestrictedAccessUse var json = JsonConvert.SerializeObject(userGroup); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserGroup/DeleteUserUserGroup"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -613,7 +614,7 @@ public async Task RemoveUserFromRestrictedAccessUse public async Task GetAllCatalogueAsync(string filterChar) { AllCatalogueResponseViewModel viewmodel = new AllCatalogueResponseViewModel { }; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"catalogue/allcatalogues/{filterChar}"; var response = await client.GetAsync(request).ConfigureAwait(false); diff --git a/LearningHub.Nhs.WebUI/Services/ContentService.cs b/LearningHub.Nhs.WebUI/Services/ContentService.cs index 281564950..b46d4ae4d 100644 --- a/LearningHub.Nhs.WebUI/Services/ContentService.cs +++ b/LearningHub.Nhs.WebUI/Services/ContentService.cs @@ -20,10 +20,11 @@ public class ContentService : BaseService, IContentService /// Initializes a new instance of the class. /// /// Learning hub http client. + /// The Open Api Http Client. /// Logger. /// azureMediaService. - public ContentService(ILearningHubHttpClient learningHubHttpClient, ILogger logger, IAzureMediaService azureMediaService) - : base(learningHubHttpClient, logger) + public ContentService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger, IAzureMediaService azureMediaService) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.azureMediaService = azureMediaService; } @@ -38,7 +39,7 @@ public async Task GetPageByIdAsync(int id, bool preview) { PageViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var response = await client.GetAsync($"content/page/{id}?publishedOnly={!preview}&preview={preview}").ConfigureAwait(false); @@ -65,7 +66,7 @@ public async Task GetPageSectionDetailVideoAssetById { PageSectionDetailViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var response = await client.GetAsync($"content/page-section-detail-video/{id}").ConfigureAwait(false); diff --git a/LearningHub.Nhs.WebUI/Services/ContributeService.cs b/LearningHub.Nhs.WebUI/Services/ContributeService.cs index dd69c37b4..ec5e73894 100644 --- a/LearningHub.Nhs.WebUI/Services/ContributeService.cs +++ b/LearningHub.Nhs.WebUI/Services/ContributeService.cs @@ -41,9 +41,10 @@ public class ContributeService : BaseService, IContributeServ /// Azure media service. /// MKIO media service. /// Learning hub http client. + /// The Open Api Http Client. /// Logger. - public ContributeService(IFileService fileService, IResourceService resourceService, IAzureMediaService azureMediaService, ILearningHubHttpClient learningHubHttpClient, ILogger logger, IAzureMediaService mediaService) - : base(learningHubHttpClient, logger) + public ContributeService(IFileService fileService, IResourceService resourceService, IAzureMediaService azureMediaService, ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger, IAzureMediaService mediaService) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.fileService = fileService; this.resourceService = resourceService; @@ -64,7 +65,7 @@ public async Task CreateNewResourceVersionAsync(int var json = JsonConvert.SerializeObject(model); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/CreateNewResourceVersion"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -98,7 +99,7 @@ public async Task CreateResourceAuthorAsync(ResourceAuthorViewModel resourc var json = JsonConvert.SerializeObject(resourceAuthorViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/AddResourceVersionAuthor"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -132,7 +133,7 @@ public async Task CreateResourceKeywordAsync(ResourceKeywordViewModel resou var json = JsonConvert.SerializeObject(resourceKeywordViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/AddResourceVersionKeyword"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -165,7 +166,7 @@ public async Task DeleteArticleFileAsync(FileDeleteRequestModel model) var json = JsonConvert.SerializeObject(model); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/DeleteArticleFile"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -195,7 +196,7 @@ public async Task DeleteArticleFileAsync(FileDeleteRequestModel model) /// The . public async Task DeleteFileChunkDetailAsync(int fileChunkDetailId) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/DeleteFileChunkDetail/{fileChunkDetailId}"; var response = await client.DeleteAsync(request).ConfigureAwait(false); @@ -226,7 +227,7 @@ public async Task DeleteResourceAttributeFileAsync(FileDeleteRequestModel var json = JsonConvert.SerializeObject(model); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/DeleteResourceAttributeFile"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -259,7 +260,7 @@ public async Task DeleteResourceAuthorAsync(AuthorDeleteRequestModel model var json = JsonConvert.SerializeObject(model); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/DeleteResourceVersionAuthor"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -292,7 +293,7 @@ public async Task DeleteResourceKeywordAsync(KeywordDeleteRequestModel mod var json = JsonConvert.SerializeObject(model); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/DeleteResourceVersionKeyword"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -322,7 +323,7 @@ public async Task DeleteResourceKeywordAsync(KeywordDeleteRequestModel mod /// The . public async Task DeleteResourceVersionAsync(int resourceVersionId) { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/DeleteResourceVersion/{resourceVersionId}"; var response = await client.DeleteAsync(request).ConfigureAwait(false); @@ -358,7 +359,7 @@ public async Task GetFileChunkDetail(int fileChunkDeta { FileChunkDetailViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetFileChunkDetail/{fileChunkDetailId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -801,7 +802,7 @@ public async Task SaveArticleAttachedFileDetailsAsync(FileCreateRequestView var json = JsonConvert.SerializeObject(fileCreateRequestViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/SaveArticleAttachedFileDetails"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -835,7 +836,7 @@ public async Task SaveArticleDetailAsync(ArticleUpdateRequestViewModel arti var json = JsonConvert.SerializeObject(articleViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/UpdateArticleDetail"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -869,7 +870,7 @@ public async Task SaveFileChunkDetailsAsync(FileChunkDetailViewModel fileCh var json = JsonConvert.SerializeObject(fileChunkDetailCreateRequestViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/SaveFileChunkDetail"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -903,7 +904,7 @@ public async Task SaveFileDetailsAsync(FileCreateRequestViewModel fileCreat var json = JsonConvert.SerializeObject(fileCreateRequestViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/SaveFileDetails"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -937,7 +938,7 @@ public async Task SaveGenericFileDetailAsync(GenericFileUpdateRequestViewMo var json = JsonConvert.SerializeObject(genericFileViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/UpdateGenericFileDetail"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -971,7 +972,7 @@ public async Task SaveScormDetailAsync(ScormUpdateRequestViewModel scormUpd var json = JsonConvert.SerializeObject(scormUpdateRequestViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/UpdateScormDetail"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -1005,7 +1006,7 @@ public async Task SaveHtmlDetailAsync(HtmlResourceUpdateRequestViewModel ht var json = JsonConvert.SerializeObject(htmlResource); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/UpdateHtmlDetail"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -1039,7 +1040,7 @@ public async Task SaveImageDetailAsync(ImageUpdateRequestViewModel imageVie var json = JsonConvert.SerializeObject(imageViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/UpdateImageDetail"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -1073,7 +1074,7 @@ public async Task SaveResourceAttributeFileDetailsAsync(FileCreateRequestVi var json = JsonConvert.SerializeObject(fileCreateRequestViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/SaveResourceAttributeFileDetails"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -1130,7 +1131,7 @@ public async Task SaveWeblinkDetailAsync(WebLinkViewModel weblinkViewModel) var json = JsonConvert.SerializeObject(weblinkViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/UpdateWeblinkDetail"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -1164,7 +1165,7 @@ public async Task SaveCaseDetailAsync(CaseViewModel caseViewModel) var json = JsonConvert.SerializeObject(caseViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/UpdateCaseDetail"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -1198,7 +1199,7 @@ public async Task SaveAssessmentDetailAsync(AssessmentViewModel assessmentV var json = JsonConvert.SerializeObject(assessmentViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/UpdateAssessmentDetail"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -1232,7 +1233,7 @@ public async Task SubmitResourceVersionForPublishAs var json = JsonConvert.SerializeObject(publishViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/SubmitResourceVersionForPublish"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -1337,7 +1338,7 @@ private async Task CreateResourceAsync(ResourceDetailViewModel resourceDeta var json = JsonConvert.SerializeObject(resourceDetailViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/CreateResource"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -1370,7 +1371,7 @@ private async Task UpdateResourceVersionAsync(ResourceDetailViewModel resourceDe var json = JsonConvert.SerializeObject(resourceDetailViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/UpdateResourceVersion"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); diff --git a/LearningHub.Nhs.WebUI/Services/CountryService.cs b/LearningHub.Nhs.WebUI/Services/CountryService.cs index b16737317..ccbe6536a 100644 --- a/LearningHub.Nhs.WebUI/Services/CountryService.cs +++ b/LearningHub.Nhs.WebUI/Services/CountryService.cs @@ -22,13 +22,15 @@ public class CountryService : BaseService, ICountryService /// Initializes a new instance of the class. /// /// Learning hub http client. + /// The Open Api Http Client. /// User api http client. /// Logger. public CountryService( ILearningHubHttpClient learningHubHttpClient, + IOpenApiHttpClient openApiHttpClient, IUserApiHttpClient userApiHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.userApiHttpClient = userApiHttpClient; } diff --git a/LearningHub.Nhs.WebUI/Services/DashboardService.cs b/LearningHub.Nhs.WebUI/Services/DashboardService.cs index 226e0392a..639eb7017 100644 --- a/LearningHub.Nhs.WebUI/Services/DashboardService.cs +++ b/LearningHub.Nhs.WebUI/Services/DashboardService.cs @@ -28,10 +28,11 @@ public class DashboardService : BaseService, IDashboardService /// Initializes a new instance of the class. /// /// learningHubHttpClient. + /// The Open Api Http Client. /// logger. /// MoodleHttpClient. - public DashboardService(ILearningHubHttpClient learningHubHttpClient, ILogger logger, IMoodleHttpClient moodleHttpClient) - : base(learningHubHttpClient, logger) + public DashboardService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger, IMoodleHttpClient moodleHttpClient) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.moodleHttpClient = moodleHttpClient; } @@ -46,7 +47,7 @@ public async Task GetMyAccessLearningsAsyn { DashboardMyLearningResponseViewModel viewmodel = new DashboardMyLearningResponseViewModel { }; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"dashboard/myaccesslearning/{dashboardType}/{pageNumber}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -75,7 +76,7 @@ public async Task GetCataloguesAsync(string { DashboardCatalogueResponseViewModel viewmodel = new DashboardCatalogueResponseViewModel { }; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"dashboard/catalogues/{dashboardType}/{pageNumber}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -104,7 +105,7 @@ public async Task GetResourcesAsync(string d { DashboardResourceResponseViewModel viewmodel = new DashboardResourceResponseViewModel { }; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"dashboard/resources/{dashboardType}/{pageNumber}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -151,7 +152,7 @@ public async Task RecordDashBoardEventAsync(DashboardEventViewModel dashboardEve }; var content = new System.Net.Http.StringContent(JsonConvert.SerializeObject(eventEntity), Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"event/Create"; var response = await client.PostAsync(request, content).ConfigureAwait(false); diff --git a/LearningHub.Nhs.WebUI/Services/DetectJsLogService.cs b/LearningHub.Nhs.WebUI/Services/DetectJsLogService.cs index 8cd0c6dd1..cbee0894d 100644 --- a/LearningHub.Nhs.WebUI/Services/DetectJsLogService.cs +++ b/LearningHub.Nhs.WebUI/Services/DetectJsLogService.cs @@ -16,9 +16,10 @@ public class DetectJsLogService : BaseService, IDetectJsLogS /// Initializes a new instance of the class. /// /// Learning hub http client. + /// The Open Api Http Client. /// Logger. - public DetectJsLogService(ILearningHubHttpClient learningHubHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + public DetectJsLogService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { } diff --git a/LearningHub.Nhs.WebUI/Services/GradeService.cs b/LearningHub.Nhs.WebUI/Services/GradeService.cs index 3baabdd83..0394b9543 100644 --- a/LearningHub.Nhs.WebUI/Services/GradeService.cs +++ b/LearningHub.Nhs.WebUI/Services/GradeService.cs @@ -21,13 +21,15 @@ public class GradeService : BaseService, IGradeService /// Initializes a new instance of the class. /// /// Learning hub http client. + /// The Open Api Http Client. /// User api http client. /// Logger. public GradeService( ILearningHubHttpClient learningHubHttpClient, + IOpenApiHttpClient openApiHttpClient, IUserApiHttpClient userApiHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.userApiHttpClient = userApiHttpClient; } diff --git a/LearningHub.Nhs.WebUI/Services/HierarchyService.cs b/LearningHub.Nhs.WebUI/Services/HierarchyService.cs index 6df3f2090..d68e29447 100644 --- a/LearningHub.Nhs.WebUI/Services/HierarchyService.cs +++ b/LearningHub.Nhs.WebUI/Services/HierarchyService.cs @@ -18,21 +18,23 @@ public class HierarchyService : BaseService, IHierarchyService /// /// Defines the _facade. /// - private readonly ILearningHubApiFacade facade; + private readonly IOpenApiFacade facade; /// /// Initializes a new instance of the class. /// /// The learning hub http client. - /// The learningHubApiFacade. + /// The Open Api Http Client. + /// The openApiFacade. /// The logger. public HierarchyService( ILearningHubHttpClient learningHubHttpClient, - ILearningHubApiFacade learningHubApiFacade, + IOpenApiHttpClient openApiHttpClient, + IOpenApiFacade openApiFacade, ILogger logger) - : base(learningHubHttpClient, logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { - this.facade = learningHubApiFacade; + this.facade = openApiFacade; } /// diff --git a/LearningHub.Nhs.WebUI/Services/InternalSystemService.cs b/LearningHub.Nhs.WebUI/Services/InternalSystemService.cs index 6105f0512..67fcb25ea 100644 --- a/LearningHub.Nhs.WebUI/Services/InternalSystemService.cs +++ b/LearningHub.Nhs.WebUI/Services/InternalSystemService.cs @@ -18,9 +18,10 @@ public class InternalSystemService : BaseService, IIntern /// Initializes a new instance of the class. /// /// Learning hub http client. + /// The Open Api Http Client. /// Logger. - public InternalSystemService(ILearningHubHttpClient learningHubHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + public InternalSystemService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { } diff --git a/LearningHub.Nhs.WebUI/Services/JobRoleService.cs b/LearningHub.Nhs.WebUI/Services/JobRoleService.cs index 97433bab8..7b9c3a674 100644 --- a/LearningHub.Nhs.WebUI/Services/JobRoleService.cs +++ b/LearningHub.Nhs.WebUI/Services/JobRoleService.cs @@ -24,13 +24,15 @@ public class JobRoleService : BaseService, IJobRoleService /// Initializes a new instance of the class. /// /// Learning hub http client. + /// The Open Api Http Client. /// User api http client. /// Logger. public JobRoleService( ILearningHubHttpClient learningHubHttpClient, + IOpenApiHttpClient openApiHttpClient, IUserApiHttpClient userApiHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.userApiHttpClient = userApiHttpClient; } diff --git a/LearningHub.Nhs.WebUI/Services/LocationService.cs b/LearningHub.Nhs.WebUI/Services/LocationService.cs index 29d9be912..578532520 100644 --- a/LearningHub.Nhs.WebUI/Services/LocationService.cs +++ b/LearningHub.Nhs.WebUI/Services/LocationService.cs @@ -21,13 +21,15 @@ public class LocationService : BaseService, ILocationService /// Initializes a new instance of the class. /// /// Learning hub http client. + /// The Open Api Http Client. /// User api http client. /// Logger. public LocationService( ILearningHubHttpClient learningHubHttpClient, + IOpenApiHttpClient openApiHttpClient, IUserApiHttpClient userApiHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.userApiHttpClient = userApiHttpClient; } diff --git a/LearningHub.Nhs.WebUI/Services/LoginWizardService.cs b/LearningHub.Nhs.WebUI/Services/LoginWizardService.cs index 433f5a7ba..c06f530c4 100644 --- a/LearningHub.Nhs.WebUI/Services/LoginWizardService.cs +++ b/LearningHub.Nhs.WebUI/Services/LoginWizardService.cs @@ -26,13 +26,15 @@ public class LoginWizardService : BaseService, ILoginWizardS /// Initializes a new instance of the class. /// /// Learning hub http client. + /// The Open Api Http Client. /// User api http client. /// Logger. public LoginWizardService( ILearningHubHttpClient learningHubHttpClient, + IOpenApiHttpClient openApiHttpClient, IUserApiHttpClient userApiHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.userApiHttpClient = userApiHttpClient; } diff --git a/LearningHub.Nhs.WebUI/Services/MyLearningService.cs b/LearningHub.Nhs.WebUI/Services/MyLearningService.cs index 4d51dcbe5..7aa1d65ad 100644 --- a/LearningHub.Nhs.WebUI/Services/MyLearningService.cs +++ b/LearningHub.Nhs.WebUI/Services/MyLearningService.cs @@ -22,9 +22,10 @@ public class MyLearningService : BaseService, IMyLearningServ /// Initializes a new instance of the class. /// /// The learningHubHttpClient. + /// The Open Api Http Client. /// The logger. - public MyLearningService(ILearningHubHttpClient learningHubHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + public MyLearningService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { } @@ -40,7 +41,7 @@ public async Task GetActivityDetailed(MyLearningReq var json = JsonConvert.SerializeObject(requestModel); var stringContent = new StringContent(json, Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"MyLearning/GetActivityDetailed"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -69,7 +70,7 @@ public async Task GetActivityDetailed(MyLearningReq public async Task> GetPlayedSegments(int resourceId, int majorVersion) { List viewModel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"MyLearning/GetPlayedSegments/{resourceId}/{majorVersion}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -100,7 +101,7 @@ public async Task> GetPlayedSegments(int resourceId public async Task> GetResourceCertificateDetails(int resourceReferenceId, int? majorVersion = 0, int? minorVersion = 0, int? userId = 0) { Tuple viewModel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"MyLearning/GetResourceCertificateDetails/{resourceReferenceId}/{majorVersion}/{minorVersion}/{userId}"; var response = await client.GetAsync(request).ConfigureAwait(false); diff --git a/LearningHub.Nhs.WebUI/Services/NotificationService.cs b/LearningHub.Nhs.WebUI/Services/NotificationService.cs index 4ce1afb09..14eaaf300 100644 --- a/LearningHub.Nhs.WebUI/Services/NotificationService.cs +++ b/LearningHub.Nhs.WebUI/Services/NotificationService.cs @@ -24,9 +24,10 @@ public class NotificationService : BaseService, INotificati /// Initializes a new instance of the class. /// /// Learning hub http client. + /// The Open Api Http Client. /// Logger. - public NotificationService(ILearningHubHttpClient learningHubHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + public NotificationService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { } @@ -97,7 +98,7 @@ public async Task> GetPagedAsync(Pagin { PagedResultSet viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var content = new StringContent(JsonConvert.SerializeObject(pagingRequestModel), Encoding.UTF8, "application/json"); @@ -126,7 +127,7 @@ public async Task GetUserNotificationIdAsync(int id) { UserNotification viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserNotification/GetById/{id}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -155,7 +156,7 @@ public async Task GetUserNotificationDetailsAsync(int id) { UserNotification viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserNotification/GetByIdAndUserId/{id}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -184,7 +185,7 @@ public async Task GetUserUnreadNotificationCountAsync(int userid) { int count = 0; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserNotification/GetUserUnreadNotificationCount/{userid}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -214,7 +215,7 @@ private async Task PutAsync(UserNotification notification) var json = JsonConvert.SerializeObject(notification); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserNotification/PutAsync"; var response = await client.PutAsync(request, stringContent).ConfigureAwait(false); @@ -247,7 +248,7 @@ private async Task PostAsync(UserNotification notification) var json = JsonConvert.SerializeObject(notification); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserNotification/PostAsync"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); diff --git a/LearningHub.Nhs.WebUI/Services/OpenApiHttpClient.cs b/LearningHub.Nhs.WebUI/Services/OpenApiHttpClient.cs new file mode 100644 index 000000000..502025b0b --- /dev/null +++ b/LearningHub.Nhs.WebUI/Services/OpenApiHttpClient.cs @@ -0,0 +1,41 @@ +namespace LearningHub.Nhs.WebUI.Services +{ + using System.Net.Http; + using LearningHub.Nhs.Caching; + using LearningHub.Nhs.Shared.Interfaces.Http; + using LearningHub.Nhs.WebUI.Configuration; + using Microsoft.AspNetCore.Http; + using Microsoft.Extensions.Logging; + using Microsoft.Extensions.Options; + + /// + /// The open api http client. + /// + public class OpenApiHttpClient : 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 OpenApiHttpClient( + 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/PartialFileUploadService.cs b/LearningHub.Nhs.WebUI/Services/PartialFileUploadService.cs index 59230f71b..b97309e65 100644 --- a/LearningHub.Nhs.WebUI/Services/PartialFileUploadService.cs +++ b/LearningHub.Nhs.WebUI/Services/PartialFileUploadService.cs @@ -36,12 +36,14 @@ public class PartialFileUploadService : BaseService, I /// /// The Settings. /// The learning hub http client. + /// The Open Api Http Client. /// The logger. public PartialFileUploadService( IOptions settings, ILearningHubHttpClient learningHubHttpClient, + IOpenApiHttpClient openApiHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.settings = settings.Value; } diff --git a/LearningHub.Nhs.WebUI/Services/RatingService.cs b/LearningHub.Nhs.WebUI/Services/RatingService.cs index 724256728..eedb5cf67 100644 --- a/LearningHub.Nhs.WebUI/Services/RatingService.cs +++ b/LearningHub.Nhs.WebUI/Services/RatingService.cs @@ -21,9 +21,10 @@ public class RatingService : BaseService, IRatingService /// Initializes a new instance of the class. /// /// Learning hub http client. + /// The Open Api Http Client. /// Logger. - public RatingService(ILearningHubHttpClient learningHubHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + public RatingService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { } diff --git a/LearningHub.Nhs.WebUI/Services/RegionService.cs b/LearningHub.Nhs.WebUI/Services/RegionService.cs index f0211252f..e12ae5f33 100644 --- a/LearningHub.Nhs.WebUI/Services/RegionService.cs +++ b/LearningHub.Nhs.WebUI/Services/RegionService.cs @@ -21,10 +21,11 @@ public class RegionService : BaseService, IRegionService /// Initializes a new instance of the class. /// /// Learning hub http client. + /// The Open Api Http Client. /// Logger. /// User Api http client. - public RegionService(ILearningHubHttpClient learningHubHttpClient, ILogger logger, IUserApiHttpClient userApiHttpClient) - : base(learningHubHttpClient, logger) + public RegionService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger, IUserApiHttpClient userApiHttpClient) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.userApiHttpClient = userApiHttpClient; } diff --git a/LearningHub.Nhs.WebUI/Services/ResourceService.cs b/LearningHub.Nhs.WebUI/Services/ResourceService.cs index 6577ba801..eb3370b7f 100644 --- a/LearningHub.Nhs.WebUI/Services/ResourceService.cs +++ b/LearningHub.Nhs.WebUI/Services/ResourceService.cs @@ -36,11 +36,12 @@ public class ResourceService : BaseService, IResourceService /// Initializes a new instance of the class. /// /// Learning hub http client. + /// The Open Api Http Client. /// Azure media services. /// Logger. /// Settings. - public ResourceService(ILearningHubHttpClient learningHubHttpClient, IAzureMediaService azureMediaService, ILogger logger, IOptions settings) - : base(learningHubHttpClient, logger) + public ResourceService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, IAzureMediaService azureMediaService, ILogger logger, IOptions settings) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.settings = settings.Value; this.azureMediaService = azureMediaService; @@ -57,7 +58,7 @@ public async Task AcceptSensitiveContentAsync(int r var stringContent = new StringContent(resourceVersionId.ToString(), Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/AcceptSensitiveContent"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -89,7 +90,7 @@ public async Task GetArticleDetailsByIdAsync(int resourceVersi { ArticleViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetArticleDetails/{resourceVersionId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -118,7 +119,7 @@ public async Task GetAudioDetailsByIdAsync(int resourceVersionId { AudioViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetAudioDetails/{resourceVersionId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -147,7 +148,7 @@ public async Task GetByIdAsync(int id) { ResourceHeaderViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetResourceHeaderViewModelAsync/{id}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -175,7 +176,7 @@ public async Task> GetFileTypeAsync() { List fileTypeList = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetFileTypes"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -204,7 +205,7 @@ public async Task GetGenericFileDetailsByIdAsync(int resou { GenericFileViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetGenericFileDetails/{resourceVersionId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -233,7 +234,7 @@ public async Task GetHtmlDetailsByIdAsync(int resourceVer { HtmlResourceViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetHtmlDetails/{resourceVersionId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -262,7 +263,7 @@ public async Task GetScormDetailsByIdAsync(int resourceVersionId { ScormViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetScormDetails/{resourceVersionId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -290,7 +291,7 @@ public async Task GetExternalContentDetailsAsyn { ExternalContentDetailsViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetExternalContentDetailsById/{resourceVersionId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -319,7 +320,7 @@ public async Task RecordExternalReferenceUserAgreementAsync(ExternalRefere var json = JsonConvert.SerializeObject(model); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/RecordExternalReferenceUserAgreement"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -351,7 +352,7 @@ public async Task GetImageDetailsByIdAsync(int resourceVersionId { ImageViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetImageDetails/{resourceVersionId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -380,7 +381,7 @@ public async Task GetInformationByIdAsync(int id) { ResourceInformationViewModel resourceInfo = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetResourceInformationViewModelAsync/{id}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -409,7 +410,7 @@ public async Task GetItemByIdAsync(int id) { ResourceItemViewModel resourceItem = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetResourceItemViewModelAsync/{id}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -455,7 +456,7 @@ public async Task> GetLicencesAsync() { List licences = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetResourceLicences"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -484,7 +485,7 @@ public async Task GetLocationsByIdAsync(int id) { CatalogueLocationsViewModel resourceLocations = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetCatalogueLocations/{id}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -513,7 +514,7 @@ public async Task GetResourceVersionAsync(int resourceV { ResourceDetailViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetResourceVersion/{resourceVersionId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -542,7 +543,7 @@ public async Task GetResourceVersionViewModelAsync(int { ResourceVersionViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetResourceVersionViewModel/{resourceVersionId.ToString()}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -571,7 +572,7 @@ public async Task GetResourceVersionExtendedAs { ResourceVersionExtendedViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetResourceVersionExtendedViewModel/{resourceVersionId.ToString()}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -611,7 +612,7 @@ public async Task GetVideoDetailsByIdAsync(int resourceVersionId { VideoViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetVideoDetails/{resourceVersionId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -650,7 +651,7 @@ public async Task GetWeblinkDetailsByIdAsync(int resourceVersi { WebLinkViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetWeblinkDetails/{resourceVersionId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -679,7 +680,7 @@ public async Task GetCaseDetailsByIdAsync(int resourceVersionId) { CaseViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetCaseDetails/{resourceVersionId.ToString()}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -708,7 +709,7 @@ public async Task GetAssessmentDetailsByIdAsync(int resourc { AssessmentViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetAssessmentDetails/{resourceVersionId.ToString()}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -737,7 +738,7 @@ public async Task GetAssessmentContent(int resourceVersionI { AssessmentViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetAssessmentContent/{resourceVersionId.ToString()}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -766,7 +767,7 @@ public async Task GetAssessmentProgressByResourceVe { AssessmentProgressViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetAssessmentProgress/resource/{resourceVersionId.ToString()}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -795,7 +796,7 @@ public async Task GetAssessmentProgressByActivity(i { AssessmentProgressViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetAssessmentProgress/activity/{assessmentResourceActivityId.ToString()}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -824,7 +825,7 @@ public async Task> GetFileStatusDetailsAsync(int[] fileIds) { List viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); string queryString = string.Join("&", fileIds.Select(fileId => $"fileIds={fileId}")); var request = $"Resource/GetFileStatusDetails?{queryString}"; @@ -857,7 +858,7 @@ public async Task UnpublishResourceVersionAsync(int var json = JsonConvert.SerializeObject(rv); var stringContent = new StringContent(json, Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/UnpublishResourceVersion"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -886,7 +887,7 @@ public async Task UnpublishResourceVersionAsync(int /// The . public async Task UserHasPublishedResourcesAsync() { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/HasPublishedResources"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -918,7 +919,7 @@ public async Task DuplicateResourceAsync(DuplicateR var json = JsonConvert.SerializeObject(model); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/DuplicateResource"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -965,7 +966,7 @@ public async Task DuplicateBlocksAsync(DuplicateBlo var json = JsonConvert.SerializeObject(model); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/DuplicateBlocks"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -1009,7 +1010,7 @@ public async Task> GetMyContri { var json = JsonConvert.SerializeObject(model); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var response = await client.PostAsync("Resource/GetMyContributions", stringContent).ConfigureAwait(false); @@ -1032,7 +1033,7 @@ public async Task> GetMyContri /// The . public async Task> GetAllPublishedResourceAsync() { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var response = await client.GetAsync("Resource/GetAllPublishedResource").ConfigureAwait(false); @@ -1058,7 +1059,7 @@ public async Task GetResourceVersionVa { ResourceVersionValidationResultViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetResourceVersionValidationResult/{resourceVersionId.ToString()}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -1087,7 +1088,7 @@ public async Task GetResourceVersionExtendedVi { ResourceVersionExtendedViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetResourceVersionExtendedViewModel/{resourceVersionId.ToString()}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -1118,7 +1119,7 @@ public async Task RevertToDraft(int resourceVersion var json = JsonConvert.SerializeObject(new { resourceVersionId }); var stringContent = new StringContent(resourceVersionId.ToString(), Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/RevertToDraft"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -1162,7 +1163,7 @@ public async Task CreateResourceVersionProviderAsyn var json = JsonConvert.SerializeObject(model); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/AddResourceProvider"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -1208,7 +1209,7 @@ public async Task CreateResourceVersionValidationResultAsync(ResourceVersionVali var json = JsonConvert.SerializeObject(validationResultViewModel); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/CreateResourceVersionValidationResult"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -1239,7 +1240,7 @@ public async Task DeleteResourceVersionProviderAsyn var json = JsonConvert.SerializeObject(model); var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/DeleteResourceProvider"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -1280,7 +1281,7 @@ public async Task DeleteResourceVersionProviderAsyn public async Task DeleteAllResourceVersionProviderAsync(int resourceVersionId) { var content = new StringContent(JsonConvert.SerializeObject(new { })); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/DeleteAllResourceProvider/{resourceVersionId}"; var response = await client.PostAsync(request, content).ConfigureAwait(false); @@ -1322,7 +1323,7 @@ public async Task> GetObsoleteResourceFile(int resourceVersionId, b { List filePaths = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Resource/GetObsoleteResourceFile/{resourceVersionId}/{deletedResource}"; var response = await client.GetAsync(request).ConfigureAwait(false); diff --git a/LearningHub.Nhs.WebUI/Services/RoadMapService.cs b/LearningHub.Nhs.WebUI/Services/RoadMapService.cs index 33210c4fb..5a16366ea 100644 --- a/LearningHub.Nhs.WebUI/Services/RoadMapService.cs +++ b/LearningHub.Nhs.WebUI/Services/RoadMapService.cs @@ -18,9 +18,10 @@ public class RoadMapService : BaseService, IRoadMapService /// Initializes a new instance of the class. /// /// Learing hub http client. + /// The Open Api Http Client. /// Logger. - public RoadMapService(ILearningHubHttpClient learningHubHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + public RoadMapService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { } diff --git a/LearningHub.Nhs.WebUI/Services/RoleService.cs b/LearningHub.Nhs.WebUI/Services/RoleService.cs index 32b0af0d8..bb75e4753 100644 --- a/LearningHub.Nhs.WebUI/Services/RoleService.cs +++ b/LearningHub.Nhs.WebUI/Services/RoleService.cs @@ -23,9 +23,10 @@ public class RoleService : BaseService, IRoleService /// /// The cache service. /// Learning hub http client. + /// The Open Api Http Client. /// Logger. - public RoleService(ICacheService cacheService, ILearningHubHttpClient learningHubHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + public RoleService(ICacheService cacheService, ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient, ILogger logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.cacheService = cacheService; } diff --git a/LearningHub.Nhs.WebUI/Services/SpecialtyService.cs b/LearningHub.Nhs.WebUI/Services/SpecialtyService.cs index 46410724c..c8853e9f5 100644 --- a/LearningHub.Nhs.WebUI/Services/SpecialtyService.cs +++ b/LearningHub.Nhs.WebUI/Services/SpecialtyService.cs @@ -21,13 +21,15 @@ public class SpecialtyService : BaseService, ISpecialtyService /// Initializes a new instance of the class. /// /// Learning hub http client. + /// The Open Api Http Client. /// User api http client. /// . public SpecialtyService( ILearningHubHttpClient learningHubHttpClient, + IOpenApiHttpClient openApiHttpClient, IUserApiHttpClient userApiHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.userApiHttpClient = userApiHttpClient; } diff --git a/LearningHub.Nhs.WebUI/Services/TermsAndConditionsService.cs b/LearningHub.Nhs.WebUI/Services/TermsAndConditionsService.cs index 24c6ddd65..b7bb5c93a 100644 --- a/LearningHub.Nhs.WebUI/Services/TermsAndConditionsService.cs +++ b/LearningHub.Nhs.WebUI/Services/TermsAndConditionsService.cs @@ -24,13 +24,15 @@ public class TermsAndConditionsService : BaseService, /// Initializes a new instance of the class. /// /// Learning hub http client. + /// The Open Api Http Client. /// User api http client. /// Logger. public TermsAndConditionsService( ILearningHubHttpClient learningHubHttpClient, + IOpenApiHttpClient openApiHttpClient, IUserApiHttpClient userApiHttpClient, ILogger logger) - : base(learningHubHttpClient, logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.userApiHttpClient = userApiHttpClient; } diff --git a/LearningHub.Nhs.WebUI/Services/UserGroupService.cs b/LearningHub.Nhs.WebUI/Services/UserGroupService.cs index bfc465966..ac0ac9bb3 100644 --- a/LearningHub.Nhs.WebUI/Services/UserGroupService.cs +++ b/LearningHub.Nhs.WebUI/Services/UserGroupService.cs @@ -28,17 +28,19 @@ public class UserGroupService : BaseService, IUserGroupService /// Initializes a new instance of the class. /// /// The learning hub http client. + /// The Open Api Http Client. /// The logger. /// The http context accessor. /// The cacheService. /// roleService. public UserGroupService( ILearningHubHttpClient learningHubHttpClient, + IOpenApiHttpClient openApiHttpClient, ILogger logger, IHttpContextAccessor contextAccessor, ICacheService cacheService, IRoleService roleService) - : base(learningHubHttpClient, logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.contextAccessor = contextAccessor; this.cacheService = cacheService; @@ -91,7 +93,7 @@ private async Task> FetchRoleUserGroupDetailAsync() { List viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserGroup/GetUserGroupRoleDetail"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -115,7 +117,7 @@ private async Task> FetchRoleUserGroupDetailForUser { List viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"UserGroup/GetUserGroupRoleDetailByUserId/{userId}"; var response = await client.GetAsync(request).ConfigureAwait(false); diff --git a/LearningHub.Nhs.WebUI/Services/UserService.cs b/LearningHub.Nhs.WebUI/Services/UserService.cs index d9addf3fa..799c91b7b 100644 --- a/LearningHub.Nhs.WebUI/Services/UserService.cs +++ b/LearningHub.Nhs.WebUI/Services/UserService.cs @@ -56,6 +56,7 @@ public class UserService : BaseService, IUserService /// Initializes a new instance of the class. /// /// The learningHubHttpClient. + /// The Open Api Http Client. /// The userApiHttpClient. /// The logger. /// The settings. @@ -68,6 +69,7 @@ public class UserService : BaseService, IUserService /// The login wizard service service. public UserService( ILearningHubHttpClient learningHubHttpClient, + IOpenApiHttpClient openApiHttpClient, IUserApiHttpClient userApiHttpClient, ILogger logger, IOptions settings, @@ -78,7 +80,7 @@ public UserService( ILocationService locationService, IGradeService gradeService, ILoginWizardService loginWizardService) - : base(learningHubHttpClient, logger) + : base(learningHubHttpClient, openApiHttpClient, logger) { this.userApiHttpClient = userApiHttpClient; this.settings = settings.Value; @@ -96,7 +98,7 @@ public async Task> GetActiveContentAsync() { List viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = "User/GetActiveContent"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -336,7 +338,7 @@ public async Task GetCurrentUserProfileAsync() { UserProfile viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = "User/GetCurrentUserProfile"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -361,7 +363,7 @@ public async Task GetUserProfileAsync(int userId) { UserProfile viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"User/GetUserProfile/{userId}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -389,7 +391,7 @@ public async Task CreateUserProfileAsync(UserProfil var json = JsonConvert.SerializeObject(userProfile); var stringContent = new StringContent(json, Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"User/CreateUserProfile"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -424,7 +426,7 @@ public async Task UpdateUserProfileAsync(UserProfil var json = JsonConvert.SerializeObject(userProfile); var stringContent = new StringContent(json, Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"User/UpdateUserProfile"; var response = await client.PutAsync(request, stringContent).ConfigureAwait(false); @@ -625,7 +627,7 @@ public async Task GetLHUserByUserIdAsync(int id) { UserLHBasicViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"User/GetByUserId/{id}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -1096,7 +1098,7 @@ public async Task UpdateUserAsync(UserUpdateViewMod var json = JsonConvert.SerializeObject(userUpdateViewModel); var stringContent = new StringContent(json, Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"User/UpdateUser"; @@ -1132,7 +1134,7 @@ public async Task CreateUserAsync(UserCreateViewMod var json = JsonConvert.SerializeObject(newLhUser); var stringContent = new StringContent(json, Encoding.UTF8, "application/json"); - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"User/CreateUser"; var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); @@ -1568,7 +1570,7 @@ public async Task ValidateEmailChangeTokenAsyn { EmailChangeValidationTokenResult tokenResult = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"User/ValidateEmailChangeToken/{Uri.EscapeUriString(token.EncodeParameter())}/{Uri.EscapeUriString(loctoken.EncodeParameter())}/{isUserRoleUpgrade}"; @@ -1597,7 +1599,7 @@ public async Task GetLastIssuedEmailChangeV { EmailChangeValidationTokenViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = "User/GetLastIssuedEmailChangeValidationToken"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -1622,7 +1624,7 @@ public async Task RegenerateEmailChangeVali { EmailChangeValidationTokenViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"User/ReGenerateEmailChangeValidationToken/{newPrimaryEmail}/{isUserRoleUpgrade}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -1647,7 +1649,7 @@ public async Task CanRequestPasswordResetAsync(string emailAddress, int pa { bool status = false; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"User/CanRequestPasswordReset/{emailAddress}/{passwordRequestLimitingPeriod}/{passwordRequestLimit}"; var response = await client.GetAsync(request).ConfigureAwait(false); @@ -1672,7 +1674,7 @@ public async Task GenerateEmailChangeValida { EmailChangeValidationTokenViewModel viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"User/GenerateEmailChangeValidationTokenAndSendEmail/{emailAddress}/{isUserRoleUpgrade}"; @@ -1696,7 +1698,7 @@ public async Task GenerateEmailChangeValida /// public async Task CancelEmailChangeValidationTokenAsync() { - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"User/CancelEmailChangeValidationToken"; @@ -1846,7 +1848,7 @@ public async Task> GetProvidersByUserIdAsync(int userId) { List viewmodel = null; - var client = await this.LearningHubHttpClient.GetClientAsync(); + var client = await this.OpenApiHttpClient.GetClientAsync(); var request = $"Provider/GetProvidersByUserId/{userId}"; var response = await client.GetAsync(request).ConfigureAwait(false); diff --git a/LearningHub.Nhs.WebUI/Startup/ServiceMappings.cs b/LearningHub.Nhs.WebUI/Startup/ServiceMappings.cs index ad98a2b59..50d52eaae 100644 --- a/LearningHub.Nhs.WebUI/Startup/ServiceMappings.cs +++ b/LearningHub.Nhs.WebUI/Startup/ServiceMappings.cs @@ -8,6 +8,7 @@ using LearningHub.Nhs.Shared.Interfaces.Http; using LearningHub.Nhs.Shared.Interfaces.Services; using LearningHub.Nhs.Shared.Services; + using LearningHub.Nhs.WebUI.Configuration; using LearningHub.Nhs.WebUI.Filters; using LearningHub.Nhs.WebUI.Helpers; using LearningHub.Nhs.WebUI.Interfaces; @@ -42,6 +43,14 @@ public static void AddLearningHubMappings(this IServiceCollection services, ICon HttpClientHandler.DangerousAcceptAnyServerCertificateValidator, }); + services.AddHttpClient() + .ConfigurePrimaryHttpMessageHandler( + () => new HttpClientHandler + { + ServerCertificateCustomValidationCallback = + HttpClientHandler.DangerousAcceptAnyServerCertificateValidator, + }); + services.AddHttpClient() .ConfigurePrimaryHttpMessageHandler( () => new HttpClientHandler @@ -68,6 +77,7 @@ public static void AddLearningHubMappings(this IServiceCollection services, ICon else { services.AddHttpClient(); + services.AddHttpClient(); services.AddHttpClient(); services.AddHttpClient(); services.AddHttpClient(); @@ -75,6 +85,7 @@ public static void AddLearningHubMappings(this IServiceCollection services, ICon // Config services.Configure(configuration.GetSection("OpenAthensScopes")); + services.Configure(configuration.GetSection(BFFPathValidationOptions.SectionName)); // Learning Hub Services services.AddTransient(); @@ -106,6 +117,7 @@ public static void AddLearningHubMappings(this IServiceCollection services, ICon services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/LearningHub.Nhs.WebUI/Styles/nhsuk/common.scss b/LearningHub.Nhs.WebUI/Styles/nhsuk/common.scss index 1c18cc3cc..e7e49e651 100644 --- a/LearningHub.Nhs.WebUI/Styles/nhsuk/common.scss +++ b/LearningHub.Nhs.WebUI/Styles/nhsuk/common.scss @@ -1,80 +1,6 @@ @use "../abstracts/all" as *; @use "nhsuk" as *; -.nhsuk-u-font-style-italic { - font-style: italic; -} - -.nhsuk-button--red { - background-color: $nhsuk-red !important; - - &:hover { - background-color: $nhsuk-red-hover !important; - border-color: $nhsuk-red-hover !important; - } -} - -.nhsuk-button--beta-login { - background-color: $nhsuk-blue; - box-shadow: 0 4px 0 #002f5c; -} - -.nhsuk-button--beta-login:hover { - background-color: $nhsuk-btn-blue-hover; -} - -// By default, the text on reverse (white) buttons turns white once clicked, rendering them invisible. -.nhsuk-button--reverse:visited { - color: $nhsuk-black -} - -.nhsuk-back-link { - padding: px2rem(20) 0; - margin-bottom: 0; -} - -.nhsuk-radios__divider { - text-align: left; - width: unset; -} - -.nhsuk-radios__item label { - font-family: $font-stack; -} - -/* Conditional radio buttons - Note: The nhsuk-radios__conditional element needs to be a SIBLING of the radio button input element - otherwise the CSS selector won't work. See Views/Bookmark/Move.cshtml for a usage example. - The NHSUK component (nhsuk-radios__conditional) requires JavaScript to work. These tweaks allow it to work without. -*/ -.nhsuk-radios__conditional { - display: none; - margin-left: -22px; - margin-top: 8px; -} - -.nhsuk-radios__input:checked ~ .nhsuk-radios__conditional { - display: block !important; -} - -/* jquery unbobtrusive validation style over */ -.nhsuk-error-summary__list li { - color: $nhsuk-red; -} - -.nhsuk-form-group.input-validation-error { - @extend .nhsuk-form-group--error; -} - -.nhsuk-input.input-validation-error { - @extend .nhsuk-input--error -} - -.nhsuk-input:focus { - border: 2px solid #212b32; - box-shadow: inset 0 0 0 2px; - outline: 4px solid #ffeb3b; /* 1 */ - outline-offset: 0; -} .display--hide { display: none !important; @@ -120,92 +46,6 @@ } -.nhsuk-bg-light-blue { - background-color: $nhsuk-light-blue-color; -} - -.nhsuk-bg-pale-blue { - background-color: $nhsuk-pale-blue-color; -} - -.nhsuk-bg-white { - background-color: $color_nhsuk-white; -} - -.nhsuk-width-container.search-width-container { - max-width: px2rem(752); - margin: 0 auto; - padding-left: px2rem(68); - padding-right: px2rem(68); -} - -#maincontent { - - button[class^='nhsuk-search__submit'] span.nhsuk-u-visually-hidden { - color: $color_nhsuk-grey-1; - background-color: $color_nhsuk-white; - } -} - -form label.nhsuk-u-visually-hidden { - color: $color_nhsuk-grey-1; - background-color: $color_nhsuk-white; -} - -/* One third column layout that switches to full width at the small desktop breakpoint (990px) instead of mobile. */ -.nhsuk-grid-column-one-third-small-desktop { - @extend .nhsuk-grid-column-one-third; - width: 33.3333333333% !important; - - @media (max-width: px2rem(990)) { - width: 100% !important; - } -} - - -/* Tweaks to styling for single card view. */ -@media(min-width: 768px) and (max-width: 990px) { - .nhsuk-card-group .nhsuk-grid-column-one-third-small-desktop { - max-width: 600px !important; - } - - .nhsuk-card-group--centred { - justify-content: center !important; - } -} - -.nhsuk-card-banner-container { - padding-bottom: 42.86%; - position: relative; -} - -.nhsuk-card-banner { - height: 100%; - object-fit: cover; - object-position: left; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -} - -.nhsuk-card-banner-empty { - background-color: $nhsuk-pale-blue-color; - border-bottom: 1px solid #d8dde0; -} - -.nhsuk-error-message.error-message--margin-bottom-1 { - margin-bottom: nhsuk-spacing(1); -} - -.nhsuk-u-margin-bottom-2point5 { - margin-bottom: 12px; - - @media(max-width: 641px) { - margin-bottom: 10px; - } -} .word-break__break-word { word-break: break-word; @@ -216,9 +56,7 @@ form label.nhsuk-u-visually-hidden { justify-content: space-between; } -.nhsuk-button--no-shrink { - white-space: nowrap; -} + .modal-footer--buttons { justify-content: space-between !important; @@ -233,14 +71,6 @@ form label.nhsuk-u-visually-hidden { box-shadow: 0 0 0 0.2rem $nhsuk-yellow !important; background-color: $govuk-focus-highlight-yellow; } -/*Add a background color to the radio button when focused */ -.nhsuk-radios__input:focus + .radioButton { - box-shadow: 0 0 0 3px $nhsuk-yellow; -} -/*Add a background color to the radio button when focused */ -.nhsuk-checkboxes__input:focus + .checkmark { - box-shadow: 0 0 0 4px $nhsuk-yellow; -} .accessible-link:focus { outline: none; diff --git a/LearningHub.Nhs.WebUI/Styles/nhsuk/layout.scss b/LearningHub.Nhs.WebUI/Styles/nhsuk/layout.scss index f8e150eeb..25b84b7d4 100644 --- a/LearningHub.Nhs.WebUI/Styles/nhsuk/layout.scss +++ b/LearningHub.Nhs.WebUI/Styles/nhsuk/layout.scss @@ -40,21 +40,6 @@ body { font-size: px2rem(16); } - -#header-dropdown-menu-control { - opacity: 0; - position: absolute; -} - -#header-dropdown-menu-control:checked ~ .nhsuk-header__navigation:not(.js-show) { - display: block -} - -#header-mobile-search-control { - display: none; -} - - button[data-toggle="modal"] { color: #005eb8; padding: 0; @@ -125,37 +110,16 @@ li.autosuggestion-option:last-of-type { top: 100%; } } - /* tablet */ @media (max-width: px2rem(768)) { - .autosuggestion-menu { top: 100%; } - - #header-mobile-search-control { - display: block; - opacity: 0; - position: absolute; - } - } /* mobile */ @media (max-width: px2rem(640)) { - - #header-mobile-search-control { - display: block; - opacity: 0; - position: absolute; - } - - #header-mobile-search-control:checked ~ .nhsuk-header__search .nhsuk-header__search-wrap { - display: block; - } - - .autosuggestion-menu { top: 100%; } -} \ No newline at end of file +} diff --git a/LearningHub.Nhs.WebUI/Styles/nhsuk/nhsuk-overrides.scss b/LearningHub.Nhs.WebUI/Styles/nhsuk/nhsuk-overrides.scss new file mode 100644 index 000000000..22c319751 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Styles/nhsuk/nhsuk-overrides.scss @@ -0,0 +1,672 @@ +@use "../abstracts/all" as *; +@use "nhsuk" as *; + +.nhsuk-u-font-style-italic { + font-style: italic; +} + +.nhsuk-button--red { + background-color: $nhsuk-red !important; + + &:hover { + background-color: $nhsuk-red-hover !important; + border-color: $nhsuk-red-hover !important; + } +} + +.nhsuk-button--beta-login { + background-color: $nhsuk-blue; + box-shadow: 0 4px 0 #002f5c; +} + +.nhsuk-button--beta-login:hover { + background-color: $nhsuk-btn-blue-hover; +} + +// By default, the text on reverse (white) buttons turns white once clicked, rendering them invisible. +.nhsuk-button--reverse:visited { + color: $nhsuk-black +} + +.nhsuk-back-link { + padding: px2rem(20) 0; + margin-bottom: 0; +} + +.nhsuk-radios__divider { + text-align: left; + width: unset; +} + +.nhsuk-radios__item label { + font-family: $font-stack; +} + +/* Conditional radio buttons - Note: The nhsuk-radios__conditional element needs to be a SIBLING of the radio button input element + otherwise the CSS selector won't work. See Views/Bookmark/Move.cshtml for a usage example. + The NHSUK component (nhsuk-radios__conditional) requires JavaScript to work. These tweaks allow it to work without. +*/ +.nhsuk-radios__conditional { + display: none; + margin-left: -22px; + margin-top: 8px; +} + +.nhsuk-radios__input:checked ~ .nhsuk-radios__conditional { + display: block !important; +} + +/* jquery unbobtrusive validation style over */ +.nhsuk-error-summary__list li { + color: $nhsuk-red; +} + +.nhsuk-form-group.input-validation-error { + @extend .nhsuk-form-group--error; +} + +.nhsuk-input.input-validation-error { + @extend .nhsuk-input--error +} + +.nhsuk-input:focus { + border: 2px solid #212b32; + box-shadow: inset 0 0 0 2px; + outline: 4px solid #ffeb3b; /* 1 */ + outline-offset: 0; +} + +.nhsuk-bg-light-blue { + background-color: $nhsuk-light-blue-color; +} + +.nhsuk-bg-pale-blue { + background-color: $nhsuk-pale-blue-color; +} + +.nhsuk-bg-white { + background-color: $color_nhsuk-white; +} + +.nhsuk-width-container.search-width-container { + max-width: px2rem(752); + margin: 0 auto; + padding-left: px2rem(68); + padding-right: px2rem(68); +} + +#maincontent { + button[class^='nhsuk-search__submit'] span.nhsuk-u-visually-hidden { + color: $color_nhsuk-grey-1; + background-color: $color_nhsuk-white; + } +} + +form label.nhsuk-u-visually-hidden { + color: $color_nhsuk-grey-1; + background-color: $color_nhsuk-white; +} + +/* One third column layout that switches to full width at the small desktop breakpoint (990px) instead of mobile. */ +.nhsuk-grid-column-one-third-small-desktop { + @extend .nhsuk-grid-column-one-third; + width: 33.3333333333% !important; + + @media (max-width: px2rem(990)) { + width: 100% !important; + } +} + + +/* Tweaks to styling for single card view. */ +@media(min-width: 768px) and (max-width: 990px) { + .nhsuk-card-group .nhsuk-grid-column-one-third-small-desktop { + max-width: 600px !important; + } + + .nhsuk-card-group--centred { + justify-content: center !important; + } +} + +.nhsuk-card-banner-container { + padding-bottom: 42.86%; + position: relative; +} + +.nhsuk-card-banner { + height: 100%; + object-fit: cover; + object-position: left; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +.nhsuk-card-banner-empty { + background-color: $nhsuk-pale-blue-color; + border-bottom: 1px solid #d8dde0; +} + +.nhsuk-error-message.error-message--margin-bottom-1 { + margin-bottom: nhsuk-spacing(1); +} + +.nhsuk-u-margin-bottom-2point5 { + margin-bottom: 12px; + + @media(max-width: 641px) { + margin-bottom: 10px; + } +} + +.nhsuk-button--no-shrink { + white-space: nowrap; +} + +/*Add a background color to the radio button when focused */ +.nhsuk-radios__input:focus + .radioButton { + box-shadow: 0 0 0 3px $nhsuk-yellow; +} +/*Add a background color to the radio button when focused */ +.nhsuk-checkboxes__input:focus + .checkmark { + box-shadow: 0 0 0 4px $nhsuk-yellow; +} + + + +// Below taken from layout.scss +// Overrides largely due to +// - Highly customised header +// - Use of full browser width hero images and full width colour bands +// - Beta banner +// +// Header customisation not needed with current frontend package +// - FGC 19/06/25 + + +.nhsuk-width-container.app-width-container { + max-width: px2rem(1208); + margin: 0 auto; + padding-left: px2rem(32); + padding-right: px2rem(32); +} + +// Header items +.nhsuk-header { + padding: 0 px2rem(32); +} + +.nhsuk-header .nhsuk-width-container.app-width-container { + max-width: px2rem(1144); + margin: 0 auto; +} + +.nhsuk-width-container.app-width-container.beta-banner { + padding: px2rem(8) px2rem(32); + max-width: px2rem(1208); + margin: 0 auto; +} + +.nhsuk-header .nhsuk-header__container::after { + content: none; +} + +.nhsuk-header__navigation.app-width-container { + max-width: px2rem(1144); +} + +.nhsuk-header__container.app-width-container { + display: flex; + justify-content: space-between; + gap: 0 px2rem(24); + padding: px2rem(16) 0; +} + +.nhsuk-header__logo { + flex: 1 0 0; +} + +.nhsuk-header__logo .nhsuk-header__link--service { + display: inline-flex; +} + +.nhsuk-header__service-name { + font-size: px2rem(19); +} + +.nhsuk-header__notification-dot { + position: absolute; + top: px2rem(8); + right: px2rem(-10); + font-size: px2rem(11); + line-height: px2rem(18); + font-weight: 900; + background: $nhsuk-error-color; + color: white; + min-width: px2rem(18); + height: px2rem(18); + text-align: center; + border-radius: px2rem(9); + padding: px2rem(1) px2rem(3) 0; +} + +.nhsuk-header__menu { + display: none; +} + +.nhsuk-header__search .nhsuk-search__input { + width: px2rem(260); +} + +.nhsuk-header__search { + .nhsuk-search__input { + width: px2rem(260); + + &::-moz-placeholder { + opacity: 1; + } + } + + #search > label.nhsuk-u-visually-hidden { + background-color: $nhsuk-white; + } +} + +#header-dropdown-menu-control { + opacity: 0; + position: absolute; +} + + +#header-dropdown-menu-control:checked ~ .nhsuk-header__navigation:not(.js-show) { + display: block +} + +#header-mobile-search-control { + display: none; +} + +.nhsuk-header__break { + display: none; +} + +.nhsuk-header__mobile-only-nav { + display: none; +} + +.nhsuk-header__mobile-break { + display: none; +} + +.nhsuk-header__navigation-item--current { + a { + font-weight: bold; + } +} + +.nhsuk-account__login { + // also a header item + font-size: px2rem(14); + float: right; + position: relative; + z-index: 2; + display: flex; + justify-content: space-between; + align-items: center; + gap: px2rem(24); +} + +.nhsuk-account__login--link, +.nhsuk-account__login--link:visited, +.nhsuk-account__login--link:hover { + // all header items + color: #fff; +} + + +// End of header items + + +.nhsuk-width-container.app-width-container--full { + // used to allow placement of hero (full width) images + margin: 0; + max-width: none +} + +.app-main-wrapper--no-padding { + // allowing hero image to touch headers + padding: 0 +} + +.nhsuk-footer { + padding: px2rem(48) 0; +} + + + +/* large desktop */ +@media (min-width: px2rem(990)) { + // entirely headers + + .nhsuk-header__navigation-item--current a { + border-bottom: 4px solid $nhsuk-grey-lighter; + font-weight: normal; + } + + .nhsuk-header__navigation-link { + position: relative; + } + + .nhsuk-header__navigation-item:last-child { + margin-right: 16px; + } +} + +/* small desktop */ +@media (max-width: px2rem(989)) { + + //entirely headers + + .nhsuk-header__container { + flex-wrap: wrap; + } + + .nhsuk-header { + padding: 0; + } + + .nhsuk-header__container.app-width-container { + flex-wrap: wrap; + gap: 0 0; + padding: px2rem(16) px2rem(32); + } + + .nhsuk-header__link--service { + align-items: center; + -ms-flex-align: center; + margin-bottom: 0; + width: auto; + } + + .nhsuk-header__service-name { + padding-left: px2rem(16); + } + + .nhsuk-header__logo { + order: 0; + } + + .nhsuk-account__login { + // also part of the header + order: 1; + margin-left: auto; + margin-right: 0px; + } + + .nhsuk-header__break { + display: block; + width: 100%; + height: px2rem(24); + order: 2 + } + + .nhsuk-header__search { + order: 3; + flex-grow: 1; + margin-left: 0; + margin-right: px2rem(24); + } + + .nhsuk-header__menu { + display: block; + position: relative; + order: 4; + flex: 0 0 px2rem(74); + } + + .nhsuk-header__navigation-list .nhsuk-header__navigation-item, + .nhsuk-header__navigation .nhsuk-header__navigation-title { + border-top: 1px solid $color_nhsuk-grey-4; + } + + .nhsuk-header__menu-toggle { + text-align: center; + margin: 0; + right: 0; + font-weight: 600; + } + + .nhsuk-header__search-form { + display: flex; + } + + .nhsuk-header__search .nhsuk-search__input { + flex: 1 0 0; + } + + #header-dropdown-menu-control:checked ~ .nhsuk-header__navigation:not(.js-show) { + display: block; + } + + .nhsuk-header__notification-dot { + position: absolute; + top: px2rem(15); + left: px2rem(115); + font-size: px2rem(11); + line-height: px2rem(18); + font-weight: 900; + background: $nhsuk-error-color; + color: $nhsuk-white; + min-width: px2rem(18); + width: fit-content; + height: px2rem(18); + text-align: center; + border-radius: px2rem(9); + } + + .nhsuk-header__navigation-item--current .nhsuk-header__notification-dot { + left: px2rem(125); + } + + .nhsuk-header__menu-notification-dot { + position: absolute; + top: px2rem(-5); + right: px2rem(-6); + background: $nhsuk-error-color; + width: px2rem(12); + height: px2rem(12); + border-radius: px2rem(6); + box-shadow: 0 0 0 2px white; + z-index: 10; + } +} + +@media (max-width: px2rem(768)) { + .nhsuk-width-container.app-width-container, + .nhsuk-width-container.app-width-container.beta-banner { + padding-left: px2rem(16); + padding-right: px2rem(16); + } + + // entirely headers from this point + + .nhsuk-back-link { + padding: 0.5rem 0; + } + + .nhsuk-header__menu .nhsuk-header__not-mobile { + display: none; + } + + .nhsuk-header__not-mobile { + display: none; + } + + .nhsuk-header__mobile-only-nav { + display: flex; + order: 1; + justify-content: space-around; + gap: 0 px2rem(16); + align-items: flex-start; + flex-wrap: wrap; + width: px2rem(166); + } + + .nhsuk-header__mobile-only-nav .nhsuk-header__menu { + margin-right: px2rem(12); + } + + .nhsuk-header__mobile-only-nav .nhsuk-header__search-toggle { + margin-left: px2rem(12); + } + + .nhsuk-header__break { + display: none; + } + + .nhsuk-header__mobile-break { + display: block; + width: 100%; + height: 0; + } + + .nhsuk-header__link--service { + flex-direction: column; + align-items: flex-start; + } + + .nhsuk-header__notification-dot { + top: px2rem(13); + left: px2rem(100); + } + + .nhsuk-header__service-name { + padding: px2rem(12) 0 0; + } + + .nhsuk-header__search-toggle { + position: relative; + height: px2rem(40); + order: 2; + padding: px2rem(7) px2rem(10) 0; + margin: 0 + } + + .nhsuk-header__search .nhsuk-search__submit { + padding-top: nhsuk-spacing(1); + } + + .nhsuk-header__menu { + order: 3; + } + + .nhsuk-header__search { + order: 4; + width: 100%; + flex-grow: 1; + margin: px2rem(16) px2rem(-16) 0; + border-bottom: 1px solid $color_nhsuk-grey-4; + } +} + +@media (max-width: px2rem(640)) { + + //entirely headers + + .nhsuk-header__not-mobile { + display: none; + } + + .nhsuk-header__logo { + max-width: none; + } + + .nhsuk-header__mobile-only-nav { + display: flex; + order: 1; + justify-content: space-around; + gap: 0 px2rem(16); + align-items: flex-start; + flex-wrap: wrap; + width: px2rem(166); + } + + .nhsuk-header__pre-login .nhsuk-header__mobile-only-nav { + align-items: center; + justify-content: flex-end; + padding-bottom: px2rem(16); + } + + .nhsuk-header__mobile-only-nav .nhsuk-header__menu { + margin-right: px2rem(12); + } + + .nhsuk-header__mobile-only-nav .nhsuk-header__search-toggle { + margin-left: px2rem(12); + } + + .nhsuk-header__break { + display: none; + } + + .nhsuk-header__mobile-break { + display: block; + width: 100%; + height: 0; + } + + .nhsuk-header__link--service { + flex-direction: column; + align-items: flex-start; + } + + .nhsuk-header__notification-dot { + top: px2rem(13); + left: px2rem(100); + } + + .nhsuk-header__service-name { + padding: px2rem(12) 0 0; + } + + .nhsuk-header__search-toggle { + position: relative; + height: px2rem(40); + order: 2; + padding: px2rem(7) px2rem(10) 0; + margin: 0 + } + + .nhsuk-header__search .nhsuk-search__submit { + padding-top: nhsuk-spacing(1); + } + + .nhsuk-header__menu { + order: 3; + } + + .nhsuk-header__search { + order: 4; + width: 100%; + flex-grow: 1; + margin: px2rem(16) px2rem(-16) 0; + border-bottom: 1px solid $color_nhsuk-grey-4; + } + + #header-mobile-search-control { + display: block; + opacity: 0; + position: absolute; + } + + #header-mobile-search-control:checked ~ .nhsuk-header__search .nhsuk-header__search-wrap { + display: block; + } + + .nhsuk-width-container.nhsuk-header__container.app-width-container { + padding-bottom: 0; + } +} diff --git a/LearningHub.Nhs.WebUI/Styles/nhsuk/nhsuk.scss b/LearningHub.Nhs.WebUI/Styles/nhsuk/nhsuk.scss index 40c7e1095..7254e0901 100644 --- a/LearningHub.Nhs.WebUI/Styles/nhsuk/nhsuk.scss +++ b/LearningHub.Nhs.WebUI/Styles/nhsuk/nhsuk.scss @@ -1,485 +1 @@ -@import "../../node_modules/nhsuk-frontend/packages/nhsuk"; - -// Overrides largely due to -// - Highly customised header -// - Use of full browser width hero images and full width colour bands -// - Beta banner -// -// Header customisation not needed with current frontend package -// -// - FGC 19/06/25 - - -.nhsuk-width-container.app-width-container { - max-width: px2rem(1208); - margin: 0 auto; - padding-left: px2rem(32); - padding-right: px2rem(32); -} - -// Header items - .nhsuk-header { - padding: 0 px2rem(32); - } - - .nhsuk-header .nhsuk-width-container.app-width-container { - max-width: px2rem(1144); - margin: 0 auto; - } - - .nhsuk-width-container.app-width-container.beta-banner { - padding: px2rem(8) px2rem(32); - max-width: px2rem(1208); - margin: 0 auto; - } - - .nhsuk-header .nhsuk-header__container::after { - content: none; - } - - .nhsuk-header__navigation.app-width-container { - max-width: px2rem(1144); - } - - .nhsuk-header__container.app-width-container { - display: flex; - justify-content: space-between; - gap: 0 px2rem(24); - padding: px2rem(16) 0; - } - - .nhsuk-header__logo { - flex: 1 0 0; - } - - .nhsuk-header__logo .nhsuk-header__link--service { - display: inline-flex; - } - - .nhsuk-header__service-name { - font-size: px2rem(19); - } - - .nhsuk-header__notification-dot { - position: absolute; - top: px2rem(8); - right: px2rem(-10); - font-size: px2rem(11); - line-height: px2rem(18); - font-weight: 900; - background: $nhsuk-error-color; - color: white; - min-width: px2rem(18); - height: px2rem(18); - text-align: center; - border-radius: px2rem(9); - padding: px2rem(1) px2rem(3) 0; - } - - .nhsuk-header__menu { - display: none; - } - - .nhsuk-header__search .nhsuk-search__input { - width: px2rem(260); - } - - .nhsuk-header__search { - .nhsuk-search__input { - width: px2rem(260); - - &::-moz-placeholder { - opacity: 1; - } - } - - #search > label.nhsuk-u-visually-hidden { - background-color: $nhsuk-white; - } - } - - .nhsuk-header__break { - display: none; - } - - .nhsuk-header__mobile-only-nav { - display: none; - } - - .nhsuk-header__mobile-break { - display: none; - } - - .nhsuk-header__navigation-item--current { - a { - font-weight: bold; - } - } - - .nhsuk-account__login { - // also a header item - font-size: px2rem(14); - float: right; - position: relative; - z-index: 2; - display: flex; - justify-content: space-between; - align-items: center; - gap: px2rem(24); - } - - .nhsuk-account__login--link, - .nhsuk-account__login--link:visited, - .nhsuk-account__login--link:hover { - // all header items - color: #fff; - } - - -// End of header items - - -.app-width-container--full { - // used to allow placement of hero (full width) images - margin: 0; - max-width: none -} - -.app-main-wrapper--no-padding { - // allowing hero image to touch headers - padding: 0 -} - -.nhsuk-footer { - padding: px2rem(48) 0; -} - - - -/* large desktop */ -@media (min-width: px2rem(990)) { - // entirely headers - - .nhsuk-header__navigation-item--current a { - border-bottom: 4px solid $nhsuk-grey-lighter; - font-weight: normal; - } - - .nhsuk-header__navigation-link { - position: relative; - } - - .nhsuk-header__navigation-item:last-child { - margin-right: 16px; - } -} - -/* small desktop */ -@media (max-width: px2rem(989)) { - - //entirely headers - - .nhsuk-header__container { - flex-wrap: wrap; - } - - .nhsuk-header { - padding: 0; - } - - .nhsuk-header__container.app-width-container { - flex-wrap: wrap; - gap: 0 0; - padding: px2rem(16) px2rem(32); - } - - .nhsuk-header__link--service { - align-items: center; - -ms-flex-align: center; - margin-bottom: 0; - width: auto; - } - - .nhsuk-header__service-name { - padding-left: px2rem(16); - } - - .nhsuk-header__logo { - order: 0; - } - - .nhsuk-header__break { - display: block; - width: 100%; - height: px2rem(24); - order: 2 - } - - .nhsuk-header__search { - order: 3; - flex-grow: 1; - margin-left: 0; - margin-right: px2rem(24); - } - - .nhsuk-header__menu { - display: block; - position: relative; - order: 4; - flex: 0 0 px2rem(74); - } - - .nhsuk-header__navigation-list .nhsuk-header__navigation-item, - .nhsuk-header__navigation .nhsuk-header__navigation-title { - border-top: 1px solid $color_nhsuk-grey-4; - } - - .nhsuk-header__menu-toggle { - text-align: center; - margin: 0; - right: 0; - font-weight: 600; - } - - .nhsuk-header__search-form { - display: flex; - } - - .nhsuk-header__search .nhsuk-search__input { - flex: 1 0 0; - } - - #header-dropdown-menu-control:checked ~ .nhsuk-header__navigation:not(.js-show) { - display: block; - } - - .nhsuk-header__notification-dot { - position: absolute; - top: px2rem(15); - left: px2rem(115); - font-size: px2rem(11); - line-height: px2rem(18); - font-weight: 900; - background: $nhsuk-error-color; - color: $nhsuk-white; - min-width: px2rem(18); - width: fit-content; - height: px2rem(18); - text-align: center; - border-radius: px2rem(9); - } - - .nhsuk-header__navigation-item--current .nhsuk-header__notification-dot { - left: px2rem(125); - } - - .nhsuk-header__menu-notification-dot { - position: absolute; - top: px2rem(-5); - right: px2rem(-6); - background: $nhsuk-error-color; - width: px2rem(12); - height: px2rem(12); - border-radius: px2rem(6); - box-shadow: 0 0 0 2px white; - z-index: 10; - } - - .nhsuk-account__login { - // also part of the header - order: 1; - margin-left: auto; - margin-right: 0px; - } - -} - -@media (max-width: px2rem(768)) { - .nhsuk-width-container.app-width-container, - .nhsuk-width-container.app-width-container.beta-banner { - padding-left: px2rem(16); - padding-right: px2rem(16); - } - - // entirely headers from this point - - .nhsuk-back-link { - padding: 0.5rem 0; - } - - .nhsuk-header__menu .nhsuk-header__not-mobile { - display: none; - } - - .nhsuk-header__not-mobile { - display: none; - } - - .nhsuk-header__mobile-only-nav { - display: flex; - order: 1; - justify-content: space-around; - gap: 0 px2rem(16); - align-items: flex-start; - flex-wrap: wrap; - width: px2rem(166); - } - - .nhsuk-header__mobile-only-nav .nhsuk-header__menu { - margin-right: px2rem(12); - } - - .nhsuk-header__mobile-only-nav .nhsuk-header__search-toggle { - margin-left: px2rem(12); - } - - .nhsuk-header__break { - display: none; - } - - .nhsuk-header__mobile-break { - display: block; - width: 100%; - height: 0; - } - - .nhsuk-header__link--service { - flex-direction: column; - align-items: flex-start; - } - - .nhsuk-header__notification-dot { - top: px2rem(13); - left: px2rem(100); - } - - .nhsuk-header__service-name { - padding: px2rem(12) 0 0; - } - - .nhsuk-header__search-toggle { - position: relative; - height: px2rem(40); - order: 2; - padding: px2rem(7) px2rem(10) 0; - margin: 0 - } - - .nhsuk-header__search .nhsuk-search__submit { - padding-top: nhsuk-spacing(1); - } - - .nhsuk-header__menu { - order: 3; - } - - .nhsuk-header__search { - order: 4; - width: 100%; - flex-grow: 1; - margin: px2rem(16) px2rem(-16) 0; - border-bottom: 1px solid $color_nhsuk-grey-4; - } - - #header-mobile-search-control:checked ~ .nhsuk-header__search .nhsuk-header__search-wrap { - display: block; - } - - .nhsuk-width-container.nhsuk-header__container.app-width-container { - padding-bottom: 0; - } - -} - -@media (max-width: px2rem(640)) { - - //entirely headers - - .nhsuk-header__not-mobile { - display: none; - } - - .nhsuk-header__logo { - max-width: none; - } - - .nhsuk-header__mobile-only-nav { - display: flex; - order: 1; - justify-content: space-around; - gap: 0 px2rem(16); - align-items: flex-start; - flex-wrap: wrap; - width: px2rem(166); - } - - .nhsuk-header__pre-login .nhsuk-header__mobile-only-nav { - align-items: center; - justify-content: flex-end; - padding-bottom: px2rem(16); - } - - .nhsuk-header__mobile-only-nav .nhsuk-header__menu { - margin-right: px2rem(12); - } - - .nhsuk-header__mobile-only-nav .nhsuk-header__search-toggle { - margin-left: px2rem(12); - } - - .nhsuk-header__break { - display: none; - } - - .nhsuk-header__mobile-break { - display: block; - width: 100%; - height: 0; - } - - .nhsuk-header__link--service { - flex-direction: column; - align-items: flex-start; - } - - .nhsuk-header__notification-dot { - top: px2rem(13); - left: px2rem(100); - } - - .nhsuk-header__service-name { - padding: px2rem(12) 0 0; - } - - .nhsuk-header__search-toggle { - position: relative; - height: px2rem(40); - order: 2; - padding: px2rem(7) px2rem(10) 0; - margin: 0 - } - - .nhsuk-header__search .nhsuk-search__submit { - padding-top: nhsuk-spacing(1); - } - - .nhsuk-header__menu { - order: 3; - } - - .nhsuk-header__search { - order: 4; - width: 100%; - flex-grow: 1; - margin: px2rem(16) px2rem(-16) 0; - border-bottom: 1px solid $color_nhsuk-grey-4; - } - - #header-mobile-search-control:checked ~ .nhsuk-header__search .nhsuk-header__search-wrap { - display: block; - } - - .nhsuk-width-container.nhsuk-header__container.app-width-container { - padding-bottom: 0; - } -} \ No newline at end of file +@import "../../node_modules/nhsuk-frontend/packages/nhsuk"; \ No newline at end of file diff --git a/LearningHub.Nhs.WebUI/Views/Search/_SearchBar.cshtml b/LearningHub.Nhs.WebUI/Views/Search/_SearchBar.cshtml index a0139e3eb..da4a475e9 100644 --- a/LearningHub.Nhs.WebUI/Views/Search/_SearchBar.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Search/_SearchBar.cshtml @@ -48,8 +48,8 @@ function autocomplete(input, minLength) { if (input != null) { input.addEventListener("input", function () { - var val = this.value; - if (val.length < minLength) { + var val = this.value.trimStart(); + if (val.length < minLength || val.trim() === "") { closeAllLists(); return false; } diff --git a/LearningHub.Nhs.WebUI/Views/Shared/Components/NavigationItems/Searchbar.cshtml b/LearningHub.Nhs.WebUI/Views/Shared/Components/NavigationItems/Searchbar.cshtml index 8f7f8a738..f3a69f8e6 100644 --- a/LearningHub.Nhs.WebUI/Views/Shared/Components/NavigationItems/Searchbar.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Shared/Components/NavigationItems/Searchbar.cshtml @@ -72,8 +72,8 @@ function autocomplete(input, minLength) { if (input != null) { input.addEventListener("input", function () { - var val = this.value; - if (val.length < minLength) { + var val = this.value.trimStart(); + if (val.length < minLength || val.trim() === "") { closeAllLists(); return false; } diff --git a/LearningHub.Nhs.WebUI/Views/Shared/Tenant/LearningHub/_Layout.cshtml b/LearningHub.Nhs.WebUI/Views/Shared/Tenant/LearningHub/_Layout.cshtml index c16fa837c..6b679b67e 100644 --- a/LearningHub.Nhs.WebUI/Views/Shared/Tenant/LearningHub/_Layout.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Shared/Tenant/LearningHub/_Layout.cshtml @@ -21,6 +21,7 @@ +