diff --git a/AdminUI/LearningHub.Nhs.AdminUI/Controllers/UserGroupController.cs b/AdminUI/LearningHub.Nhs.AdminUI/Controllers/UserGroupController.cs index 3a27787f4..1be7f211c 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/Controllers/UserGroupController.cs +++ b/AdminUI/LearningHub.Nhs.AdminUI/Controllers/UserGroupController.cs @@ -257,6 +257,7 @@ public async Task AddUsersToUserGroup(int userGroupId, string use var vr = await this.userGroupService.AddUsersToUserGroup(userGroupId, userIdList); if (vr.IsValid) { + this.ClearUserCachedPermissions(userIdList); return this.Json(new { success = true, @@ -527,5 +528,16 @@ public async Task UserGroupCatalogues(int id) return this.PartialView("_UserGroupCatalogues", catalogues); } + + private void ClearUserCachedPermissions(string userIdList) + { + if (!string.IsNullOrWhiteSpace(userIdList)) + { + foreach (var userId in userIdList.Split(",")) + { + _ = Task.Run(async () => { await this.userService.ClearUserCachedPermissions(int.Parse(userId)); }); + } + } + } } } \ No newline at end of file diff --git a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj index f222dc100..21ec69f5e 100644 --- a/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj +++ b/AdminUI/LearningHub.Nhs.AdminUI/LearningHub.Nhs.AdminUI.csproj @@ -89,7 +89,7 @@ - + diff --git a/LearningHub.Nhs.WebUI/Configuration/FindwiseSettings.cs b/LearningHub.Nhs.WebUI/Configuration/FindwiseSettings.cs index dcac6798d..683d5b4c9 100644 --- a/LearningHub.Nhs.WebUI/Configuration/FindwiseSettings.cs +++ b/LearningHub.Nhs.WebUI/Configuration/FindwiseSettings.cs @@ -14,5 +14,10 @@ public class FindwiseSettings /// Gets or sets the CatalogueSearchPageSize. /// public int CatalogueSearchPageSize { get; set; } + + /// + /// Gets or sets the AllCatalogueSearchPageSize. + /// + public int AllCatalogueSearchPageSize { get; set; } } } diff --git a/LearningHub.Nhs.WebUI/Configuration/Settings.cs b/LearningHub.Nhs.WebUI/Configuration/Settings.cs index d107ac2d5..9764d293e 100644 --- a/LearningHub.Nhs.WebUI/Configuration/Settings.cs +++ b/LearningHub.Nhs.WebUI/Configuration/Settings.cs @@ -245,5 +245,10 @@ public Settings() /// Gets or sets the MediaKindSettings. /// public MediaKindSettings MediaKindSettings { get; set; } = new MediaKindSettings(); + + /// + /// Gets or sets AllCataloguePageSize. + /// + public int AllCataloguePageSize { get; set; } } } \ No newline at end of file diff --git a/LearningHub.Nhs.WebUI/Controllers/Api/ContributeController.cs b/LearningHub.Nhs.WebUI/Controllers/Api/ContributeController.cs index 6bfbcca6c..572cd69c9 100644 --- a/LearningHub.Nhs.WebUI/Controllers/Api/ContributeController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/Api/ContributeController.cs @@ -349,11 +349,18 @@ public async Task PublishResourceVersionAsync([FromBody] PublishVi { if (associatedResource.ResourceType != ResourceTypeEnum.Scorm && associatedResource.ResourceType != ResourceTypeEnum.Html) { + try + { var obsoleteFiles = await this.resourceService.GetObsoleteResourceFile(publishViewModel.ResourceVersionId); if (obsoleteFiles != null && obsoleteFiles.Any()) { - await this.fileService.PurgeResourceFile(null, obsoleteFiles); + _ = Task.Run(async () => { await this.fileService.PurgeResourceFile(null, obsoleteFiles); }); } + } + catch (Exception ex) + { + this.Logger.LogError($"File Archive Error: {ex.Message}", $"ResourceVersionId -{publishViewModel.ResourceVersionId}"); + } } } @@ -707,8 +714,8 @@ private async Task RemoveBlockCollectionFiles(int resourceVersionId, BlockCollec { foreach (var oldblock in existingImages) { - var entry = newBlocks.FirstOrDefault(x => x.BlockType == BlockType.Media && x.MediaBlock != null && x.MediaBlock.MediaType == MediaType.Image && x.MediaBlock.Image != null && (x.MediaBlock?.Image?.File?.FileId == oldblock.MediaBlock?.Image?.File?.FileId || x.MediaBlock?.Image?.File?.FilePath == oldblock.MediaBlock?.Image?.File?.FilePath)); - if (entry == null) + var entry = newBlocks.FirstOrDefault(x => x.BlockType == BlockType.Media && x.MediaBlock != null && x.MediaBlock.MediaType == MediaType.Image && x.MediaBlock.Image != null && (x.MediaBlock?.Image?.File?.FileId == oldblock.MediaBlock?.Image?.File?.FileId || x.MediaBlock?.Image?.File?.FilePath == oldblock.MediaBlock?.Image?.File?.FilePath)); + if (entry == null) { filePaths.Add(oldblock?.MediaBlock?.Image?.File?.FilePath); } @@ -790,8 +797,10 @@ private async Task RemoveBlockCollectionFiles(int resourceVersionId, BlockCollec _ = Task.Run(async () => { await this.fileService.PurgeResourceFile(null, deleteList); }); } } - catch + catch (Exception ex) { + var param = new object[] { resourceVersionId, existingResource, newResource }; + this.Logger.LogError($"BlockCollection Archive Error: {ex.Message}", param); } } diff --git a/LearningHub.Nhs.WebUI/Controllers/Api/ResourceController.cs b/LearningHub.Nhs.WebUI/Controllers/Api/ResourceController.cs index 0616474ff..e5e8ab35e 100644 --- a/LearningHub.Nhs.WebUI/Controllers/Api/ResourceController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/Api/ResourceController.cs @@ -2,6 +2,7 @@ namespace LearningHub.Nhs.WebUI.Controllers.Api { using System; using System.Collections.Generic; + using System.Linq; using System.Threading.Tasks; using LearningHub.Nhs.Models.Enums; using LearningHub.Nhs.Models.Resource; @@ -565,9 +566,9 @@ public async Task DeleteResourceProviderAsync(int resourceVersionI /// A representing the asynchronous operation. [HttpPost] [Route("ArchiveResourceFile")] - public ActionResult ArchiveResourceFile(List filePaths) + public ActionResult ArchiveResourceFile(IEnumerable filePaths) { - _ = Task.Run(async () => { await this.fileService.PurgeResourceFile(null, filePaths); }); + _ = Task.Run(async () => { await this.fileService.PurgeResourceFile(null, filePaths.ToList()); }); return this.Ok(); } diff --git a/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs b/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs index fb4d3def3..efa8cd4f2 100644 --- a/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/CatalogueController.cs @@ -123,6 +123,7 @@ public async Task Index(int pageIndex = 1, string term = null) BookmarkId = t.BookmarkId, NodeId = int.Parse(t.Id), BadgeUrl = t.BadgeUrl, + Providers = t.Providers, }).ToList(); } else @@ -551,5 +552,70 @@ public async Task RequestPreviewAccess(CatalogueRequestAccessView return this.View("RequestPreviewAccess", viewModel); } } + + /// + /// Get all catelogues, filter and pagination based on alphabets. + /// + /// filterChar. + /// rk. + [Route("/allcatalogue")] + [Route("/allcatalogue/{filterChar}")] + public async Task GetAllCatalogue(string filterChar = "a") + { + var pageSize = this.settings.AllCataloguePageSize; + var catalogues = await this.catalogueService.GetAllCatalogueAsync(filterChar, pageSize); + return this.View("allcatalogue", catalogues); + } + + /// + /// AllCatalogues Search. + /// + /// pageIndex. + /// Search term. + /// IActionResult. + [Route("/allcataloguesearch")] + public async Task GetAllCatalogueSearch(int pageIndex = 1, string term = null) + { + var catalogues = new AllCatalogueSearchResponseViewModel(); + var searchString = term?.Trim() ?? string.Empty; + var allCatalogueSearchPageSize = this.settings.FindwiseSettings.AllCatalogueSearchPageSize; + + if (!string.IsNullOrWhiteSpace(term)) + { + var termCatalogues = await this.searchService.GetAllCatalogueSearchResultAsync( + new AllCatalogueSearchRequestModel + { + SearchText = searchString, + PageIndex = pageIndex - 1, + PageSize = allCatalogueSearchPageSize, + }); + + catalogues.TotalCount = termCatalogues.TotalHits; + catalogues.Catalogues = termCatalogues.DocumentModel.Select(t => new AllCatalogueViewModel + { + Url = t.Url, + Name = t.Name, + CardImageUrl = t.CardImageUrl, + BannerUrl = t.BannerUrl, + Description = t.Description, + RestrictedAccess = t.RestrictedAccess, + HasAccess = t.HasAccess, + IsBookmarked = t.IsBookmarked, + BookmarkId = t.BookmarkId, + NodeId = int.Parse(t.Id), + BadgeUrl = t.BadgeUrl, + Providers = t.Providers, + }).ToList(); + } + else + { + catalogues.TotalCount = 0; + catalogues.Catalogues = new List(); + } + + this.ViewBag.PageIndex = pageIndex; + this.ViewBag.PageSize = allCatalogueSearchPageSize; + return this.View("AllCatalogueSearch", catalogues); + } } } \ No newline at end of file diff --git a/LearningHub.Nhs.WebUI/Interfaces/ICatalogueService.cs b/LearningHub.Nhs.WebUI/Interfaces/ICatalogueService.cs index 30ba46a54..635eee151 100644 --- a/LearningHub.Nhs.WebUI/Interfaces/ICatalogueService.cs +++ b/LearningHub.Nhs.WebUI/Interfaces/ICatalogueService.cs @@ -138,5 +138,13 @@ public interface ICatalogueService /// The user - user group id. /// The validation result. Task RemoveUserFromRestrictedAccessUserGroup(int userUserGroupId); + + /// + /// The GetAllCatalogueAsync. + /// + /// The letter. + /// The pageSize. + /// The allcatalogue result based on letters. + Task GetAllCatalogueAsync(string filterChar, int pageSize); } } diff --git a/LearningHub.Nhs.WebUI/Interfaces/ISearchService.cs b/LearningHub.Nhs.WebUI/Interfaces/ISearchService.cs index 4f8ed36c7..b01be5bce 100644 --- a/LearningHub.Nhs.WebUI/Interfaces/ISearchService.cs +++ b/LearningHub.Nhs.WebUI/Interfaces/ISearchService.cs @@ -77,5 +77,12 @@ public interface ISearchService /// catalogue search request model. /// The . Task CreateCatalogueSearchTermEventAsync(CatalogueSearchRequestModel catalogueSearchRequestModel); + + /// + /// Get AllCatalogue Search Result Async. + /// + /// The catalogue Search Request Model. + /// The . + Task GetAllCatalogueSearchResultAsync(AllCatalogueSearchRequestModel catalogueSearchRequestModel); } } diff --git a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj index 6a9ff6ca0..9e46194b1 100644 --- a/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj +++ b/LearningHub.Nhs.WebUI/LearningHub.Nhs.WebUI.csproj @@ -108,7 +108,7 @@ - + diff --git a/LearningHub.Nhs.WebUI/Models/NavigationModel.cs b/LearningHub.Nhs.WebUI/Models/NavigationModel.cs index ca4dee523..950343bde 100644 --- a/LearningHub.Nhs.WebUI/Models/NavigationModel.cs +++ b/LearningHub.Nhs.WebUI/Models/NavigationModel.cs @@ -69,5 +69,10 @@ public class NavigationModel /// Gets or sets a value indicating whether to show my account. /// public bool ShowMyAccount { get; set; } + + /// + /// Gets or sets a value indicating whether to show Browse Catalogues. + /// + public bool ShowBrowseCatalogues { get; set; } } } diff --git a/LearningHub.Nhs.WebUI/Scripts/vuesrc/contribute/Content.vue b/LearningHub.Nhs.WebUI/Scripts/vuesrc/contribute/Content.vue index 154d78e98..00d740bb2 100644 --- a/LearningHub.Nhs.WebUI/Scripts/vuesrc/contribute/Content.vue +++ b/LearningHub.Nhs.WebUI/Scripts/vuesrc/contribute/Content.vue @@ -822,7 +822,7 @@ this.fileUploadRef.value = null; (this.$refs.fileUploader as any).uploadResourceFile(this.file); }, - fileUploadComplete(uploadResult: FileUploadResult) { + async fileUploadComplete(uploadResult: FileUploadResult) { if (!uploadResult.invalid) { if (uploadResult.resourceType != ResourceType.SCORM) { this.$store.commit("setResourceType", uploadResult.resourceType); @@ -841,7 +841,7 @@ } if (this.filePathBeforeFileChange.length > 0) { - this.getResourceFilePath('completed'); + await this.getResourceFilePath('completed'); if (this.filePathBeforeFileChange.length > 0 && this.filePathAfterFileChange.length > 0) { let filePaths = this.filePathBeforeFileChange.filter(item => !this.filePathAfterFileChange.includes(item)); if (filePaths.length > 0) { @@ -1040,6 +1040,7 @@ await resourceData.getObsoleteResourceFile(resource.resourceVersionId).then(response => { if (fileChangeStatus == 'initialised') { this.filePathBeforeFileChange = response; + this.filePathAfterFileChange.length = 0; } else if (fileChangeStatus == 'completed') { this.filePathAfterFileChange = response; diff --git a/LearningHub.Nhs.WebUI/Scripts/vuesrc/data/resource.ts b/LearningHub.Nhs.WebUI/Scripts/vuesrc/data/resource.ts index 9127917d3..817ffcf2f 100644 --- a/LearningHub.Nhs.WebUI/Scripts/vuesrc/data/resource.ts +++ b/LearningHub.Nhs.WebUI/Scripts/vuesrc/data/resource.ts @@ -558,8 +558,8 @@ const getObsoleteResourceFile = async function (id: number): Promise { }; const archiveResourceFile = async function (filepaths: string[]): Promise { - const params = {filePaths:filepaths}; - return await AxiosWrapper.axios.post('/api/Resource/DuplicateBlocks', params).then(() => { + + return await AxiosWrapper.axios.post('/api/Resource/ArchiveResourceFile', filepaths).then(() => { return true }).catch(e => { console.log('archiveResourceFile:' + e); diff --git a/LearningHub.Nhs.WebUI/Services/CatalogueService.cs b/LearningHub.Nhs.WebUI/Services/CatalogueService.cs index fc95fe746..615363cfd 100644 --- a/LearningHub.Nhs.WebUI/Services/CatalogueService.cs +++ b/LearningHub.Nhs.WebUI/Services/CatalogueService.cs @@ -602,5 +602,33 @@ public async Task RemoveUserFromRestrictedAccessUse return apiResponse.ValidationResult; } + + /// + /// GetAllCatalogueAsync. + /// + /// The filterChar. + /// the pageSize. + /// A representing the result of the asynchronous operation. + public async Task GetAllCatalogueAsync(string filterChar, int pageSize) + { + AllCatalogueResponseViewModel viewmodel = new AllCatalogueResponseViewModel { }; + var client = await this.LearningHubHttpClient.GetClientAsync(); + + var request = $"catalogue/allcatalogues/{pageSize}/{filterChar}"; + var response = await client.GetAsync(request).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + viewmodel = JsonConvert.DeserializeObject(result); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + return viewmodel; + } } } diff --git a/LearningHub.Nhs.WebUI/Services/NavigationPermissionService.cs b/LearningHub.Nhs.WebUI/Services/NavigationPermissionService.cs index 954b20ca7..95e74022e 100644 --- a/LearningHub.Nhs.WebUI/Services/NavigationPermissionService.cs +++ b/LearningHub.Nhs.WebUI/Services/NavigationPermissionService.cs @@ -80,6 +80,7 @@ public NavigationModel NotAuthenticated() ShowRegister = false, ShowSignOut = false, ShowMyAccount = false, + ShowBrowseCatalogues = false, }; } @@ -104,6 +105,7 @@ private NavigationModel AuthenticatedAdministrator(string controllerName) ShowRegister = false, ShowSignOut = true, ShowMyAccount = true, + ShowBrowseCatalogues = true, }; } @@ -128,6 +130,7 @@ private NavigationModel AuthenticatedBlueUser(string controllerName) ShowRegister = false, ShowSignOut = true, ShowMyAccount = true, + ShowBrowseCatalogues = true, }; } @@ -151,6 +154,7 @@ private NavigationModel AuthenticatedGuest() ShowRegister = false, ShowSignOut = true, ShowMyAccount = false, + ShowBrowseCatalogues = false, }; } @@ -175,6 +179,7 @@ private async Task AuthenticatedReadOnly(string controllerName) ShowRegister = false, ShowSignOut = true, ShowMyAccount = false, + ShowBrowseCatalogues = true, }; } @@ -198,6 +203,7 @@ private async Task AuthenticatedBasicUserOnly() ShowRegister = false, ShowSignOut = true, ShowMyAccount = true, + ShowBrowseCatalogues = true, }; } @@ -221,6 +227,7 @@ private NavigationModel InLoginWizard() ShowRegister = false, ShowSignOut = true, ShowMyAccount = false, + ShowBrowseCatalogues = false, }; } } diff --git a/LearningHub.Nhs.WebUI/Services/SearchService.cs b/LearningHub.Nhs.WebUI/Services/SearchService.cs index 3fc38d8a2..8e22e0eeb 100644 --- a/LearningHub.Nhs.WebUI/Services/SearchService.cs +++ b/LearningHub.Nhs.WebUI/Services/SearchService.cs @@ -587,6 +587,53 @@ public async Task CreateCatalogueSearchTermEventAsync(CatalogueSearchReques } } + /// + /// GetAllCatalogueSearchResultAsync. + /// + /// catalogueSearchRequestModel. + /// The . + public async Task GetAllCatalogueSearchResultAsync(AllCatalogueSearchRequestModel catalogueSearchRequestModel) + { + SearchAllCatalogueViewModel searchViewModel = new SearchAllCatalogueViewModel(); + + try + { + var client = await this.LearningHubHttpClient.GetClientAsync(); + + catalogueSearchRequestModel.SearchText = this.DecodeProblemCharacters(catalogueSearchRequestModel.SearchText); + + var json = JsonConvert.SerializeObject(catalogueSearchRequestModel); + var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json"); + + var request = $"Search/GetAllCatalogueSearchResult"; + var response = await client.PostAsync(request, stringContent).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadAsStringAsync(); + searchViewModel = JsonConvert.DeserializeObject(result); + + if (searchViewModel.DocumentModel != null + && searchViewModel.DocumentModel.Count != 0) + { + searchViewModel.DocumentModel.ForEach(x => x.Description = this.RemoveHtmlTags(x.Description)); + } + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + return searchViewModel; + } + catch (Exception ex) + { + searchViewModel.ErrorOnAPI = true; + this.Logger.LogError(string.Format("Error occurred in GetAllCatalogueSearchResultAsync: {0}", ex.Message)); + return searchViewModel; + } + } + /// /// The RemoveHtmlTags. /// diff --git a/LearningHub.Nhs.WebUI/Styles/nhsuk/pages/catalogue.scss b/LearningHub.Nhs.WebUI/Styles/nhsuk/pages/catalogue.scss index 22ffd1a18..dd64e5a88 100644 --- a/LearningHub.Nhs.WebUI/Styles/nhsuk/pages/catalogue.scss +++ b/LearningHub.Nhs.WebUI/Styles/nhsuk/pages/catalogue.scss @@ -173,4 +173,15 @@ textarea { font-weight: 700; line-height: 24px; word-wrap: break-word -} \ No newline at end of file +} +.allCatalogue-lettercard { + background: $nhsuk-blue !important; + padding: 12px 8px; + margin-left: 16px; + width: 52px; + height: 56px; + display: flex; + align-items: center; + justify-content: center; + color: $nhsuk-white !important; +} diff --git a/LearningHub.Nhs.WebUI/Views/Catalogue/AllCatalogue.cshtml b/LearningHub.Nhs.WebUI/Views/Catalogue/AllCatalogue.cshtml new file mode 100644 index 000000000..118a5c5f8 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Views/Catalogue/AllCatalogue.cshtml @@ -0,0 +1,144 @@ +@using LearningHub.Nhs.WebUI.Extensions +@using Microsoft.AspNetCore.WebUtilities +@model LearningHub.Nhs.Models.Catalogue.AllCatalogueResponseViewModel; + +@{ + ViewData["Title"] = "All Catalogues"; + string cardStyle = "card-provider-details--blank"; +} + +@section styles { + + +} +
+
+

+ A-Z of catalogues +

+ +
+
+
+ @await Html.PartialAsync("_AllCatalogueSearchBar", Model) +
+
+ +
+ +
+
+
+

@Model.FilterChar

+ +
+
+ +
    + + @foreach (var item in Model.Catalogues) + { +
  • + +
    + +
    + @if (!string.IsNullOrWhiteSpace(item.CardImageUrl)) + { + @item.Name + } + else if (!string.IsNullOrWhiteSpace(item.BannerUrl)) + { + @item.Name + } + else + { +
    + } +
    + @if (item.Providers?.Count > 0) + { +
    + @ProviderHelper.GetProviderString(item.Providers.FirstOrDefault().Name) +
    + } + else + { +
    + } + +
    + +

    + @item.Name +

    + +
    +
    + @Html.Raw(item.Description) +
    + +
    +
    +
    + @if (item.RestrictedAccess) + { +
    @((item.HasAccess || this.User.IsInRole("Administrator")) ? "Access Granted" : "Access restricted")
    + } +
    + +
    +
    + @if (item.Providers?.Count > 0) + { + var provider = item.Providers.First(); + @provider.Name catalogue badge + } + else if (!string.IsNullOrEmpty(item.BadgeUrl)) + { + Provider's catalogue badge + } +
    +
    +
    +
    +
    + +
  • + } +
+ + @await Html.PartialAsync("_AllCataloguePagination", Model) + +
+
\ No newline at end of file diff --git a/LearningHub.Nhs.WebUI/Views/Catalogue/AllCatalogueSearch.cshtml b/LearningHub.Nhs.WebUI/Views/Catalogue/AllCatalogueSearch.cshtml new file mode 100644 index 000000000..1d3bee421 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Views/Catalogue/AllCatalogueSearch.cshtml @@ -0,0 +1,132 @@ +@using LearningHub.Nhs.WebUI.Extensions +@using Microsoft.AspNetCore.WebUtilities +@model LearningHub.Nhs.Models.Catalogue.AllCatalogueSearchResponseViewModel; + +@{ + ViewData["Title"] = "All Catalogues Search"; + + var queryParams = QueryHelpers.ParseQuery(Context.Request.QueryString.ToString()); + var hasSearchTerm = queryParams.ContainsKey("term"); + var searchTerm = hasSearchTerm ? queryParams["term"].ToString() : null; + string cardStyle = "card-provider-details--blank"; + var pageSize = this.ViewBag.PageSize; +} + +@section styles { + +} + +
+ @if (hasSearchTerm) + { + var parms = new Dictionary { { "term", searchTerm } }; + + } + else + { + + } +

+ @(hasSearchTerm ? $"Search results for {searchTerm}" : "All catalogues") +

+ +

+ @($"{Model.TotalCount} catalogue results") +

+ + +
    + + @foreach (var item in Model.Catalogues) + { +
  • + +
    + +
    + @if (!string.IsNullOrWhiteSpace(item.CardImageUrl)) + { + @item.Name + } + else if (!string.IsNullOrWhiteSpace(item.BannerUrl)) + { + @item.Name + } + else + { +
    + } +
    + @if (item.Providers?.Count > 0) + { +
    + @ProviderHelper.GetProviderString(item.Providers.FirstOrDefault().Name) +
    + } + else + { +
    + } + +
    + +

    + @item.Name +

    + +
    +
    + @Html.Raw(item.Description) +
    + +
    +
    +
    + @if (item.RestrictedAccess) + { +
    @((item.HasAccess || this.User.IsInRole("Administrator")) ? "Access Granted" : "Access restricted")
    + } +
    + +
    +
    + + @if (item.Providers?.Count > 0) + { + var provider = item.Providers.First(); + @provider.Name catalogue badge + } + else if (!string.IsNullOrEmpty(item.BadgeUrl)) + { + Provider's catalogue badge + } +
    +
    +
    +
    +
    + +
  • + } +
+ @if (Model.TotalCount > pageSize) + { + var currentPage = this.ViewBag.PageIndex; + int totalPage = (Model.TotalCount / pageSize) + (Model.TotalCount % pageSize == 0 ? 0 : 1); + var searchQueryParam = hasSearchTerm ? $"&term={searchTerm}" : string.Empty; + var prevUrl = $"/allcataloguesearch?pageindex={currentPage - 1}{searchQueryParam}"; + var nextUrl = $"/allcataloguesearch?pageindex={currentPage + 1}{searchQueryParam}"; + + @await Html.PartialAsync("_Pagination", new PaginationViewModel(currentPage, totalPage, prevUrl, nextUrl)) + } +
\ No newline at end of file diff --git a/LearningHub.Nhs.WebUI/Views/Catalogue/Catalogues.cshtml b/LearningHub.Nhs.WebUI/Views/Catalogue/Catalogues.cshtml index 6eda29434..024f01b95 100644 --- a/LearningHub.Nhs.WebUI/Views/Catalogue/Catalogues.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Catalogue/Catalogues.cshtml @@ -8,6 +8,7 @@ var queryParams = QueryHelpers.ParseQuery(Context.Request.QueryString.ToString().ToLower()); var hasSearchTerm = queryParams.ContainsKey("term"); var searhTerm = hasSearchTerm ? queryParams["term"].ToString() : null; + string cardStyle = "card-provider-details--blank"; } @section styles{ @@ -55,6 +56,16 @@
} + @if (item.Providers?.Count > 0) + { +
+ @ProviderHelper.GetProviderString(item.Providers.FirstOrDefault().Name) +
+ } + else + { +
+ }
@@ -88,7 +99,12 @@
- @if (!string.IsNullOrEmpty(item.BadgeUrl)) + @if (item.Providers?.Count > 0) + { + var provider = item.Providers.First(); + @provider.Name catalogue badge + } + else if (!string.IsNullOrEmpty(item.BadgeUrl)) { Provider's catalogue badge } diff --git a/LearningHub.Nhs.WebUI/Views/Catalogue/_AllCataloguePagination.cshtml b/LearningHub.Nhs.WebUI/Views/Catalogue/_AllCataloguePagination.cshtml new file mode 100644 index 000000000..216facb96 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Views/Catalogue/_AllCataloguePagination.cshtml @@ -0,0 +1,36 @@ +@model LearningHub.Nhs.Models.Catalogue.AllCatalogueResponseViewModel; + +@if (Model.PrevChar != null || Model.NextChar != null) +{ + +} diff --git a/LearningHub.Nhs.WebUI/Views/Catalogue/_AllCatalogueSearchBar.cshtml b/LearningHub.Nhs.WebUI/Views/Catalogue/_AllCatalogueSearchBar.cshtml new file mode 100644 index 000000000..d86fdaeb4 --- /dev/null +++ b/LearningHub.Nhs.WebUI/Views/Catalogue/_AllCatalogueSearchBar.cshtml @@ -0,0 +1,13 @@ +@model LearningHub.Nhs.Models.Catalogue.AllCatalogueResponseViewModel; + \ No newline at end of file diff --git a/LearningHub.Nhs.WebUI/Views/Home/_CatalogueTray.cshtml b/LearningHub.Nhs.WebUI/Views/Home/_CatalogueTray.cshtml index 9b3bf931d..fd8932610 100644 --- a/LearningHub.Nhs.WebUI/Views/Home/_CatalogueTray.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Home/_CatalogueTray.cshtml @@ -73,7 +73,11 @@
-
+
+ @if (Model.Catalogues.TotalCount > 0 ) + { + View all catalogues + }
diff --git a/LearningHub.Nhs.WebUI/Views/Search/_CatalogueSearchResult.cshtml b/LearningHub.Nhs.WebUI/Views/Search/_CatalogueSearchResult.cshtml index a27a7aba0..56e54eff1 100644 --- a/LearningHub.Nhs.WebUI/Views/Search/_CatalogueSearchResult.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Search/_CatalogueSearchResult.cshtml @@ -44,6 +44,20 @@
  • +
    + @if (!string.IsNullOrWhiteSpace(item.CardImageUrl)) + { + @item.Name + } + else if (!string.IsNullOrWhiteSpace(item.BannerUrl)) + { + @item.Name + } + else + { +
    + } +
    @if (provider != null) {
    @@ -91,7 +105,7 @@ { @provider.Name catalogue badge } - else @if (hasBadge) + else if (hasBadge) { Provider's catalogue badge } diff --git a/LearningHub.Nhs.WebUI/Views/Shared/Components/NavigationItems/Default.cshtml b/LearningHub.Nhs.WebUI/Views/Shared/Components/NavigationItems/Default.cshtml index 719fb24be..4f27477d5 100644 --- a/LearningHub.Nhs.WebUI/Views/Shared/Components/NavigationItems/Default.cshtml +++ b/LearningHub.Nhs.WebUI/Views/Shared/Components/NavigationItems/Default.cshtml @@ -15,6 +15,15 @@ @if (Context.Request.Path.Value != "/Home/Error" && !SystemOffline()) { + @if (Model.ShowBrowseCatalogues) + { +
  • + + Browse catalogues + + +
  • + } @if (Model.ShowMyLearning) {
  • diff --git a/LearningHub.Nhs.WebUI/appsettings.json b/LearningHub.Nhs.WebUI/appsettings.json index f7d2a80cf..af3d9e063 100644 --- a/LearningHub.Nhs.WebUI/appsettings.json +++ b/LearningHub.Nhs.WebUI/appsettings.json @@ -97,7 +97,8 @@ }, "FindwiseSettings": { "ResourceSearchPageSize": 10, - "CatalogueSearchPageSize": 3 + "CatalogueSearchPageSize": 3, + "AllCatalogueSearchPageSize": 10 }, "MediaKindSettings": { "StorageAccountName": "", @@ -111,7 +112,8 @@ "MediaKindStorageConnectionString": "" }, "EnableTempDebugging": "false", - "LimitScormToAdmin": "false" + "LimitScormToAdmin": "false", + "AllCataloguePageSize": 10 }, "LearningHubAuthServiceConfig": { "Authority": "", diff --git a/WebAPI/LearningHub.Nhs.API/Controllers/CatalogueController.cs b/WebAPI/LearningHub.Nhs.API/Controllers/CatalogueController.cs index 4c5d06ea8..b5dbf58a9 100644 --- a/WebAPI/LearningHub.Nhs.API/Controllers/CatalogueController.cs +++ b/WebAPI/LearningHub.Nhs.API/Controllers/CatalogueController.cs @@ -371,5 +371,19 @@ public async Task AccessRequest(int accessRequestId) { return this.Ok(await this.catalogueService.AccessRequestAsync(this.CurrentUserId, accessRequestId)); } + + /// + /// Gets AllCatalogues. + /// + /// The pageSize. + /// The filterChar. + /// IActionResult. + [HttpGet] + [Route("allcatalogues/{pageSize}/{filterChar}")] + public async Task GetAllCataloguesAsync(int pageSize, string filterChar = null) + { + var response = await this.catalogueService.GetAllCataloguesAsync(pageSize, filterChar, this.CurrentUserId); + return this.Ok(response); + } } } diff --git a/WebAPI/LearningHub.Nhs.API/Controllers/SearchController.cs b/WebAPI/LearningHub.Nhs.API/Controllers/SearchController.cs index 424e54b0f..9d046bc7b 100644 --- a/WebAPI/LearningHub.Nhs.API/Controllers/SearchController.cs +++ b/WebAPI/LearningHub.Nhs.API/Controllers/SearchController.cs @@ -211,6 +211,19 @@ public async Task CreateCatalogueSearchTermAction(CatalogueSearch } } + /// + /// Get AllCatalogue search result. + /// + /// The catalogue search request model. + /// The . + [HttpPost] + [Route("GetAllCatalogueSearchResult")] + public async Task GetAllCatalogueSearchResult(AllCatalogueSearchRequestModel catalogueSearchRequestModel) + { + var vm = await this.GetAllCatalogueResults(catalogueSearchRequestModel); + return this.Ok(vm); + } + /// /// Get search result. /// @@ -382,5 +395,77 @@ private async Task GetCatalogueSearchResults(Catalogue return searchViewModel; } + + /// + /// Get All catalogue search results. + /// + /// The catalog search request model. + /// The . + private async Task GetAllCatalogueResults(AllCatalogueSearchRequestModel catalogueSearchRequestModel) + { + var results = await this.searchService.GetAllCatalogueSearchResultsAsync(catalogueSearchRequestModel); + + var documents = results.DocumentList.Documents.ToList(); + var documentIds = documents.Select(x => int.Parse(x.Id)).ToList(); + var catalogues = this.catalogueService.GetCataloguesByNodeId(documentIds); + var bookmarks = this.bookmarkRepository.GetAll().Where(b => documentIds.Contains(b.NodeId ?? -1) && b.UserId == this.CurrentUserId); + var allProviders = await this.providerService.GetAllAsync(); + + foreach (var document in documents) + { + var catalogue = catalogues.SingleOrDefault(x => x.NodeId == int.Parse(document.Id)); + if (catalogue == null) + { + continue; + } + + var roleUserGroups = this.catalogueService.GetRoleUserGroupsForCatalogue(catalogue.NodeId, true); + + // catalogue.No + document.Url = catalogue.Url; + document.BannerUrl = catalogue.BannerUrl; + document.BadgeUrl = catalogue.BadgeUrl; + document.CardImageUrl = catalogue.CardImageUrl; + document.NodePathId = catalogue.NodePathId; + + if (catalogue.RestrictedAccess) + { + document.RestrictedAccess = catalogue.RestrictedAccess; + document.HasAccess = roleUserGroups.Any(x => x.UserGroup.UserUserGroup.Any(y => y.UserId == this.CurrentUserId) + && (x.RoleId == (int)RoleEnum.Editor || x.RoleId == (int)RoleEnum.LocalAdmin || x.RoleId == (int)RoleEnum.Reader)); + } + + var bookmark = bookmarks.FirstOrDefault(x => x.NodeId == int.Parse(document.Id)); + if (bookmark != null) + { + document.BookmarkId = bookmark?.Id; + document.IsBookmarked = !bookmark?.Deleted ?? false; + } + + if (document.ProviderIds?.Count > 0) + { + document.Providers = allProviders.Where(n => document.ProviderIds.Contains(n.Id)).ToList(); + } + } + + var searchViewModel = new SearchAllCatalogueViewModel + { + DocumentModel = documents, + SearchString = catalogueSearchRequestModel.SearchText, + Hits = results.DocumentList.Documents.Count(), + DescriptionMaximumLength = this.settings.Findwise.MaximumDescriptionLength, + ErrorOnAPI = results.ErrorsOnAPICall, + Facets = results.Facets, + }; + + if (results.Stats != null) + { + searchViewModel.TotalHits = results.Stats.TotalHits; + } + + searchViewModel.SearchId = catalogueSearchRequestModel.SearchId > 0 ? catalogueSearchRequestModel.SearchId : results.SearchId; + + return searchViewModel; + } } } \ No newline at end of file diff --git a/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj b/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj index 191c99713..073baa1ff 100644 --- a/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj +++ b/WebAPI/LearningHub.Nhs.API/LearningHub.Nhs.Api.csproj @@ -27,7 +27,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj b/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj index fdacce920..722cefdee 100644 --- a/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj +++ b/WebAPI/LearningHub.Nhs.Api.Shared/LearningHub.Nhs.Api.Shared.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj b/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj index ca2c85a82..d47e3d417 100644 --- a/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj +++ b/WebAPI/LearningHub.Nhs.Api.UnitTests/LearningHub.Nhs.Api.UnitTests.csproj @@ -11,7 +11,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Database/LearningHub.Nhs.Database.sqlproj b/WebAPI/LearningHub.Nhs.Database/LearningHub.Nhs.Database.sqlproj index f513b6ec7..f19a40bbe 100644 --- a/WebAPI/LearningHub.Nhs.Database/LearningHub.Nhs.Database.sqlproj +++ b/WebAPI/LearningHub.Nhs.Database/LearningHub.Nhs.Database.sqlproj @@ -522,6 +522,8 @@ + + @@ -592,4 +594,4 @@ - \ No newline at end of file + diff --git a/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/GetCatalogues.sql b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/GetCatalogues.sql new file mode 100644 index 000000000..64eb0d38c --- /dev/null +++ b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/GetCatalogues.sql @@ -0,0 +1,39 @@ +CREATE PROCEDURE [hierarchy].[GetCatalogues] ( + @userId INT + ,@filterChar nvarchar(10) + ,@OffsetRows int + ,@fetchRows int + ) +AS +BEGIN + + SELECT + nv.NodeId + ,cnv.Id AS NodeVersionId + ,cnv.Name + ,cnv.Description + ,cnv.BannerUrl + ,cnv.BadgeUrl + ,cnv.CardImageUrl + ,cnv.Url + ,cnv.RestrictedAccess + ,CAST(CASE WHEN cnv.RestrictedAccess = 1 AND auth.CatalogueNodeId IS NULL THEN 0 ELSE 1 END AS bit) AS HasAccess + ,ub.Id AS BookMarkId + ,CAST(ISNULL(ub.[Deleted], 1) ^ 1 AS BIT) AS IsBookmarked + FROM [hierarchy].[Node] n + JOIN [hierarchy].[NodeVersion] nv ON nv.NodeId = n.Id + JOIN [hierarchy].[CatalogueNodeVersion] cnv ON cnv.NodeVersionId = nv.Id + LEFT JOIN hub.UserBookmark ub ON ub.UserId = @userId AND ub.NodeId = nv.NodeId + LEFT JOIN ( SELECT DISTINCT CatalogueNodeId + FROM [hub].[RoleUserGroupView] rug JOIN hub.UserUserGroup uug ON rug.UserGroupId = uug.UserGroupId + WHERE rug.ScopeTypeId = 1 and rug.RoleId in (1,2,3) and uug.Deleted = 0 and uug.UserId = @userId) auth ON n.Id = auth.CatalogueNodeId + WHERE n.Id <> 1 AND n.Hidden = 0 AND n.Deleted = 0 AND cnv.Deleted = 0 AND nv.VersionStatusId = 2 + and cnv.Name like @filterChar+'%' + ORDER BY cnv.Name + OFFSET @OffsetRows ROWS + FETCH NEXT @FetchRows ROWS ONLY + + + + +END diff --git a/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/GetCataloguesCount.sql b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/GetCataloguesCount.sql new file mode 100644 index 000000000..eb22506d0 --- /dev/null +++ b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Hierarchy/GetCataloguesCount.sql @@ -0,0 +1,61 @@ +CREATE PROCEDURE [hierarchy].[GetCataloguesCount] ( + @userId INT + ) +AS +BEGIN + + WITH Catalogues AS( + SELECT cnv.Name as Name + FROM [hierarchy].[Node] n + JOIN [hierarchy].[NodeVersion] nv ON nv.NodeId = n.Id + JOIN [hierarchy].[CatalogueNodeVersion] cnv ON cnv.NodeVersionId = nv.Id + LEFT JOIN hub.UserBookmark ub ON ub.UserId = @userId AND ub.NodeId = nv.NodeId + LEFT JOIN ( SELECT DISTINCT CatalogueNodeId + FROM [hub].[RoleUserGroupView] rug JOIN hub.UserUserGroup uug ON rug.UserGroupId = uug.UserGroupId + WHERE rug.ScopeTypeId = 1 and rug.RoleId in (1,2,3) and uug.Deleted = 0 and uug.UserId = @userId) auth ON n.Id = auth.CatalogueNodeId + WHERE n.Id <> 1 AND n.Hidden = 0 AND n.Deleted = 0 AND cnv.Deleted = 0 AND nv.VersionStatusId = 2 ), + + +Alphabet AS ( + SELECT 'A' AS Letter UNION ALL + SELECT 'B' UNION ALL + SELECT 'C' UNION ALL + SELECT 'D' UNION ALL + SELECT 'E' UNION ALL + SELECT 'F' UNION ALL + SELECT 'G' UNION ALL + SELECT 'H' UNION ALL + SELECT 'I' UNION ALL + SELECT 'J' UNION ALL + SELECT 'K' UNION ALL + SELECT 'L' UNION ALL + SELECT 'M' UNION ALL + SELECT 'N' UNION ALL + SELECT 'O' UNION ALL + SELECT 'P' UNION ALL + SELECT 'Q' UNION ALL + SELECT 'R' UNION ALL + SELECT 'S' UNION ALL + SELECT 'T' UNION ALL + SELECT 'U' UNION ALL + SELECT 'V' UNION ALL + SELECT 'W' UNION ALL + SELECT 'X' UNION ALL + SELECT 'Y' UNION ALL + SELECT 'Z' UNION ALL + SELECT '0-9' +) +SELECT + Alphabet.Letter AS Alphabet, + COALESCE(COUNT(cnv.Name), 0) AS Count + FROM Alphabet + LEFT JOIN Catalogues cnv + ON + ((LEFT(cnv.Name, 1) = Alphabet.Letter AND LEFT(cnv.Name, 1) BETWEEN 'A' AND 'Z') + OR (Alphabet.Letter = '0-9' AND LEFT(cnv.Name, 1) BETWEEN '0' AND '9') + ) + + GROUP BY Alphabet.Letter + ORDER BY (CASE WHEN Alphabet.Letter like '[a-z]%' THEN 0 ELSE 1 END), Alphabet.Letter; + +END diff --git a/WebAPI/LearningHub.Nhs.Repository.Interface/Hierarchy/ICatalogueNodeVersionRepository.cs b/WebAPI/LearningHub.Nhs.Repository.Interface/Hierarchy/ICatalogueNodeVersionRepository.cs index eb3eed968..1b68a3aef 100644 --- a/WebAPI/LearningHub.Nhs.Repository.Interface/Hierarchy/ICatalogueNodeVersionRepository.cs +++ b/WebAPI/LearningHub.Nhs.Repository.Interface/Hierarchy/ICatalogueNodeVersionRepository.cs @@ -121,5 +121,21 @@ public interface ICatalogueNodeVersionRepository : IGenericRepositoryThe catalogue name. /// The catalogue's node id. Task GetNodeIdByCatalogueName(string catalogueName); + + /// + /// Gets the catalogues count in alphabet list. + /// + /// The userId. + /// The catalogues alphabet count list. + List GetAllCataloguesAlphaCount(int userId); + + /// + /// Gets catalogues based on filter character. + /// + /// The pageSize. + /// The filterChar. + /// The userId. + /// The catalogues. + Task> GetAllCataloguesAsync(int pageSize, string filterChar, int userId); } } diff --git a/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj b/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj index 2fa729986..35d70c810 100644 --- a/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj +++ b/WebAPI/LearningHub.Nhs.Repository.Interface/LearningHub.Nhs.Repository.Interface.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Repository/Hierarchy/CatalogueNodeVersionRepository.cs b/WebAPI/LearningHub.Nhs.Repository/Hierarchy/CatalogueNodeVersionRepository.cs index bc8feee2d..e65bd58ef 100644 --- a/WebAPI/LearningHub.Nhs.Repository/Hierarchy/CatalogueNodeVersionRepository.cs +++ b/WebAPI/LearningHub.Nhs.Repository/Hierarchy/CatalogueNodeVersionRepository.cs @@ -355,5 +355,38 @@ join nv in this.DbContext.NodeVersion.AsNoTracking() on cnv.NodeVersionId equals where cnv.Name == catalogueName && cnv.Deleted == false select nv.NodeId).FirstOrDefaultAsync(); } + + /// + /// Gets catalogues count based on alphabets. + /// + /// The userId. + /// resources. + public List GetAllCataloguesAlphaCount(int userId) + { + var param0 = new SqlParameter("@userId", SqlDbType.Int) { Value = userId }; + + var result = this.DbContext.AllCatalogueAlphabetModel.FromSqlRaw("[hierarchy].[GetCataloguesCount] @userid", param0) + .AsNoTracking().ToList(); + return result; + } + + /// + /// Gets catalogues based on filter character. + /// + /// The pageSize. + /// The filterChar. + /// The userId. + /// resources. + public async Task> GetAllCataloguesAsync(int pageSize, string filterChar, int userId) + { + var param0 = new SqlParameter("@userId", SqlDbType.Int) { Value = userId }; + var param1 = new SqlParameter("@filterChar", SqlDbType.NVarChar, 10) { Value = filterChar.Trim() }; + var param2 = new SqlParameter("@OffsetRows", SqlDbType.Int) { Value = 0 }; + var param3 = new SqlParameter("@fetchRows", SqlDbType.Int) { Value = pageSize }; + + var result = await this.DbContext.AllCatalogueViewModel.FromSqlRaw("[hierarchy].[GetCatalogues] @userId, @filterChar, @OffsetRows, @fetchRows", param0, param1, param2, param3) + .AsNoTracking().ToListAsync(); + return result; + } } } diff --git a/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj b/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj index bca29eeb0..5e7e65365 100644 --- a/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj +++ b/WebAPI/LearningHub.Nhs.Repository/LearningHub.Nhs.Repository.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Repository/LearningHubDbContext.cs b/WebAPI/LearningHub.Nhs.Repository/LearningHubDbContext.cs index ef4775cd8..1d94dc9b6 100644 --- a/WebAPI/LearningHub.Nhs.Repository/LearningHubDbContext.cs +++ b/WebAPI/LearningHub.Nhs.Repository/LearningHubDbContext.cs @@ -770,6 +770,16 @@ public LearningHubDbContextOptions Options /// public virtual DbSet MyLearningActivity { get; set; } + /// + /// Gets or sets the AllCatalogueAlphabet. + /// + public virtual DbSet AllCatalogueAlphabetModel { get; set; } + + /// + /// Gets or sets the AllCatalogueAlphabet. + /// + public virtual DbSet AllCatalogueViewModel { get; set; } + /// /// The on model creating. /// diff --git a/WebAPI/LearningHub.Nhs.Services.Interface/ICatalogueService.cs b/WebAPI/LearningHub.Nhs.Services.Interface/ICatalogueService.cs index 283ea7ae9..d3d8c6122 100644 --- a/WebAPI/LearningHub.Nhs.Services.Interface/ICatalogueService.cs +++ b/WebAPI/LearningHub.Nhs.Services.Interface/ICatalogueService.cs @@ -238,5 +238,14 @@ public interface ICatalogueService /// The catalogueAccessRequestId. /// The catalogue access request. Task AccessRequestAsync(int userId, int catalogueAccessRequestId); + + /// + /// GetAllCataloguesAsync. + /// + /// The pageSize. + /// filterChar. + /// userId. + /// The allcatalogue result based on letters. + Task GetAllCataloguesAsync(int pageSize, string filterChar, int userId); } } diff --git a/WebAPI/LearningHub.Nhs.Services.Interface/ISearchService.cs b/WebAPI/LearningHub.Nhs.Services.Interface/ISearchService.cs index ef44e5076..2f1e0a63c 100644 --- a/WebAPI/LearningHub.Nhs.Services.Interface/ISearchService.cs +++ b/WebAPI/LearningHub.Nhs.Services.Interface/ISearchService.cs @@ -168,5 +168,12 @@ public interface ISearchService /// The . /// Task SendCatalogueSearchEventAsync(SearchActionCatalogueModel searchActionCatalogueModel); + + /// + /// Gets AllCatalogue search results async. + /// + /// The allcatalog search request model. + /// The . + Task GetAllCatalogueSearchResultsAsync(AllCatalogueSearchRequestModel catalogSearchRequestModel); } } diff --git a/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj b/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj index 13e00879d..5d2f278d4 100644 --- a/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj +++ b/WebAPI/LearningHub.Nhs.Services.Interface/LearningHub.Nhs.Services.Interface.csproj @@ -16,7 +16,7 @@ - + all diff --git a/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj b/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj index 87beb0d40..9869ac4be 100644 --- a/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj +++ b/WebAPI/LearningHub.Nhs.Services.UnitTests/LearningHub.Nhs.Services.UnitTests.csproj @@ -13,7 +13,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Services/CatalogueService.cs b/WebAPI/LearningHub.Nhs.Services/CatalogueService.cs index a074e2b99..8510c49e1 100644 --- a/WebAPI/LearningHub.Nhs.Services/CatalogueService.cs +++ b/WebAPI/LearningHub.Nhs.Services/CatalogueService.cs @@ -401,8 +401,7 @@ public List GetRoleUserGroupsForCatalogue(int catalogueNodeId, bo query = query.Include(x => x.UserGroup).ThenInclude(x => x.UserUserGroup); } - return query.Where(x => x.Scope.CatalogueNodeId == catalogueNodeId) - .ToList(); + return query.Where(x => x.Scope.CatalogueNodeId == catalogueNodeId).ToList(); } /// @@ -954,6 +953,68 @@ public async Task AccessRequestAsync(int userId return vm; } + /// + /// GetAllCataloguesAsync. + /// + /// The pageSize. + /// The filterChar. + /// The userId. + /// A representing the result of the asynchronous operation. + public async Task GetAllCataloguesAsync(int pageSize, string filterChar, int userId) + { + var catalogueAlphaCount = this.catalogueNodeVersionRepository.GetAllCataloguesAlphaCount(userId); + var filterCharMod = filterChar.Trim() == "0-9" ? "[0-9]" : filterChar; + var count = catalogueAlphaCount.FirstOrDefault(ca => ca.Alphabet == filterChar.ToUpper()).Count; + string prevChar = null, nextChar = null, curChar = null; + var filterCharIndex = catalogueAlphaCount.FindIndex(ca => ca.Alphabet == filterChar.ToUpper()); + + // check count and assign prev and next letter + if (count != 0) + { + for (int i = 0; i < catalogueAlphaCount.Count; i++) + { + if (i == filterCharIndex && i == 0) + { + prevChar = null; + } + + if (i == filterCharIndex && i == catalogueAlphaCount.Count - 1) + { + nextChar = null; + } + + if (catalogueAlphaCount[i].Count > 0 && i < filterCharIndex) + { + curChar = catalogueAlphaCount[i].Alphabet; + prevChar = curChar; + } + + if (catalogueAlphaCount[i].Count > 0 && i > filterCharIndex) + { + curChar = catalogueAlphaCount[i].Alphabet; + nextChar = curChar; + break; + } + } + } + + var catalogues = await this.catalogueNodeVersionRepository.GetAllCataloguesAsync(pageSize, filterCharMod, userId); + foreach (var catalogue in catalogues) + { + catalogue.Providers = await this.providerService.GetByCatalogueVersionIdAsync(catalogue.NodeVersionId); + } + + var response = new AllCatalogueResponseViewModel + { + CataloguesCount = catalogueAlphaCount, + Catalogues = catalogues, + FilterChar = filterChar.ToUpper(), + PrevChar = prevChar, + NextChar = nextChar, + }; + return response; + } + /// /// The RecordNodeActivity. /// diff --git a/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj b/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj index b479d88df..44fefe844 100644 --- a/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj +++ b/WebAPI/LearningHub.Nhs.Services/LearningHub.Nhs.Services.csproj @@ -13,7 +13,7 @@ - + diff --git a/WebAPI/LearningHub.Nhs.Services/SearchService.cs b/WebAPI/LearningHub.Nhs.Services/SearchService.cs index 321313bd3..a247d9aa1 100644 --- a/WebAPI/LearningHub.Nhs.Services/SearchService.cs +++ b/WebAPI/LearningHub.Nhs.Services/SearchService.cs @@ -541,6 +541,53 @@ public async Task SendCatalogueSearchEventAsync(SearchActionCatalogueModel return await this.SendSearchEventClickAsync(searchClickPayloadModel, false); } + /// + /// Gets AllCatalogue search results from findwise api call. + /// + /// The allcatalog search request model. + /// The . + public async Task GetAllCatalogueSearchResultsAsync(AllCatalogueSearchRequestModel catalogSearchRequestModel) + { + var viewmodel = new SearchAllCatalogueResultModel(); + try + { + var offset = catalogSearchRequestModel.PageIndex * catalogSearchRequestModel.PageSize; + var client = await this.FindWiseHttpClient.GetClient(this.settings.Findwise.SearchUrl); + var request = string.Format( + this.settings.Findwise.UrlSearchComponent + "?offset={1}&hits={2}&q={3}&token={4}", + this.settings.Findwise.CollectionIds.Catalogue, + offset, + catalogSearchRequestModel.PageSize, + this.EncodeSearchText(catalogSearchRequestModel.SearchText), + this.settings.Findwise.Token); + + var response = await client.GetAsync(request).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + viewmodel = JsonConvert.DeserializeObject(result); + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + this.Logger.LogError($"Get AllCatalogue Search Result failed in FindWise, HTTP Status Code:{response.StatusCode}"); + throw new Exception("AccessDenied to FindWise Server"); + } + else + { + var error = response.Content.ReadAsStringAsync().Result.ToString(); + this.Logger.LogError($"Get AllCatalogue Search Result failed in FindWise, HTTP Status Code:{response.StatusCode}, Error Message:{error}"); + throw new Exception("Error with FindWise Server"); + } + + return viewmodel; + } + catch (Exception) + { + throw; + } + } + /// /// Send search click payload. /// diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj index 5a7f79921..de8df1a58 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.ConsoleApp/LearningHub.Nhs.Migration.ConsoleApp.csproj @@ -24,7 +24,7 @@ - + all diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj index 2306024b3..52929fbd8 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Interface/LearningHub.Nhs.Migration.Interface.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj index c45bd555b..a3951c927 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Models/LearningHub.Nhs.Migration.Models.csproj @@ -10,7 +10,7 @@ - + all diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj index 2501535f9..7efd53fab 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.Staging.Repository/LearningHub.Nhs.Migration.Staging.Repository.csproj @@ -9,7 +9,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj index ac9a749f6..ad73a25cc 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration.UnitTests/LearningHub.Nhs.Migration.UnitTests.csproj @@ -10,7 +10,7 @@ - + diff --git a/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj b/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj index b5fc07022..861270f13 100644 --- a/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj +++ b/WebAPI/MigrationTool/LearningHub.Nhs.Migration/LearningHub.Nhs.Migration.csproj @@ -12,7 +12,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive