diff --git a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs index 08d1cc8f4f..0cd6ac8b16 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/UmbracoPlan.cs @@ -128,7 +128,12 @@ namespace Umbraco.Core.Migrations.Upgrade To("{38C809D5-6C34-426B-9BEA-EFD39162595C}"); To("{6017F044-8E70-4E10-B2A3-336949692ADD}"); To("{98339BEF-E4B2-48A8-B9D1-D173DC842BBE}"); - To("{CDBEDEE4-9496-4903-9CF2-4104E00FF960}"); + + Merge() + .To("{CDBEDEE4-9496-4903-9CF2-4104E00FF960}") + .With() + .To("{940FD19A-00A8-4D5C-B8FF-939143585726}") + .As("{0576E786-5C30-4000-B969-302B61E90CA3}"); //FINAL diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/RadioAndCheckboxAndDropdownPropertyEditorsMigration.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/RadioAndCheckboxAndDropdownPropertyEditorsMigration.cs new file mode 100644 index 0000000000..5327a344a4 --- /dev/null +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/RadioAndCheckboxAndDropdownPropertyEditorsMigration.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; +using Umbraco.Core.Logging; +using Umbraco.Core.Models; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Dtos; +using Umbraco.Core.PropertyEditors; + +namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 +{ + public class RadioAndCheckboxAndDropdownPropertyEditorsMigration : MigrationBase + { + public RadioAndCheckboxAndDropdownPropertyEditorsMigration(IMigrationContext context) + : base(context) + { + } + + public override void Migrate() + { + var refreshCache = false; + + refreshCache |= Migrate(Constants.PropertyEditors.Aliases.RadioButtonList, (dto, configuration) => UpdateRadioOrCheckboxPropertyDataDto(dto, configuration, true)); + refreshCache |= Migrate(Constants.PropertyEditors.Aliases.CheckBoxList, (dto, configuration) => UpdateRadioOrCheckboxPropertyDataDto(dto, configuration, false)); + refreshCache |= Migrate(Constants.PropertyEditors.Aliases.DropDownListFlexible, UpdateDropDownPropertyDataDto); + + if (refreshCache) + { + //FIXME: trigger cache rebuild. Currently the data in the database tables is wrong. + } + } + + private bool Migrate(string editorAlias, Func updateRadioPropertyDataFunc) + { + var refreshCache = false; + var dataTypes = GetDataTypes(editorAlias); + + foreach (var dataType in dataTypes) + { + ValueListConfiguration config; + + if (dataType.Configuration.IsNullOrWhiteSpace()) + continue; + + // parse configuration, and update everything accordingly + try + { + config = (ValueListConfiguration) new ValueListConfigurationEditor().FromDatabase( + dataType.Configuration); + } + catch (Exception ex) + { + Logger.Error( + ex, + "Invalid radio button configuration detected: \"{Configuration}\", cannot convert editor, values will be cleared", + dataType.Configuration); + + continue; + } + + // get property data dtos + var propertyDataDtos = Database.Fetch(Sql() + .Select() + .From() + .InnerJoin() + .On((pt, pd) => pt.Id == pd.PropertyTypeId) + .InnerJoin() + .On((dt, pt) => dt.NodeId == pt.DataTypeId) + .Where(x => x.DataTypeId == dataType.NodeId)); + + // update dtos + var updatedDtos = propertyDataDtos.Where(x => updateRadioPropertyDataFunc(x, config)); + + // persist changes + foreach (var propertyDataDto in updatedDtos) Database.Update(propertyDataDto); + + UpdateDataType(dataType); + refreshCache = true; + } + + return refreshCache; + } + + private List GetDataTypes(string editorAlias) + { + //need to convert the old drop down data types to use the new one + var dataTypes = Database.Fetch(Sql() + .Select() + .From() + .Where(x => x.EditorAlias == editorAlias)); + return dataTypes; + } + + private void UpdateDataType(DataTypeDto dataType) + { + dataType.DbType = ValueStorageType.Nvarchar.ToString(); + Database.Update(dataType); + } + + private bool UpdateRadioOrCheckboxPropertyDataDto(PropertyDataDto propData, ValueListConfiguration config, bool singleValue) + { + //Get the INT ids stored for this property/drop down + int[] ids = null; + if (!propData.VarcharValue.IsNullOrWhiteSpace()) + { + ids = ConvertStringValues(propData.VarcharValue); + } + else if (!propData.TextValue.IsNullOrWhiteSpace()) + { + ids = ConvertStringValues(propData.TextValue); + } + else if (propData.IntegerValue.HasValue) + { + ids = new[] {propData.IntegerValue.Value}; + } + + //if there are INT ids, convert them to values based on the configuration + if (ids == null || ids.Length <= 0) return false; + + //map the ids to values + var values = new List(); + var canConvert = true; + + foreach (var id in ids) + { + var val = config.Items.FirstOrDefault(x => x.Id == id); + if (val != null) + values.Add(val.Value); + else + { + Logger.Warn( + "Could not find associated data type configuration for stored Id {DataTypeId}", id); + canConvert = false; + } + } + + if (!canConvert) return false; + + //The radio button only supports selecting a single value, so if there are multiple for some insane reason we can only use the first + propData.VarcharValue = singleValue ? values[0] : JsonConvert.SerializeObject(values); + propData.TextValue = null; + propData.IntegerValue = null; + return true; + } + + private bool UpdateDropDownPropertyDataDto(PropertyDataDto propData, ValueListConfiguration config) + { + //Get the INT ids stored for this property/drop down + var values = propData.VarcharValue.Split(new []{","}, StringSplitOptions.RemoveEmptyEntries); + + //if there are INT ids, convert them to values based on the configuration + if (values == null || values.Length <= 0) return false; + + //The radio button only supports selecting a single value, so if there are multiple for some insane reason we can only use the first + propData.VarcharValue = JsonConvert.SerializeObject(values); + propData.TextValue = null; + propData.IntegerValue = null; + return true; + } + + private int[] ConvertStringValues(string val) + { + var splitVals = val.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries); + + var intVals = splitVals + .Select(x => int.TryParse(x, out var i) ? i : int.MinValue) + .Where(x => x != int.MinValue) + .ToArray(); + + //only return if the number of values are the same (i.e. All INTs) + if (splitVals.Length == intVals.Length) + return intVals; + + return null; + } + + private class ValueListConfigurationEditor : ConfigurationEditor + { + } + } +} diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/CheckboxListValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/CheckboxListValueConverter.cs index 4062ed7311..3d69c37b8b 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/CheckboxListValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/CheckboxListValueConverter.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Newtonsoft.Json; using Umbraco.Core.Models.PublishedContent; namespace Umbraco.Core.PropertyEditors.ValueConverters @@ -8,8 +9,6 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters [DefaultPropertyValueConverter] public class CheckboxListValueConverter : PropertyValueConverterBase { - private static readonly char[] Comma = { ',' }; - public override bool IsConverter(PublishedPropertyType propertyType) => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.CheckBoxList); @@ -26,7 +25,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters if (string.IsNullOrEmpty(sourceString)) return Enumerable.Empty(); - return sourceString.Split(Comma, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()); + return JsonConvert.DeserializeObject(sourceString); } } } diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/RadioButtonListValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/RadioButtonListValueConverter.cs index 362c88d08c..b99cc7e0e3 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/RadioButtonListValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/RadioButtonListValueConverter.cs @@ -10,17 +10,17 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters => propertyType.EditorAlias.InvariantEquals(Constants.PropertyEditors.Aliases.RadioButtonList); public override Type GetPropertyValueType(PublishedPropertyType propertyType) - => typeof (int); + => typeof (string); public override PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType) => PropertyCacheLevel.Element; public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview) { - var intAttempt = source.TryConvertTo(); + var attempt = source.TryConvertTo(); - if (intAttempt.Success) - return intAttempt.Result; + if (attempt.Success) + return attempt.Result; return null; } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 57aee5ffbf..f6e8a9c9de 100755 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -387,6 +387,7 @@ + diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs index 7ec23158f6..43c1a83d33 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueConverterTests.cs @@ -65,9 +65,9 @@ namespace Umbraco.Tests.PropertyEditors Assert.AreEqual(expected, result); } - [TestCase("apples", new[] { "apples" })] - [TestCase("apples,oranges", new[] { "apples", "oranges" })] - [TestCase(" apples, oranges, pears ", new[] { "apples", "oranges", "pears" })] + [TestCase("[\"apples\"]", new[] { "apples" })] + [TestCase("[\"apples\",\"oranges\"]", new[] { "apples", "oranges" })] + [TestCase("[\"apples\",\"oranges\",\"pears\"]", new[] { "apples", "oranges", "pears" })] [TestCase("", new string[] { })] [TestCase(null, new string[] { })] public void CanConvertCheckboxListPropertyEditor(object value, IEnumerable expected) @@ -78,9 +78,9 @@ namespace Umbraco.Tests.PropertyEditors Assert.AreEqual(expected, result); } - [TestCase("apples", new[] { "apples" })] - [TestCase("apples,oranges", new[] { "apples", "oranges" })] - [TestCase("apples , oranges, pears ", new[] { "apples", "oranges", "pears" })] + [TestCase("[\"apples\"]", new[] { "apples" })] + [TestCase("[\"apples\",\"oranges\"]", new[] { "apples", "oranges" })] + [TestCase("[\"apples\",\"oranges\",\"pears\"]", new[] { "apples", "oranges", "pears" })] [TestCase("", new string[] { })] [TestCase(null, new string[] { })] public void CanConvertDropdownListMultiplePropertyEditor(object value, IEnumerable expected) @@ -104,7 +104,7 @@ namespace Umbraco.Tests.PropertyEditors Assert.AreEqual(expected, result); } - + [TestCase("1", 1)] [TestCase("1", 1)] [TestCase("0", 0)] diff --git a/src/Umbraco.Web.UI.Client/src/less/buttons.less b/src/Umbraco.Web.UI.Client/src/less/buttons.less index c6a8447342..7fd62e31c7 100644 --- a/src/Umbraco.Web.UI.Client/src/less/buttons.less +++ b/src/Umbraco.Web.UI.Client/src/less/buttons.less @@ -191,13 +191,13 @@ input[type="button"] { .btn-success { .buttonBackground(@btnSuccessBackground, @btnSuccessBackgroundHighlight, @btnSuccessType); } -// Info appears as a neutral blue +// Info appears as a sand color .btn-info { - .buttonBackground(@sand-5, @blueDark, @blueExtraDark, @u-white); + .buttonBackground(@sand-5, @sand-6, @blueExtraDark, @blueMid); } // Made for Umbraco, 2019 .btn-action { - .buttonBackground(@blueExtraDark, @blueDark, @pinkLight, @u-white); + .buttonBackground(@blueExtraDark, @blueDark, @white, @u-white); } // Made for Umbraco, 2019 .btn-selection { @@ -236,11 +236,11 @@ input[type="button"] { padding: 15px 50px; font-size: 16px; border: none; - background: @green; + background: @ui-btn-positive; color: @white; font-weight: bold; &:hover { - background: @green-d1; + background: @ui-btn-positive-hover; } } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/editor/subheader/umb-editor-sub-header.less b/src/Umbraco.Web.UI.Client/src/less/components/editor/subheader/umb-editor-sub-header.less index 2b9f1e31a5..1aadb1c39b 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/editor/subheader/umb-editor-sub-header.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/editor/subheader/umb-editor-sub-header.less @@ -15,6 +15,13 @@ } } +.umb-editor-sub-header.--state-selection { + padding-left: 10px; + padding-right: 10px; + background-color: @pinkLight; + border-radius: 3px; +} + .umb-editor-sub-header.-umb-sticky-bar { box-shadow: 0 6px 3px -3px rgba(0,0,0,.16); transition: box-shadow 1s; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-cards.less b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-cards.less index de2dca5f91..e24f68078b 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-cards.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-cards.less @@ -8,6 +8,8 @@ box-sizing: border-box; max-width: 100%; display: flex; + position: relative; + user-select: none; } .umb-user-card:hover, @@ -15,6 +17,22 @@ outline: none; text-decoration: none !important; } +.umb-user-card.-selected { + &::before { + content: ""; + position: absolute; + z-index:2; + top: -2px; + left: -2px; + right: -2px; + bottom: -2px; + border: 2px solid @ui-selected-border; + border-radius: 5px; + box-shadow: 0 0 4px 0 darken(@ui-selected-border, 20), inset 0 0 2px 0 darken(@ui-selected-border, 20); + pointer-events: none; + } + +} .umb-user-card__content { position: relative; @@ -30,9 +48,12 @@ max-width: 100%; } -.umb-user-card__content:hover, -.umb-user-card:focus .umb-user-card__content { - border-color: @turquoise; +.umb-user-card__goToUser { + &:hover { + .umb-user-card__name { + text-decoration: underline; + } + } } .umb-user-card__avatar { @@ -47,24 +68,13 @@ left: 10px; } + .umb-user-card__name { font-size: 15px; font-weight: bold; text-align: center; margin-bottom: 2px; - word-wrap: break-word; -} - -.umb-user-card__checkmark { - position: absolute; - top: 10px; - right: 10px; - display: none; -} - -.umb-user-card:hover .umb-user-card__checkmark, -.umb-user-card__checkmark--visible { - display: block; + word-wrap: break-word; } .umb-user-card__group { @@ -77,4 +87,4 @@ font-size: 13px; text-align: center; margin-top: auto; -} \ No newline at end of file +} diff --git a/src/Umbraco.Web.UI.Client/src/less/mixins.less b/src/Umbraco.Web.UI.Client/src/less/mixins.less index b67fd1dd25..0dadc906ef 100644 --- a/src/Umbraco.Web.UI.Client/src/less/mixins.less +++ b/src/Umbraco.Web.UI.Client/src/less/mixins.less @@ -539,7 +539,7 @@ &.disabled, &[disabled] { color: @white; - background-color: @sand-2; + background-color: @sand-1; } /* // IE 7 + 8 can't handle box-shadow to show active, so we darken a bit ourselves diff --git a/src/Umbraco.Web.UI.Client/src/less/tables.less b/src/Umbraco.Web.UI.Client/src/less/tables.less index fa8a44ec47..09b6ea8a42 100644 --- a/src/Umbraco.Web.UI.Client/src/less/tables.less +++ b/src/Umbraco.Web.UI.Client/src/less/tables.less @@ -62,6 +62,15 @@ table { } +.table tr > td:first-child { + border-left: 4px solid transparent; +} +.table tr.--selected > td:first-child { + border-left-color:@ui-selected-border; +} + + + // CONDENSED TABLE W/ HALF PADDING // ------------------------------- diff --git a/src/Umbraco.Web.UI.Client/src/less/variables.less b/src/Umbraco.Web.UI.Client/src/less/variables.less index 80665e4c64..92d4e09895 100644 --- a/src/Umbraco.Web.UI.Client/src/less/variables.less +++ b/src/Umbraco.Web.UI.Client/src/less/variables.less @@ -76,9 +76,10 @@ @gray-10: #F3F3F5; @gray-11: #F6F6F7; -@sand-1: hsl(22, 33%, 93%);// added 2019 +@sand-1: hsl(22, 18%, 84%);// added 2019 @sand-2: hsl(22, 34%, 88%);// added 2019 @sand-5: hsl(22, 31%, 93%);// added 2019 +@sand-6: hsl(22, 29%, 95%);// added 2019 @sand-7: hsl(22, 26%, 97%);// added 2019 @@ -138,8 +139,8 @@ @ui-active-type: @blueExtraDark; @ui-active-type-hover: @blueMid; -@ui-selected: @sand-1; -@ui-selected-hover: ligthen(@sand-1, 10); +@ui-selected: @sand-5; +@ui-selected-hover: ligthen(@sand-5, 10); @ui-selected-type: @blueExtraDark; @ui-selected-type-hover: @blueMid; @ui-selected-border: @pinkLight; @@ -176,7 +177,7 @@ @ui-btn-type: @white; @ui-btn-positive: @green; -@ui-btn-positive-hover: @green-l1; +@ui-btn-positive-hover: lighten(@green, 6%); @ui-btn-positive-type: @white; @ui-btn-negative: @red; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html index 44b70ea613..eb85cc5fd2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html @@ -180,6 +180,7 @@ button-style="success" label="Select image" type="button" + disabled="model.selection.length === 0" action="submit(model)"> diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html index da94729562..1f5235146d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-media-grid.html @@ -4,7 +4,7 @@ -
+
{{item.name}}
diff --git a/src/Umbraco.Web.UI.Client/src/views/member/edit.html b/src/Umbraco.Web.UI.Client/src/views/member/edit.html index 310559b4d4..ee6e9c625c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/member/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/member/edit.html @@ -24,13 +24,13 @@
{{ group.label }}
 
