Convert level into group type and ensure names are unique again

This commit is contained in:
Ronald Barendse
2021-06-22 11:45:23 +02:00
parent 0e63edb375
commit 17d2c4cab9
24 changed files with 172 additions and 80 deletions

View File

@@ -15,7 +15,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_15_0
// Add new columns
AddColumnIfNotExists<PropertyTypeGroupDto>(columns, "parentKey");
AddColumnIfNotExists<PropertyTypeGroupDto>(columns, "level");
AddColumnIfNotExists<PropertyTypeGroupDto>(columns, "type");
AddColumnIfNotExists<PropertyTypeGroupDto>(columns, "icon");
// Create self-referencing foreign key

View File

@@ -339,21 +339,19 @@ namespace Umbraco.Core.Models
/// "generic properties" ie does not have a tab anymore.</remarks>
public bool MovePropertyType(string propertyTypeAlias, string propertyGroupName)
{
// note: not dealing with alias casing at all here?
// get property, ensure it exists
var propertyType = PropertyTypes.FirstOrDefault(x => x.Alias == propertyTypeAlias);
var propertyType = PropertyTypes.FirstOrDefault(x => x.Alias.InvariantEquals(propertyTypeAlias));
if (propertyType == null) return false;
// get new group, if required, and ensure it exists
var newPropertyGroup = propertyGroupName == null
? null
: PropertyGroups.FirstOrDefault(x => x.Name.InvariantEquals(propertyGroupName) && x.ParentKey == null && x.Level == 1);
: PropertyGroups.FirstOrDefault(x => x.Name.InvariantEquals(propertyGroupName));
if (propertyGroupName != null && newPropertyGroup == null) return false;
// get old group
var oldPropertyGroup = PropertyGroups.FirstOrDefault(x =>
x.PropertyTypes.Any(y => y.Alias == propertyTypeAlias));
x.PropertyTypes.Any(y => y.Alias.InvariantEquals(propertyTypeAlias)));
// set new group
propertyType.PropertyGroupId = newPropertyGroup == null ? null : new Lazy<int>(() => newPropertyGroup.Id, false);
@@ -403,7 +401,7 @@ namespace Umbraco.Core.Models
public void RemovePropertyGroup(string propertyGroupName)
{
// if no group exists with that name, do nothing
var group = PropertyGroups.FirstOrDefault(x => x.Name.InvariantEquals(propertyGroupName) && x.ParentKey == null && x.Level == 1);
var group = PropertyGroups.FirstOrDefault(x => x.Name.InvariantEquals(propertyGroupName));
if (group == null) return;
// first remove the group

View File

@@ -218,7 +218,7 @@ namespace Umbraco.Core.Models
private PropertyGroup AddAndReturnPropertyGroup(string name)
{
// ensure we don't have it already
if (PropertyGroups.Any(x => x.Name.InvariantEquals(name) && x.ParentKey == null && x.Level == 1))
if (PropertyGroups.Any(x => x.Name.InvariantEquals(name)))
return null;
// create the new group
@@ -227,7 +227,7 @@ namespace Umbraco.Core.Models
// check if it is inherited - there might be more than 1 but we want the 1st, to
// reuse its sort order - if there are more than 1 and they have different sort
// orders... there isn't much we can do anyways
var inheritGroup = CompositionPropertyGroups.FirstOrDefault(x => x.Name.InvariantEquals(name) && x.ParentKey == null && x.Level == 1);
var inheritGroup = CompositionPropertyGroups.FirstOrDefault(x => x.Name.InvariantEquals(name));
if (inheritGroup == null)
{
// no, just local, set sort order
@@ -260,8 +260,8 @@ namespace Umbraco.Core.Models
return false;
// get and ensure a group local to this content type
var group = PropertyGroups.FirstOrDefault(x => x.Name.InvariantEquals(propertyGroupName) && x.ParentKey == null && x.Level == 1)
??AddAndReturnPropertyGroup(propertyGroupName);
var group = PropertyGroups.FirstOrDefault(x => x.Name.InvariantEquals(propertyGroupName))
?? AddAndReturnPropertyGroup(propertyGroupName);
if (group == null)
return false;

View File

@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using Umbraco.Core.Models.Entities;
@@ -15,7 +17,7 @@ namespace Umbraco.Core.Models
public class PropertyGroup : EntityBase, IEquatable<PropertyGroup>
{
private Guid? _parentKey;
private short _level;
private PropertyGroupType _type;
private string _name;
private string _icon;
private int _sortOrder;
@@ -28,7 +30,6 @@ namespace Umbraco.Core.Models
public PropertyGroup(PropertyTypeCollection propertyTypeCollection)
{
PropertyTypes = propertyTypeCollection;
Level = 1; // TODO We default to 1 (property group) for backwards compatibility, but should use zero/no default at some point.
}
private void PropertyTypesChanged(object sender, NotifyCollectionChangedEventArgs e)
@@ -50,10 +51,10 @@ namespace Umbraco.Core.Models
/// Gets or sets the Sort Order of the Group
/// </summary>
[DataMember]
public short Level
public PropertyGroupType Type
{
get => _level;
set => SetPropertyValueAndDetectChanges(value, ref _level, nameof(Level));
get => _type;
set => SetPropertyValueAndDetectChanges(value, ref _type, nameof(Type));
}
/// <summary>
@@ -116,9 +117,9 @@ namespace Umbraco.Core.Models
}
}
public bool Equals(PropertyGroup other) => other != null && base.Equals(other) && ParentKey == other.ParentKey && Level == other.Level && Icon == other.Icon && Name.InvariantEquals(other.Name);
public bool Equals(PropertyGroup other) => other != null && base.Equals(other) && ParentKey == other.ParentKey && Type == other.Type && Icon == other.Icon && Name.InvariantEquals(other.Name);
public override int GetHashCode() => (base.GetHashCode(), ParentKey, Level, Icon, Name.ToLowerInvariant()).GetHashCode();
public override int GetHashCode() => (base.GetHashCode(), ParentKey, Type, Icon, Name?.ToLowerInvariant()).GetHashCode();
protected override void PerformDeepClone(object clone)
{
@@ -134,4 +135,41 @@ namespace Umbraco.Core.Models
}
}
}
internal static class PropertyGroupExtensions
{
/// <summary>
/// Orders the property groups by hierarchy (so child groups are after their parent group) and removes circular references.
/// </summary>
/// <param name="propertyGroups">The property groups.</param>
/// <returns>
/// The ordered property groups.
/// </returns>
public static IEnumerable<PropertyGroup> OrderByHierarchy(this IEnumerable<PropertyGroup> propertyGroups)
{
var groups = propertyGroups.ToList();
var visitedParentKeys = new HashSet<Guid>(groups.Count);
IEnumerable<PropertyGroup> OrderByHierarchy(Guid? parentKey)
{
if (parentKey.HasValue && visitedParentKeys.Add(parentKey.Value) == false)
{
// We already visited this parent key, stop to prevent a circular reference
yield break;
}
foreach (var group in groups.Where(x => x.ParentKey == parentKey).OrderBy(x => x.Type).ThenBy(x => x.SortOrder))
{
yield return group;
foreach (var childGroup in OrderByHierarchy(group.Key))
{
yield return childGroup;
}
}
}
return OrderByHierarchy(null);
}
}
}

