From 2468b06217ade808366e0410a5f110de78e2a921 Mon Sep 17 00:00:00 2001 From: Swapnamol Abraham Date: Fri, 3 May 2024 12:43:04 +0100 Subject: [PATCH 1/9] TD-4115 - Number of accessed showing incorrect in the certificate details --- WebAPI/LearningHub.Nhs.Services/MyLearningService.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/WebAPI/LearningHub.Nhs.Services/MyLearningService.cs b/WebAPI/LearningHub.Nhs.Services/MyLearningService.cs index 9abbf2316..13e28cb9d 100644 --- a/WebAPI/LearningHub.Nhs.Services/MyLearningService.cs +++ b/WebAPI/LearningHub.Nhs.Services/MyLearningService.cs @@ -169,8 +169,13 @@ public async Task> GetResourceCertif activityEntities.RemoveAll(x => x.Resource.ResourceTypeEnum == ResourceTypeEnum.Scorm && (x.ActivityStatusId == (int)ActivityStatusEnum.Downloaded || x.ActivityStatusId == (int)ActivityStatusEnum.Incomplete || x.ActivityStatusId == (int)ActivityStatusEnum.InProgress)); if (activityEntities.Any() && activityEntities.FirstOrDefault()?.Resource.ResourceTypeEnum == ResourceTypeEnum.Assessment) { + totalNumberOfAccess = activityQuery.SelectMany(x => x.AssessmentResourceActivity).OrderByDescending(a => a.CreateDate).ToList().Count(); activityEntities = activityEntities.Where(x => x.AssessmentResourceActivity.FirstOrDefault() != null && x.AssessmentResourceActivity.FirstOrDefault().Score.HasValue && ((int)Math.Round(x.AssessmentResourceActivity.FirstOrDefault().Score.Value, MidpointRounding.AwayFromZero) >= x.ResourceVersion.AssessmentResourceVersion.PassMark)).ToList(); } + else if (activityEntities.Any() && (activityEntities.FirstOrDefault()?.Resource.ResourceTypeEnum == ResourceTypeEnum.Video || activityEntities.FirstOrDefault()?.Resource.ResourceTypeEnum == ResourceTypeEnum.Audio)) + { + totalNumberOfAccess = activityQuery.SelectMany(x => x.MediaResourceActivity).OrderByDescending(a => a.CreateDate).ToList().Count(); + } if (activityEntities.Any()) { @@ -272,7 +277,7 @@ public async Task> PopulateMyLearningDetai if (latestActivityCheck.Any() && expectedActivity != null && resourceActivity.ResourceVersion.CertificateEnabled == true) { - viewModel.CertificateEnabled = true; + viewModel.CertificateEnabled = true; } else { @@ -490,7 +495,7 @@ private IQueryable ApplyFilters(IQueryable q if (requestModel.CertificateEnabled) { - query = query.Where(x => x.ResourceVersion.CertificateEnabled.Equals(true)); + query = query.Where(x => x.ResourceVersion.CertificateEnabled.Equals(true)); } return query; From ef7ebe97b040483f38a62fb580b43a7b54a07c21 Mon Sep 17 00:00:00 2001 From: Oluwatobi Awe Date: Tue, 7 May 2024 09:25:13 +0100 Subject: [PATCH 2/9] TD-3023 fix for deleted blocks which are valid in an active published resource version --- .../Controllers/Api/ContributeController.cs | 39 ++++++--- .../ResourceService.cs | 83 +++++++++++++------ 2 files changed, 86 insertions(+), 36 deletions(-) diff --git a/LearningHub.Nhs.WebUI/Controllers/Api/ContributeController.cs b/LearningHub.Nhs.WebUI/Controllers/Api/ContributeController.cs index 63c251451..887e4bd04 100644 --- a/LearningHub.Nhs.WebUI/Controllers/Api/ContributeController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/Api/ContributeController.cs @@ -496,7 +496,7 @@ public async Task SaveCaseDetailAsync([FromBody] CaseViewModel req int resourceVersionId = await this.contributeService.SaveCaseDetailAsync(request); if (existingResourceState.CaseDetails?.BlockCollection != null) { - this.RemoveBlockCollectionFiles(existingResourceState.CaseDetails.BlockCollection, request.BlockCollection); + await this.RemoveBlockCollectionFiles(request.ResourceVersionId, existingResourceState.CaseDetails.BlockCollection, request.BlockCollection); } return this.Ok(resourceVersionId); @@ -515,7 +515,7 @@ public async Task SaveAssessmentDetailAsync([FromBody] AssessmentV int resourceVersionId = await this.contributeService.SaveAssessmentDetailAsync(request); if (existingResourceState != null && existingResourceState.AssessmentDetails != null) { - this.RemoveBlockCollectionFiles(existingResourceState.AssessmentDetails, request); + await this.RemoveBlockCollectionFiles(request.ResourceVersionId, existingResourceState.AssessmentDetails, request); } return this.Ok(resourceVersionId); @@ -638,23 +638,24 @@ private async Task UserCanEditCatalogue(int catalogueId) return await this.catalogueService.CanCurrentUserEditCatalogue(catalogueId); } - private void RemoveBlockCollectionFiles(AssessmentViewModel existingModel, AssessmentViewModel newModel) + private async Task RemoveBlockCollectionFiles(int resourceVersionId, AssessmentViewModel existingModel, AssessmentViewModel newModel) { if (existingModel is { EndGuidance: { } } && existingModel.EndGuidance.Blocks != null) { - this.RemoveBlockCollectionFiles(existingModel.EndGuidance, newModel.EndGuidance); + await this.RemoveBlockCollectionFiles(resourceVersionId, existingModel.EndGuidance, newModel.EndGuidance); } if (existingModel is { AssessmentContent: { } } && existingModel.AssessmentContent.Blocks != null) { - this.RemoveBlockCollectionFiles(existingModel.AssessmentContent, newModel.AssessmentContent); + await this.RemoveBlockCollectionFiles(resourceVersionId, existingModel.AssessmentContent, newModel.AssessmentContent); } } - private void RemoveBlockCollectionFiles(BlockCollectionViewModel existingResource, BlockCollectionViewModel newResource) + private async Task RemoveBlockCollectionFiles(int resourceVersionId, BlockCollectionViewModel existingResource, BlockCollectionViewModel newResource) { try { + var obsoleteFiles = await this.resourceService.GetObsoleteResourceFile(resourceVersionId, true); var filePaths = new List(); if (existingResource != null) { @@ -706,8 +707,8 @@ private void RemoveBlockCollectionFiles(BlockCollectionViewModel existingResourc { 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); - 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); + if (entry == null) { filePaths.Add(oldblock?.MediaBlock?.Image?.File?.FilePath); } @@ -771,7 +772,18 @@ private void RemoveBlockCollectionFiles(BlockCollectionViewModel existingResourc if (filePaths != null && filePaths.Any()) { - _ = Task.Run(async () => { await this.fileService.PurgeResourceFile(null, filePaths); }); + var deleteList = new List(); + foreach (var e in filePaths) + { + if (!obsoleteFiles.Contains(e)) + { + continue; + } + + deleteList.Add(e); + } + + _ = Task.Run(async () => { await this.fileService.PurgeResourceFile(null, deleteList); }); } } catch (Exception ex) @@ -838,12 +850,15 @@ private List CheckQuestionBlock(BlockCollectionViewModel model) } else if (questionBlock.BlockType == BlockType.WholeSlideImage && questionBlock.WholeSlideImageBlock != null) { - var existingWholeSlideImages = questionBlock.WholeSlideImageBlock.WholeSlideImageBlockItems.ToList(); - if (existingWholeSlideImages.Any()) + var existingWholeSlideImages = questionBlock.WholeSlideImageBlock?.WholeSlideImageBlockItems; + if (existingWholeSlideImages != null && existingWholeSlideImages.Any()) { foreach (var wsi in existingWholeSlideImages) { - filePath.Add(wsi.WholeSlideImage?.File?.FilePath); + if (wsi.WholeSlideImage != null && wsi.WholeSlideImage.File != null) + { + filePath.Add(wsi.WholeSlideImage.File.FilePath); + } } } } diff --git a/WebAPI/LearningHub.Nhs.Services/ResourceService.cs b/WebAPI/LearningHub.Nhs.Services/ResourceService.cs index 7c7974798..c0b7e5d1f 100644 --- a/WebAPI/LearningHub.Nhs.Services/ResourceService.cs +++ b/WebAPI/LearningHub.Nhs.Services/ResourceService.cs @@ -1477,7 +1477,7 @@ public async Task> GetObsoleteResourceFile(int resourceVersionId, b { if (resource.AssessmentDetails is { EndGuidance: { } } && resource.AssessmentDetails.EndGuidance.Blocks != null) { - var assessmentFiles = this.CheckBlockFile(resource.AssessmentDetails.EndGuidance); + var assessmentFiles = this.CheckBlockFile(extendedResourceVersion.AssessmentDetails.EndGuidance, resource.AssessmentDetails.EndGuidance); if (assessmentFiles.Any()) { retVal.AddRange(assessmentFiles); @@ -1486,7 +1486,7 @@ public async Task> GetObsoleteResourceFile(int resourceVersionId, b if (resource.AssessmentDetails is { AssessmentContent: { } } && resource.AssessmentDetails.AssessmentContent.Blocks != null) { - var assessmentFiles = this.CheckBlockFile(resource.AssessmentDetails.AssessmentContent); + var assessmentFiles = this.CheckBlockFile(extendedResourceVersion.AssessmentDetails.AssessmentContent, resource.AssessmentDetails.AssessmentContent); if (assessmentFiles.Any()) { retVal.AddRange(assessmentFiles); @@ -1498,7 +1498,7 @@ public async Task> GetObsoleteResourceFile(int resourceVersionId, b { if (deletedResource) { - var caseFiles = this.CheckBlockFile(resource.CaseDetails.BlockCollection); + var caseFiles = this.CheckBlockFile(extendedResourceVersion.CaseDetails.BlockCollection, resource.CaseDetails.BlockCollection); if (caseFiles.Any()) { retVal.AddRange(caseFiles); @@ -1557,7 +1557,7 @@ public async Task> GetObsoleteResourceFile(int resourceVersionId, b { if (resource.AssessmentDetails is { EndGuidance: { } } && resource.AssessmentDetails.EndGuidance.Blocks != null) { - var assessmentFiles = this.CheckBlockFile(resource.AssessmentDetails.EndGuidance); + var assessmentFiles = this.CheckBlockFile(null, resource.AssessmentDetails.EndGuidance); if (assessmentFiles.Any()) { retVal.AddRange(assessmentFiles); @@ -1566,7 +1566,7 @@ public async Task> GetObsoleteResourceFile(int resourceVersionId, b if (resource.AssessmentDetails is { AssessmentContent: { } } && resource.AssessmentDetails.AssessmentContent.Blocks != null) { - var assessmentFiles = this.CheckBlockFile(resource.AssessmentDetails.AssessmentContent); + var assessmentFiles = this.CheckBlockFile(null, resource.AssessmentDetails.AssessmentContent); if (assessmentFiles.Any()) { retVal.AddRange(assessmentFiles); @@ -1576,7 +1576,7 @@ public async Task> GetObsoleteResourceFile(int resourceVersionId, b } else if (resource.ResourceTypeEnum == ResourceTypeEnum.Case) { - var caseFiles = this.CheckBlockFile(resource.CaseDetails.BlockCollection); + var caseFiles = this.CheckBlockFile(null, resource.CaseDetails.BlockCollection); if (caseFiles.Any()) { retVal.AddRange(caseFiles); @@ -4884,7 +4884,7 @@ private async Task CreateNewResource(ResourceTypeEnum resourceType, string return resourceVersionId; } - private List CheckBlockFile(BlockCollectionViewModel model) + private List CheckBlockFile(BlockCollectionViewModel? publishedBlock, BlockCollectionViewModel model) { var retVal = new List(); var caseBlockCollection = model; @@ -4898,7 +4898,11 @@ private List CheckBlockFile(BlockCollectionViewModel model) { foreach (var oldblock in existingAttachements) { - retVal.Add(oldblock.MediaBlock.Attachment?.File?.FilePath); + var publishedEntry = (publishedBlock != null && publishedBlock.Blocks.Any()) ? publishedBlock.Blocks.FirstOrDefault(x => x.BlockType == BlockType.Media && x.MediaBlock != null && x.MediaBlock.MediaType == MediaType.Attachment && x.MediaBlock.Attachment != null && x.MediaBlock.Attachment.File?.FileId == oldblock.MediaBlock.Attachment?.File?.FileId) : null; + if (publishedEntry == null) + { + retVal.Add(oldblock.MediaBlock.Attachment?.File?.FilePath); + } } } @@ -4907,19 +4911,23 @@ private List CheckBlockFile(BlockCollectionViewModel model) { foreach (var oldblock in existingVideos) { - if (!string.IsNullOrWhiteSpace(oldblock.MediaBlock.Video.File.FilePath)) + var publishedEntry = (publishedBlock != null && publishedBlock.Blocks.Any()) ? publishedBlock.Blocks.FirstOrDefault(x => x.BlockType == BlockType.Media && x.MediaBlock != null && x.MediaBlock.MediaType == MediaType.Video && x.MediaBlock.Video != null && x.MediaBlock.Video.VideoFile?.File?.FileId == oldblock.MediaBlock?.Video?.VideoFile?.File?.FileId) : null; + if (publishedEntry == null) { - retVal.Add(oldblock.MediaBlock.Video.File.FilePath); - } + if (!string.IsNullOrWhiteSpace(oldblock.MediaBlock.Video.File.FilePath)) + { + retVal.Add(oldblock.MediaBlock.Video.File.FilePath); + } - if (!string.IsNullOrWhiteSpace(oldblock.MediaBlock.Video?.File?.VideoFile?.File?.FilePath)) - { - retVal.Add(oldblock.MediaBlock.Video.File.VideoFile.File.FilePath); - } + if (!string.IsNullOrWhiteSpace(oldblock.MediaBlock.Video?.File?.VideoFile?.File?.FilePath)) + { + retVal.Add(oldblock.MediaBlock.Video.File.VideoFile.File.FilePath); + } - if (oldblock.MediaBlock?.Video?.File?.VideoFile?.TranscriptFile?.File?.FilePath != null) - { - retVal.Add(oldblock.MediaBlock.Video.File.VideoFile.TranscriptFile.File.FilePath); + if (oldblock.MediaBlock?.Video?.File?.VideoFile?.TranscriptFile?.File?.FilePath != null) + { + retVal.Add(oldblock.MediaBlock.Video.File.VideoFile.TranscriptFile.File.FilePath); + } } } } @@ -4929,7 +4937,11 @@ private List CheckBlockFile(BlockCollectionViewModel model) { foreach (var oldblock in existingImages) { - retVal.Add(oldblock.MediaBlock?.Image?.File?.FilePath); + var publishedEntry = (publishedBlock != null && publishedBlock.Blocks.Any()) ? publishedBlock.Blocks.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) : null; + if (publishedEntry == null) + { + retVal.Add(oldblock.MediaBlock?.Image?.File?.FilePath); + } } } @@ -4940,7 +4952,11 @@ private List CheckBlockFile(BlockCollectionViewModel model) { foreach (var oldblock in imageBlock.ImageCarouselBlock.ImageBlockCollection.Blocks) { - retVal.Add(oldblock.MediaBlock?.Image?.File?.FilePath); + var publishedEntry = (publishedBlock != null && publishedBlock.Blocks.Any()) ? publishedBlock.Blocks.FirstOrDefault(x => x.BlockType == BlockType.ImageCarousel && x.ImageCarouselBlock != null && x.ImageCarouselBlock.ImageBlockCollection != null && x.ImageCarouselBlock.ImageBlockCollection.Blocks != null && x.ImageCarouselBlock.ImageBlockCollection.Blocks.Where(x => x.MediaBlock?.Image?.File?.FileId == oldblock.MediaBlock?.Image?.File?.FileId).Any()) : null; + if (publishedEntry == null) + { + retVal.Add(oldblock.MediaBlock?.Image?.File?.FilePath); + } } } } @@ -4952,17 +4968,33 @@ private List CheckBlockFile(BlockCollectionViewModel model) { foreach (var oldblock in wsi?.WholeSlideImageBlock?.WholeSlideImageBlockItems) { - retVal.Add(oldblock.WholeSlideImage?.File?.FilePath); + var publishedEntry = (publishedBlock != null && publishedBlock.Blocks.Any()) ? publishedBlock.Blocks.FirstOrDefault(x => x.WholeSlideImageBlock != null && x.WholeSlideImageBlock.WholeSlideImageBlockItems.Where(x => x.WholeSlideImage?.File?.FileId == oldblock.WholeSlideImage?.File?.FileId).Any()) : null; + if (publishedEntry == null) + { + retVal.Add(oldblock.WholeSlideImage?.File?.FilePath); + } } } } } var questionFiles = this.CheckQuestionBlock(caseBlockCollection); - if (questionFiles.Any()) + var publishedQuestionFiles = (publishedBlock != null && publishedBlock.Blocks.Any()) ? this.CheckQuestionBlock(publishedBlock) : new List(); + if (questionFiles.Any() && !publishedQuestionFiles.Any()) { retVal.AddRange(questionFiles); } + else if (questionFiles.Any() && publishedQuestionFiles.Any()) + { + foreach (var file in questionFiles) + { + var publishedEntry = publishedQuestionFiles.FirstOrDefault(x => x.Equals(file)); + if (publishedEntry == null) + { + retVal.Add(file); + } + } + } } return retVal; @@ -5027,12 +5059,15 @@ private List CheckQuestionBlock(BlockCollectionViewModel model) } else if (questionBlock.BlockType == BlockType.WholeSlideImage && questionBlock.WholeSlideImageBlock != null) { - var existingWholeSlideImages = questionBlock.WholeSlideImageBlock.WholeSlideImageBlockItems.ToList(); + var existingWholeSlideImages = questionBlock.WholeSlideImageBlock.WholeSlideImageBlockItems; if (existingWholeSlideImages.Any()) { foreach (var wsi in existingWholeSlideImages) { - filePath.Add(wsi.WholeSlideImage?.File?.FilePath); + if (wsi.WholeSlideImage != null && wsi.WholeSlideImage.File != null) + { + filePath.Add(wsi.WholeSlideImage.File.FilePath); + } } } } From 26abd616793c6bc9dd3fee3c41df9e5915a51297 Mon Sep 17 00:00:00 2001 From: Oluwatobi Awe Date: Tue, 7 May 2024 10:41:02 +0100 Subject: [PATCH 3/9] TD-3023 check for obsolete files before saving new block collection. --- .../Controllers/Api/ContributeController.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/LearningHub.Nhs.WebUI/Controllers/Api/ContributeController.cs b/LearningHub.Nhs.WebUI/Controllers/Api/ContributeController.cs index 887e4bd04..5eeca7be7 100644 --- a/LearningHub.Nhs.WebUI/Controllers/Api/ContributeController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/Api/ContributeController.cs @@ -493,12 +493,12 @@ public async Task SaveWeblinkDetailAsync([FromBody] WebLinkViewMod public async Task SaveCaseDetailAsync([FromBody] CaseViewModel request) { var existingResourceState = await this.resourceService.GetResourceVersionExtendedAsync(request.ResourceVersionId); - int resourceVersionId = await this.contributeService.SaveCaseDetailAsync(request); if (existingResourceState.CaseDetails?.BlockCollection != null) { - await this.RemoveBlockCollectionFiles(request.ResourceVersionId, existingResourceState.CaseDetails.BlockCollection, request.BlockCollection); + await this.RemoveBlockCollectionFiles(request.ResourceVersionId, existingResourceState.CaseDetails.BlockCollection, request.BlockCollection); } + int resourceVersionId = await this.contributeService.SaveCaseDetailAsync(request); return this.Ok(resourceVersionId); } @@ -512,12 +512,12 @@ public async Task SaveCaseDetailAsync([FromBody] CaseViewModel req public async Task SaveAssessmentDetailAsync([FromBody] AssessmentViewModel request) { var existingResourceState = await this.resourceService.GetResourceVersionExtendedAsync(request.ResourceVersionId); - int resourceVersionId = await this.contributeService.SaveAssessmentDetailAsync(request); if (existingResourceState != null && existingResourceState.AssessmentDetails != null) { - await this.RemoveBlockCollectionFiles(request.ResourceVersionId, existingResourceState.AssessmentDetails, request); + await this.RemoveBlockCollectionFiles(request.ResourceVersionId, existingResourceState.AssessmentDetails, request); } + int resourceVersionId = await this.contributeService.SaveAssessmentDetailAsync(request); return this.Ok(resourceVersionId); } From db74a91df2dddbd04c68c37f706e2e8eb8c17f12 Mon Sep 17 00:00:00 2001 From: Swapnamol Abraham Date: Tue, 7 May 2024 11:37:15 +0100 Subject: [PATCH 4/9] TD-4115: Fixes for the my learning tray in progress activities --- .../Stored Procedures/Resources/GetDashboardResources.sql | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Resources/GetDashboardResources.sql b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Resources/GetDashboardResources.sql index c794f8d89..4fc44526b 100644 --- a/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Resources/GetDashboardResources.sql +++ b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Resources/GetDashboardResources.sql @@ -226,7 +226,7 @@ BEGIN INSERT INTO @MyActivity SELECT TOP (@MaxRows) ra.ResourceId, MAX(ra.Id) ResourceActivityId FROM - (SELECT a.* FROM activity.ResourceActivity a INNER JOIN (SELECT ResourceId, MAX(Id) as id FROM activity.ResourceActivity GROUP BY ResourceId,ActivityStatusId ) AS b ON a.ResourceId = b.ResourceId AND a.id = b.id order by a.Id desc OFFSET 0 ROWS) ra + (SELECT a.* FROM activity.ResourceActivity a INNER JOIN (SELECT ResourceId, MAX(Id) as id FROM activity.ResourceActivity GROUP BY ResourceId) AS b ON a.ResourceId = b.ResourceId AND a.id = b.id order by a.Id desc OFFSET 0 ROWS) ra JOIN [resources].[Resource] r ON ra.ResourceId = r.Id JOIN [resources].[ResourceVersion] rv ON rv.Id = ra.ResourceVersionId LEFT JOIN [resources].[AssessmentResourceVersion] arv ON arv.ResourceVersionId = ra.ResourceVersionId @@ -238,7 +238,6 @@ BEGIN (r.ResourceTypeId IN (1, 5, 8, 9,10, 12) AND ra.ActivityStatusId <> 3) OR (r.ResourceTypeId IN (2, 7) AND (mar.Id IS NULL OR (mar.Id IS NOT NULL AND mar.PercentComplete < 100) OR ra.ActivityStart < '2020-09-07 00:00:00 +00:00')) OR (r.ResourceTypeId = 6 AND (sa.CmiCoreLesson_status NOT IN (3, 5) AND (ra.ActivityStatusId NOT IN(3, 5)))) - OR (r.ResourceTypeId IN (9) AND ra.ActivityStatusId NOT IN (3)) OR (r.ResourceTypeId = 11 AND ((ara.Id IS NOT NULL AND ara.score < arv.PassMark) OR ra.ActivityStatusId = 7)) ) GROUP BY ra.ResourceId From 72ea324bb90542a00876feadd7610b899171c991 Mon Sep 17 00:00:00 2001 From: Swapnamol Abraham Date: Thu, 9 May 2024 15:54:35 +0100 Subject: [PATCH 5/9] TD-4121: LH-Issue with 'View certificate' link showing for all the completed entries instead showing for the latest completed record --- .../LearningHub.Nhs.Services/MyLearningService.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/WebAPI/LearningHub.Nhs.Services/MyLearningService.cs b/WebAPI/LearningHub.Nhs.Services/MyLearningService.cs index 13e28cb9d..47e20ce28 100644 --- a/WebAPI/LearningHub.Nhs.Services/MyLearningService.cs +++ b/WebAPI/LearningHub.Nhs.Services/MyLearningService.cs @@ -275,9 +275,19 @@ public async Task> PopulateMyLearningDetai expectedActivity = latestActivityCheck.Where(x => x.Id == resourceActivity.Id && (x.ActivityStatusId == ((int)ActivityStatusEnum.Completed) || x.ActivityStatusId == ((int)ActivityStatusEnum.Incomplete) || x.ActivityStatusId == ((int)ActivityStatusEnum.Passed) || x.ActivityStatusId == ((int)ActivityStatusEnum.Downloaded))).OrderByDescending(x => x.ActivityStart).FirstOrDefault(); } - if (latestActivityCheck.Any() && expectedActivity != null && resourceActivity.ResourceVersion.CertificateEnabled == true) + if (latestActivityCheck.Any() && expectedActivity != null) { - viewModel.CertificateEnabled = true; + bool isExpectedActivityIdMatched = false; + if (resourceActivity.Resource.ResourceTypeEnum == ResourceTypeEnum.Audio || resourceActivity.Resource.ResourceTypeEnum == ResourceTypeEnum.Video) + { + isExpectedActivityIdMatched = latestActivityCheck.OrderByDescending(x => x.ActivityStart).FirstOrDefault().Id == expectedActivity.LaunchResourceActivityId; + } + else + { + isExpectedActivityIdMatched = latestActivityCheck.OrderByDescending(x => x.ActivityStart).FirstOrDefault().Id == expectedActivity.Id; + } + + viewModel.CertificateEnabled = isExpectedActivityIdMatched && resourceActivity.ResourceVersion.CertificateEnabled.GetValueOrDefault(false); } else { From b9e1eebc20c7827d10b61a4c547a032f7974a260 Mon Sep 17 00:00:00 2001 From: Swapnamol Abraham Date: Thu, 9 May 2024 17:02:57 +0100 Subject: [PATCH 6/9] Removed unwanted condition --- WebAPI/LearningHub.Nhs.Services/MyLearningService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebAPI/LearningHub.Nhs.Services/MyLearningService.cs b/WebAPI/LearningHub.Nhs.Services/MyLearningService.cs index 47e20ce28..57935ad36 100644 --- a/WebAPI/LearningHub.Nhs.Services/MyLearningService.cs +++ b/WebAPI/LearningHub.Nhs.Services/MyLearningService.cs @@ -272,7 +272,7 @@ public async Task> PopulateMyLearningDetai } else { - expectedActivity = latestActivityCheck.Where(x => x.Id == resourceActivity.Id && (x.ActivityStatusId == ((int)ActivityStatusEnum.Completed) || x.ActivityStatusId == ((int)ActivityStatusEnum.Incomplete) || x.ActivityStatusId == ((int)ActivityStatusEnum.Passed) || x.ActivityStatusId == ((int)ActivityStatusEnum.Downloaded))).OrderByDescending(x => x.ActivityStart).FirstOrDefault(); + expectedActivity = latestActivityCheck.Where(x => x.Id == resourceActivity.Id && (x.ActivityStatusId == ((int)ActivityStatusEnum.Completed) || x.ActivityStatusId == ((int)ActivityStatusEnum.Passed) || x.ActivityStatusId == ((int)ActivityStatusEnum.Downloaded))).OrderByDescending(x => x.ActivityStart).FirstOrDefault(); } if (latestActivityCheck.Any() && expectedActivity != null) From 3f711aee6d44ecd23b4a04e8f2b6c183104bae87 Mon Sep 17 00:00:00 2001 From: Swapnamol Abraham Date: Fri, 10 May 2024 15:03:18 +0100 Subject: [PATCH 7/9] TD-4121: Fixed the issue with the assessment certificate view --- WebAPI/LearningHub.Nhs.Services/MyLearningService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WebAPI/LearningHub.Nhs.Services/MyLearningService.cs b/WebAPI/LearningHub.Nhs.Services/MyLearningService.cs index 57935ad36..47e20ce28 100644 --- a/WebAPI/LearningHub.Nhs.Services/MyLearningService.cs +++ b/WebAPI/LearningHub.Nhs.Services/MyLearningService.cs @@ -272,7 +272,7 @@ public async Task> PopulateMyLearningDetai } else { - expectedActivity = latestActivityCheck.Where(x => x.Id == resourceActivity.Id && (x.ActivityStatusId == ((int)ActivityStatusEnum.Completed) || x.ActivityStatusId == ((int)ActivityStatusEnum.Passed) || x.ActivityStatusId == ((int)ActivityStatusEnum.Downloaded))).OrderByDescending(x => x.ActivityStart).FirstOrDefault(); + expectedActivity = latestActivityCheck.Where(x => x.Id == resourceActivity.Id && (x.ActivityStatusId == ((int)ActivityStatusEnum.Completed) || x.ActivityStatusId == ((int)ActivityStatusEnum.Incomplete) || x.ActivityStatusId == ((int)ActivityStatusEnum.Passed) || x.ActivityStatusId == ((int)ActivityStatusEnum.Downloaded))).OrderByDescending(x => x.ActivityStart).FirstOrDefault(); } if (latestActivityCheck.Any() && expectedActivity != null) From 6bb737d6ab558f5e39fb8794e17970d4a03e84c4 Mon Sep 17 00:00:00 2001 From: Oluwatobi Awe Date: Fri, 10 May 2024 16:05:04 +0100 Subject: [PATCH 8/9] TD-3023 QuestionBlock wsi bugfix and draft published case file --- .../Controllers/Api/ContributeController.cs | 4 +- .../ResourceService.cs | 62 +++++++++++++------ 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/LearningHub.Nhs.WebUI/Controllers/Api/ContributeController.cs b/LearningHub.Nhs.WebUI/Controllers/Api/ContributeController.cs index 5eeca7be7..09ffdc6bb 100644 --- a/LearningHub.Nhs.WebUI/Controllers/Api/ContributeController.cs +++ b/LearningHub.Nhs.WebUI/Controllers/Api/ContributeController.cs @@ -493,7 +493,7 @@ public async Task SaveWeblinkDetailAsync([FromBody] WebLinkViewMod public async Task SaveCaseDetailAsync([FromBody] CaseViewModel request) { var existingResourceState = await this.resourceService.GetResourceVersionExtendedAsync(request.ResourceVersionId); - if (existingResourceState.CaseDetails?.BlockCollection != null) + if (existingResourceState?.CaseDetails?.BlockCollection != null) { await this.RemoveBlockCollectionFiles(request.ResourceVersionId, existingResourceState.CaseDetails.BlockCollection, request.BlockCollection); } @@ -903,7 +903,7 @@ private List CheckQuestionBlock(BlockCollectionViewModel model) } } - return filePath; + return filePath.Where(x => x != null).ToList(); } } } diff --git a/WebAPI/LearningHub.Nhs.Services/ResourceService.cs b/WebAPI/LearningHub.Nhs.Services/ResourceService.cs index c0b7e5d1f..e040a21c8 100644 --- a/WebAPI/LearningHub.Nhs.Services/ResourceService.cs +++ b/WebAPI/LearningHub.Nhs.Services/ResourceService.cs @@ -1471,38 +1471,60 @@ public async Task> GetObsoleteResourceFile(int resourceVersionId, b } } } - else if (resource.ResourceTypeEnum == ResourceTypeEnum.Assessment) + else if (extendedResourceVersion.ResourceTypeEnum == ResourceTypeEnum.Assessment) { - if (deletedResource) - { - if (resource.AssessmentDetails is { EndGuidance: { } } && resource.AssessmentDetails.EndGuidance.Blocks != null) + var endGuidanceFiles = new List(); + var assessmentContentFiles = new List(); + + if (resource.AssessmentDetails is { EndGuidance: { } } && resource.AssessmentDetails.EndGuidance.Blocks != null) { - var assessmentFiles = this.CheckBlockFile(extendedResourceVersion.AssessmentDetails.EndGuidance, resource.AssessmentDetails.EndGuidance); - if (assessmentFiles.Any()) + if (deletedResource) { - retVal.AddRange(assessmentFiles); + endGuidanceFiles = this.CheckBlockFile(extendedResourceVersion.AssessmentDetails.EndGuidance, resource.AssessmentDetails.EndGuidance); + } + else + { + endGuidanceFiles = this.CheckBlockFile(resource.AssessmentDetails.EndGuidance, extendedResourceVersion.AssessmentDetails.EndGuidance); + } + + if (endGuidanceFiles.Any()) + { + retVal.AddRange(endGuidanceFiles); } } - if (resource.AssessmentDetails is { AssessmentContent: { } } && resource.AssessmentDetails.AssessmentContent.Blocks != null) + if (resource.AssessmentDetails is { AssessmentContent: { } } && resource.AssessmentDetails.AssessmentContent.Blocks != null) { - var assessmentFiles = this.CheckBlockFile(extendedResourceVersion.AssessmentDetails.AssessmentContent, resource.AssessmentDetails.AssessmentContent); - if (assessmentFiles.Any()) + if (deletedResource) { - retVal.AddRange(assessmentFiles); + assessmentContentFiles = this.CheckBlockFile(extendedResourceVersion.AssessmentDetails.AssessmentContent, resource.AssessmentDetails.AssessmentContent); + } + else + { + assessmentContentFiles = this.CheckBlockFile(resource.AssessmentDetails.AssessmentContent, extendedResourceVersion.AssessmentDetails.AssessmentContent); + } + + if (assessmentContentFiles.Any()) + { + retVal.AddRange(assessmentContentFiles); } } - } } - else if (resource.ResourceTypeEnum == ResourceTypeEnum.Case) + else if (extendedResourceVersion.ResourceTypeEnum == ResourceTypeEnum.Case) { + var caseFiles = new List(); if (deletedResource) { - var caseFiles = this.CheckBlockFile(extendedResourceVersion.CaseDetails.BlockCollection, resource.CaseDetails.BlockCollection); - if (caseFiles.Any()) - { - retVal.AddRange(caseFiles); - } + caseFiles = this.CheckBlockFile(extendedResourceVersion.CaseDetails.BlockCollection, resource.CaseDetails.BlockCollection); + } + else + { + caseFiles = this.CheckBlockFile(resource.CaseDetails.BlockCollection, extendedResourceVersion.CaseDetails.BlockCollection); + } + + if (caseFiles.Any()) + { + retVal.AddRange(caseFiles); } } } @@ -4997,7 +5019,7 @@ private List CheckBlockFile(BlockCollectionViewModel? publishedBlock, Bl } } - return retVal; + return retVal.Where(x => x != null).ToList(); } private List CheckQuestionBlock(BlockCollectionViewModel model) @@ -5112,7 +5134,7 @@ private List CheckQuestionBlock(BlockCollectionViewModel model) } } - return filePath; + return filePath.Where(x => x != null).ToList(); } } } \ No newline at end of file From 6f63913f393814da8e08a15f8c3ac438627d40a7 Mon Sep 17 00:00:00 2001 From: Sarathlal Sarangadharan Date: Mon, 13 May 2024 10:48:51 +0100 Subject: [PATCH 9/9] TD-4115: Issues on showing statuses on 'My accessed Learning' section of Learning Hub Home page --- .../Resources/GetDashboardResources.sql | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Resources/GetDashboardResources.sql b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Resources/GetDashboardResources.sql index 4fc44526b..1618e5af4 100644 --- a/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Resources/GetDashboardResources.sql +++ b/WebAPI/LearningHub.Nhs.Database/Stored Procedures/Resources/GetDashboardResources.sql @@ -18,6 +18,7 @@ -- 17 Jan 2024 SA Changes to accomadate activity status changes -- 27 Feb 2024 SS Fixed missing In progress resources in the My Accessed Learning tray issue -- 2 May 2024 SA Fixed the issue on showing statuses on 'My accessed Learning' for resource type file +-- 13 May 2024 SA TD-4115 ------------------------------------------------------------------------------- CREATE PROCEDURE [resources].[GetDashboardResources] @@ -238,11 +239,13 @@ BEGIN (r.ResourceTypeId IN (1, 5, 8, 9,10, 12) AND ra.ActivityStatusId <> 3) OR (r.ResourceTypeId IN (2, 7) AND (mar.Id IS NULL OR (mar.Id IS NOT NULL AND mar.PercentComplete < 100) OR ra.ActivityStart < '2020-09-07 00:00:00 +00:00')) OR (r.ResourceTypeId = 6 AND (sa.CmiCoreLesson_status NOT IN (3, 5) AND (ra.ActivityStatusId NOT IN(3, 5)))) - OR (r.ResourceTypeId = 11 AND ((ara.Id IS NOT NULL AND ara.score < arv.PassMark) OR ra.ActivityStatusId = 7)) + OR (r.ResourceTypeId IN (9) AND ra.ActivityStatusId NOT IN (3)) + OR ((r.ResourceTypeId = 11 AND arv.AssessmentType = 2) AND ((ara.Id IS NOT NULL AND ara.score < arv.PassMark) OR ra.ActivityStatusId IN (7))) + OR ((r.ResourceTypeId = 11 AND arv.AssessmentType = 1) AND ra.ActivityStatusId IN (7)) ) GROUP BY ra.ResourceId ORDER BY ResourceActivityId DESC - + SELECT ma.ResourceActivityId, r.Id AS ResourceId ,( SELECT TOP 1 rr.OriginalResourceReferenceId FROM [resources].[ResourceReference] rr @@ -384,7 +387,8 @@ BEGIN AND ( (r.ResourceTypeId IN (2, 7) AND ra.ActivityStatusId IN (3) OR ra.ActivityStart < '2020-09-07 00:00:00 +00:00' OR mar.Id IS NOT NULL AND mar.PercentComplete = 100) OR (r.ResourceTypeId = 6 AND (sa.CmiCoreLesson_status IN(3,5) OR (ra.ActivityStatusId IN(3, 5)))) - OR (r.ResourceTypeId = 11 AND ara.Score >= arv.PassMark OR ra.ActivityStatusId IN(3, 5)) + OR ((r.ResourceTypeId = 11 AND arv.AssessmentType = 2) AND (ara.Score >= arv.PassMark OR ra.ActivityStatusId IN(3, 5))) + OR ((r.ResourceTypeId = 11 AND arv.AssessmentType =1) AND (ara.Score >= arv.PassMark AND ra.ActivityStatusId IN(3, 5))) OR (r.ResourceTypeId IN (1, 5, 8, 9, 10, 12) AND ra.ActivityStatusId IN (3))) GROUP BY ra.ResourceId ORDER BY ResourceActivityId DESC