--HG--
branch : dev
This commit is contained in:
Sebastien Ros
2010-07-14 16:09:41 -07:00
64 changed files with 368 additions and 208 deletions

View File

@@ -13,8 +13,12 @@ using Orchard.Core.Common.Models;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.Records;
using Orchard.Core.Common.Services;
using Orchard.Core.Scheduling.Models;
using Orchard.Core.Scheduling.Services;
using Orchard.Localization;
using Orchard.Security;
using Orchard.Tasks.Scheduling;
using Orchard.Tests.Modules;
using Orchard.Core.Common.ViewModels;
using System.Web.Mvc;
@@ -32,6 +36,9 @@ namespace Orchard.Core.Tests.Common.Providers {
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
builder.RegisterType<TestHandler>().As<IContentHandler>();
builder.RegisterType<CommonAspectHandler>().As<IContentHandler>();
builder.RegisterType<CommonService>().As<ICommonService>();
builder.RegisterType<PublishingTaskManager>().As<IPublishingTaskManager>();
builder.RegisterType<ScheduledTaskManager>().As<IScheduledTaskManager>();
_authn = new Mock<IAuthenticationService>();
_authz = new Mock<IAuthorizationService>();
@@ -52,6 +59,7 @@ namespace Orchard.Core.Tests.Common.Providers {
typeof(ContentItemVersionRecord),
typeof(CommonRecord),
typeof(CommonVersionRecord),
typeof(ScheduledTaskRecord),
};
}
}

View File

