From ceb3ae361afabc0b1cd353fed4bd9a620314bdc0 Mon Sep 17 00:00:00 2001 From: Niels Hartvig Date: Tue, 6 Mar 2018 11:07:08 +0100 Subject: [PATCH] Adds flexible dropdown editor to replace the four current ones --- src/Umbraco.Core/Constants-PropertyEditors.cs | 7 +- .../dropdownFlexible.controller.js | 81 ++++++++++++++++++ .../dropdownFlexible/dropdownFlexible.html | 19 +++++ .../DropdownFlexiblePropertyEditor.cs | 83 +++++++++++++++++++ src/Umbraco.Web/Umbraco.Web.csproj | 1 + 5 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.html create mode 100644 src/Umbraco.Web/PropertyEditors/DropdownFlexiblePropertyEditor.cs diff --git a/src/Umbraco.Core/Constants-PropertyEditors.cs b/src/Umbraco.Core/Constants-PropertyEditors.cs index 1f3986eeaf..43779ea44a 100644 --- a/src/Umbraco.Core/Constants-PropertyEditors.cs +++ b/src/Umbraco.Core/Constants-PropertyEditors.cs @@ -122,6 +122,11 @@ namespace Umbraco.Core /// Alias for the Dropdown list, publishing keys datatype. /// public const string DropdownlistPublishingKeysAlias = "Umbraco.DropdownlistPublishingKeys"; + + /// + /// Alias for the "new" Dropdown list, that replaces the old four deprecated ones and works as other list based property editors + /// + public const string DropDownListFlexibleAlias = "Umbraco.DropDown.Flexible"; /// /// Guid for the Folder browser datatype. @@ -452,4 +457,4 @@ namespace Umbraco.Core } } } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js new file mode 100644 index 0000000000..72efc00738 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js @@ -0,0 +1,81 @@ +angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownFlexibleController", + function($scope) { + + //setup the default config + var config = { + items: [], + multiple: false + }; + + //map the user config + angular.extend(config, $scope.model.config); + + //map back to the model + $scope.model.config = config; + + function convertArrayToDictionaryArray(model){ + //now we need to format the items in the dictionary because we always want to have an array + var newItems = []; + for (var i = 0; i < model.length; i++) { + newItems.push({ id: model[i], sortOrder: 0, value: model[i] }); + } + + return newItems; + } + + + function convertObjectToDictionaryArray(model){ + //now we need to format the items in the dictionary because we always want to have an array + var newItems = []; + var vals = _.values($scope.model.config.items); + var keys = _.keys($scope.model.config.items); + + for (var i = 0; i < vals.length; i++) { + var label = vals[i].value ? vals[i].value : vals[i]; + newItems.push({ id: keys[i], sortOrder: vals[i].sortOrder, value: label }); + } + + return newItems; + } + + $scope.updateSingleDropdownValue = function() { + $scope.model.value = [$scope.model.singleDropdownValue]; + } + + if (angular.isArray($scope.model.config.items)) { + //PP: I dont think this will happen, but we have tests that expect it to happen.. + //if array is simple values, convert to array of objects + if(!angular.isObject($scope.model.config.items[0])){ + $scope.model.config.items = convertArrayToDictionaryArray($scope.model.config.items); + } + } + else if (angular.isObject($scope.model.config.items)) { + $scope.model.config.items = convertObjectToDictionaryArray($scope.model.config.items); + } + else { + throw "The items property must be either an array or a dictionary"; + } + + + //sort the values + $scope.model.config.items.sort(function (a, b) { return (a.sortOrder > b.sortOrder) ? 1 : ((b.sortOrder > a.sortOrder) ? -1 : 0); }); + + //now we need to check if the value is null/undefined, if it is we need to set it to "" so that any value that is set + // to "" gets selected by default + if ($scope.model.value === null || $scope.model.value === undefined) { + if ($scope.model.config.multiple) { + $scope.model.value = []; + } + else { + $scope.model.value = ""; + } + } + + // if we run in single mode we'll store the value in a local variable + // so we can pass an array as the model as our PropertyValueEditor expects that + $scope.model.singleDropdownValue = ""; + if ($scope.model.config.multiple === false) { + $scope.model.singleDropdownValue = $scope.model.value; + } + + }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.html new file mode 100644 index 0000000000..a68a614ad1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.html @@ -0,0 +1,19 @@ +
+ + + + + +
diff --git a/src/Umbraco.Web/PropertyEditors/DropdownFlexiblePropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DropdownFlexiblePropertyEditor.cs new file mode 100644 index 0000000000..f64b48541d --- /dev/null +++ b/src/Umbraco.Web/PropertyEditors/DropdownFlexiblePropertyEditor.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json.Linq; +using Umbraco.Core; +using Umbraco.Core.Models; +using Umbraco.Core.PropertyEditors; + +namespace Umbraco.Web.PropertyEditors +{ + [PropertyEditor(Constants.PropertyEditors.DropDownListFlexibleAlias, "Dropdown", "dropdownFlexible", Group = "lists", Icon = "icon-indent")] + public class DropdownFlexiblePropertyEditor : PropertyEditor + { + private static readonly string _multipleKey = "multiple"; + + /// + /// Return a custom pre-value editor + /// + /// + /// + /// We are just going to re-use the ValueListPreValueEditor + /// + protected override PreValueEditor CreatePreValueEditor() + { + return new DropdownFlexiblePreValueEditor(); + } + + /// + /// We need to override the value editor so that we can ensure the string value is published in cache and not the integer ID value. + /// + /// + protected override PropertyValueEditor CreateValueEditor() + { + return new PublishValuesMultipleValueEditor(false, base.CreateValueEditor()); + } + + internal class DropdownFlexiblePreValueEditor : ValueListPreValueEditor + { + public DropdownFlexiblePreValueEditor() + { + Fields.Insert(0, new PreValueField + { + Key = "multiple", + Name = "Enable multiple choice", + Description = "When checked, the dropdown will be a select multiple /combobox style dropdown", + View = "boolean" + }); + } + + public override IDictionary ConvertEditorToDb(IDictionary editorValue, PreValueCollection currentValue) + { + + var result = base.ConvertEditorToDb(editorValue, currentValue); + + // get multiple config + result.Add(_multipleKey, new PreValue(-1, editorValue[_multipleKey].ToString())); + + return result; + } + + public override IDictionary ConvertDbToEditor(IDictionary defaultPreVals, PreValueCollection persistedPreVals) + { + // weird way, but as the value stored is 0 or 1 need to do it this way + string multipleMode = "0"; + if (persistedPreVals != null && persistedPreVals.PreValuesAsDictionary[_multipleKey] != null) + { + multipleMode = persistedPreVals.PreValuesAsDictionary[_multipleKey].Value; + + // remove from the collection sent to the base multiple values collection + persistedPreVals.PreValuesAsDictionary.Remove(_multipleKey); + } + + var returnVal = base.ConvertDbToEditor(defaultPreVals, persistedPreVals); + + returnVal[_multipleKey] = multipleMode; + return returnVal; + } + + } + } +} diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index c6d528bb3d..d11475c0fb 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -337,6 +337,7 @@ +