--HG--
branch : dev
This commit is contained in:
Sebastien Ros
2010-07-16 15:05:45 -07:00
7 changed files with 163 additions and 13 deletions

View File

@@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Web.Mvc; using System.Web.Mvc;
using System.Web.Routing; using System.Web.Routing;
using Orchard.ContentManagement; using Orchard.ContentManagement;
@@ -64,6 +66,50 @@ namespace Orchard.Core.Contents.Controllers {
return View("List", model); return View("List", model);
} }
[HttpPost, ActionName("List")]
[FormValueRequired("submit.BulkEdit")]
public ActionResult ListPOST(ContentOptions options, IEnumerable<int> itemIds) {
switch (options.BulkAction) {
case ContentsBulkAction.None:
break;
case ContentsBulkAction.PublishNow:
if (!Services.Authorizer.Authorize(Permissions.PublishContent, T("Couldn't publish selected content.")))
return new HttpUnauthorizedResult();
foreach (var item in itemIds.Select(itemId => _contentManager.GetLatest(itemId))) {
_contentManager.Publish(item);
Services.ContentManager.Flush();
}
Services.Notifier.Information(T("Content successfully published."));
break;
case ContentsBulkAction.Unpublish:
if (!Services.Authorizer.Authorize(Permissions.PublishContent, T("Couldn't unpublish selected content.")))
return new HttpUnauthorizedResult();
foreach (var item in itemIds.Select(itemId => _contentManager.GetLatest(itemId))) {
_contentManager.Unpublish(item);
Services.ContentManager.Flush();
}
Services.Notifier.Information(T("Content successfully unpublished."));
break;
case ContentsBulkAction.Remove:
if (!Services.Authorizer.Authorize(Permissions.PublishContent, T("Couldn't delete selected content.")))
return new HttpUnauthorizedResult();
foreach (var item in itemIds.Select(itemId => _contentManager.GetLatest(itemId))) {
_contentManager.Remove(item);
Services.ContentManager.Flush();
}
Services.Notifier.Information(T("Content successfully removed."));
break;
default:
throw new ArgumentOutOfRangeException();
}
// todo: persist filter & order
return RedirectToAction("List");
}
private ListContentsViewModel.Entry BuildEntry(ContentItem contentItem) { private ListContentsViewModel.Entry BuildEntry(ContentItem contentItem) {
var entry = new ListContentsViewModel.Entry { var entry = new ListContentsViewModel.Entry {
ContentItem = contentItem, ContentItem = contentItem,
@@ -222,4 +268,17 @@ namespace Orchard.Core.Contents.Controllers {
ModelState.AddModelError(key, errorMessage.ToString()); ModelState.AddModelError(key, errorMessage.ToString());
} }
} }
public class FormValueRequiredAttribute : ActionMethodSelectorAttribute {
private readonly string _submitButtonName;
public FormValueRequiredAttribute(string submitButtonName) {
_submitButtonName = submitButtonName;
}
public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) {
var value = controllerContext.HttpContext.Request.Form[_submitButtonName];
return !string.IsNullOrEmpty(value);
}
}
} }

View File

@@ -4,16 +4,60 @@ using Orchard.Mvc.ViewModels;
namespace Orchard.Core.Contents.ViewModels { namespace Orchard.Core.Contents.ViewModels {
public class ListContentsViewModel : BaseViewModel { public class ListContentsViewModel : BaseViewModel {
public ListContentsViewModel() {
Options = new ContentOptions();
}
public string Id { get; set; } public string Id { get; set; }
public string TypeName { get { return Id; } }
public string TypeName {
get { return Id; }
}
public string TypeDisplayName { get; set; } public string TypeDisplayName { get; set; }
public int? Page { get; set; } public int? Page { get; set; }
public IList<Entry> Entries { get; set; } public IList<Entry> Entries { get; set; }
public ContentOptions Options { get; set; }
#region Nested type: Entry
public class Entry { public class Entry {
public ContentItem ContentItem { get; set; } public ContentItem ContentItem { get; set; }
public ContentItemMetadata ContentItemMetadata { get; set; } public ContentItemMetadata ContentItemMetadata { get; set; }
public ContentItemViewModel ViewModel { get; set; } public ContentItemViewModel ViewModel { get; set; }
} }
#endregion
}
public class ContentOptions {
public ContentOptions() {
Filter = ContentsFilter.All;
Order = ContentsOrder.Modified;
BulkAction = ContentsBulkAction.None;
}
public ContentsFilter Filter { get; set; }
public ContentsOrder Order { get; set; }
public ContentsBulkAction BulkAction { get; set; }
}
public enum ContentsFilter {
All,
Page,
BlogPost
}
public enum ContentsOrder {
Modified,
Published,
Created,
Title
}
public enum ContentsBulkAction {
None,
PublishNow,
Unpublish,
Remove
} }
} }

