Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
7841b35
Admin UI and WebUI update to consume the Open API endpoints
OluwatobiAwe Jun 4, 2025
a4b7ce1
api route fix
OluwatobiAwe Jun 4, 2025
fbdd80c
.
OluwatobiAwe Jun 4, 2025
2f30da1
P3 endpoint fix
OluwatobiAwe Jun 6, 2025
340ae1e
Added event endpoint to the open api
OluwatobiAwe Jun 9, 2025
021c080
catalogue service test fix
OluwatobiAwe Jun 6, 2025
fccfc4a
Updated dashboard event to use the open api
OluwatobiAwe Jun 9, 2025
9f27f21
Internal Sytem db mapping
OluwatobiAwe Jun 9, 2025
6766426
azure appsetting config
OluwatobiAwe Jun 11, 2025
de8cc48
image annotation mapping
OluwatobiAwe Jun 12, 2025
6894891
appsettings update
OluwatobiAwe Jun 13, 2025
8a84fc0
Additional Updates
OluwatobiAwe Jun 17, 2025
a6e7be6
.
OluwatobiAwe Jun 17, 2025
7a482a3
api key appsettings variable update
OluwatobiAwe Jun 17, 2025
82d6823
merge RC into branch
OluwatobiAwe Jun 17, 2025
ff61a9e
Route typo fix
OluwatobiAwe Jun 17, 2025
19f0a1b
endpoint update
OluwatobiAwe Jun 17, 2025
caac5f1
service dependency issue
OluwatobiAwe Jun 17, 2025
5b9eeb2
TD-5501 Route fix for GetallbyParent Bookmark dual endpoint
OluwatobiAwe Jun 18, 2025
51557ec
Merge pull request #1193 from TechnologyEnhancedLearning/Develop/Fixe…
OluwatobiAwe Jun 18, 2025
2dc2f52
TD-5496
OluwatobiAwe Jun 18, 2025
aef4cec
Merge pull request #1198 from TechnologyEnhancedLearning/Develop/Fixe…
OluwatobiAwe Jun 18, 2025
e69bf4d
TD-5498: Search issue fixed
ArunimaGeorge Jun 18, 2025
e3de851
Merge pull request #1199 from TechnologyEnhancedLearning/Develop/Fixe…
OluwatobiAwe Jun 18, 2025
1fb6073
TD-5499: Replace Web API layer with Open API -My Contributions-Contri…
swapnamol-abraham Jun 19, 2025
ebb0111
Merge pull request #1200 from TechnologyEnhancedLearning/Develop/Fixe…
swapnamol-abraham Jun 19, 2025
f63c941
TD-5703: Fixed issues in auto suggestion and search feedback
ArunimaGeorge Jun 20, 2025
3b63ff2
Merge pull request #1204 from TechnologyEnhancedLearning/Develop/Fixe…
ArunimaGeorge Jun 20, 2025
75e3e7a
TD-5502: Replace Web API layer with Open API Layer -Admin Operations-…
swapnamol-abraham Jun 20, 2025
ad892e7
Reverted the config changes
swapnamol-abraham Jun 20, 2025
31c677a
Removed optional referenece from the service class
swapnamol-abraham Jun 23, 2025
a4c2147
Merge pull request #1205 from TechnologyEnhancedLearning/Develop/Fixe…
AnjuJose011 Jun 23, 2025
cea2f79
TD-5499: Open API replacement- To fiox the LMS connection issue on S…
swapnamol-abraham Jun 23, 2025
652cd24
Merge pull request #1211 from TechnologyEnhancedLearning/Develop/Fixe…
swapnamol-abraham Jun 24, 2025
c38af42
Userbookmark bugfix
OluwatobiAwe Jun 24, 2025
812e46c
Merge pull request #1212 from TechnologyEnhancedLearning/Develop/Fixe…
OluwatobiAwe Jun 24, 2025
98bd92a
Search Feedback fix
OluwatobiAwe Jun 27, 2025
3e54a6c
Merge pull request #1222 from TechnologyEnhancedLearning/search-feedb…
OluwatobiAwe Jun 27, 2025
dd65df0
db mapping update
TobiAwe Jul 1, 2025
1be767e
Merge pull request #1225 from TechnologyEnhancedLearning/Develop/Fixe…
OluwatobiAwe Jul 1, 2025
199a267
Addition of a missing endpoint
TobiAwe Jul 1, 2025
e19a1eb
Merge pull request #1226 from TechnologyEnhancedLearning/Develop/Fixe…
OluwatobiAwe Jul 1, 2025
8d0f9a7
fixes
AnjuJose011 Jul 7, 2025
9bd5c68
Merge pull request #1244 from TechnologyEnhancedLearning/TD-5502-Cata…
AnjuJose011 Jul 8, 2025
8b19c83
Merge RC changes into TD-5490 branch
swapnamol-abraham Jul 8, 2025
0187263
Merge RC into 5490 Branch
swapnamol-abraham Jul 8, 2025
c301902
Merge pull request #1250 from TechnologyEnhancedLearning/Merge-RC-int…
swapnamol-abraham Jul 8, 2025
993b3c7
TD-5500: Invalid date time in my learning page
swapnamol-abraham Jul 8, 2025
385c0e5
Merge pull request #1251 from TechnologyEnhancedLearning/Develop/Fixe…
swapnamol-abraham Jul 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions AdminUI/LearningHub.Nhs.AdminUI/Configuration/WebSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ public class WebSettings
/// </summary>
public string LearningHubApiUrl { get; set; }

