#4957: Fixed search settings.

This commit is contained in:
Sipke Schoorstra
2015-04-17 00:46:39 +02:00
parent 792f5162e4
commit 66248a7005
17 changed files with 168 additions and 122 deletions

View File

@@ -25,7 +25,8 @@ namespace Orchard.MediaLibrary.MediaFileName {
}
public override IEnumerable<TemplateViewModel> TypeEditorUpdate(ContentTypeDefinitionBuilder builder, IUpdateModel updateModel) {
if (builder.Current.Settings["Stereotype"] == "Media") {
var settings = builder.Current.Settings;
if (settings.ContainsKey("Stereotype") && settings["Stereotype"] == "Media") {
var model = new MediaFileNameEditorSettings();
if (updateModel.TryUpdateModel(model, "MediaFileNameEditorSettings", null, null)) {
builder.WithSetting("MediaFileNameEditorSettings.ShowFileNameEditor", model.ShowFileNameEditor.ToString());

View File

@@ -7,10 +7,10 @@ using Orchard.Environment.Extensions;
using Orchard.Indexing;
using Orchard.Localization;
using Orchard.Logging;
using Orchard.Search.Helpers;
using Orchard.Search.Models;
using Orchard.Search.Services;
using Orchard.Settings;
using Orchard.Themes;
using Orchard.UI.Navigation;
using Orchard.UI.Notify;
@@ -45,7 +45,7 @@ namespace Orchard.Search.Controllers {
searchHits = _searchService.Query(searchText, pager.Page, pager.PageSize,
Services.WorkContext.CurrentSite.As<AdminSearchSettingsPart>().FilterCulture,
searchSettingsPart.SearchIndex,
searchSettingsPart.SearchedFields,
searchSettingsPart.GetSearchFields(),
searchHit => searchHit);
}
catch (Exception exception) {

View File

@@ -9,6 +9,7 @@ using Orchard.Indexing;
using Orchard.Localization;
using Orchard.Logging;
using Orchard.Mvc;
using Orchard.Search.Helpers;
using Orchard.Search.Models;
using Orchard.Search.Settings;
using Orchard.Settings;
@@ -44,11 +45,12 @@ namespace Orchard.Search.Controllers {
[Themed(false)]
public ActionResult Index(PagerParameters pagerParameters, string part, string field, string searchText = "") {
Pager pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
var searchFields = Services.WorkContext.CurrentSite.As<SearchSettingsPart>().SearchedFields;
int totalCount = 0;
int[] foundIds = new int[0];
var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
var searchSettingsPart = Services.WorkContext.CurrentSite.As<SearchSettingsPart>();
var searchIndex = searchSettingsPart.SearchIndex;
var searchFields = searchSettingsPart.GetSearchFields();
var totalCount = 0;
var foundIds = new int[0];
if (!String.IsNullOrWhiteSpace(searchText)) {
ContentPickerSearchFieldSettings settings = null;
@@ -64,7 +66,7 @@ namespace Orchard.Search.Controllers {
return View("NoIndex");
}
var builder = _indexManager.GetSearchIndexProvider().CreateSearchBuilder(Services.WorkContext.CurrentSite.As<SearchSettingsPart>().SearchIndex);
var builder = _indexManager.GetSearchIndexProvider().CreateSearchBuilder(searchIndex);
try {
builder.Parse(searchFields, searchText);
@@ -107,7 +109,6 @@ namespace Orchard.Search.Controllers {
var pagerShape = Services.New.Pager(pager).TotalItemCount(totalCount);
foreach(IShape item in list.Items) {
item.Metadata.Type = "ContentPicker";
}

View File

@@ -7,6 +7,7 @@ using Orchard.DisplayManagement;
using Orchard.Indexing;
using Orchard.Localization;
using Orchard.Logging;
using Orchard.Search.Helpers;
using Orchard.Search.Models;
using Orchard.Search.Services;
using Orchard.Search.ViewModels;
@@ -59,7 +60,7 @@ namespace Orchard.Search.Controllers {
searchHits = _searchService.Query(q, pager.Page, pager.PageSize,
Services.WorkContext.CurrentSite.As<SearchSettingsPart>().FilterCulture,
searchSettingPart.SearchIndex,
searchSettingPart.SearchedFields,
searchSettingPart.GetSearchFields(),
searchHit => searchHit);
} catch(Exception exception) {
Logger.Error(T("Invalid search query: {0}", exception.Message).Text);

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Orchard.ContentManagement;
@@ -28,20 +27,18 @@ namespace Orchard.Search.Drivers {
protected override DriverResult Editor(AdminSearchSettingsPart part, dynamic shapeHelper) {
return Editor(part, null, shapeHelper);
}
protected override DriverResult Editor(AdminSearchSettingsPart part, IUpdateModel updater, dynamic shapeHelper) {
return ContentShape("Parts_AdminSearch_SiteSettings", () => {
var model = new SearchSettingsViewModel();
String[] searchedFields = part.SearchedFields;
var searchFields = part.SearchFields;
if (updater != null) {
// submitting: rebuild model from form data
if (updater.TryUpdateModel(model, Prefix, null, null)) {
// update part if successful
part.SearchIndex = model.SelectedIndex;
part.SearchedFields = model.Entries.First(e => e.Index == model.SelectedIndex).Fields.Where(e => e.Selected).Select(e => e.Field).ToArray();
part.SearchFields = model.Entries.ToDictionary(x => x.Index, x => x.Fields.Where(e => e.Selected).Select(e => e.Field).ToArray());
part.FilterCulture = model.FilterCulture;
}
}
@@ -55,7 +52,7 @@ namespace Orchard.Search.Drivers {
Fields = new List<SearchSettingsEntry>()
};
foreach (var field in _indexManager.GetSearchIndexProvider().GetFields(x)) {
indexSettings.Fields.Add(new SearchSettingsEntry {Field = field, Selected = (x == part.SearchIndex && searchedFields.Contains(field))});
indexSettings.Fields.Add(new SearchSettingsEntry { Field = field, Selected = (searchFields.ContainsKey(x) && searchFields[x].Contains(field)) });
}
return indexSettings;
@@ -67,18 +64,18 @@ namespace Orchard.Search.Drivers {
}
protected override void Exporting(AdminSearchSettingsPart part, ExportContentContext context) {
context.Element(part.PartDefinition.Name).Add(new XAttribute("SearchedFields", string.Join(",", part.SearchedFields)));
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 searchedFields = xElement.Attribute("SearchedFields");
if (searchedFields != null) {
searchedFields.Remove();
part.SearchedFields = searchedFields.Value.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);
var searchFields = xElement.Attribute("SearchFields");
if (searchFields != null) {
searchFields.Remove();
part.Store("SearchFields", searchFields.Value);
}
}
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Orchard.ContentManagement;
@@ -32,19 +31,16 @@ namespace Orchard.Search.Drivers {
protected override DriverResult Editor(SearchSettingsPart part, IUpdateModel updater, dynamic shapeHelper) {
return ContentShape("Parts_Search_SiteSettings", () => {
var model = new SearchSettingsViewModel();
String[] searchedFields = part.SearchedFields;
var searchFields = part.SearchFields;
if (updater != null) {
// submitting: rebuild model from form data
if (updater.TryUpdateModel(model, Prefix, null, null)) {
// update part if successful
part.SearchIndex = model.SelectedIndex;
part.SearchedFields = model.Entries.First(e => e.Index == model.SelectedIndex).Fields.Where(e => e.Selected).Select(e => e.Field).ToArray();
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 => {
@@ -53,7 +49,7 @@ namespace Orchard.Search.Drivers {
Fields = new List<SearchSettingsEntry>()
};
foreach (var field in _indexManager.GetSearchIndexProvider().GetFields(x)) {
indexSettings.Fields.Add(new SearchSettingsEntry {Field = field, Selected = (x == part.SearchIndex && searchedFields.Contains(field))});
indexSettings.Fields.Add(new SearchSettingsEntry {Field = field, Selected = (searchFields.ContainsKey(x) && searchFields[x].Contains(field))});
}
return indexSettings;
@@ -65,18 +61,18 @@ namespace Orchard.Search.Drivers {
}
protected override void Exporting(SearchSettingsPart part, ExportContentContext context) {
context.Element(part.PartDefinition.Name).Add(new XAttribute("SearchedFields", string.Join(",", part.SearchedFields)));
context.Element(part.PartDefinition.Name).Add(new XAttribute("SearchFields", part.Retrieve<string>("SearchFields")));
}
protected override void Importing(SearchSettingsPart part, ImportContentContext context) {
var xElement = context.Data.Element(part.PartDefinition.Name);
if (xElement == null) return;
var searchedFields = xElement.Attribute("SearchedFields");
if (searchedFields != null) {
searchedFields.Remove();
var searchFields = xElement.Attribute("SearchFields");
if (searchFields != null) {
searchFields.Remove();
part.SearchedFields = searchedFields.Value.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);
part.Store("SearchFields", searchFields.Value);
}
}
}

View File

@@ -1,9 +1,8 @@
using Orchard.ContentManagement;
using Orchard.Localization;
using Orchard.Search.Models;
using Orchard.Data;
using Orchard.ContentManagement.Handlers;
using Orchard.Environment.Extensions;
using Orchard.Localization;
using Orchard.Search.Models;
namespace Orchard.Search.Handlers {
[OrchardFeature("Orchard.Search.Content")]
@@ -11,11 +10,6 @@ namespace Orchard.Search.Handlers {
public AdminSearchSettingsPartHandler() {
T = NullLocalizer.Instance;
Filters.Add(new ActivatingFilter<AdminSearchSettingsPart>("Site"));
OnInitializing<AdminSearchSettingsPart>((context, part) => {
part.FilterCulture = false;
part.SearchedFields = new [] {"body, title"};
});
}
public Localizer T { get; set; }

View File

@@ -1,8 +1,8 @@
using JetBrains.Annotations;
using System.Collections.Generic;
using JetBrains.Annotations;
using Orchard.ContentManagement;
using Orchard.Localization;
using Orchard.Search.Models;
using Orchard.Data;
using Orchard.ContentManagement.Handlers;
namespace Orchard.Search.Handlers {
@@ -11,15 +11,10 @@ namespace Orchard.Search.Handlers {
public SearchSettingsPartHandler() {
T = NullLocalizer.Instance;
Filters.Add(new ActivatingFilter<SearchSettingsPart>("Site"));
OnInitializing<SearchSettingsPart>((context, part) => {
part.FilterCulture = false;
part.SearchedFields = new [] {"body, title"};
});
}
public Localizer T { get; set; }
protected override void GetItemMetadata(GetContentItemMetadataContext context) {
if (context.ContentItem.ContentType != "Site")
return;

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.Search.Models;
namespace Orchard.Search.Helpers {
public static class SearchSettingsHelper {
public static IDictionary<string, string[]> DeserializeSearchFields(string value) {
// Format: "<Index1:Field1,Field2>[|<Index1:Field1,Field2>]".
// Example: "Search:title,body|Documents:filename,title".
var data = value ?? "";
var items = data.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
var dictionary = new Dictionary<string, string[]>();
foreach (var item in items) {
var pair = item.Split(new[] { ':' }, StringSplitOptions.None);
var index = pair[0];
var fields = pair[1].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
dictionary[index] = fields;
}
return dictionary;
}
public static string SerializeSearchFields(IDictionary<string, string[]> value) {
var data = String.Join("|", value.Select(x => String.Format("{0}:{1}", x.Key, String.Join(",", x.Value))));
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];
}
}
}

View File

@@ -1,13 +1,20 @@
using System;
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.Environment.Extensions;
using Orchard.Search.Helpers;
namespace Orchard.Search.Models {
[OrchardFeature("Orchard.Search.Content")]
public class AdminSearchSettingsPart : ContentPart {
public string[] SearchedFields {
get { return (Retrieve<string>("SearchedFields") ?? "").Split(new[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries); }
set { Store("SearchedFields", String.Join(", ", value)); }
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 {

View File

@@ -1,11 +1,18 @@
using System;
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.Search.Helpers;
namespace Orchard.Search.Models {
public class SearchSettingsPart : ContentPart {
public string[] SearchedFields {
get { return (Retrieve<string>("SearchedFields") ?? "").Split(new[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries); }
set { Store("SearchedFields", String.Join(", ", value)); }
public IDictionary<string, string[]> SearchFields {
get {
var data = Retrieve<string>("SearchFields") ?? "Search:body,title";
return SearchSettingsHelper.DeserializeSearchFields(data);
}
set {
var data = SearchSettingsHelper.SerializeSearchFields(value);
Store("SearchFields", data);
}
}
public bool FilterCulture {

View File

@@ -74,6 +74,7 @@
<Compile Include="Drivers\SearchFormPartDriver.cs" />
<Compile Include="Drivers\AdminSearchSettingsPartDriver.cs" />
<Compile Include="Handlers\AdminSearchSettingsPartHandler.cs" />
<Compile Include="Helpers\SearchSettingsHelper.cs" />
<Compile Include="Models\SearchFormPart.cs" />
<Compile Include="Models\AdminSearchSettingsPart.cs" />
<Compile Include="ResourceManifest.cs" />
@@ -107,6 +108,7 @@
<Content Include="Recipes\Search.recipe.xml">
<SubType>Designer</SubType>
</Content>
<Content Include="Scripts\orchard-search-settings.js" />
<Content Include="Styles\orchard-search-admin.css" />
<Content Include="Styles\orchard-search-search.css" />
</ItemGroup>
@@ -152,6 +154,11 @@
<ItemGroup>
<Content Include="Views\EditorTemplates\Parts\AdminSearch.SiteSettings.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Scripts\Web.config">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
</staticContent>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -0,0 +1,11 @@
(function ($) {
var searchFields = $(".search-fields");
var selectedIndex = searchFields.data("selected-index");
$('li[data-index]').hide();
$("li[data-index='" + selectedIndex + "']").show();
$('#selectIndex').change(function () {
$('li[data-index]').hide();
$("li[data-index='" + $(this).val() + "']").show();
});
})(jQuery);

View File

@@ -2,12 +2,20 @@
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; }
}

View File

@@ -2,29 +2,29 @@
@model SearchSettingsViewModel
@{
Script.Require("jQuery");
Script.Include("orchard-search-settings.js");
}
<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>
<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>
<label>@T("Fields")</label>
<ul class="search-fields" data-selected-index="@Model.SelectedIndex">
@{var entryIndex = 0;}
@foreach(var modelEntry in Model.Entries) {
@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()) {
@@ -41,7 +41,7 @@
</ul>
}
</li>
entryIndex++;
entryIndex++;
}
</ul>
<span class="hint">@T("Check any property which should be used for search queries.")</span>
@@ -58,21 +58,4 @@
<span class="hint">@T("If checked, search results will only include content items localized in the current culture of the request.")</span>
</div>
</fieldset>
@using (Script.Foot()) {
<script type="text/javascript">
//<![CDATA[
(function ($) {
$('li[data-index]').hide();
$("li[data-index='@Model.SelectedIndex']").show();
$('#selectIndex').change(function () {
$('li[data-index]').hide();
$("li[data-index='" + $(this).val() + "']").show();
});
})(jQuery);
//]]>
</script>
}
</fieldset>

View File

@@ -2,29 +2,29 @@
@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>
<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>
<label>@T("Fields")</label>
<ul class="search-fields" data-selected-index="@Model.SelectedIndex">
@{var entryIndex = 0;}
@foreach(var modelEntry in Model.Entries) {
@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()) {
@@ -41,7 +41,7 @@
</ul>
}
</li>
entryIndex++;
entryIndex++;
}
</ul>
<span class="hint">@T("Check any property which should be used for search queries.")</span>
@@ -58,21 +58,4 @@
<span class="hint">@T("If checked, search results will only include content items localized in the current culture of the request.")</span>
</div>
</fieldset>
@using (Script.Foot()) {
<script type="text/javascript">
//<![CDATA[
(function ($) {
$('li[data-index]').hide();
$("li[data-index='@Model.SelectedIndex']").show();
$('#selectIndex').change(function () {
$('li[data-index]').hide();
$("li[data-index='" + $(this).val() + "']").show();
});
})(jQuery);
//]]>
</script>
}
</fieldset>