diff --git a/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs b/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs index 814f7f052..894271846 100644 --- a/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs +++ b/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Web.Mvc; using System.Web.Routing; using Orchard.ContentManagement; @@ -64,6 +66,50 @@ namespace Orchard.Core.Contents.Controllers { return View("List", model); } + [HttpPost, ActionName("List")] + [FormValueRequired("submit.BulkEdit")] + public ActionResult ListPOST(ContentOptions options, IEnumerable 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) { var entry = new ListContentsViewModel.Entry { ContentItem = contentItem, @@ -222,4 +268,17 @@ namespace Orchard.Core.Contents.Controllers { 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); + } + } } diff --git a/src/Orchard.Web/Core/Contents/ViewModels/ListContentsViewModel.cs b/src/Orchard.Web/Core/Contents/ViewModels/ListContentsViewModel.cs index 84eaaf2c2..450219e07 100644 --- a/src/Orchard.Web/Core/Contents/ViewModels/ListContentsViewModel.cs +++ b/src/Orchard.Web/Core/Contents/ViewModels/ListContentsViewModel.cs @@ -4,16 +4,60 @@ using Orchard.Mvc.ViewModels; namespace Orchard.Core.Contents.ViewModels { public class ListContentsViewModel : BaseViewModel { + public ListContentsViewModel() { + Options = new ContentOptions(); + } + public string Id { get; set; } - public string TypeName { get { return Id; } } + + public string TypeName { + get { return Id; } + } + public string TypeDisplayName { get; set; } public int? Page { get; set; } public IList 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; } 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 } } \ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/Views/Admin/List.ascx b/src/Orchard.Web/Core/Contents/Views/Admin/List.ascx index a1a035649..06ea66f69 100644 --- a/src/Orchard.Web/Core/Contents/Views/Admin/List.ascx +++ b/src/Orchard.Web/Core/Contents/Views/Admin/List.ascx @@ -1,11 +1,40 @@ <%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> +<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %>

<%:Html.TitleForPage((string.IsNullOrEmpty(Model.TypeDisplayName) ? T("Manage Content") : T("Manage {0} Content", Model.TypeDisplayName)).ToString())%>

<%: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" })%>
<% using (Html.BeginFormAntiForgeryPost()) { %> -<%:Html.UnorderedList( - Model.Entries, - (entry, i) => Html.DisplayForItem(entry.ViewModel), - "contentItems")%><% +
+ + + +
+<%--
+ + + + + +
+--%>
+ <%:Html.UnorderedList( + Model.Entries, + (entry, i) => Html.DisplayForItem(entry.ViewModel), + "")%> +
<% } %> \ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/Views/DisplayTemplates/Items/Contents.Item.SummaryAdmin.ascx b/src/Orchard.Web/Core/Contents/Views/DisplayTemplates/Items/Contents.Item.SummaryAdmin.ascx index f0fb3cb92..4a3c13b91 100644 --- a/src/Orchard.Web/Core/Contents/Views/DisplayTemplates/Items/Contents.Item.SummaryAdmin.ascx +++ b/src/Orchard.Web/Core/Contents/Views/DisplayTemplates/Items/Contents.Item.SummaryAdmin.ascx @@ -2,7 +2,7 @@ <%@ Import Namespace="Orchard.Mvc.ViewModels" %>
- <%--//todo: need an itemprop="Title" on that link in there--%> +

<%:Html.ItemEditLink(Model.Item) %>

@@ -12,6 +12,5 @@ <%:Html.Link(T("Remove").Text, Url.Action("Remove", new { area = "Contents", id = Model.Item.Id }), new { itemprop = "RemoveUrl UnsafeUrl" }) %>
<% Html.Zone("meta"); %>
-
- <% Html.ZonesAny(); %> +
<% Html.ZonesAny(); %>
\ No newline at end of file diff --git a/src/Orchard.Web/Core/Localization/Styles/admin.css b/src/Orchard.Web/Core/Localization/Styles/admin.css index fab4f64b5..6895e51c0 100644 --- a/src/Orchard.Web/Core/Localization/Styles/admin.css +++ b/src/Orchard.Web/Core/Localization/Styles/admin.css @@ -1,5 +1,5 @@ .content-localization { - margin:1.44em 0 .44em; + margin:1.44em 0 0; } .content-localization .content-localizations li, .content-localization .add-localization { diff --git a/src/Orchard.Web/Themes/TheAdmin/Styles/ie6.css b/src/Orchard.Web/Themes/TheAdmin/Styles/ie6.css index d296ecd62..b2c2d30b9 100644 --- a/src/Orchard.Web/Themes/TheAdmin/Styles/ie6.css +++ b/src/Orchard.Web/Themes/TheAdmin/Styles/ie6.css @@ -61,7 +61,7 @@ border:1px solid #8F8F8F; color:#FFFFFF; } -fieldset.bulk.actions { +fieldset.bulk-actions { width:30em; clear:left; text-align:left; diff --git a/src/Orchard.Web/Themes/TheAdmin/Styles/site.css b/src/Orchard.Web/Themes/TheAdmin/Styles/site.css index 3a2af7a2b..ae650dc42 100644 --- a/src/Orchard.Web/Themes/TheAdmin/Styles/site.css +++ b/src/Orchard.Web/Themes/TheAdmin/Styles/site.css @@ -358,7 +358,7 @@ form.inline, form.inline fieldset { /* todo: (heskew) need something other than form.inline fieldset { margin:0; } -fieldset.bulk.actions { +.bulk-actions { display:inline; height:auto; margin:0 1.4em 0 0; @@ -380,9 +380,12 @@ label.forcheckbox { display:inline; line-height:1.8em; } -fieldset.bulk.actions label, label.sub { +.bulk-actions label, .bulk-items h3, label, label.sub { display:inline; } +label.bulk-order { + text-transform:lowercase; +} label span { font-weight:normal; } @@ -638,7 +641,8 @@ table .button { -moz-box-shadow:inset 0 1px 3px #878686; -webkit-box-shadow:inset 0 1px 2px #878686; clear:both; - margin:1.4em 0; + margin:1em 0; + padding:0; } .contentItems li { border-bottom:1px solid #eaeaea; @@ -646,6 +650,10 @@ table .button { overflow:hidden; padding:0 1.4em .8em; } +.contentItems.bulk-items li { + padding-bottom:.6em; + padding-left:.6em; +} #main .contentItems li .actions { color:#EAE9D9; height:auto; @@ -680,6 +688,14 @@ table .button { .contentItems .metadata ul { 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 { border:0; float:left; @@ -697,6 +713,9 @@ table .button { .contentItems .commentcount { line-height:2em; } +#main .contentItems p { + margin:1em 0 0; +} /* Core Modules