diff --git a/src/Orchard.Core.Tests/Feeds/Controllers/FeedControllerTests.cs b/src/Orchard.Core.Tests/Feeds/Controllers/FeedControllerTests.cs index 3970d40f7..98504a380 100644 --- a/src/Orchard.Core.Tests/Feeds/Controllers/FeedControllerTests.cs +++ b/src/Orchard.Core.Tests/Feeds/Controllers/FeedControllerTests.cs @@ -167,7 +167,7 @@ namespace Orchard.Core.Tests.Feeds.Controllers { var mockContentManager = new Mock(); mockContentManager.Setup(x => x.GetItemMetadata(It.IsAny())) - .Returns(new ContentItemMetadata { DisplayText = "foo" }); + .Returns(new ContentItemMetadata(hello) { DisplayText = "foo" }); var builder = new ContainerBuilder(); //builder.RegisterModule(new ImplicitCollectionSupportModule()); diff --git a/src/Orchard.Web/Core/Contents/AdminMenu.cs b/src/Orchard.Web/Core/Contents/AdminMenu.cs index ffb707816..bd1a122fa 100644 --- a/src/Orchard.Web/Core/Contents/AdminMenu.cs +++ b/src/Orchard.Web/Core/Contents/AdminMenu.cs @@ -1,19 +1,37 @@ -using Orchard.Localization; +using System.Linq; +using Orchard.ContentManagement; +using Orchard.ContentManagement.MetaData; +using Orchard.Localization; using Orchard.UI.Navigation; namespace Orchard.Core.Contents { public class AdminMenu : INavigationProvider { + private readonly IContentDefinitionManager _contentDefinitionManager; + private readonly IContentManager _contentManager; + + public AdminMenu(IContentDefinitionManager contentDefinitionManager, IContentManager contentManager) { + _contentDefinitionManager = contentDefinitionManager; + _contentManager = contentManager; + } + public Localizer T { get; set; } public string MenuName { get { return "admin"; } } public void GetNavigation(NavigationBuilder builder) { - builder.Add(T("Content"), "1", - menu => { - menu.Add(T("Create New Content"), "1.1", item => item.Action("Create", "Admin", new { area = "Contents" })); - menu.Add(T("Manage Content"), "1.2", item => item.Action("List", "Admin", new { area = "Contents" })); - }); + var contentTypeDefinitions = _contentDefinitionManager.ListTypeDefinitions().OrderBy(d => d.Name); + + builder.Add(T("Content"), "1", menu => { + menu.Add(T("Manage Content"), "1.2", item => item.Action("List", "Admin", new {area = "Contents"})); + //foreach (var contentTypeDefinition in contentTypeDefinitions) { + // var ci = _contentManager.New(contentTypeDefinition.Name); + // var cim = _contentManager.GetItemMetadata(ci); + // var createRouteValues = cim.CreateRouteValues; + // if (createRouteValues.Any()) + // menu.Add(T("Create New {0}", contentTypeDefinition.DisplayName), "1.3", item => item.Action(cim.CreateRouteValues["Action"] as string, cim.CreateRouteValues["Controller"] as string, cim.CreateRouteValues)); + //} + }); builder.Add(T("Site Configuration"), "11", - menu => menu.Add(T("Content Types"), "3", item => item.Action("Types", "Admin", new { area = "Contents" }))); + menu => menu.Add(T("Content Types"), "3", item => item.Action("Index", "Admin", new { area = "Contents" }))); } } } \ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/ContentTypeDefinitionStub.cs b/src/Orchard.Web/Core/Contents/ContentTypeDefinitionStub.cs new file mode 100644 index 000000000..45af29afd --- /dev/null +++ b/src/Orchard.Web/Core/Contents/ContentTypeDefinitionStub.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations; + +namespace Orchard.Core.Contents { + public class ContentTypeDefinitionStub { + [StringLength(128)] + public string Name { get; set; } + [Required, StringLength(1024)] + public string DisplayName { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs b/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs index 7667980f8..a2f8dcacf 100644 --- a/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs +++ b/src/Orchard.Web/Core/Contents/Controllers/AdminController.cs @@ -4,7 +4,7 @@ using System.Web.Mvc; using System.Web.Routing; using Orchard.ContentManagement; using Orchard.ContentManagement.MetaData; -using Orchard.ContentManagement.Records; +using Orchard.Core.Contents.Services; using Orchard.Core.Contents.ViewModels; using Orchard.Data; using Orchard.Localization; @@ -16,37 +16,72 @@ namespace Orchard.Core.Contents.Controllers { [ValidateInput(false)] public class AdminController : Controller, IUpdateModel { private readonly INotifier _notifier; - private readonly IContentDefinitionManager _contentDefinitionManager; + private readonly IContentDefinitionService _contentDefinitionService; private readonly IContentManager _contentManager; private readonly ITransactionManager _transactionManager; public AdminController( + IOrchardServices orchardServices, INotifier notifier, - IContentDefinitionManager contentDefinitionManager, + IContentDefinitionService contentDefinitionService, IContentManager contentManager, ITransactionManager transactionManager) { + Services = orchardServices; _notifier = notifier; - _contentDefinitionManager = contentDefinitionManager; + _contentDefinitionService = contentDefinitionService; _contentManager = contentManager; _transactionManager = transactionManager; T = NullLocalizer.Instance; Logger = NullLogger.Instance; } + public IOrchardServices Services { get; private set; } public Localizer T { get; set; } public ILogger Logger { get; set; } + #region Types + public ActionResult Index() { return Types(); } public ActionResult Types() { - return View("Types", new ContentTypeListViewModel { - Types = _contentDefinitionManager.ListTypeDefinitions() + return View("Types", new ListContentTypesViewModel { + Types = _contentDefinitionService.GetTypeDefinitions() }); } - public ActionResult List(ListContentViewModel model) { + public ActionResult CreateType(CreateTypeViewModel viewModel) { + if (!Services.Authorizer.Authorize(Permissions.CreateContentType, T("Not allowed to create a content type."))) + return new HttpUnauthorizedResult(); + + return View(viewModel); + } + + [HttpPost, ActionName("CreateType")] + public ActionResult CreateTypePOST(CreateTypeViewModel viewModel) { + if (!Services.Authorizer.Authorize(Permissions.CreateContentType, T("Not allowed to create a content type."))) + return new HttpUnauthorizedResult(); + + var model = new ContentTypeDefinitionStub(); + TryUpdateModel(model); + + if (!ModelState.IsValid) { + Services.TransactionManager.Cancel(); + return View(viewModel); + } + + _contentDefinitionService.AddTypeDefinition(model); + + return RedirectToAction("Index"); + } + + #endregion + + #region Content + #endregion + + public ActionResult List(ListContentsViewModel model) { const int pageSize = 20; var skip = (Math.Max(model.Page ?? 0, 1) - 1) * pageSize; @@ -63,8 +98,8 @@ namespace Orchard.Core.Contents.Controllers { return View("List", model); } - private ListContentViewModel.Entry BuildEntry(ContentItem contentItem) { - var entry = new ListContentViewModel.Entry { + private ListContentsViewModel.Entry BuildEntry(ContentItem contentItem) { + var entry = new ListContentsViewModel.Entry { ContentItem = contentItem, ContentItemMetadata = _contentManager.GetItemMetadata(contentItem), ViewModel = _contentManager.BuildDisplayModel(contentItem, "List"), @@ -84,8 +119,8 @@ namespace Orchard.Core.Contents.Controllers { } ActionResult CreatableTypeList() { - var model = new ContentTypeListViewModel { - Types = _contentDefinitionManager.ListTypeDefinitions() + var model = new ListContentTypesViewModel { + Types = _contentDefinitionService.GetTypeDefinitions() }; return View("CreatableTypeList", model); @@ -107,6 +142,7 @@ namespace Orchard.Core.Contents.Controllers { [HttpPost] public ActionResult Create(CreateItemViewModel model) { + //todo: need to integrate permissions into generic content management var contentItem = _contentManager.New(model.Id); model.Content = _contentManager.UpdateEditorModel(contentItem, this); if (ModelState.IsValid) { diff --git a/src/Orchard.Web/Core/Contents/Handlers/ContentsModuleHandler.cs b/src/Orchard.Web/Core/Contents/Handlers/ContentsModuleHandler.cs index 9abef1511..cdaf807a4 100644 --- a/src/Orchard.Web/Core/Contents/Handlers/ContentsModuleHandler.cs +++ b/src/Orchard.Web/Core/Contents/Handlers/ContentsModuleHandler.cs @@ -1,13 +1,16 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Web; -using System.Web.Routing; +using System.Web.Routing; using Orchard.ContentManagement.Handlers; namespace Orchard.Core.Contents.Handlers { public class ContentsModuleHandler : ContentHandlerBase { public override void GetContentItemMetadata(GetContentItemMetadataContext context) { + if (context.Metadata.CreateRouteValues == null) { + context.Metadata.CreateRouteValues = new RouteValueDictionary { + {"Area", "Contents"}, + {"Controller", "Item"}, + {"Action", "Create"} + }; + } if (context.Metadata.EditorRouteValues == null) { context.Metadata.EditorRouteValues = new RouteValueDictionary { {"Area", "Contents"}, diff --git a/src/Orchard.Web/Core/Contents/Permissions.cs b/src/Orchard.Web/Core/Contents/Permissions.cs new file mode 100644 index 000000000..8fc85f1ae --- /dev/null +++ b/src/Orchard.Web/Core/Contents/Permissions.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using Orchard.Security.Permissions; + +namespace Orchard.Core.Contents { + public class Permissions : IPermissionProvider { + public static readonly Permission CreateContentType = new Permission { Name = "CreateContentType", Description = "Create custom content type." }; + + public string ModuleName { + get { return "Contents"; } + } + + public IEnumerable GetPermissions() { + return new Permission[] { + CreateContentType, + }; + } + + public IEnumerable GetDefaultStereotypes() { + return new[] { + new PermissionStereotype { + Name = "Administrator", + Permissions = new[] {CreateContentType} + } + }; + } + } +} diff --git a/src/Orchard.Web/Core/Contents/Services/ContentDefinitionService.cs b/src/Orchard.Web/Core/Contents/Services/ContentDefinitionService.cs new file mode 100644 index 000000000..473bebcea --- /dev/null +++ b/src/Orchard.Web/Core/Contents/Services/ContentDefinitionService.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using Orchard.ContentManagement.MetaData; +using Orchard.ContentManagement.MetaData.Models; +using Orchard.Localization; +using Orchard.UI.Notify; + +namespace Orchard.Core.Contents.Services { + public class ContentDefinitionService : IContentDefinitionService { + private readonly IContentDefinitionManager _contentDefinitionManager; + + public ContentDefinitionService(IOrchardServices services, IContentDefinitionManager contentDefinitionManager) { + Services = services; + _contentDefinitionManager = contentDefinitionManager; + T = NullLocalizer.Instance; + } + + public IOrchardServices Services { get; set; } + public Localizer T { get; set; } + + public IEnumerable GetTypeDefinitions() { + return _contentDefinitionManager.ListTypeDefinitions(); + } + + public ContentTypeDefinition GetTypeDefinition(string name) { + throw new NotImplementedException(); + } + + public void AddTypeDefinition(ContentTypeDefinitionStub definitionStub) { + if (string.IsNullOrWhiteSpace(definitionStub.Name)) + definitionStub.Name = GenerateTypeName(definitionStub.DisplayName); + + while (_contentDefinitionManager.GetTypeDefinition(definitionStub.Name) != null) + definitionStub.Name = VersionTypeName(definitionStub.Name); + + //just giving the new type some default parts for now + _contentDefinitionManager.AlterTypeDefinition( + definitionStub.Name, + cfg => cfg.Named(definitionStub.Name, definitionStub.DisplayName) + .WithPart("CommonAspect") + //.WithPart("RoutableAspect") //need to go the new routable route + .WithPart("BodyAspect")); + + Services.Notifier.Information(T("Created content type: {0}", definitionStub.DisplayName)); + } + + public void RemoveTypeDefinition(string name) { + throw new NotImplementedException(); + } + + //gratuitously stolen from the RoutableService + private static string GenerateTypeName(string displayName) { + if (string.IsNullOrWhiteSpace(displayName)) + return ""; + + var name = displayName; + //todo: might need to be made more restrictive depending on how name is used (like as an XML node name, for instance) + var dissallowed = new Regex(@"[/:?#\[\]@!$&'()*+,;=\s]+"); + + name = dissallowed.Replace(name, "-"); + name = name.Trim('-'); + + if (name.Length > 128) + name = name.Substring(0, 128); + + return name.ToLowerInvariant(); + } + + private static string VersionTypeName(string name) { + var version = 2; + var nameParts = name.Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries); + + if (nameParts.Length > 1 && int.TryParse(nameParts.Last(), out version)) { + version = version > 0 ? ++version : 2; + //this could unintentionally chomp something that looks like a version + name = string.Join("-", nameParts.Take(nameParts.Length - 1)); + } + + return string.Format("{0}-{1}", name, version); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/Services/IContentDefinitionService.cs b/src/Orchard.Web/Core/Contents/Services/IContentDefinitionService.cs new file mode 100644 index 000000000..c4f996bd9 --- /dev/null +++ b/src/Orchard.Web/Core/Contents/Services/IContentDefinitionService.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using Orchard.ContentManagement.MetaData.Models; + +namespace Orchard.Core.Contents.Services { + public interface IContentDefinitionService : IDependency { + IEnumerable GetTypeDefinitions(); + ContentTypeDefinition GetTypeDefinition(string name); + void AddTypeDefinition(ContentTypeDefinitionStub contentTypeDefinition); + void RemoveTypeDefinition(string name); + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/ViewModels/CreateTypeViewModel.cs b/src/Orchard.Web/Core/Contents/ViewModels/CreateTypeViewModel.cs new file mode 100644 index 000000000..611ec7bb6 --- /dev/null +++ b/src/Orchard.Web/Core/Contents/ViewModels/CreateTypeViewModel.cs @@ -0,0 +1,7 @@ +using Orchard.Mvc.ViewModels; + +namespace Orchard.Core.Contents.ViewModels { + public class CreateTypeViewModel : BaseViewModel { + public string DisplayName { get; set; } + } +} diff --git a/src/Orchard.Web/Core/Contents/ViewModels/ContentTypeListViewModel.cs b/src/Orchard.Web/Core/Contents/ViewModels/ListContentTypesViewModel.cs similarity index 78% rename from src/Orchard.Web/Core/Contents/ViewModels/ContentTypeListViewModel.cs rename to src/Orchard.Web/Core/Contents/ViewModels/ListContentTypesViewModel.cs index 321e98365..ab46d9040 100644 --- a/src/Orchard.Web/Core/Contents/ViewModels/ContentTypeListViewModel.cs +++ b/src/Orchard.Web/Core/Contents/ViewModels/ListContentTypesViewModel.cs @@ -4,7 +4,7 @@ using Orchard.ContentManagement.MetaData.Models; using Orchard.Mvc.ViewModels; namespace Orchard.Core.Contents.ViewModels { - public class ContentTypeListViewModel : BaseViewModel { + public class ListContentTypesViewModel : BaseViewModel { public IEnumerable Types { get; set; } } } \ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/ViewModels/ListContentViewModel.cs b/src/Orchard.Web/Core/Contents/ViewModels/ListContentsViewModel.cs similarity index 87% rename from src/Orchard.Web/Core/Contents/ViewModels/ListContentViewModel.cs rename to src/Orchard.Web/Core/Contents/ViewModels/ListContentsViewModel.cs index 36b8cb39a..c0639640f 100644 --- a/src/Orchard.Web/Core/Contents/ViewModels/ListContentViewModel.cs +++ b/src/Orchard.Web/Core/Contents/ViewModels/ListContentsViewModel.cs @@ -4,7 +4,7 @@ using Orchard.ContentManagement; using Orchard.Mvc.ViewModels; namespace Orchard.Core.Contents.ViewModels { - public class ListContentViewModel : BaseViewModel { + public class ListContentsViewModel : BaseViewModel { public string Id { get; set; } public int? Page { get; set; } public IList Entries { get; set; } diff --git a/src/Orchard.Web/Core/Contents/Views/Admin/CreatableTypeList.aspx b/src/Orchard.Web/Core/Contents/Views/Admin/CreatableTypeList.aspx index f0859f699..8aac804bf 100644 --- a/src/Orchard.Web/Core/Contents/Views/Admin/CreatableTypeList.aspx +++ b/src/Orchard.Web/Core/Contents/Views/Admin/CreatableTypeList.aspx @@ -1,5 +1,4 @@ -<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage" %> - +<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage" %> <%@ Import Namespace="Orchard.Core.Contents.ViewModels" %> <% Html.AddTitleParts(T("Create Content").ToString()); %>

diff --git a/src/Orchard.Web/Core/Contents/Views/Admin/CreateType.ascx b/src/Orchard.Web/Core/Contents/Views/Admin/CreateType.ascx new file mode 100644 index 000000000..ca466aa3d --- /dev/null +++ b/src/Orchard.Web/Core/Contents/Views/Admin/CreateType.ascx @@ -0,0 +1,13 @@ +<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> +<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %> +

<%:Html.TitleForPage(T("New Content Type").ToString())%>

<% +using (Html.BeginFormAntiForgeryPost()) { %> + <%:Html.ValidationSummary() %> +
+ + <%:Html.TextBoxFor(m => m.DisplayName, new {@class = "textMedium", autofocus = "autofocus"}) %> +
+
+ +
<% +} %> \ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/Views/Admin/List.aspx b/src/Orchard.Web/Core/Contents/Views/Admin/List.aspx index 6921ed2f8..9ca47e1a4 100644 --- a/src/Orchard.Web/Core/Contents/Views/Admin/List.aspx +++ b/src/Orchard.Web/Core/Contents/Views/Admin/List.aspx @@ -1,5 +1,4 @@ -<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage" %> - +<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage" %> <%@ Import Namespace="Orchard.Core.Contents.ViewModels" %> <% Html.AddTitleParts(T("Browse Contents").ToString()); %>

diff --git a/src/Orchard.Web/Core/Contents/Views/Admin/Types.ascx b/src/Orchard.Web/Core/Contents/Views/Admin/Types.ascx new file mode 100644 index 000000000..017a42921 --- /dev/null +++ b/src/Orchard.Web/Core/Contents/Views/Admin/Types.ascx @@ -0,0 +1,9 @@ +<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> +<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %> +

<%:Html.TitleForPage(T("Content Types").ToString())%>

+
<%: Html.ActionLink(T("Create new type").ToString(), "CreateType", null, new { @class = "button primaryAction" })%>
+<%=Html.UnorderedList( + Model.Types, + (t,i) => Html.DisplayFor(m => t).ToHtmlString(), + "contentItems" + ) %> \ No newline at end of file diff --git a/src/Orchard.Web/Core/Contents/Views/Admin/Types.aspx b/src/Orchard.Web/Core/Contents/Views/Admin/Types.aspx deleted file mode 100644 index 51b90a383..000000000 --- a/src/Orchard.Web/Core/Contents/Views/Admin/Types.aspx +++ /dev/null @@ -1,24 +0,0 @@ -<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage" %> - -<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %> -<% Html.AddTitleParts(T("Create Content").ToString()); %> -

- Create content

- - <% foreach (var t in Model.Types) {%> - - - - - - - <%} %> -
- <%:t.Name %> - - <%:Html.ActionLink(T("List Items").ToString(), "List", "Admin", new RouteValueDictionary{{"Area","Contents"},{"Id",t.Name}}, new Dictionary()) %> - - <%:Html.ActionLink(T("Create Item").ToString(), "Create", "Admin", new RouteValueDictionary{{"Area","Contents"},{"Id",t.Name}}, new Dictionary()) %> - - <%:Html.ActionLink(T("Edit Type").ToString(), "ContentTypeList", "Admin", new RouteValueDictionary{{"Area","Orchard.MetaData"},{"Id",t.Name}}, new Dictionary()) %> -
diff --git a/src/Orchard.Web/Core/Contents/Views/DisplayTemplates/ContentTypeDefinition.ascx b/src/Orchard.Web/Core/Contents/Views/DisplayTemplates/ContentTypeDefinition.ascx new file mode 100644 index 000000000..525247982 --- /dev/null +++ b/src/Orchard.Web/Core/Contents/Views/DisplayTemplates/ContentTypeDefinition.ascx @@ -0,0 +1,14 @@ +<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl" %> +
+
+

<%:Model.DisplayName%>

+

<%:Model.Name %> - <%:Html.ActionLink("[new content]", "Create", new {area = "Contents", id = Model.Name}) %>

+
+ +
\ No newline at end of file diff --git a/src/Orchard.Web/Core/Orchard.Core.csproj b/src/Orchard.Web/Core/Orchard.Core.csproj index 68773d035..63b8f57d6 100644 --- a/src/Orchard.Web/Core/Orchard.Core.csproj +++ b/src/Orchard.Web/Core/Orchard.Core.csproj @@ -76,8 +76,15 @@ + + + + + + + @@ -105,9 +112,7 @@ - - @@ -216,11 +221,13 @@ - + + + diff --git a/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs b/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs index c3be204ac..7146e2415 100644 --- a/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs +++ b/src/Orchard.Web/Core/Settings/Metadata/ContentDefinitionManager.cs @@ -54,7 +54,7 @@ namespace Orchard.Core.Settings.Metadata { private ContentTypeDefinitionRecord Acquire(ContentTypeDefinition contentTypeDefinition) { var result = _typeDefinitionRepository.Fetch(x => x.Name == contentTypeDefinition.Name).SingleOrDefault(); if (result == null) { - result = new ContentTypeDefinitionRecord { Name = contentTypeDefinition.Name }; + result = new ContentTypeDefinitionRecord { Name = contentTypeDefinition.Name, DisplayName = contentTypeDefinition.DisplayName}; _typeDefinitionRepository.Create(result); } return result; @@ -100,6 +100,7 @@ namespace Orchard.Core.Settings.Metadata { ContentTypeDefinition Build(ContentTypeDefinitionRecord source) { return new ContentTypeDefinition( source.Name, + source.DisplayName, source.ContentTypePartDefinitionRecords.Select(Build), _settingsReader.Map(Parse(source.Settings))); } diff --git a/src/Orchard.Web/Core/Settings/Metadata/Records/ContentTypeDefinitionRecord.cs b/src/Orchard.Web/Core/Settings/Metadata/Records/ContentTypeDefinitionRecord.cs index 0f6806c19..a9870689e 100644 --- a/src/Orchard.Web/Core/Settings/Metadata/Records/ContentTypeDefinitionRecord.cs +++ b/src/Orchard.Web/Core/Settings/Metadata/Records/ContentTypeDefinitionRecord.cs @@ -9,6 +9,7 @@ namespace Orchard.Core.Settings.Metadata.Records { public virtual int Id { get; set; } public virtual string Name { get; set; } + public virtual string DisplayName { get; set; } public virtual bool Hidden { get; set; } public virtual string Settings { get; set; } diff --git a/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/BlogPostDriver.cs b/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/BlogPostDriver.cs index 9c65da7bd..f1bbc8ed6 100644 --- a/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/BlogPostDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Blogs/Drivers/BlogPostDriver.cs @@ -40,6 +40,9 @@ namespace Orchard.Blogs.Drivers { } public override RouteValueDictionary GetDisplayRouteValues(BlogPost post) { + if (post.Blog == null) + return new RouteValueDictionary(); + return new RouteValueDictionary { {"Area", "Orchard.Blogs"}, {"Controller", "BlogPost"}, @@ -50,6 +53,9 @@ namespace Orchard.Blogs.Drivers { } public override RouteValueDictionary GetEditorRouteValues(BlogPost post) { + if (post.Blog == null) + return new RouteValueDictionary(); + return new RouteValueDictionary { {"Area", "Orchard.Blogs"}, {"Controller", "BlogPostAdmin"}, @@ -59,6 +65,18 @@ namespace Orchard.Blogs.Drivers { }; } + public override RouteValueDictionary GetCreateRouteValues(BlogPost post) { + if (post.Blog == null) + return new RouteValueDictionary(); + + return new RouteValueDictionary { + {"Area", "Orchard.Blogs"}, + {"Controller", "BlogPostAdmin"}, + {"Action", "Create"}, + {"blogSlug", post.Blog.Slug}, + }; + } + protected override DriverResult Display(BlogPost post, string displayType) { return Combined( ContentItemTemplate("Items/Blogs.BlogPost").LongestMatch(displayType, "Summary", "SummaryAdmin"), diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/AdminMenu.cs b/src/Orchard.Web/Modules/Orchard.MetaData/AdminMenu.cs index dbba1d1be..5757fabdb 100644 --- a/src/Orchard.Web/Modules/Orchard.MetaData/AdminMenu.cs +++ b/src/Orchard.Web/Modules/Orchard.MetaData/AdminMenu.cs @@ -10,9 +10,9 @@ namespace Orchard.MetaData { public void GetNavigation(NavigationBuilder builder) { - builder.Add(T("Content Types"), "5", + builder.Add(T("Site Configuration"), "11", menu => menu - .Add(T("Content Types"), "1.0", item => item.Action("ContentTypeList", "Admin", new { area = "Orchard.MetaData" }).Permission(Permissions.ManageMetaData)) + .Add(T("Content Types (metadata)"), "3.1", item => item.Action("ContentTypeList", "Admin", new { area = "Orchard.MetaData" }).Permission(Permissions.ManageMetaData)) ); } diff --git a/src/Orchard.Web/Modules/Orchard.MetaData/Views/Admin/ContentTypeList.ascx b/src/Orchard.Web/Modules/Orchard.MetaData/Views/Admin/ContentTypeList.ascx index c0b78eead..d07a494d9 100644 --- a/src/Orchard.Web/Modules/Orchard.MetaData/Views/Admin/ContentTypeList.ascx +++ b/src/Orchard.Web/Modules/Orchard.MetaData/Views/Admin/ContentTypeList.ascx @@ -25,7 +25,7 @@ %> - <%= Html.ActionLink(item.Name, "ContentTypeList", new {id=item.Name})%> + <%= Html.ActionLink(string.IsNullOrWhiteSpace(item.Name) ? "unkwn" : item.Name, "ContentTypeList", new {id=item.Name})%> diff --git a/src/Orchard.Web/Modules/Orchard.Pages/Drivers/PageDriver.cs b/src/Orchard.Web/Modules/Orchard.Pages/Drivers/PageDriver.cs index b64a70e42..a16a90d17 100644 --- a/src/Orchard.Web/Modules/Orchard.Pages/Drivers/PageDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.Pages/Drivers/PageDriver.cs @@ -61,6 +61,14 @@ namespace Orchard.Pages.Drivers { }; } + public override RouteValueDictionary GetCreateRouteValues(Page page) { + return new RouteValueDictionary { + {"Area", "Orchard.Pages"}, + {"Controller", "Admin"}, + {"Action", "Create"}, + }; + } + protected override DriverResult Display(Page page, string displayType) { return Combined( ContentItemTemplate("Items/Pages.Page").LongestMatch(displayType, "Summary", "SummaryAdmin"), diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs b/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs index 594109423..31cee37f2 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Controllers/SetupController.cs @@ -1,24 +1,9 @@ using System; -using System.Linq; using System.Web.Mvc; -using Orchard.Comments.Models; -using Orchard.ContentManagement; -using Orchard.Core.Common.Models; -using Orchard.Core.Navigation.Models; -using Orchard.Core.Settings.Models; -using Orchard.Data; -using Orchard.Environment; -using Orchard.Environment.Extensions; -using Orchard.Environment.ShellBuilders; -using Orchard.Environment.Descriptor; -using Orchard.Environment.Descriptor.Models; using Orchard.FileSystems.AppData; -using Orchard.Security; -using Orchard.Settings; using Orchard.Setup.Services; using Orchard.Setup.ViewModels; using Orchard.Localization; -using Orchard.Themes; using Orchard.UI.Notify; namespace Orchard.Setup.Controllers { diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs b/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs index e843ebf1c..34600b4f8 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs +++ b/src/Orchard.Web/Modules/Orchard.Setup/Services/SetupService.cs @@ -4,7 +4,6 @@ using System.Web; using Orchard.Comments.Models; using Orchard.ContentManagement; using Orchard.ContentManagement.MetaData; -using Orchard.ContentManagement.MetaData.Builders; using Orchard.Core.Common.Models; using Orchard.Core.Navigation.Models; using Orchard.Core.Settings.Models; @@ -15,7 +14,6 @@ using Orchard.Environment.ShellBuilders; using Orchard.Environment.Descriptor; using Orchard.Environment.Descriptor.Models; using Orchard.Localization; -using Orchard.ContentManagement.MetaData.Services; using Orchard.Localization.Services; using Orchard.Security; using Orchard.Settings; @@ -149,9 +147,9 @@ namespace Orchard.Setup.Services { //hackInstallationGenerator.GenerateInstallEvents(); var contentDefinitionManager = environment.Resolve(); - contentDefinitionManager.AlterTypeDefinition("blogpost", cfg => cfg.WithPart("HasComments").WithPart("HasTags").WithPart("Localized")); - contentDefinitionManager.AlterTypeDefinition("page", cfg => cfg.WithPart("HasComments").WithPart("HasTags").WithPart("Localized")); - contentDefinitionManager.AlterTypeDefinition("sandboxpage", cfg => cfg.WithPart("HasComments").WithPart("HasTags").WithPart("Localized")); + contentDefinitionManager.AlterTypeDefinition("blogpost", cfg => cfg.Named("blogpost", "Blog Post").WithPart("HasComments").WithPart("HasTags").WithPart("Localized")); + contentDefinitionManager.AlterTypeDefinition("page", cfg => cfg.Named("page", "Page").WithPart("HasComments").WithPart("HasTags").WithPart("Localized")); + contentDefinitionManager.AlterTypeDefinition("sandboxpage", cfg => cfg.Named("sandboxpage", "Sandbox Page").WithPart("HasComments").WithPart("HasTags").WithPart("Localized")); // create home page as a CMS page var page = contentManager.Create("page", VersionOptions.Draft); diff --git a/src/Orchard.Web/Themes/TheAdmin/Styles/site.css b/src/Orchard.Web/Themes/TheAdmin/Styles/site.css index 58829e83f..e96330722 100644 --- a/src/Orchard.Web/Themes/TheAdmin/Styles/site.css +++ b/src/Orchard.Web/Themes/TheAdmin/Styles/site.css @@ -638,9 +638,6 @@ table .button { overflow:hidden; padding:0 1.4em .8em; } -.contentItems li.last { - border-bottom:0; -} #main .contentItems li .actions { color:#EAE9D9; height:auto; diff --git a/src/Orchard/ContentManagement/ContentItemMetadata.cs b/src/Orchard/ContentManagement/ContentItemMetadata.cs index c35225e2f..a3ce46e26 100644 --- a/src/Orchard/ContentManagement/ContentItemMetadata.cs +++ b/src/Orchard/ContentManagement/ContentItemMetadata.cs @@ -3,11 +3,45 @@ using System.Web.Routing; namespace Orchard.ContentManagement { public class ContentItemMetadata { + public ContentItemMetadata(IContent item) { + DisplayRouteValues = GetDisplayRouteValues(item); + EditorRouteValues = GetEditorRouteValues(item); + CreateRouteValues = GetCreateRouteValues(item); + } + public string DisplayText { get; set; } public RouteValueDictionary DisplayRouteValues { get; set; } public RouteValueDictionary EditorRouteValues { get; set; } + public RouteValueDictionary CreateRouteValues { get; set; } public IEnumerable DisplayGroups { get; set; } public IEnumerable EditorGroups { get; set; } + + private static RouteValueDictionary GetDisplayRouteValues(IContent item) { + return new RouteValueDictionary { + {"Area", "Contents"}, + {"Controller", "Item"}, + {"Action", "Display"}, + {"id", item.ContentItem.Id} + }; + } + + private static RouteValueDictionary GetEditorRouteValues(IContent item) { + return new RouteValueDictionary { + {"Area", "Contents"}, + {"Controller", "Admin"}, + {"Action", "Edit"}, + {"id", item.ContentItem.Id} + }; + } + + private static RouteValueDictionary GetCreateRouteValues(IContent item) { + return new RouteValueDictionary { + {"Area", "Contents"}, + {"Controller", "Admin"}, + {"Action", "Create"}, + {"id", item.ContentItem.ContentType} + }; + } } } \ No newline at end of file diff --git a/src/Orchard/ContentManagement/DefaultContentManager.cs b/src/Orchard/ContentManagement/DefaultContentManager.cs index 56f26e543..8c518bf06 100644 --- a/src/Orchard/ContentManagement/DefaultContentManager.cs +++ b/src/Orchard/ContentManagement/DefaultContentManager.cs @@ -375,7 +375,7 @@ namespace Orchard.ContentManagement { public ContentItemMetadata GetItemMetadata(IContent content) { var context = new GetContentItemMetadataContext { ContentItem = content.ContentItem, - Metadata = new ContentItemMetadata() + Metadata = new ContentItemMetadata(content) }; foreach (var handler in Handlers) { handler.GetContentItemMetadata(context); diff --git a/src/Orchard/ContentManagement/Drivers/ContentItemDriver.cs b/src/Orchard/ContentManagement/Drivers/ContentItemDriver.cs index d1f71ddb0..78eadf1b9 100644 --- a/src/Orchard/ContentManagement/Drivers/ContentItemDriver.cs +++ b/src/Orchard/ContentManagement/Drivers/ContentItemDriver.cs @@ -27,6 +27,7 @@ namespace Orchard.ContentManagement.Drivers { context.Metadata.DisplayText = GetDisplayText(item) ?? context.Metadata.DisplayText; context.Metadata.DisplayRouteValues = GetDisplayRouteValues(item) ?? context.Metadata.DisplayRouteValues; context.Metadata.EditorRouteValues = GetEditorRouteValues(item) ?? context.Metadata.EditorRouteValues; + context.Metadata.CreateRouteValues = GetCreateRouteValues(item) ?? context.Metadata.CreateRouteValues; } } @@ -67,6 +68,7 @@ namespace Orchard.ContentManagement.Drivers { protected virtual string GetDisplayText(TContent item) { return null; } public virtual RouteValueDictionary GetDisplayRouteValues(TContent item) { return null; } public virtual RouteValueDictionary GetEditorRouteValues(TContent item) { return null; } + public virtual RouteValueDictionary GetCreateRouteValues(TContent item) { return null; } protected virtual DriverResult Display(ContentItemViewModel viewModel, string displayType) { return GetDefaultItemTemplate(); } protected virtual DriverResult Editor(ContentItemViewModel viewModel) { return GetDefaultItemTemplate(); } diff --git a/src/Orchard/ContentManagement/MetaData/Builders/ContentTypeDefinitionBuilder.cs b/src/Orchard/ContentManagement/MetaData/Builders/ContentTypeDefinitionBuilder.cs index b2d997079..0e6e92e07 100644 --- a/src/Orchard/ContentManagement/MetaData/Builders/ContentTypeDefinitionBuilder.cs +++ b/src/Orchard/ContentManagement/MetaData/Builders/ContentTypeDefinitionBuilder.cs @@ -6,6 +6,7 @@ using Orchard.ContentManagement.MetaData.Models; namespace Orchard.ContentManagement.MetaData.Builders { public class ContentTypeDefinitionBuilder { private string _name; + private string _displayName; private readonly IList _parts; private readonly IDictionary _settings; @@ -20,6 +21,7 @@ namespace Orchard.ContentManagement.MetaData.Builders { } else { _name = existing.Name; + _displayName = existing.DisplayName; _parts = existing.Parts.ToList(); _settings = existing.Settings.ToDictionary(kv => kv.Key, kv => kv.Value); } @@ -30,11 +32,12 @@ namespace Orchard.ContentManagement.MetaData.Builders { } public ContentTypeDefinition Build() { - return new ContentTypeDefinition(_name, _parts, _settings); + return new ContentTypeDefinition(_name, _displayName, _parts, _settings); } - public ContentTypeDefinitionBuilder Named(string name) { + public ContentTypeDefinitionBuilder Named(string name, string displayName = null) { _name = name; + _displayName = displayName ?? name; return this; } diff --git a/src/Orchard/ContentManagement/MetaData/Models/ContentTypeDefinition.cs b/src/Orchard/ContentManagement/MetaData/Models/ContentTypeDefinition.cs index ae9d2a114..247296a83 100644 --- a/src/Orchard/ContentManagement/MetaData/Models/ContentTypeDefinition.cs +++ b/src/Orchard/ContentManagement/MetaData/Models/ContentTypeDefinition.cs @@ -3,8 +3,9 @@ using System.Linq; namespace Orchard.ContentManagement.MetaData.Models { public class ContentTypeDefinition { - public ContentTypeDefinition(string name, IEnumerable parts, IDictionary settings) { + public ContentTypeDefinition(string name, string displayName, IEnumerable parts, IDictionary settings) { Name = name; + DisplayName = displayName; Parts = parts; Settings = settings; } @@ -16,6 +17,7 @@ namespace Orchard.ContentManagement.MetaData.Models { } public string Name { get; private set; } + public string DisplayName { get; set; } public IEnumerable Parts { get; private set; } public IDictionary Settings { get; private set; }