View File

@@ -77,32 +77,29 @@ namespace Umbraco.Core.Models
//Note this is done to ensure existing groups can be renamed
if (item.HasIdentity && item.Id > 0)
{
var exists = Contains(item.Id);
if (exists)
var index = IndexOfKey(item.Id);
if (index != -1)
{
var keyExists = Contains(item.Name);
if (keyExists)
throw new Exception($"Naming conflict: Changing the name of PropertyGroup '{item.Name}' would result in duplicates");
//collection events will be raised in SetItem
SetItem(IndexOfKey(item.Id), item);
SetItem(index, item);
return;
}
}
else
{
var key = GetKeyForItem(item);
if (key != null)
var index = IndexOfKey(item.Name);
if (index != -1)
{
var exists = Contains(key);
if (exists)
{
//collection events will be raised in SetItem
SetItem(IndexOfKey(key), item);
return;
}
//collection events will be raised in SetItem
SetItem(index, item);
return;
}
}
//collection events will be raised in InsertItem
base.Add(item);
}

View File

@@ -0,0 +1,19 @@
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents the type of a property group.
/// </summary>
public enum PropertyGroupType : short
{
/// <summary>
/// Display as a group (using a header).
/// </summary>
Group = 0,
/// <summary>
/// Display as an app (using a name and icon).
/// </summary>
App = 1,
//Tab = 2,
//Fieldset = 3
}
}

