From ef7ebe97b040483f38a62fb580b43a7b54a07c21 Mon Sep 17 00:00:00 2001 From: Oluwatobi Awe Date: Tue, 7 May 2024 09:25:13 +0100 Subject: [PATCH 1/2] 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 2/2] 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); }