From a5af5ba1a957f05990710268a2ecdc459fd84590 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 17 Jan 2017 18:54:50 +1100 Subject: [PATCH 01/23] Adds new property to PropertyEditor's to mark them as deprecated so they don't show up in the data type list unless they are already selected --- .../UmbracoSettings/ContentElement.cs | 11 +++++++++++ .../UmbracoSettings/IContentSection.cs | 6 ++++++ src/Umbraco.Core/PropertyEditors/PropertyEditor.cs | 4 ++++ .../PropertyEditors/PropertyEditorAttribute.cs | 6 ++++++ .../Mapping/AvailablePropertyEditorsResolver.cs | 14 ++++++++++++++ .../Models/Mapping/DataTypeModelMapper.cs | 3 ++- .../PropertyEditors/ContentPickerPropertyEditor.cs | 2 +- .../PropertyEditors/FolderBrowserPropertyEditor.cs | 2 +- .../PropertyEditors/MediaPickerPropertyEditor.cs | 3 ++- .../MemberGroupPickerPropertyEditor.cs | 2 +- .../PropertyEditors/MemberPickerPropertyEditor.cs | 2 +- .../MultiNodeTreePickerPropertyEditor.cs | 2 +- .../MultipleMediaPickerPropertyEditor.cs | 2 +- .../PropertyEditors/UserPickerPropertyEditor.cs | 2 +- 14 files changed, 52 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs index aed7f61a06..05189acc3e 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs @@ -159,6 +159,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings get { return GetOptionalTextElement("defaultDocumentTypeProperty", "Textstring"); } } + [ConfigurationProperty("showDeprecatedPropertyEditors")] + internal InnerTextConfigurationElement ShowDeprecatedPropertyEditors + { + get { return GetOptionalTextElement("showDeprecatedPropertyEditors", false); } + } + [ConfigurationProperty("EnableInheritedDocumentTypes")] internal InnerTextConfigurationElement EnableInheritedDocumentTypes { @@ -306,6 +312,11 @@ namespace Umbraco.Core.Configuration.UmbracoSettings get { return DefaultDocumentTypeProperty; } } + bool IContentSection.ShowDeprecatedPropertyEditors + { + get { return ShowDeprecatedPropertyEditors; } + } + bool IContentSection.EnableInheritedDocumentTypes { get { return EnableInheritedDocumentTypes; } diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs index 3d5e4435b6..a388126948 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs @@ -60,6 +60,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings string DefaultDocumentTypeProperty { get; } + /// + /// The default for this is false but if you would like deprecated property editors displayed + /// in the data type editor you can enable this + /// + bool ShowDeprecatedPropertyEditors { get; } + bool EnableInheritedDocumentTypes { get; } bool EnableInheritedMediaTypes { get; } diff --git a/src/Umbraco.Core/PropertyEditors/PropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/PropertyEditor.cs index 6cecc9dff5..c2498ecc7a 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyEditor.cs @@ -38,6 +38,7 @@ namespace Umbraco.Core.PropertyEditors IsParameterEditor = _attribute.IsParameterEditor; Icon = _attribute.Icon; Group = _attribute.Group; + IsDeprecated = _attribute.IsDeprecated; } } @@ -90,6 +91,9 @@ namespace Umbraco.Core.PropertyEditors get { return CreateValueEditor(); } } + [JsonIgnore] + public bool IsDeprecated { get; internal set; } + [JsonIgnore] IValueEditor IParameterEditor.ValueEditor { diff --git a/src/Umbraco.Core/PropertyEditors/PropertyEditorAttribute.cs b/src/Umbraco.Core/PropertyEditors/PropertyEditorAttribute.cs index d120753185..41e4ccc74e 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyEditorAttribute.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyEditorAttribute.cs @@ -60,6 +60,12 @@ namespace Umbraco.Core.PropertyEditors public string ValueType { get; set; } public bool IsParameterEditor { get; set; } + /// + /// If set to true, this property editor will not show up in the DataType's drop down list + /// if there is not already one of them chosen for a DataType + /// + public bool IsDeprecated { get; set; } + /// /// If this is is true than the editor will be displayed full width without a label /// diff --git a/src/Umbraco.Web/Models/Mapping/AvailablePropertyEditorsResolver.cs b/src/Umbraco.Web/Models/Mapping/AvailablePropertyEditorsResolver.cs index 624c641d3b..2b9047c284 100644 --- a/src/Umbraco.Web/Models/Mapping/AvailablePropertyEditorsResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/AvailablePropertyEditorsResolver.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using AutoMapper; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Web.Models.ContentEditing; @@ -10,9 +11,22 @@ namespace Umbraco.Web.Models.Mapping { internal class AvailablePropertyEditorsResolver : ValueResolver> { + private readonly IContentSection _contentSection; + + public AvailablePropertyEditorsResolver(IContentSection contentSection) + { + _contentSection = contentSection; + } + protected override IEnumerable ResolveCore(IDataTypeDefinition source) { return PropertyEditorResolver.Current.PropertyEditors + .Where(x => + { + if (_contentSection.ShowDeprecatedPropertyEditors) + return true; + return source.PropertyEditorAlias == x.Alias || x.IsDeprecated == false; + }) .OrderBy(x => x.Name) .Select(Mapper.Map); } diff --git a/src/Umbraco.Web/Models/Mapping/DataTypeModelMapper.cs b/src/Umbraco.Web/Models/Mapping/DataTypeModelMapper.cs index ac2faa82dc..d7dfdbf9d0 100644 --- a/src/Umbraco.Web/Models/Mapping/DataTypeModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/DataTypeModelMapper.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using AutoMapper; using System.Linq; using Umbraco.Core; +using Umbraco.Core.Configuration; using Umbraco.Core.Models; using Umbraco.Core.Models.Mapping; using Umbraco.Core.PropertyEditors; @@ -61,7 +62,7 @@ namespace Umbraco.Web.Models.Mapping }); config.CreateMap() - .ForMember(display => display.AvailableEditors, expression => expression.ResolveUsing(new AvailablePropertyEditorsResolver())) + .ForMember(display => display.AvailableEditors, expression => expression.ResolveUsing(new AvailablePropertyEditorsResolver(UmbracoConfig.For.UmbracoSettings().Content))) .ForMember(display => display.PreValues, expression => expression.ResolveUsing( new PreValueDisplayResolver(lazyDataTypeService))) .ForMember(display => display.SelectedEditor, expression => expression.MapFrom( diff --git a/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs index 4d58060164..6a709845ff 100644 --- a/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs @@ -4,7 +4,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.ContentPickerAlias, "Content Picker", PropertyEditorValueTypes.Integer, "contentpicker", IsParameterEditor = true, Group = "Pickers")] + [PropertyEditor(Constants.PropertyEditors.ContentPickerAlias, "[Legacy] Content Picker", PropertyEditorValueTypes.Integer, "contentpicker", IsParameterEditor = true, Group = "Pickers", IsDeprecated = true)] public class ContentPickerPropertyEditor : PropertyEditor { diff --git a/src/Umbraco.Web/PropertyEditors/FolderBrowserPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/FolderBrowserPropertyEditor.cs index bfdbe368d1..5c89b868b8 100644 --- a/src/Umbraco.Web/PropertyEditors/FolderBrowserPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/FolderBrowserPropertyEditor.cs @@ -9,7 +9,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { [Obsolete("This is no longer used by default, use the ListViewPropertyEditor instead")] - [PropertyEditor(Constants.PropertyEditors.FolderBrowserAlias, "(Obsolete) Folder Browser", "folderbrowser", HideLabel=true, Icon="icon-folder", Group="media")] + [PropertyEditor(Constants.PropertyEditors.FolderBrowserAlias, "(Obsolete) Folder Browser", "folderbrowser", HideLabel=true, Icon="icon-folder", Group="media", IsDeprecated = true)] public class FolderBrowserPropertyEditor : PropertyEditor { diff --git a/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs index 7e966d31ad..718334f60b 100644 --- a/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs @@ -9,7 +9,8 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.MediaPickerAlias, "Legacy Media Picker", PropertyEditorValueTypes.Integer, "mediapicker", Group="media", Icon="icon-picture")] + + [PropertyEditor(Constants.PropertyEditors.MediaPickerAlias, "Legacy Media Picker", PropertyEditorValueTypes.Integer, "mediapicker", Group="media", Icon="icon-picture", IsDeprecated = true)] public class MediaPickerPropertyEditor : PropertyEditor { public MediaPickerPropertyEditor() diff --git a/src/Umbraco.Web/PropertyEditors/MemberGroupPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MemberGroupPickerPropertyEditor.cs index 433199c536..d7051ba8da 100644 --- a/src/Umbraco.Web/PropertyEditors/MemberGroupPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MemberGroupPickerPropertyEditor.cs @@ -8,7 +8,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.MemberGroupPickerAlias, "Member Group Picker", "membergrouppicker", Group="People", Icon="icon-users")] + [PropertyEditor(Constants.PropertyEditors.MemberGroupPickerAlias, "Member Group Picker", "membergrouppicker", Group="People", Icon="icon-users", IsDeprecated = true)] public class MemberGroupPickerPropertyEditor : PropertyEditor { } diff --git a/src/Umbraco.Web/PropertyEditors/MemberPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MemberPickerPropertyEditor.cs index 7dadbfe24c..90e7562f3a 100644 --- a/src/Umbraco.Web/PropertyEditors/MemberPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MemberPickerPropertyEditor.cs @@ -8,7 +8,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.MemberPickerAlias, "Member Picker", PropertyEditorValueTypes.Integer, "memberpicker", Group = "People", Icon = "icon-user")] + [PropertyEditor(Constants.PropertyEditors.MemberPickerAlias, "Member Picker", PropertyEditorValueTypes.Integer, "memberpicker", Group = "People", Icon = "icon-user", IsDeprecated = true)] public class MemberPickerPropertyEditor : PropertyEditor { } diff --git a/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs index b3d3f02448..1bdf0d45d9 100644 --- a/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs @@ -5,7 +5,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.MultiNodeTreePickerAlias, "Multinode Treepicker", "contentpicker", Group="pickers", Icon="icon-page-add")] + [PropertyEditor(Constants.PropertyEditors.MultiNodeTreePickerAlias, "Multinode Treepicker", "contentpicker", Group="pickers", Icon="icon-page-add", IsDeprecated = true)] public class MultiNodeTreePickerPropertyEditor : PropertyEditor { public MultiNodeTreePickerPropertyEditor() diff --git a/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs index 37587d1c54..18a1e564d6 100644 --- a/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs @@ -3,7 +3,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.MultipleMediaPickerAlias, "Media Picker", "mediapicker", Group = "media", Icon = "icon-pictures-alt-2")] + [PropertyEditor(Constants.PropertyEditors.MultipleMediaPickerAlias, "Media Picker", "mediapicker", Group = "media", Icon = "icon-pictures-alt-2", IsDeprecated = true)] public class MultipleMediaPickerPropertyEditor : MediaPickerPropertyEditor { public MultipleMediaPickerPropertyEditor() diff --git a/src/Umbraco.Web/PropertyEditors/UserPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/UserPickerPropertyEditor.cs index e4a070cb29..f824f25294 100644 --- a/src/Umbraco.Web/PropertyEditors/UserPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/UserPickerPropertyEditor.cs @@ -6,7 +6,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.UserPickerAlias, "User picker", PropertyEditorValueTypes.Integer, "entitypicker", Group="People", Icon="icon-user")] + [PropertyEditor(Constants.PropertyEditors.UserPickerAlias, "User picker", PropertyEditorValueTypes.Integer, "entitypicker", Group="People", Icon="icon-user", IsDeprecated = true)] public class UserPickerPropertyEditor : PropertyEditor { private IDictionary _defaultPreValues; From 371c4ae1a321131157a472821a051ac9604e9092 Mon Sep 17 00:00:00 2001 From: Shannon Date: Sat, 28 Jan 2017 00:22:12 +1100 Subject: [PATCH 02/23] Starts creating new UDI picker property editors --- src/Umbraco.Core/Constants-PropertyEditors.cs | 26 +++++++++++++---- .../mediapicker/mediapicker.controller.js | 3 ++ .../config/umbracoSettings.config | 3 +- .../ContentPickerPropertyEditor.cs | 23 ++++++++++++--- .../MediaPickerPropertyEditor.cs | 29 ++++++++++++++----- .../MemberGroupPickerPropertyEditor.cs | 2 +- .../MemberPickerPropertyEditor.cs | 11 +++++-- .../MultiNodeTreePickerPropertyEditor.cs | 16 +++++++--- .../MultipleMediaPickerPropertyEditor.cs | 14 +++++++-- .../UserPickerPropertyEditor.cs | 2 +- 10 files changed, 100 insertions(+), 29 deletions(-) diff --git a/src/Umbraco.Core/Constants-PropertyEditors.cs b/src/Umbraco.Core/Constants-PropertyEditors.cs index 80f118b58e..2712fffdfa 100644 --- a/src/Umbraco.Core/Constants-PropertyEditors.cs +++ b/src/Umbraco.Core/Constants-PropertyEditors.cs @@ -42,10 +42,14 @@ namespace Umbraco.Core [Obsolete("GUIDs are no longer used to reference Property Editors, use the Alias constant instead. This will be removed in future versions")] public const string ContentPicker = "158AA029-24ED-4948-939E-C3DA209E5FBA"; + + [Obsolete("This is an obsoleted content picker, use ContentPicker2Alias instead")] + public const string ContentPickerAlias = "Umbraco.ContentPickerAlias"; + /// /// Alias for the Content Picker datatype. /// - public const string ContentPickerAlias = "Umbraco.ContentPickerAlias"; + public const string ContentPicker2Alias = "Umbraco.ContentPicker2"; /// /// Guid for the Date datatype. @@ -192,39 +196,51 @@ namespace Umbraco.Core [Obsolete("GUIDs are no longer used to reference Property Editors, use the Alias constant instead. This will be removed in future versions")] public const string MediaPicker = "EAD69342-F06D-4253-83AC-28000225583B"; + [Obsolete("This is an obsoleted picker, use MediaPicker2Alias instead")] + public const string MediaPickerAlias = "Umbraco.MediaPicker"; + /// /// Alias for the Media Picker datatype. /// - public const string MediaPickerAlias = "Umbraco.MediaPicker"; + public const string MediaPicker2Alias = "Umbraco.MediaPicker2"; + [Obsolete("This is an obsoleted picker, use MultipleMediaPicker2Alias instead")] public const string MultipleMediaPickerAlias = "Umbraco.MultipleMediaPicker"; + public const string MultipleMediaPicker2Alias = "Umbraco.MultipleMediaPicker2"; + /// /// Guid for the Member Picker datatype. /// [Obsolete("GUIDs are no longer used to reference Property Editors, use the Alias constant instead. This will be removed in future versions")] public const string MemberPicker = "39F533E4-0551-4505-A64B-E0425C5CE775"; + [Obsolete("This is an obsoleted picker, use MemberPicker2Alias instead")] + public const string MemberPickerAlias = "Umbraco.MemberPicker"; + /// /// Alias for the Member Picker datatype. /// - public const string MemberPickerAlias = "Umbraco.MemberPicker"; + public const string MemberPicker2Alias = "Umbraco.MemberPicker2"; /// /// Alias for the Member Group Picker datatype. /// public const string MemberGroupPickerAlias = "Umbraco.MemberGroupPicker"; - + /// /// Guid for the Multi-Node Tree Picker datatype /// [Obsolete("GUIDs are no longer used to reference Property Editors, use the Alias constant instead. This will be removed in future versions")] public const string MultiNodeTreePicker = "7E062C13-7C41-4AD9-B389-41D88AEEF87C"; + [Obsolete("This is an obsoleted picker, use MultiNodeTreePicker2Alias instead")] + public const string MultiNodeTreePickerAlias = "Umbraco.MultiNodeTreePicker"; + /// /// Alias for the Multi-Node Tree Picker datatype /// - public const string MultiNodeTreePickerAlias = "Umbraco.MultiNodeTreePicker"; + public const string MultiNodeTreePicker2Alias = "Umbraco.MultiNodeTreePicker2"; /// /// Guid for the Multiple Textstring datatype. diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js index bbf61a32d3..6945d995cd 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js @@ -80,6 +80,9 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl } $scope.images.push(media); + + //TODO: Determine if we are storing UDI vs INT + $scope.ids.push(media.id); }); diff --git a/src/Umbraco.Web.UI/config/umbracoSettings.config b/src/Umbraco.Web.UI/config/umbracoSettings.config index 9eb3f135e9..cc71b26b70 100644 --- a/src/Umbraco.Web.UI/config/umbracoSettings.config +++ b/src/Umbraco.Web.UI/config/umbracoSettings.config @@ -104,7 +104,8 @@ Textstring - + + true diff --git a/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs index f2c62693d6..7ccd5e2495 100644 --- a/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs @@ -1,14 +1,29 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Umbraco.Core; using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.ContentPickerAlias, "[Legacy] Content Picker", PropertyEditorValueTypes.Integer, "contentpicker", IsParameterEditor = true, Group = "Pickers", IsDeprecated = true)] - public class ContentPickerPropertyEditor : PropertyEditor + + /// + /// Legacy content property editor that stores Integer Ids + /// + [Obsolete("This editor is obsolete, use ContentPickerPropertyEditor2 instead which stores UDI")] + [PropertyEditor(Constants.PropertyEditors.ContentPickerAlias, "(Obsolete) Content Picker", PropertyEditorValueTypes.Integer, "contentpicker", IsParameterEditor = true, Group = "Pickers", IsDeprecated = true)] + public class ContentPickerPropertyEditor : ContentPickerPropertyEditor2 + { + + } + + /// + /// Content property editor that stores UDI + /// + [PropertyEditor(Constants.PropertyEditors.ContentPicker2Alias, "Content Picker", PropertyEditorValueTypes.String, "contentpicker", IsParameterEditor = true, Group = "Pickers")] + public class ContentPickerPropertyEditor2 : PropertyEditor { - public ContentPickerPropertyEditor() + public ContentPickerPropertyEditor2() { _internalPreValues = new Dictionary { diff --git a/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs index 718334f60b..f776d74829 100644 --- a/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs @@ -9,11 +9,22 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - - [PropertyEditor(Constants.PropertyEditors.MediaPickerAlias, "Legacy Media Picker", PropertyEditorValueTypes.Integer, "mediapicker", Group="media", Icon="icon-picture", IsDeprecated = true)] - public class MediaPickerPropertyEditor : PropertyEditor + /// + /// Legacy media property editor that stores Integer Ids + /// + [Obsolete("This editor is obsolete, use ContentPickerPropertyEditor2 instead which stores UDI")] + [PropertyEditor(Constants.PropertyEditors.MediaPickerAlias, "(Obsolete) Media Picker", PropertyEditorValueTypes.Integer, "mediapicker", Group = "media", Icon = "icon-picture", IsDeprecated = true)] + public class MediaPickerPropertyEditor : MediaPickerPropertyEditor2 { - public MediaPickerPropertyEditor() + } + + /// + /// Media picker property editors that stores UDI + /// + [PropertyEditor(Constants.PropertyEditors.MediaPicker2Alias, "Media Picker", PropertyEditorValueTypes.String, "mediapicker", Group = "media", Icon = "icon-picture")] + public class MediaPickerPropertyEditor2 : PropertyEditor + { + public MediaPickerPropertyEditor2() { InternalPreValues = new Dictionary { @@ -26,12 +37,9 @@ namespace Umbraco.Web.PropertyEditors protected override PropertyValueEditor CreateValueEditor() { - //TODO: Need to add some validation to the ValueEditor to ensure that any media chosen actually exists! - return base.CreateValueEditor(); + return new SingleMediaPickerValueEditor(); } - - public override IDictionary DefaultPreValues { get { return InternalPreValues; } @@ -43,6 +51,11 @@ namespace Umbraco.Web.PropertyEditors return new SingleMediaPickerPreValueEditor(); } + internal class SingleMediaPickerValueEditor : PropertyValueEditor + { + override + } + internal class SingleMediaPickerPreValueEditor : PreValueEditor { [PreValueField("startNodeId", "Start node", "mediapicker")] diff --git a/src/Umbraco.Web/PropertyEditors/MemberGroupPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MemberGroupPickerPropertyEditor.cs index d7051ba8da..433199c536 100644 --- a/src/Umbraco.Web/PropertyEditors/MemberGroupPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MemberGroupPickerPropertyEditor.cs @@ -8,7 +8,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.MemberGroupPickerAlias, "Member Group Picker", "membergrouppicker", Group="People", Icon="icon-users", IsDeprecated = true)] + [PropertyEditor(Constants.PropertyEditors.MemberGroupPickerAlias, "Member Group Picker", "membergrouppicker", Group="People", Icon="icon-users")] public class MemberGroupPickerPropertyEditor : PropertyEditor { } diff --git a/src/Umbraco.Web/PropertyEditors/MemberPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MemberPickerPropertyEditor.cs index 90e7562f3a..7314121e70 100644 --- a/src/Umbraco.Web/PropertyEditors/MemberPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MemberPickerPropertyEditor.cs @@ -8,8 +8,15 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.MemberPickerAlias, "Member Picker", PropertyEditorValueTypes.Integer, "memberpicker", Group = "People", Icon = "icon-user", IsDeprecated = true)] - public class MemberPickerPropertyEditor : PropertyEditor + + [Obsolete("This editor is obsolete, use MemberPickerPropertyEditor2 instead which stores UDI")] + [PropertyEditor(Constants.PropertyEditors.MemberPickerAlias, "(Obsolete) Member Picker", PropertyEditorValueTypes.Integer, "memberpicker", Group = "People", Icon = "icon-user", IsDeprecated = true)] + public class MemberPickerPropertyEditor : MemberPickerPropertyEditor2 + { + } + + [PropertyEditor(Constants.PropertyEditors.MemberPicker2Alias, "Member Picker", PropertyEditorValueTypes.String, "memberpicker", Group = "People", Icon = "icon-user")] + public class MemberPickerPropertyEditor2 : PropertyEditor { } } diff --git a/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs index d6b9beee7a..73cb002a16 100644 --- a/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs @@ -1,14 +1,22 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.MultiNodeTreePickerAlias, "Multinode Treepicker", "contentpicker", Group="pickers", Icon="icon-page-add", IsDeprecated = true)] - public class MultiNodeTreePickerPropertyEditor : PropertyEditor + [Obsolete("This editor is obsolete, use MultiNodeTreePickerPropertyEditor2 instead which stores UDI")] + [PropertyEditor(Constants.PropertyEditors.MultiNodeTreePickerAlias, "(Obsolete) Multinode Treepicker", "contentpicker", Group = "pickers", Icon = "icon-page-add", IsDeprecated = true)] + public class MultiNodeTreePickerPropertyEditor : MultiNodeTreePickerPropertyEditor2 { - public MultiNodeTreePickerPropertyEditor() + + } + + [PropertyEditor(Constants.PropertyEditors.MultiNodeTreePicker2Alias, "Multinode Treepicker", PropertyEditorValueTypes.Text, "contentpicker", Group="pickers", Icon="icon-page-add")] + public class MultiNodeTreePickerPropertyEditor2 : PropertyEditor + { + public MultiNodeTreePickerPropertyEditor2() { _internalPreValues = new Dictionary { diff --git a/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs index 18a1e564d6..cd002a103b 100644 --- a/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs @@ -1,12 +1,20 @@ -using Umbraco.Core; +using System; +using Umbraco.Core; using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.MultipleMediaPickerAlias, "Media Picker", "mediapicker", Group = "media", Icon = "icon-pictures-alt-2", IsDeprecated = true)] + [Obsolete("This editor is obsolete, use MultipleMediaPickerPropertyEditor2 instead which stores UDI")] + [PropertyEditor(Constants.PropertyEditors.MultipleMediaPickerAlias, "(Obsolete) Media Picker", "mediapicker", Group = "media", Icon = "icon-pictures-alt-2", IsDeprecated = true)] public class MultipleMediaPickerPropertyEditor : MediaPickerPropertyEditor { - public MultipleMediaPickerPropertyEditor() + + } + + [PropertyEditor(Constants.PropertyEditors.MultipleMediaPicker2Alias, "Media Picker", PropertyEditorValueTypes.Text, "mediapicker", Group = "media", Icon = "icon-pictures-alt-2", IsDeprecated = true)] + public class MultipleMediaPickerPropertyEditor2 : MediaPickerPropertyEditor2 + { + public MultipleMediaPickerPropertyEditor2() { //clear the pre-values so it defaults to a multiple picker. InternalPreValues.Clear(); diff --git a/src/Umbraco.Web/PropertyEditors/UserPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/UserPickerPropertyEditor.cs index f824f25294..e4a070cb29 100644 --- a/src/Umbraco.Web/PropertyEditors/UserPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/UserPickerPropertyEditor.cs @@ -6,7 +6,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.UserPickerAlias, "User picker", PropertyEditorValueTypes.Integer, "entitypicker", Group="People", Icon="icon-user", IsDeprecated = true)] + [PropertyEditor(Constants.PropertyEditors.UserPickerAlias, "User picker", PropertyEditorValueTypes.Integer, "entitypicker", Group="People", Icon="icon-user")] public class UserPickerPropertyEditor : PropertyEditor { private IDictionary _defaultPreValues; From 9ef53536bf8f8a0dfa711eb902fd2ae987242616 Mon Sep 17 00:00:00 2001 From: Shannon Date: Sat, 28 Jan 2017 01:14:24 +1100 Subject: [PATCH 03/23] Updates the base editor models to include a readonly UDI, updates all model mappers to map the UDI, --- .../UmbracoUdiTypeAttribute.cs | 15 ++++++ src/Umbraco.Core/Models/UmbracoObjectTypes.cs | 18 ++++++- .../Models/UmbracoObjectTypesExtensions.cs | 36 +++++++++++++ src/Umbraco.Core/Udi.cs | 8 +-- ...s-DeployEntityType.cs => UdiEntityType.cs} | 5 +- src/Umbraco.Core/UdiGetterExtensions.cs | 50 +++++++++---------- src/Umbraco.Core/Umbraco.Core.csproj | 3 +- src/Umbraco.Tests/UdiTests.cs | 44 ++++++++-------- .../Models/ContentEditing/EntityBasic.cs | 7 ++- .../Models/Mapping/ContentModelMapper.cs | 3 ++ .../Models/Mapping/ContentTypeModelMapper.cs | 9 ++-- .../ContentTypeModelMapperExtensions.cs | 1 + .../Models/Mapping/ContentTypeUdiResolver.cs | 21 ++++++++ .../Models/Mapping/DataTypeModelMapper.cs | 3 ++ .../Models/Mapping/EntityModelMapper.cs | 7 +++ .../Models/Mapping/MacroModelMapper.cs | 1 + .../Models/Mapping/MediaModelMapper.cs | 3 ++ .../Models/Mapping/MemberModelMapper.cs | 6 ++- .../Models/Mapping/OwnerResolver.cs | 1 + src/Umbraco.Web/Umbraco.Web.csproj | 1 + 20 files changed, 182 insertions(+), 60 deletions(-) create mode 100644 src/Umbraco.Core/CodeAnnotations/UmbracoUdiTypeAttribute.cs rename src/Umbraco.Core/{Constants-DeployEntityType.cs => UdiEntityType.cs} (98%) create mode 100644 src/Umbraco.Web/Models/Mapping/ContentTypeUdiResolver.cs diff --git a/src/Umbraco.Core/CodeAnnotations/UmbracoUdiTypeAttribute.cs b/src/Umbraco.Core/CodeAnnotations/UmbracoUdiTypeAttribute.cs new file mode 100644 index 0000000000..0bb9de6c86 --- /dev/null +++ b/src/Umbraco.Core/CodeAnnotations/UmbracoUdiTypeAttribute.cs @@ -0,0 +1,15 @@ +using System; + +namespace Umbraco.Core.CodeAnnotations +{ + [AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)] + internal class UmbracoUdiTypeAttribute : Attribute + { + public string UdiType { get; private set; } + + public UmbracoUdiTypeAttribute(string udiType) + { + UdiType = udiType; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/UmbracoObjectTypes.cs b/src/Umbraco.Core/Models/UmbracoObjectTypes.cs index 02dc44c4ce..162c66e174 100644 --- a/src/Umbraco.Core/Models/UmbracoObjectTypes.cs +++ b/src/Umbraco.Core/Models/UmbracoObjectTypes.cs @@ -26,7 +26,7 @@ namespace Umbraco.Core.Models /// /// Root /// - [UmbracoObjectType(Constants.ObjectTypes.SystemRoot)] + [UmbracoObjectType(Constants.ObjectTypes.SystemRoot)] [FriendlyName("Root")] ROOT, @@ -35,6 +35,7 @@ namespace Umbraco.Core.Models /// [UmbracoObjectType(Constants.ObjectTypes.Document, typeof(IContent))] [FriendlyName("Document")] + [UmbracoUdiType(Constants.UdiEntityType.Document)] Document, /// @@ -42,6 +43,7 @@ namespace Umbraco.Core.Models /// [UmbracoObjectType(Constants.ObjectTypes.Media, typeof(IMedia))] [FriendlyName("Media")] + [UmbracoUdiType(Constants.UdiEntityType.Media)] Media, /// @@ -49,6 +51,7 @@ namespace Umbraco.Core.Models /// [UmbracoObjectType(Constants.ObjectTypes.MemberType, typeof(IMemberType))] [FriendlyName("Member Type")] + [UmbracoUdiType(Constants.UdiEntityType.MemberType)] MemberType, /// @@ -56,6 +59,7 @@ namespace Umbraco.Core.Models /// [UmbracoObjectType(Constants.ObjectTypes.Template, typeof(ITemplate))] [FriendlyName("Template")] + [UmbracoUdiType(Constants.UdiEntityType.Template)] Template, /// @@ -63,6 +67,7 @@ namespace Umbraco.Core.Models /// [UmbracoObjectType(Constants.ObjectTypes.MemberGroup)] [FriendlyName("Member Group")] + [UmbracoUdiType(Constants.UdiEntityType.MemberGroup)] MemberGroup, //TODO: What is a 'Content Item' supposed to be??? @@ -80,6 +85,7 @@ namespace Umbraco.Core.Models /// [UmbracoObjectType(Constants.ObjectTypes.MediaType, typeof(IMediaType))] [FriendlyName("Media Type")] + [UmbracoUdiType(Constants.UdiEntityType.MediaType)] MediaType, /// @@ -87,13 +93,14 @@ namespace Umbraco.Core.Models /// [UmbracoObjectType(Constants.ObjectTypes.DocumentType, typeof(IContentType))] [FriendlyName("Document Type")] + [UmbracoUdiType(Constants.UdiEntityType.DocumentType)] DocumentType, /// /// Recycle Bin /// [UmbracoObjectType(Constants.ObjectTypes.ContentRecycleBin)] - [FriendlyName("Recycle Bin")] + [FriendlyName("Recycle Bin")] RecycleBin, /// @@ -101,6 +108,7 @@ namespace Umbraco.Core.Models /// [UmbracoObjectType(Constants.ObjectTypes.Stylesheet)] [FriendlyName("Stylesheet")] + [UmbracoUdiType(Constants.UdiEntityType.Stylesheet)] Stylesheet, /// @@ -108,6 +116,7 @@ namespace Umbraco.Core.Models /// [UmbracoObjectType(Constants.ObjectTypes.Member, typeof(IMember))] [FriendlyName("Member")] + [UmbracoUdiType(Constants.UdiEntityType.Member)] Member, /// @@ -115,6 +124,7 @@ namespace Umbraco.Core.Models /// [UmbracoObjectType(Constants.ObjectTypes.DataType, typeof(IDataTypeDefinition))] [FriendlyName("Data Type")] + [UmbracoUdiType(Constants.UdiEntityType.DataType)] DataType, /// @@ -122,6 +132,7 @@ namespace Umbraco.Core.Models /// [UmbracoObjectType(Constants.ObjectTypes.DocumentTypeContainer)] [FriendlyName("Document Type Container")] + [UmbracoUdiType(Constants.UdiEntityType.DocumentTypeContainer)] DocumentTypeContainer, /// @@ -129,6 +140,7 @@ namespace Umbraco.Core.Models /// [UmbracoObjectType(Constants.ObjectTypes.MediaTypeContainer)] [FriendlyName("Media Type Container")] + [UmbracoUdiType(Constants.UdiEntityType.MediaTypeContainer)] MediaTypeContainer, /// @@ -136,6 +148,7 @@ namespace Umbraco.Core.Models /// [UmbracoObjectType(Constants.ObjectTypes.DataTypeContainer)] [FriendlyName("Data Type Container")] + [UmbracoUdiType(Constants.UdiEntityType.DataTypeContainer)] DataTypeContainer, /// @@ -143,6 +156,7 @@ namespace Umbraco.Core.Models /// [UmbracoObjectType(Constants.ObjectTypes.RelationType)] [FriendlyName("Relation Type")] + [UmbracoUdiType(Constants.UdiEntityType.RelationType)] RelationType } } \ No newline at end of file diff --git a/src/Umbraco.Core/Models/UmbracoObjectTypesExtensions.cs b/src/Umbraco.Core/Models/UmbracoObjectTypesExtensions.cs index 34ee29b96f..5f92e6425e 100644 --- a/src/Umbraco.Core/Models/UmbracoObjectTypesExtensions.cs +++ b/src/Umbraco.Core/Models/UmbracoObjectTypesExtensions.cs @@ -12,6 +12,7 @@ namespace Umbraco.Core.Models { //MUST be concurrent to avoid thread collisions! private static readonly ConcurrentDictionary UmbracoObjectTypeCache = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary UmbracoObjectTypeUdiCache = new ConcurrentDictionary(); /// /// Get an UmbracoObjectTypes value from it's name @@ -43,6 +44,21 @@ namespace Umbraco.Core.Models return umbracoObjectType; } + public static string GetUdiType(Guid guid) + { + var umbracoObjectType = Constants.UdiEntityType.Unknown; + + foreach (var name in Enum.GetNames(typeof(UmbracoObjectTypes))) + { + var objType = GetUmbracoObjectType(name); + if (objType.GetGuid() == guid) + { + umbracoObjectType = GetUdiType(objType); + } + } + return umbracoObjectType; + } + /// /// Extension method for the UmbracoObjectTypes enum to return the enum GUID /// @@ -68,6 +84,26 @@ namespace Umbraco.Core.Models }); } + public static string GetUdiType(this UmbracoObjectTypes umbracoObjectType) + { + return UmbracoObjectTypeUdiCache.GetOrAdd(umbracoObjectType, types => + { + var type = typeof(UmbracoObjectTypes); + var memInfo = type.GetMember(umbracoObjectType.ToString()); + var attributes = memInfo[0].GetCustomAttributes(typeof(UmbracoUdiTypeAttribute), + false); + + if (attributes.Length == 0) + return Constants.UdiEntityType.Unknown; + + var attribute = ((UmbracoUdiTypeAttribute)attributes[0]); + if (attribute == null) + return Constants.UdiEntityType.Unknown; + + return attribute.UdiType; + }); + } + /// /// Extension method for the UmbracoObjectTypes enum to return the enum name /// diff --git a/src/Umbraco.Core/Udi.cs b/src/Umbraco.Core/Udi.cs index a7298c6f89..ae43bbf270 100644 --- a/src/Umbraco.Core/Udi.cs +++ b/src/Umbraco.Core/Udi.cs @@ -40,12 +40,12 @@ namespace Umbraco.Core static Udi() { // for tests etc. - UdiTypes[Constants.DeployEntityType.AnyGuid] = UdiType.GuidUdi; - UdiTypes[Constants.DeployEntityType.AnyString] = UdiType.StringUdi; + UdiTypes[Constants.UdiEntityType.AnyGuid] = UdiType.GuidUdi; + UdiTypes[Constants.UdiEntityType.AnyString] = UdiType.StringUdi; // we don't have connectors for these... - UdiTypes[Constants.DeployEntityType.Member] = UdiType.GuidUdi; - UdiTypes[Constants.DeployEntityType.MemberGroup] = UdiType.GuidUdi; + UdiTypes[Constants.UdiEntityType.Member] = UdiType.GuidUdi; + UdiTypes[Constants.UdiEntityType.MemberGroup] = UdiType.GuidUdi; // fixme - or inject from...? // there is no way we can get the "registered" service connectors, as registration diff --git a/src/Umbraco.Core/Constants-DeployEntityType.cs b/src/Umbraco.Core/UdiEntityType.cs similarity index 98% rename from src/Umbraco.Core/Constants-DeployEntityType.cs rename to src/Umbraco.Core/UdiEntityType.cs index f622661dff..4e43cb06c5 100644 --- a/src/Umbraco.Core/Constants-DeployEntityType.cs +++ b/src/Umbraco.Core/UdiEntityType.cs @@ -13,11 +13,14 @@ namespace Umbraco.Core /// /// Well-known entity types are those that Deploy already knows about, /// but entity types are strings and so can be extended beyond what is defined here. - public static class DeployEntityType + public static class UdiEntityType { + public const string Unknown = "unknown"; + // guid entity types public const string AnyGuid = "any-guid"; // that one is for tests + public const string Document = "document"; public const string Media = "media"; diff --git a/src/Umbraco.Core/UdiGetterExtensions.cs b/src/Umbraco.Core/UdiGetterExtensions.cs index 1bd018a754..8acaab6512 100644 --- a/src/Umbraco.Core/UdiGetterExtensions.cs +++ b/src/Umbraco.Core/UdiGetterExtensions.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core public static GuidUdi GetUdi(this ITemplate entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new GuidUdi(Constants.DeployEntityType.Template, entity.Key).EnsureClosed(); + return new GuidUdi(Constants.UdiEntityType.Template, entity.Key).EnsureClosed(); } /// @@ -28,7 +28,7 @@ namespace Umbraco.Core public static GuidUdi GetUdi(this IContentType entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new GuidUdi(Constants.DeployEntityType.DocumentType, entity.Key).EnsureClosed(); + return new GuidUdi(Constants.UdiEntityType.DocumentType, entity.Key).EnsureClosed(); } /// @@ -39,7 +39,7 @@ namespace Umbraco.Core public static GuidUdi GetUdi(this IMediaType entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new GuidUdi(Constants.DeployEntityType.MediaType, entity.Key).EnsureClosed(); + return new GuidUdi(Constants.UdiEntityType.MediaType, entity.Key).EnsureClosed(); } /// @@ -50,7 +50,7 @@ namespace Umbraco.Core public static GuidUdi GetUdi(this IMemberType entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new GuidUdi(Constants.DeployEntityType.MemberType, entity.Key).EnsureClosed(); + return new GuidUdi(Constants.UdiEntityType.MemberType, entity.Key).EnsureClosed(); } /// @@ -61,7 +61,7 @@ namespace Umbraco.Core public static GuidUdi GetUdi(this IMemberGroup entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new GuidUdi(Constants.DeployEntityType.MemberGroup, entity.Key).EnsureClosed(); + return new GuidUdi(Constants.UdiEntityType.MemberGroup, entity.Key).EnsureClosed(); } /// @@ -74,9 +74,9 @@ namespace Umbraco.Core if (entity == null) throw new ArgumentNullException("entity"); string type; - if (entity is IContentType) type = Constants.DeployEntityType.DocumentType; - else if (entity is IMediaType) type = Constants.DeployEntityType.MediaType; - else if (entity is IMemberType) type = Constants.DeployEntityType.MemberType; + if (entity is IContentType) type = Constants.UdiEntityType.DocumentType; + else if (entity is IMediaType) type = Constants.UdiEntityType.MediaType; + else if (entity is IMemberType) type = Constants.UdiEntityType.MemberType; else throw new NotSupportedException(string.Format("Composition type {0} is not supported.", entity.GetType().FullName)); return new GuidUdi(type, entity.Key).EnsureClosed(); } @@ -89,7 +89,7 @@ namespace Umbraco.Core public static GuidUdi GetUdi(this IDataTypeDefinition entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new GuidUdi(Constants.DeployEntityType.DataType, entity.Key).EnsureClosed(); + return new GuidUdi(Constants.UdiEntityType.DataType, entity.Key).EnsureClosed(); } /// @@ -103,11 +103,11 @@ namespace Umbraco.Core string entityType; if (entity.ContainedObjectType == Constants.ObjectTypes.DataTypeGuid) - entityType = Constants.DeployEntityType.DataTypeContainer; + entityType = Constants.UdiEntityType.DataTypeContainer; else if (entity.ContainedObjectType == Constants.ObjectTypes.DocumentTypeGuid) - entityType = Constants.DeployEntityType.DocumentTypeContainer; + entityType = Constants.UdiEntityType.DocumentTypeContainer; else if (entity.ContainedObjectType == Constants.ObjectTypes.MediaTypeGuid) - entityType = Constants.DeployEntityType.MediaTypeContainer; + entityType = Constants.UdiEntityType.MediaTypeContainer; else throw new NotSupportedException(string.Format("Contained object type {0} is not supported.", entity.ContainedObjectType)); return new GuidUdi(entityType, entity.Key).EnsureClosed(); @@ -121,7 +121,7 @@ namespace Umbraco.Core public static GuidUdi GetUdi(this IMedia entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new GuidUdi(Constants.DeployEntityType.Media, entity.Key).EnsureClosed(); + return new GuidUdi(Constants.UdiEntityType.Media, entity.Key).EnsureClosed(); } /// @@ -132,7 +132,7 @@ namespace Umbraco.Core public static GuidUdi GetUdi(this IContent entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new GuidUdi(Constants.DeployEntityType.Document, entity.Key).EnsureClosed(); + return new GuidUdi(Constants.UdiEntityType.Document, entity.Key).EnsureClosed(); } /// @@ -143,7 +143,7 @@ namespace Umbraco.Core public static GuidUdi GetUdi(this IMember entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new GuidUdi(Constants.DeployEntityType.Member, entity.Key).EnsureClosed(); + return new GuidUdi(Constants.UdiEntityType.Member, entity.Key).EnsureClosed(); } /// @@ -154,7 +154,7 @@ namespace Umbraco.Core public static StringUdi GetUdi(this Stylesheet entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new StringUdi(Constants.DeployEntityType.Stylesheet, entity.Path.TrimStart('/')).EnsureClosed(); + return new StringUdi(Constants.UdiEntityType.Stylesheet, entity.Path.TrimStart('/')).EnsureClosed(); } /// @@ -165,7 +165,7 @@ namespace Umbraco.Core public static StringUdi GetUdi(this Script entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new StringUdi(Constants.DeployEntityType.Script, entity.Path.TrimStart('/')).EnsureClosed(); + return new StringUdi(Constants.UdiEntityType.Script, entity.Path.TrimStart('/')).EnsureClosed(); } /// @@ -176,7 +176,7 @@ namespace Umbraco.Core public static GuidUdi GetUdi(this IDictionaryItem entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new GuidUdi(Constants.DeployEntityType.DictionaryItem, entity.Key).EnsureClosed(); + return new GuidUdi(Constants.UdiEntityType.DictionaryItem, entity.Key).EnsureClosed(); } /// @@ -187,7 +187,7 @@ namespace Umbraco.Core public static GuidUdi GetUdi(this IMacro entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new GuidUdi(Constants.DeployEntityType.Macro, entity.Key).EnsureClosed(); + return new GuidUdi(Constants.UdiEntityType.Macro, entity.Key).EnsureClosed(); } /// @@ -198,7 +198,7 @@ namespace Umbraco.Core public static StringUdi GetUdi(this IPartialView entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new StringUdi(Constants.DeployEntityType.PartialView, entity.Path.TrimStart('/')).EnsureClosed(); + return new StringUdi(Constants.UdiEntityType.PartialView, entity.Path.TrimStart('/')).EnsureClosed(); } /// @@ -209,7 +209,7 @@ namespace Umbraco.Core public static StringUdi GetUdi(this IXsltFile entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new StringUdi(Constants.DeployEntityType.Xslt, entity.Path.TrimStart('/')).EnsureClosed(); + return new StringUdi(Constants.UdiEntityType.Xslt, entity.Path.TrimStart('/')).EnsureClosed(); } /// @@ -222,9 +222,9 @@ namespace Umbraco.Core if (entity == null) throw new ArgumentNullException("entity"); string type; - if (entity is IContent) type = Constants.DeployEntityType.Document; - else if (entity is IMedia) type = Constants.DeployEntityType.Media; - else if (entity is IMember) type = Constants.DeployEntityType.Member; + if (entity is IContent) type = Constants.UdiEntityType.Document; + else if (entity is IMedia) type = Constants.UdiEntityType.Media; + else if (entity is IMember) type = Constants.UdiEntityType.Member; else throw new NotSupportedException(string.Format("ContentBase type {0} is not supported.", entity.GetType().FullName)); return new GuidUdi(type, entity.Key).EnsureClosed(); } @@ -237,7 +237,7 @@ namespace Umbraco.Core public static GuidUdi GetUdi(this IRelationType entity) { if (entity == null) throw new ArgumentNullException("entity"); - return new GuidUdi(Constants.DeployEntityType.RelationType, entity.Key).EnsureClosed(); + return new GuidUdi(Constants.UdiEntityType.RelationType, entity.Key).EnsureClosed(); } /// diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 3a53f273f4..05854890f7 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -164,6 +164,7 @@ + @@ -290,7 +291,6 @@ - @@ -1406,6 +1406,7 @@ + diff --git a/src/Umbraco.Tests/UdiTests.cs b/src/Umbraco.Tests/UdiTests.cs index 36242bab13..9b803d5fa3 100644 --- a/src/Umbraco.Tests/UdiTests.cs +++ b/src/Umbraco.Tests/UdiTests.cs @@ -13,41 +13,41 @@ namespace Umbraco.Tests [Test] public void StringEntityCtorTest() { - var udi = new StringUdi(Constants.DeployEntityType.AnyString, "test-id"); - Assert.AreEqual(Constants.DeployEntityType.AnyString, udi.EntityType); + var udi = new StringUdi(Constants.UdiEntityType.AnyString, "test-id"); + Assert.AreEqual(Constants.UdiEntityType.AnyString, udi.EntityType); Assert.AreEqual("test-id", udi.Id); - Assert.AreEqual("umb://" + Constants.DeployEntityType.AnyString + "/test-id", udi.ToString()); + Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/test-id", udi.ToString()); } [Test] public void StringEntityParseTest() { - var udi = Udi.Parse("umb://" + Constants.DeployEntityType.AnyString + "/test-id"); - Assert.AreEqual(Constants.DeployEntityType.AnyString, udi.EntityType); + var udi = Udi.Parse("umb://" + Constants.UdiEntityType.AnyString + "/test-id"); + Assert.AreEqual(Constants.UdiEntityType.AnyString, udi.EntityType); Assert.IsInstanceOf(udi); var stringEntityId = udi as StringUdi; Assert.IsNotNull(stringEntityId); Assert.AreEqual("test-id", stringEntityId.Id); - Assert.AreEqual("umb://" + Constants.DeployEntityType.AnyString + "/test-id", udi.ToString()); + Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyString + "/test-id", udi.ToString()); } [Test] public void GuidEntityCtorTest() { var guid = Guid.NewGuid(); - var udi = new GuidUdi(Constants.DeployEntityType.AnyGuid, guid); - Assert.AreEqual(Constants.DeployEntityType.AnyGuid, udi.EntityType); + var udi = new GuidUdi(Constants.UdiEntityType.AnyGuid, guid); + Assert.AreEqual(Constants.UdiEntityType.AnyGuid, udi.EntityType); Assert.AreEqual(guid, udi.Guid); - Assert.AreEqual("umb://" + Constants.DeployEntityType.AnyGuid + "/" + guid.ToString("N"), udi.ToString()); + Assert.AreEqual("umb://" + Constants.UdiEntityType.AnyGuid + "/" + guid.ToString("N"), udi.ToString()); } [Test] public void GuidEntityParseTest() { var guid = Guid.NewGuid(); - var s = "umb://" + Constants.DeployEntityType.AnyGuid + "/" + guid.ToString("N"); + var s = "umb://" + Constants.UdiEntityType.AnyGuid + "/" + guid.ToString("N"); var udi = Udi.Parse(s); - Assert.AreEqual(Constants.DeployEntityType.AnyGuid, udi.EntityType); + Assert.AreEqual(Constants.UdiEntityType.AnyGuid, udi.EntityType); Assert.IsInstanceOf(udi); var gudi = udi as GuidUdi; Assert.IsNotNull(gudi); @@ -82,9 +82,9 @@ namespace Umbraco.Tests var guid1 = Guid.NewGuid(); var entities = new[] { - new GuidUdi(Constants.DeployEntityType.AnyGuid, guid1), - new GuidUdi(Constants.DeployEntityType.AnyGuid, guid1), - new GuidUdi(Constants.DeployEntityType.AnyGuid, guid1), + new GuidUdi(Constants.UdiEntityType.AnyGuid, guid1), + new GuidUdi(Constants.UdiEntityType.AnyGuid, guid1), + new GuidUdi(Constants.UdiEntityType.AnyGuid, guid1), }; Assert.AreEqual(1, entities.Distinct().Count()); } @@ -93,12 +93,12 @@ namespace Umbraco.Tests public void CreateTest() { var guid = Guid.NewGuid(); - var udi = Udi.Create(Constants.DeployEntityType.AnyGuid, guid); - Assert.AreEqual(Constants.DeployEntityType.AnyGuid, udi.EntityType); + var udi = Udi.Create(Constants.UdiEntityType.AnyGuid, guid); + Assert.AreEqual(Constants.UdiEntityType.AnyGuid, udi.EntityType); Assert.AreEqual(guid, ((GuidUdi)udi).Guid); - Assert.Throws(() => Udi.Create(Constants.DeployEntityType.AnyString, guid)); - Assert.Throws(() => Udi.Create(Constants.DeployEntityType.AnyGuid, "foo")); + Assert.Throws(() => Udi.Create(Constants.UdiEntityType.AnyString, guid)); + Assert.Throws(() => Udi.Create(Constants.UdiEntityType.AnyGuid, "foo")); Assert.Throws(() => Udi.Create("barf", "foo")); } @@ -106,13 +106,13 @@ namespace Umbraco.Tests public void RangeTest() { // can parse open string udi - var stringUdiString = "umb://" + Constants.DeployEntityType.AnyString; + var stringUdiString = "umb://" + Constants.UdiEntityType.AnyString; Udi stringUdi; Assert.IsTrue(Udi.TryParse(stringUdiString, out stringUdi)); Assert.AreEqual(string.Empty, ((StringUdi)stringUdi).Id); // can parse open guid udi - var guidUdiString = "umb://" + Constants.DeployEntityType.AnyGuid; + var guidUdiString = "umb://" + Constants.UdiEntityType.AnyGuid; Udi guidUdi; Assert.IsTrue(Udi.TryParse(guidUdiString, out guidUdi)); Assert.AreEqual(Guid.Empty, ((GuidUdi)guidUdi).Guid); @@ -134,12 +134,12 @@ namespace Umbraco.Tests var guid = Guid.NewGuid(); - var udi = new GuidUdi(Constants.DeployEntityType.AnyGuid, guid); + var udi = new GuidUdi(Constants.UdiEntityType.AnyGuid, guid); var json = JsonConvert.SerializeObject(udi, settings); Assert.AreEqual(string.Format("\"umb://any-guid/{0:N}\"", guid), json); var dudi = JsonConvert.DeserializeObject(json, settings); - Assert.AreEqual(Constants.DeployEntityType.AnyGuid, dudi.EntityType); + Assert.AreEqual(Constants.UdiEntityType.AnyGuid, dudi.EntityType); Assert.AreEqual(guid, ((GuidUdi)dudi).Guid); var range = new UdiRange(udi, Constants.DeploySelector.ChildrenOfThis); diff --git a/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs b/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs index 40d884d653..b17b876e76 100644 --- a/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs +++ b/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Runtime.Serialization; using System.Text; using System.Threading.Tasks; +using Umbraco.Core; using Umbraco.Core.Models.Validation; namespace Umbraco.Web.Models.ContentEditing @@ -25,7 +26,11 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "id", IsRequired = true)] [Required] public object Id { get; set; } - + + [DataMember(Name = "udi")] + [ReadOnly(true)] + public Udi Udi { get; set; } + [DataMember(Name = "icon")] public string Icon { get; set; } diff --git a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs index 27f34a12e6..afed4bfb20 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs @@ -28,6 +28,7 @@ namespace Umbraco.Web.Models.Mapping //FROM IContent TO ContentItemDisplay config.CreateMap() + .ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Document, content.Key))) .ForMember(display => display.Owner, expression => expression.ResolveUsing(new OwnerResolver())) .ForMember(display => display.Updater, expression => expression.ResolveUsing(new CreatorResolver())) .ForMember(display => display.Icon, expression => expression.MapFrom(content => content.ContentType.Icon)) @@ -58,6 +59,7 @@ namespace Umbraco.Web.Models.Mapping //FROM IContent TO ContentItemBasic config.CreateMap>() + .ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Document, content.Key))) .ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver())) .ForMember(dto => dto.Updater, expression => expression.ResolveUsing(new CreatorResolver())) .ForMember(dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon)) @@ -68,6 +70,7 @@ namespace Umbraco.Web.Models.Mapping //FROM IContent TO ContentItemDto config.CreateMap>() + .ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Document, content.Key))) .ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver())) .ForMember(dto => dto.HasPublishedVersion, expression => expression.MapFrom(content => content.HasPublishedVersion)) .ForMember(dto => dto.Updater, expression => expression.Ignore()) diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs index bf0ec1f457..de5b5a14fd 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapper.cs @@ -161,9 +161,12 @@ namespace Umbraco.Web.Models.Mapping }); - config.CreateMap(); - config.CreateMap(); - config.CreateMap(); + config.CreateMap() + .ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.MemberType, content.Key))); + config.CreateMap() + .ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.MediaType, content.Key))); + config.CreateMap() + .ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.DocumentType, content.Key))); config.CreateMap() diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapperExtensions.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapperExtensions.cs index 52f2dbad4b..cd42c87a56 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapperExtensions.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeModelMapperExtensions.cs @@ -126,6 +126,7 @@ namespace Umbraco.Web.Models.Mapping where TPropertyTypeDisplay : PropertyTypeDisplay, new() { return mapping + .ForMember(x => x.Udi, expression => expression.ResolveUsing(new ContentTypeUdiResolver())) .ForMember(display => display.Notifications, expression => expression.Ignore()) .ForMember(display => display.Errors, expression => expression.Ignore()) .ForMember(display => display.AllowAsRoot, expression => expression.MapFrom(type => type.AllowedAsRoot)) diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeUdiResolver.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeUdiResolver.cs new file mode 100644 index 0000000000..142ff43a99 --- /dev/null +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeUdiResolver.cs @@ -0,0 +1,21 @@ +using AutoMapper; +using Umbraco.Core; +using Umbraco.Core.Models; + +namespace Umbraco.Web.Models.Mapping +{ + /// + /// Resolves a UDI for a content type based on it's type + /// + internal class ContentTypeUdiResolver : ValueResolver + { + protected override Udi ResolveCore(IContentTypeComposition source) + { + return Udi.Create( + source.GetType() == typeof(IMemberType) + ? Constants.UdiEntityType.MemberType + : source.GetType() == typeof(IMediaType) + ? Constants.UdiEntityType.MediaType : Constants.UdiEntityType.DocumentType, source.Key); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Models/Mapping/DataTypeModelMapper.cs b/src/Umbraco.Web/Models/Mapping/DataTypeModelMapper.cs index d7dfdbf9d0..e78aeaf6a3 100644 --- a/src/Umbraco.Web/Models/Mapping/DataTypeModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/DataTypeModelMapper.cs @@ -35,6 +35,7 @@ namespace Umbraco.Web.Models.Mapping }; config.CreateMap() + .ForMember(x => x.Udi, expression => expression.Ignore()) .ForMember(x => x.HasPrevalues, expression => expression.Ignore()) .ForMember(x => x.IsSystemDataType, expression => expression.Ignore()) .ForMember(x => x.Id, expression => expression.Ignore()) @@ -45,6 +46,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(x => x.AdditionalData, expression => expression.Ignore()); config.CreateMap() + .ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.DataType, content.Key))) .ForMember(x => x.HasPrevalues, expression => expression.Ignore()) .ForMember(x => x.Icon, expression => expression.Ignore()) .ForMember(x => x.Alias, expression => expression.Ignore()) @@ -62,6 +64,7 @@ namespace Umbraco.Web.Models.Mapping }); config.CreateMap() + .ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.DataType, content.Key))) .ForMember(display => display.AvailableEditors, expression => expression.ResolveUsing(new AvailablePropertyEditorsResolver(UmbracoConfig.For.UmbracoSettings().Content))) .ForMember(display => display.PreValues, expression => expression.ResolveUsing( new PreValueDisplayResolver(lazyDataTypeService))) diff --git a/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs b/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs index 5610a70008..361836e529 100644 --- a/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs @@ -17,11 +17,13 @@ namespace Umbraco.Web.Models.Mapping public override void ConfigureMappings(IConfiguration config, ApplicationContext applicationContext) { config.CreateMap() + .ForMember(x => x.Udi, expression => expression.MapFrom(x => Udi.Create(UmbracoObjectTypesExtensions.GetUdiType(x.NodeObjectTypeId), x.Key))) .ForMember(basic => basic.Icon, expression => expression.MapFrom(entity => entity.ContentTypeIcon)) .ForMember(dto => dto.Trashed, expression => expression.Ignore()) .ForMember(x => x.Alias, expression => expression.Ignore()); config.CreateMap() + .ForMember(x => x.Udi, expression => expression.Ignore()) .ForMember(basic => basic.Icon, expression => expression.UseValue("icon-box")) .ForMember(basic => basic.Path, expression => expression.UseValue("")) .ForMember(basic => basic.ParentId, expression => expression.UseValue(-1)) @@ -29,6 +31,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(x => x.AdditionalData, expression => expression.Ignore()); config.CreateMap() + .ForMember(x => x.Udi, expression => expression.Ignore()) .ForMember(basic => basic.Icon, expression => expression.UseValue("icon-tab")) .ForMember(basic => basic.Path, expression => expression.UseValue("")) .ForMember(basic => basic.ParentId, expression => expression.UseValue(-1)) @@ -38,6 +41,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(x => x.AdditionalData, expression => expression.Ignore()); config.CreateMap() + .ForMember(x => x.Udi, expression => expression.Ignore()) .ForMember(basic => basic.Icon, expression => expression.UseValue("icon-user")) .ForMember(basic => basic.Path, expression => expression.UseValue("")) .ForMember(basic => basic.ParentId, expression => expression.UseValue(-1)) @@ -46,6 +50,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(x => x.AdditionalData, expression => expression.Ignore()); config.CreateMap() + .ForMember(x => x.Udi, expression => expression.MapFrom(x => Udi.Create(Constants.UdiEntityType.Template, x.Key))) .ForMember(basic => basic.Icon, expression => expression.UseValue("icon-layout")) .ForMember(basic => basic.Path, expression => expression.MapFrom(template => template.Path)) .ForMember(basic => basic.ParentId, expression => expression.UseValue(-1)) @@ -70,6 +75,7 @@ namespace Umbraco.Web.Models.Mapping .ForMember(x => x.SortOrder, expression => expression.Ignore()); config.CreateMap() + .ForMember(x => x.Udi, expression => expression.ResolveUsing(new ContentTypeUdiResolver())) .ForMember(basic => basic.Path, expression => expression.MapFrom(x => x.Path)) .ForMember(basic => basic.ParentId, expression => expression.MapFrom(x => x.ParentId)) .ForMember(dto => dto.Trashed, expression => expression.Ignore()) @@ -77,6 +83,7 @@ namespace Umbraco.Web.Models.Mapping config.CreateMap() //default to document icon + .ForMember(x => x.Udi, expression => expression.Ignore()) .ForMember(x => x.Icon, expression => expression.Ignore()) .ForMember(x => x.Id, expression => expression.MapFrom(result => result.Id)) .ForMember(x => x.Name, expression => expression.Ignore()) diff --git a/src/Umbraco.Web/Models/Mapping/MacroModelMapper.cs b/src/Umbraco.Web/Models/Mapping/MacroModelMapper.cs index 54ebca6e68..3dc86e61c9 100644 --- a/src/Umbraco.Web/Models/Mapping/MacroModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/MacroModelMapper.cs @@ -20,6 +20,7 @@ namespace Umbraco.Web.Models.Mapping { //FROM IMacro TO EntityBasic config.CreateMap() + .ForMember(x => x.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Macro, content.Key))) .ForMember(entityBasic => entityBasic.Icon, expression => expression.UseValue("icon-settings-alt")) .ForMember(dto => dto.ParentId, expression => expression.UseValue(-1)) .ForMember(dto => dto.Path, expression => expression.ResolveUsing(macro => "-1," + macro.Id)) diff --git a/src/Umbraco.Web/Models/Mapping/MediaModelMapper.cs b/src/Umbraco.Web/Models/Mapping/MediaModelMapper.cs index 4bcdf7a158..eddb4a582e 100644 --- a/src/Umbraco.Web/Models/Mapping/MediaModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/MediaModelMapper.cs @@ -25,6 +25,7 @@ namespace Umbraco.Web.Models.Mapping { //FROM IMedia TO MediaItemDisplay config.CreateMap() + .ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Media, content.Key))) .ForMember(display => display.Owner, expression => expression.ResolveUsing(new OwnerResolver())) .ForMember(display => display.Icon, expression => expression.MapFrom(content => content.ContentType.Icon)) .ForMember(display => display.ContentTypeAlias, expression => expression.MapFrom(content => content.ContentType.Alias)) @@ -45,6 +46,7 @@ namespace Umbraco.Web.Models.Mapping //FROM IMedia TO ContentItemBasic config.CreateMap>() + .ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Media, content.Key))) .ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver())) .ForMember(dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon)) .ForMember(dto => dto.Trashed, expression => expression.MapFrom(content => content.Trashed)) @@ -56,6 +58,7 @@ namespace Umbraco.Web.Models.Mapping //FROM IMedia TO ContentItemDto config.CreateMap>() + .ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Media, content.Key))) .ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver())) .ForMember(dto => dto.Published, expression => expression.Ignore()) .ForMember(dto => dto.Updater, expression => expression.Ignore()) diff --git a/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs b/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs index 0536efd307..3982302906 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs @@ -61,6 +61,7 @@ namespace Umbraco.Web.Models.Mapping //FROM IMember TO MediaItemDisplay config.CreateMap() + .ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Member, content.Key))) .ForMember(display => display.Owner, expression => expression.ResolveUsing(new OwnerResolver())) .ForMember(display => display.Icon, expression => expression.MapFrom(content => content.ContentType.Icon)) .ForMember(display => display.ContentTypeAlias, expression => expression.MapFrom(content => content.ContentType.Alias)) @@ -84,6 +85,7 @@ namespace Umbraco.Web.Models.Mapping //FROM IMember TO MemberBasic config.CreateMap() + .ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Member, content.Key))) .ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver())) .ForMember(dto => dto.Icon, expression => expression.MapFrom(content => content.ContentType.Icon)) .ForMember(dto => dto.ContentTypeAlias, expression => expression.MapFrom(content => content.ContentType.Alias)) @@ -96,9 +98,10 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dto => dto.HasPublishedVersion, expression => expression.Ignore()); //FROM MembershipUser TO MemberBasic - config.CreateMap() + config.CreateMap() //we're giving this entity an ID of 0 - we cannot really map it but it needs an id so the system knows it's not a new entity .ForMember(member => member.Id, expression => expression.MapFrom(user => int.MaxValue)) + .ForMember(display => display.Udi, expression => expression.Ignore()) .ForMember(member => member.CreateDate, expression => expression.MapFrom(user => user.CreationDate)) .ForMember(member => member.UpdateDate, expression => expression.MapFrom(user => user.LastActivityDate)) .ForMember(member => member.Key, expression => expression.MapFrom(user => user.ProviderUserKey.TryConvertTo().Result.ToString("N"))) @@ -121,6 +124,7 @@ namespace Umbraco.Web.Models.Mapping //FROM IMember TO ContentItemDto config.CreateMap>() + .ForMember(display => display.Udi, expression => expression.MapFrom(content => Udi.Create(Constants.UdiEntityType.Member, content.Key))) .ForMember(dto => dto.Owner, expression => expression.ResolveUsing(new OwnerResolver())) .ForMember(dto => dto.Published, expression => expression.Ignore()) .ForMember(dto => dto.Updater, expression => expression.Ignore()) diff --git a/src/Umbraco.Web/Models/Mapping/OwnerResolver.cs b/src/Umbraco.Web/Models/Mapping/OwnerResolver.cs index 5f3697c3d5..067d495591 100644 --- a/src/Umbraco.Web/Models/Mapping/OwnerResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/OwnerResolver.cs @@ -1,5 +1,6 @@ using AutoMapper; using Umbraco.Core.Models; +using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Models.Membership; using Umbraco.Web.Models.ContentEditing; diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index e4bb3c9e88..48cb6a455b 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -342,6 +342,7 @@ + From a31b03b3e2797ddba29d7e252a11e8a163edc9e0 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 30 Jan 2017 15:59:42 +1100 Subject: [PATCH 04/23] Lazily loads all known UdiType's based on reading through the known constants --- src/Umbraco.Core/Udi.cs | 84 ++++++++++++++++++------------- src/Umbraco.Core/UdiEntityType.cs | 36 ++++++++++++- 2 files changed, 84 insertions(+), 36 deletions(-) diff --git a/src/Umbraco.Core/Udi.cs b/src/Umbraco.Core/Udi.cs index ae43bbf270..6267af67dc 100644 --- a/src/Umbraco.Core/Udi.cs +++ b/src/Umbraco.Core/Udi.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; +using System.Reflection; using Umbraco.Core.Deploy; namespace Umbraco.Core @@ -12,7 +13,7 @@ namespace Umbraco.Core /// An Udi can be fully qualified or "closed" eg umb://document/{guid} or "open" eg umb://document. public abstract class Udi : IComparable { - private static readonly Dictionary UdiTypes = new Dictionary(); + private static readonly Lazy> UdiTypes; private static readonly ConcurrentDictionary RootUdis = new ConcurrentDictionary(); internal readonly Uri UriValue; // internal for UdiRange @@ -39,32 +40,47 @@ namespace Umbraco.Core static Udi() { - // for tests etc. - UdiTypes[Constants.UdiEntityType.AnyGuid] = UdiType.GuidUdi; - UdiTypes[Constants.UdiEntityType.AnyString] = UdiType.StringUdi; - - // we don't have connectors for these... - UdiTypes[Constants.UdiEntityType.Member] = UdiType.GuidUdi; - UdiTypes[Constants.UdiEntityType.MemberGroup] = UdiType.GuidUdi; - - // fixme - or inject from...? - // there is no way we can get the "registered" service connectors, as registration - // happens in Deploy, not in Core, and the Udi class belongs to Core - therefore, we - // just pick every service connectors - just making sure that not two of them - // would register the same entity type, with different udi types (would not make - // much sense anyways). - var connectors = PluginManager.Current.ResolveTypes(); - foreach (var connector in connectors) + UdiTypes = new Lazy>(() => { - var attrs = connector.GetCustomAttributes(false); - foreach (var attr in attrs) + var result = new Dictionary(); + + // known types: + foreach (var fi in typeof(Constants.UdiEntityType).GetFields(BindingFlags.Public | BindingFlags.Static)) { - UdiType udiType; - if (UdiTypes.TryGetValue(attr.EntityType, out udiType) && udiType != attr.UdiType) - throw new Exception(string.Format("Entity type \"{0}\" is declared by more than one IServiceConnector, with different UdiTypes.", attr.EntityType)); - UdiTypes[attr.EntityType] = attr.UdiType; + // IsLiteral determines if its value is written at + // compile time and not changeable + // IsInitOnly determine if the field can be set + // in the body of the constructor + // for C# a field which is readonly keyword would have both true + // but a const field would have only IsLiteral equal to true + if (fi.IsLiteral && fi.IsInitOnly == false) + { + var udiType = fi.GetCustomAttribute(); + result[fi.GetValue(null).ToString()] = udiType.UdiType; + } } - } + + // Scan for unknown UDI types + // there is no way we can get the "registered" service connectors, as registration + // happens in Deploy, not in Core, and the Udi class belongs to Core - therefore, we + // just pick every service connectors - just making sure that not two of them + // would register the same entity type, with different udi types (would not make + // much sense anyways). + var connectors = PluginManager.Current.ResolveTypes(); + foreach (var connector in connectors) + { + var attrs = connector.GetCustomAttributes(false); + foreach (var attr in attrs) + { + UdiType udiType; + if (result.TryGetValue(attr.EntityType, out udiType) && udiType != attr.UdiType) + throw new Exception(string.Format("Entity type \"{0}\" is declared by more than one IServiceConnector, with different UdiTypes.", attr.EntityType)); + result[attr.EntityType] = attr.UdiType; + } + } + + return result; + }); } /// @@ -105,8 +121,8 @@ namespace Umbraco.Core udi = null; Uri uri; - if (!Uri.IsWellFormedUriString(s, UriKind.Absolute) - || !Uri.TryCreate(s, UriKind.Absolute, out uri)) + if (Uri.IsWellFormedUriString(s, UriKind.Absolute) == false + || Uri.TryCreate(s, UriKind.Absolute, out uri) == false) { if (tryParse) return false; throw new FormatException(string.Format("String \"{0}\" is not a valid udi.", s)); @@ -114,7 +130,7 @@ namespace Umbraco.Core var entityType = uri.Host; UdiType udiType; - if (!UdiTypes.TryGetValue(entityType, out udiType)) + if (UdiTypes.Value.TryGetValue(entityType, out udiType) == false) { if (tryParse) return false; throw new FormatException(string.Format("Unknown entity type \"{0}\".", entityType)); @@ -128,7 +144,7 @@ namespace Umbraco.Core return true; } Guid guid; - if (!Guid.TryParse(path, out guid)) + if (Guid.TryParse(path, out guid) == false) { if (tryParse) return false; throw new FormatException(string.Format("String \"{0}\" is not a valid udi.", s)); @@ -150,7 +166,7 @@ namespace Umbraco.Core return RootUdis.GetOrAdd(entityType, x => { UdiType udiType; - if (!UdiTypes.TryGetValue(x, out udiType)) + if (UdiTypes.Value.TryGetValue(x, out udiType) == false) throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType)); return udiType == UdiType.StringUdi ? (Udi)new StringUdi(entityType, string.Empty) @@ -177,7 +193,7 @@ namespace Umbraco.Core public static Udi Create(string entityType, string id) { UdiType udiType; - if (!UdiTypes.TryGetValue(entityType, out udiType)) + if (UdiTypes.Value.TryGetValue(entityType, out udiType) == false) throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType), "entityType"); if (string.IsNullOrWhiteSpace(id)) throw new ArgumentException("Value cannot be null or whitespace.", "id"); @@ -196,7 +212,7 @@ namespace Umbraco.Core public static Udi Create(string entityType, Guid id) { UdiType udiType; - if (!UdiTypes.TryGetValue(entityType, out udiType)) + if (UdiTypes.Value.TryGetValue(entityType, out udiType) == false) throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", entityType), "entityType"); if (udiType != UdiType.GuidUdi) throw new InvalidOperationException(string.Format("Entity type \"{0}\" does not have guid udis.", entityType)); @@ -208,7 +224,7 @@ namespace Umbraco.Core internal static Udi Create(Uri uri) { UdiType udiType; - if (!UdiTypes.TryGetValue(uri.Host, out udiType)) + if (UdiTypes.Value.TryGetValue(uri.Host, out udiType) == false) throw new ArgumentException(string.Format("Unknown entity type \"{0}\".", uri.Host), "uri"); if (udiType == UdiType.GuidUdi) return new GuidUdi(uri); @@ -219,7 +235,7 @@ namespace Umbraco.Core public void EnsureType(params string[] validTypes) { - if (!validTypes.Contains(EntityType)) + if (validTypes.Contains(EntityType) == false) throw new Exception(string.Format("Unexpected entity type \"{0}\".", EntityType)); } @@ -260,7 +276,7 @@ namespace Umbraco.Core public static bool operator !=(Udi udi1, Udi udi2) { - return !(udi1 == udi2); + return (udi1 == udi2) == false; } } diff --git a/src/Umbraco.Core/UdiEntityType.cs b/src/Umbraco.Core/UdiEntityType.cs index 4e43cb06c5..d89376f3d9 100644 --- a/src/Umbraco.Core/UdiEntityType.cs +++ b/src/Umbraco.Core/UdiEntityType.cs @@ -7,7 +7,6 @@ namespace Umbraco.Core public static partial class Constants { - /// /// Defines well-known entity types. /// @@ -15,42 +14,66 @@ namespace Umbraco.Core /// but entity types are strings and so can be extended beyond what is defined here. public static class UdiEntityType { + [UdiType(UdiType.Unknown)] public const string Unknown = "unknown"; // guid entity types + [UdiType(UdiType.GuidUdi)] public const string AnyGuid = "any-guid"; // that one is for tests - + [UdiType(UdiType.GuidUdi)] public const string Document = "document"; + [UdiType(UdiType.GuidUdi)] public const string Media = "media"; + [UdiType(UdiType.GuidUdi)] public const string Member = "member"; + [UdiType(UdiType.GuidUdi)] public const string DictionaryItem = "dictionary-item"; + [UdiType(UdiType.GuidUdi)] public const string Macro = "macro"; + [UdiType(UdiType.GuidUdi)] public const string Template = "template"; + [UdiType(UdiType.GuidUdi)] public const string DocumentType = "document-type"; + [UdiType(UdiType.GuidUdi)] public const string DocumentTypeContainer = "document-type-container"; + [UdiType(UdiType.GuidUdi)] public const string MediaType = "media-type"; + [UdiType(UdiType.GuidUdi)] public const string MediaTypeContainer = "media-type-container"; + [UdiType(UdiType.GuidUdi)] public const string DataType = "data-type"; + [UdiType(UdiType.GuidUdi)] public const string DataTypeContainer = "data-type-container"; + [UdiType(UdiType.GuidUdi)] public const string MemberType = "member-type"; + [UdiType(UdiType.GuidUdi)] public const string MemberGroup = "member-group"; + [UdiType(UdiType.GuidUdi)] public const string RelationType = "relation-type"; // string entity types + [UdiType(UdiType.StringUdi)] public const string AnyString = "any-string"; // that one is for tests + [UdiType(UdiType.StringUdi)] public const string MediaFile = "media-file"; + [UdiType(UdiType.StringUdi)] public const string TemplateFile = "template-file"; + [UdiType(UdiType.StringUdi)] public const string Script = "script"; + [UdiType(UdiType.StringUdi)] public const string Stylesheet = "stylesheet"; + [UdiType(UdiType.StringUdi)] public const string PartialView = "partial-view"; + [UdiType(UdiType.StringUdi)] public const string PartialViewMacro = "partial-view-macro"; + [UdiType(UdiType.StringUdi)] public const string Xslt = "xslt"; public static string FromUmbracoObjectType(UmbracoObjectTypes umbracoObjectType) @@ -127,6 +150,15 @@ namespace Umbraco.Core } } + [AttributeUsage(AttributeTargets.Field)] + internal class UdiTypeAttribute : Attribute + { + public UdiType UdiType { get; private set; } + public UdiTypeAttribute(UdiType udiType) + { + UdiType = udiType; + } + } } } \ No newline at end of file From 0078a5d8cc80e778dfbb21691c5543907d7c6c4d Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 30 Jan 2017 16:54:01 +1100 Subject: [PATCH 05/23] Getting the media picker wired up for udi --- src/Umbraco.Core/Constants-PropertyEditors.cs | 4 +- .../mediapicker/mediapicker.controller.js | 17 ++++-- .../Models/ContentEditing/EntityBasic.cs | 3 + .../MediaPickerPropertyEditor.cs | 58 ++++++++++++------- .../MultipleMediaPickerPropertyEditor.cs | 32 +--------- 5 files changed, 58 insertions(+), 56 deletions(-) diff --git a/src/Umbraco.Core/Constants-PropertyEditors.cs b/src/Umbraco.Core/Constants-PropertyEditors.cs index 2712fffdfa..832c87bbb4 100644 --- a/src/Umbraco.Core/Constants-PropertyEditors.cs +++ b/src/Umbraco.Core/Constants-PropertyEditors.cs @@ -204,11 +204,9 @@ namespace Umbraco.Core /// public const string MediaPicker2Alias = "Umbraco.MediaPicker2"; - [Obsolete("This is an obsoleted picker, use MultipleMediaPicker2Alias instead")] + [Obsolete("This is an obsoleted picker, use MemberPicker2Alias instead")] public const string MultipleMediaPickerAlias = "Umbraco.MultipleMediaPicker"; - public const string MultipleMediaPicker2Alias = "Umbraco.MultipleMediaPicker2"; - /// /// Guid for the Member Picker datatype. /// diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js index 6945d995cd..dafe6cc3c7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js @@ -40,7 +40,13 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl } $scope.images.push(media); - $scope.ids.push(media.id); + + if ($scope.model.config.idType === "udi") { + $scope.ids.push(media.udi); + } + else { + $scope.ids.push(media.id); + } } }); @@ -81,9 +87,12 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl $scope.images.push(media); - //TODO: Determine if we are storing UDI vs INT - - $scope.ids.push(media.id); + if ($scope.model.config.idType === "udi") { + $scope.ids.push(media.udi); + } + else { + $scope.ids.push(media.id); + } }); $scope.sync(); diff --git a/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs b/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs index b17b876e76..9f6e5b28da 100644 --- a/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs +++ b/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs @@ -6,8 +6,10 @@ using System.Linq; using System.Runtime.Serialization; using System.Text; using System.Threading.Tasks; +using Newtonsoft.Json; using Umbraco.Core; using Umbraco.Core.Models.Validation; +using Umbraco.Core.Serialization; namespace Umbraco.Web.Models.ContentEditing { @@ -29,6 +31,7 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "udi")] [ReadOnly(true)] + [JsonConverter(typeof(UdiJsonConverter))] public Udi Udi { get; set; } [DataMember(Name = "icon")] diff --git a/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs index f776d74829..169d0d4639 100644 --- a/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs @@ -16,6 +16,26 @@ namespace Umbraco.Web.PropertyEditors [PropertyEditor(Constants.PropertyEditors.MediaPickerAlias, "(Obsolete) Media Picker", PropertyEditorValueTypes.Integer, "mediapicker", Group = "media", Icon = "icon-picture", IsDeprecated = true)] public class MediaPickerPropertyEditor : MediaPickerPropertyEditor2 { + public MediaPickerPropertyEditor() + { + InternalPreValues = new Dictionary + { + {"multiPicker", "0"}, + {"onlyImages", "0"}, + {"idType", "id"} + }; + } + + protected override PreValueEditor CreatePreValueEditor() + { + return new SingleMediaPickerPreValueEditor(); + } + + internal class SingleMediaPickerPreValueEditor : PreValueEditor + { + [PreValueField("startNodeId", "Start node", "mediapicker")] + public int StartNodeId { get; set; } + } } /// @@ -28,38 +48,36 @@ namespace Umbraco.Web.PropertyEditors { InternalPreValues = new Dictionary { - {"multiPicker", "0"}, - {"onlyImages", "0"} + {"idType", "udi"} }; } protected IDictionary InternalPreValues; - - protected override PropertyValueEditor CreateValueEditor() - { - return new SingleMediaPickerValueEditor(); - } - + public override IDictionary DefaultPreValues { get { return InternalPreValues; } set { InternalPreValues = value; } } - protected override PreValueEditor CreatePreValueEditor() - { - return new SingleMediaPickerPreValueEditor(); - } + protected override PreValueEditor CreatePreValueEditor() + { + return new MediaPickerPreValueEditor(); + } + + internal class MediaPickerPreValueEditor : PreValueEditor + { + [PreValueField("multiPicker", "Pick multiple items", "boolean")] + public bool MultiPicker { get; set; } + + [PreValueField("onlyImages", "Pick only images", "boolean", Description = "Only let the editor choose images from media.")] + public bool OnlyImages { get; set; } - internal class SingleMediaPickerValueEditor : PropertyValueEditor - { - override - } - - internal class SingleMediaPickerPreValueEditor : PreValueEditor - { + [PreValueField("disableFolderSelect", "Disable folder select", "boolean", Description = "Do not allow folders to be picked.")] + public bool DisableFolderSelect { get; set; } + [PreValueField("startNodeId", "Start node", "mediapicker")] - public int StartNodeId { get; set; } + public int StartNodeId { get; set; } } } } diff --git a/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs index cd002a103b..716e71711f 100644 --- a/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs @@ -7,37 +7,11 @@ namespace Umbraco.Web.PropertyEditors [Obsolete("This editor is obsolete, use MultipleMediaPickerPropertyEditor2 instead which stores UDI")] [PropertyEditor(Constants.PropertyEditors.MultipleMediaPickerAlias, "(Obsolete) Media Picker", "mediapicker", Group = "media", Icon = "icon-pictures-alt-2", IsDeprecated = true)] public class MultipleMediaPickerPropertyEditor : MediaPickerPropertyEditor - { - - } - - [PropertyEditor(Constants.PropertyEditors.MultipleMediaPicker2Alias, "Media Picker", PropertyEditorValueTypes.Text, "mediapicker", Group = "media", Icon = "icon-pictures-alt-2", IsDeprecated = true)] - public class MultipleMediaPickerPropertyEditor2 : MediaPickerPropertyEditor2 - { - public MultipleMediaPickerPropertyEditor2() + { + public MultipleMediaPickerPropertyEditor() { //clear the pre-values so it defaults to a multiple picker. InternalPreValues.Clear(); } - - protected override PreValueEditor CreatePreValueEditor() - { - return new MediaPickerPreValueEditor(); - } - - internal class MediaPickerPreValueEditor : PreValueEditor - { - [PreValueField("multiPicker", "Pick multiple items", "boolean")] - public bool MultiPicker { get; set; } - - [PreValueField("onlyImages", "Pick only images", "boolean", Description = "Only let the editor choose images from media.")] - public bool OnlyImages { get; set; } - - [PreValueField("disableFolderSelect", "Disable folder select", "boolean", Description = "Do not allow folders to be picked.")] - public bool DisableFolderSelect { get; set; } - - [PreValueField("startNodeId", "Start node", "mediapicker")] - public int StartNodeId { get; set; } - } - } + } } \ No newline at end of file From 8d598cd37c6c9712642f581be133a733468f45d6 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 30 Jan 2017 20:40:45 +1100 Subject: [PATCH 06/23] Gets EntityController working with UDIs, INT and GUID for GetByIds --- src/Umbraco.Core/Udi.cs | 2 + src/Umbraco.Core/UdiTypeConverter.cs | 37 +++++++++ src/Umbraco.Core/Umbraco.Core.csproj | 1 + src/Umbraco.Web/Editors/EntityController.cs | 75 ++++++++++++++++++ .../Editors/EntityControllerActionSelector.cs | 68 ----------------- .../EntityControllerConfigurationAttribute.cs | 15 +--- .../Editors/FromJsonPathAttribute.cs | 76 +++++++++++++++++++ .../ParameterSwapControllerActionSelector.cs | 72 +++++++++++++++--- src/Umbraco.Web/Umbraco.Web.csproj | 2 +- 9 files changed, 254 insertions(+), 94 deletions(-) create mode 100644 src/Umbraco.Core/UdiTypeConverter.cs delete mode 100644 src/Umbraco.Web/Editors/EntityControllerActionSelector.cs create mode 100644 src/Umbraco.Web/Editors/FromJsonPathAttribute.cs diff --git a/src/Umbraco.Core/Udi.cs b/src/Umbraco.Core/Udi.cs index 6267af67dc..3161b4100e 100644 --- a/src/Umbraco.Core/Udi.cs +++ b/src/Umbraco.Core/Udi.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Reflection; using Umbraco.Core.Deploy; @@ -11,6 +12,7 @@ namespace Umbraco.Core /// Represents an entity identifier. /// /// An Udi can be fully qualified or "closed" eg umb://document/{guid} or "open" eg umb://document. + [TypeConverter(typeof(UdiTypeConverter))] public abstract class Udi : IComparable { private static readonly Lazy> UdiTypes; diff --git a/src/Umbraco.Core/UdiTypeConverter.cs b/src/Umbraco.Core/UdiTypeConverter.cs new file mode 100644 index 0000000000..110b899454 --- /dev/null +++ b/src/Umbraco.Core/UdiTypeConverter.cs @@ -0,0 +1,37 @@ +using System; +using System.ComponentModel; +using System.Globalization; + +namespace Umbraco.Core +{ + /// + /// A custom type converter for UDI + /// + /// + /// Primarily this is used so that WebApi can auto-bind a string parameter to a UDI instance + /// + internal class UdiTypeConverter : TypeConverter + { + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) + { + if (sourceType == typeof(string)) + { + return true; + } + return base.CanConvertFrom(context, sourceType); + } + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + if (value is string) + { + Udi udi; + if (Udi.TryParse((string)value, out udi)) + { + return udi; + } + } + return base.ConvertFrom(context, culture, value); + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 05854890f7..830fc9a7c5 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -1410,6 +1410,7 @@ + diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 104c451273..6cdedfd352 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Globalization; using System.Net; using System.Text; @@ -29,6 +30,7 @@ using Examine.SearchCriteria; using Umbraco.Web.Dynamics; using umbraco; using System.Text.RegularExpressions; +using System.Web.Http.Controllers; using Umbraco.Core.Xml; namespace Umbraco.Web.Editors @@ -43,6 +45,20 @@ namespace Umbraco.Web.Editors [PluginController("UmbracoApi")] public class EntityController : UmbracoAuthorizedJsonController { + + /// + /// Configures this controller with a custom action selector + /// + private class EntityControllerConfigurationAttribute : Attribute, IControllerConfiguration + { + public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor) + { + //we are not also including the Udi[] overload because that is HttpPost only so there won't be any ambiguity + controllerSettings.Services.Replace(typeof(IHttpActionSelector), new ParameterSwapControllerActionSelector( + new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetByIds", "ids", typeof(int[]), typeof(Guid[]) ))); + } + } + /// /// Returns an Umbraco alias given a string /// @@ -241,6 +257,13 @@ namespace Umbraco.Web.Editors return GetResultForId(id, type); } + /// + /// Get entities by integer ids + /// + /// + /// + /// + [HttpGet] public IEnumerable GetByIds([FromUri]int[] ids, UmbracoEntityTypes type) { if (ids == null) @@ -250,6 +273,58 @@ namespace Umbraco.Web.Editors return GetResultForIds(ids, type); } + /// + /// Get entities by GUID ids + /// + /// + /// + /// + [HttpGet] + public IEnumerable GetByIds([FromUri]Guid[] ids, UmbracoEntityTypes type) + { + if (ids == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + return GetResultForKeys(ids, type); + } + + /// + /// Get entities by string ids - will try to convert to the correct id type (int, guid, udi) + /// + /// + /// + /// + /// + /// We only allow for POST because there could be quite a lot of Ids + /// + [HttpPost] + public IEnumerable GetByIds([FromJsonPath]Udi[] ids, [FromUri]UmbracoEntityTypes type) + { + if (ids == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + if (ids.Length == 0) + { + return Enumerable.Empty(); + } + + //all udi types will need to be the same in this list so we'll determine by the first + //currently we only support GuidIdi for this method + + var guidUdi = ids[0] as GuidUdi; + if (guidUdi != null) + { + return GetResultForKeys(ids.Select(x => ((GuidUdi)x).Guid), type); + } + + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + [Obsolete("Use GetyByIds instead")] + [EditorBrowsable(EditorBrowsableState.Never)] public IEnumerable GetByKeys([FromUri]Guid[] ids, UmbracoEntityTypes type) { if (ids == null) diff --git a/src/Umbraco.Web/Editors/EntityControllerActionSelector.cs b/src/Umbraco.Web/Editors/EntityControllerActionSelector.cs deleted file mode 100644 index 9cfab1bdcd..0000000000 --- a/src/Umbraco.Web/Editors/EntityControllerActionSelector.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Web; -using System.Web.Http.Controllers; -using Umbraco.Core; - -namespace Umbraco.Web.Editors -{ - /// - /// This allows for calling GetById/GetByIds with a GUID... so it will automatically route to GetByKey/GetByKeys - /// - internal class EntityControllerActionSelector : ApiControllerActionSelector - { - - public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext) - { - if (controllerContext.Request.RequestUri.GetLeftPart(UriPartial.Path).InvariantEndsWith("GetById")) - { - var id = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query).Get("id"); - - if (id != null) - { - Guid parsed; - if (Guid.TryParse(id, out parsed)) - { - var controllerType = controllerContext.Controller.GetType(); - var method = controllerType.GetMethod("GetByKey"); - if (method != null) - { - return new ReflectedHttpActionDescriptor(controllerContext.ControllerDescriptor, method); - } - } - } - } - - if (controllerContext.Request.RequestUri.GetLeftPart(UriPartial.Path).InvariantEndsWith("GetByIds")) - { - var ids = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query).GetValues("ids"); - - if (ids != null) - { - var allmatched = true; - foreach (var id in ids) - { - Guid parsed; - if (Guid.TryParse(id, out parsed) == false) - { - allmatched = false; - } - } - if (allmatched) - { - var controllerType = controllerContext.Controller.GetType(); - var method = controllerType.GetMethod("GetByKeys"); - if (method != null) - { - return new ReflectedHttpActionDescriptor(controllerContext.ControllerDescriptor, method); - } - } - } - } - - - - return base.SelectAction(controllerContext); - } - - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/Editors/EntityControllerConfigurationAttribute.cs b/src/Umbraco.Web/Editors/EntityControllerConfigurationAttribute.cs index 7ef4ef206a..571b29ed01 100644 --- a/src/Umbraco.Web/Editors/EntityControllerConfigurationAttribute.cs +++ b/src/Umbraco.Web/Editors/EntityControllerConfigurationAttribute.cs @@ -4,18 +4,5 @@ using Umbraco.Web.WebApi; namespace Umbraco.Web.Editors { - /// - /// This get's applied to the EntityController in order to have a custom IHttpActionSelector assigned to it - /// - /// - /// NOTE: It is SOOOO important to remember that you cannot just assign this in the 'initialize' method of a webapi - /// controller as it will assign it GLOBALLY which is what you def do not want to do. - /// - internal class EntityControllerConfigurationAttribute : Attribute, IControllerConfiguration - { - public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor) - { - controllerSettings.Services.Replace(typeof(IHttpActionSelector), new EntityControllerActionSelector()); - } - } + } \ No newline at end of file diff --git a/src/Umbraco.Web/Editors/FromJsonPathAttribute.cs b/src/Umbraco.Web/Editors/FromJsonPathAttribute.cs new file mode 100644 index 0000000000..3cadd2b6ca --- /dev/null +++ b/src/Umbraco.Web/Editors/FromJsonPathAttribute.cs @@ -0,0 +1,76 @@ +using System.Net.Http; +using System.Web.Http.Controllers; +using System.Web.Http.ModelBinding; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Umbraco.Web.Editors +{ + /// + /// Used to bind a value from an inner json property + /// + /// + /// An example would be if you had json like: + /// { ids: [1,2,3,4] } + /// + /// And you had an action like: GetByIds(int[] ids, UmbracoEntityTypes type) + /// + /// The ids array will not bind because the object being sent up is an object and not an array so the + /// normal json formatter will not figure this out. + /// + /// This would also let you bind sub levels of the JSON being sent up too if you wanted with any jsonpath + /// + internal class FromJsonPathAttribute : ModelBinderAttribute + { + private readonly string _jsonPath; + + public FromJsonPathAttribute() + { + } + + public FromJsonPathAttribute(string jsonPath) : base(typeof(JsonPathBinder)) + { + _jsonPath = jsonPath; + } + + public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter) + { + var config = parameter.Configuration; + var binder = new JsonPathBinder(_jsonPath); + var valueProviderFactories = GetValueProviderFactories(config); + + return new ModelBinderParameterBinding(parameter, binder, valueProviderFactories); + } + + private class JsonPathBinder : IModelBinder + { + private readonly string _jsonPath; + + public JsonPathBinder(string jsonPath) + { + _jsonPath = jsonPath; + } + + public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) + { + var requestContent = new HttpMessageContent(actionContext.Request); + var strJson = requestContent.HttpRequestMessage.Content.ReadAsStringAsync().Result; + var json = JsonConvert.DeserializeObject(strJson); + + //if no explicit json path then use the model name + var match = json.SelectToken(_jsonPath ?? bindingContext.ModelName); + + if (match == null) + { + return false; + } + + bindingContext.Model = match.ToObject(bindingContext.ModelType); + + return true; + } + } + + + } +} \ No newline at end of file diff --git a/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs b/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs index 7f17fb9f8b..75916f6272 100644 --- a/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs +++ b/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs @@ -1,7 +1,15 @@ using System; +using System.Collections; using System.Linq; +using System.Net.Http; +using System.Net.Http.Formatting; using System.Web; +using System.Web.Http; using System.Web.Http.Controllers; +using System.Web.Http.Validation; +using System.Web.Http.ValueProviders; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Umbraco.Core; namespace Umbraco.Web.Editors @@ -12,6 +20,8 @@ namespace Umbraco.Web.Editors /// /// As an example, lets say we have 2 methods: GetChildren(int id) and GetChildren(Guid id), by default Web Api won't allow this since /// it won't know what to select, but if this Tuple is passed in new Tuple{string, string}("GetChildren", "id") + /// + /// This supports POST values too however only for JSON values /// internal class ParameterSwapControllerActionSelector : ApiControllerActionSelector { @@ -25,28 +35,68 @@ namespace Umbraco.Web.Editors { _actions = actions; } + public override HttpActionDescriptor SelectAction(HttpControllerContext controllerContext) { var found = _actions.FirstOrDefault(x => controllerContext.Request.RequestUri.GetLeftPart(UriPartial.Path).InvariantEndsWith(x.ActionName)); if (found != null) { - var id = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query).Get(found.ParamName); - - if (id != null) + if (controllerContext.Request.Method == HttpMethod.Get) { - var idTypes = found.SupportedTypes; + var requestParam = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query).Get(found.ParamName); - foreach (var idType in idTypes) + if (requestParam != null) { - var converted = id.TryConvertTo(idType); - if (converted) + var paramTypes = found.SupportedTypes; + + foreach (var paramType in paramTypes) { - var method = MatchByType(idType, controllerContext, found); - if (method != null) - return method; + var converted = requestParam.TryConvertTo(paramType); + if (converted) + { + var method = MatchByType(paramType, controllerContext, found); + if (method != null) + return method; + } } - } + } + } + else if (controllerContext.Request.Method == HttpMethod.Post) + { + + var requestContent = new HttpMessageContent(controllerContext.Request); + var strJson = requestContent.HttpRequestMessage.Content.ReadAsStringAsync().Result; + var json = JsonConvert.DeserializeObject(strJson); + + var requestParam = json[found.ParamName]; + + if (requestParam != null) + { + var paramTypes = found.SupportedTypes; + + foreach (var paramType in paramTypes) + { + try + { + var converted = requestParam.ToObject(paramType); + if (converted != null) + { + var method = MatchByType(paramType, controllerContext, found); + if (method != null) + return method; + } + } + catch (JsonReaderException) + { + //can't convert + } + catch (JsonSerializationException) + { + //can't convert + } + } + } } } return base.SelectAction(controllerContext); diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 8800dc45f5..ca602cdbd8 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -285,6 +285,7 @@ + @@ -456,7 +457,6 @@ - From e95cb14d4804a8fb8e5e04fb2b74a875a3fe212f Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 31 Jan 2017 19:11:05 +1100 Subject: [PATCH 07/23] Gets FromJsonPath working for EntityController to have GetByIds with all types of Ids for both GET and POST --- src/Umbraco.Core/TypeExtensions.cs | 21 +++++++ .../src/common/resources/entity.resource.js | 19 ++---- src/Umbraco.Web/Editors/EntityController.cs | 19 ++++-- .../Editors/FromJsonPathAttribute.cs | 29 ++++++++- .../ParameterSwapControllerActionSelector.cs | 61 ++++++++++++------- 5 files changed, 108 insertions(+), 41 deletions(-) diff --git a/src/Umbraco.Core/TypeExtensions.cs b/src/Umbraco.Core/TypeExtensions.cs index 3208c1fbe8..76dc79c219 100644 --- a/src/Umbraco.Core/TypeExtensions.cs +++ b/src/Umbraco.Core/TypeExtensions.cs @@ -425,7 +425,28 @@ namespace Umbraco.Core assemblyName.FullName.StartsWith("App_Code.") ? "App_Code" : assemblyName.Name); } + /// + /// If the given is an array or some other collection + /// comprised of 0 or more instances of a "subtype", get that type + /// + /// the source type + /// + internal static Type GetEnumeratedType(this Type type) + { + if (typeof(IEnumerable).IsAssignableFrom(type) == false) + return null; + // provided by Array + var elType = type.GetElementType(); + if (null != elType) return elType; + + // otherwise provided by collection + var elTypes = type.GetGenericArguments(); + if (elTypes.Length > 0) return elTypes[0]; + + // otherwise is not an 'enumerated' type + return null; + } } } \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js index 5e0f5deada..3defb691aa 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js @@ -166,24 +166,17 @@ function entityResource($q, $http, umbRequestHelper) { */ getByIds: function (ids, type) { - var query = ""; - _.each(ids, function(item) { - query += "ids=" + item + "&"; - }); - - // if ids array is empty we need a empty variable in the querystring otherwise the service returns a error - if (ids.length === 0) { - query += "ids=&"; - } - - query += "type=" + type; + var query = "type=" + type; return umbRequestHelper.resourcePromise( - $http.get( + $http.post( umbRequestHelper.getApiUrl( "entityApiBaseUrl", "GetByIds", - query)), + query), + { + ids: ids + }), 'Failed to retrieve entity data for ids ' + ids); }, diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 6cdedfd352..40cec56a8e 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -55,7 +55,7 @@ namespace Umbraco.Web.Editors { //we are not also including the Udi[] overload because that is HttpPost only so there won't be any ambiguity controllerSettings.Services.Replace(typeof(IHttpActionSelector), new ParameterSwapControllerActionSelector( - new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetByIds", "ids", typeof(int[]), typeof(Guid[]) ))); + new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetByIds", "ids", typeof(int[]), typeof(Guid[]), typeof(Udi[]) ))); } } @@ -263,8 +263,12 @@ namespace Umbraco.Web.Editors /// /// /// + /// + /// We allow for POST because there could be quite a lot of Ids + /// [HttpGet] - public IEnumerable GetByIds([FromUri]int[] ids, UmbracoEntityTypes type) + [HttpPost] + public IEnumerable GetByIds([FromJsonPath]int[] ids, UmbracoEntityTypes type) { if (ids == null) { @@ -279,8 +283,12 @@ namespace Umbraco.Web.Editors /// /// /// + /// + /// We allow for POST because there could be quite a lot of Ids + /// [HttpGet] - public IEnumerable GetByIds([FromUri]Guid[] ids, UmbracoEntityTypes type) + [HttpPost] + public IEnumerable GetByIds([FromJsonPath]Guid[] ids, UmbracoEntityTypes type) { if (ids == null) { @@ -288,7 +296,7 @@ namespace Umbraco.Web.Editors } return GetResultForKeys(ids, type); } - + /// /// Get entities by string ids - will try to convert to the correct id type (int, guid, udi) /// @@ -296,8 +304,9 @@ namespace Umbraco.Web.Editors /// /// /// - /// We only allow for POST because there could be quite a lot of Ids + /// We allow for POST because there could be quite a lot of Ids /// + [HttpGet] [HttpPost] public IEnumerable GetByIds([FromJsonPath]Udi[] ids, [FromUri]UmbracoEntityTypes type) { diff --git a/src/Umbraco.Web/Editors/FromJsonPathAttribute.cs b/src/Umbraco.Web/Editors/FromJsonPathAttribute.cs index 3cadd2b6ca..bb275f8fa2 100644 --- a/src/Umbraco.Web/Editors/FromJsonPathAttribute.cs +++ b/src/Umbraco.Web/Editors/FromJsonPathAttribute.cs @@ -1,8 +1,12 @@ +using System.Collections.Generic; using System.Net.Http; +using System.Web.Http; using System.Web.Http.Controllers; using System.Web.Http.ModelBinding; +using System.Web.Http.ValueProviders; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using Umbraco.Core; namespace Umbraco.Web.Editors { @@ -23,6 +27,7 @@ namespace Umbraco.Web.Editors internal class FromJsonPathAttribute : ModelBinderAttribute { private readonly string _jsonPath; + private readonly FromUriAttribute _fromUriAttribute = new FromUriAttribute(); public FromJsonPathAttribute() { @@ -33,10 +38,17 @@ namespace Umbraco.Web.Editors _jsonPath = jsonPath; } + public override IEnumerable GetValueProviderFactories(HttpConfiguration configuration) + { + return _fromUriAttribute.GetValueProviderFactories(configuration); + } + public override HttpParameterBinding GetBinding(HttpParameterDescriptor parameter) { var config = parameter.Configuration; - var binder = new JsonPathBinder(_jsonPath); + //get the default binder, we'll use that if it's a GET or if the body is empty + var underlyingBinder = base.GetModelBinder(config, parameter.ParameterType); + var binder = new JsonPathBinder(underlyingBinder, _jsonPath); var valueProviderFactories = GetValueProviderFactories(config); return new ModelBinderParameterBinding(parameter, binder, valueProviderFactories); @@ -44,17 +56,30 @@ namespace Umbraco.Web.Editors private class JsonPathBinder : IModelBinder { + private readonly IModelBinder _underlyingBinder; private readonly string _jsonPath; - public JsonPathBinder(string jsonPath) + public JsonPathBinder(IModelBinder underlyingBinder, string jsonPath) { + _underlyingBinder = underlyingBinder; _jsonPath = jsonPath; } public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) { + if (actionContext.Request.Method == HttpMethod.Get) + { + return _underlyingBinder.BindModel(actionContext, bindingContext); + } + var requestContent = new HttpMessageContent(actionContext.Request); var strJson = requestContent.HttpRequestMessage.Content.ReadAsStringAsync().Result; + + if (strJson.IsNullOrWhiteSpace()) + { + return _underlyingBinder.BindModel(actionContext, bindingContext); + } + var json = JsonConvert.DeserializeObject(strJson); //if no explicit json path then use the model name diff --git a/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs b/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs index 75916f6272..6eb2856912 100644 --- a/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs +++ b/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs @@ -42,33 +42,24 @@ namespace Umbraco.Web.Editors if (found != null) { - if (controllerContext.Request.Method == HttpMethod.Get) + HttpActionDescriptor method; + if (TryBindFromUri(controllerContext, found, out method)) { - var requestParam = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query).Get(found.ParamName); - - if (requestParam != null) - { - var paramTypes = found.SupportedTypes; - - foreach (var paramType in paramTypes) - { - var converted = requestParam.TryConvertTo(paramType); - if (converted) - { - var method = MatchByType(paramType, controllerContext, found); - if (method != null) - return method; - } - } - } + return method; } - else if (controllerContext.Request.Method == HttpMethod.Post) - { + //if it's a post we can try to read from the body and bind from th + if (controllerContext.Request.Method == HttpMethod.Post) + { var requestContent = new HttpMessageContent(controllerContext.Request); var strJson = requestContent.HttpRequestMessage.Content.ReadAsStringAsync().Result; var json = JsonConvert.DeserializeObject(strJson); + if (json == null) + { + return base.SelectAction(controllerContext); + } + var requestParam = json[found.ParamName]; if (requestParam != null) @@ -82,7 +73,7 @@ namespace Umbraco.Web.Editors var converted = requestParam.ToObject(paramType); if (converted != null) { - var method = MatchByType(paramType, controllerContext, found); + method = MatchByType(paramType, controllerContext, found); if (method != null) return method; } @@ -102,6 +93,34 @@ namespace Umbraco.Web.Editors return base.SelectAction(controllerContext); } + private bool TryBindFromUri(HttpControllerContext controllerContext, ParameterSwapInfo found, out HttpActionDescriptor method) + { + var requestParam = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query).Get(found.ParamName); + + if (requestParam != null) + { + var paramTypes = found.SupportedTypes; + + foreach (var paramType in paramTypes) + { + //check if this is IEnumerable and if so this will get it's type + //we need to know this since the requestParam will always just be a string + var enumType = paramType.GetEnumeratedType(); + + var converted = requestParam.TryConvertTo(enumType ?? paramType); + if (converted) + { + method = MatchByType(paramType, controllerContext, found); + if (method != null) + return true; + } + } + } + + method = null; + return false; + } + private static ReflectedHttpActionDescriptor MatchByType(Type idType, HttpControllerContext controllerContext, ParameterSwapInfo found) { var controllerType = controllerContext.Controller.GetType(); From 83757c60b5e32d7035ff08f75206eb3f07a434cf Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 1 Feb 2017 13:38:42 +1100 Subject: [PATCH 08/23] Adds UDI support for the content picker --- .../contentpicker/contentpicker.controller.js | 36 ++++++++++++++++--- .../ContentPickerPropertyEditor.cs | 16 +++++---- .../MediaPickerPropertyEditor.cs | 2 +- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index 947603794a..a56af3b4ae 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -17,11 +17,21 @@ function contentPickerController($scope, entityResource, editorState, iconHelper $scope.$watch(function () { //return the joined Ids as a string to watch return _.map($scope.renderModel, function (i) { - return i.id; + if ($scope.model.config.idType === "udi") { + return i.udi; + } + else { + return i.id; + } }).join(); }, function (newVal) { var currIds = _.map($scope.renderModel, function (i) { - return i.id; + if ($scope.model.config.idType === "udi") { + return i.udi; + } + else { + return i.id; + } }); $scope.model.value = trim(currIds.join(), ","); @@ -200,7 +210,12 @@ function contentPickerController($scope, entityResource, editorState, iconHelper $scope.add = function (item) { var currIds = _.map($scope.renderModel, function (i) { - return i.id; + if ($scope.model.config.idType === "udi") { + return i.udi; + } + else { + return i.id; + } }); if (currIds.indexOf(item.id) < 0) { @@ -227,7 +242,12 @@ function contentPickerController($scope, entityResource, editorState, iconHelper var unsubscribe = $scope.$on("formSubmitting", function (ev, args) { var currIds = _.map($scope.renderModel, function (i) { - return i.id; + if ($scope.model.config.idType === "udi") { + return i.udi; + } + else { + return i.id; + } }); $scope.model.value = trim(currIds.join(), ","); }); @@ -244,7 +264,12 @@ function contentPickerController($scope, entityResource, editorState, iconHelper _.each(modelIds, function (id, i) { var entity = _.find(data, function (d) { - return d.id == id; + if ($scope.model.config.idType === "udi") { + return d.udi == id; + } + else { + return d.id == id; + } }); if (entity) { @@ -304,6 +329,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper $scope.renderModel.push({ "name": item.name, "id": item.id, + "udi": item.udi, "icon": item.icon, "path": item.path, "url": item.url, diff --git a/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs index 7ccd5e2495..d1508d2012 100644 --- a/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs @@ -13,7 +13,10 @@ namespace Umbraco.Web.PropertyEditors [PropertyEditor(Constants.PropertyEditors.ContentPickerAlias, "(Obsolete) Content Picker", PropertyEditorValueTypes.Integer, "contentpicker", IsParameterEditor = true, Group = "Pickers", IsDeprecated = true)] public class ContentPickerPropertyEditor : ContentPickerPropertyEditor2 { - + public ContentPickerPropertyEditor() + { + InternalPreValues["idType"] = "int"; + } } /// @@ -25,20 +28,21 @@ namespace Umbraco.Web.PropertyEditors public ContentPickerPropertyEditor2() { - _internalPreValues = new Dictionary + InternalPreValues = new Dictionary { {"startNodeId", "-1"}, {"showOpenButton", "0"}, {"showEditButton", "0"}, - {"showPathOnHover", "0"} + {"showPathOnHover", "0"}, + {"idType", "udi"} }; } - private IDictionary _internalPreValues; + protected IDictionary InternalPreValues; public override IDictionary DefaultPreValues { - get { return _internalPreValues; } - set { _internalPreValues = value; } + get { return InternalPreValues; } + set { InternalPreValues = value; } } protected override PreValueEditor CreatePreValueEditor() diff --git a/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs index 169d0d4639..d835209362 100644 --- a/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs @@ -22,7 +22,7 @@ namespace Umbraco.Web.PropertyEditors { {"multiPicker", "0"}, {"onlyImages", "0"}, - {"idType", "id"} + {"idType", "int"} }; } From 69b913c608f3a9f948523b3752ee1acbdb0e5de9 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 1 Feb 2017 14:07:13 +1100 Subject: [PATCH 09/23] Gets MNTP working with UDI - updates EntityController to support all types of Ids for GetById --- src/Umbraco.Web/Editors/EntityController.cs | 60 ++++++++++++++----- .../ContentPickerPropertyEditor.cs | 2 +- .../MediaPickerPropertyEditor.cs | 2 +- .../MultiNodeTreePickerPropertyEditor.cs | 16 +++-- 4 files changed, 58 insertions(+), 22 deletions(-) diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 40cec56a8e..edea2821ff 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -53,9 +53,9 @@ namespace Umbraco.Web.Editors { public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor) { - //we are not also including the Udi[] overload because that is HttpPost only so there won't be any ambiguity controllerSettings.Services.Replace(typeof(IHttpActionSelector), new ParameterSwapControllerActionSelector( - new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetByIds", "ids", typeof(int[]), typeof(Guid[]), typeof(Udi[]) ))); + new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetById", "id", typeof(int), typeof(Guid), typeof(Udi)), + new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetByIds", "ids", typeof(int[]), typeof(Guid[]), typeof(Udi[])))); } } @@ -160,9 +160,7 @@ namespace Umbraco.Web.Editors return foundContent.Path.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).Select(int.Parse); } - - - + /// /// Gets the url of an entity /// @@ -201,13 +199,9 @@ namespace Umbraco.Web.Editors Content = new StringContent(returnUrl) }; } - - /// - /// Gets an entity by it's unique id if the entity supports that - /// - /// - /// - /// + + [Obsolete("Use GetyById instead")] + [EditorBrowsable(EditorBrowsableState.Never)] public EntityBasic GetByKey(Guid id, UmbracoEntityTypes type) { return GetResultForKey(id, type); @@ -251,12 +245,49 @@ namespace Umbraco.Web.Editors }, publishedContentExists: i => Umbraco.TypedContent(i) != null); } - + + #region GetById + + /// + /// Gets an entity by it's id + /// + /// + /// + /// public EntityBasic GetById(int id, UmbracoEntityTypes type) { return GetResultForId(id, type); } + /// + /// Gets an entity by it's key + /// + /// + /// + /// + public EntityBasic GetById(Guid id, UmbracoEntityTypes type) + { + return GetResultForKey(id, type); + } + + /// + /// Gets an entity by it's UDI + /// + /// + /// + /// + public EntityBasic GetById(Udi id, UmbracoEntityTypes type) + { + var guidUdi = id as GuidUdi; + if (guidUdi != null) + { + return GetResultForKey(guidUdi.Guid, type); + } + throw new HttpResponseException(HttpStatusCode.NotFound); + } + #endregion + + #region GetByIds /// /// Get entities by integer ids /// @@ -330,7 +361,8 @@ namespace Umbraco.Web.Editors } throw new HttpResponseException(HttpStatusCode.NotFound); - } + } + #endregion [Obsolete("Use GetyByIds instead")] [EditorBrowsable(EditorBrowsableState.Never)] diff --git a/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs index d1508d2012..4f798dc41e 100644 --- a/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs @@ -38,7 +38,7 @@ namespace Umbraco.Web.PropertyEditors }; } - protected IDictionary InternalPreValues; + internal IDictionary InternalPreValues; public override IDictionary DefaultPreValues { get { return InternalPreValues; } diff --git a/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs index d835209362..d6c8589871 100644 --- a/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs @@ -52,7 +52,7 @@ namespace Umbraco.Web.PropertyEditors }; } - protected IDictionary InternalPreValues; + internal IDictionary InternalPreValues; public override IDictionary DefaultPreValues { diff --git a/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs index 73cb002a16..c3e257962a 100644 --- a/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs @@ -10,7 +10,10 @@ namespace Umbraco.Web.PropertyEditors [PropertyEditor(Constants.PropertyEditors.MultiNodeTreePickerAlias, "(Obsolete) Multinode Treepicker", "contentpicker", Group = "pickers", Icon = "icon-page-add", IsDeprecated = true)] public class MultiNodeTreePickerPropertyEditor : MultiNodeTreePickerPropertyEditor2 { - + public MultiNodeTreePickerPropertyEditor() + { + InternalPreValues["idType"] = "int"; + } } [PropertyEditor(Constants.PropertyEditors.MultiNodeTreePicker2Alias, "Multinode Treepicker", PropertyEditorValueTypes.Text, "contentpicker", Group="pickers", Icon="icon-page-add")] @@ -18,12 +21,13 @@ namespace Umbraco.Web.PropertyEditors { public MultiNodeTreePickerPropertyEditor2() { - _internalPreValues = new Dictionary + InternalPreValues = new Dictionary { {"multiPicker", "1"}, {"showOpenButton", "0"}, {"showEditButton", "0"}, - {"showPathOnHover", "0"} + {"showPathOnHover", "0"}, + {"idType", "udi"} }; } @@ -32,11 +36,11 @@ namespace Umbraco.Web.PropertyEditors return new MultiNodePickerPreValueEditor(); } - private IDictionary _internalPreValues; + internal IDictionary InternalPreValues; public override IDictionary DefaultPreValues { - get { return _internalPreValues; } - set { _internalPreValues = value; } + get { return InternalPreValues; } + set { InternalPreValues = value; } } internal class MultiNodePickerPreValueEditor : PreValueEditor From 384a31e3c6cf013ca6d96cfc5c124173af209e5c Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 1 Feb 2017 15:19:52 +1100 Subject: [PATCH 10/23] Gets member picker working with UDI, ensures that the GUID is indexed for all things - can't believe this wasn't being done, updates the search model mapper to return the UDI --- .../contentpicker/contentpicker.controller.js | 39 ++++--------------- .../memberpicker/memberpicker.controller.js | 22 ++++++++--- .../Models/Mapping/EntityModelMapper.cs | 28 +++++++++++-- .../MemberPickerPropertyEditor.cs | 18 +++++++++ src/UmbracoExamine/UmbracoContentIndexer.cs | 20 ++++++++-- src/UmbracoExamine/UmbracoMemberIndexer.cs | 19 ++------- 6 files changed, 86 insertions(+), 60 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index a56af3b4ae..27df035914 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -17,21 +17,11 @@ function contentPickerController($scope, entityResource, editorState, iconHelper $scope.$watch(function () { //return the joined Ids as a string to watch return _.map($scope.renderModel, function (i) { - if ($scope.model.config.idType === "udi") { - return i.udi; - } - else { - return i.id; - } + return $scope.model.config.idType === "udi" ? i.udi : i.id; }).join(); }, function (newVal) { var currIds = _.map($scope.renderModel, function (i) { - if ($scope.model.config.idType === "udi") { - return i.udi; - } - else { - return i.id; - } + return $scope.model.config.idType === "udi" ? i.udi : i.id; }); $scope.model.value = trim(currIds.join(), ","); @@ -210,15 +200,12 @@ function contentPickerController($scope, entityResource, editorState, iconHelper $scope.add = function (item) { var currIds = _.map($scope.renderModel, function (i) { - if ($scope.model.config.idType === "udi") { - return i.udi; - } - else { - return i.id; - } + return $scope.model.config.idType === "udi" ? i.udi : i.id; }); - if (currIds.indexOf(item.id) < 0) { + var itemId = $scope.model.config.idType === "udi" ? item.udi : item.id; + + if (currIds.indexOf(itemId) < 0) { setEntityUrl(item); } }; @@ -242,12 +229,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper var unsubscribe = $scope.$on("formSubmitting", function (ev, args) { var currIds = _.map($scope.renderModel, function (i) { - if ($scope.model.config.idType === "udi") { - return i.udi; - } - else { - return i.id; - } + return $scope.model.config.idType === "udi" ? i.udi : i.id; }); $scope.model.value = trim(currIds.join(), ","); }); @@ -264,12 +246,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper _.each(modelIds, function (id, i) { var entity = _.find(data, function (d) { - if ($scope.model.config.idType === "udi") { - return d.udi == id; - } - else { - return d.id == id; - } + return $scope.model.config.idType === "udi" ? (d.udi == id) : (d.id == id); }); if (entity) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.controller.js index 0029332f64..efa05ae882 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.controller.js @@ -68,12 +68,19 @@ function memberPickerController($scope, dialogService, entityResource, $log, ico $scope.add = function (item) { var currIds = _.map($scope.renderModel, function (i) { - return i.id; + if ($scope.model.config.idType === "udi") { + return i.udi; + } + else { + return i.id; + } }); - if (currIds.indexOf(item.id) < 0) { + var itemId = $scope.model.config.idType === "udi" ? item.udi : item.id; + + if (currIds.indexOf(itemId) < 0) { item.icon = iconHelper.convertFromLegacyIcon(item.icon); - $scope.renderModel.push({name: item.name, id: item.id, icon: item.icon}); + $scope.renderModel.push({ name: item.name, id: item.id, udi: item.udi, icon: item.icon}); } }; @@ -83,7 +90,12 @@ function memberPickerController($scope, dialogService, entityResource, $log, ico var unsubscribe = $scope.$on("formSubmitting", function (ev, args) { var currIds = _.map($scope.renderModel, function (i) { - return i.id; + if ($scope.model.config.idType === "udi") { + return i.udi; + } + else { + return i.id; + } }); $scope.model.value = trim(currIds.join(), ","); }); @@ -99,7 +111,7 @@ function memberPickerController($scope, dialogService, entityResource, $log, ico _.each(data, function (item, i) { // set default icon if it's missing item.icon = (item.icon) ? iconHelper.convertFromLegacyIcon(item.icon) : "icon-user"; - $scope.renderModel.push({ name: item.name, id: item.id, icon: item.icon }); + $scope.renderModel.push({ name: item.name, id: item.id, udi: item.udi, icon: item.icon }); }); }); } diff --git a/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs b/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs index 361836e529..cd6b9b9f83 100644 --- a/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using AutoMapper; using Examine; +using Examine.LuceneEngine.Providers; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.Mapping; @@ -94,21 +95,40 @@ namespace Umbraco.Web.Models.Mapping .ForMember(dto => dto.Trashed, expression => expression.Ignore()) .ForMember(x => x.AdditionalData, expression => expression.Ignore()) .AfterMap((result, basic) => - { + { + //get the icon if there is one basic.Icon = result.Fields.ContainsKey(UmbracoContentIndexer.IconFieldName) ? result.Fields[UmbracoContentIndexer.IconFieldName] : "icon-document"; basic.Name = result.Fields.ContainsKey("nodeName") ? result.Fields["nodeName"] : "[no name]"; - if (result.Fields.ContainsKey("__NodeKey")) + if (result.Fields.ContainsKey(UmbracoContentIndexer.NodeKeyFieldName)) { Guid key; - if (Guid.TryParse(result.Fields["__NodeKey"], out key)) + if (Guid.TryParse(result.Fields[UmbracoContentIndexer.NodeKeyFieldName], out key)) { basic.Key = key; + + //need to set the UDI + if (result.Fields.ContainsKey(LuceneIndexer.IndexTypeFieldName)) + { + switch (result.Fields[LuceneIndexer.IndexTypeFieldName]) + { + case IndexTypes.Member: + basic.Udi = new GuidUdi(Constants.UdiEntityType.Member, basic.Key); + break; + case IndexTypes.Content: + basic.Udi = new GuidUdi(Constants.UdiEntityType.Document, basic.Key); + break; + case IndexTypes.Media: + basic.Udi = new GuidUdi(Constants.UdiEntityType.Media, basic.Key); + break; + } + } } } + if (result.Fields.ContainsKey("parentID")) { int parentId; @@ -121,7 +141,7 @@ namespace Umbraco.Web.Models.Mapping basic.ParentId = -1; } } - basic.Path = result.Fields.ContainsKey("__Path") ? result.Fields["__Path"] : ""; + basic.Path = result.Fields.ContainsKey(UmbracoContentIndexer.IndexPathFieldName) ? result.Fields[UmbracoContentIndexer.IndexPathFieldName] : ""; if (result.Fields.ContainsKey(UmbracoContentIndexer.NodeTypeAliasFieldName)) { diff --git a/src/Umbraco.Web/PropertyEditors/MemberPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MemberPickerPropertyEditor.cs index 7314121e70..68f864e9b6 100644 --- a/src/Umbraco.Web/PropertyEditors/MemberPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MemberPickerPropertyEditor.cs @@ -13,10 +13,28 @@ namespace Umbraco.Web.PropertyEditors [PropertyEditor(Constants.PropertyEditors.MemberPickerAlias, "(Obsolete) Member Picker", PropertyEditorValueTypes.Integer, "memberpicker", Group = "People", Icon = "icon-user", IsDeprecated = true)] public class MemberPickerPropertyEditor : MemberPickerPropertyEditor2 { + public MemberPickerPropertyEditor() + { + InternalPreValues["idType"] = "int"; + } } [PropertyEditor(Constants.PropertyEditors.MemberPicker2Alias, "Member Picker", PropertyEditorValueTypes.String, "memberpicker", Group = "People", Icon = "icon-user")] public class MemberPickerPropertyEditor2 : PropertyEditor { + public MemberPickerPropertyEditor2() + { + InternalPreValues = new Dictionary + { + {"idType", "udi"} + }; + } + + internal IDictionary InternalPreValues; + public override IDictionary DefaultPreValues + { + get { return InternalPreValues; } + set { InternalPreValues = value; } + } } } diff --git a/src/UmbracoExamine/UmbracoContentIndexer.cs b/src/UmbracoExamine/UmbracoContentIndexer.cs index e7df641122..1798596668 100644 --- a/src/UmbracoExamine/UmbracoContentIndexer.cs +++ b/src/UmbracoExamine/UmbracoContentIndexer.cs @@ -183,6 +183,7 @@ namespace UmbracoExamine /// Used to store the path of a content object /// public const string IndexPathFieldName = "__Path"; + public const string NodeKeyFieldName = "__Key"; public const string NodeTypeAliasFieldName = "__NodeTypeAlias"; public const string IconFieldName = "__Icon"; @@ -726,18 +727,23 @@ namespace UmbracoExamine //ensure the special path and node type alias fields is added to the dictionary to be saved to file var path = e.Node.Attribute("path").Value; - if (!e.Fields.ContainsKey(IndexPathFieldName)) + if (e.Fields.ContainsKey(IndexPathFieldName) == false) e.Fields.Add(IndexPathFieldName, path); //this needs to support both schema's so get the nodeTypeAlias if it exists, otherwise the name var nodeTypeAlias = e.Node.Attribute("nodeTypeAlias") == null ? e.Node.Name.LocalName : e.Node.Attribute("nodeTypeAlias").Value; - if (!e.Fields.ContainsKey(NodeTypeAliasFieldName)) + if (e.Fields.ContainsKey(NodeTypeAliasFieldName) == false) e.Fields.Add(NodeTypeAliasFieldName, nodeTypeAlias); //add icon var icon = (string)e.Node.Attribute("icon"); - if (!e.Fields.ContainsKey(IconFieldName)) - e.Fields.Add(IconFieldName, icon); + if (e.Fields.ContainsKey(IconFieldName) == false) + e.Fields.Add(IconFieldName, icon); + + //add guid + var guid = (string)e.Node.Attribute("key"); + if (e.Fields.ContainsKey(NodeKeyFieldName) == false) + e.Fields.Add(NodeKeyFieldName, guid); } /// @@ -768,6 +774,12 @@ namespace UmbracoExamine //adds the special node type alias property to the index fields.Add(NodeTypeAliasFieldName, allValuesForIndexing[NodeTypeAliasFieldName]); + //guid + if (allValuesForIndexing[IconFieldName].IsNullOrWhiteSpace() == false) + { + fields.Add(NodeKeyFieldName, allValuesForIndexing[NodeKeyFieldName]); + } + //icon if (allValuesForIndexing[IconFieldName].IsNullOrWhiteSpace() == false) { diff --git a/src/UmbracoExamine/UmbracoMemberIndexer.cs b/src/UmbracoExamine/UmbracoMemberIndexer.cs index 2e48dff64e..94cbcb2135 100644 --- a/src/UmbracoExamine/UmbracoMemberIndexer.cs +++ b/src/UmbracoExamine/UmbracoMemberIndexer.cs @@ -231,20 +231,7 @@ namespace UmbracoExamine protected override XDocument GetXDocument(string xPath, string type) { throw new NotSupportedException(); - } - - protected override Dictionary GetSpecialFieldsToIndex(Dictionary allValuesForIndexing) - { - var fields = base.GetSpecialFieldsToIndex(allValuesForIndexing); - - //adds the special path property to the index - string valuesForIndexing; - if (allValuesForIndexing.TryGetValue("__key", out valuesForIndexing)) - fields.Add("__key", valuesForIndexing); - - return fields; - - } + } /// /// Add the special __key and _searchEmail fields @@ -256,8 +243,8 @@ namespace UmbracoExamine if (e.Node.Attribute("key") != null) { - if (e.Fields.ContainsKey("__key") == false) - e.Fields.Add("__key", e.Node.Attribute("key").Value); + if (e.Fields.ContainsKey(NodeKeyFieldName) == false) + e.Fields.Add(NodeKeyFieldName, e.Node.Attribute("key").Value); } if (e.Node.Attribute("email") != null) From a03e0dfb53262c15888fe3f06cdccb3b7d53c7cc Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 2 Feb 2017 22:21:36 +1100 Subject: [PATCH 11/23] Fixes tests --- src/Umbraco.Core/Udi.cs | 3 +++ src/Umbraco.Core/UdiEntityType.cs | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Udi.cs b/src/Umbraco.Core/Udi.cs index 3161b4100e..9d67c6ccab 100644 --- a/src/Umbraco.Core/Udi.cs +++ b/src/Umbraco.Core/Udi.cs @@ -58,6 +58,9 @@ namespace Umbraco.Core if (fi.IsLiteral && fi.IsInitOnly == false) { var udiType = fi.GetCustomAttribute(); + + if (udiType == null) + throw new InvalidOperationException("All Constants listed in UdiEntityType must be attributed with " + typeof(Constants.UdiTypeAttribute)); result[fi.GetValue(null).ToString()] = udiType.UdiType; } } diff --git a/src/Umbraco.Core/UdiEntityType.cs b/src/Umbraco.Core/UdiEntityType.cs index 3ab32a6eac..bc7b0571d7 100644 --- a/src/Umbraco.Core/UdiEntityType.cs +++ b/src/Umbraco.Core/UdiEntityType.cs @@ -55,10 +55,14 @@ namespace Umbraco.Core [UdiType(UdiType.GuidUdi)] public const string RelationType = "relation-type"; - + // forms + + [UdiType(UdiType.GuidUdi)] public const string FormsForm = "forms-form"; + [UdiType(UdiType.GuidUdi)] public const string FormsWorkflow = "forms-workflow"; + [UdiType(UdiType.GuidUdi)] public const string FormsRecord = "forms-record"; // string entity types From db86f6e1eec4b01574e4d76061d7def4ac715183 Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 3 Feb 2017 11:49:22 +1100 Subject: [PATCH 12/23] Fixes up issues reported on review and adds a null check --- src/Umbraco.Web/Editors/EntityController.cs | 30 ++++++++++--------- .../ParameterSwapControllerActionSelector.cs | 2 +- .../Models/Mapping/ContentTypeUdiResolver.cs | 2 ++ src/UmbracoExamine/UmbracoContentIndexer.cs | 2 +- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index edea2821ff..81dc5d8722 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -329,13 +329,15 @@ namespace Umbraco.Web.Editors } /// - /// Get entities by string ids - will try to convert to the correct id type (int, guid, udi) + /// Get entities by UDIs /// - /// + /// + /// A list of UDIs to lookup items by, all UDIs must be of the same UDI type! + /// /// /// /// - /// We allow for POST because there could be quite a lot of Ids + /// We allow for POST because there could be quite a lot of Ids. /// [HttpGet] [HttpPost] @@ -357,7 +359,7 @@ namespace Umbraco.Web.Editors var guidUdi = ids[0] as GuidUdi; if (guidUdi != null) { - return GetResultForKeys(ids.Select(x => ((GuidUdi)x).Guid), type); + return GetResultForKeys(ids.Select(x => ((GuidUdi)x).Guid).ToArray(), type); } throw new HttpResponseException(HttpStatusCode.NotFound); @@ -759,21 +761,21 @@ namespace Umbraco.Web.Editors } } - private IEnumerable GetResultForKeys(IEnumerable keys, UmbracoEntityTypes entityType) + private IEnumerable GetResultForKeys(Guid[] keys, UmbracoEntityTypes entityType) { - var keysArray = keys.ToArray(); - if (keysArray.Any() == false) return Enumerable.Empty(); + if (keys.Length == 0) + return Enumerable.Empty(); var objectType = ConvertToObjectType(entityType); if (objectType.HasValue) { - var entities = Services.EntityService.GetAll(objectType.Value, keysArray) + var entities = Services.EntityService.GetAll(objectType.Value, keys) .WhereNotNull() .Select(Mapper.Map); // entities are in "some" order, put them back in order var xref = entities.ToDictionary(x => x.Key); - var result = keysArray.Select(x => xref.ContainsKey(x) ? xref[x] : null).Where(x => x != null); + var result = keys.Select(x => xref.ContainsKey(x) ? xref[x] : null).Where(x => x != null); return result; } @@ -791,21 +793,21 @@ namespace Umbraco.Web.Editors } } - private IEnumerable GetResultForIds(IEnumerable ids, UmbracoEntityTypes entityType) + private IEnumerable GetResultForIds(int[] ids, UmbracoEntityTypes entityType) { - var idsArray = ids.ToArray(); - if (idsArray.Any() == false) return Enumerable.Empty(); + if (ids.Length == 0) + return Enumerable.Empty(); var objectType = ConvertToObjectType(entityType); if (objectType.HasValue) { - var entities = Services.EntityService.GetAll(objectType.Value, idsArray) + var entities = Services.EntityService.GetAll(objectType.Value, ids) .WhereNotNull() .Select(Mapper.Map); // entities are in "some" order, put them back in order var xref = entities.ToDictionary(x => x.Id); - var result = idsArray.Select(x => xref.ContainsKey(x) ? xref[x] : null).Where(x => x != null); + var result = ids.Select(x => xref.ContainsKey(x) ? xref[x] : null).Where(x => x != null); return result; } diff --git a/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs b/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs index 6eb2856912..3cb94ef8e6 100644 --- a/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs +++ b/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs @@ -48,7 +48,7 @@ namespace Umbraco.Web.Editors return method; } - //if it's a post we can try to read from the body and bind from th + //if it's a post we can try to read from the body and bind from the json value if (controllerContext.Request.Method == HttpMethod.Post) { var requestContent = new HttpMessageContent(controllerContext.Request); diff --git a/src/Umbraco.Web/Models/Mapping/ContentTypeUdiResolver.cs b/src/Umbraco.Web/Models/Mapping/ContentTypeUdiResolver.cs index 142ff43a99..2d33b17155 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentTypeUdiResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentTypeUdiResolver.cs @@ -11,6 +11,8 @@ namespace Umbraco.Web.Models.Mapping { protected override Udi ResolveCore(IContentTypeComposition source) { + if (source == null) return null; + return Udi.Create( source.GetType() == typeof(IMemberType) ? Constants.UdiEntityType.MemberType diff --git a/src/UmbracoExamine/UmbracoContentIndexer.cs b/src/UmbracoExamine/UmbracoContentIndexer.cs index 1798596668..e7f9acdabf 100644 --- a/src/UmbracoExamine/UmbracoContentIndexer.cs +++ b/src/UmbracoExamine/UmbracoContentIndexer.cs @@ -775,7 +775,7 @@ namespace UmbracoExamine fields.Add(NodeTypeAliasFieldName, allValuesForIndexing[NodeTypeAliasFieldName]); //guid - if (allValuesForIndexing[IconFieldName].IsNullOrWhiteSpace() == false) + if (allValuesForIndexing[NodeKeyFieldName].IsNullOrWhiteSpace() == false) { fields.Add(NodeKeyFieldName, allValuesForIndexing[NodeKeyFieldName]); } From f2be235f85ab4aa009b4ccfcd607c7f48740e2fb Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 7 Feb 2017 11:44:04 +1100 Subject: [PATCH 13/23] Fixes the db data type for UDI media picker, fixes the initial db installation data to use the new pickers. --- src/Umbraco.Core/Constants-PropertyEditors.cs | 2 +- .../Migrations/Initial/BaseDataCreation.cs | 34 ++++++++++--------- .../MediaPickerPropertyEditor.cs | 2 +- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Core/Constants-PropertyEditors.cs b/src/Umbraco.Core/Constants-PropertyEditors.cs index 832c87bbb4..189d11d3a1 100644 --- a/src/Umbraco.Core/Constants-PropertyEditors.cs +++ b/src/Umbraco.Core/Constants-PropertyEditors.cs @@ -204,7 +204,7 @@ namespace Umbraco.Core /// public const string MediaPicker2Alias = "Umbraco.MediaPicker2"; - [Obsolete("This is an obsoleted picker, use MemberPicker2Alias instead")] + [Obsolete("This is an obsoleted picker, use MediaPicker2Alias instead")] public const string MultipleMediaPickerAlias = "Umbraco.MultipleMediaPicker"; /// diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs index 3c7fc5ed42..bfd48f81e7 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs @@ -130,21 +130,21 @@ namespace Umbraco.Core.Persistence.Migrations.Initial _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.System.DefaultMembersListViewDataTypeId, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-97", SortOrder = 2, UniqueId = new Guid("AA2C52A0-CE87-4E65-A47C-7DF09358585D"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Members", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1031, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1031", SortOrder = 2, UniqueId = new Guid("f38bd2d7-65d0-48e6-95dc-87ce06ec2d3d"), Text = Constants.Conventions.MediaTypes.Folder, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now }); _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1032, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1032", SortOrder = 2, UniqueId = new Guid("cc07b313-0843-4aa8-bbda-871c8da728c8"), Text = Constants.Conventions.MediaTypes.Image, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now }); - _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1033, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1033", SortOrder = 2, UniqueId = new Guid("4c52d8ab-54e6-40cd-999c-7a5f24903e4d"), Text = Constants.Conventions.MediaTypes.File, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now }); - _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1034, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1034", SortOrder = 2, UniqueId = new Guid("a6857c73-d6e9-480c-b6e6-f15f6ad11125"), Text = "Content Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); - _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1035, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1035", SortOrder = 2, UniqueId = new Guid("93929b9a-93a2-4e2a-b239-d99334440a59"), Text = "Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); - _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1036, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1036", SortOrder = 2, UniqueId = new Guid("2b24165f-9782-4aa3-b459-1de4a4d21f60"), Text = "Member Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); + _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1033, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1033", SortOrder = 2, UniqueId = new Guid("4c52d8ab-54e6-40cd-999c-7a5f24903e4d"), Text = Constants.Conventions.MediaTypes.File, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now }); _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1040, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1040", SortOrder = 2, UniqueId = new Guid("21e798da-e06e-4eda-a511-ed257f78d4fa"), Text = "Related Links", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1041, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1041", SortOrder = 2, UniqueId = new Guid("b6b73142-b9c1-4bf8-a16d-e1c23320b549"), Text = "Tags", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1043, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1043", SortOrder = 2, UniqueId = new Guid("1df9f033-e6d4-451f-b8d2-e0cbc50a836f"), Text = "Image Cropper", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1044, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1044", SortOrder = 0, UniqueId = new Guid("d59be02f-1df9-4228-aa1e-01917d806cda"), Text = Constants.Conventions.MemberTypes.DefaultAlias, NodeObjectType = new Guid(Constants.ObjectTypes.MemberType), CreateDate = DateTime.Now }); - _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1045, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1045", SortOrder = 2, UniqueId = new Guid("7E3962CC-CE20-4FFC-B661-5897A894BA7E"), Text = "Multiple Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); + //New UDI pickers with newer Ids + _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1046, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1046", SortOrder = 2, UniqueId = new Guid("FD1E0DA5-5606-4862-B679-5D0CF3A52A59"), Text = "Content Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); + _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1047, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1047", SortOrder = 2, UniqueId = new Guid("1EA2E01F-EBD8-4CE1-8D71-6B1149E63548"), Text = "Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); + _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1048, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1048", SortOrder = 2, UniqueId = new Guid("135D60E0-64D9-49ED-AB08-893C9BA44AE5"), Text = "Member Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); + _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1049, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1049", SortOrder = 2, UniqueId = new Guid("9DBBCBBB-2327-434A-B355-AF1B84E5010A"), Text = "Multiple Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); //TODO: We're not creating these for 7.0 //_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1039, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1039", SortOrder = 2, UniqueId = new Guid("06f349a9-c949-4b6a-8660-59c10451af42"), Text = "Ultimate Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); //_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1038, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1038", SortOrder = 2, UniqueId = new Guid("1251c96c-185c-4e9b-93f4-b48205573cbd"), Text = "Simple Editor", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); - //_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1042, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1042", SortOrder = 2, UniqueId = new Guid("0a452bd5-83f9-4bc3-8403-1286e13fb77e"), Text = "Macro Container", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); } @@ -246,17 +246,19 @@ namespace Umbraco.Core.Persistence.Migrations.Initial _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 12, DataTypeId = -40, PropertyEditorAlias = Constants.PropertyEditors.RadioButtonListAlias, DbType = "Nvarchar" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 13, DataTypeId = -41, PropertyEditorAlias = Constants.PropertyEditors.DateAlias, DbType = "Date" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 14, DataTypeId = -42, PropertyEditorAlias = Constants.PropertyEditors.DropDownListAlias, DbType = "Integer" }); - _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, PropertyEditorAlias = Constants.PropertyEditors.CheckBoxListAlias, DbType = "Nvarchar" }); - _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 16, DataTypeId = 1034, PropertyEditorAlias = Constants.PropertyEditors.ContentPickerAlias, DbType = "Integer" }); - _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 18, DataTypeId = 1036, PropertyEditorAlias = Constants.PropertyEditors.MemberPickerAlias, DbType = "Integer" }); - _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 17, DataTypeId = 1035, PropertyEditorAlias = Constants.PropertyEditors.MultipleMediaPickerAlias, DbType = "Nvarchar" }); + _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, PropertyEditorAlias = Constants.PropertyEditors.CheckBoxListAlias, DbType = "Nvarchar" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 21, DataTypeId = 1040, PropertyEditorAlias = Constants.PropertyEditors.RelatedLinksAlias, DbType = "Ntext" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 22, DataTypeId = 1041, PropertyEditorAlias = Constants.PropertyEditors.TagsAlias, DbType = "Ntext" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 24, DataTypeId = 1043, PropertyEditorAlias = Constants.PropertyEditors.ImageCropperAlias, DbType = "Ntext" }); - _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 25, DataTypeId = 1045, PropertyEditorAlias = Constants.PropertyEditors.MultipleMediaPickerAlias, DbType = "Nvarchar" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -26, DataTypeId = Constants.System.DefaultContentListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" }); _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -27, DataTypeId = Constants.System.DefaultMediaListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" }); - _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -28, DataTypeId = Constants.System.DefaultMembersListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" }); + _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -28, DataTypeId = Constants.System.DefaultMembersListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" }); + + //New UDI pickers with newer Ids + _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 26, DataTypeId = 1046, PropertyEditorAlias = Constants.PropertyEditors.ContentPicker2Alias, DbType = "Nvarchar" }); + _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 27, DataTypeId = 1047, PropertyEditorAlias = Constants.PropertyEditors.MemberPicker2Alias, DbType = "Nvarchar" }); + _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 28, DataTypeId = 1048, PropertyEditorAlias = Constants.PropertyEditors.MediaPicker2Alias, DbType = "Ntext" }); + _database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 29, DataTypeId = 1049, PropertyEditorAlias = Constants.PropertyEditors.MediaPicker2Alias, DbType = "Ntext" }); //TODO: We're not creating these for 7.0 //_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 19, DataTypeId = 1038, PropertyEditorAlias = Constants.PropertyEditors.MarkdownEditorAlias, DbType = "Ntext" }); @@ -268,10 +270,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial { _database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 3, Alias = "", SortOrder = 0, DataTypeNodeId = -87, Value = ",code,undo,redo,cut,copy,mcepasteword,stylepicker,bold,italic,bullist,numlist,outdent,indent,mcelink,unlink,mceinsertanchor,mceimage,umbracomacro,mceinserttable,umbracoembed,mcecharmap,|1|1,2,3,|0|500,400|1049,|true|" }); _database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 4, Alias = "group", SortOrder = 0, DataTypeNodeId = 1041, Value = "default" }); - - //default's for MultipleMediaPickerAlias picker - _database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 5, Alias = "multiPicker", SortOrder = 0, DataTypeNodeId = 1045, Value = "1" }); - + //defaults for the member list _database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -1, Alias = "pageSize", SortOrder = 1, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "10" }); _database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -2, Alias = "orderBy", SortOrder = 2, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "username" }); @@ -288,6 +287,9 @@ namespace Umbraco.Core.Persistence.Migrations.Initial _database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -7, Alias = "orderDirection", SortOrder = 3, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "desc" }); _database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -8, Alias = "layouts", SortOrder = 4, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "[" + cardLayout + "," + listLayout + "]" }); _database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -9, Alias = "includeProperties", SortOrder = 5, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "[{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1},{\"alias\":\"owner\",\"header\":\"Updated by\",\"isSystem\":1}]" }); + + //default's for MultipleMediaPickerAlias picker + _database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 6, Alias = "multiPicker", SortOrder = 0, DataTypeNodeId = 1049, Value = "1" }); } private void CreateUmbracoRelationTypeData() diff --git a/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs index d6c8589871..3b16aa2cb7 100644 --- a/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs @@ -41,7 +41,7 @@ namespace Umbraco.Web.PropertyEditors /// /// Media picker property editors that stores UDI /// - [PropertyEditor(Constants.PropertyEditors.MediaPicker2Alias, "Media Picker", PropertyEditorValueTypes.String, "mediapicker", Group = "media", Icon = "icon-picture")] + [PropertyEditor(Constants.PropertyEditors.MediaPicker2Alias, "Media Picker", PropertyEditorValueTypes.Text, "mediapicker", Group = "media", Icon = "icon-picture")] public class MediaPickerPropertyEditor2 : PropertyEditor { public MediaPickerPropertyEditor2() From f1709f6066a1f753da7a28b54910b6886ce64033 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 7 Feb 2017 11:58:10 +1100 Subject: [PATCH 14/23] Fixes identity seed for db --- src/Umbraco.Core/Models/Rdbms/DataTypePreValueDto.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Models/Rdbms/DataTypePreValueDto.cs b/src/Umbraco.Core/Models/Rdbms/DataTypePreValueDto.cs index 652e63df0b..6e8fc29d95 100644 --- a/src/Umbraco.Core/Models/Rdbms/DataTypePreValueDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/DataTypePreValueDto.cs @@ -9,7 +9,7 @@ namespace Umbraco.Core.Models.Rdbms internal class DataTypePreValueDto { [Column("id")] - [PrimaryKeyColumn(IdentitySeed = 6)] + [PrimaryKeyColumn(IdentitySeed = 10)] public int Id { get; set; } [Column("datatypeNodeId")] From 19e4bee34e0d6e8fca5148aa13bf549af58a2e07 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 7 Feb 2017 12:02:38 +1100 Subject: [PATCH 15/23] fixes test --- .../Repositories/DataTypeDefinitionRepositoryTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs index 4db63f6085..e07c5fa9b4 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs @@ -441,7 +441,7 @@ namespace Umbraco.Tests.Persistence.Repositories { // Act - var exists = repository.Exists(1034); //Content picker + var exists = repository.Exists(1046); //Content picker var doesntExist = repository.Exists(-80); // Assert From 122295c89ff60852a5145f76131dca50cdaf7a7e Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Tue, 7 Feb 2017 13:55:49 +0000 Subject: [PATCH 16/23] Sets MacroPicker aka MacroContainer as deperecated --- src/Umbraco.Web/PropertyEditors/MacroContainerPropertyEditor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/PropertyEditors/MacroContainerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MacroContainerPropertyEditor.cs index 6bb2cda0b0..b3e5390b64 100644 --- a/src/Umbraco.Web/PropertyEditors/MacroContainerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MacroContainerPropertyEditor.cs @@ -9,7 +9,7 @@ using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { - [PropertyEditor(Constants.PropertyEditors.MacroContainerAlias, "Macro Picker", "macrocontainer", ValueType = PropertyEditorValueTypes.Text, Group="rich content", Icon="icon-settings-alt")] + [PropertyEditor(Constants.PropertyEditors.MacroContainerAlias, "Macro Picker", "macrocontainer", ValueType = PropertyEditorValueTypes.Text, Group="rich content", Icon="icon-settings-alt", IsDeprecated = true)] public class MacroContainerPropertyEditor : PropertyEditor { /// From 846ac573cc554c16297850b65e386164e3698e4a Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 8 Feb 2017 14:18:37 +1100 Subject: [PATCH 17/23] Fixes tests, ensures we don't install test data that doesn't exist --- .../TestHelpers/Entities/MockedContentTypes.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs b/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs index 85dd604203..904ec65bb0 100644 --- a/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs +++ b/src/Umbraco.Tests/TestHelpers/Entities/MockedContentTypes.cs @@ -358,9 +358,9 @@ namespace Umbraco.Tests.TestHelpers.Entities contentCollection.Add(new PropertyType(Constants.PropertyEditors.DateAlias, DataTypeDatabaseType.Date) { Alias = "date", Name = "Date", Mandatory = false, SortOrder = 13, DataTypeDefinitionId = -41 }); contentCollection.Add(new PropertyType(Constants.PropertyEditors.DropDownListAlias, DataTypeDatabaseType.Integer) { Alias = "ddl", Name = "Dropdown List", Mandatory = false, SortOrder = 14, DataTypeDefinitionId = -42 }); contentCollection.Add(new PropertyType(Constants.PropertyEditors.CheckBoxListAlias, DataTypeDatabaseType.Nvarchar) { Alias = "chklist", Name = "Checkbox List", Mandatory = false, SortOrder = 15, DataTypeDefinitionId = -43 }); - contentCollection.Add(new PropertyType(Constants.PropertyEditors.ContentPickerAlias, DataTypeDatabaseType.Integer) { Alias = "contentPicker", Name = "Content Picker", Mandatory = false, SortOrder = 16, DataTypeDefinitionId = 1034 }); - contentCollection.Add(new PropertyType(Constants.PropertyEditors.MediaPickerAlias, DataTypeDatabaseType.Integer) { Alias = "mediaPicker", Name = "Media Picker", Mandatory = false, SortOrder = 17, DataTypeDefinitionId = 1035 }); - contentCollection.Add(new PropertyType(Constants.PropertyEditors.MemberPickerAlias, DataTypeDatabaseType.Integer) { Alias = "memberPicker", Name = "Member Picker", Mandatory = false, SortOrder = 18, DataTypeDefinitionId = 1036 }); + contentCollection.Add(new PropertyType(Constants.PropertyEditors.ContentPicker2Alias, DataTypeDatabaseType.Integer) { Alias = "contentPicker", Name = "Content Picker", Mandatory = false, SortOrder = 16, DataTypeDefinitionId = 1046 }); + contentCollection.Add(new PropertyType(Constants.PropertyEditors.MediaPicker2Alias, DataTypeDatabaseType.Integer) { Alias = "mediaPicker", Name = "Media Picker", Mandatory = false, SortOrder = 17, DataTypeDefinitionId = 1048 }); + contentCollection.Add(new PropertyType(Constants.PropertyEditors.MemberPicker2Alias, DataTypeDatabaseType.Integer) { Alias = "memberPicker", Name = "Member Picker", Mandatory = false, SortOrder = 18, DataTypeDefinitionId = 1047 }); contentCollection.Add(new PropertyType(Constants.PropertyEditors.RelatedLinksAlias, DataTypeDatabaseType.Ntext) { Alias = "relatedLinks", Name = "Related Links", Mandatory = false, SortOrder = 21, DataTypeDefinitionId = 1040 }); contentCollection.Add(new PropertyType(Constants.PropertyEditors.TagsAlias, DataTypeDatabaseType.Ntext) { Alias = "tags", Name = "Tags", Mandatory = false, SortOrder = 22, DataTypeDefinitionId = 1041 }); From a20cc60c10f8a9fe0569ac0d44e893d8a59dfe6e Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 8 Feb 2017 16:15:27 +1100 Subject: [PATCH 18/23] Updates new UDI pickers that have start nodes for pre-values to also store UDIs for their prevalues, this has a knock on effect in that we need to be able to inject some server side config for pre-value editors (otherwise we'd have to make diff udi prevalue editors but that isn't very re-usable), so have implemented that and then updated all of the logic to deal with the udi idType. --- .../PropertyEditors/PreValueField.cs | 7 ++ .../datatypes/datatype.edit.controller.js | 3 +- .../prevalueeditors/mediapicker.controller.js | 21 ++++-- .../prevalueeditors/treepicker.controller.js | 32 +++++---- .../prevalueeditors/treesource.controller.js | 12 +++- .../contentpicker/contentpicker.controller.js | 12 ++-- src/Umbraco.Web/Editors/MediaController.cs | 41 +++++++++++- .../Editors/MediaTypeController.cs | 34 ++++++++-- .../ContentEditing/PreValueFieldDisplay.cs | 9 ++- .../ContentPickerPropertyEditor.cs | 41 ++++++++++-- .../MediaPickerPropertyEditor.cs | 45 +++++++++---- .../MultiNodeTreePickerPropertyEditor.cs | 66 +++++++++++++++---- .../MultipleMediaPickerPropertyEditor.cs | 12 ++++ .../Trees/ContentTreeControllerBase.cs | 11 +++- 14 files changed, 274 insertions(+), 72 deletions(-) diff --git a/src/Umbraco.Core/PropertyEditors/PreValueField.cs b/src/Umbraco.Core/PropertyEditors/PreValueField.cs index 3cf4e960ea..2b66f7a6a8 100644 --- a/src/Umbraco.Core/PropertyEditors/PreValueField.cs +++ b/src/Umbraco.Core/PropertyEditors/PreValueField.cs @@ -15,6 +15,7 @@ namespace Umbraco.Core.PropertyEditors public PreValueField() { Validators = new List(); + Config = new Dictionary(); //check for an attribute and fill the values var att = GetType().GetCustomAttribute(false); @@ -79,5 +80,11 @@ namespace Umbraco.Core.PropertyEditors /// [JsonProperty("validation", ItemConverterType = typeof(ManifestValidatorConverter))] public List Validators { get; private set; } + + /// + /// This allows for custom configuration to be injected into the pre-value editor + /// + [JsonProperty("config")] + public IDictionary Config { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/datatypes/datatype.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/datatypes/datatype.edit.controller.js index 02d5a62432..74d35201c2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/datatypes/datatype.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/datatypes/datatype.edit.controller.js @@ -27,7 +27,8 @@ function DataTypeEditController($scope, $routeParams, $location, appState, navig description: preVals[i].description, label: preVals[i].label, view: preVals[i].view, - value: preVals[i].value + value: preVals[i].value, + config: preVals[i].config, }); } } diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/mediapicker.controller.js index 38dd99c204..86e95a8794 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/mediapicker.controller.js @@ -13,9 +13,15 @@ function mediaPickerController($scope, dialogService, entityResource, $log, icon multiPicker: false, entityType: "Media", section: "media", - treeAlias: "media" + treeAlias: "media", + idType: "int" }; + //combine the dialogOptions with any values returned from the server + if ($scope.model.config) { + angular.extend(dialogOptions, $scope.model.config); + } + $scope.openContentPicker = function() { $scope.contentPickerOverlay = dialogOptions; $scope.contentPickerOverlay.view = "treePicker"; @@ -53,18 +59,21 @@ function mediaPickerController($scope, dialogService, entityResource, $log, icon }; $scope.add = function (item) { + + var itemId = dialogOptions.idType === "udi" ? item.udi : item.id; + var currIds = _.map($scope.renderModel, function (i) { - return i.id; + return dialogOptions.idType === "udi" ? i.udi : i.id; }); - if (currIds.indexOf(item.id) < 0) { + if (currIds.indexOf(itemId) < 0) { item.icon = iconHelper.convertFromLegacyIcon(item.icon); - $scope.renderModel.push({name: item.name, id: item.id, icon: item.icon}); + $scope.renderModel.push({ name: item.name, id: item.id, icon: item.icon, udi: item.udi }); } }; var unsubscribe = $scope.$on("formSubmitting", function (ev, args) { var currIds = _.map($scope.renderModel, function (i) { - return i.id; + return dialogOptions.idType === "udi" ? i.udi : i.id; }); $scope.model.value = trim(currIds.join(), ","); }); @@ -79,7 +88,7 @@ function mediaPickerController($scope, dialogService, entityResource, $log, icon entityResource.getByIds(modelIds, dialogOptions.entityType).then(function (data) { _.each(data, function (item, i) { item.icon = iconHelper.convertFromLegacyIcon(item.icon); - $scope.renderModel.push({ name: item.name, id: item.id, icon: item.icon }); + $scope.renderModel.push({ name: item.name, id: item.id, icon: item.icon, udi: item.udi }); }); }); diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.controller.js index d2ff7bd778..48edf6e3a1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.controller.js @@ -12,26 +12,29 @@ angular.module('umbraco') multiPicker: false, entityType: "Document", type: "content", - treeAlias: "content" - }; + treeAlias: "content", + idType: "int" + }; + + //combine the config with any values returned from the server + if ($scope.model.config) { + angular.extend(config, $scope.model.config); + } if($scope.model.value){ $scope.ids = $scope.model.value.split(','); entityResource.getByIds($scope.ids, config.entityType).then(function (data) { _.each(data, function (item, i) { item.icon = iconHelper.convertFromLegacyIcon(item.icon); - $scope.renderModel.push({name: item.name, id: item.id, icon: item.icon}); - }); + $scope.renderModel.push({ name: item.name, id: item.id, icon: item.icon, udi: item.udi }); + }); }); } $scope.openContentPicker = function() { - $scope.treePickerOverlay = {}; - $scope.treePickerOverlay.section = config.type; - $scope.treePickerOverlay.treeAlias = config.treeAlias; - $scope.treePickerOverlay.multiPicker = config.multiPicker; + $scope.treePickerOverlay = config; $scope.treePickerOverlay.view = "treePicker"; - $scope.treePickerOverlay.show = true; + $scope.treePickerOverlay.show = true; $scope.treePickerOverlay.submit = function(model) { @@ -64,12 +67,15 @@ angular.module('umbraco') $scope.ids = []; }; - $scope.add =function(item){ - if($scope.ids.indexOf(item.id) < 0){ + $scope.add = function (item) { + + var itemId = config.idType === "udi" ? item.udi : item.id; + + if ($scope.ids.indexOf(itemId) < 0){ item.icon = iconHelper.convertFromLegacyIcon(item.icon); - $scope.ids.push(item.id); - $scope.renderModel.push({name: item.name, id: item.id, icon: item.icon}); + $scope.ids.push(itemId); + $scope.renderModel.push({name: item.name, id: item.id, icon: item.icon, udi: item.udi}); $scope.model.value = trim($scope.ids.join(), ","); } }; diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.controller.js b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.controller.js index ff5e31b8eb..5a53e00e1c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.controller.js @@ -12,7 +12,12 @@ angular.module('umbraco') $scope.model.value = { type: "content" }; - } + } + if (!$scope.model.config) { + $scope.model.config = { + idType: "int" + }; + } if($scope.model.value.id && $scope.model.value.type !== "member"){ var ent = "Document"; @@ -29,7 +34,8 @@ angular.module('umbraco') $scope.openContentPicker =function(){ $scope.treePickerOverlay = { - view: "treepicker", + view: "treepicker", + idType: $scope.model.config.idType, section: $scope.model.value.type, treeAlias: $scope.model.value.type, multiPicker: false, @@ -67,6 +73,6 @@ angular.module('umbraco') $scope.clear(); item.icon = iconHelper.convertFromLegacyIcon(item.icon); $scope.node = item; - $scope.model.value.id = item.id; + $scope.model.value.id = $scope.model.config.idType === "udi" ? item.udi : item.id; } }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index 27df035914..01da9cda18 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -58,7 +58,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper startNode: { query: "", type: "content", - id: $scope.model.config.startNodeId ? $scope.model.config.startNodeId : -1 // get start node for simple Content Picker + id: $scope.model.config.startNodeId ? $scope.model.config.startNodeId : -1 // get start node for simple Content Picker } }; @@ -105,10 +105,11 @@ function contentPickerController($scope, entityResource, editorState, iconHelper $scope.clear(); $scope.add(data); } - angularHelper.getCurrentForm($scope).$setDirty(); + angularHelper.getCurrentForm($scope).$setDirty(); }, treeAlias: $scope.model.config.startNode.type, - section: $scope.model.config.startNode.type + section: $scope.model.config.startNode.type, + idType: "int" }; //since most of the pre-value config's are used in the dialog options (i.e. maxNumber, minNumber, etc...) we'll merge the @@ -147,9 +148,10 @@ function contentPickerController($scope, entityResource, editorState, iconHelper if ($scope.model.config.startNode.query) { var rootId = $routeParams.id; entityResource.getByQuery($scope.model.config.startNode.query, rootId, "Document").then(function (ent) { - dialogOptions.startNodeId = ent.id; + dialogOptions.startNodeId = $scope.model.config.idType === "udi" ? ent.udi : ent.id; }); - } else { + } + else { dialogOptions.startNodeId = $scope.model.config.startNode.id; } diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs index 77ab9ff6e5..0e191954d6 100644 --- a/src/Umbraco.Web/Editors/MediaController.cs +++ b/src/Umbraco.Web/Editors/MediaController.cs @@ -59,7 +59,7 @@ namespace Umbraco.Web.Editors public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor) { controllerSettings.Services.Replace(typeof(IHttpActionSelector), new ParameterSwapControllerActionSelector( - new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetChildren", "id", typeof(int), typeof(Guid), typeof(string)))); + new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetChildren", "id", typeof(int), typeof(Guid), typeof(Udi), typeof(string)))); } } @@ -187,6 +187,7 @@ namespace Umbraco.Web.Editors .Select(Mapper.Map>); } + #region GetChildren /// /// Returns the child media objects - using the entity INT id /// @@ -244,7 +245,7 @@ namespace Umbraco.Web.Editors Direction orderDirection = Direction.Ascending, bool orderBySystemField = true, string filter = "") - { + { var entity = Services.EntityService.GetByKey(id); if (entity != null) { @@ -253,6 +254,39 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(HttpStatusCode.NotFound); } + /// + /// Returns the child media objects - using the entity UDI id + /// + /// + /// + /// + /// + /// + /// + /// + /// + [FilterAllowedOutgoingMedia(typeof(IEnumerable>), "Items")] + public PagedResult> GetChildren(Udi id, + int pageNumber = 0, + int pageSize = 0, + string orderBy = "SortOrder", + Direction orderDirection = Direction.Ascending, + bool orderBySystemField = true, + string filter = "") + { + var guidUdi = id as GuidUdi; + if (guidUdi != null) + { + var entity = Services.EntityService.GetByKey(guidUdi.Guid); + if (entity != null) + { + return GetChildren(entity.Id, pageNumber, pageSize, orderBy, orderDirection, orderBySystemField, filter); + } + } + + throw new HttpResponseException(HttpStatusCode.NotFound); + } + [Obsolete("Do not use this method, use either the overload with INT or GUID instead, this will be removed in future versions")] [EditorBrowsable(EditorBrowsableState.Never)] [UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)] @@ -275,7 +309,8 @@ namespace Umbraco.Web.Editors } throw new HttpResponseException(HttpStatusCode.NotFound); - } + } + #endregion /// /// Moves an item to the recycle bin, if it is already there then it will permanently delete it diff --git a/src/Umbraco.Web/Editors/MediaTypeController.cs b/src/Umbraco.Web/Editors/MediaTypeController.cs index db2a806572..879ffd3d0a 100644 --- a/src/Umbraco.Web/Editors/MediaTypeController.cs +++ b/src/Umbraco.Web/Editors/MediaTypeController.cs @@ -40,7 +40,7 @@ namespace Umbraco.Web.Editors public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor) { controllerSettings.Services.Replace(typeof(IHttpActionSelector), new ParameterSwapControllerActionSelector( - new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetAllowedChildren", "contentId", typeof(int), typeof(Guid), typeof(string)))); + new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetAllowedChildren", "contentId", typeof(int), typeof(Guid), typeof(Udi), typeof(string)))); } } @@ -187,6 +187,7 @@ namespace Umbraco.Web.Editors } + #region GetAllowedChildren /// /// Returns the allowed child content type objects for the content item id passed in - based on an INT id /// @@ -247,10 +248,30 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(HttpStatusCode.NotFound); } - - [Obsolete("Do not use this method, use either the overload with INT or GUID instead, this will be removed in future versions")] + + /// + /// Returns the allowed child content type objects for the content item id passed in - based on a UDI id + /// + /// + [UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)] + public IEnumerable GetAllowedChildren(Udi contentId) + { + var guidUdi = contentId as GuidUdi; + if (guidUdi != null) + { + var entity = ApplicationContext.Services.EntityService.GetByKey(guidUdi.Guid); + if (entity != null) + { + return GetAllowedChildren(entity.Id); + } + } + + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + [Obsolete("Do not use this method, use either the overload with INT, GUID or UDI instead, this will be removed in future versions")] [EditorBrowsable(EditorBrowsableState.Never)] - [UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)] + [UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)] public IEnumerable GetAllowedChildren(string contentId) { foreach (var type in new[] { typeof(int), typeof(Guid) }) @@ -260,11 +281,12 @@ namespace Umbraco.Web.Editors { //oooh magic! will auto select the right overload return GetAllowedChildren((dynamic)parsed.Result); - } + } } throw new HttpResponseException(HttpStatusCode.NotFound); - } + } + #endregion /// /// Move the media type diff --git a/src/Umbraco.Web/Models/ContentEditing/PreValueFieldDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/PreValueFieldDisplay.cs index 1e8a7ba088..6879701bde 100644 --- a/src/Umbraco.Web/Models/ContentEditing/PreValueFieldDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/PreValueFieldDisplay.cs @@ -1,4 +1,5 @@ -using System.Runtime.Serialization; +using System.Collections.Generic; +using System.Runtime.Serialization; namespace Umbraco.Web.Models.ContentEditing { @@ -33,5 +34,11 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "view", IsRequired = true)] public string View { get; set; } + /// + /// This allows for custom configuration to be injected into the pre-value editor + /// + [DataMember(Name = "config")] + public IDictionary Config { get; set; } + } } \ No newline at end of file diff --git a/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs index 4f798dc41e..ef66f8740e 100644 --- a/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ContentPickerPropertyEditor.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Umbraco.Core; using Umbraco.Core.PropertyEditors; @@ -16,7 +17,18 @@ namespace Umbraco.Web.PropertyEditors public ContentPickerPropertyEditor() { InternalPreValues["idType"] = "int"; - } + } + + /// + /// overridden to change the pre-value picker to use INT ids + /// + /// + protected override PreValueEditor CreatePreValueEditor() + { + var preValEditor = base.CreatePreValueEditor(); + preValEditor.Fields.Single(x => x.Key == "startNodeId").Config["idType"] = "int"; + return preValEditor; + } } /// @@ -52,12 +64,27 @@ namespace Umbraco.Web.PropertyEditors internal class ContentPickerPreValueEditor : PreValueEditor { - [PreValueField("showOpenButton", "Show open button (this feature is in preview!)", "boolean", Description = " Opens the node in a dialog")] - public string ShowOpenButton { get; set; } - - [PreValueField("startNodeId", "Start node", "treepicker")] - public int StartNodeId { get; set; } - + public ContentPickerPreValueEditor() + { + //create the fields + Fields.Add(new PreValueField() + { + Key = "showOpenButton", + View = "boolean", + Name = "Show open button (this feature is in preview!)", + Description = "Opens the node in a dialog" + }); + Fields.Add(new PreValueField() + { + Key = "startNodeId", + View = "treepicker", + Name = "Start node", + Config = new Dictionary + { + {"idType", "udi"} + } + }); + } } } } \ No newline at end of file diff --git a/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs index 3b16aa2cb7..5da7bf38eb 100644 --- a/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs @@ -67,17 +67,40 @@ namespace Umbraco.Web.PropertyEditors internal class MediaPickerPreValueEditor : PreValueEditor { - [PreValueField("multiPicker", "Pick multiple items", "boolean")] - public bool MultiPicker { get; set; } - - [PreValueField("onlyImages", "Pick only images", "boolean", Description = "Only let the editor choose images from media.")] - public bool OnlyImages { get; set; } - - [PreValueField("disableFolderSelect", "Disable folder select", "boolean", Description = "Do not allow folders to be picked.")] - public bool DisableFolderSelect { get; set; } - - [PreValueField("startNodeId", "Start node", "mediapicker")] - public int StartNodeId { get; set; } + public MediaPickerPreValueEditor() + { + //create the fields + Fields.Add(new PreValueField() + { + Key = "multiPicker", + View = "boolean", + Name = "Pick multiple items" + }); + Fields.Add(new PreValueField() + { + Key = "onlyImages", + View = "boolean", + Name = "Pick only images", + Description = "Only let the editor choose images from media." + }); + Fields.Add(new PreValueField() + { + Key = "disableFolderSelect", + View = "boolean", + Name = "Disable folder select", + Description = "Do not allow folders to be picked." + }); + Fields.Add(new PreValueField() + { + Key = "startNodeId", + View = "mediapicker", + Name = "Start node", + Config = new Dictionary + { + {"idType", "udi"} + } + }); + } } } } diff --git a/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs index c3e257962a..fbba130543 100644 --- a/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; @@ -14,6 +15,17 @@ namespace Umbraco.Web.PropertyEditors { InternalPreValues["idType"] = "int"; } + + /// + /// overridden to change the pre-value picker to use INT ids + /// + /// + protected override PreValueEditor CreatePreValueEditor() + { + var preValEditor = base.CreatePreValueEditor(); + preValEditor.Fields.Single(x => x.Key == "startNode").Config["idType"] = "int"; + return preValEditor; + } } [PropertyEditor(Constants.PropertyEditors.MultiNodeTreePicker2Alias, "Multinode Treepicker", PropertyEditorValueTypes.Text, "contentpicker", Group="pickers", Icon="icon-page-add")] @@ -45,20 +57,46 @@ namespace Umbraco.Web.PropertyEditors internal class MultiNodePickerPreValueEditor : PreValueEditor { - [PreValueField("startNode", "Node type", "treesource")] - public string StartNode { get; set; } - - [PreValueField("filter", "Allow items of type", "textstring", Description = "Separate with comma")] - public string Filter { get; set; } - - [PreValueField("minNumber", "Minimum number of items", "number")] - public string MinNumber { get; set; } - - [PreValueField("maxNumber", "Maximum number of items", "number")] - public string MaxNumber { get; set; } - - [PreValueField("showOpenButton", "Show open button (this feature is in preview!)", "boolean", Description = " Opens the node in a dialog")] - public string ShowOpenButton { get; set; } + public MultiNodePickerPreValueEditor() + { + //create the fields + Fields.Add(new PreValueField() + { + Key = "startNode", + View = "treesource", + Name = "Node type", + Config = new Dictionary + { + {"idType", "udi"} + } + }); + Fields.Add(new PreValueField() + { + Key = "filter", + View = "textstring", + Name = "Allow items of type", + Description = "Separate with comma" + }); + Fields.Add(new PreValueField() + { + Key = "minNumber", + View = "number", + Name = "Minimum number of items" + }); + Fields.Add(new PreValueField() + { + Key = "maxNumber", + View = "number", + Name = "Maximum number of items" + }); + Fields.Add(new PreValueField() + { + Key = "showOpenButton", + View = "boolean", + Name = "Show open button (this feature is in preview!)", + Description = "Opens the node in a dialog" + }); + } /// /// This ensures the multiPicker pre-val is set based on the maxNumber of nodes set diff --git a/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs index 716e71711f..8bd23a24a6 100644 --- a/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using Umbraco.Core; using Umbraco.Core.PropertyEditors; @@ -12,6 +13,17 @@ namespace Umbraco.Web.PropertyEditors { //clear the pre-values so it defaults to a multiple picker. InternalPreValues.Clear(); + } + + /// + /// overridden to change the pre-value picker to use INT ids + /// + /// + protected override PreValueEditor CreatePreValueEditor() + { + var preValEditor = base.CreatePreValueEditor(); + preValEditor.Fields.Single(x => x.Key == "startNodeId").Config["idType"] = "int"; + return preValEditor; } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs index 5e8172b29f..2a5e28496e 100644 --- a/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs +++ b/src/Umbraco.Web/Trees/ContentTreeControllerBase.cs @@ -300,24 +300,31 @@ namespace Umbraco.Web.Trees } /// - /// Get an entity via an id that can be either an integer or a Guid + /// Get an entity via an id that can be either an integer, Guid or UDI /// /// /// internal IUmbracoEntity GetEntityFromId(string id) { IUmbracoEntity entity; + Guid idGuid = Guid.Empty; int idInt; + Udi idUdi; + if (Guid.TryParse(id, out idGuid)) { entity = Services.EntityService.GetByKey(idGuid, UmbracoObjectType); - } else if (int.TryParse(id, out idInt)) { entity = Services.EntityService.Get(idInt, UmbracoObjectType); } + else if (Udi.TryParse(id, out idUdi)) + { + var guidUdi = idUdi as GuidUdi; + entity = guidUdi != null ? Services.EntityService.GetByKey(guidUdi.Guid, UmbracoObjectType) : null; + } else { return null; From a898c2d69792493e16ec698e836e5fabb2b5826a Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 10 Feb 2017 10:36:48 +1100 Subject: [PATCH 19/23] Fixes ParameterSwapControllerActionSelector when there is an empty parameter (not null but without a value) --- .../ParameterSwapControllerActionSelector.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs b/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs index 3cb94ef8e6..53e25c146a 100644 --- a/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs +++ b/src/Umbraco.Web/Editors/ParameterSwapControllerActionSelector.cs @@ -97,10 +97,20 @@ namespace Umbraco.Web.Editors { var requestParam = HttpUtility.ParseQueryString(controllerContext.Request.RequestUri.Query).Get(found.ParamName); - if (requestParam != null) + requestParam = (requestParam == null) ? null : requestParam.Trim(); + var paramTypes = found.SupportedTypes; + + if (requestParam == string.Empty && paramTypes.Length > 0) { - var paramTypes = found.SupportedTypes; - + //if it's empty then in theory we can select any of the actions since they'll all need to deal with empty or null parameters + //so we'll try to use the first one available + method = MatchByType(paramTypes[0], controllerContext, found); + if (method != null) + return true; + } + + if (requestParam != null) + { foreach (var paramType in paramTypes) { //check if this is IEnumerable and if so this will get it's type From bc1758f56978646d0e24f22f9b84a535d70e4342 Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 10 Feb 2017 10:45:35 +1100 Subject: [PATCH 20/23] Updates the content picker to not make an unneeded request --- .../contentpicker/contentpicker.controller.js | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index 01da9cda18..471e97e875 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -241,26 +241,36 @@ function contentPickerController($scope, entityResource, editorState, iconHelper unsubscribe(); }); - //load current data + var modelIds = $scope.model.value ? $scope.model.value.split(',') : []; - entityResource.getByIds(modelIds, entityType).then(function (data) { + //load current data if anything selected + if (modelIds.length > 0) { + entityResource.getByIds(modelIds, entityType).then(function(data) { - _.each(modelIds, function (id, i) { - var entity = _.find(data, function (d) { - return $scope.model.config.idType === "udi" ? (d.udi == id) : (d.id == id); - }); - - if (entity) { - setEntityUrl(entity); - } - - }); + _.each(modelIds, + function(id, i) { + var entity = _.find(data, + function(d) { + return $scope.model.config.idType === "udi" ? (d.udi == id) : (d.id == id); + }); + if (entity) { + setEntityUrl(entity); + } + + }); + + //everything is loaded, start the watch on the model + startWatch(); + + }); + } + else { //everything is loaded, start the watch on the model startWatch(); - - }); + } + function setEntityUrl(entity) { From 2652a583e0d6c4b0061fd6adcfb5336858219fbd Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 10 Feb 2017 10:48:43 +1100 Subject: [PATCH 21/23] updates mediapicker.controller pre value to not make an uneeded request --- .../views/prevalueeditors/mediapicker.controller.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/mediapicker.controller.js index 86e95a8794..e5c09f420e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/mediapicker.controller.js @@ -85,12 +85,15 @@ function mediaPickerController($scope, dialogService, entityResource, $log, icon //load media data var modelIds = $scope.model.value ? $scope.model.value.split(',') : []; - entityResource.getByIds(modelIds, dialogOptions.entityType).then(function (data) { - _.each(data, function (item, i) { - item.icon = iconHelper.convertFromLegacyIcon(item.icon); - $scope.renderModel.push({ name: item.name, id: item.id, icon: item.icon, udi: item.udi }); + if (modelIds.length > 0) { + entityResource.getByIds(modelIds, dialogOptions.entityType).then(function (data) { + _.each(data, function (item, i) { + item.icon = iconHelper.convertFromLegacyIcon(item.icon); + $scope.renderModel.push({ name: item.name, id: item.id, icon: item.icon, udi: item.udi }); + }); }); - }); + } + } From 90b43584d2e59d452b86eedeb7a6e96604769343 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 13 Feb 2017 19:57:21 +1100 Subject: [PATCH 22/23] Oops, fixes issue with attemping to reduce code but the 'section' parameter isn't the same in the config 'type' so needs to be manually applied like it was before. Fixes MultipleMediaPickerPropertyEditor to be multiple by default (is a bug in current versions too) --- .../src/views/prevalueeditors/treepicker.controller.js | 3 ++- .../PropertyEditors/MultipleMediaPickerPropertyEditor.cs | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.controller.js index 48edf6e3a1..cf81d1cda6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.controller.js @@ -32,7 +32,8 @@ angular.module('umbraco') } $scope.openContentPicker = function() { - $scope.treePickerOverlay = config; + $scope.treePickerOverlay = config; + $scope.treePickerOverlay.section = config.type; $scope.treePickerOverlay.view = "treePicker"; $scope.treePickerOverlay.show = true; diff --git a/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs index 8bd23a24a6..12aec22e31 100644 --- a/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultipleMediaPickerPropertyEditor.cs @@ -7,12 +7,12 @@ namespace Umbraco.Web.PropertyEditors { [Obsolete("This editor is obsolete, use MultipleMediaPickerPropertyEditor2 instead which stores UDI")] [PropertyEditor(Constants.PropertyEditors.MultipleMediaPickerAlias, "(Obsolete) Media Picker", "mediapicker", Group = "media", Icon = "icon-pictures-alt-2", IsDeprecated = true)] - public class MultipleMediaPickerPropertyEditor : MediaPickerPropertyEditor + public class MultipleMediaPickerPropertyEditor : MediaPickerPropertyEditor2 { public MultipleMediaPickerPropertyEditor() { - //clear the pre-values so it defaults to a multiple picker. - InternalPreValues.Clear(); + //default it to multi picker + InternalPreValues["multiPicker"] = "1"; } /// From c9294e5281f3bda736b4d30460eaa45eed280e55 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Tue, 14 Feb 2017 11:37:42 +0000 Subject: [PATCH 23/23] In the init DB creation the Media & Member Picker was inserted into the DB the wrong way round - now assigned with the correct name for the DataType --- .../Persistence/Migrations/Initial/BaseDataCreation.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs index bfd48f81e7..7dc57ba7f6 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs @@ -138,8 +138,8 @@ namespace Umbraco.Core.Persistence.Migrations.Initial //New UDI pickers with newer Ids _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1046, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1046", SortOrder = 2, UniqueId = new Guid("FD1E0DA5-5606-4862-B679-5D0CF3A52A59"), Text = "Content Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); - _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1047, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1047", SortOrder = 2, UniqueId = new Guid("1EA2E01F-EBD8-4CE1-8D71-6B1149E63548"), Text = "Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); - _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1048, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1048", SortOrder = 2, UniqueId = new Guid("135D60E0-64D9-49ED-AB08-893C9BA44AE5"), Text = "Member Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); + _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1047, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1047", SortOrder = 2, UniqueId = new Guid("1EA2E01F-EBD8-4CE1-8D71-6B1149E63548"), Text = "Member Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); + _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1048, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1048", SortOrder = 2, UniqueId = new Guid("135D60E0-64D9-49ED-AB08-893C9BA44AE5"), Text = "Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); _database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1049, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1049", SortOrder = 2, UniqueId = new Guid("9DBBCBBB-2327-434A-B355-AF1B84E5010A"), Text = "Multiple Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now }); //TODO: We're not creating these for 7.0