Getting content publishing/unpublishing hooked up (from the content item list)

- moved publishing control to the Contents module
- included some prep for adding bulk actions and filtering to the content item list
- publish, unpublish and remove actions need downlevel interstitial pages (functionality only workes w/ JS at the moment)

--HG--
branch : dev
This commit is contained in:
Nathan Heskew
2010-07-16 00:49:24 -07:00
parent fd3d722860
commit 7d6b76d7f5
15 changed files with 150 additions and 49 deletions

View File

@@ -35,10 +35,7 @@ namespace Orchard.Core.Common.Drivers {
public IOrchardServices Services { get; set; }
protected override DriverResult Display(CommonAspect part, string displayType) {
var model = new CommonMetadataViewModel(part);
return Combined(
ContentPartTemplate(model, "Parts/Common.Metadata").LongestMatch(displayType, "Summary", "SummaryAdmin").Location("metadata", "5"),
ContentPartTemplate(model, "Parts/Common.Publish").LongestMatch(displayType, "Summary", "SummaryAdmin").Location("secondary"));
return ContentPartTemplate(new CommonMetadataViewModel(part), "Parts/Common.Metadata").LongestMatch(displayType, "Summary", "SummaryAdmin").Location("metadata", "5");
}
protected override DriverResult Editor(CommonAspect part) {

View File

@@ -1,5 +1,6 @@
using System.Web.Mvc;
using Orchard.Core.Common.ViewModels;
using Orchard.Core.Contents.ViewModels;
using Orchard.Localization;
using Orchard.Mvc.Html;

View File

@@ -1,5 +1,4 @@
using System;
using Orchard.ContentManagement;
using Orchard.Core.Common.Models;
using Orchard.Security;
@@ -12,7 +11,6 @@ namespace Orchard.Core.Common.ViewModels {
}
public IUser Creator { get { return _commonAspect.Owner; } }
public ContentItem ContentItem { get { return _commonAspect.ContentItem; } }
public DateTime? CreatedUtc { get { return _commonAspect.CreatedUtc; } }
public DateTime? PublishedUtc { get { return _commonAspect.PublishedUtc; } }
@@ -21,22 +19,5 @@ namespace Orchard.Core.Common.ViewModels {
public DateTime? VersionCreatedUtc { get { return _commonAspect.VersionCreatedUtc; } }
public DateTime? VersionPublishedUtc { get { return _commonAspect.VersionPublishedUtc; } }
public DateTime? VersionModifiedUtc { get { return _commonAspect.VersionModifiedUtc; } }
public bool IsPublished {
get { return ContentItem.VersionRecord != null && ContentItem.VersionRecord.Published; }
}
public bool HasDraft {
get {
return (
(ContentItem.VersionRecord != null)
&& ((ContentItem.VersionRecord.Published == false)
|| (ContentItem.VersionRecord.Published && ContentItem.VersionRecord.Latest == false)));
}
}
public bool HasPublished {
get { return IsPublished || ContentItem.ContentManager.Get(ContentItem.Id, VersionOptions.Published) != null; }
}
}
}

View File

@@ -1,12 +0,0 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Core.Common.ViewModels.CommonMetadataViewModel>" %>
<% // todo: make this all work
if (Model.HasPublished) { %>
<%:Html.ItemDisplayLink(T("View").Text, Model.ContentItem) %><%:T(" | ") %><%
if (Model.HasDraft) { %>
<a href="<%:Html.AntiForgeryTokenGetUrl(Url.Action("Publish", new {id = Model.ContentItem.Id})) %>" title="<%:T("Publish Draft") %>"><%:T("Publish Draft") %></a><%:T(" | ") %><%
} %>
<a href="<%:Html.AntiForgeryTokenGetUrl(Url.Action("Unpublish", new {id = Model.ContentItem.Id})) %>" title="<%:T("Unpublish") %>"><%:T("Unpublish") %></a><%:T(" | ") %><%
}
else { %>
<a href="<%:Html.AntiForgeryTokenGetUrl(Url.Action("Publish", new {id = Model.ContentItem.Id})) %>" title="<%:T("Publish")%>"><%:T("Publish") %></a><%:T(" | ") %><%
} %>

View File

@@ -5,9 +5,7 @@ using System.Web.Routing;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.MetaData;
using Orchard.Core.Common.Models;
using Orchard.Core.Contents.ViewModels;
using Orchard.Core.PublishLater.Models;
using Orchard.Data;
using Orchard.Localization;
using Orchard.Logging;
@@ -179,6 +177,38 @@ namespace Orchard.Core.Contents.Controllers {
return RedirectToAction("List");
}
[HttpPost]
public ActionResult Publish(int id) {
if (!Services.Authorizer.Authorize(Permissions.PublishContent, T("Couldn't publish content")))
return new HttpUnauthorizedResult();
var contentItem = _contentManager.GetLatest(id);
if (contentItem == null)
return new NotFoundResult();
_contentManager.Publish(contentItem);
Services.ContentManager.Flush();
Services.Notifier.Information(T("{0} successfully published.", contentItem.TypeDefinition.DisplayName));
return RedirectToAction("List");
}
[HttpPost]
public ActionResult Unpublish(int id) {
if (!Services.Authorizer.Authorize(Permissions.PublishContent, T("Couldn't unpublish content")))
return new HttpUnauthorizedResult();
var contentItem = _contentManager.GetLatest(id);
if (contentItem == null)
return new NotFoundResult();
_contentManager.Unpublish(contentItem);
Services.ContentManager.Flush();
Services.Notifier.Information(T("{0} successfully unpublished.", contentItem.TypeDefinition.DisplayName));
return RedirectToAction("List");
}
private static void PrepareEditorViewModel(ContentItemViewModel itemViewModel) {
if (string.IsNullOrEmpty(itemViewModel.TemplateName)) {
itemViewModel.TemplateName = "Items/Contents.Item";

View File

@@ -1,6 +1,7 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.Drivers;
using Orchard.Core.Contents.ViewModels;
namespace Orchard.Core.Contents.Drivers {
public class ContentsDriver : ContentItemDriver<ContentPart> {
@@ -11,7 +12,9 @@ namespace Orchard.Core.Contents.Drivers {
}
protected override DriverResult Display(ContentPart part, string displayType) {
return ContentItemTemplate("Items/Contents.Item").LongestMatch(displayType, "Summary", "SummaryAdmin");
return Combined(
ContentItemTemplate("Items/Contents.Item").LongestMatch(displayType, "Summary", "SummaryAdmin"),
ContentPartTemplate(new PublishContentViewModel(part.ContentItem), "Parts/Contents.Publish").LongestMatch(displayType, "Summary", "SummaryAdmin").Location("secondary"));
}
}
}

View File

@@ -0,0 +1,58 @@
using System.Collections.Generic;
using Orchard.Security.Permissions;
namespace Orchard.Core.Contents {
public class Permissions : IPermissionProvider {
public static readonly Permission PublishOthersContent = new Permission { Description = "Publish or unpublish content for others", Name = "PublishOthersContent" };
public static readonly Permission PublishContent = new Permission { Description = "Publish or unpublish content", Name = "PublishContent", ImpliedBy = new[] { PublishOthersContent } };
public static readonly Permission EditOthersContent = new Permission { Description = "Edit content for others", Name = "EditOthersContent", ImpliedBy = new[] { PublishOthersContent } };
public static readonly Permission EditContent = new Permission { Description = "Edit content", Name = "EditContent", ImpliedBy = new[] { EditOthersContent, PublishContent } };
public static readonly Permission DeleteOthersContent = new Permission { Description = "Delete content for others", Name = "DeleteOthersContent" };
public static readonly Permission DeleteContent = new Permission { Description = "Delete content", Name = "DeleteContent", ImpliedBy = new[] { DeleteOthersContent } };
public static readonly Permission MetaListContent = new Permission { ImpliedBy = new[] { EditContent, PublishContent, DeleteContent } };
public string ModuleName {
get {
return "Content";
}
}
public IEnumerable<Permission> GetPermissions() {
return new Permission[] {
EditContent,
EditOthersContent,
PublishContent,
PublishOthersContent,
DeleteContent,
DeleteOthersContent,
};
}
public IEnumerable<PermissionStereotype> GetDefaultStereotypes() {
return new[] {
new PermissionStereotype {
Name = "Administrator",
Permissions = new[] {PublishOthersContent,EditOthersContent,DeleteOthersContent}
},
new PermissionStereotype {
Name = "Editor",
Permissions = new[] {PublishOthersContent,EditOthersContent,DeleteOthersContent}
},
new PermissionStereotype {
Name = "Moderator",
//Permissions = new[] {}
},
new PermissionStereotype {
Name = "Author",
Permissions = new[] {PublishContent,EditContent,DeleteContent}
},
new PermissionStereotype {
Name = "Contributor",
Permissions = new[] {EditContent}
},
};
}
}
}

View File

@@ -0,0 +1,28 @@
using Orchard.ContentManagement;
namespace Orchard.Core.Contents.ViewModels {
public class PublishContentViewModel {
public PublishContentViewModel(ContentItem contentItem) {
ContentItem = contentItem;
}
public ContentItem ContentItem { get; private set; }
public bool IsPublished {
get { return ContentItem.VersionRecord != null && ContentItem.VersionRecord.Published; }
}
public bool HasDraft {
get {
return (
(ContentItem.VersionRecord != null)
&& ((ContentItem.VersionRecord.Published == false)
|| (ContentItem.VersionRecord.Published && ContentItem.VersionRecord.Latest == false)));
}
}
public bool HasPublished {
get { return IsPublished || ContentItem.ContentManager.Get(ContentItem.Id, VersionOptions.Published) != null; }
}
}
}

View File

@@ -2,8 +2,10 @@
<h1><%:Html.TitleForPage((string.IsNullOrEmpty(Model.TypeDisplayName) ? T("Manage Content") : T("Manage {0} Content", Model.TypeDisplayName)).ToString())%></h1>
<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" })%>
</div>
</div><%
using (Html.BeginFormAntiForgeryPost()) { %>
<%:Html.UnorderedList(
Model.Entries,
(entry, i) => Html.DisplayForItem(entry.ViewModel),
"contentItems") %>
"contentItems")%><%
} %>

View File

@@ -1,17 +1,15 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<ContentItemViewModel>" %>
<%@ Import Namespace="Orchard.Mvc.ViewModels" %>
<div class="summary">
<div class="summary" itemscope="itemscope" itemid="<%:Model.Item.Id %>" itemtype="http://orchardproject.net/data/ContentItem">
<div class="properties">
<%--//todo: need an itemprop="Title" on that link in there--%>
<h3><%:Html.ItemEditLink(Model.Item) %></h3>
<div class="metadata"><% Html.Zone("metadata"); %></div>
</div>
<div class="related"><%
Html.Zone("secondary"); %>
<%:Html.ItemEditLink(T("Edit").Text, Model.Item) %><%:T(" | ") %><%
using (Html.BeginFormAntiForgeryPost(string.Format("{0}", Url.Action("Remove", new { area = "Contents" })), FormMethod.Post, new {@class = "inline link"})) { %>
<%:Html.Hidden("id", Model.Item.Id, new { id = "" })%>
<button type="submit"><%:T("Remove") %></button><%
} %>
<%:Html.ItemEditLink(T("Edit").Text, Model.Item) %><%:T(" | ") %>
<%:Html.Link(T("Remove").Text, Url.Action("Remove", new { area = "Contents", id = Model.Item.Id }), new { itemprop = "RemoveUrl UnsafeUrl" }) %>
<br /><% Html.Zone("meta"); %>
</div>
<div style="clear:both;"></div>

View File

@@ -0,0 +1,12 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Core.Contents.ViewModels.PublishContentViewModel>" %>
<% // todo: make this all work
if (Model.HasPublished) { %>
<%:Html.ItemDisplayLink(T("View").Text, Model.ContentItem) %><%:T(" | ") %><%
if (Model.HasDraft) { %>
<%:Html.Link(T("Publish Draft").Text, Url.Action("Publish", new { area = "Contents", id = Model.ContentItem.Id }), new { itemprop = "PublishUrl UnsafeUrl" })%><%:T(" | ") %><%
} %>
<%:Html.Link(T("Unpublish").Text, Url.Action("Unpublish", new { area = "Contents", id = Model.ContentItem.Id }), new { itemprop = "UnpublishUrl UnsafeUrl" })%><%:T(" | ") %><%
}
else { %>
<%:Html.Link(T("Publish").Text, Url.Action("Publish", new { area = "Contents", id = Model.ContentItem.Id }), new { itemprop = "PublishUrl UnsafeUrl" })%><%:T(" | ") %><%
} %>

View File

@@ -77,6 +77,8 @@
<Compile Include="Contents\Controllers\ItemController.cs" />
<Compile Include="Contents\Drivers\ContentsDriver.cs" />
<Compile Include="Contents\Handlers\ContentsHandler.cs" />
<Compile Include="Contents\Permissions.cs" />
<Compile Include="Contents\ViewModels\PublishContentViewModel.cs" />
<Compile Include="PublishLater\Drivers\PublishLaterPartDriver.cs" />
<Compile Include="PublishLater\Models\PublishLaterPart.cs" />
<Compile Include="PublishLater\Handlers\PublishLaterPartHandler.cs" />
@@ -228,8 +230,8 @@
<Content Include="Common\Views\DisplayTemplates\Parts\Common.Body.ManageWrapperPre.SummaryAdmin.ascx" />
<Content Include="Common\Views\DisplayTemplates\Parts\Common.Metadata.ascx" />
<Content Include="Common\Views\DisplayTemplates\Parts\Common.Metadata.SummaryAdmin.ascx" />
<Content Include="Common\Views\DisplayTemplates\Parts\Common.Publish.SummaryAdmin.ascx" />
<Content Include="Common\Views\DisplayTemplates\Parts\Common.Publish.ascx" />
<Content Include="Contents\Views\DisplayTemplates\Parts\Contents.Publish.SummaryAdmin.ascx" />
<Content Include="Contents\Views\DisplayTemplates\Parts\Contents.Publish.ascx" />
<Content Include="PublishLater\Views\DisplayTemplates\Parts\PublishLater.Metadata.ascx" />
<Content Include="PublishLater\Views\DisplayTemplates\Parts\PublishLater.Metadata.SummaryAdmin.ascx" />
<Content Include="PublishLater\Views\DisplayTemplates\Parts\PublishLater.SummaryAdmin.ascx" />

View File

@@ -6,6 +6,7 @@
<%@ Import Namespace="Orchard.Core.Common.Models" %>
<%@ Import Namespace="Orchard.ContentManagement" %>
<%@ Import Namespace="Orchard.Core.Common.ViewModels" %>
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %>
<h2><%: Html.Link(Model.Item.Title, Url.BlogPost(Model.Item)) %></h2>
<div class="meta"><%: Html.PublishedState(new CommonMetadataViewModel(Model.Item.As<CommonAspect>()), T) %> | <%Html.Zone("meta");%></div>
<div class="content"><% Html.Zone("primary", ":manage :metadata");%></div>

View File

@@ -69,7 +69,7 @@
// UnsafeUrl links -> form POST
//todo: need some real microdata support eventually (incl. revisiting usage of data-* attributes)
$(function () {
var magicToken = $("input[name=__RequestVerificationToken]");
var magicToken = $("input[name=__RequestVerificationToken]").first();
if (!magicToken) { return; } // no sense in continuing if form POSTS will fail
$("a[itemprop~=UnsafeUrl]").each(function () {
var _this = $(this);