View File

@@ -1,11 +1,40 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Core.Contents.ViewModels.ListContentsViewModel>" %> <%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Core.Contents.ViewModels.ListContentsViewModel>" %>
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %>
<h1><%:Html.TitleForPage((string.IsNullOrEmpty(Model.TypeDisplayName) ? T("Manage Content") : T("Manage {0} Content", Model.TypeDisplayName)).ToString())%></h1> <h1><%:Html.TitleForPage((string.IsNullOrEmpty(Model.TypeDisplayName) ? T("Manage Content") : T("Manage {0} Content", Model.TypeDisplayName)).ToString())%></h1>
<div class="manage"> <div class="manage">
<%:Html.ActionLink(!string.IsNullOrEmpty(Model.TypeDisplayName) ? T("Add new {0} content", Model.TypeDisplayName).Text : T("Add new content").Text, "Create", new { }, new { @class = "button primaryAction" })%> <%:Html.ActionLink(!string.IsNullOrEmpty(Model.TypeDisplayName) ? T("Add new {0} content", Model.TypeDisplayName).Text : T("Add new content").Text, "Create", new { }, new { @class = "button primaryAction" })%>
</div><% </div><%
using (Html.BeginFormAntiForgeryPost()) { %> using (Html.BeginFormAntiForgeryPost()) { %>
<%:Html.UnorderedList( <fieldset class="bulk-actions">
Model.Entries, <label for="publishActions"><%:T("Actions:")%></label>
(entry, i) => Html.DisplayForItem(entry.ViewModel), <select id="publishActions" name="<%:Html.NameOf(m => m.Options.BulkAction) %>">
"contentItems")%><% <%:Html.SelectOption(Model.Options.BulkAction, ContentsBulkAction.None, T("Choose action...").ToString())%>
<%:Html.SelectOption(Model.Options.BulkAction, ContentsBulkAction.PublishNow, T("Publish Now").ToString())%>
<%:Html.SelectOption(Model.Options.BulkAction, ContentsBulkAction.Unpublish, T("Unpublish").ToString())%>
<%:Html.SelectOption(Model.Options.BulkAction, ContentsBulkAction.Remove, T("Remove").ToString())%>
</select>
<button type="submit" name="submit.BulkEdit" value="yes"><%:T("Apply") %></button>
</fieldset>
<%-- <fieldset class="bulk-actions">
<label for="filterResults" class="bulk-filter"><%:T("Filter")%></label>
<select id="filterResults" name="<%:Html.NameOf(m => m.Options.Filter) %>">
<%:Html.SelectOption(Model.Options.Filter, ContentsFilter.All, T("All Content").ToString())%>
<%:Html.SelectOption(Model.Options.Filter, ContentsFilter.Page, T("Page").ToString())%>
<%:Html.SelectOption(Model.Options.Filter, ContentsFilter.BlogPost, T("Blog Post").ToString())%>
</select>
<label for="orderResults" class="bulk-order"><%:T("Ordered by")%></label>
<select id="orderResults" name="<%:Html.NameOf(m => m.Options.Order) %>">
<%:Html.SelectOption(Model.Options.Order, ContentsOrder.Created, T("Date Created").ToString())%>
<%:Html.SelectOption(Model.Options.Order, ContentsOrder.Modified, T("Date Modified").ToString())%>
<%:Html.SelectOption(Model.Options.Order, ContentsOrder.Published, T("Date Published").ToString())%>
<%:Html.SelectOption(Model.Options.Order, ContentsOrder.Title, T("Title").ToString())%>
</select>
<button type="submit" name="submit.Filter"><%:T("Apply") %></button>
</fieldset>
--%> <fieldset class="contentItems bulk-items">
<%:Html.UnorderedList(
Model.Entries,
(entry, i) => Html.DisplayForItem(entry.ViewModel),
"")%>
</fieldset><%
} %> } %>

View File

