diff --git a/LearningHub.Nhs.WebUI/Helpers/ResourceTypeEnumMoodle.cs b/LearningHub.Nhs.WebUI/Helpers/ResourceTypeEnumMoodle.cs new file mode 100644 index 000000000..e0601d156 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Helpers/ResourceTypeEnumMoodle.cs @@ -0,0 +1,82 @@ +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 03e93fc07..ef71191f9 100644 --- a/LearningHub.Nhs.WebUI/Helpers/UtilityHelper.cs +++ b/LearningHub.Nhs.WebUI/Helpers/UtilityHelper.cs @@ -32,6 +32,25 @@ public static class UtilityHelper { "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", ResourceTypeEnumMoodle.Video }, + { "article", ResourceTypeEnumMoodle.Article }, + { "case", ResourceTypeEnumMoodle.Case }, + { "weblink", ResourceTypeEnumMoodle.WebLink }, + { "audio", ResourceTypeEnumMoodle.Audio }, + { "scorm", ResourceTypeEnumMoodle.Scorm }, + { "assessment", ResourceTypeEnumMoodle.Assessment }, + { "genericfile", ResourceTypeEnumMoodle.GenericFile }, + { "image", ResourceTypeEnumMoodle.Image }, + { "html", ResourceTypeEnumMoodle.Html }, + { "moodle", ResourceTypeEnumMoodle.Course }, + }; + /// /// The FormatTwitterDate. /// @@ -147,6 +166,54 @@ 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(ResourceTypeEnumMoodle resourceType, int? durationInMilliseconds = 0) + { + switch (resourceType) + { + case ResourceTypeEnumMoodle.Assessment: + return "Assessment"; + case ResourceTypeEnumMoodle.Article: + return "Article"; + case ResourceTypeEnumMoodle.Audio: + string durationText = GetDurationText(durationInMilliseconds ?? 0); + durationText = string.IsNullOrEmpty(durationText) ? string.Empty : " - " + durationText; + return "Audio" + durationText; + case ResourceTypeEnumMoodle.Equipment: + return "Equipment"; + case ResourceTypeEnumMoodle.Image: + return "Image"; + case ResourceTypeEnumMoodle.Scorm: + return "elearning"; + case ResourceTypeEnumMoodle.Video: + durationText = GetDurationText(durationInMilliseconds ?? 0); + durationText = string.IsNullOrEmpty(durationText) ? string.Empty : " - " + durationText; + return "Video" + durationText; + case ResourceTypeEnumMoodle.WebLink: + return "Web link"; + case ResourceTypeEnumMoodle.GenericFile: + return "File"; + case ResourceTypeEnumMoodle.Embedded: + return "Embedded"; + case ResourceTypeEnumMoodle.Case: + return "Case"; + case ResourceTypeEnumMoodle.Html: + return "HTML"; + case ResourceTypeEnumMoodle.Moodle: + return "Course"; + case ResourceTypeEnumMoodle.Course: + return "Course"; + default: + return "File"; + } + } + /// /// Returns a prettified resource type name, suitable for display in the UI. Excludes video/audio duration string. /// diff --git a/LearningHub.Nhs.WebUI/Models/MoodleCourseResponseViewModel.cs b/LearningHub.Nhs.WebUI/Models/MoodleCourseResponseViewModel.cs index ad94f7b7a..b214cf072 100644 --- a/LearningHub.Nhs.WebUI/Models/MoodleCourseResponseViewModel.cs +++ b/LearningHub.Nhs.WebUI/Models/MoodleCourseResponseViewModel.cs @@ -92,10 +92,15 @@ public class MoodleCourseResponseViewModel /// public int? Category { get; set; } + /// + /// Gets the progress percentage formatted as a string. + /// + public string ProgressPercentage => $"{System.Math.Round(this.Progress ?? 0)}%"; + /// /// Gets or sets the progress. /// - public int? Progress { get; set; } + public double? Progress { get; set; } /// /// Gets or sets the completion status. diff --git a/LearningHub.Nhs.WebUI/Services/SearchService.cs b/LearningHub.Nhs.WebUI/Services/SearchService.cs index 41ff87edb..40feaf6fb 100644 --- a/LearningHub.Nhs.WebUI/Services/SearchService.cs +++ b/LearningHub.Nhs.WebUI/Services/SearchService.cs @@ -163,10 +163,10 @@ public async Task PerformSearch(IPrincipal user, SearchRe { var filter = filters.Where(x => x.DisplayName == filteritem).FirstOrDefault(); - if (filter != null && UtilityHelper.FindwiseResourceTypeDict.ContainsKey(filter.DisplayName)) + if (filter != null && UtilityHelper.FindwiseResourceMoodleTypeDict.ContainsKey(filter.DisplayName)) { - var resourceTypeEnum = UtilityHelper.FindwiseResourceTypeDict[filter.DisplayName]; - var searchfilter = new SearchFilterModel() { DisplayName = UtilityHelper.GetPrettifiedResourceTypeName(resourceTypeEnum), Count = filter.Count, Value = filteritem, Selected = searchRequest.Filters?.Contains(filter.DisplayName) ?? false }; + var resourceTypeEnum = UtilityHelper.FindwiseResourceMoodleTypeDict[filter.DisplayName]; + var searchfilter = new SearchFilterModel() { DisplayName = UtilityHelper.GetPrettifiedResourceTypeNameMoodle(resourceTypeEnum), Count = filter.Count, Value = filteritem, Selected = searchRequest.Filters?.Contains(filter.DisplayName) ?? false }; searchfilters.Add(searchfilter); } } diff --git a/LearningHub.Nhs.WebUI/Views/Home/_CourseEnrolled.cshtml b/LearningHub.Nhs.WebUI/Views/Home/_CourseEnrolled.cshtml index 058c39165..1dd92a06b 100644 --- a/LearningHub.Nhs.WebUI/Views/Home/_CourseEnrolled.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Home/_CourseEnrolled.cshtml @@ -60,7 +60,7 @@
@if (@Model?.Progress != null) { -
Progress: @Model.Progress%
+
Progress: @Model.ProgressPercentage
}
diff --git a/LearningHub.Nhs.WebUI/Views/Search/_ResourceSearchResult.cshtml b/LearningHub.Nhs.WebUI/Views/Search/_ResourceSearchResult.cshtml index ea636286c..c11b89ae8 100644 --- a/LearningHub.Nhs.WebUI/Views/Search/_ResourceSearchResult.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Search/_ResourceSearchResult.cshtml @@ -1,4 +1,5 @@ @model LearningHub.Nhs.WebUI.Models.Search.SearchResultViewModel +@inject Microsoft.Extensions.Configuration.IConfiguration Configuration; @using System.Linq; @using System.Web; @@ -10,99 +11,124 @@ @using LearningHub.Nhs.Models.Search.SearchClick; @{ - var resourceResult = Model.ResourceSearchResult; - var pagingModel = Model.ResourceResultPaging; - var index = pagingModel.CurrentPage * pagingModel.PageSize; - var searchString = HttpUtility.UrlEncode(Model.SearchString); - - string GetUrl(int resourceReferenceId, int itemIndex, int nodePathId, SearchClickPayloadModel payload) - { - var searchSignal = payload?.SearchSignal; - string groupId = HttpUtility.UrlEncode(Model.GroupId.ToString()); - string searchSignalQueryEncoded = HttpUtility.UrlEncode(HttpUtility.UrlDecode(searchSignal?.Query)); - - return $@"/search/record-resource-click?url=/Resource/{resourceReferenceId}&nodePathId={nodePathId}&itemIndex={payload?.HitNumber} + var resourceResult = Model.ResourceSearchResult; + var pagingModel = Model.ResourceResultPaging; + var index = pagingModel.CurrentPage * pagingModel.PageSize; + var searchString = HttpUtility.UrlEncode(Model.SearchString); + + string GetUrl(int resourceReferenceId, int itemIndex, int nodePathId, SearchClickPayloadModel payload) + { + var searchSignal = payload?.SearchSignal; + string groupId = HttpUtility.UrlEncode(Model.GroupId.ToString()); + string searchSignalQueryEncoded = HttpUtility.UrlEncode(HttpUtility.UrlDecode(searchSignal?.Query)); + + return $@"/search/record-resource-click?url=/Resource/{resourceReferenceId}&nodePathId={nodePathId}&itemIndex={payload?.HitNumber} &pageIndex={pagingModel.CurrentPage}&totalNumberOfHits={payload?.SearchSignal?.Stats?.TotalHits}&searchText={searchString}&resourceReferenceId={resourceReferenceId} &groupId={groupId}&searchId={searchSignal?.SearchId}&timeOfSearch={searchSignal?.TimeOfSearch}&userQuery={HttpUtility.UrlEncode(searchSignal.UserQuery)} &query={searchSignalQueryEncoded}&title={payload?.DocumentFields?.Title}"; - } + } + + string GetMoodleCourseUrl(string courseId) + { + var prefix = "M"; + if (courseId.StartsWith(prefix)) + { + courseId = courseId.Replace(prefix, ""); ; + } + + var apiBaseUrl = Configuration["MoodleAPIConfig:BaseUrl"]; + string path = $"course/view.php"; + string returnUrl = $@"{apiBaseUrl}/{path}?id={courseId}"; - bool showCatalogueFieldsInResources = ViewBag.ShowCatalogueFieldsInResources == null || ViewBag.ShowCatalogueFieldsInResources == true; - bool resourceAccessLevelFilterSelected = resourceResult.SearchResourceAccessLevelFilters.Any(f => f.Selected); + return returnUrl; + } + + bool showCatalogueFieldsInResources = ViewBag.ShowCatalogueFieldsInResources == null || ViewBag.ShowCatalogueFieldsInResources == true; + bool resourceAccessLevelFilterSelected = resourceResult.SearchResourceAccessLevelFilters.Any(f => f.Selected); } @foreach (var item in resourceResult.DocumentModel) { - var provider = item.Providers?.FirstOrDefault(); - -
-

- @item.Title -

- - @if (provider != null) - { -
-
- - @ProviderHelper.GetProviderString(provider.Name) -
-
- } - @if (item.CatalogueRestrictedAccess && !Model.HideRestrictedBadge && showCatalogueFieldsInResources) - { -

- @((item.CatalogueHasAccess || this.User.IsInRole("Administrator")) ? "Access Granted" : "Access restricted") -

- } - - @if (!resourceAccessLevelFilterSelected) - { -
-
- Audience access level: - @ResourceAccessLevelHelper.GetResourceAccessLevelText((ResourceAccessibilityEnum)item.ResourceAccessLevel) -
-
- } - - -
-
- Type: - @UtilityHelper.GetPrettifiedResourceTypeName(UtilityHelper.ToEnum(item.ResourceType), 0) -
-
- @await Html.PartialAsync("../Shared/_StarRating.cshtml", item.Rating) -
-
- -

- @item.Description -

- -
- @if (!string.IsNullOrWhiteSpace(item.CatalogueBadgeUrl) && showCatalogueFieldsInResources) - { - Provider's catalogue badge - } - - @if (!string.IsNullOrEmpty(item.CatalogueName) && !this.Model.CatalogueId.HasValue && showCatalogueFieldsInResources) - { - - } - -
- @UtilityHelper.GetAttribution(item.Authors) - @if (!string.IsNullOrEmpty(item.AuthoredDate)) - { - @UtilityHelper.GetInOn(item.AuthoredDate) - @: @item.AuthoredDate - } -
-
-
- index++; + var provider = item.Providers?.FirstOrDefault(); + +
+

+ @if (item.ResourceType == "moodle") + { + @item.Title + } + else + { + @item.Title + } +

+ + @if (provider != null) + { +
+
+ + @ProviderHelper.GetProviderString(provider.Name) +
+
+ } + @if (item.CatalogueRestrictedAccess && !Model.HideRestrictedBadge && showCatalogueFieldsInResources) + { +

+ @((item.CatalogueHasAccess || this.User.IsInRole("Administrator")) ? "Access Granted" : "Access restricted") +

+ } + + @if (!resourceAccessLevelFilterSelected) + { +
+
+ Audience access level: + @ResourceAccessLevelHelper.GetResourceAccessLevelText((ResourceAccessibilityEnum)item.ResourceAccessLevel) +
+
+ } + + +
+
+ Type: + @UtilityHelper.GetPrettifiedResourceTypeNameMoodle(UtilityHelper.ToEnum(item.ResourceType), 0) +
+
+ @if (item.ResourceType != "moodle") + { + @await Html.PartialAsync("../Shared/_StarRating.cshtml", item.Rating) + } +
+
+ +

+ @item.Description +

+ +
+ @if (!string.IsNullOrWhiteSpace(item.CatalogueBadgeUrl) && showCatalogueFieldsInResources) + { + Provider's catalogue badge + } + + @if (!string.IsNullOrEmpty(item.CatalogueName) && !this.Model.CatalogueId.HasValue && showCatalogueFieldsInResources) + { + + } + +
+ @UtilityHelper.GetAttribution(item.Authors) + @if (!string.IsNullOrEmpty(item.AuthoredDate)) + { + @UtilityHelper.GetInOn(item.AuthoredDate) + @: @item.AuthoredDate + } +
+
+
+ index++; } \ No newline at end of file diff --git a/WebAPI/LearningHub.Nhs.Api.Shared/Configuration/FindwiseCollectionIdSettings.cs b/WebAPI/LearningHub.Nhs.Api.Shared/Configuration/FindwiseCollectionIdSettings.cs index 89b29fc90..b83dc6805 100644 --- a/WebAPI/LearningHub.Nhs.Api.Shared/Configuration/FindwiseCollectionIdSettings.cs +++ b/WebAPI/LearningHub.Nhs.Api.Shared/Configuration/FindwiseCollectionIdSettings.cs @@ -19,5 +19,10 @@ public class FindwiseCollectionIdSettings /// Gets or sets the AutoSuggestion collection id. ///
public string AutoSuggestion { get; set; } + + /// + /// Gets or sets the moodle collection id. + /// + public string Moodle { get; set; } } }