- +
- + @@ -38,8 +38,8 @@ - @@ -51,6 +51,7 @@ ng-if="page.listViewPath" type="link" href="#{{page.listViewPath}}" + button-style="link" label="Return to list" label-key="buttons_returnToList"> diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/checkboxlist/checkboxlist.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/checkboxlist/checkboxlist.controller.js index 9ef1b69aad..1e679eb5ae 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/checkboxlist/checkboxlist.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/checkboxlist/checkboxlist.controller.js @@ -42,7 +42,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.CheckboxListContro return f.checked; }), function(m) { - return m.key; + return m.value; }); //get all of the same values between the arrays var same = _.intersection($scope.model.value, selectedVals); @@ -54,7 +54,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.CheckboxListContro $scope.selectedItems = []; for (var i = 0; i < configItems.length; i++) { - var isChecked = _.contains($scope.model.value, configItems[i].id); + var isChecked = _.contains($scope.model.value, configItems[i].value); $scope.selectedItems.push({ checked: isChecked, key: configItems[i].id, @@ -66,13 +66,13 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.CheckboxListContro function changed(item) { var index = _.findIndex($scope.model.value, function (v) { - return v === item.key; + return v === item.value; }); - + if (item.checked) { //if it doesn't exist in the model, then add it if (index < 0) { - $scope.model.value.push(item.key); + $scope.model.value.push(item.value); } } else { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/checkboxlist/checkboxlist.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/checkboxlist/checkboxlist.html index 29760e3f5b..7ec7067734 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/checkboxlist/checkboxlist.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/checkboxlist/checkboxlist.html @@ -4,9 +4,9 @@
  • diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.controller.js new file mode 100644 index 0000000000..3441b6a060 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.controller.js @@ -0,0 +1,16 @@ +function EditConfigController($scope) { + + $scope.close = function() { + if($scope.model.close) { + $scope.model.close(); + } + } + + $scope.submit = function() { + if($scope.model && $scope.model.submit) { + $scope.model.submit($scope.model); + } + } +} + +angular.module("umbraco").controller("Umbraco.PropertyEditors.GridPrevalueEditor.EditConfigController", EditConfigController); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.html index fb541ecf84..9c42e04f75 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.html @@ -1,3 +1,25 @@ +
    + + + + + +
    + + + + + + + + + +

    {{model.name}}

    @@ -12,3 +34,34 @@
    + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.controller.js index 566535fc98..4ad857b1e7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.controller.js @@ -1,10 +1,25 @@ angular.module("umbraco") .controller("Umbraco.PropertyEditors.GridPrevalueEditor.LayoutConfigController", - function ($scope) { + function ($scope, localizationService) { + + + function init() { + setTitle(); + } + + function setTitle() { + if (!$scope.model.title) { + localizationService.localize("grid_addGridLayout") + .then(function(data){ + $scope.model.title = data; + }); + } + } $scope.currentLayout = $scope.model.currentLayout; $scope.columns = $scope.model.columns; $scope.rows = $scope.model.rows; + $scope.currentSection = undefined; $scope.scaleUp = function(section, max, overflow){ var add = 1; @@ -57,9 +72,12 @@ angular.module("umbraco") template.sections.splice(index, 1); }; - $scope.closeSection = function(){ - $scope.currentSection = undefined; - }; + + $scope.close = function() { + if($scope.model.close) { + $scope.model.close(); + } + } $scope.$watch("currentLayout", function(layout){ if(layout){ @@ -71,4 +89,6 @@ angular.module("umbraco") $scope.availableLayoutSpace = $scope.columns - total; } }, true); + + init(); }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.html index 0e1a92a62c..4f0b665e24 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.html @@ -1,8 +1,31 @@
    -
    -
    + + + + +
    + + + + + + + + + + + + + +
    +

    @@ -32,7 +55,7 @@
    -
    +
    @@ -111,4 +134,27 @@
    -
    + + + + + + + + + + + + + + + + + + +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.controller.js index 4e3dde50e4..1bb7516f30 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.controller.js @@ -1,5 +1,19 @@ -function RowConfigController($scope) { +function RowConfigController($scope, localizationService) { + function init() { + setTitle(); + } + + function setTitle() { + if (!$scope.model.title) { + localizationService.localize("grid_addRowConfiguration") + .then(function(data){ + $scope.model.title = data; + }); + } + } + + $scope.currentRow = $scope.model.currentRow; $scope.editors = $scope.model.editors; $scope.columns = $scope.model.columns; @@ -69,6 +83,12 @@ function RowConfigController($scope) { $scope.closeArea = function() { $scope.currentCell = undefined; }; + + $scope.close = function() { + if($scope.model.close) { + $scope.model.close(); + } + } $scope.nameChanged = false; var originalName = $scope.currentRow.name; @@ -93,6 +113,10 @@ function RowConfigController($scope) { } }, true); + + init(); + + } angular.module("umbraco").controller("Umbraco.PropertyEditors.GridPrevalueEditor.RowConfigController", RowConfigController); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.html index c9a0d807ea..10af5ade3c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.html @@ -1,8 +1,30 @@
    -
    -
    + + + +
    + + + + + + + + + + + + + +
    +

    @@ -14,7 +36,7 @@ - + @@ -54,7 +76,7 @@
    - + @@ -97,4 +119,27 @@
    + + + +
    +
    +
    + + + + + + + + +
    + +
    +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowdeleteconfirm.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowdeleteconfirm.controller.js new file mode 100644 index 0000000000..10b5601304 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowdeleteconfirm.controller.js @@ -0,0 +1,16 @@ +function DeleteRowConfirmController($scope) { + + $scope.close = function() { + if($scope.model.close) { + $scope.model.close(); + } + } + + $scope.submit = function() { + if($scope.model && $scope.model.submit) { + $scope.model.submit($scope.model); + } + } +} + +angular.module("umbraco").controller("Umbraco.PropertyEditors.GridPrevalueEditor.DeleteRowConfirmController", DeleteRowConfirmController); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowdeleteconfirm.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowdeleteconfirm.html index c69ae2cb8f..2bf1f00b0e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowdeleteconfirm.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowdeleteconfirm.html @@ -1,4 +1,13 @@ -
    +
    + + + + + + + + +

    Warning!

    @@ -15,4 +24,31 @@ Are you sure?

    + + + +
    +
    +
    + + + + + + + + + + +
    +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.controller.js index 19057fa842..d38697d351 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.controller.js @@ -1,6 +1,6 @@ angular.module("umbraco") .controller("Umbraco.PropertyEditors.GridPrevalueEditorController", - function ($scope, gridService) { + function ($scope, gridService, editorService) { var emptyModel = { styles:[ @@ -89,28 +89,23 @@ angular.module("umbraco") }; $scope.model.value.templates.push(template); } + + var layoutConfigOverlay = { + currentLayout: template, + rows: $scope.model.value.layouts, + columns: $scope.model.value.columns, + view: "views/propertyEditors/grid/dialogs/layoutconfig.html", + size: "small", + submit: function(model) { + editorService.close(); + }, + close: function(model) { + editorService.close(); + } + }; - $scope.layoutConfigOverlay = {}; - $scope.layoutConfigOverlay.view = "views/propertyEditors/grid/dialogs/layoutconfig.html"; - $scope.layoutConfigOverlay.currentLayout = template; - $scope.layoutConfigOverlay.rows = $scope.model.value.layouts; - $scope.layoutConfigOverlay.columns = $scope.model.value.columns; - $scope.layoutConfigOverlay.show = true; + editorService.open(layoutConfigOverlay); - $scope.layoutConfigOverlay.submit = function(model) { - $scope.layoutConfigOverlay.show = false; - $scope.layoutConfigOverlay = null; - }; - - $scope.layoutConfigOverlay.close = function(oldModel) { - - //reset templates - $scope.model.value.templates = templatesCopy; - - $scope.layoutConfigOverlay.show = false; - $scope.layoutConfigOverlay = null; - } - }; $scope.deleteTemplate = function(index){ @@ -135,50 +130,44 @@ angular.module("umbraco") }; $scope.model.value.layouts.push(layout); } - - $scope.rowConfigOverlay = {}; - $scope.rowConfigOverlay.view = "views/propertyEditors/grid/dialogs/rowconfig.html"; - $scope.rowConfigOverlay.currentRow = layout; - $scope.rowConfigOverlay.editors = $scope.editors; - $scope.rowConfigOverlay.columns = $scope.model.value.columns; - $scope.rowConfigOverlay.show = true; - - $scope.rowConfigOverlay.submit = function(model) { - $scope.rowConfigOverlay.show = false; - $scope.rowConfigOverlay = null; - }; - - $scope.rowConfigOverlay.close = function(oldModel) { - $scope.model.value.layouts = layoutsCopy; - $scope.rowConfigOverlay.show = false; - $scope.rowConfigOverlay = null; + + var rowConfigOverlay = { + currentRow: layout, + editors: $scope.editors, + columns: $scope.model.value.columns, + view: "views/propertyEditors/grid/dialogs/rowconfig.html", + size: "small", + submit: function(model) { + editorService.close(); + }, + close: function(model) { + editorService.close(); + } }; + editorService.open(rowConfigOverlay); + }; //var rowDeletesPending = false; $scope.deleteLayout = function(index) { + + var rowDeleteOverlay = { + dialogData: { + rowName: $scope.model.value.layouts[index].name + }, + view: "views/propertyEditors/grid/dialogs/rowdeleteconfirm.html", + size: "small", + submit: function(model) { + $scope.model.value.layouts.splice(index, 1); + editorService.close(); + }, + close: function(model) { + editorService.close(); + } + }; - $scope.rowDeleteOverlay = {}; - $scope.rowDeleteOverlay.view = "views/propertyEditors/grid/dialogs/rowdeleteconfirm.html"; - $scope.rowDeleteOverlay.dialogData = { - rowName: $scope.model.value.layouts[index].name - }; - $scope.rowDeleteOverlay.show = true; - - $scope.rowDeleteOverlay.submit = function(model) { - - $scope.model.value.layouts.splice(index, 1); - - $scope.rowDeleteOverlay.show = false; - $scope.rowDeleteOverlay = null; - }; - - $scope.rowDeleteOverlay.close = function(oldModel) { - $scope.rowDeleteOverlay.show = false; - $scope.rowDeleteOverlay = null; - }; - + editorService.open(rowDeleteOverlay); }; @@ -210,26 +199,22 @@ angular.module("umbraco") }; var editConfigCollection = function(configValues, title, callback) { + + var editConfigCollectionOverlay = { + config: configValues, + title: title, + view: "views/propertyeditors/grid/dialogs/editconfig.html", + size: "small", + submit: function(model) { + callback(model.config); + editorService.close(); + }, + close: function(model) { + editorService.close(); + } + }; - $scope.editConfigCollectionOverlay = {}; - $scope.editConfigCollectionOverlay.view = "views/propertyeditors/grid/dialogs/editconfig.html"; - $scope.editConfigCollectionOverlay.config = configValues; - $scope.editConfigCollectionOverlay.title = title; - $scope.editConfigCollectionOverlay.show = true; - - $scope.editConfigCollectionOverlay.submit = function(model) { - - callback(model.config); - - $scope.editConfigCollectionOverlay.show = false; - $scope.editConfigCollectionOverlay = null; - }; - - $scope.editConfigCollectionOverlay.close = function(oldModel) { - $scope.editConfigCollectionOverlay.show = false; - $scope.editConfigCollectionOverlay = null; - }; - + editorService.open(editConfigCollectionOverlay); }; $scope.editConfig = function() { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.html index 539433821b..92d1a9ef26 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.prevalues.html @@ -158,28 +158,4 @@
    - - - - - - - - - - - -
    diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js index a3fc33d2ea..44c0c4ae7b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js @@ -142,7 +142,6 @@ function listViewController($scope, $routeParams, $injector, $timeout, currentUs } $scope.options = { - displayAtTabNumber: $scope.model.config.displayAtTabNumber ? $scope.model.config.displayAtTabNumber : 1, pageSize: $scope.model.config.pageSize ? $scope.model.config.pageSize : 10, pageNumber: ($routeParams.page && Number($routeParams.page) != NaN && Number($routeParams.page) > 0) ? $routeParams.page : 1, filter: '', diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html index 9a638d91fa..2c70ba5730 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html @@ -6,7 +6,7 @@
    - + @@ -85,7 +85,7 @@ type="button" label="Clear selection" label-key="buttons_clearSelection" - button-style="selection" + button-style="white" action="clearSelection()" disabled="actionInProgress"> @@ -140,7 +140,7 @@ ng-if="options.allowBulkPublish && (buttonPermissions == null || buttonPermissions.canPublish)" style="margin-right: 5px;" type="button" - button-style="selection" + button-style="white" label-key="actions_publish" icon="icon-globe" action="publish()" @@ -153,7 +153,7 @@ ng-if="options.allowBulkUnpublish && (buttonPermissions == null || buttonPermissions.canUnpublish)" style="margin-right: 5px;" type="button" - button-style="selection" + button-style="white" label-key="actions_unpublish" icon="icon-block" action="unpublish()" @@ -166,7 +166,7 @@ ng-if="options.allowBulkCopy && (buttonPermissions == null || buttonPermissions.canCopy)" style="margin-right: 5px;" type="button" - button-style="selection" + button-style="white" label-key="actions_copy" icon="icon-documents" action="copy()" @@ -179,7 +179,7 @@ ng-if="options.allowBulkMove && (buttonPermissions == null || buttonPermissions.canMove)" style="margin-right: 5px;" type="button" - button-style="selection" + button-style="white" label-key="actions_move" icon="icon-enter" action="move()" @@ -191,7 +191,7 @@
  • - \ No newline at end of file + diff --git a/src/Umbraco.Web.UI.Client/src/views/users/user.html b/src/Umbraco.Web.UI.Client/src/views/users/user.html index 74b43eb2aa..3af5cc064a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/user.html +++ b/src/Umbraco.Web.UI.Client/src/views/users/user.html @@ -12,9 +12,9 @@ hide-alias="true" navigation="vm.user.navigation"> - + - +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.html b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.html index deee402fd5..863d9658ae 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.html +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.html @@ -2,13 +2,13 @@ - - + + @@ -40,6 +40,7 @@ @@ -54,6 +55,7 @@ type="button" label="Delete" label-key="general_delete" + button-style="white" icon="icon-trash" action="vm.deleteUserGroups()" size="xs"> @@ -64,7 +66,7 @@
    - Groups ({{vm.userGroups.length}}) + Groups ({{vm.userGroups.length}})
    @@ -76,19 +78,20 @@ - - - + + + + ng-click="vm.selectUserGroup(group, vm.selection, $event)" + style="width: 20px; height: 100px;"/> - -
    \ No newline at end of file + diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js index 2001b95e99..38f6758651 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js @@ -196,27 +196,23 @@ vm.activeLayout = selectedLayout; } - function selectUser(user, selection, event) { - - // prevent the current user to be selected - if (!user.isCurrentUser) { - - if (user.selected) { - var index = selection.indexOf(user.id); - selection.splice(index, 1); - user.selected = false; - } else { - user.selected = true; - vm.selection.push(user.id); - } - - setBulkActions(vm.users); - - if (event) { - event.preventDefault(); - event.stopPropagation(); - } + function selectUser(user) { + + if (user.isCurrentUser) { + return; } + + if (user.selected) { + var index = vm.selection.indexOf(user.id); + vm.selection.splice(index, 1); + user.selected = false; + } else { + user.selected = true; + vm.selection.push(user.id); + } + + setBulkActions(vm.users); + } function clearSelection() { @@ -227,11 +223,7 @@ } function clickUser(user) { - if (vm.selection.length > 0) { - selectUser(user, vm.selection); - } else { - goToUser(user.id); - } + goToUser(user.id); } function disableUsers() { @@ -625,18 +617,20 @@ var firstSelectedUserGroups; angular.forEach(users, function (user) { - + if (!user.selected) { return; } - + + // if the current user is selected prevent any bulk actions with the user included if (user.isCurrentUser) { vm.allowDisableUser = false; vm.allowEnableUser = false; vm.allowUnlockUser = false; vm.allowSetUserGroup = false; - return; + + return false; } if (user.userDisplayState && user.userDisplayState.key === "Disabled") { @@ -660,16 +654,17 @@ } // store the user group aliases of the first selected user - if (!firstSelectedUserGroups) { - firstSelectedUserGroups = user.userGroups.map(function (ug) { return ug.alias; }); - vm.allowSetUserGroup = true; - } else if (vm.allowSetUserGroup === true) { - // for 2nd+ selected user, compare the user group aliases to determine if we should allow bulk editing. - // we don't allow bulk editing of users not currently having the same assigned user groups, as we can't - // really support that in the user group picker. - var userGroups = user.userGroups.map(function (ug) { return ug.alias; }); - if (_.difference(firstSelectedUserGroups, userGroups).length > 0) { - vm.allowSetUserGroup = false; + if (vm.allowSetUserGroup === true) { + if (!firstSelectedUserGroups) { + firstSelectedUserGroups = user.userGroups.map(function (ug) { return ug.alias; }); + } else { + // for 2nd+ selected user, compare the user group aliases to determine if we should allow bulk editing. + // we don't allow bulk editing of users not currently having the same assigned user groups, as we can't + // really support that in the user group picker. + var userGroups = user.userGroups.map(function (ug) { return ug.alias; }); + if (_.difference(firstSelectedUserGroups, userGroups).length > 0) { + vm.allowSetUserGroup = false; + } } } }); diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html index c764e919c8..cefc3c5c86 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html @@ -5,7 +5,7 @@ - + @@ -48,7 +48,7 @@ @@ -57,16 +57,16 @@ {{ vm.selection.length }} of {{ vm.users.length }} selected - + @@ -74,22 +74,22 @@ - +
    - Status: + Status: {{ vm.getFilterName(vm.userStatesFilter) }} @@ -167,7 +167,7 @@
    - Order by: + Order by: {{ vm.getSortLabel(vm.usersOptions.orderBy, vm.usersOptions.orderDirection) }} @@ -191,20 +191,18 @@ @@ -244,9 +242,14 @@ - + -
    +
    - + - {{user.name}} + {{user.name}} {{ userGroup.name }}, {{ user.formattedLastLogin }} @@ -331,7 +334,7 @@ Required {{addUserForm.name.errorMsg}} - + @@ -341,7 +344,7 @@ Required {{addUserForm.username.errorMsg}} - + @@ -355,7 +358,7 @@ - +
    - + Back to users - +
    - +

    - +
    @@ -510,7 +513,7 @@ - +
    /// A property editor to allow multiple checkbox selection of pre-defined items. /// - /// - /// Due to remaining backwards compatible, this stores the id of the checkbox items in the database - /// as INT and we have logic in here to ensure it is formatted correctly including ensuring that the string value is published - /// in cache and not the int ID. - /// [DataEditor(Constants.PropertyEditors.Aliases.CheckBoxList, "Checkbox list", "checkboxlist", Icon="icon-bulleted-list", Group="lists")] public class CheckBoxListPropertyEditor : DataEditor { @@ -31,6 +26,6 @@ namespace Umbraco.Web.PropertyEditors protected override IConfigurationEditor CreateConfigurationEditor() => new ValueListConfigurationEditor(_textService); /// - protected override IDataValueEditor CreateValueEditor() => new PublishValuesMultipleValueEditor(Logger, Attribute); + protected override IDataValueEditor CreateValueEditor() => new MultipleValueEditor(Logger, Attribute); } } diff --git a/src/Umbraco.Web/PropertyEditors/DropDownFlexiblePropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownFlexiblePropertyEditor.cs index 4424e1d245..eac692fcdd 100644 --- a/src/Umbraco.Web/PropertyEditors/DropDownFlexiblePropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/DropDownFlexiblePropertyEditor.cs @@ -18,7 +18,7 @@ namespace Umbraco.Web.PropertyEditors protected override IDataValueEditor CreateValueEditor() { - return new PublishValuesMultipleValueEditor(Logger, Attribute); + return new MultipleValueEditor(Logger, Attribute); } protected override IConfigurationEditor CreateConfigurationEditor() => new DropDownFlexibleConfigurationEditor(_textService); diff --git a/src/Umbraco.Web/PropertyEditors/ListViewConfiguration.cs b/src/Umbraco.Web/PropertyEditors/ListViewConfiguration.cs index 6448a3354c..bcddc18369 100644 --- a/src/Umbraco.Web/PropertyEditors/ListViewConfiguration.cs +++ b/src/Umbraco.Web/PropertyEditors/ListViewConfiguration.cs @@ -13,7 +13,6 @@ namespace Umbraco.Web.PropertyEditors // initialize defaults PageSize = 10; - DisplayAtTabNumber = 1; OrderBy = "SortOrder"; OrderDirection = "asc"; @@ -43,9 +42,6 @@ namespace Umbraco.Web.PropertyEditors [ConfigurationField("pageSize", "Page Size", "number", Description = "Number of items per page")] public int PageSize { get; set; } - [ConfigurationField("displayAtTabNumber", "Display At Tab Number", "number", Description = "Which tab position that the list of child items will be displayed")] - public int DisplayAtTabNumber { get; set; } - [ConfigurationField("orderBy", "Order By", "views/propertyeditors/listview/sortby.prevalues.html", Description = "The default sort order for the list")] public string OrderBy { get; set; } @@ -64,7 +60,7 @@ namespace Umbraco.Web.PropertyEditors Description = "The bulk actions that are allowed from the list view")] public BulkActionPermissionSettings BulkActionPermissions { get; set; } = new BulkActionPermissionSettings(); // TODO: managing defaults? - [ConfigurationField("tabName", "Tab Name", "textstring", Description = "The name of the listview tab (default if empty: 'Child Items')")] + [ConfigurationField("tabName", "Content app name", "textstring", Description = "The name of the listview content app (default if empty: 'Child Items')")] public string TabName { get; set; } public class Property diff --git a/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs b/src/Umbraco.Web/PropertyEditors/MultipleValueEditor.cs similarity index 69% rename from src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs rename to src/Umbraco.Web/PropertyEditors/MultipleValueEditor.cs index 8e0737dedd..bbeaff184e 100644 --- a/src/Umbraco.Web/PropertyEditors/PublishValuesMultipleValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/MultipleValueEditor.cs @@ -1,33 +1,32 @@ using System; using System.Linq; +using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; -using Umbraco.Web.Composing; namespace Umbraco.Web.PropertyEditors { /// - /// Custom value editor to handle posted json data and to return json data for the multiple selected items + /// A value editor to handle posted json array data and to return array data for the multiple selected csv items /// /// /// This is re-used by editors such as the multiple drop down list or check box list /// - internal class PublishValuesMultipleValueEditor : DataValueEditor + internal class MultipleValueEditor : DataValueEditor { private readonly ILogger _logger; - internal PublishValuesMultipleValueEditor(ILogger logger, DataEditorAttribute attribute) + internal MultipleValueEditor(ILogger logger, DataEditorAttribute attribute) : base(attribute) { _logger = logger; } /// - /// Override so that we can return a json array to the editor for multi-select values + /// Override so that we can return an array to the editor for multi-select values /// /// /// @@ -36,8 +35,8 @@ namespace Umbraco.Web.PropertyEditors /// public override object ToEditor(Property property, IDataTypeService dataTypeService, string culture = null, string segment = null) { - var delimited = base.ToEditor(property, dataTypeService, culture, segment).ToString(); - return delimited.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + var json = base.ToEditor(property, dataTypeService, culture, segment).ToString(); + return JsonConvert.DeserializeObject(json) ?? Array.Empty(); } /// @@ -55,9 +54,9 @@ namespace Umbraco.Web.PropertyEditors return null; } - var values = json.Select(item => item.Value()).ToList(); - //change to delimited - return string.Join(",", values); + var values = json.Select(item => item.Value()).ToArray(); + + return JsonConvert.SerializeObject(values); } } } diff --git a/src/Umbraco.Web/PropertyEditors/RadioButtonsPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/RadioButtonsPropertyEditor.cs index 46069fec79..601728189c 100644 --- a/src/Umbraco.Web/PropertyEditors/RadioButtonsPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/RadioButtonsPropertyEditor.cs @@ -8,7 +8,7 @@ namespace Umbraco.Web.PropertyEditors /// /// A property editor to allow the individual selection of pre-defined items. /// - [DataEditor(Constants.PropertyEditors.Aliases.RadioButtonList, "Radio button list", "radiobuttons", ValueType = ValueTypes.Integer, Group="lists", Icon="icon-target")] + [DataEditor(Constants.PropertyEditors.Aliases.RadioButtonList, "Radio button list", "radiobuttons", ValueType = ValueTypes.String, Group="lists", Icon="icon-target")] public class RadioButtonsPropertyEditor : DataEditor { private readonly ILocalizedTextService _textService; diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/FlexibleDropdownPropertyValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/FlexibleDropdownPropertyValueConverter.cs index d470f54662..43add34327 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/FlexibleDropdownPropertyValueConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/FlexibleDropdownPropertyValueConverter.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Newtonsoft.Json; using Umbraco.Core; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.PropertyEditors; @@ -17,8 +18,10 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters public override object ConvertSourceToIntermediate(IPublishedElement owner, PublishedPropertyType propertyType, object source, bool preview) { - return source?.ToString().Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => v.Trim()).ToArray() - ?? Enumerable.Empty(); + if(source == null) return Array.Empty(); + + + return JsonConvert.DeserializeObject(source.ToString()) ?? Array.Empty(); } public override object ConvertIntermediateToObject(IPublishedElement owner, PublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview) diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index fa2ac81761..26624ee4a2 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -861,7 +861,7 @@ - +