Implements the ability to have customized and configurable list views for specific content types

This commit is contained in:
Shannon
2014-09-22 18:18:09 +10:00
parent d4be8036f0
commit d87a426294
20 changed files with 253 additions and 232 deletions

View File

@@ -4,10 +4,13 @@ using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Web.Http;
using AutoMapper;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Mvc;
using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.Editors
{
@@ -20,7 +23,7 @@ namespace Umbraco.Web.Editors
/// <summary>
/// Constructor
/// </summary>
public ContentTypeControllerBase()
protected ContentTypeControllerBase()
: this(UmbracoContext.Current)
{
}
@@ -29,91 +32,42 @@ namespace Umbraco.Web.Editors
/// Constructor
/// </summary>
/// <param name="umbracoContext"></param>
public ContentTypeControllerBase(UmbracoContext umbracoContext)
protected ContentTypeControllerBase(UmbracoContext umbracoContext)
: base(umbracoContext)
{
}
/// <summary>
/// Returns the container configuration JSON structure for the content item id passed in
/// </summary>
/// <param name="contentId"></param>
public ContentTypeContainerConfiguration GetContainerConfig(int contentId)
public DataTypeBasic GetAssignedListViewDataType(int contentTypeId)
{
//var contentItem = Services.ContentService.GetById(contentId);
//if (contentItem == null)
//{
// throw new HttpResponseException(HttpStatusCode.NotFound);
//}
var objectType = Services.EntityService.GetObjectType(contentTypeId);
//if (!string.IsNullOrEmpty(contentItem.ContentType.ContainerConfig))
//{
// var containerConfig = JsonConvert.DeserializeObject<ContentTypeContainerConfiguration>(contentItem.ContentType.ContainerConfig);
// containerConfig.AdditionalColumns = new List<ContentTypeContainerConfiguration.AdditionalColumnDetail>();
// // Populate the column headings and localization keys
// if (!string.IsNullOrEmpty(containerConfig.AdditionalColumnAliases))
// {
// // Find all the properties for doc types that might be in the list
// var allowedContentTypeIds = contentItem.ContentType.AllowedContentTypes
// .Select(x => x.Id.Value)
// .ToArray();
// var allPropertiesOfAllowedContentTypes = Services.ContentTypeService
// .GetAllContentTypes(allowedContentTypeIds)
// .SelectMany(x => x.PropertyTypes)
// .ToList();
// foreach (var alias in containerConfig.AdditionalColumnAliases.Split(','))
// {
// var column = new ContentTypeContainerConfiguration.AdditionalColumnDetail
// {
// Alias = alias,
// LocalizationKey = string.Empty,
// AllowSorting = true,
// };
// // Try to find heading from custom property (getting the name from the alias)
// // - need to look in children of the current content's content type
// var property = allPropertiesOfAllowedContentTypes
// .FirstOrDefault(x => x.Alias == alias.ToFirstLower());
// if (property != null)
// {
// column.Header = property.Name;
// column.AllowSorting = false; // can't sort on custom property columns
// }
// else if (alias == "UpdateDate")
// {
// // Special case to restore hard-coded column titles
// column.Header = "Last edited";
// column.LocalizationKey = "defaultdialogs_lastEdited";
// }
// else if (alias == "Updater")
// {
// // Special case to restore hard-coded column titles (2)
// column.Header = "Updated by";
// column.LocalizationKey = "content_updatedBy";
// }
// else if (alias == "Owner")
// {
// // Special case to restore hard-coded column titles (3)
// column.Header = "Created by";
// column.LocalizationKey = "content_createBy";
// }
// else
// {
// // For others just sentence case the alias and camel case for the key
// column.Header = alias.ToFirstUpper().SplitPascalCasing();
// column.LocalizationKey = "content_" + alias.ToFirstLower();
// }
// containerConfig.AdditionalColumns.Add(column);
// }
// }
// return containerConfig;
//}
return null;
switch (objectType)
{
case UmbracoObjectTypes.MemberType:
var memberType = Services.MemberTypeService.Get(contentTypeId);
var dtMember = Services.DataTypeService.GetDataTypeDefinitionByName(Constants.Conventions.DataTypes.ListViewPrefix + memberType.Alias);
return dtMember == null
? Mapper.Map<IDataTypeDefinition, DataTypeBasic>(
Services.DataTypeService.GetDataTypeDefinitionByName(Constants.Conventions.DataTypes.ListViewPrefix + "Member"))
: Mapper.Map<IDataTypeDefinition, DataTypeBasic>(dtMember);
case UmbracoObjectTypes.MediaType:
var mediaType = Services.ContentTypeService.GetMediaType(contentTypeId);
var dtMedia = Services.DataTypeService.GetDataTypeDefinitionByName(Constants.Conventions.DataTypes.ListViewPrefix + mediaType.Alias);
return dtMedia == null
? Mapper.Map<IDataTypeDefinition, DataTypeBasic>(
Services.DataTypeService.GetDataTypeDefinitionByName(Constants.Conventions.DataTypes.ListViewPrefix + "Media"))
: Mapper.Map<IDataTypeDefinition, DataTypeBasic>(dtMedia);
case UmbracoObjectTypes.DocumentType:
var docType = Services.ContentTypeService.GetContentType(contentTypeId);
var dtDoc = Services.DataTypeService.GetDataTypeDefinitionByName(Constants.Conventions.DataTypes.ListViewPrefix + docType.Alias);
return dtDoc == null
? Mapper.Map<IDataTypeDefinition, DataTypeBasic>(
Services.DataTypeService.GetDataTypeDefinitionByName(Constants.Conventions.DataTypes.ListViewPrefix + "Content"))
: Mapper.Map<IDataTypeDefinition, DataTypeBasic>(dtDoc);
default:
throw new ArgumentOutOfRangeException();
}
}
}
}

