Merge dev => perf

--HG--
branch : perf
This commit is contained in:
Renaud Paquay
2010-11-15 16:23:24 -08:00
520 changed files with 29102 additions and 26066 deletions

View File

@@ -10,10 +10,10 @@
-->
<!-- edit shapes getting default placements -->
<!-- edit "shape" -->
<Place Parts_Common_Body_Edit="Primary:2"/>
<Place Parts_Common_Owner_Edit="Primary:20"/>
<Place Parts_Common_Container_Edit="Primary:20"/>
<Place Fields_Common_Text_Edit="Primary:2.5"/>
<Place Parts_Common_Body_Edit="Content:2"/>
<Place Parts_Common_Owner_Edit="Content:20"/>
<Place Parts_Common_Container_Edit="Content:20"/>
<Place Fields_Common_Text_Edit="Content:2.5"/>
<!-- default positioning -->
<!-- show summary for all DisplayType by default -->
<Place Parts_Common_Body_Summary="Content:5"/>
@@ -22,7 +22,8 @@
<Match DisplayType="Detail">
<!-- hide summary, show full content, for Detail -->
<Place Parts_Common_Body_Summary="-"
Parts_Common_Body="Content:5" />
Parts_Common_Body="Content:5"
Parts_Common_Metadata="Meta:2"/>
</Match>
<Match DisplayType="Summary">
<Place Parts_Common_Metadata_Summary="Meta:2"/>

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Routing;
namespace Orchard.Core.Containers {
public interface IContainersPathConstraint : IRouteConstraint, ISingletonDependency {
void SetPaths(IEnumerable<string> paths);
string FindPath(string path);
void AddPath(string path);
}
public class ContainersPathConstraint : IContainersPathConstraint {
private IDictionary<string, string> _paths = new Dictionary<string, string>();
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) {
if (routeDirection == RouteDirection.UrlGeneration)
return true;
object value;
if (values.TryGetValue(parameterName, out value)) {
var parameterValue = Convert.ToString(value);
return _paths.ContainsKey(parameterValue);
}
return false;
}
public void SetPaths(IEnumerable<string> paths) {
// Note: this does not need to be synchronized as long as the dictionary itself is treated as immutable.
// do not add or remove to the dictionary instance once created. recreate and reassign instead.
_paths = paths.Distinct().ToDictionary(path => path, StringComparer.OrdinalIgnoreCase);
}
public string FindPath(string path) {
string actual;
return _paths.TryGetValue(path, out actual) ? actual : path;
}
public void AddPath(string path) {
SetPaths(_paths.Keys.Concat(new[] { path }));
}
}
}

View File

@@ -0,0 +1,73 @@
using System;
using System.Linq;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.Core.Common.Models;
using Orchard.Core.Containers.Extensions;
using Orchard.Core.Containers.Models;
using Orchard.Core.Routable.Models;
using Orchard.DisplayManagement;
using Orchard.Themes;
using Orchard.UI.Navigation;
namespace Orchard.Core.Containers.Controllers {
public class ItemController : Controller {
private readonly IContentManager _contentManager;
private readonly IContainersPathConstraint _containersPathConstraint;
public ItemController(IContentManager contentManager, IContainersPathConstraint containersPathConstraint, IShapeFactory shapeFactory) {
_contentManager = contentManager;
_containersPathConstraint = containersPathConstraint;
Shape = shapeFactory;
}
dynamic Shape { get; set; }
[Themed]
public ActionResult Display(string path, Pager pager) {
var matchedPath = _containersPathConstraint.FindPath(path);
if (string.IsNullOrEmpty(matchedPath)) {
throw new ApplicationException("404 - should not have passed path constraint");
}
var hits = _contentManager
.Query<RoutePart, RoutePartRecord>(VersionOptions.Published)
.Where(r => r.Path == matchedPath)
.Slice(0, 2);
if (hits.Count() == 0) {
throw new ApplicationException("404 - should not have passed path constraint");
}
if (hits.Count() != 1) {
throw new ApplicationException("Ambiguous content");
}
var container = _contentManager.Get(hits.Single().Id);
IContentQuery<ContentItem> query = _contentManager
.Query(VersionOptions.Published)
.Join<CommonPartRecord>().Where(cr => cr.Container.Id == container.Id);
var descendingOrder = container.As<ContainerPart>().Record.OrderByDirection == (int) OrderByDirection.Descending;
query = query.OrderBy(container.As<ContainerPart>().Record.OrderByProperty, descendingOrder);
pager.PageSize = pager.PageSize != Pager.PageSizeDefault && container.As<ContainerPart>().Record.Paginated
? pager.PageSize
: container.As<ContainerPart>().Record.PageSize;
var pagerShape = Shape.Pager(pager).TotalItemCount(query.Count());
var startIndex = container.As<ContainerPart>().Record.Paginated ? pager.GetStartIndex() : 0;
var pageOfItems = query.Slice(startIndex, pager.PageSize).ToList();
var list = Shape.List();
list.AddRange(pageOfItems.Select(item => _contentManager.BuildDisplay(item, "Summary")));
var viewModel = Shape.ViewModel()
.ContentItems(list)
.Pager(pagerShape)
.ShowPager(container.As<ContainerPart>().Record.Paginated);
return View(viewModel);
}
}
}

View File