@@ -10,6 +10,7 @@ using Orchard.ContentManagement.Handlers;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.Records;
using Orchard.Core.Common.Models;
using Orchard.Core.Routable;
using Orchard.Core.Routable.Handlers;
using Orchard.Core.Routable.Models;
using Orchard.Core.Routable.Services;
@@ -35,6 +36,7 @@ namespace Orchard.Core.Tests.Common.Services {
builder.RegisterType<ThingHandler>().As<IContentHandler>();
builder.RegisterType<StuffHandler>().As<IContentHandler>();
builder.RegisterType<RoutableService>().As<IRoutableService>();
builder.RegisterType<RoutablePathConstraint>().As<IRoutablePathConstraint>();
builder.RegisterType<DefaultContentQuery>().As<IContentQuery>();
builder.RegisterInstance(new UrlHelper(new RequestContext(new StubHttpContext("~/"), new RouteData()))).As<UrlHelper>();

View File

@@ -45,8 +45,8 @@ namespace Orchard.Core.Tests.Settings.Metadata {
builder.RegisterType<ContentDefinitionManager>().As<IContentDefinitionManager>();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
builder.RegisterType(typeof(SettingsFormatter))
.As(typeof(IMapper<XElement, IDictionary<string, string>>))
.As(typeof(IMapper<IDictionary<string, string>, XElement>));
.As(typeof(IMapper<XElement, SettingsDictionary>))
.As(typeof(IMapper<SettingsDictionary, XElement>));
_container = builder.Build();
_container.Mock<ISessionLocator>()

View File

@@ -3,9 +3,14 @@ using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Xml.Linq;
using Autofac;
using Moq;
using NUnit.Framework;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.ContentManagement.MetaData.Services;
using Orchard.Core.Settings.Metadata;
using Orchard.Data;
using Orchard.Environment;
using Orchard.ContentManagement;
@@ -30,6 +35,10 @@ namespace Orchard.Tests.Modules.Users.Controllers {
public override void Register(ContainerBuilder builder) {
builder.RegisterType<AdminController>().SingleInstance();
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
builder.RegisterType(typeof(SettingsFormatter))
.As(typeof(IMapper<XElement, SettingsDictionary>))
.As(typeof(IMapper<SettingsDictionary, XElement>));
builder.RegisterType<ContentDefinitionManager>().As<IContentDefinitionManager>();
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
builder.RegisterType<DefaultContentQuery>().As<IContentQuery>().InstancePerDependency();
builder.RegisterType<MembershipService>().As<IMembershipService>();

View File

@@ -1,8 +1,13 @@
using System;
using System.Web.Security;
using System.Xml.Linq;
using Autofac;
using NHibernate;
using NUnit.Framework;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.ContentManagement.MetaData.Services;
using Orchard.Core.Settings.Metadata;
using Orchard.Data;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
@@ -55,6 +60,10 @@ namespace Orchard.Tests.Modules.Users.Services {
//builder.RegisterModule(new ImplicitCollectionSupportModule());
builder.RegisterType<MembershipService>().As<IMembershipService>();
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
builder.RegisterType(typeof(SettingsFormatter))
.As(typeof(IMapper<XElement, SettingsDictionary>))
.As(typeof(IMapper<SettingsDictionary, XElement>));
builder.RegisterType<ContentDefinitionManager>().As<IContentDefinitionManager>();
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
builder.RegisterType<UserHandler>().As<IContentHandler>();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));

View File

@@ -3,7 +3,6 @@ using Orchard.Data.Migration;
namespace Orchard.Core.Common.DataMigrations {
public class CommonDataMigration : DataMigrationImpl {
public int Create() {
//CREATE TABLE Common_BodyRecord (Id INTEGER not null, Text TEXT, Format TEXT, ContentItemRecord_id INTEGER, primary key (Id));
SchemaBuilder.CreateTable("BodyRecord", table => table

View File

@@ -1,13 +1,10 @@
using System;
using Orchard.ContentManagement;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Core.Common.Models;
using Orchard.Core.Common.Services;
using Orchard.Core.Common.ViewModels;
using Orchard.Localization;
using Orchard.Security;
using Orchard.Services;
using Orchard.UI.Notify;
namespace Orchard.Core.Common.Drivers {
public class CommonDriver : ContentPartDriver<CommonAspect> {
@@ -16,7 +13,6 @@ namespace Orchard.Core.Common.Drivers {
private readonly IAuthenticationService _authenticationService;
private readonly IAuthorizationService _authorizationService;
private readonly IMembershipService _membershipService;
private readonly ICommonService _commonService;
private readonly IClock _clock;
public CommonDriver(
@@ -25,13 +21,11 @@ namespace Orchard.Core.Common.Drivers {
IAuthenticationService authenticationService,
IAuthorizationService authorizationService,
IMembershipService membershipService,
ICommonService commonService,
IClock clock) {
_contentManager = contentManager;
_authenticationService = authenticationService;
_authorizationService = authorizationService;
_membershipService = membershipService;
_commonService = commonService;
_clock = clock;
T = NullLocalizer.Instance;
Services = services;
@@ -43,15 +37,14 @@ namespace Orchard.Core.Common.Drivers {
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"),
ContentPartTemplate(model, "Parts/Common.Metadata").LongestMatch(displayType, "Summary", "SummaryAdmin").Location("metadata", "5"),
ContentPartTemplate(model, "Parts/Common.Publish").LongestMatch(displayType, "Summary", "SummaryAdmin").Location("secondary"));
}
protected override DriverResult Editor(CommonAspect part) {
return Combined(
OwnerEditor(part, null),
ContainerEditor(part, null),
PublishEditor(part, null));
ContainerEditor(part, null));
}
protected override DriverResult Editor(CommonAspect instance, ContentManagement.IUpdateModel updater) {
@@ -61,34 +54,7 @@ namespace Orchard.Core.Common.Drivers {
return Combined(
OwnerEditor(instance, updater),
ContainerEditor(instance, updater),
PublishEditor(instance, updater));
}
DriverResult PublishEditor(CommonAspect part, IUpdateModel updater) {
var model = new PublishEditorViewModel(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;
_commonService.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 ContentPartTemplate(model, "Parts/Common.Publish", TemplatePrefix).Location("secondary", "1");
ContainerEditor(instance, updater));
}
DriverResult OwnerEditor(CommonAspect part, IUpdateModel updater) {

View File

@@ -1,6 +1,5 @@
using JetBrains.Annotations;
using Orchard.Core.Common.Models;
using Orchard.Core.Common.Services;
using Orchard.Data;
using Orchard.Localization;
using Orchard.ContentManagement;
@@ -13,27 +12,18 @@ namespace Orchard.Core.Common.Handlers {
public class CommonAspectHandler : ContentHandler {
private readonly IClock _clock;
private readonly IAuthenticationService _authenticationService;
private readonly IAuthorizationService _authorizationService;
private readonly IMembershipService _membershipService;
private readonly IContentManager _contentManager;
private readonly ICommonService _commonService;
public CommonAspectHandler(
IRepository<CommonRecord> commonRepository,
IRepository<CommonVersionRecord> commonVersionRepository,
IClock clock,
IAuthenticationService authenticationService,
IAuthorizationService authorizationService,
IMembershipService membershipService,
IContentManager contentManager,
ICommonService commonService) {
IContentManager contentManager) {
_clock = clock;
_authenticationService = authenticationService;
_authorizationService = authorizationService;
_membershipService = membershipService;
_contentManager = contentManager;
_commonService = commonService;
T = NullLocalizer.Instance;
Filters.Add(StorageFilter.For(commonRepository));
@@ -45,7 +35,6 @@ namespace Orchard.Core.Common.Handlers {
OnInitializing<ContentPart<CommonVersionRecord>>(AssignCreatingDates);
OnLoaded<CommonAspect>(LazyLoadHandlers);
OnLoaded<CommonAspect>((context, commonAspect) => commonAspect.ScheduledPublishUtc.Value = _commonService.GetScheduledPublishUtc(commonAspect));
OnVersioning<CommonAspect>(CopyOwnerAndContainer);
@@ -125,7 +114,6 @@ namespace Orchard.Core.Common.Handlers {
// add handlers that will load content for id's just-in-time
aspect.OwnerField.Loader(() => _contentManager.Get<IUser>(aspect.Record.OwnerId));
aspect.ContainerField.Loader(() => aspect.Record.Container == null ? null : _contentManager.Get(aspect.Record.Container.Id));
aspect.ScheduledPublishUtc.Loader(() => _commonService.GetScheduledPublishUtc(context.ContentItem));
}
static void PropertySetHandlers(InitializingContentContext context, CommonAspect aspect) {

View File

@@ -8,14 +8,11 @@ namespace Orchard.Core.Common.Models {
public class CommonAspect : ContentPart<CommonRecord>, ICommonAspect {
private readonly LazyField<IUser> _owner = new LazyField<IUser>();
private readonly LazyField<IContent> _container = new LazyField<IContent>();
private readonly LazyField<DateTime?> _scheduledPublishUtc = new LazyField<DateTime?>();
public LazyField<IUser> OwnerField { get { return _owner; } }
public LazyField<IContent> ContainerField { get { return _container; } }
public LazyField<DateTime?> ScheduledPublishUtc { get { return _scheduledPublishUtc; } }
public IUser Owner {
get { return _owner.Value; }
set { _owner.Value = value; }

View File

@@ -1,37 +0,0 @@
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Routing;
using Orchard.Mvc.Routes;
namespace Orchard.Core.Common {
public class Routes : IRouteProvider {
#region IRouteProvider Members
public IEnumerable<RouteDescriptor> GetRoutes() {
return new[] {
new RouteDescriptor {
Route = new Route(
"Admin/Common/Routable/Slugify",
new RouteValueDictionary {
{"area", "Common"},
{"controller", "Routable"},
{"action", "Slugify"}
},
new RouteValueDictionary(),
new RouteValueDictionary {
{"area", "Common"}
},
new MvcRouteHandler())
}
};
}
public void GetRoutes(ICollection<RouteDescriptor> routes) {
foreach (RouteDescriptor routeDescriptor in GetRoutes()) {
routes.Add(routeDescriptor);
}
}
#endregion
}
}

View File

@@ -1,6 +1,4 @@
using System;
using Orchard.ContentManagement;
using Orchard.Core.Common.Models;
using Orchard.ContentManagement;
using Orchard.Tasks.Scheduling;
namespace Orchard.Core.Common.Services {
@@ -13,23 +11,9 @@ namespace Orchard.Core.Common.Services {
_contentManager = contentManager;
}
DateTime? ICommonService.GetScheduledPublishUtc(ContentItem contentItem) {
var task = _publishingTaskManager.GetPublishTask(contentItem);
return (task == null ? null : task.ScheduledUtc);
}
void ICommonService.Publish(ContentItem contentItem) {
_publishingTaskManager.DeleteTasks(contentItem);
_contentManager.Publish(contentItem);
}
void ICommonService.Publish(ContentItem contentItem, DateTime scheduledPublishUtc) {
_publishingTaskManager.Publish(contentItem, scheduledPublishUtc);
}
DateTime? ICommonService.GetScheduledPublishUtc(CommonAspect commonAspect) {
var task = _publishingTaskManager.GetPublishTask(commonAspect.ContentItem);
return (task == null ? null : task.ScheduledUtc);
}
}
}

View File

@@ -1,12 +1,7 @@
using System;
using Orchard.ContentManagement;
using Orchard.Core.Common.Models;
using Orchard.ContentManagement;
namespace Orchard.Core.Common.Services {
public interface ICommonService : IDependency {
DateTime? GetScheduledPublishUtc(ContentItem contentItem);
void Publish(ContentItem contentItem);
void Publish(ContentItem contentItem, DateTime scheduledPublishUtc);
DateTime? GetScheduledPublishUtc(CommonAspect commonAspect);
}
}

View File

@@ -22,8 +22,6 @@ namespace Orchard.Core.Common.ViewModels {
public DateTime? VersionPublishedUtc { get { return _commonAspect.VersionPublishedUtc; } }
public DateTime? VersionModifiedUtc { get { return _commonAspect.VersionModifiedUtc; } }
public DateTime? ScheduledPublishUtc { get { return _commonAspect.ScheduledPublishUtc.Value; } }
public bool IsPublished {
get { return ContentItem.VersionRecord != null && ContentItem.VersionRecord.Published; }
}

View File

@@ -1,3 +0,0 @@
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ItemReferenceContentFieldDisplayViewModel>" %>
<%@ Import Namespace="Orchard.Core.Common.ViewModels"%>
<%= Html.ItemDisplayLink(Model.Item) %>

View File

@@ -1,32 +1,7 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Core.Common.ViewModels.CommonMetadataViewModel>" %>
<ul class="pageStatus">
<li><%
// Published or not
if (Model.HasPublished) { %>
<img class="icon" src="<%=ResolveUrl("~/Modules/Orchard.Pages/Content/Admin/images/online.gif") %>" alt="<%:T("Online") %>" title="<%:T("The page is currently online") %>" /> <%:T("Published") %>&nbsp;&#124;&nbsp;<%
}
else { %>
<img class="icon" src="<%=ResolveUrl("~/Modules/Orchard.Pages/Content/Admin/images/offline.gif") %>" alt="<%:T("Offline") %>" title="<%:T("The page is currently offline") %>" /> <%:T("Not Published") %>&nbsp;&#124;&nbsp;<%
} %>
</li>
<li><%
// Does the page have a draft
if (Model.HasDraft) { %>
<img class="icon" src="<%=ResolveUrl("~/Modules/Orchard.Pages/Content/Admin/images/draft.gif") %>" alt="<%:T("Draft") %>" title="<%:T("The page has a draft") %>" /><%:T("Draft") %>&nbsp;&#124;&nbsp;<%
}
else { %>
<%:T("No Draft") %>&nbsp;&#124;&nbsp;<%
} %>
</li>
<li><%
if (Model.ScheduledPublishUtc.HasValue && Model.ScheduledPublishUtc.Value > DateTime.UtcNow) { %>
<img class="icon" src="<%=ResolveUrl("~/Modules/Orchard.Pages/Content/Admin/images/scheduled.gif") %>" alt="<%:T("Scheduled") %>" title="<%:T("The page is scheduled for publishing") %>" /><%:T("Scheduled") %>
<%:Html.DateTime(Model.ScheduledPublishUtc.Value, T("M/d/yyyy h:mm tt")) %><%
}
else if (Model.IsPublished && Model.VersionPublishedUtc.HasValue) { %>
<%:T("Published: {0}", Html.DateTimeRelative(Model.VersionPublishedUtc.Value, T)) %><%
}
else if (Model.ModifiedUtc.HasValue) { %>
if (Model.ModifiedUtc.HasValue) { %>
<%:T("Last modified: {0}", Html.DateTimeRelative(Model.ModifiedUtc.Value, T)) %><%
} %>&nbsp;&#124;&nbsp;
</li>

View File

@@ -1,3 +0,0 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<ItemReferenceContentFieldEditorViewModel>" %>
<%@ Import Namespace="Orchard.Core.Common.ViewModels"%>
<%= Html.ItemEditLink(Model.Item) %>

View File

@@ -3,9 +3,11 @@ using System.Linq;
using System.Web.Mvc;
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;
@@ -124,7 +126,7 @@ namespace Orchard.Core.Contents.Controllers {
}
//need to go about this differently - to know when to publish (IPlublishableAspect ?)
if (!contentItem.Has<CommonAspect>())
if (!contentItem.Has<IPublishingControlAspect>())
_contentManager.Publish(contentItem);
_notifier.Information(T("Created content item"));
@@ -161,6 +163,10 @@ namespace Orchard.Core.Contents.Controllers {
return View("Edit", model);
}
//need to go about this differently - to know when to publish (IPlublishableAspect ?)
if (!contentItem.Has<IPublishingControlAspect>())
_contentManager.Publish(contentItem);
return RedirectToAction("Edit", new RouteValueDictionary { { "Id", contentItem.Id } });
}

View File

@@ -4,8 +4,8 @@
<%@ Import Namespace="Orchard.ContentManagement" %>
<div class="summary">
<div class="properties">
<h3><%:Html.ActionLink(Model.Item.Is<IRoutableAspect>() ? Model.Item.As<IRoutableAspect>().Title : string.Format("[title for this {0}]", Model.Item.TypeDefinition.DisplayName), "Edit", new { id = Model.Item.Id }) %></h3><%
Html.Zone("metadata"); %>
<h3><%:Html.ActionLink(Model.Item.Is<IRoutableAspect>() ? Model.Item.As<IRoutableAspect>().Title : string.Format("[title for this {0}]", Model.Item.TypeDefinition.DisplayName), "Edit", new { id = Model.Item.Id }) %></h3>
<div class="metadata"><% Html.Zone("metadata"); %></div>
</div>
<div class="related"><%
Html.Zone("secondary"); %>

View File

@@ -71,12 +71,17 @@
<Compile Include="Common\Settings\BodySettings.cs" />
<Compile Include="Common\ViewModels\CommonMetadataViewModel.cs" />
<Compile Include="Common\ViewModels\ContainerEditorViewModel.cs" />
<Compile Include="Common\ViewModels\PublishEditorViewModel.cs" />
<Compile Include="Common\ViewModels\TextContentFieldDisplayViewModel.cs" />
<Compile Include="Common\ViewModels\TextContentFieldEditorViewModel.cs" />
<Compile Include="Contents\Controllers\ItemController.cs" />
<Compile Include="Contents\Drivers\ContentsDriver.cs" />
<Compile Include="Contents\Handlers\ContentsHandler.cs" />
<Compile Include="PublishLater\Drivers\PublishLaterPartDriver.cs" />
<Compile Include="PublishLater\Models\PublishLaterPart.cs" />
<Compile Include="PublishLater\Handlers\PublishLaterPartHandler.cs" />
<Compile Include="PublishLater\Services\PublishLaterService.cs" />
<Compile Include="PublishLater\Services\IPublishLaterService.cs" />
<Compile Include="PublishLater\ViewModels\PublishLaterViewModel.cs" />
<Compile Include="Routable\Services\RoutableHomePageProvider.cs" />
<Compile Include="Contents\ViewModels\EditItemViewModel.cs" />
<Compile Include="Contents\ViewModels\ListContentsViewModel.cs" />
@@ -103,7 +108,6 @@
<Compile Include="Routable\Models\IsRoutable.cs" />
<Compile Include="Common\Permissions.cs" />
<Compile Include="Common\Models\CommonVersionRecord.cs" />
<Compile Include="Common\Routes.cs" />
<Compile Include="Common\Utilities\LazyField.cs" />
<Compile Include="Common\Handlers\CommonAspectHandler.cs" />
<Compile Include="Common\Models\CommonAspect.cs" />
@@ -214,28 +218,6 @@
</ItemGroup>
<ItemGroup>
<Content Include="Common\Module.txt" />
<Content Include="Common\Scripts\jquery.ui.core.js" />
<Content Include="Common\Scripts\jquery.ui.datepicker.js" />
<Content Include="Common\Scripts\jquery.ui.widget.js" />
<Content Include="Common\Scripts\jquery.utils.js" />
<Content Include="Common\Scripts\ui.timepickr.js" />
<Content Include="Common\Styles\datetime.css" />
<Content Include="Common\Styles\images\ui-bg_flat_0_aaaaaa_40x100.png" />
<Content Include="Common\Styles\images\ui-bg_flat_75_ffffff_40x100.png" />
<Content Include="Common\Styles\images\ui-bg_glass_55_fbf9ee_1x400.png" />
<Content Include="Common\Styles\images\ui-bg_glass_65_ffffff_1x400.png" />
<Content Include="Common\Styles\images\ui-bg_glass_75_dadada_1x400.png" />
<Content Include="Common\Styles\images\ui-bg_glass_75_e6e6e6_1x400.png" />
<Content Include="Common\Styles\images\ui-bg_glass_95_fef1ec_1x400.png" />
<Content Include="Common\Styles\images\ui-bg_highlight-soft_75_cccccc_1x100.png" />
<Content Include="Common\Styles\images\ui-icons_222222_256x240.png" />
<Content Include="Common\Styles\images\ui-icons_2e83ff_256x240.png" />
<Content Include="Common\Styles\images\ui-icons_454545_256x240.png" />
<Content Include="Common\Styles\images\ui-icons_888888_256x240.png" />
<Content Include="Common\Styles\images\ui-icons_cd0a0a_256x240.png" />
<Content Include="Common\Styles\jquery-ui-1.7.2.custom.css" />
<Content Include="Common\Styles\ui.datepicker.css" />
<Content Include="Common\Styles\ui.timepickr.css" />
<Content Include="Common\Views\DefinitionTemplates\BodyTypePartSettings.ascx" />
<Content Include="Common\Views\DefinitionTemplates\BodyPartSettings.ascx" />
<Content Include="Common\Views\DisplayTemplates\Fields\Common.TextField.ascx" />
@@ -247,9 +229,12 @@
<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="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" />
<Content Include="PublishLater\Views\DisplayTemplates\Parts\PublishLater.ascx" />
<Content Include="Common\Views\EditorTemplates\Fields\Common.TextField.ascx" />
<Content Include="Common\Views\EditorTemplates\Parts\Common.Container.ascx" />
<Content Include="Common\Views\EditorTemplates\Parts\Common.Publish.ascx" />
<Content Include="Common\Views\EditorTemplates\PlainTextEditor.ascx" />
<Content Include="Contents\Module.txt" />
<Content Include="Contents\Views\Admin\Edit.ascx" />
@@ -266,6 +251,30 @@
<Content Include="Localization\Styles\base.css" />
<Content Include="Localization\Views\DisplayTemplates\Parts\Localization.ContentTranslations.Summary.ascx" />
<Content Include="Localization\Views\DisplayTemplates\Parts\Localization.ContentTranslations.ascx" />
<Content Include="PublishLater\Module.txt" />
<Content Include="PublishLater\Scripts\jquery.ui.core.js" />
<Content Include="PublishLater\Scripts\jquery.ui.datepicker.js" />
<Content Include="PublishLater\Scripts\jquery.ui.widget.js" />
<Content Include="PublishLater\Scripts\jquery.utils.js" />
<Content Include="PublishLater\Scripts\ui.timepickr.js" />
<Content Include="PublishLater\Styles\datetime.css" />
<Content Include="PublishLater\Styles\images\ui-bg_flat_0_aaaaaa_40x100.png" />
<Content Include="PublishLater\Styles\images\ui-bg_flat_75_ffffff_40x100.png" />
<Content Include="PublishLater\Styles\images\ui-bg_glass_55_fbf9ee_1x400.png" />
<Content Include="PublishLater\Styles\images\ui-bg_glass_65_ffffff_1x400.png" />
<Content Include="PublishLater\Styles\images\ui-bg_glass_75_dadada_1x400.png" />
<Content Include="PublishLater\Styles\images\ui-bg_glass_75_e6e6e6_1x400.png" />
<Content Include="PublishLater\Styles\images\ui-bg_glass_95_fef1ec_1x400.png" />
<Content Include="PublishLater\Styles\images\ui-bg_highlight-soft_75_cccccc_1x100.png" />
<Content Include="PublishLater\Styles\images\ui-icons_222222_256x240.png" />
<Content Include="PublishLater\Styles\images\ui-icons_2e83ff_256x240.png" />
<Content Include="PublishLater\Styles\images\ui-icons_454545_256x240.png" />
<Content Include="PublishLater\Styles\images\ui-icons_888888_256x240.png" />
<Content Include="PublishLater\Styles\images\ui-icons_cd0a0a_256x240.png" />
<Content Include="PublishLater\Styles\jquery-ui-1.7.2.custom.css" />
<Content Include="PublishLater\Styles\ui.datepicker.css" />
<Content Include="PublishLater\Styles\ui.timepickr.css" />
<Content Include="PublishLater\Views\EditorTemplates\Parts\PublishLater.ascx" />
<Content Include="Reports\Module.txt" />
<Content Include="Reports\Views\Admin\Display.aspx" />
<Content Include="Reports\Views\Admin\Index.aspx" />
@@ -334,6 +343,7 @@
<Content Include="Routable\Views\Web.config" />
<Content Include="Localization\Views\Web.config" />
<Content Include="Reports\Views\Web.config" />
<Content Include="PublishLater\Views\Web.config" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

View File

@@ -0,0 +1,71 @@
using System;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Core.Common.Services;
using Orchard.Core.PublishLater.Models;
using Orchard.Core.PublishLater.Services;
using Orchard.Core.PublishLater.ViewModels;
using Orchard.Localization;
using Orchard.UI.Notify;
namespace Orchard.Core.PublishLater.Drivers {
public class PublishLaterPartDriver : ContentPartDriver<PublishLaterPart> {
private const string TemplatePrefix = "PublishLater";
private readonly ICommonService _commonService;
private readonly IPublishLaterService _publishLaterService;
public PublishLaterPartDriver(
IOrchardServices services,
ICommonService commonService,
IPublishLaterService publishLaterService) {
_commonService = commonService;
_publishLaterService = publishLaterService;
T = NullLocalizer.Instance;
Services = services;
}
public Localizer T { get; set; }
public IOrchardServices Services { get; set; }
protected override DriverResult Display(PublishLaterPart part, string displayType) {
var model = new PublishLaterViewModel(part) {
ScheduledPublishUtc = part.ScheduledPublishUtc.Value
};
return ContentPartTemplate(model, "Parts/PublishLater.Metadata").LongestMatch(displayType, "Summary", "SummaryAdmin").Location("metadata", "1");
}
protected override DriverResult Editor(PublishLaterPart part) {
return PublishEditor(part, null);
}
protected override DriverResult Editor(PublishLaterPart instance, IUpdateModel updater) {
return PublishEditor(instance, updater);
}
DriverResult PublishEditor(PublishLaterPart part, IUpdateModel updater) {
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;
}
}
return ContentPartTemplate(model, "Parts/PublishLater", TemplatePrefix).Location("secondary", "1");
}
}
}

View File

@@ -0,0 +1,16 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using Orchard.Core.PublishLater.Models;
using Orchard.Core.PublishLater.Services;
namespace Orchard.Core.PublishLater.Handlers {
public class PublishLaterPartHandler : ContentHandler {
private readonly IPublishLaterService _publishLaterService;
public PublishLaterPartHandler(IPublishLaterService publishLaterService) {
_publishLaterService = publishLaterService;
OnLoaded<PublishLaterPart>((context, publishLater) => publishLater.ScheduledPublishUtc.Loader(delegate { return _publishLaterService.GetScheduledPublishUtc(publishLater.As<PublishLaterPart>()); }));
}
}
}

View File

@@ -0,0 +1,11 @@
using System;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.Utilities;
namespace Orchard.Core.PublishLater.Models {
public class PublishLaterPart : ContentPart<PublishLaterPart>, IPublishingControlAspect {
private readonly LazyField<DateTime?> _scheduledPublishUtc = new LazyField<DateTime?>();
public LazyField<DateTime?> ScheduledPublishUtc { get { return _scheduledPublishUtc; } }
}
}

View File

@@ -0,0 +1,12 @@
Name: PublishLater
antiforgery: enabled
author: The Orchard Team
website: http://orchardproject.net
version: 0.1
orchardversion: 0.1.2010.0312
description: The PublishLater module introduces draft creation and scheduled publishing functionality.
features:
PublishLater:
Description: Draft creation and scheduled publishing.
Category: Content
Dependencies: Common

View File

@@ -0,0 +1,10 @@
using System;
using Orchard.ContentManagement;
using Orchard.Core.PublishLater.Models;
namespace Orchard.Core.PublishLater.Services {
public interface IPublishLaterService : IDependency {
DateTime? GetScheduledPublishUtc(PublishLaterPart publishLaterPart);
void Publish(ContentItem contentItem, DateTime scheduledPublishUtc);
}
}

View File

@@ -0,0 +1,23 @@
using System;
using Orchard.ContentManagement;
using Orchard.Core.PublishLater.Models;
using Orchard.Tasks.Scheduling;
namespace Orchard.Core.PublishLater.Services {
public class PublishLaterService : IPublishLaterService {
private readonly IPublishingTaskManager _publishingTaskManager;
public PublishLaterService(IPublishingTaskManager publishingTaskManager) {
_publishingTaskManager = publishingTaskManager;
}
void IPublishLaterService.Publish(ContentItem contentItem, DateTime scheduledPublishUtc) {
_publishingTaskManager.Publish(contentItem, scheduledPublishUtc);
}
DateTime? IPublishLaterService.GetScheduledPublishUtc(PublishLaterPart publishLaterPart) {
IScheduledTask task = _publishingTaskManager.GetPublishTask(publishLaterPart.ContentItem);
return (task == null ? null : task.ScheduledUtc);
}
}
}

View File

@@ -6,9 +6,9 @@ html.dyn input.hinted {
color:#ccc;
font-style:italic;
}
input#CommonAspect_ScheduledPublishUtcDate {
input#PublishLater_ScheduledPublishUtcDate {
width:56%;
}
input#CommonAspect_ScheduledPublishUtcTime {
input#PublishLater_ScheduledPublishUtcTime {
width:36%;
}

View File

@@ -1,19 +1,20 @@
using System;
using Orchard.ContentManagement;
using Orchard.Core.Common.Models;
using Orchard.Core.PublishLater.Models;
namespace Orchard.Core.Common.ViewModels {
public class PublishEditorViewModel {
private readonly CommonAspect _commonAspect;
namespace Orchard.Core.PublishLater.ViewModels {
public class PublishLaterViewModel {
private readonly PublishLaterPart _publishLaterPart;
private string _scheduledPublishUtcTime;
private string _scheduledPublishUtcDate;
public PublishEditorViewModel(CommonAspect commonAspect) {
_commonAspect = commonAspect;
public PublishLaterViewModel(PublishLaterPart publishLaterPart) {
_publishLaterPart = publishLaterPart;
}
public string Command { get; set; }
public ContentItem ContentItem { get { return _commonAspect.ContentItem; } }
public ContentItem ContentItem { get { return _publishLaterPart.ContentItem; } }
public bool IsPublished {
get { return ContentItem.VersionRecord != null && ContentItem.VersionRecord.Published; }
@@ -32,6 +33,8 @@ namespace Orchard.Core.Common.ViewModels {
get { return IsPublished || ContentItem.ContentManager.Get(ContentItem.Id, VersionOptions.Published) != null; }
}
public DateTime? VersionPublishedUtc { get { return ContentItem.As<CommonAspect>().VersionPublishedUtc; } }
public DateTime? ScheduledPublishUtc { get; set; }
public string ScheduledPublishUtcDate {

View File

@@ -0,0 +1,31 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Core.PublishLater.ViewModels.PublishLaterViewModel>" %>
<ul class="pageStatus">
<li><%
// Published or not
if (Model.HasPublished) { %>
<img class="icon" src="<%=ResolveUrl("~/Modules/Orchard.Pages/Content/Admin/images/online.gif") %>" alt="<%:T("Online") %>" title="<%:T("The page is currently online") %>" /> <%:T("Published") %>&nbsp;&#124;&nbsp;<%
}
else { %>
<img class="icon" src="<%=ResolveUrl("~/Modules/Orchard.Pages/Content/Admin/images/offline.gif") %>" alt="<%:T("Offline") %>" title="<%:T("The page is currently offline") %>" /> <%:T("Not Published") %>&nbsp;&#124;&nbsp;<%
} %>
</li>
<li><%
// Does the page have a draft
if (Model.HasDraft) { %>
<img class="icon" src="<%=ResolveUrl("~/Modules/Orchard.Pages/Content/Admin/images/draft.gif") %>" alt="<%:T("Draft") %>" title="<%:T("The page has a draft") %>" /><%:T("Draft") %>&nbsp;&#124;&nbsp;<%
}
else { %>
<%:T("No Draft") %>&nbsp;&#124;&nbsp;<%
} %>
</li>
<li><%
if ((Model.ScheduledPublishUtc.HasValue && Model.ScheduledPublishUtc.Value > DateTime.UtcNow) || (Model.IsPublished && Model.VersionPublishedUtc.HasValue)) {
if (Model.IsPublished && Model.VersionPublishedUtc.HasValue) { %>
<%:T("Published: {0}", Html.DateTimeRelative(Model.VersionPublishedUtc.Value, T)) %><%
}
else { %>
<img class="icon" src="<%=ResolveUrl("~/Modules/Orchard.Pages/Content/Admin/images/scheduled.gif") %>" alt="<%:T("Scheduled") %>" title="<%:T("The page is scheduled for publishing") %>" /><%:T("Scheduled") %>
<%:Html.DateTime(Model.ScheduledPublishUtc.Value, T("M/d/yyyy h:mm tt")) %><%
} %>&nbsp;&#124;&nbsp;</li><%
} %>
</ul>

View File

@@ -0,0 +1 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Core.PublishLater.ViewModels.PublishLaterViewModel>" %>

View File

@@ -0,0 +1,12 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Core.PublishLater.ViewModels.PublishLaterViewModel>" %>
<% // 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

@@ -0,0 +1 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Core.PublishLater.ViewModels.PublishLaterViewModel>" %>

View File

@@ -1,4 +1,4 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Core.Common.ViewModels.PublishEditorViewModel>" %>
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.Core.PublishLater.ViewModels.PublishLaterViewModel>" %>
<% Html.RegisterStyle("datetime.css"); %>
<% Html.RegisterStyle("jquery-ui-1.7.2.custom.css"); %>
<% Html.RegisterStyle("ui.datepicker.css"); %>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0"?>
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
Enabling request validation in view pages would cause validation to occur
after the input has already been processed by the controller. By default
MVC performs request validation before a controller processes the input.
To change this behavior apply the ValidateInputAttribute to a
controller or action.
-->
<pages
validateRequest="false"
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<controls>
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
</controls>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
</configuration>

View File

@@ -12,7 +12,10 @@ namespace Orchard.Core.Routable.Handlers {
_routablePathConstraint = routablePathConstraint;
Filters.Add(StorageFilter.For(repository));
OnPublished<IsRoutable>((context, routable) => _routablePathConstraint.AddPath(routable.Path));
OnPublished<IsRoutable>((context, routable) => {
if (!string.IsNullOrEmpty(routable.Path))
_routablePathConstraint.AddPath(routable.Path);
});
}
}
public class IsRoutableHandler : ContentHandlerBase {

View File

@@ -18,24 +18,38 @@ namespace Orchard.Core.Routable {
public IEnumerable<RouteDescriptor> GetRoutes() {
return new[] {
new RouteDescriptor {
Priority = 10,
Route = new Route(
"{*path}",
new RouteValueDictionary {
{"area", "Routable"},
{"controller", "Item"},
{"action", "Display"}
},
new RouteValueDictionary {
{"path", _routablePathConstraint}
},
new RouteValueDictionary {
{"area", "Routable"}
},
new MvcRouteHandler())
}
};
new RouteDescriptor {
Route = new Route(
"Admin/Common/Routable/Slugify",
new RouteValueDictionary {
{"area", "Common"},
{"controller", "Routable"},
{"action", "Slugify"}
},
new RouteValueDictionary(),
new RouteValueDictionary {
{"area", "Common"}
},
new MvcRouteHandler())
},
new RouteDescriptor {
Priority = 10,
Route = new Route(
"{*path}",
new RouteValueDictionary {
{"area", "Routable"},
{"controller", "Item"},
{"action", "Display"}
},
new RouteValueDictionary {
{"path", _routablePathConstraint}
},
new RouteValueDictionary {
{"area", "Routable"}
},
new MvcRouteHandler())
}
};
}
}

View File

@@ -8,6 +8,7 @@ using Orchard.Blogs.Services;
using Orchard.ContentManagement;
using Orchard.Core.Common.Models;
using Orchard.ContentManagement.Handlers;
using Orchard.Core.PublishLater.Models;
using Orchard.Core.Routable.Models;
using Orchard.Localization;
@@ -24,6 +25,7 @@ namespace Orchard.Blogs.Handlers {
Filters.Add(new ActivatingFilter<BlogPost>(BlogPostDriver.ContentType.Name));
Filters.Add(new ActivatingFilter<CommonAspect>(BlogPostDriver.ContentType.Name));
Filters.Add(new ActivatingFilter<PublishLaterPart>(BlogPostDriver.ContentType.Name));
Filters.Add(new ActivatingFilter<ContentPart<CommonVersionRecord>>(BlogPostDriver.ContentType.Name));
Filters.Add(new ActivatingFilter<IsRoutable>(BlogPostDriver.ContentType.Name));
Filters.Add(new ActivatingFilter<BodyAspect>(BlogPostDriver.ContentType.Name));

View File

@@ -66,6 +66,7 @@ namespace Orchard.Setup.Services {
string[] hardcoded = {
"Orchard.Framework",
"Common",
"PublishLater",
"Contents",
"Dashboard",
"Reports",

View File

@@ -677,6 +677,9 @@ table .button {
.contentItems h3 {
padding-top:0;
}
.contentItems .metadata ul {
display:inline;
}
.contentItems .properties li {
border:0;
float:left;

View File

@@ -0,0 +1,8 @@
using System;
using Orchard.ContentManagement.Utilities;
namespace Orchard.ContentManagement.Aspects {
public interface IPublishingControlAspect {
LazyField<DateTime?> ScheduledPublishUtc { get; }
}
}

View File

@@ -137,6 +137,7 @@
<Compile Include="ContentManagement\Aspects\ICommonAspect.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ContentManagement\Aspects\IPublishingControlAspect.cs" />
<Compile Include="ContentManagement\Aspects\IRoutableAspect.cs" />
<Compile Include="ContentManagement\ContentExtensions.cs">
<SubType>Code</SubType>