/// <summary>
/// Gets or sets the OpenApiUrl.
/// </summary>
public string OpenApiUrl { get; set; }

/// <summary>
/// Gets or sets the user api url.
/// </summary>
Expand Down
59 changes: 59 additions & 0 deletions AdminUI/LearningHub.Nhs.AdminUI/Helpers/IOpenApiFacade.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
namespace LearningHub.Nhs.AdminUI.Helpers
{
using System.Threading.Tasks;
using LearningHub.Nhs.Models.Common;

/// <summary>
/// Defines the <see cref="IOpenApiFacade" />.
/// </summary>
public interface IOpenApiFacade
{
/// <summary>
/// The GetAsync.
/// </summary>
/// <typeparam name="T">The type.</typeparam>
/// <param name="url">The url.</param>
/// <returns>The <see cref="Task{T}"/>.</returns>
Task<T> GetAsync<T>(string url)
where T : class, new();

/// <summary>
/// The PostAsync.
/// </summary>
/// <typeparam name="T">The type.</typeparam>
/// <param name="url">The url.</param>
/// <param name="body">The body.</param>
/// <returns>The <see cref="Task"/>.</returns>
Task PostAsync<T>(string url, T body)
where T : class, new();

/// <summary>
/// The PostAsync.
/// </summary>
/// <typeparam name="T">The type.</typeparam>
/// <typeparam name="TBody">.</typeparam>
/// <param name="url">The url.</param>
/// <param name="body">The body.</param>
/// <returns>The <see cref="Task{T}"/>.</returns>
Task<ApiResponse> PostAsync<T, TBody>(string url, TBody body)
where T : class, new()
where TBody : class, new();

/// <summary>
/// The PutAsync.
/// </summary>
/// <param name="url">The url.</param>
/// <returns>The <see cref="Task"/>.</returns>
Task<ApiResponse> PutAsync(string url);

/// <summary>
/// The PutAsync.
/// </summary>
/// <typeparam name="T">.</typeparam>
/// <param name="url">The url.</param>
/// <param name="body">The body.</param>
/// <returns>The <see cref="Task"/>.</returns>
Task<ApiResponse> PutAsync<T>(string url, T body)
where T : class, new();
}
}
241 changes: 241 additions & 0 deletions AdminUI/LearningHub.Nhs.AdminUI/Helpers/OpenApiFacade.cs
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// Defines the <see cref="OpenApiFacade" />.
/// </summary>
public class OpenApiFacade : IOpenApiFacade
{
/// <summary>
/// Defines the _client.
/// </summary>
private readonly IOpenApiHttpClient client;

/// <summary>
/// Initializes a new instance of the <see cref="OpenApiFacade"/> class.
/// </summary>
/// <param name="client">The client<see cref="IOpenApiHttpClient"/>.</param>
public OpenApiFacade(IOpenApiHttpClient client)
{
this.client = client;
}

/// <summary>
/// The GetAsync.
/// </summary>
/// <typeparam name="T">.</typeparam>
/// <param name="url">The url.</param>
/// <returns>The <see cref="Task{T}"/>.</returns>
public async Task<T> GetAsync<T>(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<T>(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}");
}
}

/// <summary>
/// The PostAsync.
/// </summary>
/// <typeparam name="T">.</typeparam>
/// <param name="url">The url.</param>
/// <param name="body">The body.</param>
/// <returns>The <see cref="Task"/>.</returns>
public async Task PostAsync<T>(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}");
}
}

