Bunch of work for containers.

- Ordering and paging on the container mostly hooked up. Paging needs to respect item settings.
- Widget settings looking good but not yet functioning. Also need to add filtering.
- Custom part not yet in place for custom ordering/filtering.

--HG--
branch : dev
This commit is contained in:
Nathan Heskew
2010-11-11 16:15:49 -08:00
parent fb4ab81df5
commit ce128483bc
20 changed files with 199 additions and 73 deletions

View File

@@ -2,8 +2,8 @@
using System.Linq; using System.Linq;
using System.Web.Mvc; using System.Web.Mvc;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.Core.Common.Models; using Orchard.Core.Common.Models;
using Orchard.Core.Containers.Models;
using Orchard.Core.Routable.Models; using Orchard.Core.Routable.Models;
using Orchard.DisplayManagement; using Orchard.DisplayManagement;
using Orchard.Themes; using Orchard.Themes;
@@ -17,10 +17,10 @@ namespace Orchard.Core.Containers.Controllers {
public ItemController(IContentManager contentManager, IContainersPathConstraint containersPathConstraint, IShapeFactory shapeFactory) { public ItemController(IContentManager contentManager, IContainersPathConstraint containersPathConstraint, IShapeFactory shapeFactory) {
_contentManager = contentManager; _contentManager = contentManager;
_containersPathConstraint = containersPathConstraint; _containersPathConstraint = containersPathConstraint;
New = shapeFactory; Shape = shapeFactory;
} }
dynamic New { get; set; } dynamic Shape { get; set; }
[Themed] [Themed]
public ActionResult Display(string path, Pager pager) { public ActionResult Display(string path, Pager pager) {
@@ -42,17 +42,42 @@ namespace Orchard.Core.Containers.Controllers {
throw new ApplicationException("Ambiguous content"); throw new ApplicationException("Ambiguous content");
} }
var containerId = hits.Single().Id; var container = _contentManager.Get(hits.Single().Id);
var items = _contentManager IContentQuery<ContentItem> query = _contentManager
.Query<ContentPart<CommonPartRecord>, CommonPartRecord>(VersionOptions.Published) .Query(VersionOptions.Published)
.Where(x => x.Container.Id == containerId) .Join<CommonPartRecord>().Where(cr => cr.Container.Id == container.Id);
.List();
var itemDisplays = items.Select(item => _contentManager.BuildDisplay(item, "Summary")); var descendingOrder = container.As<ContainerPart>().Record.OrderByDirection == (int) OrderByDirection.Descending;
var list = New.List(); //todo: (heskew) order by custom part properties
list.AddRange(itemDisplays); switch (container.As<ContainerPart>().Record.OrderByProperty) {
case "RoutePart.Title":
query = descendingOrder
? query.OrderByDescending<RoutePartRecord, string>(record => record.Title)
: query.OrderBy<RoutePartRecord, string>(record => record.Title);
break;
case "RoutePart.Slug":
query = descendingOrder
? query.OrderByDescending<RoutePartRecord, string>(record => record.Slug)
: query.OrderBy<RoutePartRecord, string>(record => record.Slug);
break;
default: // "CommonPart.PublishedUtc"
query = descendingOrder
? query.OrderByDescending<CommonPartRecord, DateTime?>(record => record.PublishedUtc)
: query.OrderBy<CommonPartRecord, DateTime?>(record => record.PublishedUtc);
break;
}
return View(list); var pagerShape = Shape.Pager(pager).TotalItemCount(query.Count());
var pageOfItems = query.Slice(pager.GetStartIndex(), pager.PageSize).ToList();
var list = Shape.List();
list.AddRange(pageOfItems.Select(item => _contentManager.BuildDisplay(item, "Summary")));
var viewModel = Shape.ViewModel()
.ContentItems(list)
.Pager(pagerShape);
return View(viewModel);
} }
} }
} }

View File