View File

@@ -33,6 +33,12 @@ namespace Umbraco.Web.Editors
[UmbracoTreeAuthorize(Constants.Trees.DataTypes)]
public class DataTypeController : UmbracoAuthorizedJsonController
{
public DataTypeDisplay GetByName(string name)
{
var dataType = Services.DataTypeService.GetDataTypeDefinitionByName(name);
return dataType == null ? null : Mapper.Map<IDataTypeDefinition, DataTypeDisplay>(dataType);
}
/// <summary>
/// Gets the content json for the content id
/// </summary>

View File

@@ -1,78 +0,0 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
namespace Umbraco.Web.Models.ContentEditing
{
/// <summary>
/// A model representing the configuration for a content type defined as a list container
/// </summary>
[DataContract(Name = "config", Namespace = "")]
public class ContentTypeContainerConfiguration
{
/// <summary>
/// The page size for the list
/// </summary>
[DataMember(Name = "pageSize")]
public int PageSize { get; set; }
/// <summary>
/// The aliases additional columns displayed after the node name in the list
/// </summary>
[DataMember(Name = "additionalColumnAliases")]
public string AdditionalColumnAliases { get; set; }
/// <summary>
/// The default order by column for the list
/// </summary>
[DataMember(Name = "orderBy")]
public string OrderBy { get; set; }
/// <summary>
/// The default order direction for the list
/// </summary>
[DataMember(Name = "orderDirection")]
public string OrderDirection { get; set; }
/// <summary>
/// Flag for whether bulk publishing is allowed
/// </summary>
[DataMember(Name = "allowBulkPublish")]
public bool AllowBulkPublish { get; set; }
/// <summary>
/// Flag for whether bulk unpublishing is allowed
/// </summary>
[DataMember(Name = "allowBulkUnpublish")]
public bool AllowBulkUnpublish { get; set; }
/// <summary>
/// Flag for whether bulk deletion is allowed
/// </summary>
[DataMember(Name = "allowBulkDelete")]
public bool AllowBulkDelete { get; set; }
/// <summary>
/// The column details for the additional columns displayed after the node name in the list
/// </summary>
/// <remarks>This isn't persisted, but is calculated from the aliases when passed to the UI</remarks>
[DataMember(Name = "additionalColumns")]
public IList<AdditionalColumnDetail> AdditionalColumns { get; set; }
[DataContract(Namespace = "")]
public class AdditionalColumnDetail
{
[DataMember(Name = "alias")]
public string Alias { get; set; }
[DataMember(Name = "header")]
public string Header { get; set; }
[DataMember(Name = "localizationKey")]
public string LocalizationKey { get; set; }
[DataMember(Name = "allowSorting")]
public bool AllowSorting { get; set; }
}
}
}

View File

@@ -0,0 +1,19 @@
using System.ComponentModel;
using System.Runtime.Serialization;
namespace Umbraco.Web.Models.ContentEditing
{
/// <summary>
/// The basic data type information
/// </summary>
[DataContract(Name = "dataType", Namespace = "")]
public class DataTypeBasic : EntityBasic
{
/// <summary>
/// Whether or not this is a system data type, in which case it cannot be deleted
/// </summary>
[DataMember(Name = "isSystem")]
[ReadOnly(true)]
public bool IsSystemDataType { get; set; }
}
}

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
@@ -10,7 +9,7 @@ namespace Umbraco.Web.Models.ContentEditing
/// Represents a data type that is being edited
/// </summary>
[DataContract(Name = "dataType", Namespace = "")]
public class DataTypeDisplay : EntityBasic, INotificationModel
public class DataTypeDisplay : DataTypeBasic, INotificationModel
{
public DataTypeDisplay()
{
@@ -35,12 +34,6 @@ namespace Umbraco.Web.Models.ContentEditing
/// </summary>
[DataMember(Name = "notifications")]
public List<Notification> Notifications { get; private set; }
/// <summary>
/// Whether or not this is a system data type, in which case it cannot be deleted
/// </summary>
[DataMember(Name = "isSystem")]
[ReadOnly(true)]
public bool IsSystemDataType { get; set; }
}
}

View File

@@ -34,6 +34,11 @@ namespace Umbraco.Web.Models.Mapping
Constants.System.DefaultMembersListViewDataTypeId
};
config.CreateMap<IDataTypeDefinition, DataTypeBasic>()
.ForMember(x => x.Icon, expression => expression.Ignore())
.ForMember(x => x.Alias, expression => expression.Ignore())
.ForMember(x => x.IsSystemDataType, expression => expression.MapFrom(definition => systemIds.Contains(definition.Id)));
config.CreateMap<IDataTypeDefinition, DataTypeDisplay>()
.ForMember(display => display.AvailableEditors, expression => expression.ResolveUsing<AvailablePropertyEditorsResolver>())
.ForMember(display => display.PreValues, expression => expression.ResolveUsing(

View File

@@ -118,14 +118,17 @@ namespace Umbraco.Web.Models.Mapping
/// <typeparam name="TPersisted"></typeparam>
/// <param name="display"></param>
/// <param name="entityType">This must be either 'content' or 'media'</param>
/// <param name="dataTypeService"></param>
internal static void AddListView<TPersisted>(TabbedContentItem<ContentPropertyDisplay, TPersisted> display, string entityType, IDataTypeService dataTypeService)
where TPersisted : IContentBase
{
int dtdId;
var customDtdName = Constants.Conventions.DataTypes.ListViewPrefix + display.ContentTypeAlias;
switch (entityType)
{
case "content":
dtdId = Constants.System.DefaultContentListViewDataTypeId;
break;
case "media":
dtdId = Constants.System.DefaultMediaListViewDataTypeId;
@@ -137,8 +140,11 @@ namespace Umbraco.Web.Models.Mapping
throw new ArgumentOutOfRangeException("entityType does not match a required value");
}
var dt = dataTypeService.GetDataTypeDefinitionById(dtdId);
var preVals = dataTypeService.GetPreValuesCollectionByDataTypeId(dtdId);
//first try to get the custom one if there is one
var dt = dataTypeService.GetDataTypeDefinitionByName(customDtdName)
?? dataTypeService.GetDataTypeDefinitionById(dtdId);
var preVals = dataTypeService.GetPreValuesCollectionByDataTypeId(dt.Id);
var editor = PropertyEditorResolver.Current.GetByAlias(dt.PropertyEditorAlias);
if (editor == null)

View File

@@ -306,6 +306,7 @@
<Compile Include="Editors\TemplateController.cs" />
<Compile Include="Editors\TuningController.cs" />
<Compile Include="GridTemplateExtensions.cs" />
<Compile Include="Models\ContentEditing\DataTypeBasic.cs" />
<Compile Include="Models\ContentEditing\MemberBasic.cs" />
<Compile Include="Models\ContentEditing\MemberListDisplay.cs" />
<Compile Include="Models\TemplateQuery\ContentTypeModel.cs" />
@@ -320,7 +321,6 @@
<Compile Include="Models\TemplateQuery\QueryResultModel.cs" />
<Compile Include="Editors\TemplateQueryController.cs" />
<Compile Include="Models\ContentEditing\ContentBaseItemSave.cs" />
<Compile Include="Models\ContentEditing\ContentTypeContainerConfiguration.cs" />
<Compile Include="Models\ContentEditing\MediaItemSave.cs" />
<Compile Include="Models\ContentEditing\TemplateDisplay.cs" />
<Compile Include="Models\DetachedContent.cs" />

View File

@@ -49,6 +49,15 @@ namespace umbraco.controls
public bool HideStructure { get; set; }
public Func<DocumentType, DocumentType> DocumentTypeCallback { get; set; }
protected string ContentTypeAlias
{
get { return _contentType.Alias; }
}
protected int ContentTypeId
{
get { return _contentType.Id; }
}
// "Tab" tab
protected uicontrols.Pane Pane8;