Implementing media search

This commit is contained in:
Sebastien Ros
2013-09-23 09:52:06 -07:00
parent 790cb94d5b
commit d920b164e0
25 changed files with 383 additions and 93 deletions

View File

@@ -0,0 +1,68 @@
using System;
using System.Linq;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.Environment.Extensions;
using Orchard.Indexing;
using Orchard.MediaLibrary.Models;
using Orchard.MediaLibrary.ViewModels;
using Orchard.Themes;
using Orchard.UI.Admin;
namespace Orchard.Search.Controllers {
[Admin]
[Themed(false)]
[OrchardFeature("Orchard.Search.MediaLibrary")]
public class MediaController : Controller {
private readonly IIndexProvider _indexProvider;
private readonly IContentManager _contentManager;
public MediaController(IIndexProvider indexProvider, IContentManager contentManager) {
_indexProvider = indexProvider;
_contentManager = contentManager;
}
public ActionResult MediaItems(string folderPath, int skip = 0, int count = 0, string order = "created", string mediaType = "", string search = "") {
var builder = _indexProvider.CreateSearchBuilder("Media");
if (!String.IsNullOrEmpty(search)) {
builder.WithField("title", search);
builder.WithField("author", search);
builder.WithField("media-caption", search);
builder.WithField("media-alternatetext", search);
builder.WithField("media-filename", search);
}
if (!String.IsNullOrEmpty(mediaType)) {
builder.WithField("type", mediaType).Mandatory().AsFilter();
}
if (!String.IsNullOrEmpty(folderPath)) {
var path = folderPath.Replace("\\", "/");
builder.WithField("media-folderpath", path.ToLowerInvariant()).AsFilter();
}
builder.SortBy(order);
if (order == "title") {
builder.Ascending();
}
var mediaPartsCount = builder.Count();
var contentItemIds = builder.Slice(skip, count).Search().Select(x => x.ContentItemId).ToArray();
var mediaParts = _contentManager.GetMany<MediaPart>(contentItemIds, VersionOptions.Published, QueryHints.Empty);
var mediaItems = mediaParts.Select(x => new MediaManagerMediaItemViewModel {
MediaPart = x,
Shape = _contentManager.BuildDisplay(x, "Thumbnail")
}).ToList();
var viewModel = new MediaManagerMediaItemsViewModel {
MediaItems = mediaItems,
MediaItemsCount = mediaPartsCount
};
return View(viewModel);
}
}
}

View File

@@ -0,0 +1,15 @@
using Orchard.ContentManagement.Drivers;
using Orchard.Environment.Extensions;
using Orchard.MediaLibrary.Models;
namespace Orchard.Search.Drivers {
[OrchardFeature("Orchard.Search.MediaLibrary")]
public class MediaLibraryExplorerPartDriver : ContentPartDriver<MediaLibraryExplorerPart> {
protected override DriverResult Display(MediaLibraryExplorerPart part, string displayType, dynamic shapeHelper) {
return Combined(
ContentShape("Parts_Search_MediaLibrary_Navigation", () => shapeHelper.Parts_Search_MediaLibrary_Navigation()),
ContentShape("Parts_Search_MediaLibrary_Actions", () => shapeHelper.Parts_Search_MediaLibrary_Actions())
);
}
}
}

View File

@@ -2,6 +2,8 @@
using Orchard.ContentManagement.MetaData;
using Orchard.Data;
using Orchard.Data.Migration;
using Orchard.Environment.Extensions;
using Orchard.Indexing;
using Orchard.Search.Models;
namespace Orchard.Search {
@@ -45,4 +47,26 @@ namespace Orchard.Search {
return 2;
}
}
[OrchardFeature("Orchard.Search.MediaLibrary")]
public class MediaMigration : DataMigrationImpl {
private readonly IIndexManager _indexManager;
public MediaMigration(IIndexManager indexManager) {
_indexManager = indexManager;
}
public int Create() {
_indexManager.GetSearchIndexProvider().CreateIndex("Media");
ContentDefinitionManager.AlterTypeDefinition("Image", cfg => cfg.WithSetting("TypeIndexing.Indexes", "Media"));
ContentDefinitionManager.AlterTypeDefinition("Video", cfg => cfg.WithSetting("TypeIndexing.Indexes", "Media"));
ContentDefinitionManager.AlterTypeDefinition("Document", cfg => cfg.WithSetting("TypeIndexing.Indexes", "Media"));
ContentDefinitionManager.AlterTypeDefinition("Audio", cfg => cfg.WithSetting("TypeIndexing.Indexes", "Media"));
ContentDefinitionManager.AlterTypeDefinition("OEmbed", cfg => cfg.WithSetting("TypeIndexing.Indexes", "Media"));
return 1;
}
}
}

