diff --git a/Oqtane.Client/Modules/Admin/SearchResults/Index.razor b/Oqtane.Client/Modules/Admin/SearchResults/Index.razor index 21d358b3..b86f8698 100644 --- a/Oqtane.Client/Modules/Admin/SearchResults/Index.razor +++ b/Oqtane.Client/Modules/Admin/SearchResults/Index.razor @@ -37,12 +37,12 @@ if (_searchResults.Results.Any()) { + Format="Grid" + Columns="1" + Toolbar="Bottom" + Parameters="@($"q={_keywords}")"> -
+

@context.Title

@((MarkupString)context.Snippet)

@@ -61,6 +61,7 @@
+ @code { public override string RenderMode => RenderModes.Static; diff --git a/Oqtane.Client/Modules/Admin/SearchResults/ModuleInfo.cs b/Oqtane.Client/Modules/Admin/SearchResults/ModuleInfo.cs deleted file mode 100644 index 7594a524..00000000 --- a/Oqtane.Client/Modules/Admin/SearchResults/ModuleInfo.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Collections.Generic; -using Oqtane.Documentation; -using Oqtane.Models; -using Oqtane.Shared; - -namespace Oqtane.Modules.Admin.SearchResults -{ - [PrivateApi("Mark this as private, since it's not very useful in the public docs")] - public class ModuleInfo : IModule - { - public ModuleDefinition ModuleDefinition => new ModuleDefinition - { - Name = "Search Results", - Description = "Display Search Results", - Version = Constants.Version, - Categories = "Admin", - Resources = new List() - { - new Resource { ResourceType = ResourceType.Stylesheet, Url = "~/Module.css" } - } - }; - } -} diff --git a/Oqtane.Server/Infrastructure/Jobs/SearchIndexJob.cs b/Oqtane.Server/Infrastructure/Jobs/SearchIndexJob.cs index 142f3d3b..8d8e987a 100644 --- a/Oqtane.Server/Infrastructure/Jobs/SearchIndexJob.cs +++ b/Oqtane.Server/Infrastructure/Jobs/SearchIndexJob.cs @@ -58,7 +58,6 @@ namespace Oqtane.Infrastructure var currentTime = DateTime.UtcNow; var lastIndexedOn = Convert.ToDateTime(siteSettings.GetValue(SearchLastIndexedOnSetting, DateTime.MinValue.ToString())); - log += $"Index Date: {lastIndexedOn}
"; var ignorePaths = siteSettings.GetValue(SearchIgnorePathsSetting, "").Split(','); var ignoreEntities = siteSettings.GetValue(SearchIgnoreEntitiesSetting, "").Split(','); diff --git a/Oqtane.Server/Providers/DatabaseSearchProvider.cs b/Oqtane.Server/Providers/DatabaseSearchProvider.cs index 96fa1b1f..a2313c59 100644 --- a/Oqtane.Server/Providers/DatabaseSearchProvider.cs +++ b/Oqtane.Server/Providers/DatabaseSearchProvider.cs @@ -129,6 +129,36 @@ namespace Oqtane.Providers return Task.CompletedTask; } + private void CleanSearchContent(SearchContent searchContent) + { + searchContent.Title = GetCleanContent(searchContent.Title); + searchContent.Description = GetCleanContent(searchContent.Description); + searchContent.Body = GetCleanContent(searchContent.Body); + searchContent.AdditionalContent = GetCleanContent(searchContent.AdditionalContent); + } + + private string GetCleanContent(string content) + { + if (string.IsNullOrWhiteSpace(content)) + { + return string.Empty; + } + + content = WebUtility.HtmlDecode(content); + + var page = new HtmlDocument(); + page.LoadHtml(content); + + var phrases = page.DocumentNode.Descendants().Where(i => + i.NodeType == HtmlNodeType.Text && + i.ParentNode.Name != "script" && + i.ParentNode.Name != "style" && + !string.IsNullOrEmpty(i.InnerText.Trim()) + ).Select(i => i.InnerText); + + return string.Join(" ", phrases); + } + private void AnalyzeSearchContent(SearchContent searchContent, Dictionary siteSettings) { var ignoreWords = IgnoreWords.Split(','); @@ -180,14 +210,15 @@ namespace Oqtane.Providers private static Dictionary GetWords(string content, string[] ignoreWords, int minimumWordLength) { - content = FormatText(content); + content = FormatContent(content); var words = new Dictionary(); if (!string.IsNullOrEmpty(content)) { - foreach (var word in content.Split(' ')) + foreach (var term in content.Split(' ')) { + var word = term.ToLower().Trim(); if (word.Length >= minimumWordLength && !ignoreWords.Contains(word)) { if (!words.ContainsKey(word)) @@ -205,48 +236,16 @@ namespace Oqtane.Providers return words; } - private static string FormatText(string text) + private static string FormatContent(string text) { text = HtmlEntity.DeEntitize(text); - foreach (var punctuation in ".?!,;:-_()[]{}'\"/\\".ToCharArray()) + foreach (var punctuation in ".?!,;:_()[]{}'\"/\\".ToCharArray()) { text = text.Replace(punctuation, ' '); } - text = text.Replace(" ", " ").ToLower().Trim(); - return text; } - private void CleanSearchContent(SearchContent searchContent) - { - searchContent.Title = GetCleanContent(searchContent.Title); - searchContent.Description = GetCleanContent(searchContent.Description); - searchContent.Body = GetCleanContent(searchContent.Body); - searchContent.AdditionalContent = GetCleanContent(searchContent.AdditionalContent); - } - - private string GetCleanContent(string content) - { - if (string.IsNullOrWhiteSpace(content)) - { - return string.Empty; - } - - content = WebUtility.HtmlDecode(content); - - var page = new HtmlDocument(); - page.LoadHtml(content); - - var phrases = page.DocumentNode.Descendants().Where(i => - i.NodeType == HtmlNodeType.Text && - i.ParentNode.Name != "script" && - i.ParentNode.Name != "style" && - !string.IsNullOrEmpty(i.InnerText.Trim()) - ).Select(i => i.InnerText); - - return string.Join(" ", phrases); - } - public Task ResetIndex() { _searchContentRepository.DeleteAllSearchContent(); diff --git a/Oqtane.Server/Repository/SearchContentRepository.cs b/Oqtane.Server/Repository/SearchContentRepository.cs index abfcd276..cdc07513 100644 --- a/Oqtane.Server/Repository/SearchContentRepository.cs +++ b/Oqtane.Server/Repository/SearchContentRepository.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Query; using Oqtane.Models; using Oqtane.Shared; @@ -26,9 +27,14 @@ namespace Oqtane.Repository .ThenInclude(w => w.SearchWord) .Where(i => i.SiteId == searchQuery.SiteId); - if (searchQuery.EntityNames != null && searchQuery.EntityNames.Any()) + if (!string.IsNullOrEmpty(searchQuery.IncludeEntities)) { - searchContents = searchContents.Where(i => searchQuery.EntityNames.Contains(i.EntityName)); + searchContents = searchContents.Where(i => searchQuery.IncludeEntities.Split(',', StringSplitOptions.RemoveEmptyEntries).Contains(i.EntityName)); + } + + if (!string.IsNullOrEmpty(searchQuery.ExcludeEntities)) + { + searchContents = searchContents.Where(i => !searchQuery.ExcludeEntities.Split(',', StringSplitOptions.RemoveEmptyEntries).Contains(i.EntityName)); } if (searchQuery.From != DateTime.MinValue) diff --git a/Oqtane.Server/wwwroot/Modules/Oqtane.Modules.Admin.SearchResults/Module.css b/Oqtane.Server/wwwroot/Modules/Oqtane.Modules.Admin.SearchResults/Module.css deleted file mode 100644 index 71194e38..00000000 --- a/Oqtane.Server/wwwroot/Modules/Oqtane.Modules.Admin.SearchResults/Module.css +++ /dev/null @@ -1,3 +0,0 @@ -.search-result-container ul.pagination li label, .search-result-container ul.dropdown-menu li label { - cursor: pointer; -} \ No newline at end of file diff --git a/Oqtane.Shared/Interfaces/ISearchProvider.cs b/Oqtane.Shared/Interfaces/ISearchProvider.cs index 4b9a451d..43981e8d 100644 --- a/Oqtane.Shared/Interfaces/ISearchProvider.cs +++ b/Oqtane.Shared/Interfaces/ISearchProvider.cs @@ -1,7 +1,4 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; using Oqtane.Models; diff --git a/Oqtane.Shared/Models/SearchQuery.cs b/Oqtane.Shared/Models/SearchQuery.cs index 00a83533..d3f8ac0c 100644 --- a/Oqtane.Shared/Models/SearchQuery.cs +++ b/Oqtane.Shared/Models/SearchQuery.cs @@ -12,7 +12,9 @@ namespace Oqtane.Models public string Keywords { get; set; } - public List EntityNames { get; set; } = new List(); + public string IncludeEntities { get; set; } = ""; // comma delimited entities to include + + public string ExcludeEntities { get; set; } = ""; // comma delimited entities to exclude public DateTime From { get; set; } diff --git a/Oqtane.Shared/Shared/SearchUtils.cs b/Oqtane.Shared/Shared/SearchUtils.cs index bf5f5986..553275a5 100644 --- a/Oqtane.Shared/Shared/SearchUtils.cs +++ b/Oqtane.Shared/Shared/SearchUtils.cs @@ -4,13 +4,6 @@ namespace Oqtane.Shared { public sealed class SearchUtils { - private static readonly List _systemPages; - - static SearchUtils() - { - _systemPages = new List { "login", "register", "profile", "404", "search" }; - } - public static List GetKeywords(string keywords) { var keywordsList = new List(); @@ -27,10 +20,5 @@ namespace Oqtane.Shared return keywordsList; } - - public static bool IsSystemPage(Models.Page page) - { - return page.Path.Contains("admin") || _systemPages.Contains(page.Path); - } } }