View File

@@ -28,9 +28,9 @@ namespace Umbraco.Core.Persistence.Dtos
[ForeignKey(typeof(PropertyTypeGroupDto), Column = "uniqueID", Name = "FK_" + TableName + "_parentKey")]
public Guid? ParentKey { get; set; }
[Column("level")]
[Constraint(Default = 1)] // TODO We default to 1 (property group) for backwards compatibility, but should use zero/no default at some point.
public short Level { get; set; } = 1;
[Column("type")]
[Constraint(Default = 0)]
public short Type { get; set; }
[Column("contenttypeNodeId")]
[ForeignKey(typeof(ContentTypeDto), Column = "nodeId")]

View File

@@ -36,7 +36,7 @@ namespace Umbraco.Core.Persistence.Factories
group.Key = groupDto.UniqueId;
group.ParentKey = groupDto.ParentKey;
group.Level = groupDto.Level;
group.Type = (PropertyGroupType)groupDto.Type;
group.Icon = groupDto.Icon;
group.Name = groupDto.Text;
group.SortOrder = groupDto.SortOrder;
@@ -109,7 +109,7 @@ namespace Umbraco.Core.Persistence.Factories
{
UniqueId = propertyGroup.Key,
ParentKey = propertyGroup.ParentKey,
Level = propertyGroup.Level,
Type = (short)propertyGroup.Type,
ContentTypeNodeId = contentTypeId,
Icon = propertyGroup.Icon,
Text = propertyGroup.Name,

View File

@@ -21,7 +21,7 @@ namespace Umbraco.Core.Persistence.Mappers
DefineMap<PropertyGroup, PropertyTypeGroupDto>(nameof(PropertyGroup.Id), nameof(PropertyTypeGroupDto.Id));
DefineMap<PropertyGroup, PropertyTypeGroupDto>(nameof(PropertyGroup.Key), nameof(PropertyTypeGroupDto.UniqueId));
DefineMap<PropertyGroup, PropertyTypeGroupDto>(nameof(PropertyGroup.ParentKey), nameof(PropertyTypeGroupDto.ParentKey));
DefineMap<PropertyGroup, PropertyTypeGroupDto>(nameof(PropertyGroup.Level), nameof(PropertyTypeGroupDto.Level));
DefineMap<PropertyGroup, PropertyTypeGroupDto>(nameof(PropertyGroup.Type), nameof(PropertyTypeGroupDto.Type));
DefineMap<PropertyGroup, PropertyTypeGroupDto>(nameof(PropertyGroup.Icon), nameof(PropertyTypeGroupDto.Icon));
DefineMap<PropertyGroup, PropertyTypeGroupDto>(nameof(PropertyGroup.Name), nameof(PropertyTypeGroupDto.Text));
DefineMap<PropertyGroup, PropertyTypeGroupDto>(nameof(PropertyGroup.SortOrder), nameof(PropertyTypeGroupDto.SortOrder));

View File

@@ -274,7 +274,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
Id = dto.Id,
Key = dto.UniqueId,
ParentKey = dto.ParentKey,
Level = dto.Level,
Type = (PropertyGroupType)dto.Type,
Icon = dto.Icon,
Name = dto.Text,
SortOrder = dto.SortOrder

View File

@@ -175,7 +175,7 @@ AND umbracoNode.nodeObjectType = @objectType",
}
//Insert Tabs
foreach (var propertyGroup in entity.PropertyGroups.OrderBy(x => x.Level).ToArray())
foreach (var propertyGroup in entity.PropertyGroups.OrderByHierarchy())
{
var tabDto = PropertyGroupFactory.BuildGroupDto(propertyGroup, nodeDto.NodeId);
var primaryKey = Convert.ToInt32(Database.Insert(tabDto));
@@ -374,7 +374,7 @@ AND umbracoNode.id <> @id",
}
// insert or update groups, assign properties
foreach (var propertyGroup in entity.PropertyGroups.OrderBy(x => x.Level).ToArray())
foreach (var propertyGroup in entity.PropertyGroups.OrderByHierarchy())
{
// insert or update group
var groupDto = PropertyGroupFactory.BuildGroupDto(propertyGroup, entity.Id);

View File

@@ -158,6 +158,7 @@
<Compile Include="Models\IconModel.cs" />
<Compile Include="Models\InstallLog.cs" />
<Compile Include="Models\MediaWithCrops.cs" />
<Compile Include="Models\PropertyGroupType.cs" />
<Compile Include="Models\PublishedContent\PublishedContentTypeExtensions.cs" />
<Compile Include="Models\RelationTypeExtensions.cs" />
<Compile Include="Persistence\Repositories\IInstallationRepository.cs" />

View File

@@ -23,12 +23,12 @@
if (newValue && newValue.length === 0) return;
scope.tabs = $filter("filter")(scope.model.groups, (group) => {
return group.level === 0;
return group.type === 1;
});
});
function getFirstTab () {
return scope.model.groups.find(group => group.level === 0);
return scope.model.groups.find(group => group.type === 1);
}
function activate() {
@@ -402,7 +402,7 @@
key: String.CreateGuid(),
name: "",
parentKey: null,
level: 0,
type: 1,
sortOrder,
icon: "icon-document color-black"
};
@@ -504,7 +504,7 @@
parentTabContentTypeNames: [],
name: "",
parentKey: tabKey || null,
level: 1,
type: 0,
sortOrder: lastGroupSortOrder
};