@@ -0,0 +1,60 @@
using System;
using System.Linq;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.Drivers;
using Orchard.Core.Containers.Models;
using Orchard.Core.Containers.ViewModels;
using Orchard.Localization;
namespace Orchard.Core.Containers.Drivers {
public class ContainablePartDriver : ContentPartDriver<ContainablePart> {
private readonly IContentManager _contentManager;
public ContainablePartDriver(IContentManager contentManager) {
_contentManager = contentManager;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
protected override DriverResult Editor(ContainablePart part, dynamic shapeHelper) {
return Editor(part, null, shapeHelper);
}
protected override DriverResult Editor(ContainablePart part, IUpdateModel updater, dynamic shapeHelper) {
return ContentShape(
"Parts_Containable_Edit",
() => {
var commonPart = part.As<ICommonPart>();
var model = new ContainableViewModel();
if (commonPart.Container != null) {
model.ContainerId = commonPart.Container.Id;
}
if (updater != null) {
var oldContainerId = model.ContainerId;
updater.TryUpdateModel(model, "Containable", null, null);
if (oldContainerId != model.ContainerId) {
commonPart.Container = _contentManager.Get(model.ContainerId, VersionOptions.Latest);
}
}
var containers = _contentManager.Query<ContainerPart, ContainerPartRecord>(VersionOptions.Latest).List();
var listItems = new[] { new SelectListItem { Text = T("(None)").Text, Value = "0" } }
.Concat(containers.Select(x => new SelectListItem {
Value = Convert.ToString(x.Id),
Text = x.ContentItem.TypeDefinition.DisplayName + ": " + x.As<IRoutableAspect>().Title,
Selected = x.Id == model.ContainerId,
}))
.ToList();
model.AvailableContainers = new SelectList(listItems, "Value", "Text", model.ContainerId);
return shapeHelper.EditorTemplate(TemplateName: "Containable", Model: model, Prefix: "Containable");
});
}
}
}

View File

@@ -0,0 +1,30 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.Handlers;
using Orchard.Core.Containers.Models;
using Orchard.Data;
namespace Orchard.Core.Containers.Drivers {
public class ContainerCustomPartDriver : ContentPartDriver<ContainerCustomPart> {
protected override DriverResult Editor(ContainerCustomPart part, dynamic shapeHelper) {
return Editor(part, null, shapeHelper);
}
protected override DriverResult Editor(ContainerCustomPart part, IUpdateModel updater, dynamic shapeHelper) {
return ContentShape(
"Parts_ContainerCustom_Edit",
() => {
if (updater != null)
updater.TryUpdateModel(part, "ContainerCustom", null, null);
return shapeHelper.EditorTemplate(TemplateName: "ContainerCustom", Model: part, Prefix: "ContainerCustom");
});
}
}
public class ContainerCustomPartHandler : ContentHandler {
public ContainerCustomPartHandler(IRepository<ContainerCustomPartRecord> repository) {
Filters.Add(StorageFilter.For(repository));
}
}
}

View File

@@ -0,0 +1,41 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.Handlers;
using Orchard.Core.Common.Models;
using Orchard.Core.Containers.Models;
using Orchard.Core.Containers.Settings;
using Orchard.Data;
namespace Orchard.Core.Containers.Drivers {
public class ContainerPartDriver : ContentPartDriver<ContainerPart> {
protected override DriverResult Editor(ContainerPart part, dynamic shapeHelper) {
return Editor(part, null, shapeHelper);
}
protected override DriverResult Editor(ContainerPart part, ContentManagement.IUpdateModel updater, dynamic shapeHelper) {
return ContentShape(
"Parts_Container_Edit",
() => {
if (updater != null)
updater.TryUpdateModel(part, "Container", null, null);
return shapeHelper.EditorTemplate(TemplateName: "Container", Model: part, Prefix: "Container");
});
}
}
public class ContainerPartHandler : ContentHandler {
public ContainerPartHandler(IRepository<ContainerPartRecord> repository, IOrchardServices orchardServices) {
Filters.Add(StorageFilter.For(repository));
OnInitializing<ContainerPart>((context, part) => {
part.Record.PageSize = part.Settings.GetModel<ContainerTypePartSettings>().PageSizeDefault
?? part.PartDefinition.Settings.GetModel<ContainerPartSettings>().PageSizeDefault;
part.Record.Paginated = part.Settings.GetModel<ContainerTypePartSettings>().PaginatedDefault
?? part.PartDefinition.Settings.GetModel<ContainerPartSettings>().PaginatedDefault;
//hard-coded defaults for ordering
part.Record.OrderByProperty = part.Is<CommonPart>() ? "CommonPart.PublishedUtc" : "";
part.Record.OrderByDirection = (int)OrderByDirection.Descending;
});
}
}
}

View File

@@ -0,0 +1,94 @@
using System;
using System.Linq;
using System.Web.Mvc;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.Handlers;
using Orchard.Core.Common.Models;
using Orchard.Core.Containers.Extensions;
using Orchard.Core.Containers.Models;
using Orchard.Core.Containers.ViewModels;
using Orchard.Data;
using Orchard.Localization;
namespace Orchard.Core.Containers.Drivers {
public class ContainerWidgetPartDriver : ContentPartDriver<ContainerWidgetPart> {
private readonly IContentManager _contentManager;
public ContainerWidgetPartDriver(IContentManager contentManager) {
_contentManager = contentManager;
T = NullLocalizer.Instance;
}
public Localizer T { get; set; }
protected override DriverResult Display(ContainerWidgetPart part, string displayType, dynamic shapeHelper) {
return ContentShape(
"Parts_ContainerWidget",
() => {
var container = _contentManager.Get(part.Record.ContainerId);
IContentQuery<ContentItem> query = _contentManager
.Query(VersionOptions.Published)
.Join<CommonPartRecord>().Where(cr => cr.Container.Id == container.Id);
var descendingOrder = part.Record.OrderByDirection == (int)OrderByDirection.Descending;
query = query.OrderBy(part.Record.OrderByProperty, descendingOrder);
if (part.Record.ApplyFilter)
query = query.Where(part.Record.FilterByProperty, part.Record.FilterByOperator, part.Record.FilterByValue);
var pageOfItems = query.Slice(0, part.Record.PageSize).ToList();
var list = shapeHelper.List();
list.AddRange(pageOfItems.Select(item => _contentManager.BuildDisplay(item, "Summary")));
return shapeHelper.Parts_ContainerWidget(ContentItems: list);
});
}
protected override DriverResult Editor(ContainerWidgetPart part, dynamic shapeHelper) {
return Editor(part, null, shapeHelper);
}
protected override DriverResult Editor(ContainerWidgetPart part, IUpdateModel updater, dynamic shapeHelper) {
return ContentShape(
"Parts_ContainerWidget_Edit",
() => {
var model = new ContainerWidgetViewModel {Part = part};
if (updater != null) {
updater.TryUpdateModel(model, "ContainerWidget", null, null);
}
var containers = _contentManager.Query<ContainerPart, ContainerPartRecord>(VersionOptions.Latest).List();
var listItems = containers.Count() < 1
? new[] {new SelectListItem {Text = T("(None - create container enabled items first)").Text, Value = "0"}}
: containers.Select(x => new SelectListItem {
Value = Convert.ToString(x.Id),
Text = x.ContentItem.TypeDefinition.DisplayName + ": " + x.As<IRoutableAspect>().Title,
Selected = x.Id == model.Part.Record.ContainerId,
});
model.AvailableContainers = new SelectList(listItems, "Value", "Text", model.Part.Record.ContainerId);
return shapeHelper.EditorTemplate(TemplateName: "ContainerWidget", Model: model, Prefix: "ContainerWidget");
});
}
}
public class ContainerWidgetPartHandler : ContentHandler {
public ContainerWidgetPartHandler(IRepository<ContainerWidgetPartRecord> repository, IOrchardServices orchardServices) {
Filters.Add(StorageFilter.For(repository));
OnInitializing<ContainerWidgetPart>((context, part) => {
part.Record.ContainerId = 0;
part.Record.PageSize = 5;
part.Record.OrderByProperty = part.Is<CommonPart>() ? "CommonPart.PublishedUtc" : "";
part.Record.OrderByDirection = (int)OrderByDirection.Descending;
part.Record.FilterByProperty = "ContainerCustomPart.CustomOne";
part.Record.FilterByOperator = "=";
});
}
}
}

View File

@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.Core.Common.Models;
using Orchard.Core.Containers.Models;
using Orchard.Core.Routable.Models;
namespace Orchard.Core.Containers.Extensions
{
public static class ContentQueryExtensions {
public static IContentQuery<T> OrderBy<T>(this IContentQuery<T> query, string partAndProperty, bool descendingOrder) where T : IContent {
//todo: (heskew) order by custom part properties
switch (partAndProperty) {
case "RoutePart.Title":
query = descendingOrder
? query.OrderByDescending<RoutePartRecord, string>(record => record.Title)
: query.OrderBy<RoutePartRecord, string>(record => record.Title);
break;
case "RoutePart.Slug":
query = descendingOrder
? query.OrderByDescending<RoutePartRecord, string>(record => record.Slug)
: query.OrderBy<RoutePartRecord, string>(record => record.Slug);
break;
case "ContainerCustomPart.CustomOne":
query = descendingOrder
? query.OrderByDescending<ContainerCustomPartRecord, string>(record => record.CustomOne)
: query.OrderBy<ContainerCustomPartRecord, string>(record => record.CustomOne);
break;
case "ContainerCustomPart.CustomTwo":
query = descendingOrder
? query.OrderByDescending<ContainerCustomPartRecord, string>(record => record.CustomTwo)
: query.OrderBy<ContainerCustomPartRecord, string>(record => record.CustomTwo);
break;
case "ContainerCustomPart.CustomThree":
query = descendingOrder
? query.OrderByDescending<ContainerCustomPartRecord, string>(record => record.CustomThree)
: query.OrderBy<ContainerCustomPartRecord, string>(record => record.CustomThree);
break;
default: // "CommonPart.PublishedUtc"
query = descendingOrder
? query.OrderByDescending<CommonPartRecord, DateTime?>(record => record.PublishedUtc)
: query.OrderBy<CommonPartRecord, DateTime?>(record => record.PublishedUtc);
break;
}
return query;
}
public static IContentQuery<ContentItem> Where(this IContentQuery<ContentItem> query, string partAndProperty, string comparisonOperator, string comparisonValue) {
var filterKey = string.Format("{0}|{1}", partAndProperty, comparisonOperator);
if (!_filters.ContainsKey(filterKey))
return query;
return _filters[filterKey](query, comparisonValue);
}
// convoluted: yes; quick and works for now: yes; technical debt: not much
private static readonly Dictionary<string, Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>> _filters = new Dictionary<string, Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>> {
{"RoutePart.Title|<", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<RoutePartRecord>(r => true /* CompareTo is not implemented - r.Title.CompareTo(s) == -1*/))},
{"RoutePart.Title|>", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<RoutePartRecord>(r => true /* CompareTo is not implemented - r.Title.CompareTo(s) == 1*/))},
{"RoutePart.Title|=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<RoutePartRecord>(r => r.Title.Equals(s, StringComparison.OrdinalIgnoreCase)))},
{"RoutePart.Title|^=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<RoutePartRecord>(r => r.Title.StartsWith(s, StringComparison.OrdinalIgnoreCase)))},
{"RoutePart.Slug|<", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<RoutePartRecord>(r => true /* CompareTo is not implemented - r.Slug.CompareTo(s) == -1*/))},
{"RoutePart.Slug|>", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<RoutePartRecord>(r => true /* CompareTo is not implemented - r.Slug.CompareTo(s) == 1*/))},
{"RoutePart.Slug|=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<RoutePartRecord>(r => r.Slug.Equals(s.Trim(), StringComparison.OrdinalIgnoreCase)))},
{"RoutePart.Slug|^=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<RoutePartRecord>(r => r.Slug.StartsWith(s, StringComparison.OrdinalIgnoreCase)))},
{"CommonPart.PublishedUtc|<", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<CommonPartRecord>(r => r.PublishedUtc < DateTime.Parse(s)))},
{"CommonPart.PublishedUtc|>", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<CommonPartRecord>(r => r.PublishedUtc > DateTime.Parse(s)))},
{"CommonPart.PublishedUtc|=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<CommonPartRecord>(r => r.PublishedUtc == DateTime.Parse(s)))}, // todo: (heskew) not practical as is. needs some sense of precision....
{"CommonPart.PublishedUtc|^=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<CommonPartRecord>(r => true /* can't modified PublishedUtc for partial comparisons */))},
// todo: (hesekw) this could benefit from a better filter implementation as this is currently very limited in functionality and I have no idea how the custom parts will be used by folks
{"ContainerCustomPart.CustomOne|<", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => true /* CompareTo is not implemented - r.CustomOne.CompareTo(s) == -1*/))},
{"ContainerCustomPart.CustomOne|>", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => true /* CompareTo is not implemented - r.CustomOne.CompareTo(s) == 1*/))},
{"ContainerCustomPart.CustomOne|=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => r.CustomOne.Equals(s, StringComparison.OrdinalIgnoreCase)))},
{"ContainerCustomPart.CustomOne|^=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => r.CustomOne.StartsWith(s, StringComparison.OrdinalIgnoreCase)))},
{"ContainerCustomPart.CustomTwo|<", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => true /* CompareTo is not implemented - r.CustomTwo.CompareTo(s) == -1*/))},
{"ContainerCustomPart.CustomTwo|>", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => true /* CompareTo is not implemented - r.CustomTwo.CompareTo(s) == 1*/))},
{"ContainerCustomPart.CustomTwo|=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => r.CustomTwo.Equals(s, StringComparison.OrdinalIgnoreCase)))},
{"ContainerCustomPart.CustomTwo|^=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => r.CustomTwo.StartsWith(s, StringComparison.OrdinalIgnoreCase)))},
{"ContainerCustomPart.CustomThree|<", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => true /* CompareTo is not implemented - r.CustomThree.CompareTo(s) == -1*/))},
{"ContainerCustomPart.CustomThree|>", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => true /* CompareTo is not implemented - r.CustomThree.CompareTo(s) == 1*/))},
{"ContainerCustomPart.CustomThree|=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => r.CustomThree.Equals(s, StringComparison.OrdinalIgnoreCase)))},
{"ContainerCustomPart.CustomThree|^=", new Func<IContentQuery<ContentItem>, string, IContentQuery<ContentItem>>((q, s) => q.Where<ContainerCustomPartRecord>(r => r.CustomThree.StartsWith(s, StringComparison.OrdinalIgnoreCase)))},
};
}
}

View File

@@ -0,0 +1,49 @@
using Orchard.ContentManagement.MetaData;
using Orchard.Core.Contents.Extensions;
using Orchard.Data.Migration;
namespace Orchard.Core.Containers {
public class Migrations : DataMigrationImpl {
public int Create() {
SchemaBuilder.CreateTable("ContainerPartRecord",
table => table
.ContentPartRecord()
.Column<bool>("Paginated")
.Column<int>("PageSize")
.Column<string>("OrderByProperty")
.Column<int>("OrderByDirection"));
SchemaBuilder.CreateTable("ContainerWidgetPartRecord",
table => table
.ContentPartRecord()
.Column<int>("ContainerId")
.Column<int>("PageSize")
.Column<string>("OrderByProperty")
.Column<int>("OrderByDirection")
.Column<bool>("ApplyFilter")
.Column<string>("FilterByProperty")
.Column<string>("FilterByOperator")
.Column<string>("FilterByValue"));
SchemaBuilder.CreateTable("ContainerCustomPartRecord",
table => table
.ContentPartRecord()
.Column<string>("CustomOne")
.Column<string>("CustomTwo")
.Column<string>("CustomThree"));
ContentDefinitionManager.AlterTypeDefinition("ContainerWidget",
cfg => cfg
.WithPart("CommonPart")
.WithPart("WidgetPart")
.WithPart("ContainerWidgetPart")
.WithSetting("Stereotype", "Widget"));
ContentDefinitionManager.AlterPartDefinition("ContainerPart", builder => builder.Attachable());
ContentDefinitionManager.AlterPartDefinition("ContainablePart", builder => builder.Attachable());
ContentDefinitionManager.AlterPartDefinition("ContainerCustomPart", builder => builder.Attachable());
return 1;
}
}
}

View File

@@ -0,0 +1,6 @@
using Orchard.ContentManagement;
namespace Orchard.Core.Containers.Models {
public class ContainablePart : ContentPart {
}
}

View File

