Adding content filters

This commit is contained in:
Sebastien Ros
2014-08-26 10:59:06 -07:00
parent 0c9519a93c
commit 09c2ae76e4
13 changed files with 149 additions and 42 deletions

View File

@@ -22,6 +22,7 @@ using Orchard.UI.Navigation;
using Orchard.UI.Notify; using Orchard.UI.Notify;
using Orchard.Settings; using Orchard.Settings;
using Orchard.Utility.Extensions; using Orchard.Utility.Extensions;
using Orchard.Localization.Services;
namespace Orchard.Core.Contents.Controllers { namespace Orchard.Core.Contents.Controllers {
[ValidateInput(false)] [ValidateInput(false)]
@@ -30,6 +31,8 @@ namespace Orchard.Core.Contents.Controllers {
private readonly IContentDefinitionManager _contentDefinitionManager; private readonly IContentDefinitionManager _contentDefinitionManager;
private readonly ITransactionManager _transactionManager; private readonly ITransactionManager _transactionManager;
private readonly ISiteService _siteService; private readonly ISiteService _siteService;
private readonly ICultureManager _cultureManager;
private readonly ICultureFilter _cultureFilter;
public AdminController( public AdminController(
IOrchardServices orchardServices, IOrchardServices orchardServices,
@@ -37,12 +40,17 @@ namespace Orchard.Core.Contents.Controllers {
IContentDefinitionManager contentDefinitionManager, IContentDefinitionManager contentDefinitionManager,
ITransactionManager transactionManager, ITransactionManager transactionManager,
ISiteService siteService, ISiteService siteService,
IShapeFactory shapeFactory) { IShapeFactory shapeFactory,
ICultureManager cultureManager,
ICultureFilter cultureFilter) {
Services = orchardServices; Services = orchardServices;
_contentManager = contentManager; _contentManager = contentManager;
_contentDefinitionManager = contentDefinitionManager; _contentDefinitionManager = contentDefinitionManager;
_transactionManager = transactionManager; _transactionManager = transactionManager;
_siteService = siteService; _siteService = siteService;
_cultureManager = cultureManager;
_cultureFilter = cultureFilter;
T = NullLocalizer.Instance; T = NullLocalizer.Instance;
Logger = NullLogger.Instance; Logger = NullLogger.Instance;
Shape = shapeFactory; Shape = shapeFactory;
@@ -100,11 +108,17 @@ namespace Orchard.Core.Contents.Controllers {
break; break;
} }
if(!String.IsNullOrWhiteSpace(model.Options.SelectedCulture)) {
query = _cultureFilter.FilterCulture(query, model.Options.SelectedCulture);
}
model.Options.SelectedFilter = model.TypeName; model.Options.SelectedFilter = model.TypeName;
model.Options.FilterOptions = GetListableTypes(false) model.Options.FilterOptions = GetListableTypes(false)
.Select(ctd => new KeyValuePair<string, string>(ctd.Name, ctd.DisplayName)) .Select(ctd => new KeyValuePair<string, string>(ctd.Name, ctd.DisplayName))
.ToList().OrderBy(kvp => kvp.Value); .ToList().OrderBy(kvp => kvp.Value);
model.Options.Cultures = _cultureManager.ListCultures();
var maxPagedCount = _siteService.GetSiteSettings().MaxPagedCount; var maxPagedCount = _siteService.GetSiteSettings().MaxPagedCount;
var pagerShape = Shape.Pager(pager).TotalItemCount(maxPagedCount > 0 ? maxPagedCount : query.Count()); var pagerShape = Shape.Pager(pager).TotalItemCount(maxPagedCount > 0 ? maxPagedCount : query.Count());
var pageOfContentItems = query.Slice(pager.GetStartIndex(), pager.PageSize).ToList(); var pageOfContentItems = query.Slice(pager.GetStartIndex(), pager.PageSize).ToList();
@@ -140,6 +154,7 @@ namespace Orchard.Core.Contents.Controllers {
public ActionResult ListFilterPOST(ContentOptions options) { public ActionResult ListFilterPOST(ContentOptions options) {
var routeValues = ControllerContext.RouteData.Values; var routeValues = ControllerContext.RouteData.Values;
if (options != null) { if (options != null) {
routeValues["Options.SelectedCulture"] = options.SelectedCulture; //todo: don't hard-code the key
routeValues["Options.OrderBy"] = options.OrderBy; //todo: don't hard-code the key routeValues["Options.OrderBy"] = options.OrderBy; //todo: don't hard-code the key
routeValues["Options.ContentsStatus"] = options.ContentsStatus; //todo: don't hard-code the key routeValues["Options.ContentsStatus"] = options.ContentsStatus; //todo: don't hard-code the key
if (GetListableTypes(false).Any(ctd => string.Equals(ctd.Name, options.SelectedFilter, StringComparison.OrdinalIgnoreCase))) { if (GetListableTypes(false).Any(ctd => string.Equals(ctd.Name, options.SelectedFilter, StringComparison.OrdinalIgnoreCase))) {

View File

@@ -35,10 +35,12 @@ namespace Orchard.Core.Contents.ViewModels {
ContentsStatus = ContentsStatus.Latest; ContentsStatus = ContentsStatus.Latest;
} }
public string SelectedFilter { get; set; } public string SelectedFilter { get; set; }
public string SelectedCulture { get; set; }
public IEnumerable<KeyValuePair<string, string>> FilterOptions { get; set; } public IEnumerable<KeyValuePair<string, string>> FilterOptions { get; set; }
public ContentsOrder OrderBy { get; set; } public ContentsOrder OrderBy { get; set; }
public ContentsStatus ContentsStatus { get; set; } public ContentsStatus ContentsStatus { get; set; }
public ContentsBulkAction BulkAction { get; set; } public ContentsBulkAction BulkAction { get; set; }
public IEnumerable<string> Cultures { get; set; }
} }
public enum ContentsOrder { public enum ContentsOrder {

View File

@@ -33,6 +33,13 @@
@Html.SelectOption((string)Model.Options.SelectedFilter, (string)filterOption.Key, (string)filterOption.Value) @Html.SelectOption((string)Model.Options.SelectedFilter, (string)filterOption.Key, (string)filterOption.Value)
} }
</select> </select>
<label for="filterCultures" class="bulk-culture">@T("Culture")</label>
<select id="filterCultures" name="Options.SelectedCulture">
@Html.SelectOption((string)Model.Options.SelectedCulture, "", T("any (show all)").ToString())
@foreach (string culture in Model.Options.Cultures) {
@Html.SelectOption((string)Model.Options.SelectedCulture, culture, System.Globalization.CultureInfo.GetCultureInfo(culture).DisplayName)
}
</select>
<label for="orderResults" class="bulk-order">@T("Ordered by")</label> <label for="orderResults" class="bulk-order">@T("Ordered by")</label>
<select id="orderResults" name="Options.OrderBy"> <select id="orderResults" name="Options.OrderBy">
@Html.SelectOption((ContentsOrder)Model.Options.OrderBy, ContentsOrder.Created, T("recently created").ToString()) @Html.SelectOption((ContentsOrder)Model.Options.OrderBy, ContentsOrder.Created, T("recently created").ToString())

View File

@@ -77,6 +77,7 @@
<Compile Include="Providers\CultureSelectorSelector.cs" /> <Compile Include="Providers\CultureSelectorSelector.cs" />
<Compile Include="Services\AdminDirectionalityFactory.cs" /> <Compile Include="Services\AdminDirectionalityFactory.cs" />
<Compile Include="Services\CultureSelectorFactory.cs" /> <Compile Include="Services\CultureSelectorFactory.cs" />
<Compile Include="Services\LocalizationCultureFilter.cs" />
<Compile Include="Services\DefaultCultureStorageProvider.cs" /> <Compile Include="Services\DefaultCultureStorageProvider.cs" />
<Compile Include="Services\ICultureService.cs" /> <Compile Include="Services\ICultureService.cs" />
<Compile Include="Drivers\LocalizationPartDriver.cs" /> <Compile Include="Drivers\LocalizationPartDriver.cs" />

View File

@@ -0,0 +1,25 @@
using System.Web;
using Orchard.ContentManagement;
using Orchard.Environment.Extensions;
using Orchard.Localization.Models;
namespace Orchard.Localization.Services {
[OrchardSuppressDependency("Orchard.Localization.Services.DefaultCultureFilter")]
public class LocalizationCultureFilter : ICultureFilter {
private readonly ICultureManager _cultureManager;
public LocalizationCultureFilter(ICultureManager cultureManager) {
_cultureManager = cultureManager;
}
public IContentQuery<ContentItem> FilterCulture(IContentQuery<ContentItem> query, string cultureName) {
var culture = _cultureManager.GetCultureByName(cultureName);
if (culture != null) {
return query.Where<LocalizationPartRecord>(x => x.CultureId == culture.Id);
}
return query;
}
}
}

View File

@@ -18,6 +18,7 @@ using Orchard.Widgets.Models;
using Orchard.Widgets.Services; using Orchard.Widgets.Services;
using Orchard.ContentManagement.Aspects; using Orchard.ContentManagement.Aspects;
using Orchard.Core.Contents.Settings; using Orchard.Core.Contents.Settings;
using Orchard.Localization.Services;
namespace Orchard.Widgets.Controllers { namespace Orchard.Widgets.Controllers {
@@ -27,18 +28,21 @@ namespace Orchard.Widgets.Controllers {
private readonly IWidgetsService _widgetsService; private readonly IWidgetsService _widgetsService;
private readonly ISiteThemeService _siteThemeService; private readonly ISiteThemeService _siteThemeService;
private readonly IVirtualPathProvider _virtualPathProvider; private readonly IVirtualPathProvider _virtualPathProvider;
private readonly ICultureManager _cultureManager;
public AdminController( public AdminController(
IOrchardServices services, IOrchardServices services,
IWidgetsService widgetsService, IWidgetsService widgetsService,
IShapeFactory shapeFactory, IShapeFactory shapeFactory,
ISiteThemeService siteThemeService, ISiteThemeService siteThemeService,
IVirtualPathProvider virtualPathProvider) { IVirtualPathProvider virtualPathProvider,
ICultureManager cultureManager) {
Services = services; Services = services;
_widgetsService = widgetsService; _widgetsService = widgetsService;
_siteThemeService = siteThemeService; _siteThemeService = siteThemeService;
_virtualPathProvider = virtualPathProvider; _virtualPathProvider = virtualPathProvider;
_cultureManager = cultureManager;
T = NullLocalizer.Instance; T = NullLocalizer.Instance;
Logger = NullLogger.Instance; Logger = NullLogger.Instance;
@@ -50,7 +54,7 @@ namespace Orchard.Widgets.Controllers {
public ILogger Logger { get; set; } public ILogger Logger { get; set; }
dynamic Shape { get; set; } dynamic Shape { get; set; }
public ActionResult Index(int? layerId) { public ActionResult Index(int? layerId, string culture) {
ExtensionDescriptor currentTheme = _siteThemeService.GetSiteTheme(); ExtensionDescriptor currentTheme = _siteThemeService.GetSiteTheme();
if (currentTheme == null) { if (currentTheme == null) {
Services.Notifier.Error(T("To manage widgets you must have a theme enabled.")); Services.Notifier.Error(T("To manage widgets you must have a theme enabled."));
@@ -79,12 +83,26 @@ namespace Orchard.Widgets.Controllers {
string zonePreviewImagePath = string.Format("{0}/{1}/ThemeZonePreview.png", currentTheme.Location, currentTheme.Id); string zonePreviewImagePath = string.Format("{0}/{1}/ThemeZonePreview.png", currentTheme.Location, currentTheme.Id);
string zonePreviewImage = _virtualPathProvider.FileExists(zonePreviewImagePath) ? zonePreviewImagePath : null; string zonePreviewImage = _virtualPathProvider.FileExists(zonePreviewImagePath) ? zonePreviewImagePath : null;
var widgets = _widgetsService.GetWidgets();
if (!String.IsNullOrWhiteSpace(culture)) {
widgets = widgets.Where(x => {
if(x.Has<ILocalizableAspect>()) {
return String.Equals(x.As<ILocalizableAspect>().Culture, culture, StringComparison.InvariantCultureIgnoreCase);
}
return false;
}).ToList();
}
var viewModel = Shape.ViewModel() var viewModel = Shape.ViewModel()
.CurrentTheme(currentTheme) .CurrentTheme(currentTheme)
.CurrentLayer(currentLayer) .CurrentLayer(currentLayer)
.CurrentCulture(culture)
.Layers(layers) .Layers(layers)
.Widgets(_widgetsService.GetWidgets()) .Widgets(widgets)
.Zones(currentThemesZones) .Zones(currentThemesZones)
.Cultures(_cultureManager.ListCultures())
.OrphanZones(allZones.Except(currentThemesZones)) .OrphanZones(allZones.Except(currentThemesZones))
.OrphanWidgets(_widgetsService.GetOrphanedWidgets()) .OrphanWidgets(_widgetsService.GetOrphanedWidgets())
.ZonePreviewImage(zonePreviewImage); .ZonePreviewImage(zonePreviewImage);

View File

@@ -172,7 +172,7 @@
<Content Include="Views\Admin\ChooseWidget.cshtml" /> <Content Include="Views\Admin\ChooseWidget.cshtml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Views\WidgetLayersControl.cshtml" /> <Content Include="Views\WidgetFiltersControl.cshtml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Views\WidgetPlacement.cshtml" /> <Content Include="Views\WidgetPlacement.cshtml" />

View File

@@ -4,7 +4,7 @@
} }
@Display.WidgetPlacement_Orphans(OrphanWidgets: Model.OrphanWidgets) @Display.WidgetPlacement_Orphans(OrphanWidgets: Model.OrphanWidgets)
<div id="widgets" class="group"> <div id="widgets" class="group">
@Display.WidgetLayersControl(Layers: Model.Layers, CurrentLayer: Model.CurrentLayer) @Display.WidgetFiltersControl(Layers: Model.Layers, CurrentLayer: Model.CurrentLayer, Cultures: Model.Cultures, CurrentCulture: Model.CurrentCulture)
<div id="layout-widgets-placement"> <div id="layout-widgets-placement">
@Display.WidgetPlacement(Widgets: Model.Widgets, Zones: Model.Zones, OrphanZones: Model.OrphanZones, CurrentLayer: Model.CurrentLayer) @Display.WidgetPlacement(Widgets: Model.Widgets, Zones: Model.Zones, OrphanZones: Model.OrphanZones, CurrentLayer: Model.CurrentLayer)
</div> </div>

View File

@@ -1,36 +1,52 @@
@using Orchard.Utility.Extensions; @using Orchard.Utility.Extensions;
@using Orchard.Widgets.Models; @using Orchard.Widgets.Models;
@{ @{
Style.Require("WidgetsAdmin"); Style.Require("WidgetsAdmin");
Script.Require("Switchable").AtFoot(); Script.Require("Switchable").AtFoot();
Style.Require("Switchable"); Style.Require("Switchable");
IEnumerable<LayerPart> layers = Model.Layers; IEnumerable<LayerPart> layers = Model.Layers;
var returnUrl = Request.RawUrl; IEnumerable<string> cultures = Model.Cultures;
} var returnUrl = Request.RawUrl;
<div id="widgets-layers-control" class="widgets-container"> }
@if (layers.Any()) { <div id="widgets-layers-control" class="widgets-container">
using (Html.BeginForm("index", "admin", FormMethod.Get, new {area = "Orchard.Widgets"})) { @if (layers.Any()) {
<fieldset class="bulk-actions-auto"> using (Html.BeginForm("index", "admin", FormMethod.Get, new { area = "Orchard.Widgets" })) {
<label for="layerId">@T("Current Layer:")</label> <fieldset class="bulk-actions-auto">
<select id="layerId" name="layerId"> <label for="layerId">@T("Current Layer:")</label>
@foreach (var layer in layers) { <select id="layerId" name="layerId">
@Html.SelectOption((int)Model.CurrentLayer.Id, (int)layer.Id, (string)layer.Name) @foreach (var layer in layers) {
} @Html.SelectOption((int)Model.CurrentLayer.Id, (int)layer.Id, (string)layer.Name)
</select> }
<button type="submit" class="apply-bulk-actions-auto">@T("Show")</button> </select>
@Html.Link(T("Edit").Text, Url.Action("EditLayer", "Admin", new { area = "Orchard.Widgets", id = Model.CurrentLayer.Id, returnUrl }), new { @class = "button" }) <button type="submit" class="apply-bulk-actions-auto">@T("Show")</button>
</fieldset> @Html.Link(T("Edit").Text, Url.Action("EditLayer", "Admin", new { area = "Orchard.Widgets", id = Model.CurrentLayer.Id, returnUrl }), new { @class = "button" })
} </fieldset>
} }
<div id="widgets-layer-add"> }
@Html.Link(T("Add a new layer...").Text, Url.Action("AddLayer", "Admin", new { area = "Orchard.Widgets", returnUrl })) <div id="widgets-layer-add">
</div> @Html.Link(T("Add a new layer...").Text, Url.Action("AddLayer", "Admin", new { area = "Orchard.Widgets", returnUrl }))
</div>
@if (!String.IsNullOrEmpty(Model.CurrentLayer.Description)) {
<div>
<span class="hint" id="widgets-layer-description">@Model.CurrentLayer.Description</span> @using (Html.BeginForm("index", "admin", FormMethod.Get, new { area = "Orchard.Widgets" })) {
<br /> <fieldset class="bulk-actions-auto">
</div> <label for="culture">@T("Current Culture:")</label>
} <select id="culture" name="culture">
</div> @Html.SelectOption((string)Model.CurrentCulture, "", T("any (show all)").ToString())
@foreach (var culture in cultures) {
@Html.SelectOption((string)Model.CurrentCulture, (string)culture, System.Globalization.CultureInfo.GetCultureInfo(culture).DisplayName)
}
</select>
<button type="submit" class="apply-bulk-actions-auto">@T("Show")</button>
</fieldset>
}
@if (!String.IsNullOrEmpty(Model.CurrentLayer.Description)) {
<div>
<span class="hint" id="widgets-layer-description">@Model.CurrentLayer.Description</span>
<br />
</div>
}
</div>

View File

@@ -623,6 +623,9 @@ legend span {
label.bulk-order { label.bulk-order {
text-transform:lowercase; text-transform:lowercase;
} }
label.bulk-culture {
text-transform:lowercase;
}
label span { label span {
font-weight:normal; font-weight:normal;
} }

View File

@@ -0,0 +1,10 @@
using System.Web;
using Orchard.ContentManagement;
namespace Orchard.Localization.Services {
public class DefaultCultureFilter : ICultureFilter {
public IContentQuery<ContentItem> FilterCulture(IContentQuery<ContentItem> query, string cultureName) {
return query;
}
}
}

View File

@@ -0,0 +1,8 @@
using System.Web;
using Orchard.ContentManagement;
namespace Orchard.Localization.Services {
public interface ICultureFilter : IDependency {
IContentQuery<ContentItem> FilterCulture(IContentQuery<ContentItem> query, string cultureName);
}
}

View File

@@ -275,6 +275,8 @@
<Compile Include="Localization\Services\DefaultLocalizedStringManager.cs" /> <Compile Include="Localization\Services\DefaultLocalizedStringManager.cs" />
<Compile Include="Localization\Services\ICalendarSelector.cs" /> <Compile Include="Localization\Services\ICalendarSelector.cs" />
<Compile Include="Localization\Services\ICalendarManager.cs" /> <Compile Include="Localization\Services\ICalendarManager.cs" />
<Compile Include="Localization\Services\DefaultCultureFilter.cs" />
<Compile Include="Localization\Services\ICultureFilter.cs" />
<Compile Include="Localization\Services\IDateLocalizationServices.cs" /> <Compile Include="Localization\Services\IDateLocalizationServices.cs" />
<Compile Include="Localization\Services\IDateFormatter.cs" /> <Compile Include="Localization\Services\IDateFormatter.cs" />
<Compile Include="Localization\Services\IDateTimeFormatProvider.cs" /> <Compile Include="Localization\Services\IDateTimeFormatProvider.cs" />