mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-09-23 04:43:35 +08:00
Initial new List Management UI.
--HG-- branch : dev
This commit is contained in:
@@ -1,12 +1,16 @@
|
|||||||
using System.Linq;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Web.Mvc;
|
||||||
using System.Web.Routing;
|
using System.Web.Routing;
|
||||||
using Orchard.ContentManagement;
|
using Orchard.ContentManagement;
|
||||||
|
using Orchard.ContentManagement.Aspects;
|
||||||
using Orchard.ContentManagement.Drivers;
|
using Orchard.ContentManagement.Drivers;
|
||||||
using Orchard.ContentManagement.Handlers;
|
using Orchard.ContentManagement.Handlers;
|
||||||
using Orchard.ContentManagement.MetaData;
|
using Orchard.ContentManagement.MetaData;
|
||||||
using Orchard.Core.Common.Models;
|
using Orchard.Core.Common.Models;
|
||||||
using Orchard.Core.Containers.Models;
|
using Orchard.Core.Containers.Models;
|
||||||
using Orchard.Core.Containers.Settings;
|
using Orchard.Core.Containers.Settings;
|
||||||
|
using Orchard.Core.Containers.ViewModels;
|
||||||
using Orchard.Data;
|
using Orchard.Data;
|
||||||
using Orchard.Localization;
|
using Orchard.Localization;
|
||||||
using Orchard.UI.Notify;
|
using Orchard.UI.Notify;
|
||||||
@@ -42,17 +46,31 @@ namespace Orchard.Core.Containers.Drivers {
|
|||||||
Services.Notifier.Warning(T("There are no content types in the system with a Containable part attached. Consider adding a Containable part to some content type, existing or new, in order to relate items to this (Container enabled) item."));
|
Services.Notifier.Warning(T("There are no content types in the system with a Containable part attached. Consider adding a Containable part to some content type, existing or new, in order to relate items to this (Container enabled) item."));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Editor(part, null, shapeHelper);
|
return Editor(part, (IUpdateModel)null, shapeHelper);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override DriverResult Editor(ContainerPart part, IUpdateModel updater, dynamic shapeHelper) {
|
protected override DriverResult Editor(ContainerPart part, IUpdateModel updater, dynamic shapeHelper) {
|
||||||
return ContentShape(
|
return ContentShape(
|
||||||
"Parts_Container_Edit",
|
"Parts_Container_Edit",
|
||||||
() => {
|
() => {
|
||||||
if (updater != null)
|
var model = new ContainerViewModel { Part = part };
|
||||||
updater.TryUpdateModel(part, "Container", null, null);
|
// todo: is there a non-string comparison way to find ConaintableParts?
|
||||||
|
var containables = _contentDefinitionManager.ListTypeDefinitions().Where(td => td.Parts.Any(p => p.PartDefinition.Name == "ContainablePart")).ToList();
|
||||||
|
var listItems = new[] { new SelectListItem { Text = T("(Any)").Text, Value = "" } }
|
||||||
|
.Concat(containables.Select(x => new SelectListItem {
|
||||||
|
Value = Convert.ToString(x.Name),
|
||||||
|
Text = x.DisplayName,
|
||||||
|
Selected = x.Name == model.Part.Record.ItemContentType,
|
||||||
|
}))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
return shapeHelper.EditorTemplate(TemplateName: "Container", Model: part, Prefix: "Container");
|
model.AvailableContainables = new SelectList(listItems, "Value", "Text", model.Part.Record.ItemContentType);
|
||||||
|
|
||||||
|
if (updater != null) {
|
||||||
|
updater.TryUpdateModel(model, "Container", null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return shapeHelper.EditorTemplate(TemplateName: "Container", Model: model, Prefix: "Container");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,20 +89,5 @@ namespace Orchard.Core.Containers.Drivers {
|
|||||||
part.Record.OrderByDirection = (int)OrderByDirection.Descending;
|
part.Record.OrderByDirection = (int)OrderByDirection.Descending;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void GetItemMetadata(GetContentItemMetadataContext context) {
|
|
||||||
var container = context.ContentItem.As<ContainerPart>();
|
|
||||||
|
|
||||||
if (container == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// containers link to their contents in admin screens
|
|
||||||
context.Metadata.AdminRouteValues = new RouteValueDictionary {
|
|
||||||
{"Area", "Contents"},
|
|
||||||
{"Controller", "Admin"},
|
|
||||||
{"Action", "List"},
|
|
||||||
{"containerId", container.Id}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -45,5 +45,10 @@ namespace Orchard.Core.Containers {
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int UpdateFrom1() {
|
||||||
|
SchemaBuilder.AlterTable("ContainerPartRecord", table => table.AddColumn<string>("ItemContentType"));
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -6,6 +6,7 @@ namespace Orchard.Core.Containers.Models {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class ContainerPartRecord : ContentPartRecord {
|
public class ContainerPartRecord : ContentPartRecord {
|
||||||
|
public virtual string ItemContentType { get; set; }
|
||||||
public virtual bool Paginated { get; set; }
|
public virtual bool Paginated { get; set; }
|
||||||
public virtual int PageSize { get; set; }
|
public virtual int PageSize { get; set; }
|
||||||
public virtual string OrderByProperty { get; set; }
|
public virtual string OrderByProperty { get; set; }
|
||||||
|
@@ -3,7 +3,6 @@
|
|||||||
<!--
|
<!--
|
||||||
Parts_Container_Contained
|
Parts_Container_Contained
|
||||||
Parts_Container_Contained_Summary
|
Parts_Container_Contained_Summary
|
||||||
Parts_Container_Contained_SummaryAdmin
|
|
||||||
-->
|
-->
|
||||||
<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"/>
|
||||||
@@ -11,7 +10,4 @@
|
|||||||
<Place Parts_ContainerWidget_Edit="Content:5"/>
|
<Place Parts_ContainerWidget_Edit="Content:5"/>
|
||||||
<Place Parts_Container_SiteSettings="Content:10"/>
|
<Place Parts_Container_SiteSettings="Content:10"/>
|
||||||
<Place Parts_ContainerWidget="Content"/>
|
<Place Parts_ContainerWidget="Content"/>
|
||||||
<Match DisplayType="SummaryAdmin">
|
|
||||||
<Place Parts_Container_Contained_SummaryAdmin="Actions:10"/>
|
|
||||||
</Match>
|
|
||||||
</Placement>
|
</Placement>
|
||||||
|
@@ -0,0 +1,9 @@
|
|||||||
|
using System.Web.Mvc;
|
||||||
|
using Orchard.Core.Containers.Models;
|
||||||
|
|
||||||
|
namespace Orchard.Core.Containers.ViewModels {
|
||||||
|
public class ContainerViewModel {
|
||||||
|
public ContainerPart Part { get; set; }
|
||||||
|
public SelectList AvailableContainables { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@@ -1,27 +1,31 @@
|
|||||||
@model Orchard.Core.Containers.Models.ContainerPart
|
@model Orchard.Core.Containers.ViewModels.ContainerViewModel
|
||||||
@using Orchard.Core.Containers.Models;
|
@using Orchard.Core.Containers.Models;
|
||||||
<fieldset>
|
<fieldset>
|
||||||
@Html.LabelFor(m => m.Record.OrderByProperty, T("Order by"))
|
@Html.LabelFor(m => m.Part.Record.ItemContentType, T("Contains"))
|
||||||
<select id="@Html.FieldIdFor(m => m.Record.OrderByProperty)" name="@Html.FieldNameFor(m => m.Record.OrderByProperty)">
|
@Html.DropDownListFor(m => m.Part.Record.ItemContentType, Model.AvailableContainables)
|
||||||
@Html.SelectOption(Model.Record.OrderByProperty, "CommonPart.PublishedUtc", T("Date Published").Text)
|
</fieldset>
|
||||||
@Html.SelectOption(Model.Record.OrderByProperty, "RoutePart.Title", T("Title").Text)
|
<fieldset>
|
||||||
@Html.SelectOption(Model.Record.OrderByProperty, "RoutePart.Slug", T("Slug").Text)
|
@Html.LabelFor(m => m.Part.Record.OrderByProperty, T("Order by"))
|
||||||
@Html.SelectOption(Model.Record.OrderByProperty, "CustomPropertiesPart.CustomOne", T("Custom 1").Text)
|
<select id="@Html.FieldIdFor(m => m.Part.Record.OrderByProperty)" name="@Html.FieldNameFor(m => m.Part.Record.OrderByProperty)">
|
||||||
@Html.SelectOption(Model.Record.OrderByProperty, "CustomPropertiesPart.CustomTwo", T("Custom 2").Text)
|
@Html.SelectOption(Model.Part.Record.OrderByProperty, "CommonPart.PublishedUtc", T("Date Published").Text)
|
||||||
@Html.SelectOption(Model.Record.OrderByProperty, "CustomPropertiesPart.CustomThree", T("Custom 3").Text)
|
@Html.SelectOption(Model.Part.Record.OrderByProperty, "RoutePart.Title", T("Title").Text)
|
||||||
|
@Html.SelectOption(Model.Part.Record.OrderByProperty, "RoutePart.Slug", T("Slug").Text)
|
||||||
|
@Html.SelectOption(Model.Part.Record.OrderByProperty, "CustomPropertiesPart.CustomOne", T("Custom 1").Text)
|
||||||
|
@Html.SelectOption(Model.Part.Record.OrderByProperty, "CustomPropertiesPart.CustomTwo", T("Custom 2").Text)
|
||||||
|
@Html.SelectOption(Model.Part.Record.OrderByProperty, "CustomPropertiesPart.CustomThree", T("Custom 3").Text)
|
||||||
</select>
|
</select>
|
||||||
<select id="@Html.FieldIdFor(m => m.Record.OrderByDirection)" name="@Html.FieldNameFor(m => m.Record.OrderByDirection)">
|
<select id="@Html.FieldIdFor(m => m.Part.Record.OrderByDirection)" name="@Html.FieldNameFor(m => m.Part.Record.OrderByDirection)">
|
||||||
@Html.SelectOption(Model.Record.OrderByDirection, (int)OrderByDirection.Ascending, T("Ascending").Text)
|
@Html.SelectOption(Model.Part.Record.OrderByDirection, (int)OrderByDirection.Ascending, T("Ascending").Text)
|
||||||
@Html.SelectOption(Model.Record.OrderByDirection, (int)OrderByDirection.Descending, T("Descending").Text)
|
@Html.SelectOption(Model.Part.Record.OrderByDirection, (int)OrderByDirection.Descending, T("Descending").Text)
|
||||||
</select>
|
</select>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<fieldset class="with-checkbox">
|
<fieldset class="with-checkbox">
|
||||||
<span>
|
<span>
|
||||||
@Html.LabelFor(m => m.Record.PageSize, T("Page size"))
|
@Html.LabelFor(m => m.Part.Record.PageSize, T("Page size"))
|
||||||
@Html.TextBoxFor(m => m.Record.PageSize, new { @class = "text text-small" })
|
@Html.TextBoxFor(m => m.Part.Record.PageSize, new { @class = "text text-small" })
|
||||||
</span>
|
</span>
|
||||||
<span class="checkbox-and-label">
|
<span class="checkbox-and-label">
|
||||||
@Html.CheckBoxFor(m => m.Record.Paginated)
|
@Html.CheckBoxFor(m => m.Part.Record.Paginated)
|
||||||
<label for="@Html.FieldIdFor(m => m.Record.Paginated)" class="forcheckbox">@T("Show paging controls")</label>
|
<label for="@Html.FieldIdFor(m => m.Part.Record.Paginated)" class="forcheckbox">@T("Show paging controls")</label>
|
||||||
</span>
|
</span>
|
||||||
</fieldset>
|
</fieldset>
|
@@ -9,6 +9,7 @@ using Orchard.ContentManagement.Aspects;
|
|||||||
using Orchard.ContentManagement.MetaData;
|
using Orchard.ContentManagement.MetaData;
|
||||||
using Orchard.ContentManagement.MetaData.Models;
|
using Orchard.ContentManagement.MetaData.Models;
|
||||||
using Orchard.Core.Common.Models;
|
using Orchard.Core.Common.Models;
|
||||||
|
using Orchard.Core.Containers.Models;
|
||||||
using Orchard.Core.Contents.Settings;
|
using Orchard.Core.Contents.Settings;
|
||||||
using Orchard.Core.Contents.ViewModels;
|
using Orchard.Core.Contents.ViewModels;
|
||||||
using Orchard.Data;
|
using Orchard.Data;
|
||||||
@@ -52,10 +53,8 @@ namespace Orchard.Core.Contents.Controllers {
|
|||||||
|
|
||||||
public ActionResult List(ListContentsViewModel model, PagerParameters pagerParameters) {
|
public ActionResult List(ListContentsViewModel model, PagerParameters pagerParameters) {
|
||||||
Pager pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
|
Pager pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
|
||||||
if (model.ContainerId != null && _contentManager.GetLatest((int)model.ContainerId) == null)
|
|
||||||
return HttpNotFound();
|
|
||||||
|
|
||||||
var query = _contentManager.Query(VersionOptions.Latest, GetCreatableTypes().Select(ctd => ctd.Name).ToArray());
|
var query = _contentManager.Query(VersionOptions.Latest, GetCreatableTypes(false).Select(ctd => ctd.Name).ToArray());
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(model.TypeName)) {
|
if (!string.IsNullOrEmpty(model.TypeName)) {
|
||||||
var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(model.TypeName);
|
var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(model.TypeName);
|
||||||
@@ -68,10 +67,6 @@ namespace Orchard.Core.Contents.Controllers {
|
|||||||
query = query.ForType(model.TypeName);
|
query = query.ForType(model.TypeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model.ContainerId != null) {
|
|
||||||
query = query.Join<CommonPartRecord>().Where(cr => cr.Container.Id == model.ContainerId);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (model.Options.OrderBy) {
|
switch (model.Options.OrderBy) {
|
||||||
case ContentsOrder.Modified:
|
case ContentsOrder.Modified:
|
||||||
//query = query.OrderByDescending<ContentPartRecord, int>(ci => ci.ContentItemRecord.Versions.Single(civr => civr.Latest).Id);
|
//query = query.OrderByDescending<ContentPartRecord, int>(ci => ci.ContentItemRecord.Versions.Single(civr => civr.Latest).Id);
|
||||||
@@ -87,7 +82,7 @@ namespace Orchard.Core.Contents.Controllers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model.Options.SelectedFilter = model.TypeName;
|
model.Options.SelectedFilter = model.TypeName;
|
||||||
model.Options.FilterOptions = GetCreatableTypes()
|
model.Options.FilterOptions = GetCreatableTypes(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.Key);
|
.ToList().OrderBy(kvp => kvp.Key);
|
||||||
|
|
||||||
@@ -107,8 +102,8 @@ namespace Orchard.Core.Contents.Controllers {
|
|||||||
return View((object)viewModel);
|
return View((object)viewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<ContentTypeDefinition> GetCreatableTypes() {
|
private IEnumerable<ContentTypeDefinition> GetCreatableTypes(bool andContainable) {
|
||||||
return _contentDefinitionManager.ListTypeDefinitions().Where(ctd => ctd.Settings.GetModel<ContentTypeSettings>().Creatable);
|
return _contentDefinitionManager.ListTypeDefinitions().Where(ctd => ctd.Settings.GetModel<ContentTypeSettings>().Creatable && (!andContainable || ctd.Parts.Any(p => p.PartDefinition.Name == "ContainablePart")) );
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost, ActionName("List")]
|
[HttpPost, ActionName("List")]
|
||||||
@@ -117,7 +112,7 @@ namespace Orchard.Core.Contents.Controllers {
|
|||||||
var routeValues = ControllerContext.RouteData.Values;
|
var routeValues = ControllerContext.RouteData.Values;
|
||||||
if (options != null) {
|
if (options != null) {
|
||||||
routeValues["Options.OrderBy"] = options.OrderBy; //todo: don't hard-code the key
|
routeValues["Options.OrderBy"] = options.OrderBy; //todo: don't hard-code the key
|
||||||
if (GetCreatableTypes().Any(ctd => string.Equals(ctd.Name, options.SelectedFilter, StringComparison.OrdinalIgnoreCase))) {
|
if (GetCreatableTypes(false).Any(ctd => string.Equals(ctd.Name, options.SelectedFilter, StringComparison.OrdinalIgnoreCase))) {
|
||||||
routeValues["id"] = options.SelectedFilter;
|
routeValues["id"] = options.SelectedFilter;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -177,22 +172,29 @@ namespace Orchard.Core.Contents.Controllers {
|
|||||||
return this.RedirectLocal(returnUrl, () => RedirectToAction("List"));
|
return this.RedirectLocal(returnUrl, () => RedirectToAction("List"));
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionResult CreatableTypeList() {
|
ActionResult CreatableTypeList(int? containerId) {
|
||||||
dynamic viewModel = Shape.ViewModel(ContentTypes: GetCreatableTypes());
|
dynamic viewModel = Shape.ViewModel(ContentTypes: GetCreatableTypes(containerId.HasValue), ContainerId: containerId);
|
||||||
|
|
||||||
// Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
|
// Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
|
||||||
return View("CreatableTypeList", (object)viewModel);
|
return View("CreatableTypeList", (object)viewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ActionResult Create(string id) {
|
public ActionResult Create(string id, int? containerId) {
|
||||||
if (string.IsNullOrEmpty(id))
|
if (string.IsNullOrEmpty(id))
|
||||||
return CreatableTypeList();
|
return CreatableTypeList(containerId);
|
||||||
|
|
||||||
var contentItem = _contentManager.New(id);
|
var contentItem = _contentManager.New(id);
|
||||||
|
|
||||||
if (!Services.Authorizer.Authorize(Permissions.PublishContent, contentItem, T("Cannot create content")))
|
if (!Services.Authorizer.Authorize(Permissions.PublishContent, contentItem, T("Cannot create content")))
|
||||||
return new HttpUnauthorizedResult();
|
return new HttpUnauthorizedResult();
|
||||||
|
|
||||||
|
if (containerId.HasValue && contentItem.Is<ContainablePart>()) {
|
||||||
|
var common = contentItem.As<CommonPart>();
|
||||||
|
if (common != null) {
|
||||||
|
common.Container = _contentManager.Get(containerId.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dynamic model = _contentManager.BuildEditor(contentItem);
|
dynamic model = _contentManager.BuildEditor(contentItem);
|
||||||
// Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
|
// Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
|
||||||
return View((object)model);
|
return View((object)model);
|
||||||
|
@@ -8,7 +8,6 @@ namespace Orchard.Core.Contents.ViewModels {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
public int? ContainerId { get; set; }
|
|
||||||
|
|
||||||
public string TypeName {
|
public string TypeName {
|
||||||
get { return Id; }
|
get { return Id; }
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
@{ Layout.Title = T("Create New Content").ToString(); }
|
@{ Layout.Title = T("Create New Content").ToString(); }
|
||||||
|
|
||||||
@foreach (var type in Model.ContentTypes) {
|
@foreach (var type in Model.ContentTypes) {
|
||||||
<p>@Html.ActionLink((string)type.DisplayName, "Create", new { Area = "Contents", Id = (string)type.Name })</p>
|
<p>@Html.ActionLink((string)type.DisplayName, "Create", new { Area = "Contents", Id = (string)type.Name, ContainerId = Model.ContainerId })</p>
|
||||||
}
|
}
|
@@ -87,6 +87,7 @@
|
|||||||
<Compile Include="Containers\Settings\ContainerSettings.cs" />
|
<Compile Include="Containers\Settings\ContainerSettings.cs" />
|
||||||
<Compile Include="Containers\ViewModels\ContainableViewModel.cs" />
|
<Compile Include="Containers\ViewModels\ContainableViewModel.cs" />
|
||||||
<Compile Include="Containers\ViewModels\ContainerWidgetViewModel.cs" />
|
<Compile Include="Containers\ViewModels\ContainerWidgetViewModel.cs" />
|
||||||
|
<Compile Include="Containers\ViewModels\ContainerViewModel.cs" />
|
||||||
<Compile Include="Contents\Security\AuthorizationEventHandler.cs" />
|
<Compile Include="Contents\Security\AuthorizationEventHandler.cs" />
|
||||||
<Compile Include="Common\Services\BbcodeFilter.cs" />
|
<Compile Include="Common\Services\BbcodeFilter.cs" />
|
||||||
<Compile Include="Common\Services\ICommonService.cs" />
|
<Compile Include="Common\Services\ICommonService.cs" />
|
||||||
@@ -99,7 +100,6 @@
|
|||||||
<Compile Include="Contents\Extensions\MetaDataExtensions.cs" />
|
<Compile Include="Contents\Extensions\MetaDataExtensions.cs" />
|
||||||
<Compile Include="Contents\Handlers\ContentsHandler.cs" />
|
<Compile Include="Contents\Handlers\ContentsHandler.cs" />
|
||||||
<Compile Include="Contents\Permissions.cs" />
|
<Compile Include="Contents\Permissions.cs" />
|
||||||
<Compile Include="Contents\Routes.cs" />
|
|
||||||
<Compile Include="Contents\Settings\ContentTypeSettings.cs" />
|
<Compile Include="Contents\Settings\ContentTypeSettings.cs" />
|
||||||
<Compile Include="Contents\Settings\ContentPartSettings.cs" />
|
<Compile Include="Contents\Settings\ContentPartSettings.cs" />
|
||||||
<Compile Include="Contents\Shapes.cs" />
|
<Compile Include="Contents\Shapes.cs" />
|
||||||
@@ -383,9 +383,6 @@
|
|||||||
<Content Include="Routable\Views\Parts.RoutableTitle_Summary.cshtml" />
|
<Content Include="Routable\Views\Parts.RoutableTitle_Summary.cshtml" />
|
||||||
<Content Include="Routable\Views\Parts.RoutableTitle_SummaryAdmin.cshtml" />
|
<Content Include="Routable\Views\Parts.RoutableTitle_SummaryAdmin.cshtml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Content Include="Containers\Views\Parts.Container.Contained.SummaryAdmin.cshtml" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Shapes\Views\ShapeResult\Display.cshtml" />
|
<Content Include="Shapes\Views\ShapeResult\Display.cshtml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@@ -0,0 +1,269 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Web.Mvc;
|
||||||
|
using Orchard.ContentManagement;
|
||||||
|
using Orchard.ContentManagement.MetaData;
|
||||||
|
using Orchard.ContentManagement.MetaData.Models;
|
||||||
|
using Orchard.Core.Common.Models;
|
||||||
|
using Orchard.Core.Containers.Models;
|
||||||
|
using Orchard.Core.Contents;
|
||||||
|
using Orchard.Core.Contents.Controllers;
|
||||||
|
using Orchard.Core.Contents.Settings;
|
||||||
|
using Orchard.Data;
|
||||||
|
using Orchard.DisplayManagement;
|
||||||
|
using Orchard.DisplayManagement.Shapes;
|
||||||
|
using Orchard.Lists.ViewModels;
|
||||||
|
using Orchard.Localization;
|
||||||
|
using Orchard;
|
||||||
|
using Orchard.Logging;
|
||||||
|
using Orchard.Mvc.Extensions;
|
||||||
|
using Orchard.Settings;
|
||||||
|
using Orchard.UI.Navigation;
|
||||||
|
using Orchard.UI.Notify;
|
||||||
|
|
||||||
|
namespace Lists.Controllers {
|
||||||
|
public class AdminController : Controller {
|
||||||
|
private readonly IContentManager _contentManager;
|
||||||
|
private readonly IContentDefinitionManager _contentDefinitionManager;
|
||||||
|
private readonly ITransactionManager _transactionManager;
|
||||||
|
private readonly ISiteService _siteService;
|
||||||
|
|
||||||
|
public IOrchardServices Services { get; set; }
|
||||||
|
|
||||||
|
public AdminController(
|
||||||
|
IOrchardServices orchardServices,
|
||||||
|
IContentManager contentManager,
|
||||||
|
IContentDefinitionManager contentDefinitionManager,
|
||||||
|
ITransactionManager transactionManager,
|
||||||
|
ISiteService siteService,
|
||||||
|
IShapeFactory shapeFactory) {
|
||||||
|
Services = orchardServices;
|
||||||
|
_contentManager = contentManager;
|
||||||
|
_contentDefinitionManager = contentDefinitionManager;
|
||||||
|
_transactionManager = transactionManager;
|
||||||
|
_siteService = siteService;
|
||||||
|
T = NullLocalizer.Instance;
|
||||||
|
Logger = NullLogger.Instance;
|
||||||
|
Shape = shapeFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Localizer T { get; set; }
|
||||||
|
public ILogger Logger { get; set; }
|
||||||
|
dynamic Shape { get; set; }
|
||||||
|
|
||||||
|
private IEnumerable<ContentTypeDefinition> GetContainableTypes() {
|
||||||
|
return _contentDefinitionManager.ListTypeDefinitions().Where(ctd => ctd.Parts.Any(c => c.PartDefinition.Name == "ContainablePart") && ctd.Settings.GetModel<ContentTypeSettings>().Creatable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActionResult List(ListContentsViewModel model, PagerParameters pagerParameters) {
|
||||||
|
var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
|
||||||
|
var container = _contentManager.GetLatest((int)model.ContainerId);
|
||||||
|
if (container == null) {
|
||||||
|
return HttpNotFound();
|
||||||
|
}
|
||||||
|
var restrictedContentType = container.As<ContainerPart>().Record.ItemContentType;
|
||||||
|
var hasRestriction = !string.IsNullOrEmpty(restrictedContentType);
|
||||||
|
|
||||||
|
var metadata = container.ContentManager.GetItemMetadata(container);
|
||||||
|
model.ContainerDisplayName = metadata.DisplayText;
|
||||||
|
if (string.IsNullOrEmpty(model.ContainerDisplayName)) {
|
||||||
|
model.ContainerDisplayName = container.ContentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = _contentManager.Query(VersionOptions.Latest);
|
||||||
|
|
||||||
|
if (hasRestriction) {
|
||||||
|
model.FilterByContentType = restrictedContentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(model.FilterByContentType)) {
|
||||||
|
var contentTypeDefinition = _contentDefinitionManager.GetTypeDefinition(model.FilterByContentType);
|
||||||
|
if (contentTypeDefinition == null)
|
||||||
|
return HttpNotFound();
|
||||||
|
query = query.ForType(model.FilterByContentType);
|
||||||
|
}
|
||||||
|
query = query.Join<CommonPartRecord>().Where(cr => cr.Container.Id == model.ContainerId);
|
||||||
|
|
||||||
|
switch (model.Options.OrderBy) {
|
||||||
|
case ContentsOrder.Modified:
|
||||||
|
query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.ModifiedUtc);
|
||||||
|
break;
|
||||||
|
case ContentsOrder.Published:
|
||||||
|
query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.PublishedUtc);
|
||||||
|
break;
|
||||||
|
case ContentsOrder.Created:
|
||||||
|
query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.CreatedUtc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
model.Options.SelectedFilter = model.FilterByContentType;
|
||||||
|
|
||||||
|
if (!hasRestriction) {
|
||||||
|
model.Options.FilterOptions = GetContainableTypes()
|
||||||
|
.Select(ctd => new KeyValuePair<string, string>(ctd.Name, ctd.DisplayName))
|
||||||
|
.ToList().OrderBy(kvp => kvp.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
var pagerShape = Shape.Pager(pager).TotalItemCount(query.Count());
|
||||||
|
var pageOfContentItems = query.Slice(pager.GetStartIndex(), pager.PageSize).ToList();
|
||||||
|
|
||||||
|
var list = Shape.List();
|
||||||
|
list.AddRange(pageOfContentItems.Select(ci => _contentManager.BuildDisplay(ci, "SummaryAdmin")));
|
||||||
|
|
||||||
|
dynamic viewModel = Shape.ViewModel()
|
||||||
|
.ContentItems(list)
|
||||||
|
.Pager(pagerShape)
|
||||||
|
.ContainerId(model.ContainerId)
|
||||||
|
.Options(model.Options)
|
||||||
|
.HasRestriction(hasRestriction)
|
||||||
|
.ContainerDisplayName(model.ContainerDisplayName)
|
||||||
|
.ContainerContentType(container.ContentType)
|
||||||
|
.ContainerItemContentType(hasRestriction ? restrictedContentType : (model.FilterByContentType ?? ""))
|
||||||
|
.OtherLists(_contentManager.Query<ContainerPart>(VersionOptions.Latest).List()
|
||||||
|
.Select(part => part.ContentItem)
|
||||||
|
.Where(item => item != container)
|
||||||
|
.OrderBy(item => item.As<CommonPart>().VersionPublishedUtc));
|
||||||
|
|
||||||
|
// Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
|
||||||
|
return View((object)viewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost, ActionName("List")]
|
||||||
|
[FormValueRequired("submit.BulkEdit")]
|
||||||
|
public ActionResult ListPOST(ContentOptions options, IEnumerable<int> itemIds, int? targetContainerId, string returnUrl) {
|
||||||
|
if (itemIds != null) {
|
||||||
|
switch (options.BulkAction) {
|
||||||
|
case ContentsBulkAction.None:
|
||||||
|
break;
|
||||||
|
case ContentsBulkAction.PublishNow:
|
||||||
|
if (!BulkPublishNow(itemIds)) {
|
||||||
|
return new HttpUnauthorizedResult();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ContentsBulkAction.Unpublish:
|
||||||
|
if (!BulkUnpublish(itemIds)) {
|
||||||
|
return new HttpUnauthorizedResult();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ContentsBulkAction.Remove:
|
||||||
|
if (!BulkRemove(itemIds)) {
|
||||||
|
return new HttpUnauthorizedResult();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ContentsBulkAction.RemoveFromList:
|
||||||
|
if (!BulkRemoveFromList(itemIds)) {
|
||||||
|
return new HttpUnauthorizedResult();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ContentsBulkAction.MoveToList:
|
||||||
|
if (!BulkMoveToList(itemIds, targetContainerId)) {
|
||||||
|
return new HttpUnauthorizedResult();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.RedirectLocal(returnUrl, () => RedirectToAction("List"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool BulkMoveToList(IEnumerable<int> itemIds, int? targetContainerId) {
|
||||||
|
if (!targetContainerId.HasValue) {
|
||||||
|
Services.Notifier.Information(T("Please select the list to move the items to."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var id = targetContainerId.Value;
|
||||||
|
var targetContainer = _contentManager.Get<ContainerPart>(id);
|
||||||
|
if (targetContainer == null) {
|
||||||
|
Services.Notifier.Information(T("Please select the list to move the items to."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var itemContentType = targetContainer.Record.ItemContentType;
|
||||||
|
|
||||||
|
foreach (var item in itemIds.Select(itemId => _contentManager.GetLatest(itemId))) {
|
||||||
|
if (!Services.Authorizer.Authorize(Permissions.EditContent, item, T("Couldn't move selected content."))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// ensure the item can be in that container.
|
||||||
|
if (!string.IsNullOrEmpty(itemContentType) && item.ContentType != itemContentType) {
|
||||||
|
Services.Notifier.Information(T("One or more items could not be moved to the '{0}' list because it is restricted to containing items of type '{1}'.", _contentManager.GetItemMetadata(item).DisplayText, itemContentType));
|
||||||
|
return true; // todo: transactions
|
||||||
|
}
|
||||||
|
|
||||||
|
item.As<CommonPart>().Record.Container = targetContainer.ContentItem.Record;
|
||||||
|
}
|
||||||
|
Services.Notifier.Information(T("Content successfully moved to <a href=\"{0}\">{1}</a>.",
|
||||||
|
Url.Action("List", new { containerId = targetContainerId }), _contentManager.GetItemMetadata(targetContainer).DisplayText));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool BulkRemoveFromList(IEnumerable<int> itemIds) {
|
||||||
|
foreach (var item in itemIds.Select(itemId => _contentManager.GetLatest(itemId))) {
|
||||||
|
if (!Services.Authorizer.Authorize(Permissions.EditContent, item, T("Couldn't remove selected content from the list."))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
item.As<CommonPart>().Record.Container = null;
|
||||||
|
}
|
||||||
|
Services.Notifier.Information(T("Content successfully removed from the list."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool BulkRemove(IEnumerable<int> itemIds) {
|
||||||
|
foreach (var item in itemIds.Select(itemId => _contentManager.GetLatest(itemId))) {
|
||||||
|
if (!Services.Authorizer.Authorize(Permissions.DeleteContent, item, T("Couldn't remove selected content."))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_contentManager.Remove(item);
|
||||||
|
}
|
||||||
|
Services.Notifier.Information(T("Content successfully removed."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool BulkUnpublish(IEnumerable<int> itemIds) {
|
||||||
|
foreach (var item in itemIds.Select(itemId => _contentManager.GetLatest(itemId))) {
|
||||||
|
if (!Services.Authorizer.Authorize(Permissions.PublishContent, item, T("Couldn't unpublish selected content."))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_contentManager.Unpublish(item);
|
||||||
|
}
|
||||||
|
Services.Notifier.Information(T("Content successfully unpublished."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool BulkPublishNow(IEnumerable<int> itemIds) {
|
||||||
|
foreach (var item in itemIds.Select(itemId => _contentManager.GetLatest(itemId))) {
|
||||||
|
if (!Services.Authorizer.Authorize(Permissions.PublishContent, item, T("Couldn't publish selected content.")))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_contentManager.Publish(item);
|
||||||
|
}
|
||||||
|
Services.Notifier.Information(T("Content successfully published."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost, ActionName("List")]
|
||||||
|
[FormValueRequired("submit.Filter")]
|
||||||
|
public ActionResult ListFilterPOST(ContentOptions options) {
|
||||||
|
var routeValues = ControllerContext.RouteData.Values;
|
||||||
|
if (options != null) {
|
||||||
|
routeValues["Options.OrderBy"] = options.OrderBy;
|
||||||
|
if (GetContainableTypes().Any(ctd => string.Equals(ctd.Name, options.SelectedFilter, StringComparison.OrdinalIgnoreCase))) {
|
||||||
|
routeValues["filterByContentType"] = options.SelectedFilter;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
routeValues.Remove("filterByContentType");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RedirectToAction("List", routeValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Web.Routing;
|
||||||
|
using Orchard.ContentManagement;
|
||||||
|
using Orchard.ContentManagement.Handlers;
|
||||||
|
using Orchard.Core.Containers.Models;
|
||||||
|
using Orchard.Data;
|
||||||
|
|
||||||
|
namespace Orchard.Lists.Handlers {
|
||||||
|
public class ContainerPartHandler : ContentHandler {
|
||||||
|
public ContainerPartHandler() {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void GetItemMetadata(GetContentItemMetadataContext context) {
|
||||||
|
var container = context.ContentItem.As<ContainerPart>();
|
||||||
|
|
||||||
|
if (container == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// containers link to their contents in admin screens
|
||||||
|
context.Metadata.AdminRouteValues = new RouteValueDictionary {
|
||||||
|
{"Area", "Orchard.Lists"},
|
||||||
|
{"Controller", "Admin"},
|
||||||
|
{"Action", "List"},
|
||||||
|
{"containerId", container.Id}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -39,6 +39,7 @@
|
|||||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll</HintPath>
|
<HintPath>..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll</HintPath>
|
||||||
@@ -47,7 +48,11 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="AdminMenu.cs" />
|
<Compile Include="AdminMenu.cs" />
|
||||||
|
<Compile Include="Handlers\ContainerPartHandler.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Routes.cs" />
|
||||||
|
<Content Include="Scripts\orchard-lists-admin.js" />
|
||||||
|
<Compile Include="ViewModels\ListContentsViewModel.cs" />
|
||||||
<Content Include="Module.txt" />
|
<Content Include="Module.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -61,6 +66,7 @@
|
|||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Controllers\AdminController.cs" />
|
||||||
<Compile Include="Migrations.cs" />
|
<Compile Include="Migrations.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -76,7 +82,21 @@
|
|||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Views\" />
|
<Content Include="Placement.info" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Views\Admin\List.cshtml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Views\Parts.Container.Contained.SummaryAdmin.cshtml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Views\Parts.Container.Manage.cshtml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Scripts\Web.config">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Content>
|
||||||
</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" />
|
||||||
|
9
src/Orchard.Web/Modules/Orchard.Lists/Placement.info
Normal file
9
src/Orchard.Web/Modules/Orchard.Lists/Placement.info
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<Placement>
|
||||||
|
<!-- available display shapes -->
|
||||||
|
<!--
|
||||||
|
Parts_Container_Contained_SummaryAdmin
|
||||||
|
-->
|
||||||
|
<Match DisplayType="SummaryAdmin">
|
||||||
|
<Place Parts_Container_Contained_SummaryAdmin="Actions:10"/>
|
||||||
|
</Match>
|
||||||
|
</Placement>
|
@@ -3,7 +3,7 @@ using System.Web.Mvc;
|
|||||||
using System.Web.Routing;
|
using System.Web.Routing;
|
||||||
using Orchard.Mvc.Routes;
|
using Orchard.Mvc.Routes;
|
||||||
|
|
||||||
namespace Orchard.Core.Contents {
|
namespace Orchard.Lists {
|
||||||
public class Routes : IRouteProvider {
|
public class Routes : IRouteProvider {
|
||||||
public void GetRoutes(ICollection<RouteDescriptor> routes) {
|
public void GetRoutes(ICollection<RouteDescriptor> routes) {
|
||||||
foreach (RouteDescriptor routeDescriptor in GetRoutes()) {
|
foreach (RouteDescriptor routeDescriptor in GetRoutes()) {
|
||||||
@@ -16,36 +16,36 @@ namespace Orchard.Core.Contents {
|
|||||||
new RouteDescriptor {
|
new RouteDescriptor {
|
||||||
Priority = 5,
|
Priority = 5,
|
||||||
Route = new Route(
|
Route = new Route(
|
||||||
"Admin/Contents/List/{id}/InContainer/{containerId}",
|
"Admin/Orchard.Lists/{containerId}/{filterByContentType}",
|
||||||
new RouteValueDictionary {
|
new RouteValueDictionary {
|
||||||
{"area", "Contents"},
|
{"area", "Contents"},
|
||||||
{"controller", "Admin"},
|
{"controller", "Admin"},
|
||||||
{"action", "List"}
|
{"action", "List"},
|
||||||
|
{"filterByContentType", ""}
|
||||||
},
|
},
|
||||||
new RouteValueDictionary {
|
new RouteValueDictionary{
|
||||||
{"id", @"\w+"},
|
{"filterByContentType", @"\w+"},
|
||||||
{"containerId", @"\d+"}
|
{"containerId", @"\d+"}
|
||||||
},
|
},
|
||||||
new RouteValueDictionary {
|
new RouteValueDictionary {
|
||||||
{"area", "Contents"}
|
{"area", "Orchard.Lists"}
|
||||||
},
|
},
|
||||||
new MvcRouteHandler())
|
new MvcRouteHandler())
|
||||||
},
|
},
|
||||||
new RouteDescriptor {
|
new RouteDescriptor {
|
||||||
Priority = 5,
|
Priority = 5,
|
||||||
Route = new Route(
|
Route = new Route(
|
||||||
"Admin/Contents/List/InContainer/{containerId}",
|
"Admin/Orchard.Lists/{containerId}",
|
||||||
new RouteValueDictionary {
|
new RouteValueDictionary {
|
||||||
{"area", "Contents"},
|
{"area", "Orchard.Lists"},
|
||||||
{"controller", "Admin"},
|
{"controller", "Admin"},
|
||||||
{"action", "List"},
|
{"action", "List"}
|
||||||
{"id", ""}
|
|
||||||
},
|
},
|
||||||
new RouteValueDictionary{
|
new RouteValueDictionary {
|
||||||
{"containerId", @"\d+"}
|
{"containerId", @"\d+"}
|
||||||
},
|
},
|
||||||
new RouteValueDictionary {
|
new RouteValueDictionary {
|
||||||
{"area", "Contents"}
|
{"area", "Orchard.Lists"}
|
||||||
},
|
},
|
||||||
new MvcRouteHandler())
|
new MvcRouteHandler())
|
||||||
}
|
}
|
21
src/Orchard.Web/Modules/Orchard.Lists/Scripts/Web.config
Normal file
21
src/Orchard.Web/Modules/Orchard.Lists/Scripts/Web.config
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<appSettings>
|
||||||
|
<add key="webpages:Enabled" value="false" />
|
||||||
|
</appSettings>
|
||||||
|
<system.web>
|
||||||
|
<httpHandlers>
|
||||||
|
<!-- iis6 - for any request in this location, return via managed static file handler -->
|
||||||
|
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
|
||||||
|
</httpHandlers>
|
||||||
|
</system.web>
|
||||||
|
<system.webServer>
|
||||||
|
<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>
|
@@ -0,0 +1,10 @@
|
|||||||
|
jQuery("#publishActions").bind("change", function () {
|
||||||
|
var value = jQuery(this).val(),
|
||||||
|
target = jQuery("#TargetContainerId");
|
||||||
|
if (value === "MoveToList") {
|
||||||
|
target.css("display", "inline");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
target.css("display", "none");
|
||||||
|
}
|
||||||
|
});
|
@@ -0,0 +1,53 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Orchard.ContentManagement;
|
||||||
|
|
||||||
|
namespace Orchard.Lists.ViewModels {
|
||||||
|
public class ListContentsViewModel {
|
||||||
|
public ListContentsViewModel() {
|
||||||
|
Options = new ContentOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FilterByContentType { get; set; }
|
||||||
|
public int? ContainerId { get; set; }
|
||||||
|
public string ContainerDisplayName { get; set; }
|
||||||
|
|
||||||
|
public int? Page { get; set; }
|
||||||
|
public IList<Entry> Entries { get; set; }
|
||||||
|
public ContentOptions Options { get; set; }
|
||||||
|
|
||||||
|
#region Nested type: Entry
|
||||||
|
|
||||||
|
public class Entry {
|
||||||
|
public ContentItem ContentItem { get; set; }
|
||||||
|
public ContentItemMetadata ContentItemMetadata { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ContentOptions {
|
||||||
|
public ContentOptions() {
|
||||||
|
OrderBy = ContentsOrder.Modified;
|
||||||
|
BulkAction = ContentsBulkAction.None;
|
||||||
|
}
|
||||||
|
public string SelectedFilter { get; set; }
|
||||||
|
public IEnumerable<KeyValuePair<string, string>> FilterOptions { get; set; }
|
||||||
|
public ContentsOrder OrderBy { get; set; }
|
||||||
|
public ContentsBulkAction BulkAction { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ContentsOrder {
|
||||||
|
Modified,
|
||||||
|
Published,
|
||||||
|
Created
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ContentsBulkAction {
|
||||||
|
None,
|
||||||
|
PublishNow,
|
||||||
|
Unpublish,
|
||||||
|
Remove,
|
||||||
|
RemoveFromList,
|
||||||
|
MoveToList
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,64 @@
|
|||||||
|
@using Orchard.Lists.ViewModels;
|
||||||
|
@{
|
||||||
|
Script.Include("orchard-lists-admin.js");
|
||||||
|
|
||||||
|
string createLinkText = string.IsNullOrEmpty(Model.ContainerItemContentType) ? T("Create New Content").ToString() : T("Create New {0}", Model.ContainerItemContentType).ToString();
|
||||||
|
|
||||||
|
Layout.Title = T("Manage Content for {0}", Model.ContainerDisplayName);
|
||||||
|
|
||||||
|
var lists = ((IEnumerable<dynamic>)Model.OtherLists).Select(
|
||||||
|
contentItem => new SelectListItem {
|
||||||
|
Text = contentItem.ContentType + ": " + contentItem.ContentManager.GetItemMetadata(contentItem).DisplayText,
|
||||||
|
Value = contentItem.Id.ToString(System.Globalization.CultureInfo.InvariantCulture)
|
||||||
|
}).ToList();
|
||||||
|
lists.Insert(0, new SelectListItem { Text = T("Move to...").ToString(), Value = "" });
|
||||||
|
}
|
||||||
|
<style type="text/css">
|
||||||
|
.dyn #TargetContainerId {
|
||||||
|
display: none /* todo: move to css file */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div> </div>
|
||||||
|
@Display.Parts_Container_Manage(ContainerDisplayName: Model.ContainerDisplayName, ContainerContentType: Model.ContainerContentType, ContainerId: Model.ContainerId)
|
||||||
|
|
||||||
|
<div class="manage">
|
||||||
|
@Html.ActionLink(createLinkText, "Create", new { Area = "Contents", Id = (string)Model.Options.SelectedFilter, ContainerId = Model.ContainerId, ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl }, new { @class = "button primaryAction" })
|
||||||
|
</div>
|
||||||
|
@using (Html.BeginFormAntiForgeryPost()) {
|
||||||
|
<fieldset class="bulk-actions">
|
||||||
|
<label for="publishActions">@T("Actions:")</label>
|
||||||
|
<select id="publishActions" name="Options.BulkAction">
|
||||||
|
@Html.SelectOption((ContentsBulkAction)Model.Options.BulkAction, ContentsBulkAction.None, T("Choose action...").ToString())
|
||||||
|
@Html.SelectOption((ContentsBulkAction)Model.Options.BulkAction, ContentsBulkAction.PublishNow, T("Publish Now").ToString())
|
||||||
|
@Html.SelectOption((ContentsBulkAction)Model.Options.BulkAction, ContentsBulkAction.Unpublish, T("Unpublish").ToString())
|
||||||
|
@Html.SelectOption((ContentsBulkAction)Model.Options.BulkAction, ContentsBulkAction.Remove, T("Delete").ToString())
|
||||||
|
@Html.SelectOption((ContentsBulkAction)Model.Options.BulkAction, ContentsBulkAction.RemoveFromList, T("Remove from List").ToString())
|
||||||
|
@Html.SelectOption((ContentsBulkAction)Model.Options.BulkAction, ContentsBulkAction.MoveToList, T("Move to List...").ToString())
|
||||||
|
</select>
|
||||||
|
@Html.DropDownList("TargetContainerId", lists, new { id = "TargetContainerId" })
|
||||||
|
<button type="submit" name="submit.BulkEdit" value="yes">@T("Apply")</button>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset class="bulk-actions">
|
||||||
|
@if(!Model.HasRestriction) {
|
||||||
|
<label for="filterResults" class="bulk-filter">@T("Show")</label>
|
||||||
|
<select id="filterResults" name="Options.SelectedFilter">
|
||||||
|
@Html.SelectOption((string)Model.Options.SelectedFilter, "", T("any (show all)").ToString())
|
||||||
|
@foreach(var filterOption in Model.Options.FilterOptions) {
|
||||||
|
@Html.SelectOption((string)Model.Options.SelectedFilter, (string)filterOption.Key, (string)filterOption.Value)
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
}
|
||||||
|
<label for="orderResults" class="bulk-order">@T("Ordered by")</label>
|
||||||
|
<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.Modified, T("recently modified").ToString())
|
||||||
|
@Html.SelectOption((ContentsOrder)Model.Options.OrderBy, ContentsOrder.Published, T("recently published").ToString())
|
||||||
|
</select>
|
||||||
|
<button type="submit" name="submit.Filter" value="yes please">@T("Apply")</button>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset class="contentItems bulk-items">
|
||||||
|
@Display(Model.ContentItems)
|
||||||
|
</fieldset>
|
||||||
|
@Display(Model.Pager)
|
||||||
|
}
|
@@ -5,5 +5,5 @@
|
|||||||
ContentPart contentPart = Model.ContentPart;
|
ContentPart contentPart = Model.ContentPart;
|
||||||
}
|
}
|
||||||
@if (contentPart.Is<ContainerPart>()) {
|
@if (contentPart.Is<ContainerPart>()) {
|
||||||
@Html.Link(T("Contained Items").Text, Url.Action("List", "Admin", new { area = "Contents", containerId = contentPart.Id }))@T(" | ")
|
@Html.Link(T("Contained Items").Text, Url.Action("List", "Admin", new { area = "Orchard.Lists", containerId = contentPart.Id }))@T(" | ")
|
||||||
}
|
}
|
@@ -0,0 +1,8 @@
|
|||||||
|
<div class="item-properties actions">
|
||||||
|
<p>
|
||||||
|
@Html.ActionLink(T("Show Other Lists").ToString(), "List", new { Area = "Contents", Id = Model.ContainerContentType }) |
|
||||||
|
@Html.ActionLink(T("Show Orphaned Content Items").ToString(), "Orphaned") |
|
||||||
|
@Html.ActionLink(T("{0} Properties", (string)Model.ContainerContentType).ToString(), "Edit", new { Area = "Contents", Id = Model.ContainerId })
|
||||||
|
|
||||||
|
</p>
|
||||||
|
</div>
|
Reference in New Issue
Block a user