diff --git a/src/Umbraco.Core/Models/Editors/ContentPropertyData.cs b/src/Umbraco.Core/Models/Editors/ContentPropertyData.cs index 98afb691e8..6676a7c3a7 100644 --- a/src/Umbraco.Core/Models/Editors/ContentPropertyData.cs +++ b/src/Umbraco.Core/Models/Editors/ContentPropertyData.cs @@ -22,6 +22,8 @@ namespace Umbraco.Core.Models.Editors AdditionalData = new ReadOnlyDictionary(additionalData); } + //TODO: Change this to an object so we can post JSON or json converted clr types if we want! + /// /// The string value submitted for the property /// diff --git a/src/Umbraco.Core/PropertyEditors/PreValueEditor.cs b/src/Umbraco.Core/PropertyEditors/PreValueEditor.cs index bfd33c2be0..da4eafa059 100644 --- a/src/Umbraco.Core/PropertyEditors/PreValueEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/PreValueEditor.cs @@ -102,9 +102,10 @@ namespace Umbraco.Core.PropertyEditors /// This can be overridden if perhaps you have a comma delimited string posted value but want to convert those to individual rows, or to convert /// a json structure to multiple rows. /// - public virtual IDictionary FormatDataForPersistence(IDictionary editorValue, PreValueCollection currentValue) + public virtual IDictionary FormatDataForPersistence(IDictionary editorValue, PreValueCollection currentValue) { - return editorValue; + //convert to a string based value to be saved in the db + return editorValue.ToDictionary(x => x.Key, x => x.Value == null ? null : x.Value.ToString()); } /// diff --git a/src/Umbraco.Core/PropertyEditors/ValueEditor.cs b/src/Umbraco.Core/PropertyEditors/ValueEditor.cs index 637bffbc4a..ef4b711b66 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueEditor.cs @@ -171,6 +171,8 @@ namespace Umbraco.Core.PropertyEditors return result.Result; } + //TODO: Change the result to object so we can pass back JSON or json converted clr types if we want! + /// /// A method used to serialize the databse value to a string value which is then used to be sent /// to the editor in JSON format. diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/valHighlight.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/valHighlight.directive.js new file mode 100644 index 0000000000..5d4b6cf9f9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/valHighlight.directive.js @@ -0,0 +1,30 @@ +/** +* @ngdoc directive +* @name umbraco.directives.directive:valHighlight +* @restrict A +* @description Used on input fields when you want to signal that they are in error, this will highlight the item for 1 second +**/ +function valHighlight($timeout) { + return { + restrict: "A", + link: function (scope, element, attrs, ctrl) { + + scope.$watch(function() { + return scope.$eval(attrs.valHighlight); + }, function(newVal, oldVal) { + if (newVal === true) { + element.addClass("highlight-error"); + $timeout(function () { + //set the bound scope property to false + scope[attrs.valHighlight] = false; + }, 1000); + } + else { + element.removeClass("highlight-error"); + } + }); + + } + }; +} +angular.module('umbraco.directives').directive("valHighlight", valHighlight); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/forms.less b/src/Umbraco.Web.UI.Client/src/less/forms.less index f9b864b678..f14465b6d4 100644 --- a/src/Umbraco.Web.UI.Client/src/less/forms.less +++ b/src/Umbraco.Web.UI.Client/src/less/forms.less @@ -399,6 +399,16 @@ input[type="checkbox"][readonly] { } +input.highlight-error, +select.highlight-error, +textarea.highlight-error { + border-color: #953b39 !important; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; +} + + // FORM ACTIONS // ------------ diff --git a/src/Umbraco.Web.UI.Client/src/less/mixins.less b/src/Umbraco.Web.UI.Client/src/less/mixins.less index 9529b6be54..e1f9170424 100644 --- a/src/Umbraco.Web.UI.Client/src/less/mixins.less +++ b/src/Umbraco.Web.UI.Client/src/less/mixins.less @@ -198,9 +198,6 @@ } } - - - // CSS3 PROPERTIES // -------------------------------------------------- diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.controller.js index 579da61857..ce75a5ab04 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.controller.js @@ -8,12 +8,14 @@ angular.module("umbraco").controller("Umbraco.Editors.DropdownController", keyName: "alias", valueName: "name" }; - + //map the user config angular.extend(config, $scope.model.config); //map back to the model $scope.model.config = config; + $scope.selectExpression = "e." + config.keyName + " as e." + config.valueName + " for e in model.config.items"; + //now we need to format the items in the array because we always want to have a dictionary for (var i = 0; i < $scope.model.config.items.length; i++) { if (angular.isString($scope.model.config.items[i])) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.html index 5249d017e2..a4e7079c1b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.html @@ -1,7 +1,6 @@
+ ng-options="{{selectExpression}}">
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.prevalue.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.prevalue.controller.js new file mode 100644 index 0000000000..6f10385cfb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.prevalue.controller.js @@ -0,0 +1,33 @@ +angular.module("umbraco").controller("Umbraco.Editors.DropdownPreValueController", + function ($scope, $timeout) { + + $scope.newItem = ""; + $scope.hasError = false; + + $scope.remove = function(item, evt) { + + evt.preventDefault(); + + $scope.model.value = _.reject($scope.model.value, function(i) { + return i === item; + }); + }; + + $scope.add = function (evt) { + + evt.preventDefault(); + + if (!_.contains($scope.model.value, $scope.newItem)) { + if ($scope.newItem) { + $scope.model.value.push($scope.newItem); + $scope.newItem = ""; + $scope.hasError = false; + return; + } + } + + //there was an error, do the highlight (will be set back by the directive) + $scope.hasError = true; + }; + + }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.prevalue.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.prevalue.html index 04eeca9c10..440fa629db 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.prevalue.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdown/dropdown.prevalue.html @@ -1,5 +1,13 @@ -
- - +
+
    +
  • + + +
  • +
  • + + +
  • +
\ No newline at end of file diff --git a/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs b/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs index 1d6d2f5b12..ee5c2447a9 100644 --- a/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs +++ b/src/Umbraco.Web/Editors/DataTypeValidateAttribute.cs @@ -88,7 +88,7 @@ namespace Umbraco.Web.Editors foreach (var v in propertyEditor.PreValueEditor.Fields.SelectMany(x => x.Validators)) { - foreach (var result in v.Validate(postedValue, preVal.Key, propertyEditor)) + foreach (var result in v.Validate(postedValue != null ? postedValue.ToString() : null, preVal.Key, propertyEditor)) { //if there are no member names supplied then we assume that the validation message is for the overall property // not a sub field on the property editor diff --git a/src/Umbraco.Web/Models/ContentEditing/PreValueFieldSave.cs b/src/Umbraco.Web/Models/ContentEditing/PreValueFieldSave.cs index e13a5dcf24..64b1058f8a 100644 --- a/src/Umbraco.Web/Models/ContentEditing/PreValueFieldSave.cs +++ b/src/Umbraco.Web/Models/ContentEditing/PreValueFieldSave.cs @@ -18,6 +18,6 @@ namespace Umbraco.Web.Models.ContentEditing /// The value stored for the pre-value field ///
[DataMember(Name = "value", IsRequired = true)] - public string Value { get; set; } + public object Value { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Web/Models/Mapping/PreValueDisplayResolver.cs b/src/Umbraco.Web/Models/Mapping/PreValueDisplayResolver.cs index 3457d2e781..547d1a9fde 100644 --- a/src/Umbraco.Web/Models/Mapping/PreValueDisplayResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/PreValueDisplayResolver.cs @@ -70,7 +70,7 @@ namespace Umbraco.Web.Models.Mapping LogHelper.Warn("Could not find persisted pre-value for field " + field.Key); continue; } - field.Value = dictionaryVals.Single(x => x.Key.InvariantEquals(field.Key)).Value.ToString(); + field.Value = dictionaryVals.Single(x => x.Key.InvariantEquals(field.Key)).Value; } diff --git a/src/Umbraco.Web/PropertyEditors/DropDownPreValueEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownPreValueEditor.cs index 7e4f8d4548..1db5cc9c3d 100644 --- a/src/Umbraco.Web/PropertyEditors/DropDownPreValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/DropDownPreValueEditor.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -13,7 +14,7 @@ namespace Umbraco.Web.PropertyEditors { /// - /// The editor is expecting a json array for a field with a key named "temp" so we need to format the persisted values + /// The editor is expecting a json array for a field with a key named "items" so we need to format the persisted values /// to this format to be used in the editor. /// /// @@ -23,9 +24,8 @@ namespace Umbraco.Web.PropertyEditors { var dictionary = PreValueCollection.AsDictionary(persistedPreVals); var arrayOfVals = dictionary.Select(item => item.Value).ToList(); - var json = JsonConvert.SerializeObject(arrayOfVals); - return new Dictionary {{"temp", json}}; + return new Dictionary { { "items", arrayOfVals } }; } /// @@ -33,23 +33,28 @@ namespace Umbraco.Web.PropertyEditors /// /// /// - /// + /// + /// A string/string dictionary since all values that need to be persisted in the database are strings. + /// /// /// This is mostly because we want to maintain compatibility with v6 drop down property editors that store their prevalues in different db rows. /// - public override IDictionary FormatDataForPersistence(IDictionary editorValue, Core.Models.PreValueCollection currentValue) + public override IDictionary FormatDataForPersistence(IDictionary editorValue, PreValueCollection currentValue) { - var val = editorValue["temp"]; + var val = editorValue["items"] as JArray; var result = new Dictionary(); - if (val.IsNullOrWhiteSpace()) return result; + + if (val == null) + { + return result; + } try { - var deserialized = JsonConvert.DeserializeObject(val); var index = 0; - foreach (var item in deserialized) + foreach (var item in val) { - result.Add(index.ToInvariantString(), item); + result.Add(index.ToInvariantString(), item.ToString()); index++; } } diff --git a/src/Umbraco.Web/PropertyEditors/DropDownPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/DropDownPropertyEditor.cs index f668dcd9cf..6f8a8429a6 100644 --- a/src/Umbraco.Web/PropertyEditors/DropDownPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/DropDownPropertyEditor.cs @@ -17,10 +17,13 @@ namespace Umbraco.Web.PropertyEditors new PreValueField { Description = "Add and remove values for the drop down list", - //we're going to call this 'temp' because we are going to override the + //we're going to call this 'items' because we are going to override the //serialization of the pre-values to ensure that each one gets saved with it's own key //(new db row per pre-value, thus to maintain backwards compatibility) - Key = "temp", + + //It's also important to note that by default the dropdown angular controller is expecting the + // config options to come in with a property called 'items' + Key = "items", Name = ui.Text("editdatatype", "addPrevalue"), View = "Views/PropertyEditors/dropdown/dropdown.prevalue.html" }