diff --git a/Oqtane.Client/Modules/Admin/Jobs/Index.razor b/Oqtane.Client/Modules/Admin/Jobs/Index.razor index 81c36430..8c2dc8fe 100644 --- a/Oqtane.Client/Modules/Admin/Jobs/Index.razor +++ b/Oqtane.Client/Modules/Admin/Jobs/Index.razor @@ -152,7 +152,8 @@ else private async Task Refresh() { + ShowProgressIndicator(); await GetJobs(); - StateHasChanged(); + HideProgressIndicator(); } } diff --git a/Oqtane.Client/Modules/Admin/Jobs/Log.razor b/Oqtane.Client/Modules/Admin/Jobs/Log.razor index e82ea9ae..7dbc6a3f 100644 --- a/Oqtane.Client/Modules/Admin/Jobs/Log.razor +++ b/Oqtane.Client/Modules/Admin/Jobs/Log.razor @@ -78,7 +78,8 @@ else private async Task Refresh() { + ShowProgressIndicator(); await GetJobLogs(); - StateHasChanged(); + HideProgressIndicator(); } } diff --git a/Oqtane.Client/Modules/Admin/Search/Index.razor b/Oqtane.Client/Modules/Admin/Search/Index.razor index c76a594e..8a32ff22 100644 --- a/Oqtane.Client/Modules/Admin/Search/Index.razor +++ b/Oqtane.Client/Modules/Admin/Search/Index.razor @@ -53,35 +53,36 @@

+

