diff --git a/src/Umbraco.Core/PropertyEditors/Validators/RegexValidator.cs b/src/Umbraco.Core/PropertyEditors/Validators/RegexValidator.cs index 0727c0d24f..e405fa3a3e 100644 --- a/src/Umbraco.Core/PropertyEditors/Validators/RegexValidator.cs +++ b/src/Umbraco.Core/PropertyEditors/Validators/RegexValidator.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Text.RegularExpressions; +using Umbraco.Core.Composing; using Umbraco.Core.Exceptions; +using Umbraco.Core.Services; namespace Umbraco.Core.PropertyEditors.Validators { @@ -11,6 +13,7 @@ namespace Umbraco.Core.PropertyEditors.Validators /// internal sealed class RegexValidator : IValueFormatValidator, IManifestValueValidator { + private readonly ILocalizedTextService _textService; private string _regex; /// @@ -22,8 +25,8 @@ namespace Umbraco.Core.PropertyEditors.Validators /// Use this constructor when the validator is used as an , /// and the regular expression is supplied at validation time. This constructor is also used when /// the validator is used as an and the regular expression - /// is supplied via the method. - public RegexValidator() + /// is supplied via the method. + public RegexValidator() : this(Current.Services.TextService, null) { } /// @@ -31,10 +34,9 @@ namespace Umbraco.Core.PropertyEditors.Validators /// /// Use this constructor when the validator is used as an , /// and the regular expression must be supplied when the validator is created. - public RegexValidator(string regex) + public RegexValidator(ILocalizedTextService textService, string regex) { - if (string.IsNullOrWhiteSpace(regex)) - throw new ArgumentNullOrEmptyException(nameof(regex)); + _textService = textService; _regex = regex; } @@ -66,7 +68,7 @@ namespace Umbraco.Core.PropertyEditors.Validators { if (string.IsNullOrWhiteSpace(format)) throw new ArgumentNullOrEmptyException(nameof(format)); if (value == null || !new Regex(format).IsMatch(value.ToString())) - yield return new ValidationResult("Value is invalid, it does not match the correct pattern", new[] { "value" }); + yield return new ValidationResult(_textService.Localize("validation", "invalidPattern"), new[] { "value" }); } } } diff --git a/src/Umbraco.Core/PropertyEditors/Validators/RequiredValidator.cs b/src/Umbraco.Core/PropertyEditors/Validators/RequiredValidator.cs index bc3cf66caa..4db0afd359 100644 --- a/src/Umbraco.Core/PropertyEditors/Validators/RequiredValidator.cs +++ b/src/Umbraco.Core/PropertyEditors/Validators/RequiredValidator.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; +using Umbraco.Core.Services; namespace Umbraco.Core.PropertyEditors.Validators { @@ -8,6 +9,17 @@ namespace Umbraco.Core.PropertyEditors.Validators /// internal sealed class RequiredValidator : IValueRequiredValidator, IManifestValueValidator { + private readonly ILocalizedTextService _textService; + + public RequiredValidator() + { + } + + public RequiredValidator(ILocalizedTextService textService) + { + _textService = textService; + } + /// public string ValidationName => "Required"; @@ -22,20 +34,20 @@ namespace Umbraco.Core.PropertyEditors.Validators { if (value == null) { - yield return new ValidationResult("Value cannot be null", new[] {"value"}); + yield return new ValidationResult(_textService.Localize("validation", "invalidNull"), new[] {"value"}); yield break; } if (valueType.InvariantEquals(ValueTypes.Json)) { if (value.ToString().DetectIsEmptyJson()) - yield return new ValidationResult("Value cannot be empty", new[] { "value" }); + yield return new ValidationResult(_textService.Localize("validation", "invalidEmpty"), new[] { "value" }); yield break; } if (value.ToString().IsNullOrWhiteSpace()) { - yield return new ValidationResult("Value cannot be empty", new[] { "value" }); + yield return new ValidationResult(_textService.Localize("validation", "invalidEmpty"), new[] { "value" }); } } } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/tabbedcontent.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/tabbedcontent.directive.js new file mode 100644 index 0000000000..ba68cb4e10 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/tabbedcontent.directive.js @@ -0,0 +1,38 @@ +(function () { + 'use strict'; + + function tabbedContentDirective() { + + var directive = { + restrict: 'E', + replace: true, + templateUrl: 'views/components/content/tabbed-content.html', + controller: function ($scope) { + + //expose the property/methods for other directives to use + this.content = $scope.content; + + }, + link: function(scope) { + + function onInit() { + angular.forEach(scope.content.tabs, function (group) { + group.open = true; + }); + } + + onInit(); + + }, + scope: { + content: "=" + } + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('tabbedContent', tabbedContentDirective); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js index 71c59860df..f3ba2a048d 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js @@ -12,10 +12,7 @@ function valPropertyMsg(serverValidationManager) { return { - scope: { - property: "=" - }, - require: ['^^form', '^^valFormManager'], + require: ['^^form', '^^valFormManager', '^^umbProperty', '^^tabbedContent'], replace: true, restrict: "E", template: "
{{errorMsg}}
", @@ -24,25 +21,31 @@ function valPropertyMsg(serverValidationManager) { //the property form controller api var formCtrl = ctrl[0]; - //the valFormManager controller api var valFormManager = ctrl[1]; + //the property controller api + var umbPropCtrl = ctrl[2]; + //the tabbed content controller api + var tabbedContent = ctrl[3]; + + var currentProperty = umbPropCtrl.property; + var currentCulture = tabbedContent.content.language.culture; var watcher = null; // Gets the error message to display function getErrorMsg() { //this can be null if no property was assigned - if (scope.property) { + if (currentProperty) { //first try to get the error msg from the server collection - var err = serverValidationManager.getPropertyError(scope.property.alias, ""); + var err = serverValidationManager.getPropertyError(currentProperty.alias, null, ""); //if there's an error message use it if (err && err.errorMsg) { return err.errorMsg; } else { //TODO: localize - return scope.property.propertyErrorMessage ? scope.property.propertyErrorMessage : "Property has errors"; + return currentProperty.propertyErrorMessage ? currentProperty.propertyErrorMessage : "Property has errors"; } } @@ -59,8 +62,10 @@ function valPropertyMsg(serverValidationManager) { function startWatch() { //if there's not already a watch if (!watcher) { - watcher = scope.$watch("property.value", function (newValue, oldValue) { - + watcher = scope.$watch(function () { + return currentProperty.value; + }, function (newValue, oldValue) { + if (!newValue || angular.equals(newValue, oldValue)) { return; } @@ -133,7 +138,7 @@ function valPropertyMsg(serverValidationManager) { }); //listen for the forms saving event - unsubscribe.push(scope.$on("formSubmitting", function(ev, args) { + unsubscribe.push(scope.$on("formSubmitting", function (ev, args) { showValidation = true; if (hasError && scope.errorMsg === "") { scope.errorMsg = getErrorMsg(); @@ -145,7 +150,7 @@ function valPropertyMsg(serverValidationManager) { })); //listen for the forms saved event - unsubscribe.push(scope.$on("formSubmitted", function(ev, args) { + unsubscribe.push(scope.$on("formSubmitted", function (ev, args) { showValidation = false; scope.errorMsg = ""; formCtrl.$setValidity('valPropertyMsg', true); @@ -160,8 +165,8 @@ function valPropertyMsg(serverValidationManager) { // indicate that a content property is invalid at the property level since developers may not actually implement // the correct field validation in their property editors. - if (scope.property) { //this can be null if no property was assigned - serverValidationManager.subscribe(scope.property.alias, "", function (isValid, propertyErrors, allErrors) { + if (currentProperty) { //this can be null if no property was assigned + serverValidationManager.subscribe(currentProperty.alias, currentCulture, "", function (isValid, propertyErrors, allErrors) { hasError = !isValid; if (hasError) { //set the error message to the server message @@ -183,7 +188,7 @@ function valPropertyMsg(serverValidationManager) { // but they are a different callback instance than the above. element.bind('$destroy', function () { stopWatch(); - serverValidationManager.unsubscribe(scope.property.alias, ""); + serverValidationManager.unsubscribe(currentProperty.alias, currentCulture, ""); }); } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js index 1432a713c0..b4492f8099 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserver.directive.js @@ -7,13 +7,14 @@ **/ function valServer(serverValidationManager) { return { - require: ['ngModel', '?^umbProperty'], + require: ['ngModel', '?^^umbProperty', '?^^tabbedContent'], restrict: "A", link: function (scope, element, attr, ctrls) { var modelCtrl = ctrls[0]; var umbPropCtrl = ctrls.length > 1 ? ctrls[1] : null; - if (!umbPropCtrl) { + var tabbedContent = ctrls.length > 2 ? ctrls[2] : null; + if (!umbPropCtrl || !tabbedContent) { //we cannot proceed, this validator will be disabled return; } @@ -54,6 +55,7 @@ function valServer(serverValidationManager) { } var currentProperty = umbPropCtrl.property; + var currentCulture = tabbedContent.content.language.culture; //default to 'value' if nothing is set var fieldName = "value"; @@ -66,7 +68,7 @@ function valServer(serverValidationManager) { } //subscribe to the server validation changes - serverValidationManager.subscribe(currentProperty.alias, fieldName, function (isValid, propertyErrors, allErrors) { + serverValidationManager.subscribe(currentProperty.alias, currentCulture, fieldName, function (isValid, propertyErrors, allErrors) { if (!isValid) { modelCtrl.$setValidity('valServer', false); //assign an error msg property to the current validator @@ -86,9 +88,9 @@ function valServer(serverValidationManager) { // but they are a different callback instance than the above. element.bind('$destroy', function () { stopWatch(); - serverValidationManager.unsubscribe(currentProperty.alias, fieldName); + serverValidationManager.unsubscribe(currentProperty.alias, currentCulture, fieldName); }); } }; } -angular.module('umbraco.directives.validation').directive("valServer", valServer); \ No newline at end of file +angular.module('umbraco.directives.validation').directive("valServer", valServer); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserverfield.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserverfield.directive.js index 29fd94ff5b..d170670d15 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserverfield.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserverfield.directive.js @@ -33,7 +33,7 @@ function valServerField(serverValidationManager) { })); //subscribe to the server validation changes - serverValidationManager.subscribe(null, fieldName, function (isValid, fieldErrors, allErrors) { + serverValidationManager.subscribe(null, null, fieldName, function (isValid, fieldErrors, allErrors) { if (!isValid) { ngModel.$setValidity('valServerField', false); //assign an error msg property to the current validator @@ -50,7 +50,7 @@ function valServerField(serverValidationManager) { // NOTE: this is very important otherwise when this controller re-binds the previous subscriptsion will remain // but they are a different callback instance than the above. element.bind('$destroy', function () { - serverValidationManager.unsubscribe(null, fieldName); + serverValidationManager.unsubscribe(null, null, fieldName); }); } }); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js index ac90a0d333..64ddf8c228 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js @@ -145,32 +145,33 @@ function formHelper(angularHelper, serverValidationManager, $timeout, notificati // that each property is a User Developer property editor. // The way that Content Type Editor ModelState is created is simply based on the ASP.Net validation data-annotations // system. - // So, to do this (since we need to support backwards compat), we need to hack a little bit. For Content Properties, - // which are user defined, we know that they will exist with a prefixed ModelState of "_Properties.", so if we detect - // this, then we know it's a Property. + // So, to do this there's some special ModelState syntax we need to know about. + // For Content Properties, which are user defined, we know that they will exist with a prefixed + // ModelState of "_Properties.", so if we detect this, then we know it's for a content Property. //the alias in model state can be in dot notation which indicates // * the first part is the content property alias // * the second part is the field to which the valiation msg is associated with - //There will always be at least 2 parts for properties since all model errors for properties are prefixed with "Properties" - //If it is not prefixed with "Properties" that means the error is for a field of the object directly. + //There will always be at least 3 parts for content properties since all model errors for properties are prefixed with "_Properties" + //If it is not prefixed with "_Properties" that means the error is for a field of the object directly. var parts = e.split("."); //Check if this is for content properties - specific to content/media/member editors because those are special // user defined properties with custom controls. - if (parts.length > 1 && parts[0] === "_Properties") { + if (parts.length > 2 && parts[0] === "_Properties") { var propertyAlias = parts[1]; + var culture = parts[2]; - //if it contains 2 '.' then we will wire it up to a property's field - if (parts.length > 2) { + //if it contains 3 '.' then we will wire it up to a property's html field + if (parts.length > 3) { //add an error with a reference to the field for which the validation belongs too - serverValidationManager.addPropertyError(propertyAlias, parts[2], modelState[e][0]); + serverValidationManager.addPropertyError(propertyAlias, culture, parts[3], modelState[e][0]); } else { - //add a generic error for the property, no reference to a specific field - serverValidationManager.addPropertyError(propertyAlias, "", modelState[e][0]); + //add a generic error for the property, no reference to a specific html field + serverValidationManager.addPropertyError(propertyAlias, culture, "", modelState[e][0]); } } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/servervalidationmgr.service.js b/src/Umbraco.Web.UI.Client/src/common/services/servervalidationmgr.service.js index d7e34d0f1c..41af17148b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/servervalidationmgr.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/servervalidationmgr.service.js @@ -28,11 +28,11 @@ function serverValidationManager($timeout) { //find errors for this field name return _.filter(self.items, function (item) { - return (item.propertyAlias === null && item.fieldName === fieldName); + return (item.propertyAlias === null && item.culture === null && item.fieldName === fieldName); }); } - function getPropertyErrors(self, propertyAlias, fieldName) { + function getPropertyErrors(self, propertyAlias, culture, fieldName) { if (!angular.isString(propertyAlias)) { throw "propertyAlias must be a string"; } @@ -42,7 +42,7 @@ function serverValidationManager($timeout) { //find all errors for this property return _.filter(self.items, function (item) { - return (item.propertyAlias === propertyAlias && (item.fieldName === fieldName || (fieldName === undefined || fieldName === ""))); + return (item.propertyAlias === propertyAlias && item.culture === culture && (item.fieldName === fieldName || (fieldName === undefined || fieldName === ""))); }); } @@ -104,7 +104,7 @@ function serverValidationManager($timeout) { * field alias to listen for. * If propertyAlias is null, then this subscription is for a field property (not a user defined property). */ - subscribe: function (propertyAlias, fieldName, callback) { + subscribe: function (propertyAlias, culture, fieldName, callback) { if (!callback) { return; } @@ -115,41 +115,46 @@ function serverValidationManager($timeout) { return item.propertyAlias === null && item.fieldName === fieldName; }); if (!exists1) { - callbacks.push({ propertyAlias: null, fieldName: fieldName, callback: callback }); + callbacks.push({ propertyAlias: null, culture: null, fieldName: fieldName, callback: callback }); } } else if (propertyAlias !== undefined) { + if (!culture) { + culture = null; // if empty or null, always make null + } //don't add it if it already exists var exists2 = _.find(callbacks, function (item) { - return item.propertyAlias === propertyAlias && item.fieldName === fieldName; + return item.propertyAlias === propertyAlias && item.culture === culture && item.fieldName === fieldName; }); if (!exists2) { - callbacks.push({ propertyAlias: propertyAlias, fieldName: fieldName, callback: callback }); + callbacks.push({ propertyAlias: propertyAlias, culture: culture, fieldName: fieldName, callback: callback }); } } }, - unsubscribe: function (propertyAlias, fieldName) { + unsubscribe: function (propertyAlias, culture, fieldName) { if (propertyAlias === null) { //remove all callbacks for the content field callbacks = _.reject(callbacks, function (item) { - return item.propertyAlias === null && item.fieldName === fieldName; + return item.propertyAlias === null && item.culture === null && item.fieldName === fieldName; }); } else if (propertyAlias !== undefined) { - + + if (!culture) { + culture = null; // if empty or null, always make null + } + //remove all callbacks for the content property callbacks = _.reject(callbacks, function (item) { - return item.propertyAlias === propertyAlias && + return item.propertyAlias === propertyAlias && item.culture === culture && (item.fieldName === fieldName || ((item.fieldName === undefined || item.fieldName === "") && (fieldName === undefined || fieldName === ""))); }); } - - }, @@ -164,10 +169,15 @@ function serverValidationManager($timeout) { * This will always return any callbacks registered for just the property (i.e. field name is empty) and for ones with an * explicit field name set. */ - getPropertyCallbacks: function (propertyAlias, fieldName) { + getPropertyCallbacks: function (propertyAlias, culture, fieldName) { + + if (!culture) { + culture = null; // if empty or null, always make null + } + var found = _.filter(callbacks, function (item) { //returns any callback that have been registered directly against the field and for only the property - return (item.propertyAlias === propertyAlias && (item.fieldName === fieldName || (item.fieldName === undefined || item.fieldName === ""))); + return (item.propertyAlias === propertyAlias && item.culture === culture && (item.fieldName === fieldName || (item.fieldName === undefined || item.fieldName === ""))); }); return found; }, @@ -184,7 +194,7 @@ function serverValidationManager($timeout) { getFieldCallbacks: function (fieldName) { var found = _.filter(callbacks, function (item) { //returns any callback that have been registered directly against the field - return (item.propertyAlias === null && item.fieldName === fieldName); + return (item.propertyAlias === null && item.culture === null && item.fieldName === fieldName); }); return found; }, @@ -207,6 +217,7 @@ function serverValidationManager($timeout) { if (!this.hasFieldError(fieldName)) { this.items.push({ propertyAlias: null, + culture: null, fieldName: fieldName, errorMsg: errorMsg }); @@ -231,24 +242,29 @@ function serverValidationManager($timeout) { * @description * Adds an error message for the content property */ - addPropertyError: function (propertyAlias, fieldName, errorMsg) { + addPropertyError: function (propertyAlias, culture, fieldName, errorMsg) { if (!propertyAlias) { return; } - + + if (!culture) { + culture = null; // if empty or null, always make null + } + //only add the item if it doesn't exist - if (!this.hasPropertyError(propertyAlias, fieldName)) { + if (!this.hasPropertyError(propertyAlias, culture, fieldName)) { this.items.push({ propertyAlias: propertyAlias, + culture: culture, fieldName: fieldName, errorMsg: errorMsg }); } //find all errors for this item - var errorsForCallback = getPropertyErrors(this, propertyAlias, fieldName); + var errorsForCallback = getPropertyErrors(this, propertyAlias, culture, fieldName); //we should now call all of the call backs registered for this error - var cbs = this.getPropertyCallbacks(propertyAlias, fieldName); + var cbs = this.getPropertyCallbacks(propertyAlias, culture, fieldName); //call each callback for this error for (var cb in cbs) { executeCallback(this, errorsForCallback, cbs[cb].callback); @@ -264,14 +280,14 @@ function serverValidationManager($timeout) { * @description * Removes an error message for the content property */ - removePropertyError: function (propertyAlias, fieldName) { + removePropertyError: function (propertyAlias, culture, fieldName) { if (!propertyAlias) { return; } //remove the item this.items = _.reject(this.items, function (item) { - return (item.propertyAlias === propertyAlias && (item.fieldName === fieldName || (fieldName === undefined || fieldName === ""))); + return (item.propertyAlias === propertyAlias && item.culture === culture && (item.fieldName === fieldName || (fieldName === undefined || fieldName === ""))); }); }, @@ -316,10 +332,10 @@ function serverValidationManager($timeout) { * @description * Gets the error message for the content property */ - getPropertyError: function (propertyAlias, fieldName) { + getPropertyError: function (propertyAlias, culture, fieldName) { var err = _.find(this.items, function (item) { //return true if the property alias matches and if an empty field name is specified or the field name matches - return (item.propertyAlias === propertyAlias && (item.fieldName === fieldName || (fieldName === undefined || fieldName === ""))); + return (item.propertyAlias === propertyAlias && item.culture === culture && (item.fieldName === fieldName || (fieldName === undefined || fieldName === ""))); }); return err; }, @@ -336,7 +352,7 @@ function serverValidationManager($timeout) { getFieldError: function (fieldName) { var err = _.find(this.items, function (item) { //return true if the property alias matches and if an empty field name is specified or the field name matches - return (item.propertyAlias === null && item.fieldName === fieldName); + return (item.propertyAlias === null && item.culture === null && item.fieldName === fieldName); }); return err; }, @@ -348,12 +364,12 @@ function serverValidationManager($timeout) { * @function * * @description - * Checks if the content property + field name combo has an error + * Checks if the content property + culture + field name combo has an error */ - hasPropertyError: function (propertyAlias, fieldName) { + hasPropertyError: function (propertyAlias, culture, fieldName) { var err = _.find(this.items, function (item) { //return true if the property alias matches and if an empty field name is specified or the field name matches - return (item.propertyAlias === propertyAlias && (item.fieldName === fieldName || (fieldName === undefined || fieldName === ""))); + return (item.propertyAlias === propertyAlias && item.culture === culture && (item.fieldName === fieldName || (fieldName === undefined || fieldName === ""))); }); return err ? true : false; }, @@ -370,7 +386,7 @@ function serverValidationManager($timeout) { hasFieldError: function (fieldName) { var err = _.find(this.items, function (item) { //return true if the property alias matches and if an empty field name is specified or the field name matches - return (item.propertyAlias === null && item.fieldName === fieldName); + return (item.propertyAlias === null && item.culture === null && item.fieldName === fieldName); }); return err ? true : false; }, @@ -380,4 +396,4 @@ function serverValidationManager($timeout) { }; } -angular.module('umbraco.services').factory('serverValidationManager', serverValidationManager); \ No newline at end of file +angular.module('umbraco.services').factory('serverValidationManager', serverValidationManager); diff --git a/src/Umbraco.Web.UI.Client/src/views/components/content/tabbed-content.html b/src/Umbraco.Web.UI.Client/src/views/components/content/tabbed-content.html new file mode 100644 index 0000000000..eb7a541a42 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/components/content/tabbed-content.html @@ -0,0 +1,17 @@ +
+
+ +
+
{{ group.label }}
+   +
+ +
+ + + + +
+ +
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property.html b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property.html index 24bc1de6ed..a6f2096002 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property.html @@ -2,7 +2,7 @@
- +
@@ -19,4 +19,4 @@
- \ No newline at end of file + diff --git a/src/Umbraco.Web.UI.Client/src/views/content/apps/content/content.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/apps/content/content.controller.js index 3e30b25a94..cb3f0e6be3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/apps/content/content.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/apps/content/content.controller.js @@ -6,14 +6,9 @@ var vm = this; vm.loading = true; + //TODO: Figure out what we need to do to maintain validation states since this will re-init the editor function onInit() { - vm.content = $scope.model.viewModel; - - angular.forEach(vm.content.tabs, function (group) { - group.open = true; - }); - vm.loading = false; } diff --git a/src/Umbraco.Web.UI.Client/src/views/content/apps/content/content.html b/src/Umbraco.Web.UI.Client/src/views/content/apps/content/content.html index db71539c59..76d939a81e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/apps/content/content.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/apps/content/content.html @@ -1,18 +1,5 @@
-
- -
-
{{ group.label }}
-   -
- -
- - - -
- -
- + +
diff --git a/src/Umbraco.Web.UI.Client/test/unit/common/services/server-validation-manager.spec.js b/src/Umbraco.Web.UI.Client/test/unit/common/services/server-validation-manager.spec.js index 2740bd7317..7510b766a8 100644 --- a/src/Umbraco.Web.UI.Client/test/unit/common/services/server-validation-manager.spec.js +++ b/src/Umbraco.Web.UI.Client/test/unit/common/services/server-validation-manager.spec.js @@ -60,12 +60,12 @@ it('can retrieve property validation errors for a sub field', function () { //arrange - serverValidationManager.addPropertyError("myProperty", "value1", "Some value 1"); - serverValidationManager.addPropertyError("myProperty", "value2", "Another value 2"); + serverValidationManager.addPropertyError("myProperty", null, "value1", "Some value 1"); + serverValidationManager.addPropertyError("myProperty", null, "value2", "Another value 2"); //act - var err1 = serverValidationManager.getPropertyError("myProperty", "value1"); - var err2 = serverValidationManager.getPropertyError("myProperty", "value2"); + var err1 = serverValidationManager.getPropertyError("myProperty", null, "value1"); + var err2 = serverValidationManager.getPropertyError("myProperty", null, "value2"); //assert expect(err1).not.toBeUndefined(); @@ -82,8 +82,8 @@ it('can add a property errors with multiple sub fields and it the first will be retreived with only the property alias', function () { //arrange - serverValidationManager.addPropertyError("myProperty", "value1", "Some value 1"); - serverValidationManager.addPropertyError("myProperty", "value2", "Another value 2"); + serverValidationManager.addPropertyError("myProperty", null, "value1", "Some value 1"); + serverValidationManager.addPropertyError("myProperty", null, "value2", "Another value 2"); //act var err = serverValidationManager.getPropertyError("myProperty"); @@ -98,10 +98,10 @@ it('will return null for a non-existing property error', function () { //arrage - serverValidationManager.addPropertyError("myProperty", "value", "Required"); + serverValidationManager.addPropertyError("myProperty", null, "value", "Required"); //act - var err = serverValidationManager.getPropertyError("DoesntExist", "value"); + var err = serverValidationManager.getPropertyError("DoesntExist", null, "value"); //assert expect(err).toBeUndefined(); @@ -111,15 +111,15 @@ it('detects if a property error exists', function () { //arrange - serverValidationManager.addPropertyError("myProperty", "value1", "Some value 1"); - serverValidationManager.addPropertyError("myProperty", "value2", "Another value 2"); + serverValidationManager.addPropertyError("myProperty", null, "value1", "Some value 1"); + serverValidationManager.addPropertyError("myProperty", null, "value2", "Another value 2"); //act var err1 = serverValidationManager.hasPropertyError("myProperty"); - var err2 = serverValidationManager.hasPropertyError("myProperty", "value1"); - var err3 = serverValidationManager.hasPropertyError("myProperty", "value2"); + var err2 = serverValidationManager.hasPropertyError("myProperty", null, "value1"); + var err3 = serverValidationManager.hasPropertyError("myProperty", null, "value2"); var err4 = serverValidationManager.hasPropertyError("notFound"); - var err5 = serverValidationManager.hasPropertyError("myProperty", "notFound"); + var err5 = serverValidationManager.hasPropertyError("myProperty", null, "notFound"); //assert expect(err1).toBe(true); @@ -133,30 +133,30 @@ it('can remove a property error with a sub field specified', function () { //arrage - serverValidationManager.addPropertyError("myProperty", "value1", "Some value 1"); - serverValidationManager.addPropertyError("myProperty", "value2", "Another value 2"); + serverValidationManager.addPropertyError("myProperty", null, "value1", "Some value 1"); + serverValidationManager.addPropertyError("myProperty", null, "value2", "Another value 2"); //act - serverValidationManager.removePropertyError("myProperty", "value1"); + serverValidationManager.removePropertyError("myProperty", null, "value1"); //assert - expect(serverValidationManager.hasPropertyError("myProperty", "value1")).toBe(false); - expect(serverValidationManager.hasPropertyError("myProperty", "value2")).toBe(true); + expect(serverValidationManager.hasPropertyError("myProperty", null, "value1")).toBe(false); + expect(serverValidationManager.hasPropertyError("myProperty", null, "value2")).toBe(true); }); it('can remove a property error and all sub field errors by specifying only the property', function () { //arrage - serverValidationManager.addPropertyError("myProperty", "value1", "Some value 1"); - serverValidationManager.addPropertyError("myProperty", "value2", "Another value 2"); + serverValidationManager.addPropertyError("myProperty", null, "value1", "Some value 1"); + serverValidationManager.addPropertyError("myProperty", null, "value2", "Another value 2"); //act serverValidationManager.removePropertyError("myProperty"); //assert - expect(serverValidationManager.hasPropertyError("myProperty", "value1")).toBe(false); - expect(serverValidationManager.hasPropertyError("myProperty", "value2")).toBe(false); + expect(serverValidationManager.hasPropertyError("myProperty", null, "value1")).toBe(false); + expect(serverValidationManager.hasPropertyError("myProperty", null, "value2")).toBe(false); }); @@ -168,7 +168,7 @@ var args; //arrange - serverValidationManager.subscribe(null, "Name", function (isValid, propertyErrors, allErrors) { + serverValidationManager.subscribe(null, null, "Name", function (isValid, propertyErrors, allErrors) { args = { isValid: isValid, propertyErrors: propertyErrors, @@ -178,7 +178,7 @@ //act serverValidationManager.addFieldError("Name", "Required"); - serverValidationManager.addPropertyError("myProperty", "value1", "Some value 1"); + serverValidationManager.addPropertyError("myProperty", null, "value1", "Some value 1"); //assert expect(args).not.toBeUndefined(); @@ -195,8 +195,8 @@ }; var cb2 = function () { }; - serverValidationManager.subscribe(null, "Name", cb1); - serverValidationManager.subscribe(null, "Title", cb2); + serverValidationManager.subscribe(null, null, "Name", cb1); + serverValidationManager.subscribe(null, null, "Title", cb2); //act serverValidationManager.addFieldError("Name", "Required"); @@ -224,7 +224,7 @@ var numCalled = 0; //arrange - serverValidationManager.subscribe("myProperty", "value1", function (isValid, propertyErrors, allErrors) { + serverValidationManager.subscribe("myProperty", null, "value1", function (isValid, propertyErrors, allErrors) { args1 = { isValid: isValid, propertyErrors: propertyErrors, @@ -232,7 +232,7 @@ }; }); - serverValidationManager.subscribe("myProperty", "", function (isValid, propertyErrors, allErrors) { + serverValidationManager.subscribe("myProperty", null, "", function (isValid, propertyErrors, allErrors) { numCalled++; args2 = { isValid: isValid, @@ -242,9 +242,9 @@ }); //act - serverValidationManager.addPropertyError("myProperty", "value1", "Some value 1"); - serverValidationManager.addPropertyError("myProperty", "value2", "Some value 2"); - serverValidationManager.addPropertyError("myProperty", "", "Some value 3"); + serverValidationManager.addPropertyError("myProperty", null, "value1", "Some value 1"); + serverValidationManager.addPropertyError("myProperty", null, "value2", "Some value 2"); + serverValidationManager.addPropertyError("myProperty", null, "", "Some value 3"); //assert expect(args1).not.toBeUndefined(); @@ -272,4 +272,4 @@ }); -}); \ No newline at end of file +}); diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index 4f419ccece..98ad4ea404 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -2063,6 +2063,9 @@ To manage your website, simply open the Umbraco back office and start adding con Invalid date Not a number Invalid email + Value cannot be null + Value cannot be empty + Value is invalid, it does not match the correct pattern