View File

@@ -64,7 +64,7 @@
var saveModel = _.pick(displayModel,
'compositeContentTypes', 'isContainer', 'allowAsRoot', 'allowedTemplates', 'allowedContentTypes',
'alias', 'description', 'thumbnail', 'name', 'id', 'icon', 'trashed',
'key', 'parentId', 'alias', 'path', 'allowCultureVariant', 'allowSegmentVariant', 'isElement', 'tabs');
'key', 'parentId', 'alias', 'path', 'allowCultureVariant', 'allowSegmentVariant', 'isElement');
// TODO: Map these
saveModel.allowedTemplates = _.map(displayModel.allowedTemplates, function (t) { return t.alias; });
@@ -75,7 +75,7 @@
});
saveModel.groups = _.map(realGroups, function (g) {
var saveGroup = _.pick(g, 'inherited', 'id', 'sortOrder', 'name', 'key', 'parentKey', 'level', 'icon');
var saveGroup = _.pick(g, 'inherited', 'id', 'sortOrder', 'name', 'key', 'parentKey', 'type', 'icon');
var realProperties = _.reject(g.properties, function (p) {
//do not include these properties

View File

@@ -204,7 +204,7 @@ namespace Umbraco.Web.Editors
Id = x.Id,
Key = x.Key,
ParentKey = x.ParentKey,
Level = x.Level,
Type = x.Type,
Icon = x.Icon,
Alias = x.Alias,
Label = x.Label,

View File

@@ -88,7 +88,7 @@ namespace Umbraco.Web.Models.ContentEditing
yield return validationResult;
}
var duplicateGroups = Groups.GroupBy(x => (x.Name?.ToUpperInvariant(), x.Level)).Where(x => x.Count() > 1).ToArray();
var duplicateGroups = Groups.GroupBy(x => x.Name?.ToUpperInvariant()).Where(x => x.Count() > 1).ToArray();
if (duplicateGroups.Any())
{
//we need to return the field name with an index so it's wired up correctly

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
using Umbraco.Core.Models;
namespace Umbraco.Web.Models.ContentEditing
{
@@ -39,8 +40,8 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "parentKey")]
public Guid? ParentKey { get; set; }
[DataMember(Name = "level")]
public short Level { get; set; }
[DataMember(Name = "type")]
public PropertyGroupType Type { get; set; }
[DataMember(Name = "icon")]
public string Icon { get; set; }

View File

@@ -1,5 +1,7 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;
namespace Umbraco.Web.Models.ContentEditing
@@ -36,4 +38,42 @@ namespace Umbraco.Web.Models.ContentEditing
[ReadOnly(true)]
public IEnumerable<string> ParentTabContentTypeNames { get; set; }
}
internal static class PropertyGroupDisplayExtensions
{
/// <summary>
/// Orders the property groups by hierarchy (so child groups are after their parent group) and removes circular references.
/// </summary>
/// <param name="propertyGroups">The property groups.</param>
/// <returns>
/// The ordered property groups.
/// </returns>
public static IEnumerable<PropertyGroupDisplay<T>> OrderByHierarchy<T>(this IEnumerable<PropertyGroupDisplay<T>> propertyGroups)
where T : PropertyTypeDisplay
{
var groups = propertyGroups.ToList();
var visitedParentKeys = new HashSet<Guid>(groups.Count);
IEnumerable<PropertyGroupDisplay<T>> OrderByHierarchy(Guid? parentKey)
{
if (parentKey.HasValue && visitedParentKeys.Add(parentKey.Value) == false)
{
// We already visited this parent key, stop to prevent a circular reference
yield break;
}
foreach (var group in groups.Where(x => x.ParentKey == parentKey).OrderBy(x => x.Type).ThenBy(x => x.SortOrder))
{
yield return group;
foreach (var childGroup in OrderByHierarchy(group.Key))
{
yield return childGroup;
}
}
}
return OrderByHierarchy(null);
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using Umbraco.Core.Models;
namespace Umbraco.Web.Models.ContentEditing
{
@@ -19,8 +20,8 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "parentKey")]
public Guid? ParentKey { get; set; }
[DataMember(Name = "level")]
public int Level { get; set; }
[DataMember(Name = "type")]
public PropertyGroupType Type { get; set; }
[DataMember(Name = "icon")]
public string Icon { get; set; }

View File

@@ -38,7 +38,7 @@ namespace Umbraco.Web.Models.Mapping
target.Id = source.Id;
target.Key = source.Key;
target.ParentKey = source.ParentKey;
target.Level = source.Level;
target.Type = source.Type;
target.Icon = source.Icon;
target.IsActive = true;
target.Label = source.Name;

View File

@@ -303,7 +303,7 @@ namespace Umbraco.Web.Models.Mapping
target.Key = source.Key;
target.ParentKey = source.ParentKey;
target.Level = source.Level;
target.Type = source.Type;
target.Icon = source.Icon;
target.Name = source.Name;
target.SortOrder = source.SortOrder;
@@ -317,7 +317,7 @@ namespace Umbraco.Web.Models.Mapping
target.Key = source.Key;
target.ParentKey = source.ParentKey;
target.Level = source.Level;
target.Type = source.Type;
target.Icon = source.Icon;
target.Name = source.Name;
target.SortOrder = source.SortOrder;
@@ -331,7 +331,7 @@ namespace Umbraco.Web.Models.Mapping
target.Key = source.Key;
target.ParentKey = source.ParentKey;
target.Level = source.Level;
target.Type = source.Type;
target.Icon = source.Icon;
target.Name = source.Name;
target.SortOrder = source.SortOrder;
@@ -348,7 +348,7 @@ namespace Umbraco.Web.Models.Mapping
target.Key = source.Key;
target.ParentKey = source.ParentKey;
target.Level = source.Level;
target.Type = source.Type;
target.Icon = source.Icon;
target.Name = source.Name;
target.SortOrder = source.SortOrder;
@@ -670,7 +670,7 @@ namespace Umbraco.Web.Models.Mapping
{
var propertiesA = properties.ToArray();
var distinctProperties = propertiesA
.Select(x => x.Alias.ToUpperInvariant())
.Select(x => x.Alias?.ToUpperInvariant())
.Distinct()
.Count();
if (distinctProperties != propertiesA.Length)
@@ -681,7 +681,7 @@ namespace Umbraco.Web.Models.Mapping
{
var groupsA = groups.ToArray();
var distinctProperties = groupsA
.Select(x => (x.Name?.ToUpperInvariant(), x.Level))
.Select(x => x.Name?.ToUpperInvariant())
.Distinct()
.Count();
if (distinctProperties != groupsA.Length)

View File

@@ -85,7 +85,7 @@ namespace Umbraco.Web.Models.Mapping
// Umbraco.Code.MapAll -Udi -Trashed
private static void Map(PropertyGroup source, EntityBasic target, MapperContext context)
{
target.Alias = source.Name.ToLowerInvariant();
target.Alias = source.Name?.ToLowerInvariant();
target.Icon = "icon-tab";
target.Id = source.Id;
target.Key = source.Key;

View File

@@ -77,7 +77,7 @@ namespace Umbraco.Web.Models.Mapping
Id = tab.Id,
Key = tab.Key,
ParentKey = tab.ParentKey,
Level = tab.Level,
Type = tab.Type,
Icon = tab.Icon,
Name = tab.Name,
SortOrder = tab.SortOrder,
@@ -106,7 +106,7 @@ namespace Umbraco.Web.Models.Mapping
Id = tab.Id,
Key = tab.Key,
ParentKey = tab.ParentKey,
Level = tab.Level,
Type = tab.Type,
Icon = tab.Icon,
Name = tab.Name,
SortOrder = tab.SortOrder,
@@ -146,7 +146,6 @@ namespace Umbraco.Web.Models.Mapping
var genericTab = new PropertyGroupDisplay<TPropertyType>
{
Id = PropertyGroupBasic.GenericPropertiesGroupId,
Level = 1,
Name = "Generic properties",
ContentTypeId = source.Id,
SortOrder = 999,
@@ -171,36 +170,36 @@ namespace Umbraco.Web.Models.Mapping
// now merge tabs based on names
// as for one name, we might have one local tab, plus some inherited tabs
var groupsGroupsByNameAndLevel = groups.GroupBy(x => (x.Name, x.Level)).ToArray();
var groupsGroupsByHierarchy = groups.GroupBy(x => (x.Name, x.ParentKey, x.Type)).ToArray();
groups = new List<PropertyGroupDisplay<TPropertyType>>(); // start with a fresh list
foreach (var groupsByNameAndLevel in groupsGroupsByNameAndLevel)
foreach (var groupsByHierarchy in groupsGroupsByHierarchy)
{
// single group, just use it
if (groupsByNameAndLevel.Count() == 1)
if (groupsByHierarchy.Count() == 1)
{
groups.Add(groupsByNameAndLevel.First());
groups.Add(groupsByHierarchy.First());
continue;
}
// multiple groups, merge
var group = groupsByNameAndLevel.FirstOrDefault(x => x.Inherited == false) // try local
?? groupsByNameAndLevel.First(); // else pick one randomly
var group = groupsByHierarchy.FirstOrDefault(x => x.Inherited == false) // try local
?? groupsByHierarchy.First(); // else pick one randomly
groups.Add(group);
// in case we use the local one, flag as inherited
group.Inherited = true;
// merge (and sort) properties
var properties = groupsByNameAndLevel.SelectMany(x => x.Properties).OrderBy(x => x.SortOrder).ToArray();
var properties = groupsByHierarchy.SelectMany(x => x.Properties).OrderBy(x => x.SortOrder).ToArray();
group.Properties = properties;
// collect parent group info
var parentGroups = groupsByNameAndLevel.Where(x => x.ContentTypeId != source.Id).ToArray();
var parentGroups = groupsByHierarchy.Where(x => x.ContentTypeId != source.Id).ToArray();
group.ParentTabContentTypes = parentGroups.SelectMany(x => x.ParentTabContentTypes).ToArray();
group.ParentTabContentTypeNames = parentGroups.SelectMany(x => x.ParentTabContentTypeNames).ToArray();
}
return groups.OrderBy(x => x.Level).ThenBy(x => x.SortOrder).ToArray();
return groups.OrderByHierarchy();
}
private IEnumerable<TPropertyType> MapProperties(IEnumerable<PropertyType> properties, IContentTypeBase contentType, int groupId, bool inherited)

View File

@@ -58,7 +58,6 @@ namespace Umbraco.Web.Models.Mapping
tabs.Add(new Tab<ContentPropertyDisplay>
{
Id = 0,
Level = 1,
Label = LocalizedTextService.Localize("general/properties"),
Alias = "Generic properties",
Properties = genericproperties
@@ -132,13 +131,12 @@ namespace Umbraco.Web.Models.Mapping
// content.CompositionPropertyGroups).
var groups = contentType.CompositionPropertyGroups.ToArray();
var parentKeys = groups.Where(x => x.ParentKey.HasValue).Select(x => x.ParentKey.Value).Distinct().ToArray();
var groupsGroupsByNameAndLevel = groups.OrderBy(x => x.Level).ThenBy(x => x.SortOrder).GroupBy(x => (x.Name, x.Level));
foreach (var groupsByNameAndLevel in groupsGroupsByNameAndLevel)
foreach (var groupsByHierarchy in groups.OrderByHierarchy().GroupBy(x => (x.Name, x.ParentKey)))
{
var properties = new List<Property>();
// merge properties for groups with the same name
foreach (var group in groupsByNameAndLevel)
foreach (var group in groupsByHierarchy)
{
var groupProperties = source.GetPropertiesForGroup(group)
.Where(x => IgnoreProperties.Contains(x.Alias) == false); // skip ignored
@@ -146,7 +144,7 @@ namespace Umbraco.Web.Models.Mapping
properties.AddRange(groupProperties);
}
if (properties.Count == 0 && groupsByNameAndLevel.All(x => !parentKeys.Contains(x.Key)))
if (properties.Count == 0 && groupsByHierarchy.All(x => !parentKeys.Contains(x.Key)))
continue;
//map the properties
@@ -154,15 +152,15 @@ namespace Umbraco.Web.Models.Mapping
// add the tab
// we need to pick an identifier... there is no "right" way...
var g = groupsByNameAndLevel.FirstOrDefault(x => x.Id == source.ContentTypeId) // try local
?? groupsByNameAndLevel.First(); // else pick one randomly
var g = groupsByHierarchy.FirstOrDefault(x => x.Id == source.ContentTypeId) // try local
?? groupsByHierarchy.First(); // else pick one randomly
tabs.Add(new Tab<ContentPropertyDisplay>
{
Id = g.Id,
Key = g.Key,
ParentKey = g.ParentKey,
Level = g.Level,
Type = g.Type,
Icon = g.Icon,
Alias = g.Name,
Label = LocalizedTextService.UmbracoDictionaryTranslate(g.Name),