diff --git a/LearningHub.Nhs.WebUI/Views/Search/_ResourceSearchResult.cshtml b/LearningHub.Nhs.WebUI/Views/Search/_ResourceSearchResult.cshtml
index 647583787..81156cd91 100644
--- a/LearningHub.Nhs.WebUI/Views/Search/_ResourceSearchResult.cshtml
+++ b/LearningHub.Nhs.WebUI/Views/Search/_ResourceSearchResult.cshtml
@@ -93,7 +93,7 @@
Type:
- @UtilityHelper.GetPrettifiedResourceTypeNameMoodle(UtilityHelper.ToEnum(item.ResourceType), 0)
+ @UtilityHelper.GetPrettifiedResourceTypeNameMoodle(UtilityHelper.ToEnum(item.ResourceType), 0)
@if (item.ResourceType != "moodle")
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/MoodleConfig.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/MoodleConfig.cs
new file mode 100644
index 000000000..de178b6a2
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/MoodleConfig.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LearningHub.Nhs.OpenApi.Models.Configuration
+{
+ ///
+ /// The Moodle Settings.
+ ///
+ public class MoodleConfig
+ {
+ ///
+ /// Gets or sets the base url for the Moodle service.
+ ///
+ public string APIBaseUrl { get; set; } = null!;
+
+ ///
+ /// Gets or sets the Web service Rest Format.
+ ///
+ public string APIWSRestFormat { get; set; } = null!;
+
+ ///
+ /// Gets or sets the token.
+ ///
+ public string APIWSToken { get; set; } = null!;
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/HttpClients/IMoodleHttpClient.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/HttpClients/IMoodleHttpClient.cs
new file mode 100644
index 000000000..4a98b4ebf
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/HttpClients/IMoodleHttpClient.cs
@@ -0,0 +1,23 @@
+using System.Net.Http;
+using System.Threading.Tasks;
+
+namespace LearningHub.Nhs.OpenApi.Services.Interface.HttpClients
+{
+ ///
+ /// The Moodle Http Client interface.
+ ///
+ public interface IMoodleHttpClient
+ {
+ ///
+ /// The get cient async.
+ ///
+ ///
The .
+ Task
GetClient();
+
+ ///
+ /// GetDefaultParameters.
+ ///
+ /// defaultParameters.
+ string GetDefaultParameters();
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMoodleApiService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMoodleApiService.cs
new file mode 100644
index 000000000..e366a4370
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMoodleApiService.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LearningHub.Nhs.OpenApi.Services.Interface.Services
+{
+ ///
+ /// IMoodleApiService.
+ ///
+ public interface IMoodleApiService
+ {
+ ///
+ /// GetResourcesAsync.
+ ///
+ /// The current LH User Id.
+ /// A representing the result of the asynchronous operation.
+ Task GetMoodleUserIdByUsernameAsync(int currentUserId);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/HttpClients/MoodleHttpClient.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/HttpClients/MoodleHttpClient.cs
new file mode 100644
index 000000000..73af93977
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/HttpClients/MoodleHttpClient.cs
@@ -0,0 +1,95 @@
+using LearningHub.Nhs.OpenApi.Models.Configuration;
+using LearningHub.Nhs.OpenApi.Services.Interface.HttpClients;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LearningHub.Nhs.OpenApi.Services.HttpClients
+{
+ ///
+ /// The Moodle Http Client.
+ ///
+ public class MoodleHttpClient : IMoodleHttpClient, IDisposable
+ {
+ private readonly MoodleConfig moodleConfig;
+ private readonly HttpClient httpClient = new();
+
+ private bool initialised = false;
+ private string moodleAPIBaseUrl;
+ private string moodleAPIMoodleWSRestFormat;
+ private string moodleAPIWSToken;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// httpClient.
+ /// config.
+ public MoodleHttpClient(HttpClient httpClient, IOptions moodleConfig)
+ {
+ this.moodleConfig = moodleConfig.Value;
+ this.httpClient = httpClient;
+
+ this.moodleAPIBaseUrl = this.moodleConfig.APIBaseUrl + "webservice/rest/server.php";
+ this.moodleAPIMoodleWSRestFormat = this.moodleConfig.APIWSRestFormat;
+ this.moodleAPIWSToken = this.moodleConfig.APIWSToken;
+ }
+
+ ///
+ /// The Get Client method.
+ ///
+ /// The .
+ public async Task GetClient()
+ {
+ this.Initialise(this.moodleAPIBaseUrl);
+ return this.httpClient;
+ }
+
+ ///
+ /// GetDefaultParameters.
+ ///
+ /// defaultParameters.
+ public string GetDefaultParameters()
+ {
+ string defaultParameters = $"wstoken={this.moodleAPIWSToken}"
+ + $"&moodlewsrestformat={this.moodleAPIMoodleWSRestFormat}";
+
+ return defaultParameters;
+ }
+
+ ///
+ public void Dispose()
+ {
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// The dispoase.
+ ///
+ /// disposing.
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ this.httpClient.Dispose();
+ }
+ }
+
+ private void Initialise(string httpClientUrl)
+ {
+ if (this.initialised == false)
+ {
+ this.httpClient.BaseAddress = new Uri(httpClientUrl);
+ this.httpClient.DefaultRequestHeaders.Accept.Clear();
+ this.httpClient.DefaultRequestHeaders.Accept.Add(
+ new MediaTypeWithQualityHeaderValue("application/json"));
+ this.initialised = true;
+ }
+ }
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj
index 9002a0237..bf7b23c23 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj
@@ -30,7 +30,7 @@
-
+
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleApiService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleApiService.cs
new file mode 100644
index 000000000..90ffc4280
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleApiService.cs
@@ -0,0 +1,90 @@
+namespace LearningHub.Nhs.OpenApi.Services.Services
+{
+ using LearningHub.Nhs.Models.Moodle.API;
+ using LearningHub.Nhs.OpenApi.Services.Interface.HttpClients;
+ using LearningHub.Nhs.OpenApi.Services.Interface.Services;
+ using Microsoft.Extensions.Logging;
+ using Newtonsoft.Json;
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Net;
+ using System.Net.Http;
+ using System.Text;
+ using System.Threading.Tasks;
+
+ ///
+ /// MoodleApiService.
+ ///
+ public class MoodleApiService : IMoodleApiService
+ {
+ private readonly IMoodleHttpClient moodleHttpClient;
+ private readonly ILogger logger;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// moodleHttpClient.
+ /// logger.
+ public MoodleApiService(IMoodleHttpClient moodleHttpClient, ILogger logger)
+ {
+ this.moodleHttpClient = moodleHttpClient;
+ this.logger = logger;
+ }
+ ///
+ /// GetMoodleUserIdByUsernameAsync.
+ ///
+ /// current User Id.
+ /// UserId from Moodle.
+ public async Task GetMoodleUserIdByUsernameAsync(int currentUserId)
+ {
+ var parameters = new Dictionary
+ {
+ { "criteria[0][key]", "username" },
+ { "criteria[0][value]", currentUserId.ToString() }
+ };
+
+ var response = await GetCallMoodleApiAsync("core_user_get_users", parameters);
+
+ var user = response?.Users?.FirstOrDefault(u => u.Username == currentUserId.ToString());
+ return user?.Id ?? 0;
+ }
+
+
+ private async Task GetCallMoodleApiAsync(string wsFunction, Dictionary parameters)
+ {
+ var client = await this.moodleHttpClient.GetClient();
+ string defaultParameters = this.moodleHttpClient.GetDefaultParameters();
+
+ // Build URL query
+ var queryBuilder = new StringBuilder();
+
+ queryBuilder.Append($"&wsfunction={wsFunction}");
+
+ foreach (var param in parameters)
+ {
+ queryBuilder.Append($"&{param.Key}={Uri.EscapeDataString(param.Value)}");
+ }
+
+ string fullUrl = "?" + defaultParameters + queryBuilder.ToString();
+
+ HttpResponseMessage response = await client.GetAsync(fullUrl);
+ string result = await response.Content.ReadAsStringAsync();
+
+ if (response.IsSuccessStatusCode)
+ {
+ return JsonConvert.DeserializeObject(result);
+ }
+ else if (response.StatusCode == HttpStatusCode.Unauthorized || response.StatusCode == HttpStatusCode.Forbidden)
+ {
+ this.logger.LogError($"Moodle API access denied. Status Code: {response.StatusCode}");
+ throw new Exception("AccessDenied to MoodleApi");
+ }
+ else
+ {
+ this.logger.LogError($"Moodle API error. Status Code: {response.StatusCode}, Message: {result}");
+ throw new Exception("Error with MoodleApi");
+ }
+ }
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs
index fb9098bde..f00f13253 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs
@@ -23,6 +23,7 @@ public static class Startup
public static void AddServices(this IServiceCollection services)
{
services.AddScoped();
+ services.AddHttpClient();
services.AddScoped();
services.AddScoped();
services.AddScoped();
@@ -33,6 +34,7 @@ public static void AddServices(this IServiceCollection services)
services.AddScoped();
services.AddScoped();
services.AddScoped();
+ services.AddScoped();
services.AddScoped();
services.AddScoped();
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Configuration/ConfigurationExtensions.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Configuration/ConfigurationExtensions.cs
index 63b61f042..7d5a61795 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi/Configuration/ConfigurationExtensions.cs
+++ b/OpenAPI/LearningHub.Nhs.OpenApi/Configuration/ConfigurationExtensions.cs
@@ -40,6 +40,11 @@ public static class ConfigurationExtensions
///
public const string AzureSectionName = "Azure";
+ ///
+ /// The FindwiseSectionName.
+ ///
+ public const string MoodleSectionName = "Moodle";
+
///
/// Adds config.
///
@@ -58,6 +63,8 @@ public static void AddConfig(this IServiceCollection services, IConfiguration co
services.AddOptions().Bind(config.GetSection(LearningHubApiSectionName));
services.AddOptions().Bind(config.GetSection(AzureSectionName));
+
+ services.AddOptions().Bind(config.GetSection(MoodleSectionName));
}
private static OptionsBuilder RegisterPostConfigure(this OptionsBuilder builder)
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MoodleController.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MoodleController.cs
new file mode 100644
index 000000000..30cb31a4e
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MoodleController.cs
@@ -0,0 +1,47 @@
+namespace LearningHub.NHS.OpenAPI.Controllers
+{
+ using LearningHub.Nhs.OpenApi.Services.Interface.Services;
+ using Microsoft.AspNetCore.Authorization;
+ using Microsoft.AspNetCore.Mvc;
+ using System.Threading.Tasks;
+
+ ///
+ /// Moodle operations.
+ ///
+ [Route("Moodle")]
+ [ApiController]
+ [Authorize]
+ public class MoodleController : Controller
+ {
+ private readonly IMoodleApiService moodleService;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The moodle service.
+ public MoodleController(IMoodleApiService moodleService)
+ {
+ this.moodleService = moodleService;
+ }
+
+ ///
+ /// The GetMoodleUserId.
+ ///
+ /// The LH user id.
+ /// The .
+ [HttpGet]
+ [Route("GetMoodleUserId/{currentUserId?}")]
+ public async Task GetMoodleUserId(int? currentUserId)
+ {
+ if (currentUserId.HasValue)
+ {
+ var moodleUser = await this.moodleService.GetMoodleUserIdByUsernameAsync(currentUserId.Value);
+ return this.Ok(moodleUser);
+ }
+ else
+ {
+ return this.Ok(0);
+ }
+ }
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json b/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json
index 401183bf6..61417224f 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json
+++ b/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json
@@ -119,5 +119,10 @@
"ResponseType": "code id_token",
"AuthSecret": "",
"AuthTimeout": 20
+ },
+ "Moodle": {
+ "APIBaseUrl": "",
+ "APIWSRestFormat": "json",
+ "APIWSToken": ""
}
}
From 60f1317bf214bfd1d02925a5090f7eb554c5f66e Mon Sep 17 00:00:00 2001
From: Binon
Date: Wed, 30 Jul 2025 15:22:55 +0100
Subject: [PATCH 05/11] Rolling back Models to 48 to fix the build
---
LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj | 2 +-
.../LearningHub.Nhs.OpenApi.Services.csproj | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj
index b69ead582..dc2cf661d 100644
--- a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj
+++ b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj
@@ -113,7 +113,7 @@
-
+
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj
index bf7b23c23..9002a0237 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj
@@ -30,7 +30,7 @@
-
+
From 81c4c2c346ae5ffd4e74ac29ea198301a6976459 Mon Sep 17 00:00:00 2001
From: AnjuJose011 <154979799+AnjuJose011@users.noreply.github.com>
Date: Thu, 31 Jul 2025 09:01:16 +0100
Subject: [PATCH 06/11] upadtes-TD-5868
---
.../ContributeProvideByTab.vue | 2 +-
.../Styles/sections/_all.scss | 422 +++++++++---------
2 files changed, 214 insertions(+), 210 deletions(-)
diff --git a/LearningHub.Nhs.WebUI/Scripts/vuesrc/contribute-resource/ContributeProvideByTab.vue b/LearningHub.Nhs.WebUI/Scripts/vuesrc/contribute-resource/ContributeProvideByTab.vue
index a177d7002..608af2201 100644
--- a/LearningHub.Nhs.WebUI/Scripts/vuesrc/contribute-resource/ContributeProvideByTab.vue
+++ b/LearningHub.Nhs.WebUI/Scripts/vuesrc/contribute-resource/ContributeProvideByTab.vue
@@ -3,7 +3,7 @@
Content developed with
-
When applicable pease select the provider of this content. This will enable users to search for content produced by specific organisations.
+
When applicable please select the provider of this content. This will enable users to search for content produced by specific organisations.
Not applicable
diff --git a/LearningHub.Nhs.WebUI/Styles/sections/_all.scss b/LearningHub.Nhs.WebUI/Styles/sections/_all.scss
index 22c55622d..a127ade9d 100644
--- a/LearningHub.Nhs.WebUI/Styles/sections/_all.scss
+++ b/LearningHub.Nhs.WebUI/Styles/sections/_all.scss
@@ -140,268 +140,272 @@ div.contribute {
}
div.contribute {
- h2 {
- .warningTriangle {
- padding-left: 10px;
- vertical-align: middle;
- }
- }
-
- h3 {
- .warningTriangle {
- padding-left: 10px;
- vertical-align: middle;
- }
- }
-
- div.common-content {
- div.form-group {
- margin-bottom: 0;
+ h2 {
+ .warningTriangle {
+ padding-left: 10px;
+ vertical-align: middle;
+ }
}
- .bg-grey-white {
- padding: 17px 25px 30px 25px;
- color: $nhsuk-black;
+ h3 {
+ .warningTriangle {
+ padding-left: 10px;
+ vertical-align: middle;
+ }
}
- }
- div.white-background {
- background-color: $nhsuk-white;
- min-height: 420px;
- }
-
- .limit-width {
- width: 100%;
- max-width: 850px;
- margin-left: 40px;
- padding-right: 50px;
- }
+ div.common-content {
+ div.form-group {
+ margin-bottom: 0;
+ }
- div.contribute-header {
- .draftText {
- color: $nhsuk-green;
- margin-top: 0;
+ .bg-grey-white {
+ padding: 17px 25px 30px 25px;
+ color: $nhsuk-black;
+ }
}
- .error-message {
- color: $nhsuk-red;
- font-weight: bold;
+ div.white-background {
+ background-color: $nhsuk-white;
+ min-height: 420px;
}
- .warning-banner {
- display: flex;
- flex-flow: row;
- justify-content: space-between;
- padding: 1.5rem 1.5rem 0.8rem 1.5rem;
- border-bottom: 1px solid $nhsuk-grey-light;
- border-top: 1px solid $nhsuk-grey-light;
-
- div.warningTriangle {
- font-size: 40px;
- }
-
- div.info {
- padding-left: 12px;
- }
-
- div.dismiss {
- text-align: end;
- padding-top: .5rem;
- padding-right: 2rem;
-
- button {
- font-size: 2.5rem;
- color: $nhsuk-grey;
- }
- }
-
- .warning-banner-left {
- display: flex;
- justify-content: space-between;
+ .limit-width {
width: 100%;
- max-width: 800px;
+ max-width: 850px;
margin-left: 40px;
- }
+ padding-right: 50px;
}
- }
- .warningTriangle {
- color: #ffb81c;
- font-size: 2rem;
+ div.contribute-header {
+ .draftText {
+ color: $nhsuk-green;
+ margin-top: 0;
+ }
- &.large {
- font-size: 4rem !important;
- }
- }
+ .error-message {
+ color: $nhsuk-red;
+ font-weight: bold;
+ }
- button.delete-button {
- text-decoration: none;
- color: $nhsuk-grey-placeholder;
- font-size: 1.6rem;
+ .warning-banner {
+ display: flex;
+ flex-flow: row;
+ justify-content: space-between;
+ padding: 1.5rem 1.5rem 0.8rem 1.5rem;
+ border-bottom: 1px solid $nhsuk-grey-light;
+ border-top: 1px solid $nhsuk-grey-light;
+
+ div.warningTriangle {
+ font-size: 40px;
+ }
- i {
- margin-right: 4px;
- font-size: 1.8rem;
- }
- }
+ div.info {
+ padding-left: 12px;
+ }
- button.publish-button {
- color: $nhsuk-white;
- background-color: $nhsuk-green;
- font-size: 19px;
- text-align: center !important;
- border: 1px solid $nhsuk-green !important;
- min-height: 50px;
- min-width: 115px;
- padding: 0px 25px 0px 25px;
- border-radius: 5px;
- }
+ div.dismiss {
+ text-align: end;
+ padding-top: .5rem;
+ padding-right: 2rem;
- button.publish-button:disabled {
- background-color: $nhsuk-grey;
- border-color: $nhsuk-grey !important;
- }
+ button {
+ font-size: 2.5rem;
+ color: $nhsuk-grey;
+ }
+ }
- button.btn-outline-custom:disabled {
- color: $nhsuk-grey !important;
- border-color: $nhsuk-grey !important;
- }
+ .warning-banner-left {
+ display: flex;
+ justify-content: space-between;
+ width: 100%;
+ max-width: 800px;
+ margin-left: 40px;
+ }
+ }
+ }
- button.btn-outline-custom:disabled:hover {
- background-color: $nhsuk-white !important;
- }
+ .warningTriangle {
+ color: #ffb81c;
+ font-size: 2rem;
- div.resource-area-container, div.common-content {
- div.resource-area-header {
- background-color: $nhsuk-grey;
- color: $nhsuk-grey-white;
- border-top-left-radius: .5rem;
- border-top-right-radius: .5rem;
- font-family: $font-stack-bold;
- padding: 1.4rem 2rem 1.0rem 2rem;
- display: flex;
- justify-content: space-between;
+ &.large {
+ font-size: 4rem !important;
+ }
+ }
- a,
- button {
+ button.delete-button {
text-decoration: none;
- font-size: 19px;
- font-family: $font-stack;
- color: $nhsuk-grey-white !important;
- padding-top: 0;
+ color: $nhsuk-grey-placeholder;
+ font-size: 1.6rem;
i {
- margin-left: 4px;
+ margin-right: 4px;
+ font-size: 1.8rem;
}
- }
}
- div.resource-area-body {
- background-color: $nhsuk-grey-white;
- border-bottom-left-radius: .5rem;
- border-bottom-right-radius: .5rem;
- min-height: 300px;
- padding: 20px 10px 20px 10px;
+ button.publish-button {
+ color: $nhsuk-white;
+ background-color: $nhsuk-green;
+ font-size: 19px;
+ text-align: center !important;
+ border: 1px solid $nhsuk-green !important;
+ min-height: 50px;
+ min-width: 115px;
+ padding: 0px 25px 0px 25px;
+ border-radius: 5px;
}
- .radio-options {
- height: 12px !important;
- width: 12px !important;
- border: 1px solid $nhsuk-black;
- color: $nhsuk-black;
+ button.publish-button:disabled {
+ background-color: $nhsuk-grey;
+ border-color: $nhsuk-grey !important;
}
- .radio-options-text {
- margin-right: 20px;
+ button.btn-outline-custom:disabled {
+ color: $nhsuk-grey !important;
+ border-color: $nhsuk-grey !important;
}
- .author-details, .file-details, .licence-details {
- display: flex;
- justify-content: space-between;
- background-color: $nhsuk-white;
- border-radius: 5px;
- padding: 25px;
+ button.btn-outline-custom:disabled:hover {
+ background-color: $nhsuk-white !important;
+ }
- button,
- a {
- font-size: 16px;
- color: $nhsuk-red;
- text-decoration: none;
- display: flex;
- justify-content: space-between;
+ div.resource-area-container, div.common-content {
+ div.resource-area-header {
+ background-color: $nhsuk-grey;
+ color: $nhsuk-grey-white;
+ border-top-left-radius: .5rem;
+ border-top-right-radius: .5rem;
+ font-family: $font-stack-bold;
+ padding: 1.4rem 2rem 1.0rem 2rem;
+ display: flex;
+ justify-content: space-between;
- i {
- padding-left: 10px;
- padding-top: 3px;
+ a,
+ button {
+ text-decoration: none;
+ font-size: 19px;
+ font-family: $font-stack;
+ color: $nhsuk-grey-white !important;
+ padding-top: 0;
+
+ i {
+ margin-left: 4px;
+ }
+ }
}
- }
- .divider {
- color: $nhsuk-grey-light;
- }
- }
+ div.resource-area-body {
+ background-color: $nhsuk-grey-white;
+ border-bottom-left-radius: .5rem;
+ border-bottom-right-radius: .5rem;
+ min-height: 300px;
+ padding: 20px 10px 20px 10px;
+ }
- .author-details {
- border: solid 1px $nhsuk-grey-light;
- padding: 22px 15px 10px 15px;
+ .radio-options {
+ height: 12px !important;
+ width: 12px !important;
+ border: 1px solid $nhsuk-black;
+ color: $nhsuk-black;
+ }
- i {
- color: $nhsuk-grey;
- margin-right: 1rem;
- }
- }
+ .radio-options-text {
+ margin-right: 20px;
+ }
- .keyword-container {
- display: flex;
- flex-wrap: wrap;
+ .author-details, .file-details, .licence-details {
+ display: flex;
+ justify-content: space-between;
+ background-color: $nhsuk-white;
+ border-radius: 5px;
+ padding: 25px;
+
+ button,
+ a {
+ font-size: 16px;
+ color: $nhsuk-red;
+ text-decoration: none;
+ display: flex;
+ justify-content: space-between;
+
+ i {
+ padding-left: 10px;
+ padding-top: 3px;
+ }
+ }
- .keyword-tag {
- background-color: $nhsuk-grey-white;
- border-radius: 20px;
- margin-bottom: 10px;
- padding: 8px 10px 3px 15px;
+ .divider {
+ color: $nhsuk-grey-light;
+ }
+ }
- button {
- color: $nhsuk-red;
- font-size: 2rem;
+ .author-details {
+ border: solid 1px $nhsuk-grey-light;
+ padding: 22px 15px 10px 15px;
+
+ i {
+ color: $nhsuk-grey;
+ margin-right: 1rem;
+ }
}
- }
- }
- span.optional {
- font-family: $font-stack;
- }
+ .keyword-label {
+ font-weight: normal;
+ }
+
+ .keyword-container {
+ display: flex;
+ flex-wrap: wrap;
+
+ .keyword-tag {
+ background-color: $nhsuk-grey-white;
+ border-radius: 20px;
+ margin-bottom: 10px;
+ padding: 8px 10px 3px 15px;
+
+ button {
+ color: $nhsuk-red;
+ font-size: 2rem;
+ }
+ }
+ }
+
+ span.optional {
+ font-family: $font-stack;
+ }
- textarea {
- width: 100%;
+ textarea {
+ width: 100%;
+ }
}
- }
- .authored-date label {
- font-size: 1.6rem;
- }
+ .authored-date label {
+ font-size: 1.6rem;
+ }
- div.publish-warning {
- display: flex;
- flex-direction: row;
+ div.publish-warning {
+ display: flex;
+ flex-direction: row;
- .triangle {
- margin-right: 10px;
- display: flex;
- align-items: center;
+ .triangle {
+ margin-right: 10px;
+ display: flex;
+ align-items: center;
- i {
- padding-top: 5px;
- }
+ i {
+ padding-top: 5px;
+ }
+ }
}
- }
- div.highlighted-info {
- background-color: rgba(255, 184, 28, 0.05);
- border: 1px solid #FFB81C;
- padding: 15px 24px;
- margin: 15px 15px 0 15px;
- }
+ div.highlighted-info {
+ background-color: rgba(255, 184, 28, 0.05);
+ border: 1px solid #FFB81C;
+ padding: 15px 24px;
+ margin: 15px 15px 0 15px;
+ }
}
@media (max-width: 768px) {
From 3ff0fc75cbba114e7fd314402e0c0827e4c3cd1e Mon Sep 17 00:00:00 2001
From: Binon
Date: Thu, 31 Jul 2025 09:34:16 +0100
Subject: [PATCH 07/11] Removed moodle models in WebUI
---
.../Shared/Tenant/LearningHub/_Layout.cshtml | 22 ++++++++++---------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/LearningHub.Nhs.WebUI/Views/Shared/Tenant/LearningHub/_Layout.cshtml b/LearningHub.Nhs.WebUI/Views/Shared/Tenant/LearningHub/_Layout.cshtml
index 6b679b67e..1214ec0f7 100644
--- a/LearningHub.Nhs.WebUI/Views/Shared/Tenant/LearningHub/_Layout.cshtml
+++ b/LearningHub.Nhs.WebUI/Views/Shared/Tenant/LearningHub/_Layout.cshtml
@@ -170,15 +170,17 @@
@functions {
public async Task DisplayOffline()
{
- if (ViewContext.RouteData.Values["controller"].ToString() != "Offline" && User.Identity.IsAuthenticated)
- {
- var internalSystem = await this.internalSystemService.GetByIdAsync((int)InternalSystemType.LearningHub);
-
- return internalSystem.IsOffline;
- }
- else
- {
- return false;
- }
+ return false;
+
+ // if (ViewContext.RouteData.Values["controller"].ToString() != "Offline" && User.Identity.IsAuthenticated)
+ // {
+ // var internalSystem = await this.internalSystemService.GetByIdAsync((int)InternalSystemType.LearningHub);
+
+ // return internalSystem.IsOffline;
+ // }
+ // else
+ // {
+ // return false;
+ // }
}
}
\ No newline at end of file
From c60e16546c2bf98b4f08a95fb2c696e922acd3b2 Mon Sep 17 00:00:00 2001
From: Binon
Date: Thu, 31 Jul 2025 09:34:54 +0100
Subject: [PATCH 08/11] Removed the Moodle models in WebUI
---
.../Helpers/ResourceTypeEnumMoodle.cs | 82 ---------
.../Helpers/UtilityHelper.cs | 66 +------
.../LearningHub.Nhs.WebUI.csproj | 2 +-
.../MoodleCompletionResponseViewModel.cs | 28 ---
.../Models/MoodleCourseCompletionViewModel.cs | 103 -----------
.../Models/MoodleCourseResponseViewModel.cs | 165 ------------------
.../Models/MoodleOverviewFileViewModel.cs | 38 ----
.../Models/MoodleUserResponseViewModel.cs | 121 -------------
.../Services/MoodleApiService.cs | 2 +-
.../Services/SearchService.cs | 6 +-
.../Views/Search/_ResourceSearchResult.cshtml | 2 +-
.../LearningHub.Nhs.OpenApi.Services.csproj | 2 +-
12 files changed, 9 insertions(+), 608 deletions(-)
delete mode 100644 LearningHub.Nhs.WebUI/Helpers/ResourceTypeEnumMoodle.cs
delete mode 100644 LearningHub.Nhs.WebUI/Models/MoodleCompletionResponseViewModel.cs
delete mode 100644 LearningHub.Nhs.WebUI/Models/MoodleCourseCompletionViewModel.cs
delete mode 100644 LearningHub.Nhs.WebUI/Models/MoodleCourseResponseViewModel.cs
delete mode 100644 LearningHub.Nhs.WebUI/Models/MoodleOverviewFileViewModel.cs
delete mode 100644 LearningHub.Nhs.WebUI/Models/MoodleUserResponseViewModel.cs
diff --git a/LearningHub.Nhs.WebUI/Helpers/ResourceTypeEnumMoodle.cs b/LearningHub.Nhs.WebUI/Helpers/ResourceTypeEnumMoodle.cs
deleted file mode 100644
index e0601d156..000000000
--- a/LearningHub.Nhs.WebUI/Helpers/ResourceTypeEnumMoodle.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-namespace LearningHub.Nhs.WebUI.Helpers;
-
-///
-/// Represents the types of resources available in Moodle.
-///
-public enum ResourceTypeEnumMoodle
-{
- ///
- /// The undefined resource type.
- ///
- Undefined,
-
- ///
- /// The article resource type.
- ///
- Article,
-
- ///
- /// The audio resource type.
- ///
- Audio,
-
- ///
- /// The embedded resource type.
- ///
- Embedded,
-
- ///
- /// The equipment resource type.
- ///
- Equipment,
-
- ///
- /// The image resource type.
- ///
- Image,
-
- ///
- /// The SCORM resource type.
- ///
- Scorm,
-
- ///
- /// The video resource type.
- ///
- Video,
-
- ///
- /// The web link resource type.
- ///
- WebLink,
-
- ///
- /// The generic file resource type.
- ///
- GenericFile,
-
- ///
- /// The clinical case resource type.
- ///
- Case,
-
- ///
- /// The assessment resource type.
- ///
- Assessment,
-
- ///
- /// The HTML resource type.
- ///
- Html,
-
- ///
- /// The Moodle resource type.
- ///
- Moodle,
-
- ///
- /// The Moodle course resource type.
- ///
- Course,
-}
\ No newline at end of file
diff --git a/LearningHub.Nhs.WebUI/Helpers/UtilityHelper.cs b/LearningHub.Nhs.WebUI/Helpers/UtilityHelper.cs
index c07ab98e9..e1732d5a3 100644
--- a/LearningHub.Nhs.WebUI/Helpers/UtilityHelper.cs
+++ b/LearningHub.Nhs.WebUI/Helpers/UtilityHelper.cs
@@ -19,24 +19,6 @@ public static class UtilityHelper
/// Findwise resource type dictionary.
///
public static readonly Dictionary FindwiseResourceTypeDict = new Dictionary()
- {
- { "video", ResourceTypeEnum.Video },
- { "article", ResourceTypeEnum.Article },
- { "case", ResourceTypeEnum.Case },
- { "weblink", ResourceTypeEnum.WebLink },
- { "audio", ResourceTypeEnum.Audio },
- { "scorm", ResourceTypeEnum.Scorm },
- { "assessment", ResourceTypeEnum.Assessment },
- { "genericfile", ResourceTypeEnum.GenericFile },
- { "image", ResourceTypeEnum.Image },
- { "html", ResourceTypeEnum.Html },
- };
-
- /// TODO: Remove this method after adding to Moodle resource types to models project.
- ///
- /// Findwise Moodle resource type dictionary.
- ///
- public static readonly Dictionary FindwiseResourceMoodleTypeDict = new Dictionary()
{
{ "video", ResourceTypeEnum.Video },
{ "article", ResourceTypeEnum.Article },
@@ -166,52 +148,6 @@ public static string GetPrettifiedResourceTypeName(ResourceTypeEnum resourceType
}
}
- /// TODO: Remove this method after adding to Moodle resource types to models project.
- ///
- /// Returns a prettified resource type name, suitable for display in the UI. Includes video/audio duration string.
- ///
- /// The resource type.
- /// The media duration in milliseconds.
- /// The resource type name, and duration if applicable.
- public static string GetPrettifiedResourceTypeNameMoodle(ResourceTypeEnum resourceType, int? durationInMilliseconds = 0)
- {
- switch (resourceType)
- {
- case ResourceTypeEnum.Assessment:
- return "Assessment";
- case ResourceTypeEnum.Article:
- return "Article";
- case ResourceTypeEnum.Audio:
- string durationText = GetDurationText(durationInMilliseconds ?? 0);
- durationText = string.IsNullOrEmpty(durationText) ? string.Empty : " - " + durationText;
- return "Audio" + durationText;
- case ResourceTypeEnum.Equipment:
- return "Equipment";
- case ResourceTypeEnum.Image:
- return "Image";
- case ResourceTypeEnum.Scorm:
- return "elearning";
- case ResourceTypeEnum.Video:
- durationText = GetDurationText(durationInMilliseconds ?? 0);
- durationText = string.IsNullOrEmpty(durationText) ? string.Empty : " - " + durationText;
- return "Video" + durationText;
- case ResourceTypeEnum.WebLink:
- return "Web link";
- case ResourceTypeEnum.GenericFile:
- return "File";
- case ResourceTypeEnum.Embedded:
- return "Embedded";
- case ResourceTypeEnum.Case:
- return "Case";
- case ResourceTypeEnum.Html:
- return "HTML";
- case ResourceTypeEnum.Moodle:
- return "Course";
- default:
- return "File";
- }
- }
-
///
/// Returns a prettified resource type name, suitable for display in the UI. Excludes video/audio duration string.
///
@@ -245,6 +181,8 @@ public static string GetPrettifiedResourceTypeName(ResourceTypeEnum resourceType
return "Case";
case ResourceTypeEnum.Html:
return "HTML";
+ case ResourceTypeEnum.Moodle:
+ return "Course";
default:
return "File";
}
diff --git a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj
index dc2cf661d..b69ead582 100644
--- a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj
+++ b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj
@@ -113,7 +113,7 @@
-
+
diff --git a/LearningHub.Nhs.WebUI/Models/MoodleCompletionResponseViewModel.cs b/LearningHub.Nhs.WebUI/Models/MoodleCompletionResponseViewModel.cs
deleted file mode 100644
index 1692a32e6..000000000
--- a/LearningHub.Nhs.WebUI/Models/MoodleCompletionResponseViewModel.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-namespace LearningHub.Nhs.WebUI.Models
-{
- ///
- /// MoodleCompletionResponseViewModel.
- ///
- public class MoodleCompletionResponseViewModel
- {
- ///
- /// Gets or sets the completion status.
- ///
- public string Exception { get; set; }
-
- ///
- /// Gets or sets error code.
- ///
- public string Errorcode { get; set; }
-
- ///
- /// Gets or sets Error message.
- ///
- public string Message { get; set; }
-
- ///
- /// Gets or sets Debug info.
- ///
- public string Debuginfo { get; set; }
- }
-}
diff --git a/LearningHub.Nhs.WebUI/Models/MoodleCourseCompletionViewModel.cs b/LearningHub.Nhs.WebUI/Models/MoodleCourseCompletionViewModel.cs
deleted file mode 100644
index 06eb5cb8f..000000000
--- a/LearningHub.Nhs.WebUI/Models/MoodleCourseCompletionViewModel.cs
+++ /dev/null
@@ -1,103 +0,0 @@
-namespace LearningHub.Nhs.WebUI.Models
-{
- using System.Collections.Generic;
-
- ///
- /// MoodleCourseCompletionViewModel.
- ///
- public class MoodleCourseCompletionViewModel
- {
- ///
- /// Gets or sets the completion status.
- ///
- public CompletStatus CompletionStatus { get; set; }
-
- ///
- /// Gets or sets the list of warnings.
- ///
- public List