@code { public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin; private string _searchProvider; - private string _enabled; - private string _lastIndexedOn; - private string _ignorePages; - private string _ignoreEntities; - private string _minimumWordLength; - private string _ignoreWords; + private string _enabled = "True"; + private string _lastIndexedOn = ""; + private string _ignorePages = ""; + private string _ignoreEntities = ""; + private string _minimumWordLength = "3"; + private string _ignoreWords = "the,be,to,of,and,a,i,in,that,have,it,for,not,on,with,he,as,you,do,at,this,but,his,by,from,they,we,say,her,she,or,an,will,my,one,all,would,there,their,what,so,up,out,if,about,who,get,which,go,me,when,make,can,like,time,no,just,him,know,take,people,into,year,your,good,some,could,them,see,other,than,then,now,look,only,come,its,over,think,also,back,after,use,two,how,our,work,first,well,way,even,new,want,because,any,these,give,day,most,us"; - protected override async Task OnInitializedAsync() - { + protected override async Task OnInitializedAsync() + { var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); _searchProvider = SettingService.GetSetting(settings, "Search_SearchProvider", Constants.DefaultSearchProviderName); - _enabled = SettingService.GetSetting(settings, "Search_Enabled", "True"); - _lastIndexedOn = SettingService.GetSetting(settings, "Search_LastIndexedOn", ""); - _ignorePages = SettingService.GetSetting(settings, "Search_IgnorePages", ""); - _ignoreEntities = SettingService.GetSetting(settings, "Search_IgnoreEntities", ""); - _minimumWordLength = SettingService.GetSetting(settings, "Search_MininumWordLength", "3"); - _ignoreWords = SettingService.GetSetting(settings, "Search_IgnoreWords", ""); + _enabled = SettingService.GetSetting(settings, "Search_Enabled", _enabled); + _lastIndexedOn = SettingService.GetSetting(settings, "Search_LastIndexedOn", _lastIndexedOn); + _ignorePages = SettingService.GetSetting(settings, "Search_IgnorePages", _ignorePages); + _ignoreEntities = SettingService.GetSetting(settings, "Search_IgnoreEntities", _ignoreEntities); + _minimumWordLength = SettingService.GetSetting(settings, "Search_MininumWordLength", _minimumWordLength); + _ignoreWords = SettingService.GetSetting(settings, "Search_IgnoreWords", _ignoreWords); } - private async Task Save() - { - try - { + private async Task Save() + { + try + { var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); settings = SettingService.SetSetting(settings, "Search_SearchProvider", _searchProvider); settings = SettingService.SetSetting(settings, "Search_Enabled", _enabled, true); @@ -93,10 +94,28 @@ await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId); AddModuleMessage(Localizer["Success.Save"], MessageType.Success); } - catch (Exception ex) - { + catch (Exception ex) + { await logger.LogError(ex, "Error Saving Search Settings {Error}", ex.Message); AddModuleMessage(Localizer["Error.Save"], MessageType.Error); } - } + } + + private async Task Reindex() + { + try + { + _lastIndexedOn = DateTime.MinValue.ToString(); + var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); + settings = SettingService.SetSetting(settings, "Search_LastIndexedOn", _lastIndexedOn, true); + await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId); + AddModuleMessage(Localizer["Message.Reindex"], MessageType.Success); + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Saving Search Settings {Error}", ex.Message); + AddModuleMessage(Localizer["Error.Save"], MessageType.Error); + } + } + } \ No newline at end of file diff --git a/Oqtane.Client/Modules/Admin/SearchResults/Index.razor b/Oqtane.Client/Modules/Admin/SearchResults/Index.razor index 4043761a..e69a0f63 100644 --- a/Oqtane.Client/Modules/Admin/SearchResults/Index.razor +++ b/Oqtane.Client/Modules/Admin/SearchResults/Index.razor @@ -102,7 +102,7 @@ private void Search() { - NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, $"page=1&q={_keywords}")); + NavigationManager.NavigateTo(NavigateUrl(PageState.Page.Path, $"page=1&q={WebUtility.UrlEncode(_keywords)}")); } private async Task PerformSearch() diff --git a/Oqtane.Client/Resources/Modules/Admin/Search/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Search/Index.resx index 0e0ce755..0f8e26f4 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Search/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Search/Index.resx @@ -165,4 +165,16 @@ Search Provider: + + The search index will be rebuilt for this site. Please be patient during the reindexing process. + + + Reindex + + + Reindex + + + Are You Sure You Wish To Reindex Search Content? + \ No newline at end of file diff --git a/Oqtane.Client/Themes/Controls/Theme/Search.razor b/Oqtane.Client/Themes/Controls/Theme/Search.razor index 69270239..0d8ebb51 100644 --- a/Oqtane.Client/Themes/Controls/Theme/Search.razor +++ b/Oqtane.Client/Themes/Controls/Theme/Search.razor @@ -52,7 +52,7 @@ { if (_searchResultsPage != null) { - var url = NavigateUrl(_searchResultsPage.Path, $"q={_keywords}"); + var url = NavigateUrl(_searchResultsPage.Path, $"q={WebUtility.UrlEncode(_keywords)}"); NavigationManager.NavigateTo(url); } } diff --git a/Oqtane.Server/Infrastructure/Jobs/SearchIndexJob.cs b/Oqtane.Server/Infrastructure/Jobs/SearchIndexJob.cs index 75375737..21b28e40 100644 --- a/Oqtane.Server/Infrastructure/Jobs/SearchIndexJob.cs +++ b/Oqtane.Server/Infrastructure/Jobs/SearchIndexJob.cs @@ -186,18 +186,21 @@ namespace Oqtane.Infrastructure if (string.IsNullOrEmpty(searchContent.Title)) { - searchContent.Title = string.Empty; - if (!string.IsNullOrEmpty(pageModule.Title)) - { - searchContent.Title = pageModule.Title; - } - else if (pageModule.Page != null) + if (pageModule.Page != null) { searchContent.Title = !string.IsNullOrEmpty(pageModule.Page.Title) ? pageModule.Page.Title : pageModule.Page.Name; } + else + { + searchContent.Title = pageModule.Title; + } + } + + if (searchContent.Description == null) + { + searchContent.Description = (searchContent.Title != pageModule.Title) ? pageModule.Title : string.Empty; } - if (searchContent.Description == null) { searchContent.Description = string.Empty;} if (searchContent.Body == null) { searchContent.Body = string.Empty; } if (string.IsNullOrEmpty(searchContent.Url)) diff --git a/Oqtane.Server/Modules/Admin/Files/Manager/FileManager.cs b/Oqtane.Server/Modules/Admin/Files/Manager/FileManager.cs index 06cc90e6..96b75879 100644 --- a/Oqtane.Server/Modules/Admin/Files/Manager/FileManager.cs +++ b/Oqtane.Server/Modules/Admin/Files/Manager/FileManager.cs @@ -57,6 +57,7 @@ namespace Oqtane.Modules.Admin.Files.Manager EntityName = EntityNames.File, EntityId = file.FileId.ToString(), Title = path, + Description = "", Body = body, Url = $"{Constants.FileUrl}{folder.Path}{file.Name}", Permissions = $"{EntityNames.Folder}:{folder.FolderId}", diff --git a/Oqtane.Server/Services/SearchService.cs b/Oqtane.Server/Services/SearchService.cs index 47070116..528f48e1 100644 --- a/Oqtane.Server/Services/SearchService.cs +++ b/Oqtane.Server/Services/SearchService.cs @@ -37,12 +37,10 @@ namespace Oqtane.Services var searchProvider = GetSearchProvider(searchQuery.SiteId); var searchResults = await searchProvider.GetSearchResultsAsync(searchQuery); - // security trim results + // security trim results and aggregate by Url var results = searchResults.Where(item => HasViewPermission(item, searchQuery)) - .OrderBy(item => item.Url).ThenByDescending(item => item.Score); - - // aggegrate by Url - results.GroupBy(group => group.Url) + .OrderBy(item => item.Url).ThenByDescending(item => item.Score) + .GroupBy(group => group.Url) .Select(result => new SearchResult { SearchContentId = result.First().SearchContentId, diff --git a/Oqtane.Shared/Models/SearchContent.cs b/Oqtane.Shared/Models/SearchContent.cs index 3f439a77..547b4ad2 100644 --- a/Oqtane.Shared/Models/SearchContent.cs +++ b/Oqtane.Shared/Models/SearchContent.cs @@ -33,10 +33,11 @@ namespace Oqtane.Models public DateTime CreatedOn { get; set; } - public int Count { get; set; } // only populated for queries - public List SearchContentProperties { get; set; } // only used during updates + [NotMapped] + public int Count { get; set; } // only populated for queries + [NotMapped] public bool IsDeleted { get; set; } // only used during updates