mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Merge pull request #5177 from sfmskywalker/feature/searchwidget
Search Widget Enhancements
This commit is contained in:
@@ -37,16 +37,18 @@ namespace Orchard.Search.Controllers {
|
||||
|
||||
public ActionResult Index(PagerParameters pagerParameters, string searchText = "") {
|
||||
var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
|
||||
var searchSettingsPart = Services.WorkContext.CurrentSite.As<AdminSearchSettingsPart>();
|
||||
var adminSearchSettingsPart = Services.WorkContext.CurrentSite.As<AdminSearchSettingsPart>();
|
||||
var searchSettingsPart = Services.WorkContext.CurrentSite.As<SearchSettingsPart>();
|
||||
|
||||
IPageOfItems<ISearchHit> searchHits = new PageOfItems<ISearchHit>(new ISearchHit[] { });
|
||||
try {
|
||||
|
||||
searchHits = _searchService.Query(searchText, pager.Page, pager.PageSize,
|
||||
Services.WorkContext.CurrentSite.As<AdminSearchSettingsPart>().FilterCulture,
|
||||
searchSettingsPart.SearchIndex,
|
||||
searchSettingsPart.GetSearchFields(),
|
||||
searchHit => searchHit);
|
||||
searchHits = _searchService.Query(
|
||||
searchText, pager.Page, pager.PageSize,
|
||||
searchSettingsPart.FilterCulture,
|
||||
adminSearchSettingsPart.SearchIndex,
|
||||
searchSettingsPart.GetSearchFields(adminSearchSettingsPart.SearchIndex),
|
||||
searchHit => searchHit);
|
||||
}
|
||||
catch (Exception exception) {
|
||||
Logger.Error(T("Invalid search query: {0}", exception.Message).Text);
|
||||
|
@@ -48,7 +48,7 @@ namespace Orchard.Search.Controllers {
|
||||
var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
|
||||
var searchSettingsPart = Services.WorkContext.CurrentSite.As<SearchSettingsPart>();
|
||||
var searchIndex = searchSettingsPart.SearchIndex;
|
||||
var searchFields = searchSettingsPart.GetSearchFields();
|
||||
var searchFields = searchSettingsPart.GetSearchFields(searchSettingsPart.SearchIndex);
|
||||
var totalCount = 0;
|
||||
var foundIds = new int[0];
|
||||
|
||||
|
@@ -30,6 +30,7 @@ namespace Orchard.Search.Controllers {
|
||||
IContentManager contentManager,
|
||||
ISiteService siteService,
|
||||
IShapeFactory shapeFactory) {
|
||||
|
||||
Services = services;
|
||||
_searchService = searchService;
|
||||
_contentManager = contentManager;
|
||||
@@ -45,23 +46,24 @@ namespace Orchard.Search.Controllers {
|
||||
public ILogger Logger { get; set; }
|
||||
dynamic Shape { get; set; }
|
||||
|
||||
public ActionResult Index(PagerParameters pagerParameters, string q = "") {
|
||||
public ActionResult Index(PagerParameters pagerParameters, string searchIndex = null, string q = "") {
|
||||
var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
|
||||
var searchSettingPart = Services.WorkContext.CurrentSite.As<SearchSettingsPart>();
|
||||
var index = !String.IsNullOrWhiteSpace(searchIndex) ? searchIndex.Trim() : searchSettingPart.SearchIndex;
|
||||
|
||||
if (String.IsNullOrEmpty(searchSettingPart.SearchIndex)) {
|
||||
Services.Notifier.Error(T("Please define a default search index"));
|
||||
if (String.IsNullOrEmpty(index)) {
|
||||
Services.Notifier.Error(T("Please define a default search index."));
|
||||
return HttpNotFound();
|
||||
}
|
||||
|
||||
IPageOfItems<ISearchHit> searchHits = new PageOfItems<ISearchHit>(new ISearchHit[] { });
|
||||
try {
|
||||
|
||||
searchHits = _searchService.Query(q, pager.Page, pager.PageSize,
|
||||
Services.WorkContext.CurrentSite.As<SearchSettingsPart>().FilterCulture,
|
||||
searchSettingPart.SearchIndex,
|
||||
searchSettingPart.GetSearchFields(),
|
||||
searchHit => searchHit);
|
||||
searchHits = _searchService.Query(
|
||||
q, pager.Page, pager.PageSize,
|
||||
Services.WorkContext.CurrentSite.As<SearchSettingsPart>().FilterCulture,
|
||||
index,
|
||||
searchSettingPart.GetSearchFields(index),
|
||||
searchHit => searchHit);
|
||||
} catch(Exception exception) {
|
||||
Logger.Error(T("Invalid search query: {0}", exception.Message).Text);
|
||||
Services.Notifier.Error(T("Invalid search query: {0}", exception.Message));
|
||||
|
@@ -1,12 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using System.Linq;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Indexing;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Search.Models;
|
||||
using Orchard.Search.ViewModels;
|
||||
|
||||
@@ -18,13 +14,8 @@ namespace Orchard.Search.Drivers {
|
||||
|
||||
public AdminSearchSettingsPartDriver(IIndexManager indexManager) {
|
||||
_indexManager = indexManager;
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public Localizer T { get; set; }
|
||||
|
||||
protected override string Prefix { get { return "AdminSearchSettings"; } }
|
||||
|
||||
protected override DriverResult Editor(AdminSearchSettingsPart part, dynamic shapeHelper) {
|
||||
return Editor(part, null, shapeHelper);
|
||||
|
||||
@@ -32,51 +23,19 @@ namespace Orchard.Search.Drivers {
|
||||
|
||||
protected override DriverResult Editor(AdminSearchSettingsPart part, IUpdateModel updater, dynamic shapeHelper) {
|
||||
return ContentShape("Parts_AdminSearch_SiteSettings", () => {
|
||||
var model = new SearchSettingsViewModel();
|
||||
var searchFields = part.SearchFields;
|
||||
var model = new AdminSearchSettingsViewModel {
|
||||
AvailableIndexes = _indexManager.GetSearchIndexProvider().List().ToList(),
|
||||
SelectedIndex = part.SearchIndex
|
||||
};
|
||||
|
||||
if (updater != null) {
|
||||
if (updater.TryUpdateModel(model, Prefix, null, null)) {
|
||||
if (updater.TryUpdateModel(model, Prefix, null, new[] { "AvailableIndexes" })) {
|
||||
part.SearchIndex = model.SelectedIndex;
|
||||
part.SearchFields = model.Entries.ToDictionary(x => x.Index, x => x.Fields.Where(e => e.Selected).Select(e => e.Field).ToArray());
|
||||
part.FilterCulture = model.FilterCulture;
|
||||
}
|
||||
}
|
||||
else if (_indexManager.HasIndexProvider()) {
|
||||
// viewing editor: build model from part
|
||||
model.FilterCulture = part.FilterCulture;
|
||||
model.SelectedIndex = part.SearchIndex;
|
||||
model.Entries = _indexManager.GetSearchIndexProvider().List().Select(x => {
|
||||
var indexSettings = new IndexSettingsEntry {
|
||||
Index = x,
|
||||
Fields = new List<SearchSettingsEntry>()
|
||||
};
|
||||
foreach (var field in _indexManager.GetSearchIndexProvider().GetFields(x)) {
|
||||
indexSettings.Fields.Add(new SearchSettingsEntry { Field = field, Selected = (searchFields.ContainsKey(x) && searchFields[x].Contains(field)) });
|
||||
}
|
||||
|
||||
return indexSettings;
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
|
||||
return shapeHelper.EditorTemplate(TemplateName: "Parts/AdminSearch.SiteSettings", Model: model, Prefix: Prefix);
|
||||
}).OnGroup("admin search");
|
||||
}
|
||||
|
||||
protected override void Exporting(AdminSearchSettingsPart part, ExportContentContext context) {
|
||||
context.Element(part.PartDefinition.Name).Add(new XAttribute("SearchFields", part.Retrieve<string>("SearchFields")));
|
||||
}
|
||||
|
||||
protected override void Importing(AdminSearchSettingsPart part, ImportContentContext context) {
|
||||
var xElement = context.Data.Element(part.PartDefinition.Name);
|
||||
if (xElement == null) return;
|
||||
|
||||
var searchFields = xElement.Attribute("SearchFields");
|
||||
if (searchFields != null) {
|
||||
searchFields.Remove();
|
||||
|
||||
part.Store("SearchFields", searchFields.Value);
|
||||
}
|
||||
}).OnGroup("search");
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,19 +1,49 @@
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using System.Linq;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.Indexing;
|
||||
using Orchard.Search.Models;
|
||||
using Orchard.Search.ViewModels;
|
||||
|
||||
namespace Orchard.Search.Drivers {
|
||||
public class SearchFormPartDriver : ContentPartDriver<SearchFormPart> {
|
||||
private readonly IIndexManager _indexManager;
|
||||
public SearchFormPartDriver(IIndexManager indexManager) {
|
||||
_indexManager = indexManager;
|
||||
}
|
||||
|
||||
protected override DriverResult Display(SearchFormPart part, string displayType, dynamic shapeHelper) {
|
||||
var model = new SearchViewModel();
|
||||
return ContentShape("Parts_Search_SearchForm",
|
||||
() => {
|
||||
var shape = shapeHelper.Parts_Search_SearchForm();
|
||||
shape.ContentPart = part;
|
||||
shape.ViewModel = model;
|
||||
return shape;
|
||||
});
|
||||
return ContentShape("Parts_Search_SearchForm", () => {
|
||||
var shape = shapeHelper.Parts_Search_SearchForm();
|
||||
shape.AvailableIndexes = _indexManager.GetSearchIndexProvider().List().ToList();
|
||||
shape.ContentPart = part;
|
||||
shape.ViewModel = model;
|
||||
return shape;
|
||||
});
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(SearchFormPart part, dynamic shapeHelper) {
|
||||
return Editor(part, null, shapeHelper);
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(SearchFormPart part, IUpdateModel updater, dynamic shapeHelper) {
|
||||
return ContentShape("Parts_Search_SearchForm_Edit", () => {
|
||||
var viewModel = new SearchFormViewModel {
|
||||
OverrideIndex = part.OverrideIndex,
|
||||
AvailableIndexes = _indexManager.GetSearchIndexProvider().List().ToList(),
|
||||
SelectedIndex = part.SelectedIndex
|
||||
};
|
||||
|
||||
if (updater != null) {
|
||||
if (updater.TryUpdateModel(viewModel, Prefix, null, new[] {"AvailableIndexes"})) {
|
||||
part.OverrideIndex = viewModel.OverrideIndex;
|
||||
part.SelectedIndex = viewModel.SelectedIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return shapeHelper.EditorTemplate(TemplateName: "Parts/Search.SearchForm", Model: viewModel, Prefix: Prefix);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@@ -29,35 +29,48 @@ namespace Orchard.Search.Drivers {
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(SearchSettingsPart part, IUpdateModel updater, dynamic shapeHelper) {
|
||||
return ContentShape("Parts_Search_SiteSettings", () => {
|
||||
var model = new SearchSettingsViewModel();
|
||||
var searchFields = part.SearchFields;
|
||||
return Combined(
|
||||
ContentShape("Parts_Search_SiteSettings_Index", () => {
|
||||
var model = new SearchSettingsIndexViewModel {
|
||||
SelectedIndex = part.SearchIndex,
|
||||
AvailableIndexes = _indexManager.GetSearchIndexProvider().List().ToList()
|
||||
};
|
||||
|
||||
if (updater != null) {
|
||||
if (updater.TryUpdateModel(model, Prefix, null, null)) {
|
||||
part.SearchIndex = model.SelectedIndex;
|
||||
part.SearchFields = model.Entries.ToDictionary(x => x.Index, x => x.Fields.Where(e => e.Selected).Select(e => e.Field).ToArray());
|
||||
part.FilterCulture = model.FilterCulture;
|
||||
}
|
||||
}
|
||||
else if (_indexManager.HasIndexProvider()) {
|
||||
model.FilterCulture = part.FilterCulture;
|
||||
model.SelectedIndex = part.SearchIndex;
|
||||
model.Entries = _indexManager.GetSearchIndexProvider().List().Select(x => {
|
||||
var indexSettings = new IndexSettingsEntry {
|
||||
Index = x,
|
||||
Fields = new List<SearchSettingsEntry>()
|
||||
};
|
||||
foreach (var field in _indexManager.GetSearchIndexProvider().GetFields(x)) {
|
||||
indexSettings.Fields.Add(new SearchSettingsEntry {Field = field, Selected = (searchFields.ContainsKey(x) && searchFields[x].Contains(field))});
|
||||
if (updater != null) {
|
||||
if (updater.TryUpdateModel(model, Prefix, null, null)) {
|
||||
part.SearchIndex = model.SelectedIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return indexSettings;
|
||||
}).ToList();
|
||||
}
|
||||
return shapeHelper.EditorTemplate(TemplateName: "Parts/Search.SiteSettings.Index", Model: model, Prefix: Prefix);
|
||||
}).OnGroup("search"),
|
||||
ContentShape("Parts_Search_SiteSettings_Fields", () => {
|
||||
var model = new SearchSettingsFieldsViewModel();
|
||||
var searchFields = part.SearchFields;
|
||||
|
||||
return shapeHelper.EditorTemplate(TemplateName: "Parts/Search.SiteSettings", Model: model, Prefix: Prefix);
|
||||
}).OnGroup("search");
|
||||
if (updater != null) {
|
||||
if (updater.TryUpdateModel(model, Prefix, null, null)) {
|
||||
part.SearchFields = model.Entries.ToDictionary(x => x.Index, x => x.Fields.Where(e => e.Selected).Select(e => e.Field).ToArray());
|
||||
part.FilterCulture = model.FilterCulture;
|
||||
}
|
||||
}
|
||||
else if (_indexManager.HasIndexProvider()) {
|
||||
model.FilterCulture = part.FilterCulture;
|
||||
model.Entries = _indexManager.GetSearchIndexProvider().List().Select(x => {
|
||||
var indexSettings = new IndexSettingsEntry {
|
||||
Index = x,
|
||||
Fields = new List<SearchSettingsEntry>()
|
||||
};
|
||||
foreach (var field in _indexManager.GetSearchIndexProvider().GetFields(x)) {
|
||||
indexSettings.Fields.Add(new SearchSettingsEntry { Field = field, Selected = (searchFields.ContainsKey(x) && searchFields[x].Contains(field)) });
|
||||
}
|
||||
|
||||
return indexSettings;
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
return shapeHelper.EditorTemplate(TemplateName: "Parts/Search.SiteSettings.Fields", Model: model, Prefix: Prefix);
|
||||
}).OnGroup("search"));
|
||||
}
|
||||
|
||||
protected override void Exporting(SearchSettingsPart part, ExportContentContext context) {
|
||||
|
@@ -18,7 +18,7 @@ namespace Orchard.Search.Handlers {
|
||||
if (context.ContentItem.ContentType != "Site")
|
||||
return;
|
||||
base.GetItemMetadata(context);
|
||||
context.Metadata.EditorGroupInfo.Add(new GroupInfo(T("Admin Search")));
|
||||
context.Metadata.EditorGroupInfo.Add(new GroupInfo(T("Search")));
|
||||
}
|
||||
}
|
||||
}
|
@@ -28,12 +28,8 @@ namespace Orchard.Search.Helpers {
|
||||
return data;
|
||||
}
|
||||
|
||||
public static string[] GetSearchFields(this AdminSearchSettingsPart part) {
|
||||
return part.SearchFields.ContainsKey(part.SearchIndex) ? part.SearchFields[part.SearchIndex] : new string[0];
|
||||
}
|
||||
|
||||
public static string[] GetSearchFields(this SearchSettingsPart part) {
|
||||
return part.SearchFields.ContainsKey(part.SearchIndex) ? part.SearchFields[part.SearchIndex] : new string[0];
|
||||
public static string[] GetSearchFields(this SearchSettingsPart part, string index) {
|
||||
return part.SearchFields.ContainsKey(index) ? part.SearchFields[index] : new string[0];
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,27 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Search.Helpers;
|
||||
|
||||
namespace Orchard.Search.Models {
|
||||
[OrchardFeature("Orchard.Search.Content")]
|
||||
public class AdminSearchSettingsPart : ContentPart {
|
||||
public IDictionary<string, string[]> SearchFields {
|
||||
get {
|
||||
var data = Retrieve<string>("SearchFields") ?? "Admin:body,title";
|
||||
return SearchSettingsHelper.DeserializeSearchFields(data);
|
||||
}
|
||||
set {
|
||||
var data = SearchSettingsHelper.SerializeSearchFields(value);
|
||||
Store("SearchFields", data);
|
||||
}
|
||||
}
|
||||
|
||||
public bool FilterCulture {
|
||||
get { return this.Retrieve(x => x.FilterCulture); }
|
||||
set { this.Store(x => x.FilterCulture, value); }
|
||||
}
|
||||
|
||||
|
||||
public string SearchIndex {
|
||||
get { return this.Retrieve(x => x.SearchIndex); }
|
||||
set { this.Store(x => x.SearchIndex, value); }
|
||||
|
@@ -5,5 +5,14 @@ namespace Orchard.Search.Models {
|
||||
/// Content part for the search form widget
|
||||
/// </summary>
|
||||
public class SearchFormPart : ContentPart {
|
||||
public bool OverrideIndex {
|
||||
get { return this.Retrieve(x => x.OverrideIndex); }
|
||||
set { this.Store(x => x.OverrideIndex, value); }
|
||||
}
|
||||
|
||||
public string SelectedIndex {
|
||||
get { return this.Retrieve(x => x.SelectedIndex); }
|
||||
set { this.Store(x => x.SelectedIndex, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -88,16 +88,17 @@
|
||||
<Compile Include="Services\SearchService.cs" />
|
||||
<Compile Include="Settings\ContentPickerFieldEditorEvents.cs" />
|
||||
<Compile Include="Settings\ContentPickerFieldSettings.cs" />
|
||||
<Compile Include="ViewModels\SearchSettingsViewModel.cs" />
|
||||
<Compile Include="ViewModels\AdminSearchSettingsViewModel.cs" />
|
||||
<Compile Include="ViewModels\SearchFormViewModel.cs" />
|
||||
<Compile Include="ViewModels\SearchSettingsIndexViewModel.cs" />
|
||||
<Compile Include="ViewModels\SearchResultViewModel.cs" />
|
||||
<Compile Include="ViewModels\SearchViewModel.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
|
||||
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
|
||||
<Project>{2d1d92bb-4555-4cbe-8d0e-63563d6ce4c6}</Project>
|
||||
<Name>Orchard.Framework</Name>
|
||||
<Private>false</Private>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard.MediaLibrary\Orchard.MediaLibrary.csproj">
|
||||
<Project>{73a7688a-5bd3-4f7e-adfa-ce36c5a10e3b}</Project>
|
||||
@@ -114,7 +115,7 @@
|
||||
<Content Include="Styles\orchard-search-search.css" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\EditorTemplates\Parts\Search.SiteSettings.cshtml" />
|
||||
<Content Include="Views\EditorTemplates\Parts\Search.SiteSettings.Index.cshtml" />
|
||||
<Content Include="Views\Search\Index.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -160,6 +161,12 @@
|
||||
<SubType>Designer</SubType>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\EditorTemplates\Parts\Search.SearchForm.cshtml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\EditorTemplates\Parts\Search.SiteSettings.Fields.cshtml" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
|
@@ -1,11 +1,13 @@
|
||||
<Placement>
|
||||
<Place Parts_AdminSearch_SiteSettings="Content:1"/>
|
||||
<Place Parts_Search_SiteSettings="Content:1"/>
|
||||
<Place Parts_AdminSearch_SiteSettings="Content:2"/>
|
||||
<Place Parts_Search_SiteSettings_Index="Content:1"/>
|
||||
<Place Parts_Search_SiteSettings_Fields="Content:3"/>
|
||||
<Place Parts_Search_SearchForm="Content:1"/>
|
||||
<Place Parts_Search_SearchForm_Edit="Content:1"/>
|
||||
|
||||
<Place
|
||||
Parts_Search_MediaLibrary_Actions="Actions:6"
|
||||
Parts_Search_MediaLibrary_Navigation="Navigation:1"
|
||||
<Place
|
||||
Parts_Search_MediaLibrary_Actions="Actions:6"
|
||||
Parts_Search_MediaLibrary_Navigation="Navigation:1"
|
||||
/>
|
||||
|
||||
|
||||
</Placement>
|
||||
|
@@ -3,7 +3,6 @@ using Orchard.UI.Resources;
|
||||
namespace Orchard.Search {
|
||||
public class ResourceManifest : IResourceManifestProvider {
|
||||
public void BuildManifests(ResourceManifestBuilder builder) {
|
||||
builder.Add().DefineStyle("SearchAdmin").SetUrl("orchard-search-admin.css"); // todo: this does not appear to be used anywhere
|
||||
builder.Add().DefineStyle("Search").SetUrl("orchard-search-search.css");
|
||||
}
|
||||
}
|
||||
|
@@ -13,22 +13,22 @@ namespace Orchard.Search {
|
||||
|
||||
public IEnumerable<RouteDescriptor> GetRoutes() {
|
||||
return new[] {
|
||||
new RouteDescriptor {
|
||||
Priority = 5,
|
||||
Route = new Route(
|
||||
"Search",
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Search"},
|
||||
{"controller", "search"},
|
||||
{"action", "index"}
|
||||
},
|
||||
null,
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Search"}
|
||||
},
|
||||
new MvcRouteHandler())
|
||||
}
|
||||
};
|
||||
new RouteDescriptor {
|
||||
Priority = 5,
|
||||
Route = new Route("Search/{searchIndex}",
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Search"},
|
||||
{"controller", "Search"},
|
||||
{"action", "Index"},
|
||||
{"searchIndex", UrlParameter.Optional}
|
||||
},
|
||||
null,
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Search"}
|
||||
},
|
||||
new MvcRouteHandler())
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,3 +1,4 @@
|
||||
#main button {
|
||||
display:block;
|
||||
.search-indexes > li {
|
||||
float: left;
|
||||
margin: 0 2em 2em 0;
|
||||
}
|
@@ -23,5 +23,4 @@ form.search input {
|
||||
/*Search widget styles. More syles could be added here to target specific zones.*/
|
||||
.widget-search-form {
|
||||
float:right;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Search.ViewModels {
|
||||
public class AdminSearchSettingsViewModel {
|
||||
public AdminSearchSettingsViewModel() {
|
||||
AvailableIndexes = new List<string>();
|
||||
}
|
||||
|
||||
public string SelectedIndex { get; set; }
|
||||
public IList<string> AvailableIndexes { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Search.ViewModels {
|
||||
public class SearchFormViewModel {
|
||||
public bool OverrideIndex { get; set; }
|
||||
public string SelectedIndex { get; set; }
|
||||
public IList<string> AvailableIndexes { get; set; }
|
||||
}
|
||||
}
|
@@ -1,28 +1,35 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Search.ViewModels {
|
||||
public class SearchSettingsViewModel {
|
||||
public SearchSettingsViewModel() {
|
||||
Entries = new List<IndexSettingsEntry>();
|
||||
}
|
||||
|
||||
public string SelectedIndex { get; set; }
|
||||
public IList<IndexSettingsEntry> Entries { get; set; }
|
||||
public bool FilterCulture { get; set; }
|
||||
}
|
||||
|
||||
public class IndexSettingsEntry {
|
||||
public IndexSettingsEntry() {
|
||||
Fields = new List<SearchSettingsEntry>();
|
||||
}
|
||||
|
||||
public string Index { get; set; }
|
||||
public IList<SearchSettingsEntry> Fields { get; set; }
|
||||
}
|
||||
|
||||
public class SearchSettingsEntry {
|
||||
public string Field { get; set; }
|
||||
public bool Selected { get; set; }
|
||||
public int Weight { get; set; }
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.Search.ViewModels {
|
||||
public class SearchSettingsIndexViewModel {
|
||||
public SearchSettingsIndexViewModel() {
|
||||
AvailableIndexes = new List<string>();
|
||||
}
|
||||
public string SelectedIndex { get; set; }
|
||||
public IList<string> AvailableIndexes { get; set; }
|
||||
}
|
||||
|
||||
public class SearchSettingsFieldsViewModel {
|
||||
public SearchSettingsFieldsViewModel() {
|
||||
Entries = new List<IndexSettingsEntry>();
|
||||
}
|
||||
|
||||
public IList<IndexSettingsEntry> Entries { get; set; }
|
||||
public bool FilterCulture { get; set; }
|
||||
}
|
||||
|
||||
public class IndexSettingsEntry {
|
||||
public IndexSettingsEntry() {
|
||||
Fields = new List<SearchSettingsEntry>();
|
||||
}
|
||||
|
||||
public string Index { get; set; }
|
||||
public IList<SearchSettingsEntry> Fields { get; set; }
|
||||
}
|
||||
|
||||
public class SearchSettingsEntry {
|
||||
public string Field { get; set; }
|
||||
public bool Selected { get; set; }
|
||||
public int Weight { get; set; }
|
||||
}
|
||||
}
|
@@ -1,61 +1,12 @@
|
||||
@using Orchard.Search.ViewModels
|
||||
@model SearchSettingsViewModel
|
||||
@model AdminSearchSettingsViewModel
|
||||
@{
|
||||
Script.Require("jQuery");
|
||||
Script.Include("orchard-search-settings.js");
|
||||
var indexOptions = Model.AvailableIndexes.Select(x => new SelectListItem { Text = x, Value = x, Selected = x == Model.SelectedIndex });
|
||||
}
|
||||
<fieldset>
|
||||
<legend>@T("Admin Search")</legend>
|
||||
<div>
|
||||
<label>@T("Indexes")</label>
|
||||
|
||||
@if (Model.Entries != null && Model.Entries.Any()) {
|
||||
if (String.IsNullOrWhiteSpace(Model.SelectedIndex)) {
|
||||
Model.Entries.Insert(0, new IndexSettingsEntry { Index = "" });
|
||||
}
|
||||
|
||||
<select id="selectIndex" name="@Html.NameFor(m => m.SelectedIndex)">
|
||||
@foreach (var modelEntry in Model.Entries) {
|
||||
@Html.SelectOption(Model.SelectedIndex, modelEntry.Index, modelEntry.Index)
|
||||
}
|
||||
</select>
|
||||
<span class="hint">@T("Select which index to use in search queries.")</span>
|
||||
|
||||
<label>@T("Fields")</label>
|
||||
<ul class="search-fields" data-selected-index="@Model.SelectedIndex">
|
||||
@{var entryIndex = 0;}
|
||||
@foreach (var modelEntry in Model.Entries) {
|
||||
@Html.HiddenFor(m => m.Entries[entryIndex].Index)
|
||||
<li data-index="@modelEntry.Index">
|
||||
@if (modelEntry.Fields != null && modelEntry.Fields.Any()) {
|
||||
<ul>
|
||||
@{ var fieldIndex = 0;}
|
||||
@foreach (var fieldEntry in Model.Entries[entryIndex].Fields) {
|
||||
<li>
|
||||
@Html.EditorFor(m => m.Entries[entryIndex].Fields[fieldIndex].Selected)
|
||||
@Html.HiddenFor(m => m.Entries[entryIndex].Fields[fieldIndex].Field)
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Entries[entryIndex].Fields[fieldIndex].Selected)">@Model.Entries[entryIndex].Fields[fieldIndex].Field</label>
|
||||
</li>
|
||||
fieldIndex++;
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
</li>
|
||||
entryIndex++;
|
||||
}
|
||||
</ul>
|
||||
<span class="hint">@T("Check any property which should be used for search queries.")</span>
|
||||
|
||||
}
|
||||
else {
|
||||
<span class="hint">@T("There is currently no index to search from. Please update your index, and check if some indexable content exists.")</span>
|
||||
}
|
||||
<div class="form-group">
|
||||
@Html.LabelFor(m => m.SelectedIndex, T("Admin Index"))
|
||||
@Html.DropDownListFor(m => m.SelectedIndex, indexOptions)
|
||||
@Html.Hint(T("The index to search when used in the dashboard."))
|
||||
</div>
|
||||
<div>
|
||||
<label>@T("Localization")</label>
|
||||
@Html.EditorFor(m => m.FilterCulture)
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.FilterCulture)">@T("Narrow search to current culture only")</label>
|
||||
<span class="hint">@T("If checked, search results will only include content items localized in the current culture of the request.")</span>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
@@ -0,0 +1,19 @@
|
||||
@model Orchard.Search.ViewModels.SearchFormViewModel
|
||||
@{
|
||||
Script.Require("ShapesBase");
|
||||
}
|
||||
@{
|
||||
var indexOptions = Model.AvailableIndexes.Select(x => new SelectListItem { Text = x, Value = x, Selected = x == Model.SelectedIndex });
|
||||
}
|
||||
<fieldset>
|
||||
<div class="form-group">
|
||||
@Html.CheckBoxFor(m => m.OverrideIndex)
|
||||
@Html.LabelFor(m => m.OverrideIndex, T("Override Search Index").Text, new { @class = "forcheckbox" })
|
||||
@Html.Hint(T("Check this if you want to specify a different index for this widget to search."))
|
||||
</div>
|
||||
<div class="form-group" data-controllerid="@Html.FieldIdFor(m => m.OverrideIndex)">
|
||||
@Html.LabelFor(m => m.SelectedIndex, T("Index"))
|
||||
@Html.DropDownListFor(m => m.SelectedIndex, indexOptions)
|
||||
@Html.Hint(T("The index to search."))
|
||||
</div>
|
||||
</fieldset>
|
@@ -0,0 +1,48 @@
|
||||
@using Orchard.Search.ViewModels
|
||||
@model SearchSettingsFieldsViewModel
|
||||
@{
|
||||
Style.Include("orchard-search-admin.css");
|
||||
}
|
||||
<fieldset>
|
||||
<div class="form-group">
|
||||
@if (Model.Entries != null && Model.Entries.Any()) {
|
||||
<label>@T("Fields")</label>
|
||||
<ul class="search-indexes group">
|
||||
@{
|
||||
var indexes = Model.Entries.Select(x => x.Index);
|
||||
var entryIndex = 0;
|
||||
foreach (var index in indexes) {
|
||||
var fieldEntries = Model.Entries.Single(x => x.Index == index).Fields;
|
||||
var entryIndexClosure = entryIndex;
|
||||
@Html.HiddenFor(m => m.Entries[entryIndex].Index)
|
||||
<li>
|
||||
<h3>@index</h3>
|
||||
<ul>
|
||||
@{ var fieldIndex = 0; }
|
||||
@foreach (var fieldEntry in fieldEntries) {
|
||||
var fieldIndexClosure = fieldIndex;
|
||||
<li>
|
||||
@Html.EditorFor(m => m.Entries[entryIndex].Fields[fieldIndex].Selected)
|
||||
@Html.HiddenFor(m => m.Entries[entryIndex].Fields[fieldIndex].Field)
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Entries[entryIndexClosure].Fields[fieldIndexClosure].Selected)">@Model.Entries[entryIndex].Fields[fieldIndex].Field</label>
|
||||
</li>
|
||||
fieldIndex++;
|
||||
}
|
||||
</ul>
|
||||
</li>
|
||||
entryIndex++;
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
<span class="hint">@T("Check any field for each index which should be used for search queries.")</span>
|
||||
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
<label>@T("Localization")</label>
|
||||
@Html.EditorFor(m => m.FilterCulture)
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.FilterCulture)">@T("Narrow search to current culture only")</label>
|
||||
<span class="hint">@T("If checked, search results will only include content items localized in the current culture of the request.")</span>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
@@ -0,0 +1,19 @@
|
||||
@using Orchard.Search.ViewModels
|
||||
@model SearchSettingsIndexViewModel
|
||||
@{
|
||||
var indexOptions = Model.AvailableIndexes.Select(x => new SelectListItem { Text = x, Value = x, Selected = x == Model.SelectedIndex });
|
||||
}
|
||||
<fieldset>
|
||||
<legend>@T("Search")</legend>
|
||||
<div class="form-group">
|
||||
<label>@T("Default Index")</label>
|
||||
@if (Model.AvailableIndexes.Any()) {
|
||||
@Html.LabelFor(m => m.SelectedIndex, T("Index"))
|
||||
@Html.DropDownListFor(m => m.SelectedIndex, indexOptions)
|
||||
@Html.Hint(T("Select which index to use by default in search queries."))
|
||||
}
|
||||
else {
|
||||
<span class="hint">@T("There is currently no index to search from. Please update your index, and check if some indexable content exists.")</span>
|
||||
}
|
||||
</div>
|
||||
</fieldset>
|
@@ -1,61 +0,0 @@
|
||||
@using Orchard.Search.ViewModels
|
||||
@model SearchSettingsViewModel
|
||||
@{
|
||||
Script.Require("jQuery");
|
||||
Script.Include("orchard-search-settings.js");
|
||||
}
|
||||
<fieldset>
|
||||
<legend>@T("Search")</legend>
|
||||
<div>
|
||||
<label>@T("Indexes")</label>
|
||||
|
||||
@if (Model.Entries != null && Model.Entries.Any()) {
|
||||
if (String.IsNullOrWhiteSpace(Model.SelectedIndex)) {
|
||||
Model.Entries.Insert(0, new IndexSettingsEntry { Index = "" });
|
||||
}
|
||||
|
||||
<select id="selectIndex" name="@Html.NameFor(m => m.SelectedIndex)">
|
||||
@foreach (var modelEntry in Model.Entries) {
|
||||
@Html.SelectOption(Model.SelectedIndex, modelEntry.Index, modelEntry.Index)
|
||||
}
|
||||
</select>
|
||||
<span class="hint">@T("Select which index to use in search queries.")</span>
|
||||
|
||||
<label>@T("Fields")</label>
|
||||
<ul class="search-fields" data-selected-index="@Model.SelectedIndex">
|
||||
@{var entryIndex = 0;}
|
||||
@foreach (var modelEntry in Model.Entries) {
|
||||
@Html.HiddenFor(m => m.Entries[entryIndex].Index)
|
||||
<li data-index="@modelEntry.Index">
|
||||
@if (modelEntry.Fields != null && modelEntry.Fields.Any()) {
|
||||
<ul>
|
||||
@{ var fieldIndex = 0;}
|
||||
@foreach (var fieldEntry in Model.Entries[entryIndex].Fields) {
|
||||
<li>
|
||||
@Html.EditorFor(m => m.Entries[entryIndex].Fields[fieldIndex].Selected)
|
||||
@Html.HiddenFor(m => m.Entries[entryIndex].Fields[fieldIndex].Field)
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Entries[entryIndex].Fields[fieldIndex].Selected)">@Model.Entries[entryIndex].Fields[fieldIndex].Field</label>
|
||||
</li>
|
||||
fieldIndex++;
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
</li>
|
||||
entryIndex++;
|
||||
}
|
||||
</ul>
|
||||
<span class="hint">@T("Check any property which should be used for search queries.")</span>
|
||||
|
||||
}
|
||||
else {
|
||||
<span class="hint">@T("There is currently no index to search from. Please update your index, and check if some indexable content exists.")</span>
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
<label>@T("Localization")</label>
|
||||
@Html.EditorFor(m => m.FilterCulture)
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.FilterCulture)">@T("Narrow search to current culture only")</label>
|
||||
<span class="hint">@T("If checked, search results will only include content items localized in the current culture of the request.")</span>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
@@ -1,11 +1,20 @@
|
||||
@using Orchard.Search.ViewModels;
|
||||
|
||||
@using Orchard.ContentManagement
|
||||
@using Orchard.Search.Models
|
||||
@using Orchard.Search.ViewModels;
|
||||
@{
|
||||
Style.Require("Search");
|
||||
}
|
||||
@{
|
||||
var settings = WorkContext.CurrentSite.As<SearchSettingsPart>();
|
||||
var part = (SearchFormPart)Model.ContentPart;
|
||||
var index = part.OverrideIndex && part.SelectedIndex != settings.SearchIndex ? part.SelectedIndex : default(string);
|
||||
var routeValues = new RouteValueDictionary { { "area", "Orchard.Search" } };
|
||||
|
||||
|
||||
@using(Html.BeginForm("index", "search", new { area = "Orchard.Search" }, FormMethod.Get, new { @class = "search-form" })) {
|
||||
if (!String.IsNullOrEmpty(index)) {
|
||||
routeValues.Add("searchIndex", index);
|
||||
}
|
||||
}
|
||||
@using (Html.BeginForm("Index", "Search", routeValues, FormMethod.Get, new RouteValueDictionary { { "class", "search-form" } })) {
|
||||
<fieldset>
|
||||
@Html.TextBox("q", (SearchViewModel)Model.ViewModel.Query)
|
||||
@Html.Hidden("culture", WorkContext.CurrentCulture)
|
||||
|
Reference in New Issue
Block a user