using System.Runtime.Serialization; using Umbraco.Cms.Core.Models.ContentEditing; using Umbraco.Extensions; namespace Umbraco.Cms.Core.Trees; /// /// Represents a model in the tree /// /// /// TreeNode is sealed to prevent developers from adding additional json data to the response /// [DataContract(Name = "node", Namespace = "")] public class TreeNode : EntityBasic { /// /// Internal constructor, to create a tree node use the CreateTreeNode methods of the TreeApiController. /// /// /// The parent id for the current node /// /// public TreeNode(string nodeId, string? parentId, string? getChildNodesUrl, string? menuUrl) { if (nodeId == null) { throw new ArgumentNullException(nameof(nodeId)); } if (string.IsNullOrWhiteSpace(nodeId)) { throw new ArgumentException( "Value can't be empty or consist only of white-space characters.", nameof(nodeId)); } Id = nodeId; ParentId = parentId; ChildNodesUrl = getChildNodesUrl; MenuUrl = menuUrl; CssClasses = new List(); // default Icon = "icon-folder-close"; Path = "-1"; } [DataMember(Name = "parentId", IsRequired = true)] public new object? ParentId { get; set; } /// /// A flag to set whether or not this node has children /// [DataMember(Name = "hasChildren")] public bool HasChildren { get; set; } /// /// The tree nodetype which refers to the type of node rendered in the tree /// [DataMember(Name = "nodeType")] public string? NodeType { get; set; } /// /// Optional: The Route path for the editor for this node /// /// /// If this is not set, then the route path will be automatically determined by: {section}/edit/{id} /// [DataMember(Name = "routePath")] public string? RoutePath { get; set; } /// /// The JSON URL to load the nodes children /// [DataMember(Name = "childNodesUrl")] public string? ChildNodesUrl { get; set; } /// /// The JSON URL to load the menu from /// [DataMember(Name = "menuUrl")] public string? MenuUrl { get; set; } /// /// Returns true if the icon represents a CSS class instead of a file path /// [DataMember(Name = "iconIsClass")] public bool IconIsClass { get { if (Icon.IsNullOrWhiteSpace()) { return true; } if (Icon!.StartsWith("..")) { return false; } // if it starts with a '.' or doesn't contain a '.' at all then it is a class return Icon.StartsWith(".") || Icon.Contains(".") == false; } } /// /// Returns the icon file path if the icon is not a class, otherwise returns an empty string /// [DataMember(Name = "iconFilePath")] public string IconFilePath => string.Empty; // TODO Figure out how to do this, without the model has to know a bout services and config. // // if (IconIsClass) // return string.Empty; // // //absolute path with or without tilde // if (Icon.StartsWith("~") || Icon.StartsWith("/")) // return IOHelper.ResolveUrl("~" + Icon.TrimStart(Constants.CharArrays.Tilde)); // // //legacy icon path // return string.Format("{0}images/umbraco/{1}", Current.Configs.Global().Path.EnsureEndsWith("/"), Icon); /// /// A list of additional/custom css classes to assign to the node /// [DataMember(Name = "cssClasses")] public IList CssClasses { get; private set; } }