#17772: Making creation date editable on blog posts and pages by making it a setting on the common part

--HG--
branch : 1.x
This commit is contained in:
Andre Rodrigues
2011-05-11 14:08:22 -07:00
parent 4e742d28b3
commit 755df9e913
13 changed files with 225 additions and 25 deletions

View File

@@ -1,8 +1,12 @@
using System.Xml;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Xml;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.Handlers;
using Orchard.Core.Common.Models;
using Orchard.Core.Common.Settings;
using Orchard.Core.Common.ViewModels;
using Orchard.Localization;
using Orchard.Security;
@@ -16,6 +20,9 @@ namespace Orchard.Core.Common.Drivers {
private readonly IMembershipService _membershipService;
private readonly IClock _clock;
private const string DatePattern = "M/d/yyyy";
private const string TimePattern = "h:mm tt";
public CommonPartDriver(
IOrchardServices services,
IContentManager contentManager,
@@ -51,9 +58,7 @@ namespace Orchard.Core.Common.Drivers {
}
protected override DriverResult Editor(CommonPart part, dynamic shapeHelper) {
return Combined(
OwnerEditor(part, null, shapeHelper),
ContainerEditor(part, null, shapeHelper));
return BuildEditor(part, null, shapeHelper);
}
protected override DriverResult Editor(CommonPart part, IUpdateModel updater, dynamic shapeHelper) {
@@ -61,9 +66,22 @@ namespace Orchard.Core.Common.Drivers {
part.ModifiedUtc = _clock.UtcNow;
part.VersionModifiedUtc = _clock.UtcNow;
return Combined(
OwnerEditor(part, updater, shapeHelper),
ContainerEditor(part, updater, shapeHelper));
return BuildEditor(part, updater, shapeHelper);
}
private DriverResult BuildEditor(CommonPart part, IUpdateModel updater, dynamic shapeHelper) {
List<DriverResult> parts = new List<DriverResult>();
CommonTypePartSettings commonTypePartSettings = GetTypeSettings(part);
parts.Add(OwnerEditor(part, updater, shapeHelper));
if (commonTypePartSettings.ShowCreatedUtcEditor) {
parts.Add(CreatedUtcEditor(part, updater, shapeHelper));
}
parts.Add(ContainerEditor(part, updater, shapeHelper));
return Combined(parts.ToArray());
}
DriverResult OwnerEditor(CommonPart part, IUpdateModel updater, dynamic shapeHelper) {
@@ -95,6 +113,42 @@ namespace Orchard.Core.Common.Drivers {
() => shapeHelper.EditorTemplate(TemplateName: "Parts.Common.Owner", Model: model, Prefix: Prefix));
}
DriverResult CreatedUtcEditor(CommonPart part, IUpdateModel updater, dynamic shapeHelper) {
var currentUser = _authenticationService.GetAuthenticatedUser();
if (!_authorizationService.TryCheckAccess(StandardPermissions.SiteOwner, currentUser, part)) {
return null;
}
var model = new CreatedUtcEditorViewModel();
if (part.CreatedUtc != null) {
model.CreatedDate = part.CreatedUtc.Value.ToLocalTime().ToString(DatePattern, CultureInfo.InvariantCulture);
model.CreatedTime = part.CreatedUtc.Value.ToLocalTime().ToString(TimePattern, CultureInfo.InvariantCulture);
}
if (updater != null) {
updater.TryUpdateModel(model, Prefix, null, null);
if (!string.IsNullOrWhiteSpace(model.CreatedDate) && !string.IsNullOrWhiteSpace(model.CreatedTime)) {
DateTime createdUtc;
string parseDateTime = String.Concat(model.CreatedDate, " ", model.CreatedTime);
// use an english culture as it is the one used by jQuery.datepicker by default
if (DateTime.TryParse(parseDateTime, CultureInfo.GetCultureInfo("en-US"), DateTimeStyles.AssumeLocal, out createdUtc)) {
part.CreatedUtc = createdUtc;
}
else {
updater.AddModelError(Prefix, T("{0} is an invalid date and time", parseDateTime));
}
}
else {
updater.AddModelError(Prefix, T("Both the date and time need to be specified."));
}
}
return ContentShape("Parts_Common_CreatedUtc_Edit",
() => shapeHelper.EditorTemplate(TemplateName: "Parts.Common.CreatedUtc", Model: model, Prefix: Prefix));
}
DriverResult ContainerEditor(CommonPart part, IUpdateModel updater, dynamic shapeHelper) {
var currentUser = _authenticationService.GetAuthenticatedUser();
if (!_authorizationService.TryCheckAccess(StandardPermissions.SiteOwner, currentUser, part)) {
@@ -124,6 +178,10 @@ namespace Orchard.Core.Common.Drivers {
() => shapeHelper.EditorTemplate(TemplateName: "Parts.Common.Container", Model: model, Prefix: Prefix));
}
private static CommonTypePartSettings GetTypeSettings(CommonPart part) {
return part.Settings.GetModel<CommonTypePartSettings>();
}
protected override void Importing(CommonPart part, ImportContentContext context) {
var owner = context.Attribute(part.PartDefinition.Name, "Owner");
if (owner != null) {

View File

@@ -12,6 +12,7 @@
<!-- edit "shape" -->
<Place Parts_Common_Body_Edit="Content:2"/>
<Place Parts_Common_Owner_Edit="Content:20"/>
<Place Parts_Common_CreatedUtc_Edit="Content:18"/>
<Place Parts_Common_Container_Edit="Content:20"/>
<Place Fields_Common_Text_Edit="Content:2.5"/>
<!-- default positioning -->

View File

@@ -0,0 +1,9 @@
using Orchard.UI.Resources;
namespace Orchard.Core.Common {
public class ResourceManifest : IResourceManifestProvider {
public void BuildManifests(ResourceManifestBuilder builder) {
builder.Add().DefineStyle("Common_DatePicker").SetUrl("orchard-common-datetime.css");
}
}
}

View File

@@ -0,0 +1,32 @@
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.ContentManagement.ViewModels;
namespace Orchard.Core.Common.Settings {
public class CommonTypePartSettings {
public bool ShowCreatedUtcEditor { get; set; }
}
public class CommonSettingsHooks : ContentDefinitionEditorEventsBase {
public override IEnumerable<TemplateViewModel> TypePartEditor(ContentTypePartDefinition definition) {
if (definition.PartDefinition.Name != "CommonPart")
yield break;
var model = definition.Settings.GetModel<CommonTypePartSettings>();
yield return DefinitionTemplate(model);
}
public override IEnumerable<TemplateViewModel> TypePartEditorUpdate(ContentTypePartDefinitionBuilder builder, IUpdateModel updateModel) {
if (builder.Name != "CommonPart")
yield break;
var model = new CommonTypePartSettings();
updateModel.TryUpdateModel(model, "CommonTypePartSettings", null, null);
builder.WithSetting("CommonTypePartSettings.ShowCreatedUtcEditor", model.ShowCreatedUtcEditor.ToString());
yield return DefinitionTemplate(model);
}
}
}

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.web>
<httpHandlers>
<!-- iis6 - for any request in this location, return via managed static file handler -->
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers accessPolicy="Script,Read">
<!--
iis7 - for any request to a file exists on disk, return it via native http module.
accessPolicy 'Script' is to allow for a managed 404 page.
-->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

View File

@@ -0,0 +1,14 @@
fieldset.createdutc-datetime {
float:left;
clear:none;
white-space: nowrap;
vertical-align: middle;
}
fieldset.createdutc-datetime legend {
display:none;
}
fieldset.createdutc-datetime input {
padding:1px;
text-align:center;
color:#666;
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.Core.Common.ViewModels {
public class CreatedUtcEditorViewModel {
public string CreatedDate { get; set; }
public string CreatedTime { get; set; }
}
}

View File

@@ -0,0 +1,6 @@
@model Orchard.Core.Common.Settings.CommonTypePartSettings
<fieldset>
@Html.CheckBoxFor(m => m.ShowCreatedUtcEditor)
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.ShowCreatedUtcEditor)">@T("Show editor for create date time")</label>
@Html.ValidationMessageFor(m => m.ShowCreatedUtcEditor)
</fieldset>

View File

@@ -0,0 +1,41 @@
@model CreatedUtcEditorViewModel
@using Orchard.Core.Common.ViewModels;
@{
Script.Require("jQueryUtils_TimePicker");
Script.Require("jQueryUI_DatePicker");
Style.Require("Common_DatePicker");
Style.Require("jQueryUtils_TimePicker");
Style.Require("jQueryUI_DatePicker");
}
<fieldset class="createdutc-datetime">
@Html.LabelFor(m => m.CreatedDate, T("Created On"))
<label class="forpicker" for="@ViewData.TemplateInfo.GetFullHtmlFieldId("CreatedDate")">@T("Date")</label>
@Html.EditorFor(m => m.CreatedDate)
<label class="forpicker" for="@ViewData.TemplateInfo.GetFullHtmlFieldId("CreatedTime")">@T("Time")</label>
@Html.EditorFor(m => m.CreatedTime)
</fieldset>
@using(Script.Foot()) {
<script type="text/javascript">
//<![CDATA[
$(function () {
var clearHint = function ($this) { if ($this.val() == $this.data("hint")) { $this.removeClass("hinted").val("") } };
var resetHint = function ($this) { setTimeout(function () { if (!$this.val()) { $this.addClass("hinted").val($this.data("hint")) } }, 300) };
@* todo: (heskew) make a plugin *@
$("label.forpicker").each(function () {
var $this = $(this);
var pickerInput = $("#" + $this.attr("for"));
if (!pickerInput.val()) {
pickerInput.data("hint", $this.text());
pickerInput.addClass("hinted")
.val(pickerInput.data("hint"))
.focus(function() {clearHint($(this));})
.blur(function() {resetHint($(this));});
$this.closest("form").submit(function() {clearHint(pickerInput); pickerInput = 0;});
}
});
$('#@ViewData.TemplateInfo.GetFullHtmlFieldId("CreatedDate")').datepicker({ showAnim: "" }).focus(function () { $('#@ViewData.TemplateInfo.GetFullHtmlFieldId("Command_Created")').attr("checked", "checked") });
$('#@ViewData.TemplateInfo.GetFullHtmlFieldId("CreatedTime")').timepickr().focus(function () { $('#@ViewData.TemplateInfo.GetFullHtmlFieldId("Command_Created")').attr("checked", "checked") });
})
//]]>
</script>
}

View File

@@ -66,7 +66,10 @@
<Compile Include="Common\Models\CommonPartVersionRecord.cs" />
<Compile Include="Common\Models\IdentityPartRecord.cs" />
<Compile Include="Common\Models\IdentityPart.cs" />
<Compile Include="Common\ResourceManifest.cs" />
<Compile Include="Common\Services\XmlRpcHandler.cs" />
<Compile Include="Common\Settings\CommonSettings.cs" />
<Compile Include="Common\ViewModels\CreatedUtcEditorViewModel.cs" />
<Compile Include="Containers\Controllers\ItemController.cs" />
<Compile Include="Containers\Drivers\ContainablePartDriver.cs" />
<Compile Include="Containers\Drivers\ContainerPartDriver.cs" />
@@ -243,6 +246,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="Common\Module.txt" />
<Content Include="Common\Styles\orchard-common-datetime.css" />
<Content Include="Common\Views\DefinitionTemplates\BodyTypePartSettings.cshtml" />
<Content Include="Common\Views\DefinitionTemplates\BodyPartSettings.cshtml" />
<Content Include="Common\Views\Fields.Common.Text.cshtml" />
@@ -427,6 +431,17 @@
<ItemGroup>
<Content Include="web.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Common\Views\DefinitionTemplates\CommonTypePartSettings.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Common\Views\EditorTemplates\Parts.Common.CreatedUtc.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Common\Styles\Web.config">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@@ -46,7 +46,8 @@ namespace Orchard.Blogs {
ContentDefinitionManager.AlterTypeDefinition("BlogPost",
cfg => cfg
.WithPart("BlogPostPart")
.WithPart("CommonPart")
.WithPart("CommonPart", p => p
.WithSetting("CommonTypePartSettings.ShowCreatedUtcEditor", "true"))
.WithPart("PublishLaterPart")
.WithPart("RoutePart")
.WithPart("BodyPart")

View File

@@ -8,23 +8,18 @@ namespace Orchard.Experimental {
public class TestingListsMigrations : DataMigrationImpl {
public int Create() {
ContentDefinitionManager.AlterTypeDefinition("ListItem",
cfg => cfg
.WithPart("CommonPart")
.WithPart("RoutePart")
.WithPart("BodyPart")
.WithPart("ContainablePart")
.Creatable());
cfg => cfg
.WithPart("CommonPart")
.WithPart("RoutePart")
.WithPart("BodyPart")
.WithPart("ContainablePart")
.Creatable()
);
ContentDefinitionManager.AlterTypeDefinition("Page",
cfg => cfg
.WithPart("ContainablePart"));
//ContentDefinitionManager.AlterTypeDefinition("ListWidget",
// cfg => cfg
// .WithPart("CommonPart")
// .WithPart("WidgetPart")
// .WithPart("ListWidgetPart")
// .WithSetting("Stereotype", "Widget"));
cfg => cfg
.WithPart("ContainablePart")
);
return 1;
}

View File

@@ -6,8 +6,9 @@ namespace Orchard.Pages {
public class Migrations : DataMigrationImpl {
public int Create() {
ContentDefinitionManager.AlterTypeDefinition("Page",
cfg=>cfg
.WithPart("CommonPart")
cfg => cfg
.WithPart("CommonPart", p => p
.WithSetting("CommonTypePartSettings.ShowCreatedUtcEditor", "true"))
.WithPart("PublishLaterPart")
.WithPart("RoutePart")
.WithPart("BodyPart")