Starting to get a UI around content type management

- added a DisplayName to the ContentTypeDefinition
- added a CreateRouteValues rvd to go along with the existing display and edit
- set default display, edit and create route values for ContentItemMetadata (* should get fallback route values in a different manner. probably not good to refer to an area, even by string, in core from the fwk)
- starting to shape up the content type list into a more consistent UI
- added create type action, view, etc. for creating new content types
 - supporting service has a few default parts hard-coded for now

--HG--
branch : dev
This commit is contained in:
Nathan Heskew
2010-06-16 04:22:51 -07:00
parent ec0e452c3a
commit 6e756f54ff
32 changed files with 350 additions and 88 deletions

View File

@@ -167,7 +167,7 @@ namespace Orchard.Core.Tests.Feeds.Controllers {
var mockContentManager = new Mock<IContentManager>();
mockContentManager.Setup(x => x.GetItemMetadata(It.IsAny<IContent>()))
.Returns(new ContentItemMetadata { DisplayText = "foo" });
.Returns(new ContentItemMetadata(hello) { DisplayText = "foo" });
var builder = new ContainerBuilder();
//builder.RegisterModule(new ImplicitCollectionSupportModule());

View File

@@ -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" }));
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" })));
}
}
}

View File

@@ -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; }
}
}

View File

@@ -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) {

View File

@@ -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"},

View File

@@ -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<Permission> GetPermissions() {
return new Permission[] {
CreateContentType,
};
}
public IEnumerable<PermissionStereotype> GetDefaultStereotypes() {
return new[] {
new PermissionStereotype {
Name = "Administrator",
Permissions = new[] {CreateContentType}
}
};
}
}
}

View File

@@ -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<ContentTypeDefinition> 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);
}
}
}

View File

@@ -0,0 +1,11 @@
using System.Collections.Generic;
using Orchard.ContentManagement.MetaData.Models;
namespace Orchard.Core.Contents.Services {
public interface IContentDefinitionService : IDependency {
IEnumerable<ContentTypeDefinition> GetTypeDefinitions();
ContentTypeDefinition GetTypeDefinition(string name);
void AddTypeDefinition(ContentTypeDefinitionStub contentTypeDefinition);
void RemoveTypeDefinition(string name);
}
}

View File

@@ -0,0 +1,7 @@
using Orchard.Mvc.ViewModels;
namespace Orchard.Core.Contents.ViewModels {
public class CreateTypeViewModel : BaseViewModel {
public string DisplayName { get; set; }
}
}

View File

@@ -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<ContentTypeDefinition> Types { get; set; }
}
}

View File

@@ -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<Entry> Entries { get; set; }

View File

@@ -1,5 +1,4 @@
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<ContentTypeListViewModel>" %>
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<ListContentTypesViewModel>" %>
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %>
<% Html.AddTitleParts(T("Create Content").ToString()); %>
<p>

View File

@@ -0,0 +1,13 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<CreateTypeViewModel>" %>
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %>
<h1><%:Html.TitleForPage(T("New Content Type").ToString())%></h1><%
using (Html.BeginFormAntiForgeryPost()) { %>
<%:Html.ValidationSummary() %>
<fieldset>
<label for="DisplayName"><%:T("Display Name") %></label>
<%:Html.TextBoxFor(m => m.DisplayName, new {@class = "textMedium", autofocus = "autofocus"}) %>
</fieldset>
<fieldset>
<button class="primaryAction" type="submit"><%:T("Create") %></button>
</fieldset><%
} %>

View File

@@ -1,5 +1,4 @@
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<ListContentViewModel>" %>
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<ListContentsViewModel>" %>
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %>
<% Html.AddTitleParts(T("Browse Contents").ToString()); %>
<p>

View File

@@ -0,0 +1,9 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<ListContentTypesViewModel>" %>
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %>
<h1><%:Html.TitleForPage(T("Content Types").ToString())%></h1>
<div class="manage"><%: Html.ActionLink(T("Create new type").ToString(), "CreateType", null, new { @class = "button primaryAction" })%></div>
<%=Html.UnorderedList(
Model.Types,
(t,i) => Html.DisplayFor(m => t).ToHtmlString(),
"contentItems"
) %>

View File

@@ -1,24 +0,0 @@
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<ContentTypeListViewModel>" %>
<%@ Import Namespace="Orchard.Core.Contents.ViewModels" %>
<% Html.AddTitleParts(T("Create Content").ToString()); %>
<p>
Create content</p>
<table>
<% foreach (var t in Model.Types) {%>
<tr>
<td>
<%:t.Name %>
</td>
<td>
<%:Html.ActionLink(T("List Items").ToString(), "List", "Admin", new RouteValueDictionary{{"Area","Contents"},{"Id",t.Name}}, new Dictionary<string, object>()) %>
</td>
<td>
<%:Html.ActionLink(T("Create Item").ToString(), "Create", "Admin", new RouteValueDictionary{{"Area","Contents"},{"Id",t.Name}}, new Dictionary<string, object>()) %>
</td>
<td>
<%:Html.ActionLink(T("Edit Type").ToString(), "ContentTypeList", "Admin", new RouteValueDictionary{{"Area","Orchard.MetaData"},{"Id",t.Name}}, new Dictionary<string, object>()) %>
</td>
</tr>
<%} %>
</table>

View File

