diff --git a/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js b/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js
index fe57534ffb..d744f8277f 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js
@@ -730,7 +730,7 @@
return null;
}
- var dataModel = getDataByUdi(layoutEntry.udi, this.value.contentData);
+ var dataModel = getDataByUdi(layoutEntry.contentUdi, this.value.contentData);
if (dataModel === null) {
return null;
}
diff --git a/src/Umbraco.Web.UI.Client/src/less/alerts.less b/src/Umbraco.Web.UI.Client/src/less/alerts.less
index 3907b59f58..3539e21064 100644
--- a/src/Umbraco.Web.UI.Client/src/less/alerts.less
+++ b/src/Umbraco.Web.UI.Client/src/less/alerts.less
@@ -7,6 +7,7 @@
// -------------------------
.alert {
+ position: relative;
padding: 8px 35px 8px 14px;
margin-bottom: @baseLineHeight;
background-color: @warningBackground;
@@ -98,3 +99,29 @@
.alert-block p + p {
margin-top: 5px;
}
+
+
+// Property error alerts
+// -------------------------
+.alert.property-error {
+
+ display: inline-block;
+ font-size: 14px;
+ padding: 6px 16px 6px 12px;
+ margin-bottom: 6px;
+
+ &::after {
+ content:'';
+ position: absolute;
+ bottom:-6px;
+ left: 6px;
+ width: 0;
+ height: 0;
+ border-left: 6px solid transparent;
+ border-right: 6px solid transparent;
+ border-top: 6px solid;
+ }
+ &.alert-error::after {
+ border-top-color: @errorBackground;
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-variant-switcher.less b/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-variant-switcher.less
index 8dbc070856..eae25b273c 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-variant-switcher.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-variant-switcher.less
@@ -50,6 +50,19 @@ button.umb-variant-switcher__toggle {
font-weight: bold;
background-color: @errorBackground;
color: @errorText;
+
+ animation-duration: 1.4s;
+ animation-iteration-count: infinite;
+ animation-name: umb-variant-switcher__toggle--badge-bounce;
+ animation-timing-function: ease;
+ @keyframes umb-variant-switcher__toggle--badge-bounce {
+ 0% { transform: translateY(0); }
+ 20% { transform: translateY(-6px); }
+ 40% { transform: translateY(0); }
+ 55% { transform: translateY(-3px); }
+ 70% { transform: translateY(0); }
+ 100% { transform: translateY(0); }
+ }
}
}
}
@@ -226,6 +239,19 @@ button.umb-variant-switcher__toggle {
font-weight: bold;
background-color: @errorBackground;
color: @errorText;
+
+ animation-duration: 1.4s;
+ animation-iteration-count: infinite;
+ animation-name: umb-variant-switcher__name--badge-bounce;
+ animation-timing-function: ease;
+ @keyframes umb-variant-switcher__name--badge-bounce {
+ 0% { transform: translateY(0); }
+ 20% { transform: translateY(-6px); }
+ 40% { transform: translateY(0); }
+ 55% { transform: translateY(-3px); }
+ 70% { transform: translateY(0); }
+ 100% { transform: translateY(0); }
+ }
}
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less
index cb673e3c6f..2fc705b11b 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less
@@ -53,6 +53,39 @@
height: 4px;
}
}
+
+ // Validation
+ .show-validation &.-has-error {
+ color: @red;
+
+ &:hover {
+ color: @red !important;
+ }
+
+ &::before {
+ background-color: @red;
+ }
+
+ &:not(.is-active) {
+ .badge {
+ animation-duration: 1.4s;
+ animation-iteration-count: infinite;
+ animation-name: umb-sub-views-nav-item--badge-bounce;
+ animation-timing-function: ease;
+ @keyframes umb-sub-views-nav-item--badge-bounce {
+ 0% { transform: translateY(0); }
+ 20% { transform: translateY(-6px); }
+ 40% { transform: translateY(0); }
+ 55% { transform: translateY(-3px); }
+ 70% { transform: translateY(0); }
+ 100% { transform: translateY(0); }
+ }
+ }
+ .badge.--error-badge {
+ display: block;
+ }
+ }
+ }
}
&__action:active,
@@ -101,6 +134,10 @@
height: 12px;
min-width: 12px;
}
+ &.--error-badge {
+ display: none;
+ font-weight: 900;
+ }
}
&-text {
@@ -182,13 +219,3 @@
}
}
}
-
-// Validation
-.show-validation .umb-sub-views-nav-item__action.-has-error,
-.show-validation .umb-sub-views-nav-item > a.-has-error {
- color: @red;
-
- &::before {
- background-color: @red;
- }
-}
diff --git a/src/Umbraco.Web.UI.Client/src/less/main.less b/src/Umbraco.Web.UI.Client/src/less/main.less
index ce20b8dc88..2354e96d38 100644
--- a/src/Umbraco.Web.UI.Client/src/less/main.less
+++ b/src/Umbraco.Web.UI.Client/src/less/main.less
@@ -272,6 +272,7 @@ label:not([for]) {
/* CONTROL VALIDATION */
.umb-control-required {
color: @controlRequiredColor;
+ font-weight: 900;
}
.controls-row {
diff --git a/src/Umbraco.Web.UI.Client/src/less/mixins.less b/src/Umbraco.Web.UI.Client/src/less/mixins.less
index a87080a326..9739a90dae 100644
--- a/src/Umbraco.Web.UI.Client/src/less/mixins.less
+++ b/src/Umbraco.Web.UI.Client/src/less/mixins.less
@@ -138,7 +138,9 @@
// additional targetting of the ng-invalid class.
.formFieldState(@textColor: @gray-4, @borderColor: @gray-7, @backgroundColor: @gray-10) {
// Set the text color
- .control-label,
+ > .control-label,
+ > .umb-el-wrap > .control-label,
+ > .umb-el-wrap > .control-header > .control-label,
.help-block,
.help-inline {
color: @textColor;
diff --git a/src/Umbraco.Web.UI.Client/src/less/variables.less b/src/Umbraco.Web.UI.Client/src/less/variables.less
index 2f627f3ab3..840c6d529f 100644
--- a/src/Umbraco.Web.UI.Client/src/less/variables.less
+++ b/src/Umbraco.Web.UI.Client/src/less/variables.less
@@ -481,7 +481,7 @@
@formErrorText: @errorBackground;
@formErrorBackground: lighten(@errorBackground, 55%);
-@formErrorBorder: darken(spin(@errorBackground, -10), 3%);
+@formErrorBorder: @red;
@formSuccessText: @successBackground;
@formSuccessBackground: lighten(@successBackground, 48%);
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js
index f515cbb4ba..af13ef6241 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js
@@ -1,6 +1,6 @@
angular.module("umbraco")
.controller("Umbraco.Editors.BlockEditorController",
- function ($scope, localizationService, formHelper) {
+ function ($scope, localizationService, formHelper, overlayService) {
var vm = this;
vm.model = $scope.model;
@@ -42,6 +42,7 @@ angular.module("umbraco")
vm.submitAndClose = function () {
if (vm.model && vm.model.submit) {
+
// always keep server validations since this will be a nested editor and server validations are global
if (formHelper.submitForm({
scope: $scope,
@@ -49,13 +50,16 @@ angular.module("umbraco")
keepServerValidation: true
})) {
vm.model.submit(vm.model);
+ vm.saveButtonState = "success";
+ } else {
+ vm.saveButtonState = "error";
}
}
}
vm.close = function () {
if (vm.model && vm.model.close) {
- // TODO: At this stage there could very well have been server errors that have been cleared
+ // TODO: At this stage there could very well have been server errors that have been cleared
// but if we 'close' we are basically cancelling the value changes which means we'd want to cancel
// all of the server errors just cleared. It would be possible to do that but also quite annoying.
// The rudimentary way would be to:
@@ -67,6 +71,29 @@ angular.module("umbraco")
// * It would have a 'commit' method to commit the removed errors - which we would call in the formHelper.submitForm when it's successful
// * It would have a 'rollback' method to reset the removed errors - which we would call here
+
+ if (vm.blockForm.$dirty === true) {
+ localizationService.localizeMany(["prompt_discardChanges", "blockEditor_blockHasChanges"]).then(function (localizations) {
+ const confirm = {
+ title: localizations[0],
+ view: "default",
+ content: localizations[1],
+ submitButtonLabelKey: "general_discard",
+ submitButtonStyle: "danger",
+ closeButtonLabelKey: "general_cancel",
+ submit: function () {
+ overlayService.close();
+ vm.model.close(vm.model);
+ },
+ close: function () {
+ overlayService.close();
+ }
+ };
+ overlayService.open(confirm);
+ });
+
+ return;
+ }
// TODO: check if content/settings has changed and ask user if they are sure.
vm.model.close(vm.model);
}
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.html
index de18f13d2c..dfcfd48887 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.html
+++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.html
@@ -44,7 +44,7 @@