View File

@@ -22,3 +22,8 @@ Features:
Description: Provides a search tab in Content Picker.
Dependencies: Orchard.ContentPicker, Orchard.Search
Category: Search
Orchard.Search.MediaLibrary:
Name: Media Library Search
Description: Provides search menu item in the Media Library explorer.
Dependencies: Orchard.MediaLibrary, Orchard.Search
Category: Search

View File

@@ -62,6 +62,8 @@
<Compile Include="Controllers\ContentPickerController.cs" />
<Compile Include="ContentAdminMenu.cs" />
<Compile Include="Controllers\AdminController.cs" />
<Compile Include="Controllers\MediaController.cs" />
<Compile Include="Drivers\MediaLibraryExplorerPartDriver.cs" />
<Compile Include="Drivers\SearchFormPartDriver.cs" />
<Compile Include="Models\SearchFormPart.cs" />
<Compile Include="ResourceManifest.cs" />
@@ -86,6 +88,10 @@
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
<Name>Orchard.Framework</Name>
</ProjectReference>
<ProjectReference Include="..\Orchard.MediaLibrary\Orchard.MediaLibrary.csproj">
<Project>{73a7688a-5bd3-4f7e-adfa-ce36c5a10e3b}</Project>
<Name>Orchard.MediaLibrary</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Include="Module.txt" />
@@ -126,6 +132,15 @@
<ItemGroup>
<Content Include="Views\ContentPicker\NoIndex.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Parts\Search.MediaLibrary.Actions.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Parts\Search.MediaLibrary.Navigation.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\Media\MediaItems.cshtml" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

View File

@@ -1,4 +1,10 @@
<Placement>
<Place Parts_Search_SiteSettings="Content:1"/>
<Place Parts_Search_SearchForm="Content:1"/>
<Place
Parts_Search_MediaLibrary_Actions="Actions:6"
Parts_Search_MediaLibrary_Navigation="Navigation:1"
/>
</Placement>

View File

@@ -0,0 +1,24 @@
@using Orchard.Utility.Extensions
@model Orchard.MediaLibrary.ViewModels.MediaManagerMediaItemsViewModel
@{
Response.ContentType = "text/json";
@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(
new {
mediaItemsCount = Model.MediaItemsCount,
mediaItems = Model.MediaItems.Select(x => new {
id = x.MediaPart.Id,
contentType = x.MediaPart.ContentItem.ContentType,
contentTypeClass = x.MediaPart.ContentItem.ContentType.HtmlClassify(),
title = x.MediaPart.Title,
alternateText = x.MediaPart.AlternateText,
caption = x.MediaPart.Caption,
resource = x.MediaPart.MediaUrl,
mimeType = x.MediaPart.MimeType,
mimeTypeClass = x.MediaPart.MimeType.HtmlClassify(),
thumbnail = Display(x.Shape).ToString(),
editLink = Url.ItemEditUrl(x.MediaPart)
}).ToArray()
}))
}

View File

@@ -0,0 +1,27 @@
Search <form style="display:inline" data-bind="submit: doSearch"><input data-bind="value: searchText" id="input-media-library-search" type="text" class="text"/></form>
@using (Script.Foot()) {
<script type="text/javascript">
//<![CDATA[
var previous = enhanceViewModel;
enhanceViewModel = function(viewModel) {
previous(viewModel);
viewModel.searchText = ko.observable();
viewModel.doSearch = function () {
var self = viewModel;
self.loadMediaItemsUrl = function (folderPath, skip, count, order, mediaType) {
var searchActionUrl = '@HttpUtility.JavaScriptStringEncode(Url.Action("MediaItems", "Media", new {area = "Orchard.Search"}))';
return searchActionUrl + '?folderPath=' + folderPath + '&skip=' + skip + '&count=' + count + '&order=' + order + '&mediaType=' + mediaType + '&search=' + self.searchText();
};
self.getMediaItems(20);
};
};
//]]>
</script>