From 5bd9d317ab407636b4d0d40bc7dcca8077a74fda Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 24 Feb 2020 14:35:02 +0800 Subject: [PATCH 1/5] Add document full text search function (elastic search). --- .../app/VoloDocs.Web/VoloDocsWebModule.cs | 3 + .../docs/app/VoloDocs.Web/appsettings.json | 6 +- .../Documents/IDocumentAdminAppService.cs | 2 + .../Documents/DocumentAdminAppService.cs | 15 +- .../Docs/Admin/DocumentsAdminController.cs | 7 + .../Docs/Documents/DocumentSearchInput.cs | 19 ++ .../Docs/Documents/DocumentSearchOutput.cs | 24 +++ .../Docs/Documents/IDocumentAppService.cs | 3 + .../Volo/Docs/Documents/DocumentAppService.cs | 23 ++- .../Volo.Docs.Domain/Volo.Docs.Domain.csproj | 1 + .../Volo/Docs/DocsDomainModule.cs | 16 ++ .../Elastic/DefaultElasticClientProvider.cs | 27 +++ .../Elastic/DocsElasticSearchOptions.cs | 15 ++ .../Elastic/DocumentChangedEventHandler.cs | 49 +++++ .../Elastic/ElasticDocumentFullSearch.cs | 179 ++++++++++++++++++ .../FullSearch/Elastic/EsDocument.cs | 29 +++ .../FullSearch/Elastic/IDocumentFullSearch.cs | 20 ++ .../Elastic/IElasticClientProvider.cs | 9 + .../Docs/Documents/DocsDocumentController.cs | 10 +- .../docs/src/Volo.Docs.Web/DocsWebModule.cs | 3 +- .../Pages/Documents/Project/Index.cshtml | 14 +- .../Pages/Documents/Project/index.js | 10 +- .../Pages/Documents/Search.cshtml | 67 +++++++ .../Pages/Documents/Search.cshtml.cs | 68 +++++++ 24 files changed, 611 insertions(+), 8 deletions(-) create mode 100644 modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentSearchInput.cs create mode 100644 modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentSearchOutput.cs create mode 100644 modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/DefaultElasticClientProvider.cs create mode 100644 modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/DocsElasticSearchOptions.cs create mode 100644 modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/DocumentChangedEventHandler.cs create mode 100644 modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/ElasticDocumentFullSearch.cs create mode 100644 modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/EsDocument.cs create mode 100644 modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/IDocumentFullSearch.cs create mode 100644 modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/IElasticClientProvider.cs create mode 100644 modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml create mode 100644 modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml.cs diff --git a/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs index d46ae6e021..8d54eaae90 100644 --- a/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs +++ b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs @@ -33,6 +33,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; using Volo.Abp.Account; using Volo.Abp.Validation.Localization; +using Volo.Docs.Documents.FullSearch.Elastic; namespace VoloDocs.Web { @@ -71,6 +72,8 @@ namespace VoloDocs.Web options.RoutePrefix = null; }); + Configure(options => { options.Enable = true; }); + Configure(options => { options.ConnectionStrings.Default = configuration["ConnectionString"]; diff --git a/modules/docs/app/VoloDocs.Web/appsettings.json b/modules/docs/app/VoloDocs.Web/appsettings.json index 3d89a0a1e3..44eb9adc30 100644 --- a/modules/docs/app/VoloDocs.Web/appsettings.json +++ b/modules/docs/app/VoloDocs.Web/appsettings.json @@ -1,4 +1,8 @@ { "ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True;MultipleActiveResultSets=true", - "LogoUrl": "/assets/images/Logo.png" + "LogoUrl": "/assets/images/Logo.png", + + "ElasticSearch": { + "Url": "http://172.25.134.11:9200" + } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/IDocumentAdminAppService.cs b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/IDocumentAdminAppService.cs index 6adab29c74..1f18c0e64b 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/IDocumentAdminAppService.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application.Contracts/Volo/Docs/Admin/Documents/IDocumentAdminAppService.cs @@ -8,5 +8,7 @@ namespace Volo.Docs.Admin.Documents Task PullAllAsync(PullAllDocumentInput input); Task PullAsync(PullDocumentInput input); + + Task ReindexAsync(); } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs index 255fed246f..845062148b 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs @@ -7,6 +7,7 @@ using Newtonsoft.Json; using Volo.Abp.Application.Services; using Volo.Abp.Caching; using Volo.Docs.Documents; +using Volo.Docs.Documents.FullSearch.Elastic; using Volo.Docs.Projects; namespace Volo.Docs.Admin.Documents @@ -18,16 +19,19 @@ namespace Volo.Docs.Admin.Documents private readonly IDocumentRepository _documentRepository; private readonly IDocumentSourceFactory _documentStoreFactory; private readonly IDistributedCache _documentUpdateCache; + private readonly IDocumentFullSearch _documentFullSearch; public DocumentAdminAppService(IProjectRepository projectRepository, IDocumentRepository documentRepository, IDocumentSourceFactory documentStoreFactory, - IDistributedCache documentUpdateCache) + IDistributedCache documentUpdateCache, + IDocumentFullSearch documentFullSearch) { _projectRepository = projectRepository; _documentRepository = documentRepository; _documentStoreFactory = documentStoreFactory; _documentUpdateCache = documentUpdateCache; + _documentFullSearch = documentFullSearch; } public async Task PullAllAsync(PullAllDocumentInput input) @@ -80,6 +84,15 @@ namespace Volo.Docs.Admin.Documents await UpdateDocumentUpdateInfoCache(sourceDocument); } + public async Task ReindexAsync() + { + var docs = await _documentRepository.GetListAsync(); + foreach (var doc in docs) + { + await _documentFullSearch.AddOrUpdateAsync(doc); + } + } + private async Task UpdateDocumentUpdateInfoCache(Document document) { var cacheKey = $"DocumentUpdateInfo{document.ProjectId}#{document.Name}#{document.LanguageCode}#{document.Version}"; diff --git a/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/DocumentsAdminController.cs b/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/DocumentsAdminController.cs index 75f610d3e5..1dd1327266 100644 --- a/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/DocumentsAdminController.cs +++ b/modules/docs/src/Volo.Docs.Admin.HttpApi/Volo/Docs/Admin/DocumentsAdminController.cs @@ -32,5 +32,12 @@ namespace Volo.Docs.Admin { return _documentAdminAppService.PullAsync(input); } + + [HttpPost] + [Route("Reindex")] + public Task ReindexAsync() + { + return _documentAdminAppService.ReindexAsync(); + } } } diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentSearchInput.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentSearchInput.cs new file mode 100644 index 0000000000..b3e40367d0 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentSearchInput.cs @@ -0,0 +1,19 @@ +using System; + +namespace Volo.Docs.Documents +{ + public class DocumentSearchInput + { + public string Context { get; set; } + + public Guid ProjectId { get; set; } + + public string LanguageCode { get; set; } + + public string Version { get; set; } + + public int? SkipCount { get; set; } + + public int? MaxResultCount { get; set; } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentSearchOutput.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentSearchOutput.cs new file mode 100644 index 0000000000..43875db527 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/DocumentSearchOutput.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Docs.Documents +{ + public class DocumentSearchOutput + { + public DocumentSearchOutput() + { + Highlight = new List(); + } + + public string Name { get; set; } + + public string FileName { get; set; } + + public string Version { get; set; } + + public string LanguageCode { get; set; } + + public List Highlight { get; set; } + } +} diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/IDocumentAppService.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/IDocumentAppService.cs index b1195e0254..68f62abce5 100644 --- a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/IDocumentAppService.cs +++ b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/IDocumentAppService.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Threading.Tasks; using Volo.Abp.Application.Services; @@ -14,5 +15,7 @@ namespace Volo.Docs.Documents Task GetParametersAsync(GetParametersDocumentInput input); Task GetResourceAsync(GetDocumentResourceInput input); + + Task> SearchAsync(DocumentSearchInput input); } } \ No newline at end of file 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 7ea04ec0c0..77bb82579d 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 @@ -7,6 +7,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Volo.Abp.Caching; +using Volo.Docs.Documents.FullSearch.Elastic; using Volo.Docs.Projects; namespace Volo.Docs.Documents @@ -20,6 +21,8 @@ namespace Volo.Docs.Documents protected IDistributedCache ResourceCache { get; } protected IDistributedCache DocumentUpdateCache { get; } protected IHostEnvironment HostEnvironment { get; } + private readonly IDocumentFullSearch _documentFullSearch; + public DocumentAppService( IProjectRepository projectRepository, IDocumentRepository documentRepository, @@ -27,7 +30,8 @@ namespace Volo.Docs.Documents IDistributedCache languageCache, IDistributedCache resourceCache, IDistributedCache documentUpdateCache, - IHostEnvironment hostEnvironment) + IHostEnvironment hostEnvironment, + IDocumentFullSearch documentFullSearch) { _projectRepository = projectRepository; _documentRepository = documentRepository; @@ -36,6 +40,7 @@ namespace Volo.Docs.Documents ResourceCache = resourceCache; DocumentUpdateCache = documentUpdateCache; HostEnvironment = hostEnvironment; + _documentFullSearch = documentFullSearch; } public virtual async Task GetAsync(GetDocumentInput input) @@ -124,6 +129,22 @@ namespace Volo.Docs.Documents ); } + 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); + + return esDocs.Select(esDoc => new DocumentSearchOutput//TODO: auto map + { + Name = esDoc.Name, + FileName = esDoc.FileName, + Version = esDoc.Version, + LanguageCode = esDoc.LanguageCode, + Highlight = esDoc.Highlight + }).ToList(); + } + public async Task GetParametersAsync(GetParametersDocumentInput input) { var project = await _projectRepository.GetAsync(input.ProjectId); diff --git a/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj b/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj index 234832ef1a..c2540754a3 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj +++ b/modules/docs/src/Volo.Docs.Domain/Volo.Docs.Domain.csproj @@ -18,6 +18,7 @@ + diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs index 81f681403d..ba2ee6018d 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainModule.cs @@ -1,10 +1,14 @@ using System; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp; using Volo.Abp.Domain; using Volo.Abp.Localization; using Volo.Abp.Modularity; +using Volo.Abp.Threading; using Volo.Abp.VirtualFileSystem; using Volo.Docs.Documents; +using Volo.Docs.Documents.FullSearch.Elastic; using Volo.Docs.FileSystem.Documents; using Volo.Docs.GitHub.Documents; using Volo.Docs.Localization; @@ -43,5 +47,17 @@ namespace Volo.Docs client.Timeout = TimeSpan.FromMilliseconds(15000); }); } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + using (var scope = context.ServiceProvider.CreateScope()) + { + if (scope.ServiceProvider.GetRequiredService>().Value.Enable) + { + var documentFullSearch = scope.ServiceProvider.GetRequiredService(); + AsyncHelper.RunSync(() => documentFullSearch.CreateIndexIfNeededAsync()); + } + } + } } } diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/DefaultElasticClientProvider.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/DefaultElasticClientProvider.cs new file mode 100644 index 0000000000..5db064fd5f --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/DefaultElasticClientProvider.cs @@ -0,0 +1,27 @@ +using System; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Options; +using Nest; +using Volo.Abp.DependencyInjection; + +namespace Volo.Docs.Documents.FullSearch.Elastic +{ + public class DefaultElasticClientProvider : IElasticClientProvider, ISingletonDependency + { + protected readonly DocsElasticSearchOptions Options; + protected readonly IConfiguration Configuration; + + public DefaultElasticClientProvider(IOptions options, IConfiguration configuration) + { + Configuration = configuration; + Options = options.Value; + } + + public virtual IElasticClient GetClient() + { + var node = new Uri(Configuration["ElasticSearch:Url"]); + var settings = new ConnectionSettings(node).DefaultIndex(Options.IndexName); + return new ElasticClient(settings); + } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/DocsElasticSearchOptions.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/DocsElasticSearchOptions.cs new file mode 100644 index 0000000000..40bbf66b08 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/DocsElasticSearchOptions.cs @@ -0,0 +1,15 @@ +namespace Volo.Docs.Documents.FullSearch.Elastic +{ + public class DocsElasticSearchOptions + { + public DocsElasticSearchOptions() + { + Enable = false; + IndexName = "abp_documents"; + } + + public bool Enable { get; set; } + + public string IndexName { get; set; } + } +} diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/DocumentChangedEventHandler.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/DocumentChangedEventHandler.cs new file mode 100644 index 0000000000..3d1bd50a59 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/DocumentChangedEventHandler.cs @@ -0,0 +1,49 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Entities.Events; +using Volo.Abp.EventBus; + +namespace Volo.Docs.Documents.FullSearch.Elastic +{ + public class DocumentChangedEventHandler : ILocalEventHandler>, + ILocalEventHandler>, + ILocalEventHandler>, + ITransientDependency + { + private readonly DocsElasticSearchOptions _options; + private readonly IDocumentFullSearch _documentFullSearch; + + public DocumentChangedEventHandler(IDocumentFullSearch documentFullSearch, IOptions options) + { + _documentFullSearch = documentFullSearch; + _options = options.Value; + } + + public async Task HandleEventAsync(EntityCreatedEventData eventData) + { + await AddOrUpdate(eventData.Entity); + } + + public async Task HandleEventAsync(EntityUpdatedEventData eventData) + { + await AddOrUpdate(eventData.Entity); + } + + private async Task AddOrUpdate(Document document) + { + if (_options.Enable) + { + await _documentFullSearch.AddOrUpdateAsync(document); + } + } + + public async Task HandleEventAsync(EntityDeletedEventData eventData) + { + if (_options.Enable) + { + await _documentFullSearch.DeleteAsync(eventData.Entity.Id); + } + } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/ElasticDocumentFullSearch.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/ElasticDocumentFullSearch.cs new file mode 100644 index 0000000000..2fdbe27d1a --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/ElasticDocumentFullSearch.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Elasticsearch.Net; +using Microsoft.Extensions.Options; +using Nest; +using Volo.Abp; +using Volo.Abp.Domain.Services; + +namespace Volo.Docs.Documents.FullSearch.Elastic +{ + public class ElasticDocumentFullSearch : DomainService, IDocumentFullSearch + { + private readonly IElasticClientProvider _clientProvider; + private readonly DocsElasticSearchOptions _options; + + public ElasticDocumentFullSearch(IElasticClientProvider clientProvider, IOptions options) + { + _clientProvider = clientProvider; + _options = options.Value; + + if (!_options.Enable) + { + //TODO: localize message + throw new BusinessException("", ""); + } + } + + public async Task CreateIndexIfNeededAsync(CancellationToken cancellationToken = default) + { + var client = _clientProvider.GetClient(); + + var existsResponse = await client.Indices.ExistsAsync(_options.IndexName, ct: cancellationToken); + + HandleError(existsResponse); + + if (!existsResponse.Exists) + { + HandleError(await client.Indices.CreateAsync(_options.IndexName, c => c + .Map(m => + { + return m + .Properties(p => p + .Keyword(x => x.Name(d => d.Id)) + .Keyword(x => x.Name(d => d.ProjectId)) + .Keyword(x => x.Name(d => d.Name)) + .Keyword(x => x.Name(d => d.FileName)) + .Keyword(x => x.Name(d => d.Version)) + .Keyword(x => x.Name(d => d.LanguageCode)) + .Text(x => x.Name(d => d.Content))); + }), cancellationToken)); + } + } + + public async Task AddOrUpdateAsync(Document document, CancellationToken cancellationToken = default) + { + var client = _clientProvider.GetClient(); + + var existsResponse = await client.DocumentExistsAsync(DocumentPath.Id(document.Id), + x => x.Index(_options.IndexName), cancellationToken); + + HandleError(existsResponse); + + var esDocument = new EsDocument + { + Id = document.Id, + ProjectId = document.ProjectId, + Name = document.Name, + FileName = document.FileName, + Content = document.Content, + LanguageCode = document.LanguageCode, + Version = document.Version + }; + + if (!existsResponse.Exists) + { + HandleError(await client.IndexAsync(esDocument, + x => x.Id(document.Id).Index(_options.IndexName), cancellationToken)); + } + else + { + HandleError(await client.UpdateAsync(DocumentPath.Id(document.Id), + x => x.Doc(esDocument).Index(_options.IndexName), cancellationToken)); + } + + } + + public async Task DeleteAsync(Guid id, CancellationToken cancellationToken = default) + { + HandleError(await _clientProvider.GetClient() + .DeleteAsync(DocumentPath.Id(id), x => x.Index(_options.IndexName), cancellationToken)); + } + + public async Task> SearchAsync(string context, Guid projectId, string languageCode, + string version, int? skipCount = null, int? maxResultCount = null, + CancellationToken cancellationToken = default) + { + var request = new SearchRequest + { + Size = maxResultCount ?? 10, + From = skipCount ?? 0, + Query = new BoolQuery + { + Must = new QueryContainer[] + { + new MatchQuery + { + Field = "content", + Query = context + } + }, + Filter = new QueryContainer[] + { + new BoolQuery + { + Must = new QueryContainer[] + { + new TermQuery + { + Field = "projectId", + Value = projectId + }, + new TermQuery + { + Field = "version", + Value = version + }, + new TermQuery + { + Field = "languageCode", + Value = languageCode + } + } + } + } + }, + Highlight = new Highlight + { + PreTags = new[] { "" }, + PostTags = new[] { "" }, + Fields = new Dictionary + { + { + "content", new HighlightField() + } + } + } + }; + + //var json = _clientProvider.GetClient().RequestResponseSerializer.SerializeToString(request); + var response = await _clientProvider.GetClient().SearchAsync(request, cancellationToken); + + HandleError(response); + + var docs = new List(); + foreach (var hit in response.Hits) + { + var doc = hit.Source; + if (hit.Highlight.ContainsKey("content")) + { + doc.Highlight = new List(); + doc.Highlight.AddRange(hit.Highlight["content"]); + } + docs.Add(doc); + } + + return docs; + } + + protected void HandleError(IElasticsearchResponse response) + { + if (!response.ApiCall.Success) + { + throw response.ApiCall.OriginalException; + } + } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/EsDocument.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/EsDocument.cs new file mode 100644 index 0000000000..df78744361 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/EsDocument.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; + +namespace Volo.Docs.Documents.FullSearch.Elastic +{ + public class EsDocument + { + public EsDocument() + { + Highlight = new List(); + } + + public Guid Id { get; set; } + + public Guid ProjectId { get; set; } + + public string Name { get; set; } + + public string FileName { get; set; } + + public string Version { get; set; } + + public string LanguageCode { get; set; } + + public string Content { get; set; } + + public List Highlight { get; set; } + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/IDocumentFullSearch.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/IDocumentFullSearch.cs new file mode 100644 index 0000000000..615f5be4b4 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/IDocumentFullSearch.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Volo.Docs.Documents.FullSearch.Elastic +{ + public interface IDocumentFullSearch + { + Task CreateIndexIfNeededAsync(CancellationToken cancellationToken = default); + + Task AddOrUpdateAsync(Document document, CancellationToken cancellationToken = default); + + Task DeleteAsync(Guid id, CancellationToken cancellationToken = default); + + Task> SearchAsync(string context, Guid projectId, string languageCode, + string version, int? skipCount = null, int? maxResultCount = null, + CancellationToken cancellationToken = default); + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/IElasticClientProvider.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/IElasticClientProvider.cs new file mode 100644 index 0000000000..e1424bfbd6 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/IElasticClientProvider.cs @@ -0,0 +1,9 @@ +using Nest; + +namespace Volo.Docs.Documents.FullSearch.Elastic +{ + public interface IElasticClientProvider + { + IElasticClient GetClient(); + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Documents/DocsDocumentController.cs b/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Documents/DocsDocumentController.cs index a066a92f23..3384ee3314 100644 --- a/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Documents/DocsDocumentController.cs +++ b/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Documents/DocsDocumentController.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Volo.Abp; using Volo.Abp.AspNetCore.Mvc; @@ -46,6 +47,13 @@ namespace Volo.Docs.Documents return DocumentAppService.GetResourceAsync(input); } + [HttpPost] + [Route("search")] + public Task> SearchAsync(DocumentSearchInput input) + { + return DocumentAppService.SearchAsync(input); + } + [HttpGet] [Route("parameters")] public Task GetParametersAsync(GetParametersDocumentInput input) diff --git a/modules/docs/src/Volo.Docs.Web/DocsWebModule.cs b/modules/docs/src/Volo.Docs.Web/DocsWebModule.cs index 5b7309a310..26031f53de 100644 --- a/modules/docs/src/Volo.Docs.Web/DocsWebModule.cs +++ b/modules/docs/src/Volo.Docs.Web/DocsWebModule.cs @@ -1,4 +1,4 @@ -using System; +using System; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; @@ -61,6 +61,7 @@ namespace Volo.Docs options.Conventions.AddPageRoute("/Documents/Project/Index", routePrefix + "{projectName}"); options.Conventions.AddPageRoute("/Documents/Project/Index", routePrefix + "{languageCode}/{projectName}"); options.Conventions.AddPageRoute("/Documents/Project/Index", routePrefix + "{languageCode}/{projectName}/{version}/{*documentName}"); + options.Conventions.AddPageRoute("/Documents/Search", routePrefix + "search/{languageCode}/{projectName}/{version}/{*keyword}"); }); context.Services.AddAutoMapperObjectMapper(); diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml index 7029cc410a..9da501c102 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml @@ -135,6 +135,18 @@ } +
+
+
+
+ +
+ + +
+
+
+
@@ -142,7 +154,7 @@
- +
diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js index 9cbfd547ab..8f53f1cf6e 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/index.js @@ -1,4 +1,4 @@ -(function ($) { +(function ($) { $(function () { var initNavigationFilter = function (navigationContainerId) { @@ -56,13 +56,19 @@ }); }; - $(".docs-page .docs-tree-list input[type='search']").keyup(function (e) { + $("#filter").keyup(function (e) { filterDocumentItems(e.target.value); if (e.key === "Enter") { gotoFilteredDocumentIfThereIsOnlyOne(); } }); + + $("#fullsearch").keyup(function (e) { + if (e.key === "Enter") { + window.open($(this).data("fullsearch-url") + this.value); + } + }); }; var initAnchorTags = function (container) { diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml new file mode 100644 index 0000000000..0e518ddf0e --- /dev/null +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml @@ -0,0 +1,67 @@ +@page +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.AspNetCore.Mvc.UI.Layout +@using Volo.Abp.AspNetCore.Mvc.UI.Theming +@using Volo.Docs.Localization +@using Volo.Docs.Pages.Documents +@inject IHtmlLocalizer L +@inject IThemeManager ThemeManager +@inject IPageLayout PageLayout +@model SearchModel +@{ + Layout = ThemeManager.CurrentTheme.GetEmptyLayout(); +} +@section styles { + +} + +
+
+ + +
+ +
+
Search results
+ + @foreach (var docs in Model.SearchOutputs) + { +
+
+
+ + @functions + { + string RemoveFileExtensionFromPath(string path) + { + if (path == null) + { + return null; + } + + return path.EndsWith("." + @Model.Project.Format) + ? path.Left(path.Length - Model.Project.Format.Length - 1) + : path; + } + } + + +

@RemoveFileExtensionFromPath(docs.Name)

+ + @foreach (var highlight in docs.Highlight) + { +

@Html.Raw(highlight)

+ } + +
+
+
+ } +
+
\ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml.cs new file mode 100644 index 0000000000..531f0201f1 --- /dev/null +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Volo.Docs.Documents; +using Volo.Docs.HtmlConverting; +using Volo.Docs.Models; +using Volo.Docs.Projects; + +namespace Volo.Docs.Pages.Documents +{ + public class SearchModel : PageModel + { + [BindProperty(SupportsGet = true)] + public string ProjectName { get; set; } + + [BindProperty(SupportsGet = true)] + public string Version { get; set; } + + [BindProperty(SupportsGet = true)] + public string LanguageCode { get; set; } + + [BindProperty(SupportsGet = true)] + public string KeyWord { get; set; } + + public ProjectDto Project { get; set; } + + private readonly IProjectAppService _projectAppService; + private readonly IDocumentAppService _documentAppService; + + public SearchModel(IProjectAppService projectAppService, + IDocumentAppService documentAppService) + { + _projectAppService = projectAppService; + _documentAppService = documentAppService; + } + + public List SearchOutputs { get; set; } = new List(); + + public async Task OnGetAsync(string keyword) + { + KeyWord = keyword; + + Project = await _projectAppService.GetAsync(ProjectName); + + var output = await _projectAppService.GetVersionsAsync(Project.ShortName); + + var versions = output.Items.ToList(); + + if (versions.Any() && string.Equals(Version, DocsAppConsts.Latest, StringComparison.OrdinalIgnoreCase)) + { + Version = versions.First().Name; + } + + SearchOutputs = await _documentAppService.SearchAsync(new DocumentSearchInput + { + ProjectId = Project.Id, + Context = KeyWord, + LanguageCode = LanguageCode, + Version = Version + }); + + return Page(); + } + } +} \ No newline at end of file From 3df7be2778d2d48b03a97d1b1dd01b95c48bf83c Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 24 Feb 2020 17:17:06 +0800 Subject: [PATCH 2/5] Check es is enabled. --- .../app/VoloDocs.Web/VoloDocsWebModule.cs | 5 ++++- .../Volo/Docs/DocsDomainErrorCodes.cs | 7 ++++++ .../Elastic/ElasticDocumentFullSearch.cs | 22 ++++++++++++++----- .../Volo/Docs/Localization/Domain/en.json | 2 ++ .../Docs/Localization/Domain/zh-Hans.json | 2 ++ .../Docs/Localization/Domain/zh-Hant.json | 1 + 6 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/DocsDomainErrorCodes.cs diff --git a/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs index 8d54eaae90..0c8e5354b6 100644 --- a/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs +++ b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs @@ -72,7 +72,10 @@ namespace VoloDocs.Web options.RoutePrefix = null; }); - Configure(options => { options.Enable = true; }); + Configure(options => + { + options.Enable = true; + }); Configure(options => { diff --git a/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/DocsDomainErrorCodes.cs b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/DocsDomainErrorCodes.cs new file mode 100644 index 0000000000..1931343aad --- /dev/null +++ b/modules/docs/src/Volo.Docs.Domain.Shared/Volo/Docs/DocsDomainErrorCodes.cs @@ -0,0 +1,7 @@ +namespace Volo.Docs +{ + public static class DocsDomainErrorCodes + { + public const string ElasticSearchNotEnabled = "Volo.Docs.Domain:010001"; + } +} \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/ElasticDocumentFullSearch.cs b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/ElasticDocumentFullSearch.cs index 2fdbe27d1a..4574633318 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/ElasticDocumentFullSearch.cs +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/FullSearch/Elastic/ElasticDocumentFullSearch.cs @@ -19,16 +19,12 @@ namespace Volo.Docs.Documents.FullSearch.Elastic { _clientProvider = clientProvider; _options = options.Value; - - if (!_options.Enable) - { - //TODO: localize message - throw new BusinessException("", ""); - } } public async Task CreateIndexIfNeededAsync(CancellationToken cancellationToken = default) { + CheckEsEnabled(); + var client = _clientProvider.GetClient(); var existsResponse = await client.Indices.ExistsAsync(_options.IndexName, ct: cancellationToken); @@ -55,6 +51,8 @@ namespace Volo.Docs.Documents.FullSearch.Elastic public async Task AddOrUpdateAsync(Document document, CancellationToken cancellationToken = default) { + CheckEsEnabled(); + var client = _clientProvider.GetClient(); var existsResponse = await client.DocumentExistsAsync(DocumentPath.Id(document.Id), @@ -88,6 +86,8 @@ namespace Volo.Docs.Documents.FullSearch.Elastic public async Task DeleteAsync(Guid id, CancellationToken cancellationToken = default) { + CheckEsEnabled(); + HandleError(await _clientProvider.GetClient() .DeleteAsync(DocumentPath.Id(id), x => x.Index(_options.IndexName), cancellationToken)); } @@ -96,6 +96,8 @@ namespace Volo.Docs.Documents.FullSearch.Elastic string version, int? skipCount = null, int? maxResultCount = null, CancellationToken cancellationToken = default) { + CheckEsEnabled(); + var request = new SearchRequest { Size = maxResultCount ?? 10, @@ -175,5 +177,13 @@ namespace Volo.Docs.Documents.FullSearch.Elastic throw response.ApiCall.OriginalException; } } + + protected void CheckEsEnabled() + { + if (!_options.Enable) + { + throw new BusinessException(DocsDomainErrorCodes.ElasticSearchNotEnabled); + } + } } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json index 92858a87f0..9c14a84133 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json @@ -17,6 +17,8 @@ "NavigationDocumentNotFound": "This version does not have a navigation document!", "DocumentNotFoundInSelectedLanguage": "Document in the language you wanted is not found. Document in the default language is shown.", "FilterTopics": "Filter topics", + "FullSearch": "Search document", + "Volo.Docs.Domain:010001": "Elastic search is not enabled.", "MultipleVersionDocumentInfo": "This document has multiple versions. Select the options best fit for you.", "New": "New", "Upd": "Upd", diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json index 3eec4562bb..3d9df18295 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hans.json @@ -17,6 +17,8 @@ "NavigationDocumentNotFound": "这个版本没有导航文件!", "DocumentNotFoundInSelectedLanguage": "本文档不适用于所选语言, 将以默认语言显示文档.", "FilterTopics": "过滤主题", + "FullSearch": "搜索文档", + "Volo.Docs.Domain:010001": "Elastic search未启用.", "New": "新文档", "Upd": "更新", "NewExplanation": "在最近两周内创建.", diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hant.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hant.json index 5c3d723b0a..9fbc677120 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hant.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/zh-Hant.json @@ -17,6 +17,7 @@ "NavigationDocumentNotFound": "這個版本沒有導覽文件!", "DocumentNotFoundInSelectedLanguage": "本文件不適用於所選語系,將以預設語系顯示.", "FilterTopics": "過濾主題", + "FullSearch": "搜索文件", "New": "新文檔", "Upd": "更新", "NewExplanation": "在最近兩周內創建.", From 300c10d00d38512787dcaef84dfc8beafc150cec Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 9 Mar 2020 09:55:39 +0800 Subject: [PATCH 3/5] Rebuilding the index excludes navigation and parameter files. --- modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj | 3 ++- modules/docs/app/VoloDocs.Web/appsettings.json | 3 +-- .../Volo/Docs/Admin/Documents/DocumentAdminAppService.cs | 7 +++++++ .../Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj b/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj index 3cc24371b8..9eb89ff5bb 100644 --- a/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj +++ b/modules/docs/app/VoloDocs.Web/VoloDocs.Web.csproj @@ -1,4 +1,4 @@ - + @@ -8,6 +8,7 @@ true false win-x64;osx-x64;linux-x64 + 5f11b41f-0025-4fe6-ab97-60ec1bd4e8c2 diff --git a/modules/docs/app/VoloDocs.Web/appsettings.json b/modules/docs/app/VoloDocs.Web/appsettings.json index 44eb9adc30..db1d4b31f6 100644 --- a/modules/docs/app/VoloDocs.Web/appsettings.json +++ b/modules/docs/app/VoloDocs.Web/appsettings.json @@ -1,8 +1,7 @@ { "ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True;MultipleActiveResultSets=true", "LogoUrl": "/assets/images/Logo.png", - "ElasticSearch": { - "Url": "http://172.25.134.11:9200" + "Url": "http://localhost:9200" } } \ No newline at end of file diff --git a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs index 845062148b..4bc793f799 100644 --- a/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs +++ b/modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs @@ -87,8 +87,15 @@ namespace Volo.Docs.Admin.Documents public async Task ReindexAsync() { var docs = await _documentRepository.GetListAsync(); + var projects = await _projectRepository.GetListAsync(); foreach (var doc in docs) { + var project = projects.FirstOrDefault(x => x.Id == doc.ProjectId); + if (project != null && (doc.FileName == project.NavigationDocumentName || doc.FileName == project.ParametersDocumentName)) + { + continue; + } + await _documentFullSearch.AddOrUpdateAsync(doc); } } diff --git a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json index 9c14a84133..e8c7122ec3 100644 --- a/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json +++ b/modules/docs/src/Volo.Docs.Domain/Volo/Docs/Localization/Domain/en.json @@ -17,7 +17,7 @@ "NavigationDocumentNotFound": "This version does not have a navigation document!", "DocumentNotFoundInSelectedLanguage": "Document in the language you wanted is not found. Document in the default language is shown.", "FilterTopics": "Filter topics", - "FullSearch": "Search document", + "FullSearch": "Search in documents", "Volo.Docs.Domain:010001": "Elastic search is not enabled.", "MultipleVersionDocumentInfo": "This document has multiple versions. Select the options best fit for you.", "New": "New", From d6c9e6b13e105b606133fa12f14d7bf4d682771d Mon Sep 17 00:00:00 2001 From: maliming Date: Mon, 9 Mar 2020 10:34:21 +0800 Subject: [PATCH 4/5] Add FullSearchEnabledAsync method. --- .../Docs/Documents/IDocumentAppService.cs | 2 ++ .../Volo/Docs/Documents/DocumentAppService.cs | 11 +++++++++- .../Docs/Documents/DocsDocumentController.cs | 7 +++++++ .../Pages/Documents/Project/Index.cshtml | 20 ++++++++++--------- .../Pages/Documents/Project/Index.cshtml.cs | 3 +++ .../Pages/Documents/Search.cshtml.cs | 5 +++++ 6 files changed, 38 insertions(+), 10 deletions(-) diff --git a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/IDocumentAppService.cs b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/IDocumentAppService.cs index 68f62abce5..259d9edf0b 100644 --- a/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/IDocumentAppService.cs +++ b/modules/docs/src/Volo.Docs.Application.Contracts/Volo/Docs/Documents/IDocumentAppService.cs @@ -17,5 +17,7 @@ namespace Volo.Docs.Documents Task GetResourceAsync(GetDocumentResourceInput input); Task> SearchAsync(DocumentSearchInput input); + + Task FullSearchEnabledAsync(); } } \ No newline at end of file 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 77bb82579d..342130d530 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 @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Newtonsoft.Json; using Volo.Abp.Caching; using Volo.Docs.Documents.FullSearch.Elastic; @@ -22,6 +23,7 @@ namespace Volo.Docs.Documents protected IDistributedCache DocumentUpdateCache { get; } protected IHostEnvironment HostEnvironment { get; } private readonly IDocumentFullSearch _documentFullSearch; + private readonly DocsElasticSearchOptions _docsElasticSearchOptions; public DocumentAppService( IProjectRepository projectRepository, @@ -31,7 +33,8 @@ namespace Volo.Docs.Documents IDistributedCache resourceCache, IDistributedCache documentUpdateCache, IHostEnvironment hostEnvironment, - IDocumentFullSearch documentFullSearch) + IDocumentFullSearch documentFullSearch, + IOptions docsElasticSearchOptions) { _projectRepository = projectRepository; _documentRepository = documentRepository; @@ -41,6 +44,7 @@ namespace Volo.Docs.Documents DocumentUpdateCache = documentUpdateCache; HostEnvironment = hostEnvironment; _documentFullSearch = documentFullSearch; + _docsElasticSearchOptions = docsElasticSearchOptions.Value; } public virtual async Task GetAsync(GetDocumentInput input) @@ -145,6 +149,11 @@ namespace Volo.Docs.Documents }).ToList(); } + public async Task FullSearchEnabledAsync() + { + return await Task.FromResult(_docsElasticSearchOptions.Enable); + } + public async Task GetParametersAsync(GetParametersDocumentInput input) { var project = await _projectRepository.GetAsync(input.ProjectId); diff --git a/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Documents/DocsDocumentController.cs b/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Documents/DocsDocumentController.cs index 3384ee3314..a2e4017dc1 100644 --- a/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Documents/DocsDocumentController.cs +++ b/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Documents/DocsDocumentController.cs @@ -54,6 +54,13 @@ namespace Volo.Docs.Documents return DocumentAppService.SearchAsync(input); } + [HttpGet] + [Route("fullsearchenabled")] + public Task FullSearchEnabledAsync() + { + return DocumentAppService.FullSearchEnabledAsync(); + } + [HttpGet] [Route("parameters")] public Task GetParametersAsync(GetParametersDocumentInput input) diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml index 9da501c102..68ba541938 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml @@ -147,18 +147,20 @@ -
-
-
-
- -
+ @if (Model.FullSearchEnabled) + { +
+
+
+
+ +
- + +
-
- + } @if (Model.Navigation == null || !Model.Navigation.HasChildItems) { diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs index 5788743784..b5bfbf0a8c 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs @@ -64,6 +64,8 @@ namespace Volo.Docs.Pages.Documents.Project public DocumentParametersDto DocumentPreferences { get; set; } public DocumentRenderParameters UserPreferences { get; set; } = new DocumentRenderParameters(); + + public bool FullSearchEnabled { get; set; } private readonly IDocumentAppService _documentAppService; private readonly IDocumentToHtmlConverterFactory _documentToHtmlConverterFactory; @@ -106,6 +108,7 @@ namespace Volo.Docs.Pages.Documents.Project { DocumentsUrlPrefix = _uiOptions.RoutePrefix; ShowProjectsCombobox = _uiOptions.ShowProjectsCombobox; + FullSearchEnabled = await _documentAppService.FullSearchEnabledAsync(); try { diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml.cs index 531f0201f1..7be8271b0f 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Search.cshtml.cs @@ -41,6 +41,11 @@ namespace Volo.Docs.Pages.Documents public async Task OnGetAsync(string keyword) { + if (!await _documentAppService.FullSearchEnabledAsync()) + { + return RedirectToPage("Index"); + } + KeyWord = keyword; Project = await _projectAppService.GetAsync(ProjectName); From a4fade9ff1bcc8f58490e6affffb28d1db7c3551 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Mon, 9 Mar 2020 09:58:04 +0300 Subject: [PATCH 5/5] DocsDocumentController FullSearchEnabledAsync route kebab case --- .../Volo/Docs/Documents/DocsDocumentController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Documents/DocsDocumentController.cs b/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Documents/DocsDocumentController.cs index a2e4017dc1..d8d68ec0e8 100644 --- a/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Documents/DocsDocumentController.cs +++ b/modules/docs/src/Volo.Docs.HttpApi/Volo/Docs/Documents/DocsDocumentController.cs @@ -55,7 +55,7 @@ namespace Volo.Docs.Documents } [HttpGet] - [Route("fullsearchenabled")] + [Route("full-search-enabled")] public Task FullSearchEnabledAsync() { return DocumentAppService.FullSearchEnabledAsync();