Reassembling* the admin content (management) list and content item edit

* edit partially on the new UI composition model

--HG--
branch : dev
This commit is contained in:
Nathan Heskew
2010-10-13 04:51:15 -07:00
parent ec7f111021
commit 14aef1985f
20 changed files with 206 additions and 113 deletions

View File

@@ -35,7 +35,6 @@ namespace Orchard.Core.Common.Drivers {
}
protected override DriverResult Display(BodyPart part, string displayType, dynamic shapeHelper) {
return Combined(
ContentShape("Parts_Common_Body",
() => {

View File

@@ -36,11 +36,14 @@ namespace Orchard.Core.Common.Drivers {
public IOrchardServices Services { get; set; }
protected override DriverResult Display(CommonPart part, string displayType, dynamic shapeHelper) {
var metadata = shapeHelper.Parts_Common_Metadata(ContentPart: part);
if (!string.IsNullOrWhiteSpace(displayType))
metadata.Metadata.Type = string.Format("{0}.{1}", metadata.Metadata.Type, displayType);
var location = part.GetLocation(displayType);
return ContentShape(metadata).Location(location);
return Combined(
ContentShape("Parts_Common_Metadata",
() => shapeHelper.Parts_Common_Metadata(ContentPart: part)),
ContentShape("Parts_Common_Metadata_Summary",
() => shapeHelper.Parts_Common_Metadata_Summary(ContentPart: part)),
ContentShape("Parts_Common_Metadata_SummaryAdmin",
() => shapeHelper.Parts_Common_Metadata_SummaryAdmin(ContentPart: part))
);
}
protected override DriverResult Editor(CommonPart part, dynamic shapeHelper) {

View File

@@ -1,13 +1,17 @@
<Placement>
<Place Parts_Common_Body_Editor="Primary:2"/>
<!-- show summary for all DisplayType by default -->
<Place Parts_Common_Body_Summary="Content:5"/>
<Match DisplayType="Detail">
<!-- hide summary, show full content, for Detail -->
<Place Parts_Common_Body_Summary="-"
Parts_Common_Body="Content:5" />
</Match>
<Place Parts_Common_Metadata="-"/>
<Place Parts_Common_Metadata_Summary="-"/>
<Place Parts_Common_Metadata_SummaryAdmin="-"/>
<Place Parts_Common_Body_Editor="Primary:2"/>
<!-- show summary for all DisplayType by default -->
<Place Parts_Common_Body_Summary="Content:5"/>
<Match DisplayType="Detail">
<!-- hide summary, show full content, for Detail -->
<Place Parts_Common_Body_Summary="-"
Parts_Common_Body="Content:5" />
</Match>
<Match DisplayType="SummaryAdmin">
<Place Parts_Common_Body_Summary="-"
Parts_PublishLater_Metadata_SummaryAdmin="Metadata:1"/>
</Match>
</Placement>

View File

@@ -1,7 +1,15 @@
@model Orchard.Core.Common.ViewModels.CommonMetadataViewModel
<ul class="pageStatus">
<li>@if (Model.ModifiedUtc.HasValue) {
@T("Last modified: {0}", Html.DateTimeRelative(Model.ModifiedUtc.Value, T))}&nbsp;&#124;&nbsp;
</li>
<li>@T("By {0}", Model.Creator.UserName)</li>
@using Orchard.ContentManagement;
@using Orchard.Core.Common.Models;
@using Orchard.Security;
@{
CommonPart commonPart = Model.ContentPart;
DateTime? modifiedUtc = commonPart.As<CommonPart>() == null ? null : commonPart.As<CommonPart>().ModifiedUtc;
// owner isn't really who last modified this, is it?
IUser owner = commonPart.As<CommonPart>() == null ? null : commonPart.As<CommonPart>().Owner;
}
<ul class="pageStatus">
<li>@if (modifiedUtc.HasValue) {
@T("Last modified: {0}", Html.DateTimeRelative(modifiedUtc.Value, T))}&nbsp;&#124;&nbsp;
</li>
<li>@T("By {0}", owner.UserName)</li>
</ul>

View File

@@ -1,15 +1,17 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Core.ContentsLocation.Models;
namespace Orchard.Core.Contents.Drivers {
public class ContentsDriver : ContentPartDriver<ContentPart> {
protected override DriverResult Display(ContentPart part, string displayType, dynamic shapeHelper) {
var publish = shapeHelper.Parts_Contents_Publish(ContentPart: part);
if (!string.IsNullOrWhiteSpace(displayType))
publish.Metadata.Type = string.Format("{0}.{1}", publish.Metadata.Type, displayType);
var location = part.GetLocation(displayType, "Secondary", "5");
return ContentShape(publish).Location(location);
return Combined(
ContentShape("Parts_Contents_Publish",
() => shapeHelper.Parts_Contents_Publish(ContentPart: part)),
ContentShape("Parts_Contents_Publish_Summary",
() => shapeHelper.Parts_Contents_Publish_Summary(ContentPart: part)),
ContentShape("Parts_Contents_Publish_SummaryAdmin",
() => shapeHelper.Parts_Contents_Publish_SummaryAdmin(ContentPart: part))
);
}
}
}

View File

@@ -0,0 +1,11 @@
<Placement>
<Place Parts_Contents_Publish="-"/>
<Place Parts_Contents_Publish_Summary="-"/>
<Place Parts_Contents_Publish_SummaryAdmin="-"/>
<Match DisplayType="Detail">
<Place Parts_Contents_Publish="Primary:5"/>
</Match>
<Match DisplayType="SummaryAdmin">
<Place Parts_Contents_Publish_SummaryAdmin="Secondary:5"/>
</Match>
</Placement>

View File

@@ -10,6 +10,7 @@ namespace Orchard.Core.Contents {
if (contentItem != null) {
displaying.ShapeMetadata.Alternates.Add("Items_Content__" + contentItem.ContentType);
displaying.ShapeMetadata.Alternates.Add("Items_Content__" + contentItem.Id);
displaying.ShapeMetadata.Alternates.Add("Items_Content_" + displaying.ShapeMetadata.DisplayType);
}
});

View File

@@ -3,7 +3,7 @@
@Display(Model.Primary)
</div>
<div class="secondary">
@Display(Model.secondary)
@Display(Model.Secondary)
<fieldset>
<input class="button primaryAction" type="submit" name="submit.Save" value="@T("Save")"/>
</fieldset>

View File

@@ -8,12 +8,11 @@
<div class="properties">
<input type="checkbox" value="@contentItem.Id" name="itemIds"/>
<h3>@Html.ItemEditLink(contentItem)</h3>
<div class="metadata">@Display(Model.metadata)</div>
<div class="metadata">@Display(Model.Meta)</div>
</div>
<div class="related">@Display(Model.secondary)
<div class="related">@Display(Model.Secondary)
@Html.ItemEditLink(T("Edit").Text, contentItem) @T(" | ")
@Html.Link(T("Remove").Text, Url.Action("Remove", "Admin", new { area = "Contents", id = contentItem.Id, returnUrl }), new { itemprop = "RemoveUrl UnsafeUrl" })
<br />@Display(Model.meta)
</div>
<div class="primary">@Display(Model.Primary)</div>
</div>

View File

@@ -2,17 +2,18 @@
@using Orchard.Utility.Extensions;
@{
Script.Require("ShapesBase");
ContentPart contentPart = Model.ContentPart;
}
@if (Model.HasPublished) {
@Html.ItemDisplayLink(T("View").Text, (ContentItem)Model.ContentItem)
@if (contentPart.HasPublished()) {
@Html.ItemDisplayLink(T("View").Text, (ContentItem)Model.ContentPart.ContentItem)
@T(" | ")
if (Model.HasDraft) {
@Html.Link(T("Publish Draft").Text, Url.Action("Publish", "Admin", new { area = "Contents", id = Model.ContentItem.Id, returnUrl = ViewContext.RequestContext.HttpContext.Request.ToUrlString() }), new { itemprop = "PublishUrl UnsafeUrl" })
if (contentPart.HasDraft()) {
@Html.Link(T("Publish Draft").Text, Url.Action("Publish", "Admin", new { area = "Contents", id = contentPart.ContentItem.Id, returnUrl = Request.ToUrlString() }), new { itemprop = "PublishUrl UnsafeUrl" })
@T(" | ")
}
@Html.Link(T("Unpublish").Text, Url.Action("Unpublish", "Admin", new { area = "Contents", id = Model.ContentItem.Id, returnUrl = ViewContext.RequestContext.HttpContext.Request.ToUrlString() }), new { itemprop = "UnpublishUrl UnsafeUrl" })
@Html.Link(T("Unpublish").Text, Url.Action("Unpublish", "Admin", new { area = "Contents", id = contentPart.ContentItem.Id, returnUrl = Request.ToUrlString() }), new { itemprop = "UnpublishUrl UnsafeUrl" })
@T(" | ")
} else {
@Html.Link(T("Publish").Text, Url.Action("Publish", "Admin", new { area = "Contents", id = Model.ContentItem.Id, returnUrl = ViewContext.RequestContext.HttpContext.Request.ToUrlString() }), new { itemprop = "PublishUrl UnsafeUrl" })
@Html.Link(T("Publish").Text, Url.Action("Publish", "Admin", new { area = "Contents", id = contentPart.ContentItem.Id, returnUrl = Request.ToUrlString() }), new { itemprop = "PublishUrl UnsafeUrl" })
@T(" | ")
}

View File

@@ -22,11 +22,14 @@ namespace Orchard.Core.Localization.Drivers {
}
protected override DriverResult Display(LocalizationPart part, string displayType, dynamic shapeHelper) {
var contentTranslations = shapeHelper.Parts_Localization_ContentTranslations(ContentPart: part, Localizations: GetDisplayLocalizations(part));
if (!string.IsNullOrWhiteSpace(displayType))
contentTranslations.Metadata.Type = string.Format("{0}.{1}", contentTranslations.Metadata.Type, displayType);
var location = part.GetLocation(displayType);
return ContentShape(contentTranslations).Location(location);
return Combined(
ContentShape("Parts_Localization_ContentTranslations",
() => shapeHelper.Parts_Localization_ContentTranslations(ContentPart: part, Localizations: GetDisplayLocalizations(part))),
ContentShape("Parts_Localization_ContentTranslations_Summary",
() => shapeHelper.Parts_Localization_ContentTranslations_Summary(ContentPart: part, Localizations: GetDisplayLocalizations(part))),
ContentShape("Parts_Localization_ContentTranslations_SummaryAdmin",
() => shapeHelper.Parts_Localization_ContentTranslations_SummaryAdmin(ContentPart: part, Localizations: GetDisplayLocalizations(part)))
);
}
protected override DriverResult Editor(LocalizationPart part, dynamic shapeHelper) {

View File

@@ -0,0 +1,14 @@
<Placement>
<Place Parts_Localization_ContentTranslations="-"/>
<Place Parts_Localization_ContentTranslations_Summary="-"/>
<Place Parts_Localization_ContentTranslations_SummaryAdmin="-"/>
<Match DisplayType="Detail">
<Place Parts_Localization_ContentTranslations="Primary:5"/>
</Match>
<Match DisplayType="Summary">
<Place Parts_Localization_ContentTranslations_Summary="Primary:5"/>
</Match>
<Match DisplayType="SummaryAdmin">
<Place Parts_Localization_ContentTranslations_SummaryAdmin="Primary:5"/>
</Match>
</Placement>

View File

@@ -1,11 +1,12 @@
@model Orchard.Core.Localization.ViewModels.ContentLocalizationsViewModel
@using Orchard.Core.Localization.Models;
@{
Style.Require("LocalizationAdmin");
IEnumerable<LocalizationPart> localizations = Model.Localizations;
var localizationLinks = Html.UnorderedList(localizations, (c, i) => Html.ItemEditLink(c.Culture.Culture, c), "localizations");
}
<div class="content-localization">
@if (Model.Localizations.Count() > 0) {
//todo: need this info in the view model
<div class="content-localizations"><h4>@T("Translations:")</h4>@Html.UnorderedList(Model.Localizations, (c, i) => Html.ItemEditLink(c.Culture.Culture, c), "localizations")</div>
@if (localizations.Count() > 0) {
<div class="content-localizations"><h4>@T("Translations:")</h4>@localizationLinks</div>
}
<div class="add-localization">@Html.ActionLink(T("+ New translation").Text, "translate", "admin", new { area = "Localization", id = Model.MasterId }, null)</div>
</div>

View File

@@ -393,6 +393,9 @@
<Content Include="Shapes\Views\Web.config" />
<Content Include="Dashboard\Views\Helper\Index.cshtml" />
<None Include="Common\Placement.info" />
<None Include="Contents\Placement.info" />
<None Include="Localization\Placement.info" />
<None Include="PublishLater\Placement.info" />
<None Include="Routable\Views\Parts\RoutableTitle.cshtml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

View File

@@ -2,7 +2,6 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Core.Common.Services;
using Orchard.Core.ContentsLocation.Models;
using Orchard.Core.PublishLater.Models;
using Orchard.Core.PublishLater.Services;
using Orchard.Core.PublishLater.ViewModels;
@@ -10,7 +9,7 @@ using Orchard.Localization;
namespace Orchard.Core.PublishLater.Drivers {
public class PublishLaterPartDriver : ContentPartDriver<PublishLaterPart> {
private const string TemplatePrefix = "PublishLater";
private const string TemplateName = "Parts/PublishLater";
private readonly ICommonService _commonService;
private readonly IPublishLaterService _publishLaterService;
@@ -27,46 +26,51 @@ namespace Orchard.Core.PublishLater.Drivers {
public Localizer T { get; set; }
public IOrchardServices Services { get; set; }
protected override string Prefix {
get { return "PublishLater"; }
}
protected override DriverResult Display(PublishLaterPart part, string displayType, dynamic shapeHelper) {
var metadata = shapeHelper.Parts_PublishLater_Metadata(ContentPart: part, ScheduledPublishUtc: part.ScheduledPublishUtc.Value);
if (!string.IsNullOrWhiteSpace(displayType))
metadata.Metadata.Type = string.Format("{0}.{1}", metadata.Metadata.Type, displayType);
var location = part.GetLocation(displayType);
return ContentShape(metadata).Location(location);
return Combined(
ContentShape("Parts_PublishLater_Metadata",
() => shapeHelper.Parts_PublishLater_Metadata(ContentPart: part, ScheduledPublishUtc: part.ScheduledPublishUtc.Value)),
ContentShape("Parts_PublishLater_Metadata_Summary",
() => shapeHelper.Parts_PublishLater_Metadata_Summary(ContentPart: part, ScheduledPublishUtc: part.ScheduledPublishUtc.Value)),
ContentShape("Parts_PublishLater_Metadata_SummaryAdmin",
() => shapeHelper.Parts_PublishLater_Metadata_SummaryAdmin(ContentPart: part, ScheduledPublishUtc: part.ScheduledPublishUtc.Value))
);
}
protected override DriverResult Editor(PublishLaterPart part, dynamic shapeHelper) {
return PublishEditor(part, null);
var model = BuildEditorViewModel(part);
return ContentShape("Parts_PublishLater_Editor",
() => shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: model, Prefix: Prefix));
}
protected override DriverResult Editor(PublishLaterPart instance, IUpdateModel updater, dynamic shapeHelper) {
return PublishEditor(instance, updater);
}
DriverResult PublishEditor(PublishLaterPart part, IUpdateModel updater) {
protected override DriverResult Editor(PublishLaterPart part, IUpdateModel updater, dynamic shapeHelper) {
var model = new PublishLaterViewModel(part);
if (updater != null) {
updater.TryUpdateModel(model, TemplatePrefix, null, null);
switch (model.Command) {
case "PublishNow":
_commonService.Publish(model.ContentItem);
//Services.Notifier.Information(T("{0} has been published!", model.ContentItem.TypeDefinition.DisplayName));
break;
case "PublishLater":
DateTime scheduled;
if (DateTime.TryParse(string.Format("{0} {1}", model.ScheduledPublishUtcDate, model.ScheduledPublishUtcTime), out scheduled))
model.ScheduledPublishUtc = scheduled;
_publishLaterService.Publish(model.ContentItem, model.ScheduledPublishUtc.HasValue ? model.ScheduledPublishUtc.Value : DateTime.MaxValue);
//Services.Notifier.Information(T("{0} has been scheduled for publishing!", model.ContentItem.TypeDefinition.DisplayName));
break;
case "SaveDraft":
//Services.Notifier.Information(T("{0} draft has been saved!", model.ContentItem.TypeDefinition.DisplayName));
break;
}
updater.TryUpdateModel(model, Prefix, null, null);
switch (model.Command) {
case "PublishNow":
_commonService.Publish(model.ContentItem);
//Services.Notifier.Information(T("{0} has been published!", model.ContentItem.TypeDefinition.DisplayName));
break;
case "PublishLater":
DateTime scheduled;
if (DateTime.TryParse(string.Format("{0} {1}", model.ScheduledPublishUtcDate, model.ScheduledPublishUtcTime), out scheduled))
model.ScheduledPublishUtc = scheduled;
_publishLaterService.Publish(model.ContentItem, model.ScheduledPublishUtc.HasValue ? model.ScheduledPublishUtc.Value : DateTime.MaxValue);
//Services.Notifier.Information(T("{0} has been scheduled for publishing!", model.ContentItem.TypeDefinition.DisplayName));
break;
case "SaveDraft":
//Services.Notifier.Information(T("{0} draft has been saved!", model.ContentItem.TypeDefinition.DisplayName));
break;
}
return ContentShape("Parts_PublishLater_Editor",
() => shapeHelper.EditorTemplate(TemplateName: TemplateName, Model: model, Prefix: Prefix));
}
return ContentPartTemplate(model, "Parts/PublishLater", TemplatePrefix).Location(part.GetLocation("Editor"));
private static PublishLaterViewModel BuildEditorViewModel(PublishLaterPart part) {
return new PublishLaterViewModel(part);
}
}
}

View File

@@ -0,0 +1,15 @@
<Placement>
<Place Parts_PublishLater_Metadata="-"/>
<Place Parts_PublishLater_Metadata_Summary="-"/>
<Place Parts_PublishLater_Metadata_SummaryAdmin="-"/>
<Place Parts_PublishLater_Editor="Secondary:1"/>
<Match DisplayType="Detail">
<Place Parts_PublishLater_Metadata="Meta:1"/>
</Match>
<Match DisplayType="Summary">
<Place Parts_PublishLater_Metadata_Summary="Meta:1"/>
</Match>
<Match DisplayType="SummaryAdmin">
<Place Parts_PublishLater_Metadata_SummaryAdmin="Meta:1"/>
</Match>
</Placement>

View File

@@ -27,7 +27,10 @@
@Html.EditorFor(m => m.ScheduledPublishUtcTime)
</div>
</fieldset>
<script type="text/javascript"> $(function () {
@using(Script.Foot()) {
<script type="text/javascript">
//<![CDATA[
$(function () {
@* todo: (heskew) make a plugin *@
$("label.forpicker").each(function () {
var $this = $(this);
@@ -42,4 +45,7 @@
});
$(@(new HtmlString(string.Format("\"#{0}\"", ViewData.TemplateInfo.GetFullHtmlFieldId("ScheduledPublishUtcDate"))))).datepicker({ showAnim: "" }).focus(function () { $(@(new HtmlString(string.Format("\"#{0}\"", ViewData.TemplateInfo.GetFullHtmlFieldId("Command_PublishLater"))))).attr("checked", "checked") });
$(@(new HtmlString(string.Format("\"#{0}\"", ViewData.TemplateInfo.GetFullHtmlFieldId("ScheduledPublishUtcTime"))))).timepickr().focus(function () { $(@(new HtmlString(string.Format("\"#{0}\"", ViewData.TemplateInfo.GetFullHtmlFieldId("Command_PublishLater"))))).attr("checked", "checked") });
})</script>
})
//]]>
</script>
}

View File

@@ -1,30 +1,36 @@
@model Orchard.Core.PublishLater.ViewModels.PublishLaterViewModel
<ul class="pageStatus">
<li>@* Published or not *@
@if (Model.HasPublished) {
<img class="icon" src="@Href("~/Core/PublishLater/Content/Admin/images/online.gif")" alt="@T("Online")" title="@T("The page is currently online")" /> <text>@T("Published")&nbsp;&#124;&nbsp;</text>
}
else {
<img class="icon" src="@Href("~/Core/PublishLater/Content/Admin/images/offline.gif")" alt="@T("Offline")" title="@T("The page is currently offline")" /> <text>@T("Not Published")&nbsp;&#124;&nbsp;</text>
}
</li>
@using Orchard.ContentManagement;
@using Orchard.Core.Common.Models;
@using Orchard.Core.PublishLater.Models;
@{
PublishLaterPart publishLaterPart = Model.ContentPart;
DateTime? versionPublishedUtc = publishLaterPart.As<CommonPart>() == null ? null : publishLaterPart.As<CommonPart>().VersionPublishedUtc;
}
<ul class="pageStatus">
<li>@* Published or not *@
@if (publishLaterPart.HasPublished()) {
<img class="icon" src="@Href("~/Core/PublishLater/Content/Admin/images/online.gif")" alt="@T("Online")" title="@T("The page is currently online")" /> <text>@T("Published")&nbsp;&#124;&nbsp;</text>
}
else {
<img class="icon" src="@Href("~/Core/PublishLater/Content/Admin/images/offline.gif")" alt="@T("Offline")" title="@T("The page is currently offline")" /> <text>@T("Not Published")&nbsp;&#124;&nbsp;</text>
}
</li>
<li>
@* Does the page have a draft *@
@if (publishLaterPart.HasDraft()) {
<img class="icon" src="@Href("~/Core/PublishLater/Content/Admin/images/draft.gif")" alt="@T("Draft")" title="@T("The page has a draft")" /><text> @T("Draft")&nbsp;&#124;&nbsp;</text>
}
else {
<text>@T("No Draft")&nbsp;&#124;&nbsp;</text>
}
</li>
@if ((((DateTime?)Model.ScheduledPublishUtc).HasValue && Model.ScheduledPublishUtc.Value > DateTime.UtcNow) || (publishLaterPart.IsPublished() && versionPublishedUtc.HasValue)) {
<li>
@* Does the page have a draft *@
@if (Model.HasDraft) {
<img class="icon" src="@Href("~/Core/PublishLater/Content/Admin/images/draft.gif")" alt="@T("Draft")" title="@T("The page has a draft")" /><text> @T("Draft")&nbsp;&#124;&nbsp;</text>
@if (publishLaterPart.IsPublished() && versionPublishedUtc.HasValue) {
@T("Published: {0}", Html.DateTimeRelative(versionPublishedUtc.Value, T))
}
else {
<text>@T("No Draft")&nbsp;&#124;&nbsp;</text>
}
</li>
@if ((Model.ScheduledPublishUtc.HasValue && Model.ScheduledPublishUtc.Value > DateTime.UtcNow) || (Model.IsPublished && Model.VersionPublishedUtc.HasValue)) {
<li>
@if (Model.IsPublished && Model.VersionPublishedUtc.HasValue) {
@T("Published: {0}", Html.DateTimeRelative(Model.VersionPublishedUtc.Value, T))
}
else {
<img class="icon" src="@Href("~/Core/PublishLater/Content/Admin/images/scheduled.gif")" alt="@T("Scheduled")" title="@T("The page is scheduled for publishing")" /><text> @T("Scheduled") </text>
@Html.DateTime(Model.ScheduledPublishUtc.Value, T("M/d/yyyy h:mm tt"))
}&nbsp;&#124;&nbsp;</li>
}
</ul>
<img class="icon" src="@Href("~/Core/PublishLater/Content/Admin/images/scheduled.gif")" alt="@T("Scheduled")" title="@T("The page is scheduled for publishing")" /><text> @T("Scheduled") </text>
@Html.DateTime((DateTime)Model.ScheduledPublishUtc.Value, T("M/d/yyyy h:mm tt"))
}&nbsp;&#124;&nbsp;</li>
}
</ul>

View File

@@ -41,6 +41,8 @@
@Display(Model.Footer)</div>
@* tmp *@
<!--
<div style="background:#666;color:#daf2f6;margin:10px;padding:10px;font:12px/18px Consolas,'Lucida Console','Bitstream Vera Sans Mono','DejaVu Sans Mono',monospace;">
@Display.DumpShapeTable()
</div>
</div>
-->

View File

@@ -205,10 +205,21 @@ namespace Orchard.ContentManagement {
return content == null ? default(T) : (T)content.ContentItem.Get(typeof(T));
}
public static IEnumerable<T> AsPart<T>(this IEnumerable<ContentItem> items) where T : IContent {
return items == null ? null : items.Where(item => item.Is<T>()).Select(item => item.As<T>());
}
public static bool IsPublished(this IContent content) {
return content.ContentItem.VersionRecord != null && content.ContentItem.VersionRecord.Published;
}
public static bool HasDraft(this IContent content) {
return (
(content.ContentItem.VersionRecord != null)
&& ((content.ContentItem.VersionRecord.Published == false)
|| (content.ContentItem.VersionRecord.Published && content.ContentItem.VersionRecord.Latest == false)));
}
public static bool HasPublished(this IContent content) {
return content.IsPublished() || content.ContentItem.ContentManager.Get(content.ContentItem.Id, VersionOptions.Published) != null;
}
}
}