@@ -0,0 +1,14 @@
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<Orchard.ContentManagement.MetaData.Models.ContentTypeDefinition>" %>
<div class="summary">
<div class="properties">
<h3><%:Model.DisplayName%></h3>
<p><%:Model.Name %> - <%:Html.ActionLink("[new content]", "Create", new {area = "Contents", id = Model.Name}) %></p>
</div>
<div class="related">
<%:Html.ActionLink(T("List Items").ToString(), "List", new {area = "Contents", id = Model.Name})%><%:T(" | ")%>
<%:Html.ActionLink(T("[Edit]").ToString(), "EditType", new {area = "Contents", id = Model.Name})%><%:T(" | ") %>
<% using (Html.BeginFormAntiForgeryPost(Url.Action("RemoveType", new {area = "Contents", id = Model.Name}), FormMethod.Post, new { @class = "inline link" })) { %>
<button type="submit" class="linkButton" title="<%:T("Delete") %>"><%:T("[Delete]")%></button><%
} %>
</div>
</div>

View File

@@ -76,8 +76,15 @@
<Compile Include="Common\ViewModels\ContainerEditorViewModel.cs" />
<Compile Include="Common\ViewModels\TextContentFieldDisplayViewModel.cs" />
<Compile Include="Common\ViewModels\TextContentFieldEditorViewModel.cs" />
<Compile Include="Contents\ContentTypeDefinitionStub.cs" />
<Compile Include="Contents\Controllers\ItemController.cs" />
<Compile Include="Contents\Handlers\ContentsModuleHandler.cs" />
<Compile Include="Contents\Permissions.cs" />
<Compile Include="Contents\Services\ContentDefinitionService.cs" />
<Compile Include="Contents\Services\IContentDefinitionService.cs" />
<Compile Include="Contents\ViewModels\CreateTypeViewModel.cs" />
<Compile Include="Contents\ViewModels\ListContentsViewModel.cs" />
<Compile Include="Contents\ViewModels\ListContentTypesViewModel.cs" />
<Compile Include="Localization\Drivers\LocalizedDriver.cs" />
<Compile Include="Routable\Controllers\ItemController.cs" />
<Compile Include="Routable\Drivers\RoutableDriver.cs" />
@@ -105,9 +112,7 @@
<Compile Include="Contents\AdminMenu.cs" />
<Compile Include="Contents\Controllers\AdminController.cs" />
<Compile Include="Contents\ViewModels\CreateItemViewModel.cs" />
<Compile Include="Contents\ViewModels\ContentTypeListViewModel.cs" />
<Compile Include="Contents\ViewModels\EditItemViewModel.cs" />
<Compile Include="Contents\ViewModels\ListContentViewModel.cs" />
<Compile Include="Dashboard\AdminMenu.cs" />
<Compile Include="Dashboard\Controllers\AdminController.cs" />
<Compile Include="Dashboard\Routes.cs" />
@@ -216,11 +221,13 @@
<Content Include="Common\Views\EditorTemplates\Parts\Common.Container.ascx" />
<Content Include="Common\Views\EditorTemplates\Parts\Common.TextContentField.ascx" />
<Content Include="Contents\Module.txt" />
<Content Include="Contents\Views\Admin\Types.aspx" />
<Content Include="Contents\Views\Admin\CreateType.ascx" />
<Content Include="Contents\Views\Admin\Types.ascx" />
<Content Include="Contents\Views\Admin\List.aspx" />
<Content Include="Contents\Views\Admin\Edit.aspx" />
<Content Include="Contents\Views\Admin\CreatableTypeList.aspx" />
<Content Include="Contents\Views\Admin\Create.aspx" />
<Content Include="Contents\Views\DisplayTemplates\ContentTypeDefinition.ascx" />
<Content Include="Contents\Views\DisplayTemplates\Items\Contents.Item.ascx" />
<Content Include="Contents\Views\EditorTemplates\Items\Contents.Item.ascx" />
<Content Include="Contents\Views\Item\Preview.aspx" />

View File

@@ -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)));
}

View File

@@ -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; }

View File

@@ -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"),

View File

@@ -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))
);
}

View File

@@ -25,7 +25,7 @@
%>
<tr class="<%=contentTypeClass %>">
<td>
<%= Html.ActionLink(item.Name, "ContentTypeList", new {id=item.Name})%>
<%= Html.ActionLink(string.IsNullOrWhiteSpace(item.Name) ? "unkwn" : item.Name, "ContentTypeList", new {id=item.Name})%>
</td>
</tr>

View File

@@ -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"),

View File

@@ -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 {

View File

@@ -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<IContentDefinitionManager>();
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);

View File

@@ -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;

View File

@@ -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<string> DisplayGroups { get; set; }
public IEnumerable<string> 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}
};
}
}
}

View File

@@ -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);

View File

@@ -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<TContent> viewModel, string displayType) { return GetDefaultItemTemplate(); }
protected virtual DriverResult Editor(ContentItemViewModel<TContent> viewModel) { return GetDefaultItemTemplate(); }

View File

@@ -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<ContentTypeDefinition.Part> _parts;
private readonly IDictionary<string, string> _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;
}

View File

@@ -3,8 +3,9 @@ using System.Linq;
namespace Orchard.ContentManagement.MetaData.Models {
public class ContentTypeDefinition {
public ContentTypeDefinition(string name, IEnumerable<Part> parts, IDictionary<string, string> settings) {
public ContentTypeDefinition(string name, string displayName, IEnumerable<Part> parts, IDictionary<string, string> 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<Part> Parts { get; private set; }
public IDictionary<string, string> Settings { get; private set; }