@@ -2,7 +2,7 @@
<%@ Import Namespace="Orchard.Mvc.ViewModels" %> <%@ Import Namespace="Orchard.Mvc.ViewModels" %>
<div class="summary" itemscope="itemscope" itemid="<%:Model.Item.Id %>" itemtype="http://orchardproject.net/data/ContentItem"> <div class="summary" itemscope="itemscope" itemid="<%:Model.Item.Id %>" itemtype="http://orchardproject.net/data/ContentItem">
<div class="properties"> <div class="properties">
<%--//todo: need an itemprop="Title" on that link in there--%> <input type="checkbox" value="<%:Model.Item.Id %>" name="itemIds"/>
<h3><%:Html.ItemEditLink(Model.Item) %></h3> <h3><%:Html.ItemEditLink(Model.Item) %></h3>
<div class="metadata"><% Html.Zone("metadata"); %></div> <div class="metadata"><% Html.Zone("metadata"); %></div>
</div> </div>
@@ -12,6 +12,5 @@
<%:Html.Link(T("Remove").Text, Url.Action("Remove", new { area = "Contents", id = Model.Item.Id }), new { itemprop = "RemoveUrl UnsafeUrl" }) %> <%:Html.Link(T("Remove").Text, Url.Action("Remove", new { area = "Contents", id = Model.Item.Id }), new { itemprop = "RemoveUrl UnsafeUrl" }) %>
<br /><% Html.Zone("meta"); %> <br /><% Html.Zone("meta"); %>
</div> </div>
<div style="clear:both;"></div> <div class="primary"><% Html.ZonesAny(); %></div>
<% Html.ZonesAny(); %>
</div> </div>

View File

@@ -1,5 +1,5 @@
.content-localization { .content-localization {
margin:1.44em 0 .44em; margin:1.44em 0 0;
} }
.content-localization .content-localizations li, .content-localization .content-localizations li,
.content-localization .add-localization { .content-localization .add-localization {

View File

@@ -61,7 +61,7 @@ border:1px solid #8F8F8F;
color:#FFFFFF; color:#FFFFFF;
} }
fieldset.bulk.actions { fieldset.bulk-actions {
width:30em; width:30em;
clear:left; clear:left;
text-align:left; text-align:left;

View File

@@ -358,7 +358,7 @@ form.inline, form.inline fieldset { /* todo: (heskew) need something other than
form.inline fieldset { form.inline fieldset {
margin:0; margin:0;
} }
fieldset.bulk.actions { .bulk-actions {
display:inline; display:inline;
height:auto; height:auto;
margin:0 1.4em 0 0; margin:0 1.4em 0 0;
@@ -380,9 +380,12 @@ label.forcheckbox {
display:inline; display:inline;
line-height:1.8em; line-height:1.8em;
} }
fieldset.bulk.actions label, label.sub { .bulk-actions label, .bulk-items h3, label, label.sub {
display:inline; display:inline;
} }
label.bulk-order {
text-transform:lowercase;
}
label span { label span {
font-weight:normal; font-weight:normal;
} }
@@ -638,7 +641,8 @@ table .button {
-moz-box-shadow:inset 0 1px 3px #878686; -moz-box-shadow:inset 0 1px 3px #878686;
-webkit-box-shadow:inset 0 1px 2px #878686; -webkit-box-shadow:inset 0 1px 2px #878686;
clear:both; clear:both;
margin:1.4em 0; margin:1em 0;
padding:0;
} }
.contentItems li { .contentItems li {
border-bottom:1px solid #eaeaea; border-bottom:1px solid #eaeaea;
@@ -646,6 +650,10 @@ table .button {
overflow:hidden; overflow:hidden;
padding:0 1.4em .8em; padding:0 1.4em .8em;
} }
.contentItems.bulk-items li {
padding-bottom:.6em;
padding-left:.6em;
}
#main .contentItems li .actions { #main .contentItems li .actions {
color:#EAE9D9; color:#EAE9D9;
height:auto; height:auto;
@@ -680,6 +688,14 @@ table .button {
.contentItems .metadata ul { .contentItems .metadata ul {
display:inline; display:inline;
} }
.contentItems.bulk-items .metadata, .contentItems.bulk-items .primary {
margin:.6em 0 0 2em;
}
.contentItems.bulk-items .primary {
clear:both;
float:left;
margin-top:0;
}
.contentItems .properties li { .contentItems .properties li {
border:0; border:0;
float:left; float:left;
@@ -697,6 +713,9 @@ table .button {
.contentItems .commentcount { .contentItems .commentcount {
line-height:2em; line-height:2em;
} }
#main .contentItems p {
margin:1em 0 0;
}
/* Core Modules /* Core Modules