diff --git a/modules/docs/src/Volo.Docs.Application/Volo/Docs/DocsApplicationModule.cs b/modules/docs/src/Volo.Docs.Application/Volo/Docs/DocsApplicationModule.cs index b3e9f579be..053a3bdb84 100644 --- a/modules/docs/src/Volo.Docs.Application/Volo/Docs/DocsApplicationModule.cs +++ b/modules/docs/src/Volo.Docs.Application/Volo/Docs/DocsApplicationModule.cs @@ -1,7 +1,9 @@ using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.AutoMapper; using Volo.Abp.Caching; using Volo.Abp.Modularity; +using Volo.Docs.Documents; namespace Volo.Docs { @@ -15,10 +17,13 @@ namespace Volo.Docs public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddAutoMapperObjectMapper(); + Configure(options => { options.AddProfile(validate: true); }); + + context.Services.TryAddSingleton(NullNavigationTreePostProcessor.Instance); } } } diff --git a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs index 430cd9ead2..251d96d237 100644 --- a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs +++ b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs @@ -18,6 +18,8 @@ namespace Volo.Docs.Documents { public class DocumentAppService : DocsAppServiceBase, IDocumentAppService { + public INavigationTreePostProcessor NavigationTreePostProcessor { get; set; } + private readonly IProjectRepository _projectRepository; private readonly IDocumentRepository _documentRepository; private readonly IDocumentSourceFactory _documentStoreFactory; @@ -54,6 +56,8 @@ namespace Volo.Docs.Documents _cacheTimeout = GetCacheTimeout(); _documentResourceAbsoluteExpiration = GetDocumentResourceAbsoluteExpirationTimeout(); _documentResourceSlidingExpiration = GetDocumentResourceSlidingExpirationTimeout(); + + NavigationTreePostProcessor = NullNavigationTreePostProcessor.Instance; } public virtual async Task GetAsync(GetDocumentInput input) @@ -91,9 +95,11 @@ namespace Volo.Docs.Documents input.Version ); - if (!JsonConvertExtensions.TryDeserializeObject(navigationDocument.Content, out var navigationNode)) + if (!JsonConvertExtensions.TryDeserializeObject(navigationDocument.Content, + out var navigationNode)) { - throw new UserFriendlyException($"Cannot validate navigation file '{project.NavigationDocumentName}' for the project {project.Name}."); + throw new UserFriendlyException( + $"Cannot validate navigation file '{project.NavigationDocumentName}' for the project {project.Name}."); } var leafs = navigationNode.Items.GetAllNodes(x => x.Items) @@ -102,7 +108,9 @@ namespace Volo.Docs.Documents foreach (var leaf in leafs) { - var cacheKey = CacheKeyGenerator.GenerateDocumentUpdateInfoCacheKey(project, leaf.Path, input.LanguageCode, input.Version); + var cacheKey = + CacheKeyGenerator.GenerateDocumentUpdateInfoCacheKey(project, leaf.Path, input.LanguageCode, + input.Version); var documentUpdateInfo = await DocumentUpdateCache.GetAsync(cacheKey); if (documentUpdateInfo != null) { @@ -112,13 +120,22 @@ namespace Volo.Docs.Documents } } + await NavigationTreePostProcessor.ProcessAsync( + new NavigationTreePostProcessorContext( + navigationDocument, + navigationNode + ) + ); + return navigationNode; } public async Task GetResourceAsync(GetDocumentResourceInput input) { var project = await _projectRepository.GetAsync(input.ProjectId); - var cacheKey = CacheKeyGenerator.GenerateDocumentResourceCacheKey(project, input.Name, input.LanguageCode, input.Version); + var cacheKey = + CacheKeyGenerator.GenerateDocumentResourceCacheKey(project, input.Name, input.LanguageCode, + input.Version); input.Version = string.IsNullOrWhiteSpace(input.Version) ? project.LatestVersionBranchName : input.Version; async Task GetResourceAsync() @@ -133,25 +150,26 @@ namespace Volo.Docs.Documents } return ObjectMapper.Map( - await ResourceCache.GetOrAddAsync( - cacheKey, - GetResourceAsync, - () => new DistributedCacheEntryOptions - { - AbsoluteExpirationRelativeToNow = _documentResourceAbsoluteExpiration, - SlidingExpiration = _documentResourceSlidingExpiration - } - ) - ); + await ResourceCache.GetOrAddAsync( + cacheKey, + GetResourceAsync, + () => new DistributedCacheEntryOptions + { + AbsoluteExpirationRelativeToNow = _documentResourceAbsoluteExpiration, + SlidingExpiration = _documentResourceSlidingExpiration + } + ) + ); } public async Task> SearchAsync(DocumentSearchInput input) { var project = await _projectRepository.GetAsync(input.ProjectId); - var esDocs = await _documentFullSearch.SearchAsync(input.Context, project.Id, input.LanguageCode, input.Version); + var esDocs = + await _documentFullSearch.SearchAsync(input.Context, project.Id, input.LanguageCode, input.Version); - return esDocs.Select(esDoc => new DocumentSearchOutput//TODO: auto map + return esDocs.Select(esDoc => new DocumentSearchOutput //TODO: auto map { Name = esDoc.Name, FileName = esDoc.FileName, @@ -184,9 +202,11 @@ namespace Volo.Docs.Documents input.Version ); - if (!JsonConvertExtensions.TryDeserializeObject(document.Content, out var documentParameters)) + if (!JsonConvertExtensions.TryDeserializeObject(document.Content, + out var documentParameters)) { - throw new UserFriendlyException($"Cannot validate document parameters file '{project.ParametersDocumentName}' for the project {project.Name}."); + throw new UserFriendlyException( + $"Cannot validate document parameters file '{project.ParametersDocumentName}' for the project {project.Name}."); } return documentParameters; @@ -225,7 +245,8 @@ namespace Volo.Docs.Documents return await GetDocumentAsync(documentName, project, languageCode, version, document); } - var cacheKey = CacheKeyGenerator.GenerateDocumentUpdateInfoCacheKey(project, document.Name, document.LanguageCode, document.Version); + var cacheKey = CacheKeyGenerator.GenerateDocumentUpdateInfoCacheKey(project, document.Name, + document.LanguageCode, document.Version); await DocumentUpdateCache.SetAsync(cacheKey, new DocumentUpdateInfo { Name = document.Name, @@ -241,23 +262,28 @@ namespace Volo.Docs.Documents { var documentDto = ObjectMapper.Map(document); documentDto.Project = ObjectMapper.Map(project); - documentDto.Contributors = ObjectMapper.Map, List>(document.Contributors); + documentDto.Contributors = + ObjectMapper.Map, List>(document.Contributors); return documentDto; } - private async Task GetDocumentAsync(string documentName, Project project, string languageCode, string version, Document oldDocument = null) + private async Task GetDocumentAsync(string documentName, Project project, + string languageCode, string version, Document oldDocument = null) { Logger.LogInformation($"Not found in the cache. Requesting {documentName} from the source..."); var source = _documentStoreFactory.Create(project.DocumentStoreType); - var sourceDocument = await source.GetDocumentAsync(project, documentName, languageCode, version, oldDocument?.LastSignificantUpdateTime); + var sourceDocument = await source.GetDocumentAsync(project, documentName, languageCode, version, + oldDocument?.LastSignificantUpdateTime); - await _documentRepository.DeleteAsync(project.Id, sourceDocument.Name, sourceDocument.LanguageCode, sourceDocument.Version); + await _documentRepository.DeleteAsync(project.Id, sourceDocument.Name, sourceDocument.LanguageCode, + sourceDocument.Version); await _documentRepository.InsertAsync(sourceDocument, true); Logger.LogInformation($"Document retrieved: {documentName}"); - var cacheKey = CacheKeyGenerator.GenerateDocumentUpdateInfoCacheKey(project, sourceDocument.Name, sourceDocument.LanguageCode, sourceDocument.Version); + var cacheKey = CacheKeyGenerator.GenerateDocumentUpdateInfoCacheKey(project, sourceDocument.Name, + sourceDocument.LanguageCode, sourceDocument.Version); await DocumentUpdateCache.SetAsync(cacheKey, new DocumentUpdateInfo { Name = sourceDocument.Name, diff --git a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/INavigationTreePostProcessor.cs b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/INavigationTreePostProcessor.cs new file mode 100644 index 0000000000..4dd6bad015 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/INavigationTreePostProcessor.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Volo.Docs.Documents +{ + public interface INavigationTreePostProcessor + { + Task ProcessAsync(NavigationTreePostProcessorContext context); + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/NavigationTreePostProcessorContext.cs b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/NavigationTreePostProcessorContext.cs new file mode 100644 index 0000000000..4bc1018a6c --- /dev/null +++ b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/NavigationTreePostProcessorContext.cs @@ -0,0 +1,14 @@ +namespace Volo.Docs.Documents +{ + public class NavigationTreePostProcessorContext + { + public DocumentWithDetailsDto Document { get; } + public NavigationNode RootNode { get; } + + public NavigationTreePostProcessorContext(DocumentWithDetailsDto document, NavigationNode rootNode) + { + Document = document; + RootNode = rootNode; + } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/NullNavigationTreePostProcessor.cs b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/NullNavigationTreePostProcessor.cs new file mode 100644 index 0000000000..a0d7c3f4de --- /dev/null +++ b/modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/NullNavigationTreePostProcessor.cs @@ -0,0 +1,20 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Docs.Documents +{ + public sealed class NullNavigationTreePostProcessor : INavigationTreePostProcessor + { + public static NullNavigationTreePostProcessor Instance { get; } = new NullNavigationTreePostProcessor(); + + private NullNavigationTreePostProcessor() + { + + } + + public Task ProcessAsync(NavigationTreePostProcessorContext context) + { + return Task.CompletedTask; + } + } +} \ No newline at end of file