/// <summary>
/// The PostAsync.
/// </summary>
/// <typeparam name="T">The return type.</typeparam>
/// <typeparam name="TBody">The type of body parameter.</typeparam>
/// <param name="url">The url.</param>
/// <param name="body">The body.</param>
/// <returns>The <see cref="Task{T}"/>.</returns>
public async Task<ApiResponse> PostAsync<T, TBody>(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<ApiResponse>(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}");
}
}

/// <summary>
/// The PutAsync.
/// </summary>
/// <param name="url">The url.</param>
/// <returns>The <see cref="Task"/>.</returns>
public async Task<ApiResponse> 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<ApiResponse>(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}");
}
}

/// <summary>
/// The PutAsync.
/// </summary>
/// <typeparam name="T">.</typeparam>
/// <param name="url">The url.</param>
/// <param name="body">The body.</param>
/// <returns>The <see cref="Task"/>.</returns>
public async Task<ApiResponse> PutAsync<T>(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<ApiResponse>(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}");
}
}
}
}
17 changes: 17 additions & 0 deletions AdminUI/LearningHub.Nhs.AdminUI/Interfaces/IOpenApiHttpClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace LearningHub.Nhs.AdminUI.Interfaces
{
using System.Net.Http;
using System.Threading.Tasks;

/// <summary>
/// The OpenApiHttpClient interface.
/// </summary>
public interface IOpenApiHttpClient
{
/// <summary>
/// The get client.
/// </summary>
/// <returns>The <see cref="Task"/>.</returns>
Task<HttpClient> GetClientAsync();
}
}
9 changes: 9 additions & 0 deletions AdminUI/LearningHub.Nhs.AdminUI/ServiceCollectionExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ public static void ConfigureServices(this IServiceCollection services, IConfigur
services.AddSingleton(configuration);

services.AddScoped<ILearningHubApiFacade, LearningHubApiFacade>();
services.AddScoped<IOpenApiFacade, OpenApiFacade>();
services.AddScoped<IResourceService, ResourceService>();
services.AddScoped<IUserService, UserService>();
services.AddScoped<IUserGroupService, UserGroupService>();
Expand Down Expand Up @@ -132,11 +133,19 @@ public static void ConfigureServices(this IServiceCollection services, IConfigur
ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator,
});
services.AddHttpClient<IOpenApiHttpClient, OpenApiHttpClient>()
.ConfigurePrimaryHttpMessageHandler(
() => new HttpClientHandler
{
ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator,
});
}
else
{
services.AddHttpClient<ILearningHubHttpClient, LearningHubHttpClient>();
services.AddHttpClient<IUserApiHttpClient, UserApiHttpClient>();
services.AddHttpClient<IOpenApiHttpClient, OpenApiHttpClient>();
}

services.AddTransient<CookieEventHandler>();
Expand Down
21 changes: 21 additions & 0 deletions AdminUI/LearningHub.Nhs.AdminUI/Services/BaseService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ public class BaseService
/// </summary>
private ILearningHubHttpClient learningHubHttpClient;

/// <summary>
/// Defines the openApiHttpClient.
/// </summary>
private IOpenApiHttpClient openApiHttpClient;

/// <summary>
/// Initializes a new instance of the <see cref="BaseService"/> class.
/// </summary>
Expand All @@ -21,9 +26,25 @@ protected BaseService(ILearningHubHttpClient learningHubHttpClient)
this.learningHubHttpClient = learningHubHttpClient;
}

/// <summary>
/// Initializes a new instance of the <see cref="BaseService"/> class.
/// </summary>
/// <param name="learningHubHttpClient">The learningHubHttpClient<see cref="ILearningHubHttpClient"/>.</param>
/// <param name="openApiHttpClient">The openApiHttpClient<see cref="IOpenApiHttpClient"/>.</param>
protected BaseService(ILearningHubHttpClient learningHubHttpClient, IOpenApiHttpClient openApiHttpClient)
{
this.learningHubHttpClient = learningHubHttpClient;
this.openApiHttpClient = openApiHttpClient;
}

/// <summary>
/// Gets the LearningHubHttpClient.
/// </summary>
protected ILearningHubHttpClient LearningHubHttpClient => this.learningHubHttpClient;

/// <summary>
/// Gets the OpenApiHttpClient.
/// </summary>
protected IOpenApiHttpClient OpenApiHttpClient => this.openApiHttpClient;
}
}
Loading
Loading