@@ -0,0 +1,13 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Records;
namespace Orchard.Core.Containers.Models {
public class ContainerCustomPart : ContentPart<ContainerCustomPartRecord> {
}
public class ContainerCustomPartRecord : ContentPartRecord {
public virtual string CustomOne { get; set; }
public virtual string CustomTwo { get; set; }
public virtual string CustomThree { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Records;
namespace Orchard.Core.Containers.Models {
public class ContainerPart : ContentPart<ContainerPartRecord> {
}
public class ContainerPartRecord : ContentPartRecord {
public virtual bool Paginated { get; set; }
public virtual int PageSize { get; set; }
public virtual string OrderByProperty { get; set; }
public virtual int OrderByDirection { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
using Orchard.ContentManagement;
using Orchard.ContentManagement.Records;
namespace Orchard.Core.Containers.Models {
public class ContainerWidgetPart : ContentPart<ContainerWidgetPartRecord> {
}
public class ContainerWidgetPartRecord : ContentPartRecord {
public virtual int ContainerId { get; set; }
public virtual int PageSize { get; set; }
public virtual string OrderByProperty { get; set; }
public virtual int OrderByDirection { get; set; }
public virtual bool ApplyFilter { get; set; }
public virtual string FilterByProperty { get; set; }
public virtual string FilterByOperator { get; set; }
public virtual string FilterByValue { get; set; }
}
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.Core.Containers.Models {
public enum OrderByDirection {
Ascending,
Descending,
}
}

View File

@@ -0,0 +1,12 @@
Name: Containers
AntiForgery: enabled
Author: The Orchard Team
Website: http://orchardproject.net
Version: 0.8.0
OrchardVersion: 0.8.0
Description: The containers module introduces container and containable behaviors for content items.
Features:
Containers:
Description: Container and containable parts to enable parent-child relationships between content items.
Dependencies: Contents, Routable
Category: Content

View File

@@ -0,0 +1,8 @@
<Placement>
<Place Parts_Containable_Edit="Content:before.3"/>
<Place Parts_Container_Edit="Content:5"/>
<Place Parts_ContainerCustom_Edit="Content:5"/>
<Place Parts_ContainerWidget_Edit="Content:5"/>
<Place Parts_Container_SiteSettings="Content:10"/>
<Place Parts_ContainerWidget="Content"/>
</Placement>

View File

@@ -0,0 +1,42 @@
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Routing;
using Orchard.Mvc.Routes;
namespace Orchard.Core.Containers {
public class Routes : IRouteProvider {
private readonly IContainersPathConstraint _containersPathConstraint;
public Routes(IContainersPathConstraint containersPathConstraint) {
_containersPathConstraint = containersPathConstraint;
}
public void GetRoutes(ICollection<RouteDescriptor> routes) {
foreach (var routeDescriptor in GetRoutes())
routes.Add(routeDescriptor);
}
public IEnumerable<RouteDescriptor> GetRoutes() {
return new[] {
new RouteDescriptor {
Priority = 15,
Route = new Route(
"{*path}",
new RouteValueDictionary {
{"area", "Containers"},
{"controller", "Item"},
{"action", "Display"}
},
new RouteValueDictionary {
{"path", _containersPathConstraint}
},
new RouteValueDictionary {
{"area", "Containers"}
},
new MvcRouteHandler())
}
};
}
}
}

View File

@@ -0,0 +1,34 @@
using System.Linq;
using Orchard.ContentManagement;
using Orchard.Core.Containers.Models;
using Orchard.Core.Routable.Models;
using Orchard.Environment;
using Orchard.Tasks;
namespace Orchard.Core.Containers.Services {
public class ContainersPathConstraintUpdater : IOrchardShellEvents, IBackgroundTask {
private readonly IContainersPathConstraint _containersPathConstraint;
private readonly IContentManager _contentManager;
public ContainersPathConstraintUpdater(IContainersPathConstraint containersPathConstraint, IContentManager contentManager) {
_containersPathConstraint = containersPathConstraint;
_contentManager = contentManager;
}
void IOrchardShellEvents.Activated() {
Refresh();
}
void IOrchardShellEvents.Terminating() {
}
void IBackgroundTask.Sweep() {
Refresh();
}
private void Refresh() {
var routeParts = _contentManager.Query<RoutePart, RoutePartRecord>().Join<ContainerPartRecord>().List();
_containersPathConstraint.SetPaths(routeParts.Select(x=>x.Path));
}
}
}

View File

@@ -0,0 +1,87 @@
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.Containers.Settings {
public class ContainerPartSettings {
public const int PageSizeDefaultDefault = 10;
public const bool PaginatedDefaultDefault = true;
private int? _pageSizeDefault;
private bool? _paginiatedDefault;
public int PageSizeDefault {
get {
return _pageSizeDefault != null
? (int)_pageSizeDefault
: PageSizeDefaultDefault;
}
set { _pageSizeDefault = value; }
}
public bool PaginatedDefault {
get {
return _paginiatedDefault != null
? (bool)_paginiatedDefault
: PaginatedDefaultDefault;
}
set { _paginiatedDefault = value; }
}
}
public class ContainerTypePartSettings {
public int? PageSizeDefault { get; set; }
public bool? PaginatedDefault { get; set; }
}
public class ContainerSettingsHooks : ContentDefinitionEditorEventsBase {
public override IEnumerable<TemplateViewModel> TypePartEditor(ContentTypePartDefinition definition) {
if (definition.PartDefinition.Name != "ContainerPart")
yield break;
var model = definition.Settings.GetModel<ContainerTypePartSettings>();
var partModel = definition.PartDefinition.Settings.GetModel<ContainerPartSettings>();
if (model.PageSizeDefault == null)
model.PageSizeDefault = partModel.PageSizeDefault;
if (model.PaginatedDefault == null)
model.PaginatedDefault = partModel.PaginatedDefault;
yield return DefinitionTemplate(model);
}
public override IEnumerable<TemplateViewModel> PartEditor(ContentPartDefinition definition) {
if (definition.Name != "ContainerPart")
yield break;
var model = definition.Settings.GetModel<ContainerPartSettings>();
yield return DefinitionTemplate(model);
}
public override IEnumerable<TemplateViewModel> TypePartEditorUpdate(ContentTypePartDefinitionBuilder builder, IUpdateModel updateModel) {
if (builder.Name != "ContainerPart")
yield break;
var model = new ContainerTypePartSettings();
updateModel.TryUpdateModel(model, "ContainerTypePartSettings", null, null);
builder.WithSetting("ContainerTypePartSettings.PageSizeDefault", model.PageSizeDefault.ToString());
builder.WithSetting("ContainerTypePartSettings.PaginatedDefault", model.PaginatedDefault.ToString());
yield return DefinitionTemplate(model);
}
public override IEnumerable<TemplateViewModel> PartEditorUpdate(ContentPartDefinitionBuilder builder, IUpdateModel updateModel) {
if (builder.Name != "ContainerPart")
yield break;
var model = new ContainerPartSettings();
updateModel.TryUpdateModel(model, "ContainerPartSettings", null, null);
builder.WithSetting("ContainerPartSettings.PageSizeDefault", model.PageSizeDefault.ToString());
builder.WithSetting("ContainerPartSettings.PaginatedDefault", model.PaginatedDefault.ToString());
yield return DefinitionTemplate(model);
}
}
}

View File

@@ -0,0 +1,6 @@
namespace Orchard.Core.Common.Settings {
public class LocationSettings {
public string Zone { get; set; }
public string Position { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
using System.Web.Mvc;
namespace Orchard.Core.Containers.ViewModels {
public class ContainableViewModel {
public int ContainerId { get; set; }
public SelectList AvailableContainers { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
using System.Web.Mvc;
using Orchard.Core.Containers.Models;
namespace Orchard.Core.Containers.ViewModels {
public class ContainerWidgetViewModel {
public bool UseFilter { get; set; }
public SelectList AvailableContainers { get; set; }
public ContainerWidgetPart Part { get; set; }
}
}

View File

@@ -0,0 +1,9 @@
@model Orchard.Core.Containers.Settings.ContainerPartSettings
<fieldset>
<label for="@Html.FieldIdFor(m => m.PageSizeDefault)">@T("Default Page Size")</label>
@Html.EditorFor(m => m.PageSizeDefault)
</fieldset>
<fieldset>
@Html.EditorFor(m => m.PaginatedDefault)
<label for="@Html.FieldIdFor( m => m.PaginatedDefault)" class="forcheckbox">@T("Show paging controls")</label>
</fieldset>

View File

@@ -0,0 +1,9 @@
@model Orchard.Core.Containers.Settings.ContainerTypePartSettings
<fieldset>
<label for="@Html.FieldIdFor(m => m.PageSizeDefault)">@T("Default Page Size")</label>
@Html.EditorFor(m => m.PageSizeDefault)
</fieldset>
<fieldset>
<label for="@Html.FieldIdFor( m => m.PaginatedDefault)">@T("Show paging controls")</label>
@Html.EditorFor(m => m.PaginatedDefault)
</fieldset>

View File

@@ -0,0 +1,5 @@
@model Orchard.Core.Containers.ViewModels.ContainableViewModel
<fieldset>
@Html.LabelFor(m => m.ContainerId, T("Add to"))
@Html.DropDownListFor(m => m.ContainerId, Model.AvailableContainers)
</fieldset>

View File

@@ -0,0 +1,27 @@
@model Orchard.Core.Containers.Models.ContainerPart
@using Orchard.Core.Containers.Models;
<fieldset>
@Html.LabelFor(m => m.Record.OrderByProperty, T("Order by"))
<select id="@Html.FieldIdFor(m => m.Record.OrderByProperty)" name="@Html.FieldNameFor(m => m.Record.OrderByProperty)">
@Html.SelectOption(Model.Record.OrderByProperty, "CommonPart.PublishedUtc", T("Date Published").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "RoutePart.Title", T("Title").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "RoutePart.Slug", T("Slug").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "ContainerCustomPart.CustomOne", T("Custom 1").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "ContainerCustomPart.CustomTwo", T("Custom 2").Text)
@Html.SelectOption(Model.Record.OrderByProperty, "ContainerCustomPart.CustomThree", T("Custom 3").Text)
</select>
<select id="@Html.FieldIdFor(m => m.Record.OrderByDirection)" name="@Html.FieldNameFor(m => m.Record.OrderByDirection)">
@Html.SelectOption(Model.Record.OrderByDirection, (int)OrderByDirection.Ascending, T("Ascending").Text)
@Html.SelectOption(Model.Record.OrderByDirection, (int)OrderByDirection.Descending, T("Descending").Text)
</select>
</fieldset>
<fieldset class="with-checkbox">
<span>
@Html.LabelFor(m => m.Record.PageSize, T("Page size"))
@Html.TextBoxFor(m => m.Record.PageSize, new { @class = "text text-small" })
</span>
<span class="checkbox-and-label">
@Html.CheckBoxFor(m => m.Record.Paginated)
<label for="@Html.FieldIdFor(m => m.Record.Paginated)" class="forcheckbox">@T("Show paging controls")</label>
</span>
</fieldset>

View File

@@ -0,0 +1,13 @@
@model Orchard.Core.Containers.Models.ContainerCustomPart
<fieldset>
@Html.LabelFor(m => m.Record.CustomOne, T("Custom One"))
@Html.EditorFor(m => m.Record.CustomOne)
</fieldset>
<fieldset>
@Html.LabelFor(m => m.Record.CustomTwo, T("Custom Two"))
@Html.EditorFor(m => m.Record.CustomTwo)
</fieldset>
<fieldset>
@Html.LabelFor(m => m.Record.CustomThree, T("Custom Three"))
@Html.EditorFor(m => m.Record.CustomThree)
</fieldset>

View File

@@ -0,0 +1,56 @@
@model Orchard.Core.Containers.ViewModels.ContainerWidgetViewModel
@using Orchard.Core.Containers.Models;
@{
Script.Require("ShapesBase");
}
<fieldset>
@Html.LabelFor(m => m.Part.Record.ContainerId, T("Show items from"))
@Html.DropDownListFor(m => m.Part.Record.ContainerId, Model.AvailableContainers)
</fieldset>
<fieldset>
<span>
@Html.LabelFor(m => m.Part.Record.PageSize, T("Maximum number of items to display"))
@Html.TextBoxFor(m => m.Part.Record.PageSize, new { @class = "text text-small" })
</span>
</fieldset>
<fieldset>
@Html.LabelFor(m => m.Part.Record.OrderByProperty, T("Order by"))
<select id="@Html.FieldIdFor(m => m.Part.Record.OrderByProperty)" name="@Html.FieldNameFor(m => m.Part.Record.OrderByProperty)">
@Html.SelectOption(Model.Part.Record.OrderByProperty, "CommonPart.PublishedUtc", T("Date Published").Text)
@Html.SelectOption(Model.Part.Record.OrderByProperty, "RoutePart.Title", T("Title").Text)
@Html.SelectOption(Model.Part.Record.OrderByProperty, "RoutePart.Slug", T("Slug").Text)
@Html.SelectOption(Model.Part.Record.OrderByProperty, "ContainerCustomPart.CustomOne", T("Custom 1").Text)
@Html.SelectOption(Model.Part.Record.OrderByProperty, "ContainerCustomPart.CustomTwo", T("Custom 2").Text)
@Html.SelectOption(Model.Part.Record.OrderByProperty, "ContainerCustomPart.CustomThree", T("Custom 3").Text)
</select>
<select title="@T("Order direction")" id="@Html.FieldIdFor(m => m.Part.Record.OrderByDirection)" name="@Html.FieldNameFor(m => m.Part.Record.OrderByDirection)">
@Html.SelectOption(Model.Part.Record.OrderByDirection, (int)OrderByDirection.Ascending, T("Ascending").Text)
@Html.SelectOption(Model.Part.Record.OrderByDirection, (int)OrderByDirection.Descending, T("Descending").Text)
</select>
</fieldset>
<fieldset>
<div>
@Html.EditorFor(m => m.Part.Record.ApplyFilter)
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.Part.Record.ApplyFilter)">@T("Filter items")</label>
</div>
<div data-controllerid="@Html.FieldIdFor(m => m.Part.Record.ApplyFilter)">
@Html.LabelFor(m => m.Part.Record.FilterByProperty, T("Filter where"))
<select id="@Html.FieldIdFor(m => m.Part.Record.FilterByProperty)" name="@Html.FieldNameFor(m => m.Part.Record.FilterByProperty)">
@Html.SelectOption(Model.Part.Record.FilterByProperty, "CommonPart.PublishedUtc", T("Date Published").Text)
@Html.SelectOption(Model.Part.Record.FilterByProperty, "RoutePart.Title", T("Title").Text)
@Html.SelectOption(Model.Part.Record.FilterByProperty, "RoutePart.Slug", T("Slug").Text)
@Html.SelectOption(Model.Part.Record.FilterByProperty, "ContainerCustomPart.CustomOne", T("Custom 1").Text)
@Html.SelectOption(Model.Part.Record.FilterByProperty, "ContainerCustomPart.CustomTwo", T("Custom 2").Text)
@Html.SelectOption(Model.Part.Record.FilterByProperty, "ContainerCustomPart.CustomThree", T("Custom 3").Text)
</select>
<select title="@T("Filter operator")" id="@Html.FieldIdFor(m => m.Part.Record.FilterByOperator)" name="@Html.FieldNameFor(m => m.Part.Record.FilterByOperator)">
@Html.SelectOption(Model.Part.Record.FilterByOperator, "=", T("is equal to").Text)
@Html.SelectOption(Model.Part.Record.FilterByOperator, "<", T("is less than").Text)
@Html.SelectOption(Model.Part.Record.FilterByOperator, ">", T("is greater than").Text)
@Html.SelectOption(Model.Part.Record.FilterByOperator, "^=", T("starts with").Text)
</select>
<span>
@Html.TextBoxFor(m => m.Part.Record.FilterByValue, new { @class = "text", title = T("Filter value") })
</span>
</div>
</fieldset>

View File

@@ -0,0 +1,4 @@
@Display(Model.ContentItems)
@if (Model.ShowPager) {
@Display(Model.Pager)
}

View File

@@ -0,0 +1 @@
@Display(Model.ContentItems)

View File

@@ -21,16 +21,22 @@ namespace Orchard.Core.Contents {
public void GetNavigation(NavigationBuilder builder) {
var contentTypeDefinitions = _contentDefinitionManager.ListTypeDefinitions().OrderBy(d => d.Name);
builder.Add(T("Content"), "2", menu => {
menu.Add(T("Manage Content"), "1", item => item.Action("List", "Admin", new { area = "Contents", id = "" }));
foreach (var contentTypeDefinition in contentTypeDefinitions.Where(ctd => ctd.Settings.GetModel<ContentTypeSettings>().Creatable)) {
var ci = _contentManager.New(contentTypeDefinition.Name);
var cim = _contentManager.GetItemMetadata(ci);
var createRouteValues = cim.CreateRouteValues;
if (createRouteValues.Any())
menu.Add(T("Create {0}", contentTypeDefinition.DisplayName), "1.3", item => item.Action(cim.CreateRouteValues["Action"] as string, cim.CreateRouteValues["Controller"] as string, cim.CreateRouteValues));
}
});
builder.Add(T("Content"), "2",
menu => menu.Add(T("Content Items"), "1", item => item.Action("List", "Admin", new {area = "Contents", id = ""})));
var contentTypes = contentTypeDefinitions.Where(ctd => ctd.Settings.GetModel<ContentTypeSettings>().Creatable).OrderBy(ctd => ctd.DisplayName);
if (contentTypes.Count() > 0) {
builder.Add(T("New"), "-1", menu => {
foreach (var contentTypeDefinition in contentTypes) {
var ci = _contentManager.New(contentTypeDefinition.Name);
var cim = _contentManager.GetItemMetadata(ci);
var createRouteValues = cim.CreateRouteValues;
// review: the display name should be a LocalizedString
if (createRouteValues.Any())
menu.Add(T(contentTypeDefinition.DisplayName), "5", item => item.Action(cim.CreateRouteValues["Action"] as string, cim.CreateRouteValues["Controller"] as string, cim.CreateRouteValues));
}
});
}
}
}
}

View File

@@ -8,6 +8,7 @@ using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Models;
using Orchard.ContentManagement.Records;
using Orchard.Core.Common.Models;
using Orchard.Core.Contents.Settings;
using Orchard.Core.Contents.ViewModels;
@@ -15,6 +16,7 @@ using Orchard.Data;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.Logging;
using Orchard.UI.Navigation;
using Orchard.UI.Notify;
namespace Orchard.Core.Contents.Controllers {
@@ -44,13 +46,10 @@ namespace Orchard.Core.Contents.Controllers {
public Localizer T { get; set; }
public ILogger Logger { get; set; }
public ActionResult List(ListContentsViewModel model) {
public ActionResult List(ListContentsViewModel model, Pager pager) {
if (model.ContainerId != null && _contentManager.GetLatest((int)model.ContainerId) == null)
return HttpNotFound();
const int pageSize = 20;
var skip = (Math.Max(model.Page ?? 0, 1) - 1) * pageSize;
var query = _contentManager.Query(VersionOptions.Latest, GetCreatableTypes().Select(ctd => ctd.Name).ToArray());
if (!string.IsNullOrEmpty(model.TypeName)) {
@@ -67,56 +66,34 @@ namespace Orchard.Core.Contents.Controllers {
if (model.ContainerId != null)
query = query.Join<CommonPartRecord>().Where(cr => cr.Container.Id == model.ContainerId);
// Ordering
//-- want something like
//switch (model.Options.OrderBy) {
// case ContentsOrder.Modified:
// query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.ModifiedUtc);
// break;
// case ContentsOrder.Published:
// query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.PublishedUtc);
// break;
// case ContentsOrder.Created:
// query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.CreatedUtc);
// break;
//}
//-- but resorting to
var contentItems = query.List();
switch (model.Options.OrderBy) {
case ContentsOrder.Modified:
contentItems = contentItems.OrderByDescending(ci => ci.VersionRecord.Id);
//query = query.OrderByDescending<ContentPartRecord, int>(ci => ci.ContentItemRecord.Versions.Single(civr => civr.Latest).Id);
query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.ModifiedUtc);
break;
case ContentsOrder.Published:
query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.PublishedUtc);
break;
//case ContentsOrder.Published:
// would be lying w/out a published date instead of a bool but that only comes with the common aspect
// contentItems = contentItems.OrderByDescending(ci => ci.VersionRecord.Published/*Date*/);
// break;
case ContentsOrder.Created:
contentItems = contentItems.OrderByDescending(ci => ci.Id);
//query = query.OrderByDescending<ContentPartRecord, int>(ci => ci.Id);
query = query.OrderByDescending<CommonPartRecord, DateTime?>(cr => cr.CreatedUtc);
break;
}
//-- for the moment
//-- because I'd rather do this
//var contentItems = query.Slice(skip, pageSize);
//-- instead of this (having the ordering and skip/take after the query)
contentItems = contentItems.Skip(skip).Take(pageSize).ToList();
model.Options.SelectedFilter = model.TypeName;
model.Options.FilterOptions = GetCreatableTypes()
.Select(ctd => new KeyValuePair<string, string>(ctd.Name, ctd.DisplayName))
.ToList().OrderBy(kvp => kvp.Key);
var pagerShape = Shape.Pager(pager).TotalItemCount(query.Count());
var pageOfContentItems = query.Slice(pager.GetStartIndex(), pager.PageSize).ToList();
var list = Shape.List();
list.AddRange(contentItems.Select(ci => _contentManager.BuildDisplay(ci, "SummaryAdmin")));
list.AddRange(pageOfContentItems.Select(ci => _contentManager.BuildDisplay(ci, "SummaryAdmin")));
var viewModel = Shape.ViewModel()
.ContentItems(list)
.Pager(pagerShape)
.Options(model.Options)
.TypeDisplayName(model.TypeDisplayName ?? "");
@@ -215,24 +192,39 @@ namespace Orchard.Core.Contents.Controllers {
return View(model);
}
[HttpPost, ActionName("Create")]
[FormValueRequired("submit.Save")]
public ActionResult CreatePOST(string id) {
return CreatePOST(id, contentItem => {
if (!contentItem.Has<IPublishingControlAspect>() && !contentItem.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable)
_contentManager.Publish(contentItem);
});
}
[HttpPost, ActionName("Create")]
public ActionResult CreatePOST(string id) {
[FormValueRequired("submit.Publish")]
public ActionResult CreateAndPublishPOST(string id) {
return CreatePOST(id, contentItem => _contentManager.Publish(contentItem));
}
private ActionResult CreatePOST(string id, Action<ContentItem> conditionallyPublish) {
var contentItem = _contentManager.New(id);
if (!Services.Authorizer.Authorize(Permissions.PublishContent, contentItem, T("Couldn't create content")))
return new HttpUnauthorizedResult();
_contentManager.Create(contentItem, VersionOptions.Draft);
var model = _contentManager.UpdateEditor(contentItem, this);
var isDraftable = contentItem.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable;
_contentManager.Create(
contentItem,
isDraftable ? VersionOptions.Draft : VersionOptions.Published);
var model = _contentManager.UpdateEditor(contentItem, this);
if (!ModelState.IsValid) {
_transactionManager.Cancel();
return View(model);
}
if (!contentItem.Has<IPublishingControlAspect>())
_contentManager.Publish(contentItem);
conditionallyPublish(contentItem);
Services.Notifier.Information(string.IsNullOrWhiteSpace(contentItem.TypeDefinition.DisplayName)
? T("Your content has been created.")
@@ -255,7 +247,21 @@ namespace Orchard.Core.Contents.Controllers {
}
[HttpPost, ActionName("Edit")]
[FormValueRequired("submit.Save")]
public ActionResult EditPOST(int id, string returnUrl) {
return EditPOST(id, returnUrl, contentItem => {
if (!contentItem.Has<IPublishingControlAspect>() && !contentItem.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable)
_contentManager.Publish(contentItem);
});
}
[HttpPost, ActionName("Edit")]
[FormValueRequired("submit.Publish")]
public ActionResult EditAndPublishPOST(int id, string returnUrl) {
return EditPOST(id, returnUrl, contentItem => _contentManager.Publish(contentItem));
}
private ActionResult EditPOST(int id, string returnUrl, Action<ContentItem> conditionallyPublish) {
var contentItem = _contentManager.Get(id, VersionOptions.DraftRequired);
if (contentItem == null)
@@ -270,9 +276,7 @@ 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);
conditionallyPublish(contentItem);
Services.Notifier.Information(string.IsNullOrWhiteSpace(contentItem.TypeDefinition.DisplayName)
? T("Your content has been saved.")

View File

@@ -1,5 +1,7 @@
using Orchard.ContentManagement;
using System.Collections.Generic;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Core.Contents.Settings;
namespace Orchard.Core.Contents.Drivers {
public class ContentsDriver : ContentPartDriver<ContentPart> {
@@ -13,5 +15,18 @@ namespace Orchard.Core.Contents.Drivers {
() => shapeHelper.Parts_Contents_Publish_SummaryAdmin(ContentPart: part))
);
}
protected override DriverResult Editor(ContentPart part, dynamic shapeHelper) {
var results = new List<DriverResult> { ContentShape("Content_SaveButton", saveButton => saveButton) };
if (part.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable)
results.Add(ContentShape("Content_PublishButton", publishButton => publishButton));
return Combined(results.ToArray());
}
protected override DriverResult Editor(ContentPart part, IUpdateModel updater, dynamic shapeHelper) {
return Editor(part, updater);
}
}
}

View File

@@ -6,6 +6,9 @@ namespace Orchard.Core.Contents.Extensions {
public static ContentTypeDefinitionBuilder Creatable(this ContentTypeDefinitionBuilder builder, bool creatable = true) {
return builder.WithSetting("ContentTypeSettings.Creatable", creatable.ToString());
}
public static ContentTypeDefinitionBuilder Draftable(this ContentTypeDefinitionBuilder builder, bool draftable = true) {
return builder.WithSetting("ContentTypeSettings.Draftable", draftable.ToString());
}
public static ContentPartDefinitionBuilder Attachable(this ContentPartDefinitionBuilder builder, bool attachable = true) {
return builder.WithSetting("ContentPartSettings.Attachable", attachable.ToString());
}

View File

@@ -4,10 +4,13 @@
Parts_Contents_Publish
Parts_Contents_Publish_SummaryAdmin
-->
<!-- edit "shape" -->
<Place Content_PublishButton="Sidebar:24"/>
<Place Content_SaveButton="Sidebar:23"/>
<Match DisplayType="Detail">
<Place Parts_Contents_Publish="Content:5"/>
</Match>
<Match DisplayType="SummaryAdmin">
<Place Parts_Contents_Publish_SummaryAdmin="Secondary:5"/>
<Place Parts_Contents_Publish_SummaryAdmin="Actions:5"/>
</Match>
</Placement>

View File

@@ -1,8 +1,12 @@
namespace Orchard.Core.Contents.Settings {
public class ContentTypeSettings {
/// <summary>
/// This setting is used to display a Content Type in Content Management menu like
/// Used to determine if an instance of this content type can be created through the UI
/// </summary>
public bool Creatable { get; set; }
/// <summary>
/// Used to determine if this content type supports draft versions
/// </summary>
public bool Draftable { get; set; }
}
}

View File

@@ -35,11 +35,12 @@
<select id="orderResults" name="Options.OrderBy">
@Html.SelectOption((ContentsOrder)Model.Options.OrderBy, ContentsOrder.Created, T("recently created").ToString())
@Html.SelectOption((ContentsOrder)Model.Options.OrderBy, ContentsOrder.Modified, T("recently modified").ToString())
@Html.SelectOption((ContentsOrder)Model.Options.OrderBy, ContentsOrder.Published, T("recently published").ToString())
</select>
<button type="submit" name="submit.Filter" value="yes please">@T("Apply")</button>
</fieldset>
<fieldset class="contentItems bulk-items">
@Display(Model.ContentItems)
@Display(Model.ContentItems2)
</fieldset>
@Display(Model.Pager)
}

View File

@@ -0,0 +1,3 @@
<fieldset class="publish-button">
<button type="submit" name="submit.Publish" value="submit.Publish">@T("Publish Now")</button>
</fieldset>

View File

@@ -0,0 +1,3 @@
<fieldset class="save-button">
<button class="primaryAction" type="submit" name="submit.Save" value="submit.Save">@T("Save")</button>
</fieldset>

View File

@@ -1,11 +1,21 @@
<div class="sections">
<div class="primary">
@Display(Model.Primary)
<div class="edit-item">
<div class="edit-item-primary">
@if (Model.Content != null) {
<div class="edit-item-content">
@Display(Model.Content)
</div>
}
</div>
<div class="secondary">
@Display(Model.Secondary)
<fieldset>
<button class="primaryAction" type="submit" name="submit.Save" value="submit.Save">@T("Save")</button>
</fieldset>
<div class="edit-item-secondary group">
@if (Model.Actions != null) {
<div class="edit-item-actions">
@Display(Model.Actions)
</div>
}
@if (Model.Sidebar != null) {
<div class="edit-item-sidebar group">
@Display(Model.Sidebar)
</div>
}
</div>
</div>

View File

@@ -0,0 +1,20 @@
@using Orchard.Utility.Extensions;
@{
var contentTypeClassName = ((string)Model.ContentItem.ContentType).HtmlClassify();
}
<article class="content-item @contentTypeClassName">
<header>
@Display(Model.Header)
@if (Model.Meta != null) {
<div class="metadata">
@Display(Model.Meta)
</div>
}
</header>
@Display(Model.Content)
@if(Model.Footer != null) {
<footer>
@Display(Model.Footer)
</footer>
}
</article>

View File

@@ -8,11 +8,19 @@
<div class="properties">
<input type="checkbox" value="@contentItem.Id" name="itemIds"/>
<h3>@Html.ItemEditLink(contentItem)</h3>
@if (Model.Header != null) {
<div class="header">@Display(Model.Header)</div>
}
@if (Model.Meta != null) {
<div class="metadata">@Display(Model.Meta)</div>
}
</div>
<div class="related">@Display(Model.Secondary)
<div class="related">
@Display(Model.Actions)
@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" })
</div>
<div class="primary">@Display(Model.Primary)</div>
@if (Model.Content != null) {
<div class="primary">@Display(Model.Content)</div>
}
</div>

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -8,8 +8,9 @@ namespace Orchard.Core.Dashboard {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Orchard"), "0",
menu => menu.Add(T("Dashboard"), "0", item => item.Action("Index", "Admin", new { area = "Dashboard" }).Permission(StandardPermissions.AccessAdminPanel)));
builder.Add(T("Dashboard"), "-5",
menu => menu.Add(T("Orchard"), "-5", item => item.Action("Index", "Admin", new { area = "Dashboard" })
.Permission(StandardPermissions.AccessAdminPanel)));
}
}
}

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -6,7 +6,7 @@
Parts_Localization_ContentTranslations_SummaryAdmin
-->
<!-- edit shape just gets default placement -->
<Place Parts_Localization_ContentTranslations_Edit="Primary:before.1"/>
<Place Parts_Localization_ContentTranslations_Edit="Content:0"/>
<Match DisplayType="Detail">
<Place Parts_Localization_ContentTranslations="Content:2"/>
</Match>
@@ -14,6 +14,6 @@
<Place Parts_Localization_ContentTranslations_Summary="Content:2"/>
</Match>
<Match DisplayType="SummaryAdmin">
<Place Parts_Localization_ContentTranslations_SummaryAdmin="Primary:5"/>
<Place Parts_Localization_ContentTranslations_SummaryAdmin="Content:5"/>
</Match>
</Placement>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<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

@@ -1,10 +1,6 @@
.summary .content-localization {
margin: .7em 0;
}
.content-localization .content-localizations li,
.content-localization .add-localization {
font-size:1.4em;
}
.content-localization .culture-selected {
margin-bottom:.5em;
}

View File

@@ -2,7 +2,7 @@
@using Orchard.Core.Localization.ViewModels;
@{
dynamic content = Model.Content;
content.Zones.Primary.Add(New.Partial(TemplateName: "CultureSelection", Model: Model), "0");
content.Zones.Content.Add(New.Partial(TemplateName: "CultureSelection", Model: Model), "0");
}
<h1>@Html.TitleForPage(T("Translate Content").ToString())</h1>
@using (Html.BeginFormAntiForgeryPost()) {

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -1,3 +1,3 @@
<Placement>
<Place Parts_MessageSettings_Edit="Primary:10"/>
<Place Parts_MessageSettings_Edit="Content:10"/>
</Placement>

View File

@@ -50,19 +50,25 @@ namespace Orchard.Core.Messaging.Services {
Service = service
};
if ( properties != null ) {
foreach (var key in properties.Keys)
context.Properties.Add(key, properties[key]);
try {
if (properties != null) {
foreach (var key in properties.Keys)
context.Properties.Add(key, properties[key]);
}
_messageEventHandler.Sending(context);
foreach (var channel in _channels) {
channel.SendMessage(context);
}
_messageEventHandler.Sent(context);
}
_messageEventHandler.Sending(context);
foreach ( var channel in _channels ) {
channel.SendMessage(context);
finally {
context.MailMessage.Dispose();
}
_messageEventHandler.Sent(context);
Logger.Information("Message {0} sent", type);
}
catch ( Exception e ) {

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<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

@@ -9,8 +9,8 @@ namespace Orchard.Core.Navigation {
public void GetNavigation(NavigationBuilder builder) {
//todo: - add new menu? and list menus? ...and remove hard-coded menu name here
builder.Add(T("Navigation"), "8",
menu => menu
.Add(T("Main Menu"), "6.0", item => item.Action("Index", "Admin", new { area = "Navigation" }).Permission(Permissions.ManageMainMenu)));
menu => menu.Add(T("Main Menu"), "0", item => item.Action("Index", "Admin", new { area = "Navigation" })
.Permission(Permissions.ManageMainMenu)));
}
}
}

View File

@@ -8,6 +8,7 @@ using Orchard.Core.Navigation.ViewModels;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.Mvc.AntiForgery;
using Orchard.UI;
using Orchard.UI.Navigation;
using Orchard.Utility;
@@ -41,7 +42,7 @@ namespace Orchard.Core.Navigation.Controllers {
model = new NavigationManagementViewModel();
if (model.MenuItemEntries == null || model.MenuItemEntries.Count() < 1)
model.MenuItemEntries = _menuService.Get().Select(CreateMenuItemEntries).OrderBy(menuPartEntry => menuPartEntry.MenuItem.Position, new PositionComparer()).ToList();
model.MenuItemEntries = _menuService.Get().Select(CreateMenuItemEntries).OrderBy(menuPartEntry => menuPartEntry.MenuItem.Position, new FlatPositionComparer()).ToList();
// need action name as this action is referenced from another action
return View("Index", model);

View File

@@ -1,3 +1,3 @@
<Placement>
<Place Parts_Navigation_Menu_Edit="Primary:9"/>
<Place Parts_Navigation_Menu_Edit="Content:9"/>
</Placement>

View File

@@ -35,7 +35,7 @@
}
</tbody>
</table>
<fieldset class="actions"><button type="submit" class="button primaryAction">@T("Update All")</button></fieldset>
<fieldset class="actions"><button type="submit" class="primaryAction">@T("Update All")</button></fieldset>
}
<h2>@T("Add New Item")</h2>

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -27,7 +27,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet>..\..\OrchardBasicCorrectness.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -53,16 +53,38 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\aspnetmvc\System.Web.Mvc.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\aspnetmvc\System.Web.WebPages.dll</HintPath>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Compile Include="Containers\Controllers\ItemController.cs" />
<Compile Include="Containers\Drivers\ContainablePartDriver.cs" />
<Compile Include="Containers\Drivers\ContainerPartDriver.cs" />
<Compile Include="Common\Migrations.cs" />
<Compile Include="Common\Drivers\BodyPartDriver.cs" />
<Compile Include="Common\Drivers\CommonPartDriver.cs" />
<Compile Include="Common\Drivers\TextFieldDriver.cs" />
<Compile Include="Containers\ContainersPathConstraint.cs" />
<Compile Include="Containers\Drivers\ContainerWidgetPartDriver.cs" />
<Compile Include="Containers\Drivers\ContainerCustomPartDriver.cs" />
<Compile Include="Containers\Extensions\ContentQueryExtensions.cs" />
<Compile Include="Containers\Migrations.cs" />
<Compile Include="Containers\Models\ContainablePart.cs" />
<Compile Include="Containers\Models\ContainerPart.cs" />
<Compile Include="Common\Shapes.cs" />
<Compile Include="Common\Fields\TextField.cs" />
<Compile Include="Containers\Models\ContainerWidgetPart.cs" />
<Compile Include="Containers\Models\ContainerCustomPart.cs" />
<Compile Include="Containers\Models\OrderByDirection.cs" />
<Compile Include="Containers\Routes.cs" />
<Compile Include="Containers\Services\ContainersPathConstraintUpdater.cs" />
<Compile Include="Containers\Settings\ContainerSettings.cs" />
<Compile Include="Containers\ViewModels\ContainableViewModel.cs" />
<Compile Include="Containers\ViewModels\ContainerWidgetViewModel.cs" />
<Compile Include="Contents\Security\AuthorizationEventHandler.cs" />
<Compile Include="Common\Services\BbcodeFilter.cs" />
<Compile Include="Common\Services\ICommonService.cs" />
@@ -233,6 +255,7 @@
<Content Include="Common\Views\Parts\Common.Body.SummaryAdmin.cshtml" />
<Content Include="Common\Views\Parts\Common.Metadata.cshtml" />
<Content Include="Common\Views\Parts\Common.Metadata.SummaryAdmin.cshtml" />
<Content Include="Containers\Module.txt" />
<Content Include="Contents\Views\Admin\Create.cshtml" />
<Content Include="Contents\Views\Admin\Edit.cshtml" />
<Content Include="Contents\Views\Admin\List.cshtml" />
@@ -265,12 +288,8 @@
<Content Include="Settings\Views\Admin\Index.cshtml" />
<Content Include="Settings\Views\Admin\Culture.cshtml" />
<Content Include="Contents\Views\Items\Content.Edit.cshtml" />
<Content Include="Routable\Placement.info">
<SubType>Designer</SubType>
</Content>
<Content Include="Settings\Placement.info">
<SubType>Designer</SubType>
</Content>
<Content Include="Routable\Placement.info" />
<Content Include="Settings\Placement.info" />
<Content Include="Settings\Views\DisplayTemplates\CurrentCulture.cshtml" />
<Content Include="Settings\Views\DisplayTemplates\RemovableCulture.cshtml" />
<Content Include="Shapes\Module.txt" />
@@ -289,8 +308,6 @@
<Content Include="Shapes\Views\HeadPreload.cshtml" />
<Content Include="Shapes\Views\Message.cshtml" />
<Content Include="Shapes\Views\NotFound.cshtml" />
<Content Include="Shapes\Views\UI\Switchable.cshtml" />
<Content Include="Web.config" />
<Content Include="XmlRpc\Module.txt" />
<Content Include="Settings\Views\EditorTemplates\Parts\Settings.SiteSettingsPart.cshtml" />
</ItemGroup>
@@ -346,20 +363,46 @@
<Content Include="Shapes\Views\Web.config" />
<Content Include="Common\Placement.info" />
<Content Include="Common\Views\Parts\Common.Metadata.Summary.cshtml" />
<Content Include="Contents\Placement.info" />
<Content Include="Contents\Placement.info">
<SubType>Designer</SubType>
</Content>
<Content Include="Contents\Views\Content.ControlWrapper.cshtml" />
<Content Include="Contents\Views\Item\Display.cshtml" />
<Content Include="Localization\Placement.info" />
<Content Include="Messaging\Placement.info">
<SubType>Designer</SubType>
</Content>
<Content Include="Navigation\Placement.info">
<SubType>Designer</SubType>
</Content>
<Content Include="Messaging\Placement.info" />
<Content Include="Navigation\Placement.info" />
<Content Include="Routable\Views\Parts\RoutableTitle.cshtml" />
<Content Include="Routable\Views\Item\Display.cshtml" />
<Content Include="Routable\Views\Routable.HomePage.cshtml" />
<Content Include="Localization\Views\Parts\Localization.ContentTranslations.SummaryAdmin.cshtml" />
<Content Include="Contents\Views\Items\Content.Summary.cshtml" />
<Content Include="Shapes\Views\Pager.cshtml" />
<Content Include="Contents\Views\Content.SaveButton.cshtml" />
<Content Include="Contents\Views\Content.PublishButton.cshtml" />
<Content Include="Shapes\Scripts\Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Shapes\Styles\Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Routable\Scripts\Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Localization\Styles\Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Settings\Styles\Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Containers\Placement.info" />
<Content Include="Containers\Views\EditorTemplates\ContainerWidget.cshtml" />
<Content Include="Containers\Views\EditorTemplates\Container.cshtml" />
<Content Include="Containers\Views\Item\Display.cshtml" />
<Content Include="Containers\Views\DefinitionTemplates\ContainerPartSettings.cshtml" />
<Content Include="Containers\Views\DefinitionTemplates\ContainerTypePartSettings.cshtml" />
<Content Include="Containers\Views\EditorTemplates\Containable.cshtml" />
<Content Include="Containers\Views\Parts\ContainerWidget.cshtml" />
<Content Include="Containers\Views\EditorTemplates\ContainerCustom.cshtml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

View File

@@ -1,5 +1,6 @@
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
@@ -32,3 +33,4 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.8.0")]
[assembly: AssemblyFileVersion("0.8.0")]
[assembly: SecurityTransparent]

View File

@@ -8,8 +8,9 @@ namespace Orchard.Core.Reports {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Site Configuration"), "11",
menu => menu.Add(T("Reports"), "15", item => item.Action("Index", "Admin", new { area = "Reports" }).Permission(StandardPermissions.AccessAdminPanel)));
builder.Add(T("Configuration"), "50",
menu => menu.Add(T("Reports"), "20", item => item.Action("Index", "Admin", new { area = "Reports" })
.Permission(StandardPermissions.AccessAdminPanel)));
}
}
}

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -1,4 +1,9 @@
<Placement>
<Place Parts_RoutableTitle="Header:5"/>
<Place Parts_Routable_Edit="Primary:before.5"/>
<Place Parts_Routable_Edit="Content:before.5"/>
<Match DisplayType="Detail">
<Place Parts_RoutableTitle="Header:5"/>
</Match>
<Match DisplayType="Summary">
<Place Parts_RoutableTitle="Header:5"/>
</Match>
</Placement>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<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

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -7,9 +7,9 @@ namespace Orchard.Core.Settings {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Site Configuration"), "11",
menu => menu
.Add(T("Settings"), "10", item => item.Action("Index", "Admin", new { area = "Settings" }).Permission(Permissions.ManageSettings)));
builder.Add(T("Configuration"), "50",
menu => menu.Add(T("Settings"), "10", item => item.Action("Index", "Admin", new { area = "Settings" })
.Permission(Permissions.ManageSettings)));
}
}
}

View File

@@ -1,3 +1,3 @@
<Placement>
<Place Parts_Settings_SiteSettingsPart="Primary:1"/>
<Place Parts_Settings_SiteSettingsPart="Content:1"/>
</Placement>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<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

@@ -1,10 +1,8 @@
<h1>@Html.TitleForPage(T("Manage Settings").ToString())</h1>
@using (Html.BeginFormAntiForgeryPost()) {
@Html.ValidationSummary()
@Display(Model.Primary)
<fieldset>
<input class="button primaryAction" type="submit" value="@T("Save")" />
</fieldset>
}
@Html.ValidationSummary()
@Display(Model.Content)
<fieldset>
<button class="primaryAction" type="submit">@T("Save")</button>
</fieldset>
}

View File

@@ -33,6 +33,6 @@
<div>
<label for="SiteDebugMode">@T("Resource Debug Mode")</label>
@Html.DropDownList("ResourceDebugMode", resourceDebugMode)
<p>@T("Determines whether scripts and stylesheets load in their debuggable or minified form.")</p>
<span class="hint">@T("Determines whether scripts and stylesheets load in their debuggable or minified form.")</span>
</div>
</fieldset>

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -1,7 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Orchard.UI.Resources;
namespace Orchard.Core.Shapes {
@@ -11,6 +7,11 @@ namespace Orchard.Core.Shapes {
manifest.DefineScript("ShapesBase").SetUrl("base.js").SetDependencies("jQuery");
manifest.DefineStyle("Shapes").SetUrl("site.css"); // todo: missing
manifest.DefineStyle("ShapesSpecial").SetUrl("special.css");
manifest.DefineScript("Switchable").SetUrl("jquery.switchable.js")
.SetDependencies("jQuery")
.SetDependencies("ShapesBase");
manifest.DefineStyle("Switchable").SetUrl("jquery.switchable.css");
}
}
}

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<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

@@ -85,15 +85,48 @@
var firstError = _this.find(".input-validation-error").first();
// try to focus the first error on the page
if (firstError.size() === 1) {
return firstError.focus();
firstError.focus();
return _this;
}
// or, give it up to the browser to autofocus
if ('autofocus' in document.createElement('input')) {
return;
return _this;
}
// otherwise, make the autofocus attribute work
var autofocus = _this.find(":input[autofocus]").first();
return autofocus.focus();
autofocus.focus();
return _this;
},
helpfullyPlacehold: function () {
var _this = $(this);
// give it up to the browser to handle placeholder text
if ('placeholder' in document.createElement('input')) {
return _this;
}
// otherwise, make the placeholder attribute work
$(":input[placeholder]")
.each(function () {
var _this = $(this);
if (_this.val() === "") {
_this.val(_this.attr("placeholder")).addClass("placeholderd");
}
})
.live("focus", function () {
var _this = $(this);
if (_this.val() === _this.attr("placeholder")) {
_this.val("").removeClass("placeholderd");
}
})
.live("blur", function () {
var _this = $(this);
if (_this.val() === "") {
_this.val(_this.attr("placeholder")).addClass("placeholderd");
}
});
return _this;
},
toggleWhatYouControl: function () {
var _this = $(this);
@@ -103,14 +136,14 @@
_controllees.hide(); // <- unhook this when the following comment applies
$(_controllees.show()[0]).find("input").focus(); // <- aaaand a slideDown there...eventually
} else if (!(_this.is(":checked") && _controlleesAreHidden)) {
//_controllees.slideUp(200); <- hook this back up when chrome behaves, or when I care less
//_controllees.slideUp(200); <- hook this back up when chrome behaves, or when I care less...or when chrome behaves
_controllees.hide()
}
return this;
return _this;
}
});
// collapsable areas - anything with a data-controllerid attribute has its visibility controlled by the id-ed radio/checkbox
(function () {
$(function () {
$("[data-controllerid]").each(function () {
var controller = $("#" + $(this).attr("data-controllerid"));
if (controller.data("isControlling")) {
@@ -126,9 +159,9 @@
$("[name=" + controller.attr("name") + "]").click(function () { $("[name=" + $(this).attr("name") + "]").each($(this).toggleWhatYouControl); });
}
});
})();
});
// inline form link buttons (form.inline.link button) swapped out for a link that submits said form
(function () {
$(function () {
$("form.inline.link").each(function () {
var _this = $(this);
var link = $("<a class='wasFormInlineLink' href='.'/>");
@@ -141,10 +174,12 @@
_this.css({ "position": "absolute", "left": "-9999em" });
$("body").append(_this);
});
})();
// (do) a little better autofocus
});
// some default value add behavior
$(function () {
$("body").helpfullyFocus();
$("body").helpfullyFocus() // (do) a little better autofocus
.helpfullyPlacehold(); // pick up on placeholders
});
// UnsafeUrl links -> form POST
//todo: need some real microdata support eventually (incl. revisiting usage of data-* attributes)

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<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,41 @@
@{
var nextText = HasText(Model.NextText) ? Model.NextText : T("Older").Text;
var previousText = HasText(Model.PreviousText) ? Model.PreviousText : T("Newer").Text;
var routeData = new RouteValueDictionary(ViewContext.RouteData.Values);
var queryString = ViewContext.HttpContext.Request.QueryString;
if (queryString != null) {
foreach (string key in queryString.Keys) {
if (key != null && !routeData.ContainsKey(key)) {
var value = queryString[key];
routeData[key] = queryString[key];
}
}
}
if (routeData.ContainsKey("id") && !HasText(routeData["id"])) {
routeData.Remove("id");
}
var hasNextPage = (Model.Page * Model.PageSize) < Model.TotalItemCount;
Model.Classes.Add("pager");
Model.Classes.Add("group");
var tag = Tag(Model, "ul");
}
@if (hasNextPage || Model.Page > 1) {
@tag.StartElement
if(hasNextPage) {
routeData["page"] = Model.Page + 1;
<li class="page-next">
@Html.ActionLink((string)nextText, (string)routeData["action"], (string)routeData["controller"], routeData, null)
</li>
}
if(Model.Page > 1) {
routeData["page"] = Model.Page - 1;
<li class="page-previous">
@Html.ActionLink((string)previousText, (string)routeData["action"], (string)routeData["controller"], routeData, null)
</li>
}
@tag.EndElement
}

View File

@@ -1,5 +0,0 @@
@{
Style.Require("Switchable");
Script.Require("Switchable");
}
@string.Format("{0} switchable", Model)

View File

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -1,31 +0,0 @@
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"/>
</assemblies>
</compilation>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
<add namespace="System.Linq"/>
<add namespace="System.Collections.Generic"/>
<add namespace="Orchard.Mvc.Html"/>
</namespaces>
</pages>
</system.web>
<system.web.extensions/>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="2.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<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

@@ -23,6 +23,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>..\..\..\OrchardBasicCorrectness.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -61,9 +62,6 @@
<ItemGroup>
<Content Include="Module.txt" />
</ItemGroup>
<ItemGroup>
<Content Include="Web.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Orchard\Orchard.Framework.csproj">
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>

View File

@@ -1,6 +1,6 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
@@ -33,3 +33,4 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.8.0")]
[assembly: AssemblyFileVersion("0.8.0")]
[assembly: SecurityTransparent]

View File

@@ -1,32 +0,0 @@
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35, processorArchitecture=MSIL"/>
</assemblies>
</compilation>
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID">
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
<add namespace="System.Linq"/>
<add namespace="System.Collections.Generic"/>
<add namespace="Orchard.Mvc.Html"/>
</namespaces>
</pages>
</system.web>
<system.web.extensions/>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="2.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<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

@@ -23,6 +23,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>..\..\..\OrchardBasicCorrectness.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -83,6 +84,16 @@
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="Styles\Web.config">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="Content\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

@@ -1,6 +1,6 @@
<Placement>
<Place Parts_ArchiveLater_Edit="Sidebar:2"/>
<Match DisplayType="SummaryAdmin">
<Place Parts_ArchiveLater_Metadata_SummaryAdmin="Meta:2"/>
</Match>
<Place Parts_ArchiveLater_Edit="Secondary:2"/>
</Placement>

View File

@@ -1,6 +1,6 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
@@ -32,3 +32,4 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
[assembly: AssemblyVersion("0.8.0")]
[assembly: AssemblyFileVersion("0.8.0")]
[assembly: SecurityTransparent]

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<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

@@ -2,8 +2,6 @@
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
@@ -27,8 +25,6 @@
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
<runtime>

View File

@@ -16,7 +16,7 @@ namespace Orchard.Blogs {
public string MenuName { get { return "admin"; } }
public void GetNavigation(NavigationBuilder builder) {
builder.Add(T("Blogs"), "1", BuildMenu);
builder.Add(T("Blogs"), "2.5", BuildMenu);
}
private void BuildMenu(NavigationItemBuilder menu) {
@@ -24,16 +24,15 @@ namespace Orchard.Blogs {
var blogCount = blogs.Count();
var singleBlog = blogCount == 1 ? blogs.ElementAt(0) : null;
if (blogCount > 0 && singleBlog == null)
menu.Add(T("Manage Blogs"), "1.0",
item =>
item.Action("List", "BlogAdmin", new {area = "Orchard.Blogs"}).Permission(Permissions.MetaListBlogs));
if (blogCount > 0 && singleBlog == null) {
menu.Add(T("List"), "3",
item => item.Action("List", "BlogAdmin", new {area = "Orchard.Blogs"}).Permission(Permissions.MetaListBlogs));
}
else if (singleBlog != null)
menu.Add(T("Manage Blog"), "1.0",
item =>
item.Action("Item", "BlogAdmin", new {area = "Orchard.Blogs", blogSlug = singleBlog.Slug}).Permission(Permissions.MetaListBlogs));
item => item.Action("Item", "BlogAdmin", new { area = "Orchard.Blogs", blogSlug = singleBlog.Slug }).Permission(Permissions.MetaListBlogs));
if ( singleBlog != null )
if (singleBlog != null)
menu.Add(T("Create New Post"), "1.1",
item =>
item.Action("Create", "BlogPostAdmin", new { area = "Orchard.Blogs", blogSlug = singleBlog.Slug }).Permission(Permissions.PublishBlogPost));

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<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

@@ -10,6 +10,7 @@ using Orchard.Data;
using Orchard.DisplayManagement;
using Orchard.Localization;
using Orchard.UI.Admin;
using Orchard.UI.Navigation;
using Orchard.UI.Notify;
namespace Orchard.Blogs.Controllers {
@@ -27,7 +28,8 @@ namespace Orchard.Blogs.Controllers {
IBlogPostService blogPostService,
IContentManager contentManager,
ITransactionManager transactionManager,
IBlogSlugConstraint blogSlugConstraint) {
IBlogSlugConstraint blogSlugConstraint,
IShapeFactory shapeFactory) {
Services = services;
_blogService = blogService;
_blogPostService = blogPostService;
@@ -35,8 +37,10 @@ namespace Orchard.Blogs.Controllers {
_transactionManager = transactionManager;
_blogSlugConstraint = blogSlugConstraint;
T = NullLocalizer.Instance;
Shape = shapeFactory;
}
dynamic Shape { get; set; }
public Localizer T { get; set; }
public IOrchardServices Services { get; set; }
@@ -135,14 +139,25 @@ namespace Orchard.Blogs.Controllers {
return View(viewModel);
}
public ActionResult Item(string blogSlug) {
public ActionResult Item(string blogSlug, Pager pager) {
BlogPart blogPart = _blogService.Get(blogSlug);
if (blogPart == null)
return HttpNotFound();
var model = Services.ContentManager.BuildDisplay(blogPart, "DetailAdmin");
return View(model);
var blogPosts = _blogPostService.Get(blogPart, pager.GetStartIndex(), pager.PageSize, VersionOptions.Latest)
.Select(bp => _contentManager.BuildDisplay(bp, "SummaryAdmin"));
var blog = Services.ContentManager.BuildDisplay(blogPart, "DetailAdmin");
var list = Shape.List();
list.AddRange(blogPosts);
blog.Content.Add(Shape.Parts_Blogs_BlogPost_ListAdmin(ContentItems: list), "5");
var totalItemCount = _blogPostService.PostCount(blogPart, VersionOptions.Latest);
blog.Content.Add(Shape.Pager(pager).TotalItemCount(totalItemCount), "Content:after");
return View(blog);
}
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {

View File

@@ -3,13 +3,15 @@ using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Xml.Linq;
using Orchard.Blogs.Extensions;
using Orchard.Blogs.Models;
using Orchard.Blogs.Routing;
using Orchard.Blogs.Services;
using Orchard.ContentManagement;
using Orchard.Core.Feeds;
using Orchard.DisplayManagement;
using Orchard.Logging;
using Orchard.Themes;
using Orchard.UI.Navigation;
namespace Orchard.Blogs.Controllers {
[Themed]
@@ -18,6 +20,7 @@ namespace Orchard.Blogs.Controllers {
private readonly IBlogService _blogService;
private readonly IBlogPostService _blogPostService;
private readonly IBlogSlugConstraint _blogSlugConstraint;
private readonly IFeedManager _feedManager;
private readonly RouteCollection _routeCollection;
public BlogController(
@@ -25,12 +28,14 @@ namespace Orchard.Blogs.Controllers {
IBlogService blogService,
IBlogPostService blogPostService,
IBlogSlugConstraint blogSlugConstraint,
IFeedManager feedManager,
RouteCollection routeCollection,
IShapeFactory shapeFactory) {
_services = services;
_blogService = blogService;
_blogPostService = blogPostService;
_blogSlugConstraint = blogSlugConstraint;
_feedManager = feedManager;
_routeCollection = routeCollection;
Logger = NullLogger.Instance;
Shape = shapeFactory;
@@ -51,10 +56,7 @@ namespace Orchard.Blogs.Controllers {
return View(viewModel);
}
//TODO: (erikpo) Should move the slug parameter and get call and null check up into a model binder
public ActionResult Item(string blogSlug, int page) {
const int pageSize = 10;
public ActionResult Item(string blogSlug, Pager pager) {
var correctedSlug = _blogSlugConstraint.FindSlug(blogSlug);
if (correctedSlug == null)
return HttpNotFound();
@@ -63,21 +65,18 @@ namespace Orchard.Blogs.Controllers {
if (blogPart == null)
return HttpNotFound();
var blogPosts = _blogPostService.Get(blogPart, (page - 1) * pageSize, pageSize)
_feedManager.Register(blogPart);
var blogPosts = _blogPostService.Get(blogPart, pager.GetStartIndex(), pager.PageSize)
.Select(b => _services.ContentManager.BuildDisplay(b, "Summary"));
blogPart.As<BlogPagerPart>().Page = page;
blogPart.As<BlogPagerPart>().PageSize = pageSize;
blogPart.As<BlogPagerPart>().BlogSlug = correctedSlug;
blogPart.As<BlogPagerPart>().ThereIsANextPage = _blogPostService.Get(blogPart, (page) * pageSize, pageSize).Any();
var blog = _services.ContentManager.BuildDisplay(blogPart);
var list = Shape.List();
list.AddRange(blogPosts);
blog.Content.Add(Shape.Parts_Blogs_BlogPost_List(ContentItems: list), "5");
var totalItemCount = _blogPostService.PostCount(blogPart);
blog.Content.Add(Shape.Pager(pager).TotalItemCount(totalItemCount), "Content:after");
return View(blog);
}

View File

@@ -1,11 +0,0 @@
using Orchard.Blogs.Models;
using Orchard.ContentManagement.Drivers;
namespace Orchard.Blogs.Drivers {
public class BlogPagerPartDriver : ContentPartDriver<BlogPagerPart> {
protected override DriverResult Display(BlogPagerPart part, string displayType, dynamic shapeHelper) {
return ContentShape("Parts_Blogs_Blog_Pager",
() => shapeHelper.Parts_Blogs_Blog_Pager(ContentPart: part, Page: part.Page, PageSize: part.PageSize, BlogSlug: part.BlogSlug, ThereIsANextPage: part.ThereIsANextPage));
}
}
}

View File

@@ -41,24 +41,25 @@ namespace Orchard.Blogs.Drivers {
ContentShape("Parts_Blogs_Blog_Description",
() => shapeHelper.Parts_Blogs_Blog_Description(ContentPart: part, Description: part.Description)),
ContentShape("Parts_Blogs_Blog_BlogPostCount",
() => shapeHelper.Parts_Blogs_Blog_BlogPostCount(ContentPart: part, PostCount: part.PostCount)),
() => shapeHelper.Parts_Blogs_Blog_BlogPostCount(ContentPart: part, PostCount: part.PostCount))
//,
// todo: (heskew) implement a paging solution that doesn't require blog posts to be tied to the blog within the controller
ContentShape("Parts_Blogs_BlogPost_List",
() => {
_feedManager.Register(part);
return null;
//ContentShape("Parts_Blogs_BlogPost_List",
// () => {
// _feedManager.Register(part);
// var list = shapeHelper.List();
// list.AddRange(_blogPostService.Get(part)
// .Select(bp => _contentManager.BuildDisplay(bp, "Summary")));
// return shapeHelper.Parts_Blogs_BlogPost_List(ContentPart: part, ContentItems: list);
}),
ContentShape("Parts_Blogs_BlogPost_List_Admin",
() => {
var list = shapeHelper.List();
list.AddRange(_blogPostService.Get(part, VersionOptions.Latest)
.Select(bp => _contentManager.BuildDisplay(bp, "SummaryAdmin")));
return shapeHelper.Parts_Blogs_BlogPost_List_Admin(ContentPart: part, ContentItems: list);
})
// }),
//ContentShape("Parts_Blogs_BlogPost_List_Admin",
// () =>
// {
// var list = shapeHelper.List();
// list.AddRange(_blogPostService.Get(part, VersionOptions.Latest)
// .Select(bp => _contentManager.BuildDisplay(bp, "SummaryAdmin")));
// return shapeHelper.Parts_Blogs_BlogPost_List_Admin(ContentPart: part, ContentItems: list);
// })
);
}

View File

@@ -39,7 +39,6 @@ namespace Orchard.Blogs {
.WithPart("BlogPart")
.WithPart("CommonPart")
.WithPart("RoutePart")
.WithPart("BlogPagerPart")
);
ContentDefinitionManager.AlterTypeDefinition("BlogPost",

View File

@@ -1,10 +0,0 @@
using Orchard.ContentManagement;
namespace Orchard.Blogs.Models {
public class BlogPagerPart : ContentPart {
public int Page { get; set; }
public int PageSize { get; set; }
public string BlogSlug { get; set; }
public bool ThereIsANextPage { get; set; }
}
}

View File

@@ -9,10 +9,10 @@ Features:
Orchard.Blogs:
Name: Blogs
Description: A simple web log.
Dependencies: Feeds
Dependencies: Shapes, Common, Routable, Feeds, Orchard.Widgets, Orchard.jQuery
Category: Content
Orchard.Blogs.RemotePublishing:
Name: Remote Blog Publishing
Description: Blog easier using a dedicated MetaWeblogAPI-compatible publishing tool.
Dependencies: XmlRpc
Category: Content Publishing
Dependencies: XmlRpc, Orchard.Blogs
Category: Content Publishing

View File

@@ -27,7 +27,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet>..\..\..\OrchardBasicCorrectness.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -55,14 +55,12 @@
<ItemGroup>
<Compile Include="AdminMenu.cs" />
<Compile Include="Drivers\BlogArchivesPartDriver.cs" />
<Compile Include="Drivers\BlogPagerPartDriver.cs" />
<Compile Include="Drivers\RemoteBlogPublishingDriver.cs" />
<Compile Include="Drivers\RecentBlogPostsPartDriver.cs" />
<Compile Include="Handlers\BlogArchivesPartHandler.cs" />
<Compile Include="Handlers\RecentBlogPostsPartHandler.cs" />
<Compile Include="Models\BlogArchivesPart.cs" />
<Compile Include="Models\BlogArchivesPartRecord.cs" />
<Compile Include="Models\BlogPagerPart.cs" />
<Compile Include="Models\RecentBlogPostsPart.cs" />
<Compile Include="Models\RecentBlogPostsPartRecord.cs" />
<Compile Include="ResourceManifest.cs" />
@@ -107,7 +105,6 @@
<Content Include="Scripts\archives.js" />
<Content Include="Styles\admin.css" />
<Content Include="Styles\archives.css" />
<Content Include="Styles\pagination.css" />
<Content Include="Views\BlogAdmin\Create.cshtml" />
<Content Include="Views\BlogAdmin\Edit.cshtml" />
<Content Include="Views\BlogAdmin\Item.cshtml" />
@@ -121,11 +118,10 @@
<Content Include="Views\Parts\Blogs.Blog.Manage.cshtml" />
<Content Include="Views\Parts\Blogs.Blog.Description.cshtml" />
<Content Include="Views\EditorTemplates\Parts\Blogs.Blog.Fields.cshtml" />
<Content Include="Views\Parts\Blogs.BlogPost.List.Admin.cshtml">
<Content Include="Views\Parts\Blogs.BlogPost.ListAdmin.cshtml">
<SubType>Code</SubType>
</Content>
<Content Include="Views\Items\Content-Blog.SummaryAdmin.cshtml" />
<Content Include="Web.config" />
<Content Include="Views\Web.config" />
</ItemGroup>
<ItemGroup>
@@ -149,12 +145,18 @@
<Content Include="Views\EditorTemplates\Parts\Blogs.BlogArchives.cshtml" />
<Content Include="Views\Items\Content-Blog.DetailAdmin.cshtml" />
<Content Include="Views\Items\Content-Blog.Edit.cshtml" />
<Content Include="Views\Items\Content-BlogPost.Editor.cshtml" />
<Content Include="Views\Items\Content-BlogPost.SummaryAdmin.cshtml" />
<Content Include="Views\Parts\Blogs.BlogPost.List.cshtml" />
<Content Include="Views\Parts\Blogs.Blog.Pager.cshtml" />
<Content Include="Views\Parts\Blogs.RecentBlogPosts.cshtml" />
<Content Include="Views\Parts\Blogs.Blog.BlogPostCount.cshtml" />
<Content Include="Scripts\Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Styles\Web.config">
<SubType>Designer</SubType>
</Content>
<Content Include="Content\Web.config">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

Some files were not shown because too many files have changed in this diff Show More