@@ -0,0 +1,63 @@
using System;
using System.Linq;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.Handlers;
using Orchard.Core.Common.Models;
using Orchard.Core.Containers.Models;
using Orchard.Data;
using Orchard.Localization;
namespace Orchard.Core.Containers.Drivers {
public class ContainerWidgetPartDriver : ContentPartDriver<ContainerWidgetPart> {
private readonly IContentManager _contentManager;
public ContainerWidgetPartDriver(IContentManager contentManager) {
_contentManager = contentManager;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
protected override DriverResult Editor(ContainerWidgetPart part, dynamic shapeHelper) {
return Editor(part, null, shapeHelper);
}
protected override DriverResult Editor(ContainerWidgetPart part, IUpdateModel updater, dynamic shapeHelper) {
return ContentShape(
"Parts_ContainerWidget_Edit",
() => {
if (updater != null)
updater.TryUpdateModel(part, "ContainerSelector", null, null);
var containers = _contentManager.Query<ContainerPart, ContainerPartRecord>(VersionOptions.Latest).List();
var listItems = containers.Count() < 1
? new[] {new SelectListItem {Text = T("(None - create container enabled items first)").Text, Value = "0"}}
: containers.Select(x => new SelectListItem {
Value = Convert.ToString(x.Id),
Text = x.ContentItem.TypeDefinition.DisplayName + ": " + x.As<IRoutableAspect>().Title,
Selected = x.Id == part.Record.ContainerId,
});
part.AvailableContainers = new SelectList(listItems, "Value", "Text", part.Record.ContainerId);
return shapeHelper.EditorTemplate(TemplateName: "ContainerWidget", Model: part, Prefix: "ContainerWidget");
});
}
}
public class ContainerWidgetPartHandler : ContentHandler {
public ContainerWidgetPartHandler(IRepository<ContainerWidgetPartRecord> repository, IOrchardServices orchardServices) {
Filters.Add(StorageFilter.For(repository));
OnInitializing<ContainerWidgetPart>((context, part) => {
part.Record.ContainerId = 0;
part.Record.PageSize = 5;
part.Record.OrderByProperty = part.Is<CommonPart>() ? "CommonPart.PublishedUtc" : "";
part.Record.OrderByDirection = (int)OrderByDirection.Descending;
});
}
}
}

View File

@@ -13,6 +13,13 @@ namespace Orchard.Core.Containers {
.Column<string>("OrderByProperty") .Column<string>("OrderByProperty")
.Column<int>("OrderByDirection")); .Column<int>("OrderByDirection"));
ContentDefinitionManager.AlterTypeDefinition("ContainerWidget",
cfg => cfg
.WithPart("CommonPart")
.WithPart("WidgetPart")
.WithPart("ContainerWidgetPart")
.WithSetting("Stereotype", "Widget"));
ContentDefinitionManager.AlterPartDefinition("ContainerPart", builder => builder.Attachable()); ContentDefinitionManager.AlterPartDefinition("ContainerPart", builder => builder.Attachable());
ContentDefinitionManager.AlterPartDefinition("ContainablePart", builder => builder.Attachable()); ContentDefinitionManager.AlterPartDefinition("ContainablePart", builder => builder.Attachable());

View File

@@ -11,9 +11,4 @@ namespace Orchard.Core.Containers.Models {
public virtual string OrderByProperty { get; set; } public virtual string OrderByProperty { get; set; }
public virtual int OrderByDirection { get; set; } public virtual int OrderByDirection { get; set; }
} }
public enum OrderByDirection {
Ascending,
Descending,
}
} }

View File

@@ -1,15 +0,0 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Records;
namespace Orchard.Core.Containers.Models {
public class ContainerSettingsPart : ContentPart<ContainerSettingsPartRecord> {
}
public class ContainerSettingsPartRecord : ContentPartRecord {
private int _defaultPageSize = 10;
public virtual int DefaultPageSize {
get { return _defaultPageSize; }
set { _defaultPageSize = value; }
}
}
}

View File

