using System; using System.Collections.Generic; using System.Linq; using AutoMapper; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Web.Models.ContentEditing; using umbraco; namespace Umbraco.Web.Models.Mapping { /// /// Creates the tabs collection with properties assigned for display models /// internal class TabsAndPropertiesResolver : ValueResolver>> { protected IEnumerable IgnoreProperties { get; set; } public TabsAndPropertiesResolver() { IgnoreProperties = new List(); } public TabsAndPropertiesResolver(IEnumerable ignoreProperties) { if (ignoreProperties == null) throw new ArgumentNullException("ignoreProperties"); IgnoreProperties = ignoreProperties; } /// /// Maps properties on to the generic properties tab /// /// /// /// /// Any additional custom properties to assign to the generic properties tab. /// /// /// The generic properties tab is mapped during AfterMap and is responsible for /// setting up the properties such as Created date, udpated date, template selected, etc... /// public static void MapGenericProperties( TPersisted content, ContentItemDisplayBase display, params ContentPropertyDisplay[] customProperties) where TPersisted : IContentBase { var genericProps = display.Tabs.Single(x => x.Id == 0); //store the current props to append to the newly inserted ones var currProps = genericProps.Properties.ToArray(); var labelEditor = PropertyEditorResolver.Current.GetByAlias(Constants.PropertyEditors.NoEditAlias).ValueEditor.View; var contentProps = new List { new ContentPropertyDisplay { Alias = string.Format("{0}id", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = "Id", Value = Convert.ToInt32(display.Id).ToInvariantString(), View = labelEditor }, new ContentPropertyDisplay { Alias = string.Format("{0}creator", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = ui.Text("content", "createBy"), Description = "Original author", //TODO: Localize this Value = display.Owner.Name, View = labelEditor }, new ContentPropertyDisplay { Alias = string.Format("{0}createdate", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = ui.Text("content", "createDate"), Description = "Date/time this document was created", //TODO: Localize this Value = display.CreateDate.ToIsoString(), View = labelEditor }, new ContentPropertyDisplay { Alias = string.Format("{0}updatedate", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = ui.Text("content", "updateDate"), Description = "Date/time this document was created", //TODO: Localize this Value = display.UpdateDate.ToIsoString(), View = labelEditor }, new ContentPropertyDisplay { Alias = string.Format("{0}doctype", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = ui.Text("content", "documentType"), Value = display.ContentTypeName, View = labelEditor } }; //add the custom ones contentProps.AddRange(customProperties); //now add the user props contentProps.AddRange(currProps); //re-assign genericProps.Properties = contentProps; } internal static void AddContainerView(TabbedContentItem display) where TPersisted : IContentBase { var listViewTab = new Tab(); listViewTab.Alias = "containerView"; listViewTab.Label = ui.Text("content", "childItems"); listViewTab.Id = 25; listViewTab.IsActive = true; var listViewProperties = new List(); listViewProperties.Add(new ContentPropertyDisplay { Alias = string.Format("{0}containerView", Constants.PropertyEditors.InternalGenericPropertiesPrefix), Label = "", Value = null, View = "listview", HideLabel = true }); listViewTab.Properties = listViewProperties; //Is there a better way? var tabs = new List>(); tabs.Add(listViewTab); tabs.AddRange(display.Tabs); display.Tabs = tabs; } protected override IEnumerable> ResolveCore(IContentBase content) { var aggregateTabs = new List>(); //now we need to aggregate the tabs and properties since we might have duplicate tabs (based on aliases) because // of how content composition works. foreach (var propertyGroups in content.PropertyGroups.OrderBy(x => x.SortOrder).GroupBy(x => x.Name)) { var aggregateProperties = new List(); //there will always be one group with a null parent id (the top-most) //then we'll iterate over all of the groups and ensure the properties are //added in order so that when they render they are rendered with highest leve //parent properties first. int? currentParentId = null; for (var i = 0; i < propertyGroups.Count(); i++) { var current = propertyGroups.Single(x => x.ParentId == currentParentId); var propsForGroup = content.GetPropertiesForGroup(current) .Where(x => IgnoreProperties.Contains(x.Alias) == false); //don't include ignored props aggregateProperties.AddRange( Mapper.Map, IEnumerable>( propsForGroup)); currentParentId = current.Id; } //then we'll just use the root group's data to make the composite tab var rootGroup = propertyGroups.Single(x => x.ParentId == null); aggregateTabs.Add(new Tab { Id = rootGroup.Id, Alias = rootGroup.Name, Label = TranslateTab(rootGroup.Name), Properties = aggregateProperties, IsActive = false }); } //now add the generic properties tab for any properties that don't belong to a tab var orphanProperties = content.GetNonGroupedProperties() .Where(x => IgnoreProperties.Contains(x.Alias) == false); //don't include ignored props //now add the generic properties tab aggregateTabs.Add(new Tab { Id = 0, Label = ui.Text("general", "properties"), Alias = "Generic properties", Properties = Mapper.Map, IEnumerable>(orphanProperties) }); //set the first tab to active aggregateTabs.First().IsActive = true; return aggregateTabs; } private string TranslateTab(string tabName) { if (!tabName.StartsWith("#")) return tabName; return tabName.Substring(1); /* * The below currently doesnt work on my machine, since the dictonary always creates an entry with lang id = 0, but I dont have a lang id zero * so the query always fails, which is odd * var local = ApplicationContext.Current.Services.LocalizationService; var dic = local.GetDictionaryItemByKey(tabName); if (dic == null || !dic.Translations.Any()) return tabName; var lang = local.GetLanguageByCultureCode(UmbracoContext.Current.Security.CurrentUser.Language); if (lang == null) return tabName; var translation = dic.Translations.Where(x => x.Language == lang).FirstOrDefault(); if (translation == null) return tabName; return translation.Value;*/ } } }