Merge pull request #5177 from sfmskywalker/feature/searchwidget

Search Widget Enhancements
This commit is contained in:
Sébastien Ros
2015-04-20 21:20:49 -07:00
25 changed files with 317 additions and 302 deletions

View File

@@ -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);

View File

@@ -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];

View File

@@ -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));

View File

@@ -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");
}
}
}

View File

@@ -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);
});
}
}
}

View File

@@ -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) {

View File

@@ -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")));
}
}
}

View File

@@ -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];
}
}
}

View File

@@ -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); }

View File

@@ -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); }
}
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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");
}
}

View File

@@ -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())
}
};
}
}
}

View File

@@ -1,3 +1,4 @@
#main button {
display:block;
.search-indexes > li {
float: left;
margin: 0 2em 2em 0;
}

View File

@@ -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;
}
}

View File

@@ -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; }
}
}

View File

@@ -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; }
}
}

View File

@@ -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; }
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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)