@@ -0,0 +1,16 @@
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Records;
namespace Orchard.Core.Containers.Models {
public class ContainerWidgetPart : ContentPart<ContainerWidgetPartRecord> {
public SelectList AvailableContainers { get; set; }
}
public class ContainerWidgetPartRecord : ContentPartRecord {
public virtual int ContainerId { get; set; }
public virtual int PageSize { get; set; }
public virtual string OrderByProperty { get; set; }
public virtual int OrderByDirection { get; set; }
}
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.Core.Containers.Models {
public enum OrderByDirection {
Ascending,
Descending,
}
}

View File

@@ -1,5 +1,6 @@
<Placement> <Placement>
<Place Parts_Containable_Edit="Content:before.3"/> <Place Parts_Containable_Edit="Content:before.3"/>
<Place Parts_Container_Edit="Content:5"/> <Place Parts_Container_Edit="Content:5"/>
<Place Parts_ContainerWidget_Edit="Content:5"/>
<Place Parts_Container_SiteSettings="Content:10"/> <Place Parts_Container_SiteSettings="Content:10"/>
</Placement> </Placement>

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData; using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Builders; using Orchard.ContentManagement.MetaData.Builders;

View File

@@ -1,8 +1,4 @@
using System; using System.Web.Mvc;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Orchard.Core.Containers.ViewModels { namespace Orchard.Core.Containers.ViewModels {
public class ContainableViewModel { public class ContainableViewModel {

View File

@@ -1,5 +1,4 @@
@model Orchard.Core.Containers.ViewModels.ContainableViewModel @model Orchard.Core.Containers.ViewModels.ContainableViewModel
<fieldset> <fieldset>
@Html.LabelFor(m => m.ContainerId, T("Add to")) @Html.LabelFor(m => m.ContainerId, T("Add to"))
@Html.DropDownListFor(m => m.ContainerId, Model.AvailableContainers) @Html.DropDownListFor(m => m.ContainerId, Model.AvailableContainers)

View File

@@ -1,21 +1,27 @@
@model Orchard.Core.Containers.Models.ContainerPart @model Orchard.Core.Containers.Models.ContainerPart
@using Orchard.Core.Containers.Models; @using Orchard.Core.Containers.Models;
<fieldset class="with-checkbox">
<span>
@Html.LabelFor(m => m.Record.PageSize, T("Page Size"))
@Html.EditorFor(m => m.Record.PageSize)
</span>
<span class="checkbox-and-label">
@Html.CheckBoxFor(m => m.Record.Paginated)
<label for="@Html.FieldIdFor( m => m.Record.Paginated)" class="forcheckbox">@T("Show paging controls")</label>
</span>
</fieldset>
<fieldset> <fieldset>
@Html.LabelFor(m => m.Record.OrderByProperty, T("Order By")) @Html.LabelFor(m => m.Record.OrderByProperty, T("Order by"))
@Html.TextBoxFor(m => m.Record.OrderByProperty, new { @class = "textMedium" }) <select id="@Html.FieldIdFor(m => m.Record.OrderByProperty)" name="@Html.FieldNameFor(m => m.Record.OrderByProperty)">
<select id="@Html.FieldIdFor( m => m.Record.OrderByDirection)" name="@Html.FieldIdFor( m => m.Record.OrderByDirection)"> @Html.SelectOption(Model.Record.OrderByProperty, "CommonPart.PublishedUtc", T("Date Published").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "RoutePart.Title", T("Title").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "RoutePart.Slug", T("Slug").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "ContainerCustomPart.Custom1", T("Custom 1").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "ContainerCustomPart.Custom2", T("Custom 2").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "ContainerCustomPart.Custom3", T("Custom 3").Text)
</select>
<select id="@Html.FieldIdFor(m => m.Record.OrderByDirection)" name="@Html.FieldNameFor(m => m.Record.OrderByDirection)">
@Html.SelectOption(Model.Record.OrderByDirection, (int)OrderByDirection.Ascending, T("Ascending").Text) @Html.SelectOption(Model.Record.OrderByDirection, (int)OrderByDirection.Ascending, T("Ascending").Text)
@Html.SelectOption(Model.Record.OrderByDirection, (int)OrderByDirection.Descending, T("Descending").Text) @Html.SelectOption(Model.Record.OrderByDirection, (int)OrderByDirection.Descending, T("Descending").Text)
</select> </select>
<span class="hint">Currently, only ordering by a content part property is supported (e.g. CommonPart.PublishedUtc).</span> </fieldset>
<fieldset class="with-checkbox">
<span>
@Html.LabelFor(m => m.Record.PageSize, T("Page size"))
@Html.TextBoxFor(m => m.Record.PageSize, new { @class = "text text-small" })
</span>
<span class="checkbox-and-label">
@Html.CheckBoxFor(m => m.Record.Paginated)
<label for="@Html.FieldIdFor(m => m.Record.Paginated)" class="forcheckbox">@T("Show paging controls")</label>
</span>
</fieldset> </fieldset>

View File

@@ -0,0 +1,27 @@
@model Orchard.Core.Containers.Models.ContainerWidgetPart
@using Orchard.Core.Containers.Models;
<fieldset>
@Html.LabelFor(m => m.Record.ContainerId, T("Show items from"))
@Html.DropDownListFor(m => m.Record.ContainerId, Model.AvailableContainers)
</fieldset>
<fieldset>
@Html.LabelFor(m => m.Record.OrderByProperty, T("Order by"))
<select id="@Html.FieldIdFor(m => m.Record.OrderByProperty)" name="@Html.FieldNameFor(m => m.Record.OrderByProperty)">
@Html.SelectOption(Model.Record.OrderByProperty, "CommonPart.PublishedUtc", T("Date Published").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "RoutePart.Title", T("Title").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "RoutePart.Slug", T("Slug").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "ContainerCustomPart.Custom1", T("Custom 1").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "ContainerCustomPart.Custom2", T("Custom 2").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "ContainerCustomPart.Custom3", T("Custom 3").Text)
</select>
<select id="@Html.FieldIdFor(m => m.Record.OrderByDirection)" name="@Html.FieldNameFor(m => m.Record.OrderByDirection)">
@Html.SelectOption(Model.Record.OrderByDirection, (int)OrderByDirection.Ascending, T("Ascending").Text)
@Html.SelectOption(Model.Record.OrderByDirection, (int)OrderByDirection.Descending, T("Descending").Text)
</select>
</fieldset>
<fieldset>
<span>
@Html.LabelFor(m => m.Record.PageSize, T("Maximum number of items to display"))
@Html.TextBoxFor(m => m.Record.PageSize, new { @class = "text text-small" })
</span>
</fieldset>

View File

@@ -1 +1,2 @@
@Display(Model) @Display(Model.ContentItems)
@Display(Model.Pager)

View File

@@ -78,12 +78,14 @@
<Compile Include="Common\Drivers\CommonPartDriver.cs" /> <Compile Include="Common\Drivers\CommonPartDriver.cs" />
<Compile Include="Common\Drivers\TextFieldDriver.cs" /> <Compile Include="Common\Drivers\TextFieldDriver.cs" />
<Compile Include="Containers\ContainersPathConstraint.cs" /> <Compile Include="Containers\ContainersPathConstraint.cs" />
<Compile Include="Containers\Drivers\ContainerWidgetPartDriver.cs" />
<Compile Include="Containers\Migrations.cs" /> <Compile Include="Containers\Migrations.cs" />
<Compile Include="Containers\Models\ContainerSettingsPart.cs" />
<Compile Include="Containers\Models\ContainablePart.cs" /> <Compile Include="Containers\Models\ContainablePart.cs" />
<Compile Include="Containers\Models\ContainerPart.cs" /> <Compile Include="Containers\Models\ContainerPart.cs" />
<Compile Include="Common\Shapes.cs" /> <Compile Include="Common\Shapes.cs" />
<Compile Include="Common\Fields\TextField.cs" /> <Compile Include="Common\Fields\TextField.cs" />
<Compile Include="Containers\Models\ContainerWidgetPart.cs" />
<Compile Include="Containers\Models\OrderByDirection.cs" />
<Compile Include="Containers\Routes.cs" /> <Compile Include="Containers\Routes.cs" />
<Compile Include="Containers\Services\ContainersPathConstraintUpdater.cs" /> <Compile Include="Containers\Services\ContainersPathConstraintUpdater.cs" />
<Compile Include="Containers\Settings\ContainerSettings.cs" /> <Compile Include="Containers\Settings\ContainerSettings.cs" />
@@ -398,11 +400,12 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Content> </Content>
<Content Include="Containers\Placement.info" /> <Content Include="Containers\Placement.info" />
<Content Include="Containers\Views\EditorTemplates\Containable.cshtml" /> <Content Include="Containers\Views\EditorTemplates\ContainerWidget.cshtml" />
<Content Include="Containers\Views\EditorTemplates\Container.cshtml" /> <Content Include="Containers\Views\EditorTemplates\Container.cshtml" />
<Content Include="Containers\Views\Item\Display.cshtml" /> <Content Include="Containers\Views\Item\Display.cshtml" />
<Content Include="Containers\Views\DefinitionTemplates\ContainerPartSettings.cshtml" /> <Content Include="Containers\Views\DefinitionTemplates\ContainerPartSettings.cshtml" />
<Content Include="Containers\Views\DefinitionTemplates\ContainerTypePartSettings.cshtml" /> <Content Include="Containers\Views\DefinitionTemplates\ContainerTypePartSettings.cshtml" />
<Content Include="Containers\Views\EditorTemplates\Containable.cshtml" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" /> <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

View File

@@ -13,13 +13,6 @@ namespace Orchard.Lists {
.WithPart("MenuPart") .WithPart("MenuPart")
.Creatable()); .Creatable());
ContentDefinitionManager.AlterTypeDefinition("ListWidget",
cfg => cfg
.WithPart("CommonPart")
.WithPart("WidgetPart")
.WithPart("ContainerPart")
.WithSetting("Stereotype", "Widget"));
return 1; return 1;
} }
} }

