using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.ContentEditing; using Umbraco.Core.Serialization; using Umbraco.Web.Routing; namespace Umbraco.Web.Models.ContentEditing { /// /// A model representing a content item to be displayed in the back office /// [DataContract(Name = "content", Namespace = "")] public class ContentItemDisplay : INotificationModel, IErrorModel //ListViewAwareContentItemDisplayBase { public ContentItemDisplay() { AllowPreview = true; Notifications = new List(); Errors = new Dictionary(); Variants = new List(); ContentApps = new List(); } [DataMember(Name = "id", IsRequired = true)] [Required] public int Id { get; set; } [DataMember(Name = "udi")] [ReadOnly(true)] [JsonConverter(typeof(UdiJsonConverter))] public Udi Udi { get; set; } [DataMember(Name = "icon")] public string Icon { get; set; } [DataMember(Name = "trashed")] [ReadOnly(true)] public bool Trashed { get; set; } /// /// This is the unique Id stored in the database - but could also be the unique id for a custom membership provider /// [DataMember(Name = "key")] public Guid Key { get; set; } [DataMember(Name = "parentId", IsRequired = true)] [Required] public int ParentId { get; set; } /// /// The path of the entity /// [DataMember(Name = "path")] public string Path { get; set; } /// /// A collection of content variants /// /// /// If a content item is invariant, this collection will only contain one item, else it will contain all culture variants /// [DataMember(Name = "variants")] public IEnumerable Variants { get; set; } [DataMember(Name = "owner")] public UserProfile Owner { get; set; } [DataMember(Name = "updater")] public UserProfile Updater { get; set; } /// /// The name of the content type /// [DataMember(Name = "contentTypeName")] public string ContentTypeName { get; set; } /// /// Indicates if the content is configured as a list view container /// [DataMember(Name = "isContainer")] public bool IsContainer { get; set; } /// /// Indicates if the content is configured as an element /// [DataMember(Name = "isElement")] public bool IsElement { get; set; } /// /// Property indicating if this item is part of a list view parent /// [DataMember(Name = "isChildOfListView")] public bool IsChildOfListView { get; set; } /// /// Property for the entity's individual tree node URL /// /// /// This is required if the item is a child of a list view since the tree won't actually be loaded, /// so the app will need to go fetch the individual tree node in order to be able to load it's action list (menu) /// [DataMember(Name = "treeNodeUrl")] public string TreeNodeUrl { get; set; } [DataMember(Name = "contentTypeId")] public int ContentTypeId { get; set; } [DataMember(Name = "contentTypeKey")] public Guid ContentTypeKey { get; set; } [DataMember(Name = "contentTypeAlias", IsRequired = true)] [Required(AllowEmptyStrings = false)] public string ContentTypeAlias { get; set; } [DataMember(Name = "sortOrder")] public int SortOrder { get; set; } /// /// This is the last updated date for the entire content object regardless of variants /// /// /// Each variant has it's own update date assigned as well /// [DataMember(Name = "updateDate")] public DateTime UpdateDate { get; set; } [DataMember(Name = "template")] public string TemplateAlias { get; set; } [DataMember(Name = "templateId")] public int TemplateId { get; set; } [DataMember(Name = "allowedTemplates")] public IDictionary AllowedTemplates { get; set; } [DataMember(Name = "documentType")] public ContentTypeBasic DocumentType { get; set; } [DataMember(Name = "urls")] public UrlInfo[] Urls { get; set; } /// /// Determines whether previewing is allowed for this node /// /// /// By default this is true but by using events developers can toggle this off for certain documents if there is nothing to preview /// [DataMember( Name = "allowPreview" )] public bool AllowPreview { get; set; } /// /// The allowed 'actions' based on the user's permissions - Create, Update, Publish, Send to publish /// /// /// Each char represents a button which we can then map on the front-end to the correct actions /// [DataMember(Name = "allowedActions")] public IEnumerable AllowedActions { get; set; } [DataMember(Name = "isBlueprint")] public bool IsBlueprint { get; set; } [DataMember(Name = "apps")] public IEnumerable ContentApps { get; set; } /// /// The real persisted content object - used during inbound model binding /// /// /// This is not used for outgoing model information. /// [IgnoreDataMember] public IContent PersistedContent { get; set; } /// /// The DTO object used to gather all required content data including data type information etc... for use with validation - used during inbound model binding /// /// /// We basically use this object to hydrate all required data from the database into one object so we can validate everything we need /// instead of having to look up all the data individually. /// This is not used for outgoing model information. /// [IgnoreDataMember] public ContentPropertyCollectionDto ContentDto { get; set; } /// /// This is used to add custom localized messages/strings to the response for the app to use for localized UI purposes. /// [DataMember(Name = "notifications")] [ReadOnly(true)] public List Notifications { get; private set; } /// /// This is used for validation of a content item. /// /// /// A content item can be invalid but still be saved. This occurs when there's property validation errors, we will /// still save the item but it cannot be published. So we need a way of returning validation errors as well as the /// updated model. /// /// NOTE: The ProperCase is important because when we return ModeState normally it will always be proper case. /// [DataMember(Name = "ModelState")] [ReadOnly(true)] public IDictionary Errors { get; set; } /// /// A collection of extra data that is available for this specific entity/entity type /// [DataMember(Name = "metaData")] [ReadOnly(true)] public IDictionary AdditionalData { get; private set; } } }