diff --git a/src/Umbraco.Web/Editors/DashboardController.cs b/src/Umbraco.Web/Editors/DashboardController.cs index 97db8818f2..7d95b69270 100644 --- a/src/Umbraco.Web/Editors/DashboardController.cs +++ b/src/Umbraco.Web/Editors/DashboardController.cs @@ -202,6 +202,10 @@ namespace Umbraco.Web.Editors return _dashboardService.GetDashboards(section, Security.CurrentUser).Select(x => new Tab { Id = x.Id, + Key = x.Key, + ParentKey = x.ParentKey, + Level = x.Level, + Icon = x.Icon, Alias = x.Alias, Label = x.Label, Expanded = x.Expanded, diff --git a/src/Umbraco.Web/Models/ContentEditing/Tab.cs b/src/Umbraco.Web/Models/ContentEditing/Tab.cs index 758317606c..4536b80889 100644 --- a/src/Umbraco.Web/Models/ContentEditing/Tab.cs +++ b/src/Umbraco.Web/Models/ContentEditing/Tab.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Runtime.Serialization; namespace Umbraco.Web.Models.ContentEditing @@ -12,6 +13,18 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "id")] public int Id { get; set; } + [DataMember(Name = "key")] + public Guid Key { get; set; } + + [DataMember(Name = "parentKey")] + public Guid? ParentKey { get; set; } + + [DataMember(Name = "level")] + public int Level { get; set; } + + [DataMember(Name = "icon")] + public string Icon { get; set; } + [DataMember(Name = "active")] public bool IsActive { get; set; } diff --git a/src/Umbraco.Web/Models/Mapping/ContentPropertyMapDefinition.cs b/src/Umbraco.Web/Models/Mapping/ContentPropertyMapDefinition.cs index baa9b7be69..981db18616 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentPropertyMapDefinition.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentPropertyMapDefinition.cs @@ -36,6 +36,10 @@ namespace Umbraco.Web.Models.Mapping private void Map(PropertyGroup source, Tab target, MapperContext mapper) { target.Id = source.Id; + target.Key = source.Key; + target.ParentKey = source.ParentKey; + target.Level = source.Level; + target.Icon = source.Icon; target.IsActive = true; target.Label = source.Name; } diff --git a/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesMapper.cs b/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesMapper.cs index b8d76572fb..28c94fed8d 100644 --- a/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesMapper.cs @@ -129,13 +129,15 @@ namespace Umbraco.Web.Models.Mapping // need to aggregate the tabs, as content.PropertyGroups contains all the composition tabs, // and there might be duplicates (content does not work like contentType and there is no // content.CompositionPropertyGroups). - var groupsGroupsByName = contentType.CompositionPropertyGroups.OrderBy(x => x.SortOrder).GroupBy(x => x.Name); - foreach (var groupsByName in groupsGroupsByName) + 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) { var properties = new List(); // merge properties for groups with the same name - foreach (var group in groupsByName) + foreach (var group in groupsByNameAndLevel) { var groupProperties = source.GetPropertiesForGroup(group) .Where(x => IgnoreProperties.Contains(x.Alias) == false); // skip ignored @@ -143,7 +145,7 @@ namespace Umbraco.Web.Models.Mapping properties.AddRange(groupProperties); } - if (properties.Count == 0) + if (properties.Count == 0 && groupsByNameAndLevel.All(x => !parentKeys.Contains(x.Key))) continue; //map the properties @@ -151,15 +153,18 @@ namespace Umbraco.Web.Models.Mapping // add the tab // we need to pick an identifier... there is no "right" way... - var g = groupsByName.FirstOrDefault(x => x.Id == source.ContentTypeId) // try local - ?? groupsByName.First(); // else pick one randomly - var groupId = g.Id; - var groupName = groupsByName.Key; + var g = groupsByNameAndLevel.FirstOrDefault(x => x.Id == source.ContentTypeId) // try local + ?? groupsByNameAndLevel.First(); // else pick one randomly + tabs.Add(new Tab { - Id = groupId, - Alias = groupName, - Label = LocalizedTextService.UmbracoDictionaryTranslate(groupName), + Id = g.Id, + Key = g.Key, + ParentKey = g.ParentKey, + Level = g.Level, + Icon = g.Icon, + Alias = g.Name, + Label = LocalizedTextService.UmbracoDictionaryTranslate(g.Name), Properties = mappedProperties, IsActive = false });