View File

@@ -81,7 +81,6 @@ namespace Orchard.Setup.Services {
"Localization", "Localization",
"Routable", "Routable",
"Settings", "Settings",
"XmlRpc",
"Messaging", "Messaging",
"Orchard.Users", "Orchard.Users",
"Orchard.Roles", "Orchard.Roles",

View File

@@ -45,6 +45,7 @@ namespace Orchard.Widgets.Services {
.Where(x => x.ExtensionType == "Theme") .Where(x => x.ExtensionType == "Theme")
.SelectMany(x => x.Zones.Split(',')) .SelectMany(x => x.Zones.Split(','))
.Distinct() .Distinct()
.Select(x => x.Trim())
.ToArray(); .ToArray();
} }

View File

@@ -486,6 +486,9 @@ select, textarea, input.text, input.textMedium, input.text-box {
input.text, input.textMedium, input.text-box { input.text, input.textMedium, input.text-box {
line-height:1.2em; line-height:1.2em;
} }
input.text-small {
width:4em;
}
input.textMedium { input.textMedium {
width:26em; width:26em;
} }

View File

@@ -34,7 +34,8 @@ namespace Orchard.Environment.Features {
} }
public IEnumerable<FeatureDescriptor> GetEnabledFeatures() { public IEnumerable<FeatureDescriptor> GetEnabledFeatures() {
throw new NotImplementedException(); var currentShellDescriptor = _shellDescriptorManager.GetShellDescriptor();
return _extensionManager.EnabledFeatures(currentShellDescriptor);
} }
public void EnableFeatures(IEnumerable<string> featureNames) { public void EnableFeatures(IEnumerable<string> featureNames) {