From 47986ec0f59a6f73544ac312739c4a79aa1fd66d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Thu, 30 Jul 2020 15:01:29 +0200
Subject: [PATCH 01/89] limit control-label effect to the first control-label,
these 3 new lines covers all cases that i could find in CMS.
---
src/Umbraco.Web.UI.Client/src/less/mixins.less | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/less/mixins.less b/src/Umbraco.Web.UI.Client/src/less/mixins.less
index a87080a326cb..9739a90dae7a 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;
From 55805eabc3ab87571f23b9f40e60cc8fa4b7ea6a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Thu, 30 Jul 2020 15:26:40 +0200
Subject: [PATCH 02/89] make the required-star as bold as possible.
---
src/Umbraco.Web.UI.Client/src/less/main.less | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Umbraco.Web.UI.Client/src/less/main.less b/src/Umbraco.Web.UI.Client/src/less/main.less
index ce20b8dc88f5..2354e96d38c7 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 {
From 33afbb8af6c4cb9127d46a36d447adb3e99b69b5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Thu, 30 Jul 2020 16:13:22 +0200
Subject: [PATCH 03/89] added validation-error badge to navigation item
---
.../src/less/components/umb-editor-navigation-item.less | 8 ++++++++
.../components/editor/umb-editor-navigation-item.html | 1 +
2 files changed, 9 insertions(+)
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 cb673e3c6f79..c2f3e0f04d15 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
@@ -101,6 +101,10 @@
height: 12px;
min-width: 12px;
}
+ &.--error-badge {
+ display: none;
+ font-weight: 900;
+ }
}
&-text {
@@ -191,4 +195,8 @@
&::before {
background-color: @red;
}
+ .badge.--error-badge {
+ display: block;
+ }
+
}
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation-item.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation-item.html
index 484e0175c560..9e5669f443e4 100644
--- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation-item.html
+++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation-item.html
@@ -9,6 +9,7 @@
{{ vm.item.name }}
{{vm.item.badge.count}}
+ !
-
+
+
+
-
+
+
+
-
+
+ on-confirm="vm.performDelete"
+ on-cancel="vm.cancel"
+ confirm-button-style="danger"
+ confirm-label-key="general_delete">
diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.html
index 5aba520b9b9b..135796519768 100644
--- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.html
+++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.html
@@ -86,7 +86,8 @@ Create an item under {{current
+ text="Create template for the Parent Document Type">
+
@@ -96,7 +97,8 @@ Create an item under {{current
+ text="Create template for the Item Document Type">
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/logviewer/search.html b/src/Umbraco.Web.UI.Client/src/views/logviewer/search.html
index b4f910fd7b16..6f828ac49f4a 100644
--- a/src/Umbraco.Web.UI.Client/src/views/logviewer/search.html
+++ b/src/Umbraco.Web.UI.Client/src/views/logviewer/search.html
@@ -39,7 +39,11 @@
-
+
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html
index 9f91e1d0f7cc..45e2a4e376df 100644
--- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html
+++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html
@@ -122,73 +122,81 @@
on-remove="vm.removeContentItem()">
-
+
+
+
+
+
-
-
+
+
-
+
+
-
+
+
-
+
+
-
+
+
-
+
+
-
+
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html
index 15b66d856d3c..1240a61fbb9c 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html
@@ -1,50 +1,49 @@
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+ {{ layout.name }}
+ (system layout)
+
+
+
+
-
-
-
-
- {{ layout.name }}
- (system layout)
-
-
-
-
-
-
-
+
-
+
-
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/orderDirection.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/orderDirection.prevalues.html
index 7ec089593695..b6028ad5bb31 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/orderDirection.prevalues.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/orderDirection.prevalues.html
@@ -2,10 +2,20 @@
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/radiobuttons/radiobuttons.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/radiobuttons/radiobuttons.html
index 1c3aa898dbe9..82952193e792 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/radiobuttons/radiobuttons.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/radiobuttons/radiobuttons.html
@@ -3,7 +3,12 @@
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.html
index ee2929e3ea63..d70f469e6fe7 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.html
@@ -2,22 +2,22 @@
-
+
+
-
+
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.html b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.html
index beb1962b4ee5..4d8d94e1aa40 100644
--- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.html
+++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.html
@@ -14,13 +14,19 @@
-
-
diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/views/relationType.html b/src/Umbraco.Web.UI.Client/src/views/relationtypes/views/relationType.html
index 043ced9a5fe4..100d8d9d09a1 100644
--- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/views/relationType.html
+++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/views/relationType.html
@@ -11,10 +11,18 @@
From d5f658f0c12f6213b565bcd029c41a6696cd9084 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Fri, 7 Aug 2020 14:08:38 +0200
Subject: [PATCH 39/89] rename postFormSubmitting to formSubmittingFinalPhase
---
.../services/blockeditormodelobject.service.js | 4 ++--
.../src/common/services/formhelper.service.js | 12 ++++++------
.../inlineblock/inlineblock.editor.controller.js | 4 ++--
3 files changed, 10 insertions(+), 10 deletions(-)
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 9964dac34306..0e9abf85038c 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
@@ -331,7 +331,7 @@
this.isolatedScope.blockObjects = {};
this.__watchers.push(this.isolatedScope.$on("$destroy", this.destroy.bind(this)));
- this.__watchers.push(propertyEditorScope.$on("postFormSubmitting", this.sync.bind(this)));
+ this.__watchers.push(propertyEditorScope.$on("formSubmittingFinalPhase", this.sync.bind(this)));
};
@@ -356,7 +356,7 @@
// re-create the watchers
this.__watchers = [];
this.__watchers.push(this.isolatedScope.$on("$destroy", this.destroy.bind(this)));
- this.__watchers.push(propertyEditorScope.$on("postFormSubmitting", this.sync.bind(this)));
+ this.__watchers.push(propertyEditorScope.$on("formSubmittingFinalPhase", this.sync.bind(this)));
},
/**
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 962961729b43..c2f4fb6d68fe 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
@@ -17,10 +17,10 @@ function formHelper(angularHelper, serverValidationManager, notificationsService
* @function
*
* @description
- * Called by controllers when submitting a form - this ensures that all client validation is checked,
+ * Called by controllers when submitting a form - this ensures that all client validation is checked,
* server validation is cleared, that the correct events execute and status messages are displayed.
* This returns true if the form is valid, otherwise false if form submission cannot continue.
- *
+ *
* @param {object} args An object containing arguments for form submission
*/
submitForm: function (args) {
@@ -45,7 +45,7 @@ function formHelper(angularHelper, serverValidationManager, notificationsService
args.scope.$broadcast("formSubmitting", { scope: args.scope, action: args.action });
// Some property editors need to perform an action after all property editors have reacted to the formSubmitting.
- args.scope.$broadcast("postFormSubmitting", { scope: args.scope, action: args.action });
+ args.scope.$broadcast("formSubmittingFinalPhase", { scope: args.scope, action: args.action });
//then check if the form is valid
if (!args.skipValidation) {
@@ -73,7 +73,7 @@ function formHelper(angularHelper, serverValidationManager, notificationsService
*
* @description
* Called by controllers when a form has been successfully submitted, this ensures the correct events are raised.
- *
+ *
* @param {object} args An object containing arguments for form submission
*/
resetForm: function (args) {
@@ -109,7 +109,7 @@ function formHelper(angularHelper, serverValidationManager, notificationsService
* @description
* Needs to be called when a form submission fails, this will wire up all server validation errors in ModelState and
* add the correct messages to the notifications. If a server error has occurred this will show a ysod.
- *
+ *
* @param {object} err The error object returned from the http promise
*/
handleError: function (err) {
@@ -148,7 +148,7 @@ function formHelper(angularHelper, serverValidationManager, notificationsService
*
* @description
* This wires up all of the server validation model state so that valServer and valServerField directives work
- *
+ *
* @param {object} err The error object returned from the http promise
*/
handleServerValidation: function (modelState) {
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.controller.js
index c2c86ca8242b..06c14248382c 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.controller.js
@@ -12,8 +12,8 @@
// boardcast the formSubmitting event to trigger syncronization or none-live property-editors
$scope.$broadcast("formSubmitting", { scope: $scope });
// Some property editors need to performe an action after all property editors have reacted to the formSubmitting.
- $scope.$broadcast("postFormSubmitting", { scope: $scope });
-
+ $scope.$broadcast("formSubmittingFinalPhase", { scope: $scope });
+
block.active = false;
} else {
$scope.api.activateBlock(block);
From 015dc9944a773ef4cc3a185212aaadadc21ddb0f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Fri, 7 Aug 2020 15:04:24 +0200
Subject: [PATCH 40/89] set settingsPreview when updated
---
.../prevalue/blocklist.blockconfiguration.overlay.controller.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js
index cc3e85494acf..b1937e718d76 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js
@@ -100,6 +100,7 @@
};
vm.applySettingsToBlock = function(block, key) {
block.settingsElementTypeKey = key;
+ vm.settingsPreview = vm.getElementTypeByKey(vm.block.settingsElementTypeKey);
};
vm.requestRemoveSettingsForBlock = function(block) {
From 35b66529493058cbde8a0df806d9d11df82b0ec5 Mon Sep 17 00:00:00 2001
From: Shannon Deminick
Date: Fri, 7 Aug 2020 23:37:32 +1000
Subject: [PATCH 41/89] Fix server validation issue with block editor due to
cultures not being carried over correctly (#8594)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Niels Lyngsø
---
.../application/umblogin.directive.js | 1 +
.../components/content/edit.controller.js | 1 +
.../validation/valformmanager.directive.js | 5 +-
.../validation/valpropertymsg.directive.js | 10 ++-
.../validation/valservermatch.directive.js | 2 +
.../blockeditormodelobject.service.js | 3 +-
.../services/contenteditinghelper.service.js | 3 +
.../src/common/services/formhelper.service.js | 19 +++-
.../common/overlays/user/user.controller.js | 2 +-
.../content.createblueprint.controller.js | 88 +++++++++----------
.../src/views/datatypes/create.controller.js | 3 +-
.../datatypes/datatype.edit.controller.js | 1 +
.../dictionary.create.controller.js | 3 +-
.../dictionary/dictionary.edit.controller.js | 4 +-
.../views/documenttypes/create.controller.js | 8 +-
.../src/views/languages/edit.controller.js | 2 +-
.../views/macros/macros.create.controller.js | 3 +-
.../views/macros/macros.edit.controller.js | 3 +-
.../src/views/media/media.edit.controller.js | 1 +
.../src/views/mediatypes/create.controller.js | 5 +-
.../views/member/member.edit.controller.js | 2 +-
.../src/views/membergroups/edit.controller.js | 1 +
.../views/membertypes/create.controller.js | 4 +-
.../src/views/packages/edit.controller.js | 3 +-
.../partialviewmacros/create.controller.js | 3 +-
.../views/partialviews/create.controller.js | 3 +-
.../umbBlockListPropertyEditor.component.js | 45 +++++++---
.../views/relationtypes/create.controller.js | 3 +-
.../views/relationtypes/edit.controller.js | 3 +-
.../src/views/scripts/create.controller.js | 11 +--
.../views/stylesheets/create.controller.js | 15 ++--
.../src/views/users/user.controller.js | 6 +-
32 files changed, 167 insertions(+), 99 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umblogin.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umblogin.directive.js
index c2b298ad2409..43598593f441 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umblogin.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umblogin.directive.js
@@ -168,6 +168,7 @@
vm.inviteStep = 2;
}, function (err) {
+ formHelper.resetForm({ scope: $scope, hasErrors: true });
formHelper.handleError(err);
vm.invitedUserPasswordModel.buttonState = "error";
});
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js
index e3c2913e4ede..d02c48750adb 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js
@@ -581,6 +581,7 @@
eventsService.emit("content.unpublished", { content: $scope.content });
overlayService.close();
}, function (err) {
+ formHelper.resetForm({ scope: $scope, hasErrors: true });
$scope.page.buttonGroupState = 'error';
handleHttpException(err);
});
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js
index 47f114560095..77c26e066e62 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js
@@ -159,9 +159,6 @@ function valFormManager(serverValidationManager, $rootScope, $timeout, $location
element.removeClass(SHOW_VALIDATION_CLASS_NAME);
scope.showValidation = false;
notifySubView();
- //clear form state as at this point we retrieve new data from the server
- //and all validation will have cleared at this point
- formCtrl.$setPristine();
}));
var confirmed = false;
@@ -238,6 +235,8 @@ function valFormManager(serverValidationManager, $rootScope, $timeout, $location
}
});
+ // TODO: I'm unsure why this exists, i believe this may be a hack for something like tinymce which might automatically
+ // change a form value on load but we need it to be $pristine?
$timeout(function () {
formCtrl.$setPristine();
}, 1000);
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 979ac23bb305..26c0403f8584 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
@@ -306,7 +306,15 @@ function valPropertyMsg(serverValidationManager, localizationService, angularHel
formCtrl.$setValidity('valPropertyMsg', false);
startWatch();
-
+ // This check is required in order to be able to reset ourselves and is typically for complex editor
+ // scenarios where the umb-property itself doesn't contain any ng-model controls which means that the
+ // above serverValidityResetter technique will not work to clear valPropertyMsg errors.
+ // In order for this to work we rely on the current form controller's $pristine state. This means that anytime
+ // the form is submitted whether there are validation errors or not the state must be reset... this is automatically
+ // taken care of with the formHelper.resetForm method that should be used in all cases. $pristine is required because it's
+ // a value that is cascaded to all form controls based on the hierarchy of child ng-model controls. This allows us to easily
+ // know if a value has changed. The alternative is what we used to do which was to put a deep $watch on the entire complex value
+ // which is hugely inefficient.
if (propertyErrors.length === 1 && hadError && !formCtrl.$pristine) {
var propertyValidationPath = umbPropCtrl.getValidationPath();
serverValidationManager.removePropertyError(propertyValidationPath, currentCulture, "", currentSegment);
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valservermatch.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valservermatch.directive.js
index 1b4c593735e0..5f8600c8c0fe 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valservermatch.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valservermatch.directive.js
@@ -54,6 +54,8 @@ function valServerMatch(serverValidationManager) {
function bindCallback(validationKey, matchVal, matchType) {
+ if (!matchVal) return;
+
if (Utilities.isString(matchVal)) {
matchVal = [matchVal]; // normalize to an array since the value can also natively be an array
}
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 0e9abf85038c..5cc717be4672 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
@@ -351,7 +351,8 @@
// update our values
this.value = propertyModelValue;
this.value.layout = this.value.layout || {};
- this.value.data = this.value.data || [];
+ this.value.contentData = this.value.contentData || [];
+ this.value.settingsData = this.value.settingsData || [];
// re-create the watchers
this.__watchers = [];
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js
index cda10ee6df89..4ffd0c3c0b23 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js
@@ -117,6 +117,9 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt
return $q.resolve(data);
}, function (err) {
+
+ formHelper.resetForm({ scope: args.scope, hasErrors: true });
+
self.handleSaveError({
showNotifications: args.showNotifications,
softRedirect: args.softRedirect,
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 c2f4fb6d68fe..5866e28b1ece 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
@@ -47,6 +47,9 @@ function formHelper(angularHelper, serverValidationManager, notificationsService
// Some property editors need to perform an action after all property editors have reacted to the formSubmitting.
args.scope.$broadcast("formSubmittingFinalPhase", { scope: args.scope, action: args.action });
+ // Set the form state to submitted
+ currentForm.$setSubmitted();
+
//then check if the form is valid
if (!args.skipValidation) {
if (currentForm.$invalid) {
@@ -77,14 +80,28 @@ function formHelper(angularHelper, serverValidationManager, notificationsService
* @param {object} args An object containing arguments for form submission
*/
resetForm: function (args) {
+
+ var currentForm;
+
if (!args) {
throw "args cannot be null";
}
if (!args.scope) {
throw "args.scope cannot be null";
}
+ if (!args.formCtrl) {
+ //try to get the closest form controller
+ currentForm = angularHelper.getRequiredCurrentForm(args.scope);
+ }
+ else {
+ currentForm = args.formCtrl;
+ }
+
+ // Set the form state to pristine
+ currentForm.$setPristine();
+ currentForm.$setUntouched();
- args.scope.$broadcast("formSubmitted", { scope: args.scope });
+ args.scope.$broadcast(args.hasErrors ? "formSubmittedValidationFailed" : "formSubmitted", { scope: args.scope });
},
showNotifications: function (args) {
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js
index 8248d1186374..115e2dd6a327 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js
@@ -160,7 +160,7 @@ angular.module("umbraco")
}, 2000);
}, function (err) {
-
+ formHelper.resetForm({ scope: $scope, hasErrors: true });
formHelper.handleError(err);
$scope.changePasswordButtonState = "error";
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.createblueprint.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.createblueprint.controller.js
index 9a2c845d49b9..afd844aa0169 100644
--- a/src/Umbraco.Web.UI.Client/src/views/content/content.createblueprint.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/content/content.createblueprint.controller.js
@@ -1,50 +1,50 @@
(function () {
- function CreateBlueprintController(
- $scope,
- contentResource,
- navigationService,
- localizationService,
- formHelper,
- contentEditingHelper) {
-
- $scope.message = {
- name: $scope.currentNode.name
- };
-
- localizationService.localize("blueprints_createBlueprintFrom", ["" + $scope.message.name + ""]).then(function (localizedVal) {
- $scope.title = localizedVal;
- });
-
- $scope.cancel = function () {
- navigationService.hideMenu();
- };
-
- $scope.create = function () {
- if (formHelper.submitForm({
- scope: $scope,
- formCtrl: this.blueprintForm
- })) {
-
- contentResource.createBlueprintFromContent($scope.currentNode.id, $scope.message.name)
- .then(function(data) {
-
- formHelper.resetForm({ scope: $scope });
-
- navigationService.hideMenu();
- },
- function(err) {
-
- contentEditingHelper.handleSaveError({
- err: err
- });
-
+ function CreateBlueprintController(
+ $scope,
+ contentResource,
+ navigationService,
+ localizationService,
+ formHelper,
+ contentEditingHelper) {
+
+ $scope.message = {
+ name: $scope.currentNode.name
+ };
+
+ localizationService.localize("blueprints_createBlueprintFrom", ["" + $scope.message.name + ""]).then(function (localizedVal) {
+ $scope.title = localizedVal;
+ });
+
+ $scope.cancel = function () {
+ navigationService.hideMenu();
+ };
+
+ $scope.create = function () {
+ if (formHelper.submitForm({
+ scope: $scope,
+ formCtrl: this.blueprintForm
+ })) {
+
+ contentResource.createBlueprintFromContent($scope.currentNode.id, $scope.message.name)
+ .then(function (data) {
+
+ formHelper.resetForm({ scope: $scope });
+
+ navigationService.hideMenu();
+ },
+ function (err) {
+ formHelper.resetForm({ scope: $scope, hasErrors: true });
+ contentEditingHelper.handleSaveError({
+ err: err
+ });
+
+ }
+ );
}
- );
- }
- };
- }
+ };
+ }
- angular.module("umbraco").controller("Umbraco.Editors.Content.CreateBlueprintController", CreateBlueprintController);
+ angular.module("umbraco").controller("Umbraco.Editors.Content.CreateBlueprintController", CreateBlueprintController);
}());
diff --git a/src/Umbraco.Web.UI.Client/src/views/datatypes/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/datatypes/create.controller.js
index 15e1a9402eb3..9bc602678edd 100644
--- a/src/Umbraco.Web.UI.Client/src/views/datatypes/create.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/datatypes/create.controller.js
@@ -28,10 +28,11 @@ function DataTypeCreateController($scope, $location, navigationService, dataType
var currPath = node.path ? node.path : "-1";
navigationService.syncTree({ tree: "datatypes", path: currPath + "," + folderId, forceReload: true, activate: true });
- formHelper.resetForm({ scope: $scope });
+ formHelper.resetForm({ scope: $scope, formCtrl: this.createFolderFor });
}, function(err) {
+ formHelper.resetForm({ scope: $scope, formCtrl: this.createFolderFor, hasErrors: true });
// TODO: Handle errors
});
};
diff --git a/src/Umbraco.Web.UI.Client/src/views/datatypes/datatype.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/datatypes/datatype.edit.controller.js
index 66983bbc05a5..a2af8c82392f 100644
--- a/src/Umbraco.Web.UI.Client/src/views/datatypes/datatype.edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/datatypes/datatype.edit.controller.js
@@ -128,6 +128,7 @@ function DataTypeEditController($scope, $routeParams, appState, navigationServic
}, function(err) {
+ formHelper.resetForm({ scope: $scope, hasErrors: true });
//NOTE: in the case of data type values we are setting the orig/new props
// to be the same thing since that only really matters for content/media.
contentEditingHelper.handleSaveError({
diff --git a/src/Umbraco.Web.UI.Client/src/views/dictionary/dictionary.create.controller.js b/src/Umbraco.Web.UI.Client/src/views/dictionary/dictionary.create.controller.js
index 82c4e6e7b5b2..2be4e522c392 100644
--- a/src/Umbraco.Web.UI.Client/src/views/dictionary/dictionary.create.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/dictionary/dictionary.create.controller.js
@@ -28,13 +28,14 @@ function DictionaryCreateController($scope, $location, dictionaryResource, navig
navigationService.syncTree({ tree: "dictionary", path: currPath + "," + data, forceReload: true, activate: true });
// reset form state
- formHelper.resetForm({ scope: $scope });
+ formHelper.resetForm({ scope: $scope, formCtrl: this.createDictionaryForm });
// navigate to edit view
var currentSection = appState.getSectionState("currentSection");
$location.path("/" + currentSection + "/dictionary/edit/" + data);
}, function (err) {
+ formHelper.resetForm({ scope: $scope, formCtrl: this.createDictionaryForm, hasErrors: true });
if (err.data && err.data.message) {
notificationsService.error(err.data.message);
navigationService.hideMenu();
diff --git a/src/Umbraco.Web.UI.Client/src/views/dictionary/dictionary.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/dictionary/dictionary.edit.controller.js
index ea1ca00b21f3..7619c7abfc1c 100644
--- a/src/Umbraco.Web.UI.Client/src/views/dictionary/dictionary.edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/dictionary/dictionary.edit.controller.js
@@ -86,7 +86,7 @@ function DictionaryEditController($scope, $routeParams, $location, dictionaryRes
dictionaryResource.save(vm.content, vm.nameDirty)
.then(function (data) {
- formHelper.resetForm({ scope: $scope, notifications: data.notifications });
+ formHelper.resetForm({ scope: $scope });
bindDictionary(data);
@@ -94,6 +94,8 @@ function DictionaryEditController($scope, $routeParams, $location, dictionaryRes
},
function (err) {
+ formHelper.resetForm({ scope: $scope, hasErrors: true });
+
contentEditingHelper.handleSaveError({
err: err
});
diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.controller.js
index 732aa898a70c..2348b43852d6 100644
--- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.controller.js
@@ -47,12 +47,13 @@ function DocumentTypesCreateController($scope, $location, navigationService, con
activate: true
});
- formHelper.resetForm({ scope: $scope });
+ formHelper.resetForm({ scope: $scope, formCtrl: this.createFolderForm });
var section = appState.getSectionState("currentSection");
}, function (err) {
+ formHelper.resetForm({ scope: $scope, formCtrl: this.createFolderForm, hasErrors: true });
$scope.error = err;
});
@@ -83,9 +84,7 @@ function DocumentTypesCreateController($scope, $location, navigationService, con
$location.search('create', null);
$location.search('notemplate', null);
- formHelper.resetForm({
- scope: $scope
- });
+ formHelper.resetForm({ scope: $scope, formCtrl: this.createDoctypeCollectionForm });
var section = appState.getSectionState("currentSection");
@@ -94,6 +93,7 @@ function DocumentTypesCreateController($scope, $location, navigationService, con
}, function (err) {
+ formHelper.resetForm({ scope: $scope, formCtrl: this.createDoctypeCollectionForm, hasErrors: true });
$scope.error = err;
//show any notifications
diff --git a/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js
index 96441e610103..a030e0d77fdf 100644
--- a/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js
@@ -161,7 +161,7 @@
}, function (err) {
vm.page.saveButtonState = "error";
-
+ formHelper.resetForm({ scope: $scope, hasErrors: true });
formHelper.handleError(err);
});
diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/macros.create.controller.js b/src/Umbraco.Web.UI.Client/src/views/macros/macros.create.controller.js
index e2559741a2ea..e8c5c550d054 100644
--- a/src/Umbraco.Web.UI.Client/src/views/macros/macros.create.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/macros/macros.create.controller.js
@@ -25,7 +25,7 @@ function MacrosCreateController($scope, $location, macroResource, navigationServ
navigationService.syncTree({ tree: "macros", path: currPath + "," + data, forceReload: true, activate: true });
// reset form state
- formHelper.resetForm({ scope: $scope });
+ formHelper.resetForm({ scope: $scope, formCtrl: this.createMacroForm });
// navigate to edit view
var currentSection = appState.getSectionState("currentSection");
@@ -33,6 +33,7 @@ function MacrosCreateController($scope, $location, macroResource, navigationServ
}, function (err) {
+ formHelper.resetForm({ scope: $scope, formCtrl: this.createMacroForm, hasErrors: true });
if (err.data && err.data.message) {
notificationsService.error(err.data.message);
navigationService.hideMenu();
diff --git a/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js
index 3261739d362f..127f5669950b 100644
--- a/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/macros/macros.edit.controller.js
@@ -33,10 +33,11 @@ function MacrosEditController($scope, $q, $routeParams, macroResource, editorSta
vm.page.saveButtonState = "busy";
macroResource.saveMacro(vm.macro).then(function (data) {
- formHelper.resetForm({ scope: $scope, notifications: data.notifications });
+ formHelper.resetForm({ scope: $scope });
bindMacro(data);
vm.page.saveButtonState = "success";
}, function (error) {
+ formHelper.resetForm({ scope: $scope, hasErrors: true });
contentEditingHelper.handleSaveError({
err: error
});
diff --git a/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js
index a7ce67fc0b07..c5d35ad241c5 100644
--- a/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js
@@ -206,6 +206,7 @@ function mediaEditController($scope, $routeParams, $q, appState, mediaResource,
}, function(err) {
+ formHelper.resetForm({ scope: $scope, hasErrors: true });
contentEditingHelper.handleSaveError({
err: err,
rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, err.data)
diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/mediatypes/create.controller.js
index 8ff9106def7f..3b7e16384027 100644
--- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/create.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/create.controller.js
@@ -30,11 +30,12 @@ function MediaTypesCreateController($scope, $location, navigationService, mediaT
var currPath = node.path ? node.path : "-1";
navigationService.syncTree({ tree: "mediatypes", path: currPath + "," + folderId, forceReload: true, activate: true });
- formHelper.resetForm({ scope: $scope });
+ formHelper.resetForm({ scope: $scope, formCtrl: this.createFolderForm });
var section = appState.getSectionState("currentSection");
- }, function(err) {
+ }, function (err) {
+ formHelper.resetForm({ scope: $scope, formCtrl: this.createFolderForm, hasErrors: true });
$scope.error = err;
});
};
diff --git a/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js
index 3ec76deb8e84..2cee0420cd4a 100644
--- a/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js
@@ -208,7 +208,7 @@ function MemberEditController($scope, $routeParams, $location, appState, memberR
navigationService.syncTree({ tree: "member", path: path.split(","), forceReload: true });
}, function (err) {
-
+ formHelper.resetForm({ scope: $scope, hasErrors: true });
contentEditingHelper.handleSaveError({
err: err,
rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, err.data)
diff --git a/src/Umbraco.Web.UI.Client/src/views/membergroups/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/membergroups/edit.controller.js
index 00c6dfbba82b..4602a5aa25f8 100644
--- a/src/Umbraco.Web.UI.Client/src/views/membergroups/edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/membergroups/edit.controller.js
@@ -88,6 +88,7 @@ function MemberGroupsEditController($scope, $routeParams, appState, navigationSe
}, function (err) {
+ formHelper.resetForm({ scope: $scope, hasErrors: true });
contentEditingHelper.handleSaveError({
err: err
});
diff --git a/src/Umbraco.Web.UI.Client/src/views/membertypes/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/membertypes/create.controller.js
index adf6cbc8a60e..d87544282733 100644
--- a/src/Umbraco.Web.UI.Client/src/views/membertypes/create.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/membertypes/create.controller.js
@@ -31,10 +31,10 @@ function MemberTypesCreateController($scope, $location, navigationService, membe
var currPath = node.path ? node.path : "-1";
navigationService.syncTree({ tree: "membertypes", path: currPath + "," + folderId, forceReload: true, activate: true });
- formHelper.resetForm({ scope: $scope });
+ formHelper.resetForm({ scope: $scope, formCtrl: this.createFolderForm });
}, function(err) {
-
+ formHelper.resetForm({ scope: $scope, formCtrl: this.createFolderForm, hasErrors: true });
// TODO: Handle errors
});
};
diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js
index 63750ff0f218..de8ad6d1c497 100644
--- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.controller.js
@@ -194,7 +194,7 @@
vm.package = updatedPackage;
vm.buttonState = "success";
- formHelper.resetForm({ scope: $scope });
+ formHelper.resetForm({ scope: $scope, formCtrl: editPackageForm });
if (create) {
//if we are creating, then redirect to the correct url and reload
@@ -204,6 +204,7 @@
}
}, function (err) {
+ formHelper.resetForm({ scope: $scope, formCtrl: editPackageForm, hasErrors: true });
formHelper.handleError(err);
vm.buttonState = "error";
});
diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/create.controller.js
index 52b58d094db5..a843f420c88e 100644
--- a/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/create.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/create.controller.js
@@ -46,12 +46,13 @@
activate: true
});
- formHelper.resetForm({ scope: $scope });
+ formHelper.resetForm({ scope: $scope, formCtrl: form });
var section = appState.getSectionState("currentSection");
}, function (err) {
+ formHelper.resetForm({ scope: $scope, formCtrl: form, hasErrors: true });
vm.createFolderError = err;
});
diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviews/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/partialviews/create.controller.js
index fbde1d5a075c..97aa059806e1 100644
--- a/src/Umbraco.Web.UI.Client/src/views/partialviews/create.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/partialviews/create.controller.js
@@ -56,12 +56,13 @@
activate: true
});
- formHelper.resetForm({ scope: $scope });
+ formHelper.resetForm({ scope: $scope, formCtrl: form });
var section = appState.getSectionState("currentSection");
}, function(err) {
+ formHelper.resetForm({ scope: $scope, formCtrl: form, hasErrors: true });
vm.createFolderError = err;
});
}
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js
index 928e627fa34a..89f7c5d4d011 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js
@@ -202,23 +202,36 @@
return "views/propertyeditors/blocklist/blocklistentryeditors/labelblock/labelblock.editor.html";
}
+ /**
+ * Ensure that the containing content variant languag and current property culture is transfered along
+ * to the scaffolded content object representing this block.
+ * This is required for validation along with ensuring that the umb-property inheritance is constently maintained.
+ * @param {any} content
+ */
+ function ensureCultureData(content) {
+
+ if (!content) return;
+
+ if (vm.umbVariantContent.editor.content.language) {
+ // set the scaffolded content's language to the language of the current editor
+ content.language = vm.umbVariantContent.editor.content.language;
+ }
+ // currently we only ever deal with invariant content for blocks so there's only one
+ content.variants[0].tabs.forEach(tab => {
+ tab.properties.forEach(prop => {
+ // set the scaffolded property to the culture of the containing property
+ prop.culture = vm.umbProperty.property.culture;
+ });
+ });
+ }
+
function getBlockObject(entry) {
var block = modelObject.getBlockObject(entry);
if (block === null) return null;
- // ensure that the containing content variant language/culture is transfered along
- // to the scaffolded content object representing this block. This is required for validation
- // along with ensuring that the umb-property inheritance is constently maintained.
- if (vm.umbVariantContent.editor.content.language) {
- block.content.language = vm.umbVariantContent.editor.content.language;
- // currently we only ever deal with invariant content for blocks so there's only one
- block.content.variants[0].tabs.forEach(tab => {
- tab.properties.forEach(prop => {
- prop.culture = vm.umbVariantContent.editor.content.language.culture;
- });
- });
- }
+ ensureCultureData(block.content);
+ ensureCultureData(block.settings);
// TODO: Why is there a '/' prefixed? that means this will never work with virtual directories
block.view = (block.config.view ? "/" + block.config.view : getDefaultViewForBlock(block));
@@ -272,8 +285,12 @@
var removed = vm.layout.splice(layoutIndex, 1);
removed.forEach(x => {
// remove any server validation errors associated
- var guid = udiService.getKey(x.contentUdi);
- serverValidationManager.removePropertyError(guid, vm.umbProperty.property.culture, vm.umbProperty.property.segment, "", { matchType: "contains" });
+ var guids = [udiService.getKey(x.contentUdi), (x.settingsUdi ? udiService.getKey(x.settingsUdi) : null)];
+ guids.forEach(guid => {
+ if (guid) {
+ serverValidationManager.removePropertyError(guid, vm.umbProperty.property.culture, vm.umbProperty.property.segment, "", { matchType: "contains" });
+ }
+ })
});
modelObject.removeDataAndDestroyModel(block);
diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js
index 71f59a9a1f51..b2fbee4b3613 100644
--- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/create.controller.js
@@ -36,11 +36,12 @@ function RelationTypeCreateController($scope, $location, relationTypeResource, n
var currentPath = node.path ? node.path : "-1";
navigationService.syncTree({ tree: "relationTypes", path: currentPath + "," + data, forceReload: true, activate: true });
- formHelper.resetForm({ scope: $scope });
+ formHelper.resetForm({ scope: $scope, formCtrl: this.createRelationTypeForm });
var currentSection = appState.getSectionState("currentSection");
$location.path("/" + currentSection + "/relationTypes/edit/" + data);
}, function (err) {
+ formHelper.resetForm({ scope: $scope, formCtrl: this.createRelationTypeForm, hasErrors: true });
if (err.data && err.data.message) {
notificationsService.error(err.data.message);
navigationService.hideMenu();
diff --git a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js
index 74b3e31b8746..a39b48c27836 100644
--- a/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/relationtypes/edit.controller.js
@@ -116,12 +116,13 @@ function RelationTypeEditController($scope, $routeParams, relationTypeResource,
vm.page.saveButtonState = "busy";
relationTypeResource.save(vm.relationType).then(function (data) {
- formHelper.resetForm({ scope: $scope, notifications: data.notifications });
+ formHelper.resetForm({ scope: $scope });
bindRelationType(data);
vm.page.saveButtonState = "success";
}, function (error) {
+ formHelper.resetForm({ scope: $scope, hasErrors: true });
contentEditingHelper.handleSaveError({
err: error
});
diff --git a/src/Umbraco.Web.UI.Client/src/views/scripts/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/scripts/create.controller.js
index 096ae72e6131..14d7e54a66ec 100644
--- a/src/Umbraco.Web.UI.Client/src/views/scripts/create.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/scripts/create.controller.js
@@ -27,7 +27,7 @@
function createFolder(form) {
- if (formHelper.submitForm({scope: $scope, formCtrl: form })) {
+ if (formHelper.submitForm({ scope: $scope, formCtrl: form })) {
codefileResource.createContainer("scripts", node.id, vm.folderName).then(function (saved) {
@@ -40,14 +40,15 @@
activate: true
});
- formHelper.resetForm({ scope: $scope });
+ formHelper.resetForm({ scope: $scope, formCtrl: form });
var section = appState.getSectionState("currentSection");
- }, function(err) {
+ }, function (err) {
+
+ formHelper.resetForm({ scope: $scope, formCtrl: form, hasErrors: true });
+ vm.createFolderError = err;
- vm.createFolderError = err;
-
});
}
diff --git a/src/Umbraco.Web.UI.Client/src/views/stylesheets/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/stylesheets/create.controller.js
index 6033a6bdc7ad..af80878c35d4 100644
--- a/src/Umbraco.Web.UI.Client/src/views/stylesheets/create.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/stylesheets/create.controller.js
@@ -22,14 +22,14 @@
$location.path("/settings/stylesheets/edit/" + node.id).search("create", "true").search("rtestyle", "true");
navigationService.hideMenu();
}
-
+
function showCreateFolder() {
vm.creatingFolder = true;
}
function createFolder(form) {
- if (formHelper.submitForm({scope: $scope, formCtrl: form })) {
+ if (formHelper.submitForm({ scope: $scope, formCtrl: form })) {
codefileResource.createContainer("stylesheets", node.id, vm.folderName).then(function (saved) {
@@ -42,12 +42,13 @@
activate: true
});
- formHelper.resetForm({ scope: $scope });
+ formHelper.resetForm({ scope: $scope, formCtrl: form });
+
+ }, function (err) {
- }, function(err) {
+ formHelper.resetForm({ scope: $scope, formCtrl: form, hasErrors: true });
+ vm.createFolderError = err;
- vm.createFolderError = err;
-
});
}
@@ -57,7 +58,7 @@
const showMenu = true;
navigationService.hideDialog(showMenu);
}
-
+
}
angular.module("umbraco").controller("Umbraco.Editors.StyleSheets.CreateController", StyleSheetsCreateController);
diff --git a/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js
index 19218d3d08c2..ac99e3d35d42 100644
--- a/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js
@@ -168,7 +168,9 @@
extendedSave(saved).then(function (result) {
//if all is good, then reset the form
formHelper.resetForm({ scope: $scope });
- }, Utilities.noop);
+ }, function () {
+ formHelper.resetForm({ scope: $scope, hasErrors: true });
+ });
vm.user = _.omit(saved, "navigation");
//restore
@@ -179,7 +181,7 @@
vm.page.saveButtonState = "success";
}, function (err) {
-
+ formHelper.resetForm({ scope: $scope, hasErrors: true });
contentEditingHelper.handleSaveError({
err: err,
showNotifications: true
From 79478cd5e2d0aeb091379ae662c49c05613b1405 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Fri, 7 Aug 2020 16:11:13 +0200
Subject: [PATCH 42/89] highlight validation issues for content part of blocks,
first take.
---
.../inlineblock/inlineblock.editor.html | 2 +-
.../inlineblock/inlineblock.editor.less | 53 +++++++++++++++++--
.../labelblock/labelblock.editor.less | 40 +++++++++++++-
3 files changed, 89 insertions(+), 6 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.html
index 360eeed8c066..e5a46cbdeb47 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.html
@@ -6,7 +6,7 @@
ng-focus="block.focus">
- {{block.label}}
+ {{block.label}}
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.less
index 2be20946b8b6..08306deeba85 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.less
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/inlineblock/inlineblock.editor.less
@@ -22,6 +22,7 @@
background-color: white;
.caret {
+ vertical-align: middle;
transform: rotate(-90deg);
transition: transform 80ms ease-out;
}
@@ -32,7 +33,8 @@
vertical-align: middle;
}
- span {
+ span.name {
+ position: relative;
display: inline-block;
vertical-align: middle;
}
@@ -54,10 +56,55 @@
}
}
- &.--error {
- border-color: @formErrorBorder !important;
+
+ ng-form.ng-invalid-val-server-match-content > .umb-block-list__block > .umb-block-list__block--content > div > & {
+ > button {
+ color: @formErrorText;
+ span.caret {
+ border-top-color: @formErrorText;
+ }
+ }
+ }
+ ng-form.ng-invalid-val-server-match-content > .umb-block-list__block:not(.--active) > .umb-block-list__block--content > div > & {
+ > button {
+ span.name {
+ &::after {
+ content: "!";
+ text-align: center;
+ position: absolute;
+ top: -6px;
+ right: -15px;
+ min-width: 10px;
+ color: @white;
+ background-color: @ui-active-type;
+ border: 2px solid @white;
+ border-radius: 50%;
+ font-size: 10px;
+ font-weight: bold;
+ padding: 2px;
+ line-height: 10px;
+ background-color: @formErrorText;
+ font-weight: 900;
+
+ animation-duration: 1.4s;
+ animation-iteration-count: infinite;
+ animation-name: blockelement-inlineblock-editor--badge-bounce;
+ animation-timing-function: ease;
+ @keyframes blockelement-inlineblock-editor--badge-bounce {
+ 0% { transform: translateY(0); }
+ 20% { transform: translateY(-4px); }
+ 40% { transform: translateY(0); }
+ 55% { transform: translateY(-2px); }
+ 70% { transform: translateY(0); }
+ 100% { transform: translateY(0); }
+ }
+ }
+ }
+ }
}
}
+
+
.blockelement-inlineblock-editor__inner {
border-top: 1px solid @gray-8;
background-color: @gray-12;
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/labelblock/labelblock.editor.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/labelblock/labelblock.editor.less
index 51fb7242ef1a..f589249f97fa 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/labelblock/labelblock.editor.less
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklistentryeditors/labelblock/labelblock.editor.less
@@ -24,6 +24,7 @@
}
span {
+ position: relative;
display: inline-block;
vertical-align: middle;
}
@@ -39,7 +40,42 @@
background-color: @ui-active;
}
- &.--error {
- border-color: @formErrorBorder !important;
+ ng-form.ng-invalid-val-server-match-content > .umb-block-list__block > .umb-block-list__block--content > div > & {
+ color: @formErrorText;
+ }
+ ng-form.ng-invalid-val-server-match-content > .umb-block-list__block:not(.--active) > .umb-block-list__block--content > div > & {
+ span {
+ &::after {
+ content: "!";
+ text-align: center;
+ position: absolute;
+ top: -6px;
+ right: -15px;
+ min-width: 10px;
+ color: @white;
+ background-color: @ui-active-type;
+ border: 2px solid @white;
+ border-radius: 50%;
+ font-size: 10px;
+ font-weight: bold;
+ padding: 2px;
+ line-height: 10px;
+ background-color: @formErrorText;
+ font-weight: 900;
+
+ animation-duration: 1.4s;
+ animation-iteration-count: infinite;
+ animation-name: blockelement-inlineblock-editor--badge-bounce;
+ animation-timing-function: ease;
+ @keyframes blockelement-inlineblock-editor--badge-bounce {
+ 0% { transform: translateY(0); }
+ 20% { transform: translateY(-4px); }
+ 40% { transform: translateY(0); }
+ 55% { transform: translateY(-2px); }
+ 70% { transform: translateY(0); }
+ 100% { transform: translateY(0); }
+ }
+ }
+ }
}
}
From 5d73949b7a75ad1ee923ce75d6be84c3dbe9a515 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Mon, 10 Aug 2020 11:37:39 +0200
Subject: [PATCH 43/89] validation highlight for custom view
---
.../umb-block-list-property-editor.less | 53 +++++++++++++++++--
.../blocklist/umb-block-list-row.html | 2 +-
.../umbBlockListPropertyEditor.component.js | 1 +
3 files changed, 50 insertions(+), 6 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.less
index 0c92aef44bb8..0c7d58d245fc 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.less
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.less
@@ -99,11 +99,54 @@ ng-form.ng-invalid-val-server-match-settings > .umb-block-list__block > .umb-blo
}
.umb-block-list__block--content {
- position: relative;
- width: 100%;
- min-height: @umb-block-list__item_minimum_height;
- background-color: @white;
- border-radius: @baseBorderRadius;
+
+ > div {
+ position: relative;
+ width: 100%;
+ min-height: @umb-block-list__item_minimum_height;
+ background-color: @white;
+ border-radius: @baseBorderRadius;
+ box-sizing: border-box;
+ }
+
+ &.--show-validation {
+ ng-form.ng-invalid-val-server-match-content > .umb-block-list__block > & > div {
+ border: 2px solid @formErrorText;
+ border-radius: @baseBorderRadius;
+ &::after {
+ content: "!";
+ position: absolute;
+ top: -12px;
+ right: -12px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 18px;
+ height: 18px;
+ border-radius: 50%;
+ font-size: 13px;
+ text-align: center;
+ font-weight: bold;
+ background-color: @errorBackground;
+ color: @errorText;
+ border: 2px solid @white;
+ font-weight: 900;
+
+ animation-duration: 1.4s;
+ animation-iteration-count: infinite;
+ animation-name: umb-block-list__block--content--badge-bounce;
+ animation-timing-function: ease;
+ @keyframes umb-block-list__block--content--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); }
+ }
+ }
+ }
+ }
}
.blockelement__draggable-element {
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-row.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-row.html
index b76a5d583d8d..c2657985cf48 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-row.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-row.html
@@ -3,7 +3,7 @@
Date: Mon, 3 Aug 2020 12:39:07 +0200
Subject: [PATCH 44/89] Fix issue with tour's next button not clickable when
infinite editing bar is open
---
src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml b/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml
index bd8d23a851ea..68670b16d2c3 100644
--- a/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml
+++ b/src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml
@@ -72,16 +72,16 @@
-
-
-
-
+
-
+
+
+
+
From a2dd9ad0c471c86f13e18205bd6eb827d02d9b68 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Wed, 12 Aug 2020 10:34:15 +0200
Subject: [PATCH 45/89] dont render input if not shown.
---
.../src/views/components/editor/umb-editor-header.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html
index 7929f92371ca..26f03c97ca55 100644
--- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html
+++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html
@@ -42,7 +42,7 @@
localize="placeholder"
placeholder="@placeholders_entername"
name="headerName"
- ng-show="!nameLocked"
+ ng-if="!nameLocked"
ng-model="name"
ng-class="{'name-is-empty': $parent.name===null || $parent.name===''}"
umb-auto-focus
From 244d441dd45fc03ba5001e71dce0fb1904854da5 Mon Sep 17 00:00:00 2001
From: Warren Buckley
Date: Wed, 12 Aug 2020 12:04:19 +0100
Subject: [PATCH 46/89] Remove the if security check if access to settings
section - seems we do not need to do this
We check on the content node itself in the info tab for access to the doctype & template based on the section rather than the null presence of this property
---
src/Umbraco.Web/Models/Mapping/CommonMapper.cs | 15 +++------------
1 file changed, 3 insertions(+), 12 deletions(-)
diff --git a/src/Umbraco.Web/Models/Mapping/CommonMapper.cs b/src/Umbraco.Web/Models/Mapping/CommonMapper.cs
index 1276a2a405cf..f7db17ff7498 100644
--- a/src/Umbraco.Web/Models/Mapping/CommonMapper.cs
+++ b/src/Umbraco.Web/Models/Mapping/CommonMapper.cs
@@ -49,18 +49,9 @@ public UserProfile GetCreator(IContent source, MapperContext context)
public ContentTypeBasic GetContentType(IContentBase source, MapperContext context)
{
- // TODO: We can resolve the UmbracoContext from the IValueResolver options!
- // OMG
- if (HttpContext.Current != null && Composing.Current.UmbracoContext != null && Composing.Current.UmbracoContext.Security.CurrentUser != null
- && Composing.Current.UmbracoContext.Security.CurrentUser.AllowedSections.Any(x => x.Equals(Constants.Applications.Settings)))
- {
- var contentType = _contentTypeBaseServiceProvider.GetContentTypeOf(source);
- var contentTypeBasic = context.Map(contentType);
-
- return contentTypeBasic;
- }
- //no access
- return null;
+ var contentType = _contentTypeBaseServiceProvider.GetContentTypeOf(source);
+ var contentTypeBasic = context.Map(contentType);
+ return contentTypeBasic;
}
public string GetTreeNodeUrl(IContentBase source)
From 2896e260af489bcc230a1942cfd1acd0ef381994 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Thu, 13 Aug 2020 07:37:53 +0200
Subject: [PATCH 47/89] Revert "dont render input if not shown."
This reverts commit a2dd9ad0c471c86f13e18205bd6eb827d02d9b68.
---
.../src/views/components/editor/umb-editor-header.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html
index 26f03c97ca55..7929f92371ca 100644
--- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html
+++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html
@@ -42,7 +42,7 @@
localize="placeholder"
placeholder="@placeholders_entername"
name="headerName"
- ng-if="!nameLocked"
+ ng-show="!nameLocked"
ng-model="name"
ng-class="{'name-is-empty': $parent.name===null || $parent.name===''}"
umb-auto-focus
From 00edd197f82e5a768772fb8d6e567183466abaaf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Thu, 13 Aug 2020 08:13:32 +0200
Subject: [PATCH 48/89] added attribute name-required, which can be used to
make name not required. Since the value defaults to true.
---
.../components/editor/umbeditorheader.directive.js | 12 +++++++-----
.../infiniteeditors/blockeditor/blockeditor.html | 1 +
.../views/components/editor/umb-editor-header.html | 4 ++--
3 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js
index 58f799e5af71..76687dc0d650 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js
@@ -188,6 +188,7 @@ Use this directive to construct a header inside the main editor window.
@param {string} name The content name.
+@param {boolean=} nameRequired Require name to be defined. (True by default)
@param {array=} tabs Array of tabs. See example above.
@param {array=} navigation Array of sub views. See example above.
@param {boolean=} nameLocked Set to true
to lock the name.
@@ -199,7 +200,7 @@ Use this directive to construct a header inside the main editor window.
@param {boolean=} hideAlias Set to true
to hide alias.
@param {string=} description Add a description to the content.
@param {boolean=} hideDescription Set to true
to hide description.
-@param {boolean=} setpagetitle If true the page title will be set to reflect the type of data the header is working with
+@param {boolean=} setpagetitle If true the page title will be set to reflect the type of data the header is working with
@param {string=} editorfor The localization to use to aid accessibility on the edit and create screen
**/
@@ -207,7 +208,7 @@ Use this directive to construct a header inside the main editor window.
'use strict';
function EditorHeaderDirective(editorService, localizationService, editorState, $rootScope) {
-
+
function link(scope, $injector) {
scope.vm = {};
@@ -329,11 +330,11 @@ Use this directive to construct a header inside the main editor window.
}
scope.accessibility.a11yMessageVisible = !isEmptyOrSpaces(scope.accessibility.a11yMessage);
scope.accessibility.a11yNameVisible = !isEmptyOrSpaces(scope.accessibility.a11yName);
-
+
});
}
-
+
function isEmptyOrSpaces(str) {
return str === null || str===undefined || str.trim ==='';
@@ -348,7 +349,7 @@ Use this directive to construct a header inside the main editor window.
});
}
-
+
var directive = {
transclude: true,
@@ -358,6 +359,7 @@ Use this directive to construct a header inside the main editor window.
scope: {
name: "=",
nameLocked: "=",
+ nameRequired: "=?",
menu: "=",
hideActionsMenu: "",
icon: "=",
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 dfcfd48887de..285e554c6862 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
@@ -6,6 +6,7 @@
From b42bd51392acf2b0f767d5aac878dc25fe382adc Mon Sep 17 00:00:00 2001
From: Nikolaj
Date: Thu, 13 Aug 2020 09:02:18 +0200
Subject: [PATCH 49/89] Add partial views tests
---
.../integration/Settings/partialsViews.ts | 152 +++++++++++++++---
1 file changed, 131 insertions(+), 21 deletions(-)
diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViews.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViews.ts
index b644c6642b51..5fa4e151089d 100644
--- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViews.ts
+++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViews.ts
@@ -1,35 +1,145 @@
///
+import { PartialViewBuilder } from "umbraco-cypress-testhelpers";
+
context('Partial Views', () => {
- beforeEach(() => {
- cy.umbracoLogin(Cypress.env('username'), Cypress.env('password'));
- });
+ beforeEach(() => {
+ cy.umbracoLogin(Cypress.env('username'), Cypress.env('password'));
+ });
+
+ function navigateToSettings() {
+ cy.umbracoSection('settings');
+ cy.get('li .umb-tree-root:contains("Settings")').should("be.visible");
+ }
+
+ function openPartialViewsCreatePanel() {
+ navigateToSettings();
+ cy.umbracoTreeItem("settings", ["Partial Views"]).rightclick();
+ }
+
+ it('Create new empty partial view', () => {
+ const name = "TestPartialView";
+ const fileName = name + ".cshtml";
+
+ cy.umbracoEnsurePartialViewNameNotExists(fileName);
+
+ openPartialViewsCreatePanel();
+
+ cy.umbracoContextMenuAction("action-create").click();
+ cy.get('.menu-label').first().click(); // TODO: Fucked we cant use something like cy.umbracoContextMenuAction("action-mediaType").click();
+
+ //Type name
+ cy.umbracoEditorHeaderName(name);
+
+ //Save
+ cy.get('.btn-success').click();
+
+ //Assert
+ cy.umbracoSuccessNotification().should('be.visible');
+ cy.umbracoPartialViewExists(fileName).then(exists => { expect(exists).to.be.true; });
+
+ //Clean up
+ cy.umbracoEnsurePartialViewNameNotExists(fileName);
+ });
+
+ it('Create partial view from snippet', () => {
+ const name = "TestPartialViewFromSnippet";
+ const fileName = name + ".cshtml";
+
+ cy.umbracoEnsurePartialViewNameNotExists(fileName);
+
+ openPartialViewsCreatePanel();
+
+ cy.umbracoContextMenuAction("action-create").click();
+ cy.get('.menu-label').eq(1).click();
+ // Select snippet
+ cy.get('.menu-label').eq(2).click();
+
+ // Type name
+ cy.umbracoEditorHeaderName(name);
+
+ // Save
+ cy.get('.btn-success').click();
+
+ // Assert
+ cy.umbracoSuccessNotification().should('be.visible');
+ cy.umbracoPartialViewExists(fileName).then(exists => { expect(exists).to.be.true; });
+
+ // Clean up
+ cy.umbracoEnsurePartialViewNameNotExists(fileName);
+ });
+
+ it('Partial view with no name', () => {
+ openPartialViewsCreatePanel();
+
+ cy.umbracoContextMenuAction("action-create").click();
+ cy.get('.menu-label').first().click();
+
+ // The test would fail intermittently, most likely because the editor didn't have time to load
+ // This should ensure that the editor is loaded and the test should no longer fail unexpectedly.
+ cy.get('.ace_content', {timeout: 5000}).should('exist');
+
+ // Click save
+ cy.get('.btn-success').click();
+
+ // Asserts
+ cy.umbracoErrorNotification().should('be.visible');
+ });
+
+ it('Delete partial view', () => {
+ const name = "TestDeletePartialView";
+ const fileName = name + ".cshtml";
+
+ cy.umbracoEnsurePartialViewNameNotExists(fileName);
+
+ // Build and save partial view
+ const partialView = new PartialViewBuilder()
+ .withName(name)
+ .withContent("@inherits Umbraco.Web.Mvc.UmbracoViewPage")
+ .build();
+
+ cy.savePartialView(partialView);
+
+ navigateToSettings();
+
+ // Delete partial view
+ cy.umbracoTreeItem("settings", ["Partial Views", fileName]).rightclick();
+ cy.umbracoContextMenuAction("action-delete").click();
+ cy.umbracoButtonByLabelKey("general_ok").click();
- it('Create new empty partial view', () => {
- const name = "TestPartialView";
- const fileName = name + ".cshtml";
+ // Assert
+ cy.contains(fileName).should('not.exist');
+ cy.umbracoPartialViewExists(fileName).then(exists => { expect(exists).to.be.false; });
- cy.umbracoEnsurePartialViewNameNotExists(fileName);
+ // Clean
+ cy.umbracoEnsurePartialViewNameNotExists(fileName);
+ });
- cy.umbracoSection('settings');
- cy.get('li .umb-tree-root:contains("Settings")').should("be.visible");
+ it('Edit partial view', () => {
+ const name = 'EditPartialView';
+ const fileName = name + ".cshtml";
- cy.umbracoTreeItem("settings", ["Partial Views"]).rightclick();
+ cy.umbracoEnsurePartialViewNameNotExists(fileName);
- cy.umbracoContextMenuAction("action-create").click();
- cy.get('.menu-label').first().click(); // TODO: Fucked we cant use something like cy.umbracoContextMenuAction("action-mediaType").click();
+ const partialView = new PartialViewBuilder()
+ .withName(name)
+ .withContent("@inherits Umbraco.Web.Mvc.UmbracoViewPage\n")
+ .build();
- //Type name
- cy.umbracoEditorHeaderName(name);
+ cy.savePartialView(partialView);
- //Save
- cy.get('.btn-success').click();
+ navigateToSettings();
+ // Open partial view
+ cy.umbracoTreeItem("settings", ["Partial Views", fileName]).click();
+ // Edit
+ cy.get('.ace_content').type("var num = 5;");
+ cy.get('.btn-success').click();
- //Assert
- cy.umbracoSuccessNotification().should('be.visible');
+ // Assert
+ cy.umbracoSuccessNotification().should('be.visible');
+ // Clean
+ cy.umbracoEnsurePartialViewNameNotExists(fileName);
+ });
- //Clean up
- cy.umbracoEnsurePartialViewNameNotExists(fileName);
- });
});
From cc696ade1c95ca76a5058781e3109eb58f40c9e5 Mon Sep 17 00:00:00 2001
From: Nikolaj
Date: Thu, 13 Aug 2020 09:02:54 +0200
Subject: [PATCH 50/89] Update npm packages
---
src/Umbraco.Tests.AcceptanceTest/package.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Umbraco.Tests.AcceptanceTest/package.json b/src/Umbraco.Tests.AcceptanceTest/package.json
index 5840518184b8..867b7f5cf389 100644
--- a/src/Umbraco.Tests.AcceptanceTest/package.json
+++ b/src/Umbraco.Tests.AcceptanceTest/package.json
@@ -5,9 +5,9 @@
},
"devDependencies": {
"cross-env": "^7.0.2",
- "cypress": "^4.12.0",
+ "cypress": "^4.12.1",
"ncp": "^2.0.0",
- "umbraco-cypress-testhelpers": "^1.0.0-beta-46"
+ "umbraco-cypress-testhelpers": "^1.0.0-beta-48"
},
"dependencies": {
"typescript": "^3.9.2"
From e76ffc865ca0624bbfca994d7fc4cbec8c8be7c7 Mon Sep 17 00:00:00 2001
From: Nikolaj
Date: Thu, 13 Aug 2020 09:09:15 +0200
Subject: [PATCH 51/89] Ensure that the template is deleted when creating a new
documentType
---
.../cypress/integration/Settings/documentTypes.ts | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/documentTypes.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/documentTypes.ts
index e0a651731ac8..c40d65d54120 100644
--- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/documentTypes.ts
+++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/documentTypes.ts
@@ -10,6 +10,7 @@ context('Document Types', () => {
const name = "Test document type";
cy.umbracoEnsureDocumentTypeNameNotExists(name);
+ cy.umbracoEnsureTemplateNameNotExists(name);
cy.umbracoSection('settings');
cy.get('li .umb-tree-root:contains("Settings")').should("be.visible");
@@ -44,6 +45,7 @@ context('Document Types', () => {
//Assert
cy.umbracoSuccessNotification().should('be.visible');
+ cy.umbracoEnsureTemplateNameNotExists(name);
//Clean up
cy.umbracoEnsureDocumentTypeNameNotExists(name);
From 9a2fb1e0d8b573885fc6789bfeb4f420a50df4bc Mon Sep 17 00:00:00 2001
From: Nikolaj
Date: Thu, 13 Aug 2020 09:11:58 +0200
Subject: [PATCH 52/89] Fix javascript test
---
.../cypress/integration/Settings/partialsViewMacroFiles.ts | 2 +-
.../cypress/integration/Settings/scripts.ts | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViewMacroFiles.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViewMacroFiles.ts
index 0a1fec7bc8b8..bf1c25c16dd9 100644
--- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViewMacroFiles.ts
+++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViewMacroFiles.ts
@@ -119,7 +119,7 @@ context('Partial View Macro Files', () => {
// Assert
cy.contains(fullName).should('not.exist');
- // Clearn
+ // Clean
cleanup(name);
});
diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/scripts.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/scripts.ts
index 8cffd3e59bea..cce8a45da6af 100644
--- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/scripts.ts
+++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/scripts.ts
@@ -14,7 +14,7 @@ context('Scripts', () => {
cy.umbracoSection('settings');
cy.get('li .umb-tree-root:contains("Settings")').should("be.visible");
- cy.umbracoTreeItem("settings", ["Stylesheets"]).rightclick();
+ cy.umbracoTreeItem("settings", ["Scripts"]).rightclick();
cy.umbracoContextMenuAction("action-create").click();
cy.get('.menu-label').first().click(); // TODO: Fucked we cant use something like cy.umbracoContextMenuAction("action-mediaType").click();
From 1512496f4f6c82ebc67de0ea1ce34af584ba057c Mon Sep 17 00:00:00 2001
From: Nikolaj
Date: Thu, 13 Aug 2020 09:31:28 +0200
Subject: [PATCH 53/89] Add template tests
---
.../cypress/integration/Settings/templates.ts | 147 +++++++++++++++---
1 file changed, 128 insertions(+), 19 deletions(-)
diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts
index 6871db7ffed2..194419ee8889 100644
--- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts
+++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts
@@ -1,57 +1,166 @@
///
-import {DocumentTypeBuilder, TemplateBuilder} from "umbraco-cypress-testhelpers";
+import { TemplateBuilder } from 'umbraco-cypress-testhelpers';
context('Templates', () => {
- beforeEach(() => {
- cy.umbracoLogin(Cypress.env('username'), Cypress.env('password'));
- });
-
- it('Create template', () => {
- const name = "Test template";
-
- cy.umbracoEnsureTemplateNameNotExists(name);
+ beforeEach(() => {
+ cy.umbracoLogin(Cypress.env('username'), Cypress.env('password'));
+ });
+ function navigateToSettings() {
cy.umbracoSection('settings');
cy.get('li .umb-tree-root:contains("Settings")').should("be.visible");
+ }
+ function createTemplate() {
+ navigateToSettings();
cy.umbracoTreeItem("settings", ["Templates"]).rightclick();
-
cy.umbracoContextMenuAction("action-create").click();
+ }
+
+
+ it('Create template', () => {
+ const name = "Test template test";
+ cy.umbracoEnsureTemplateNameNotExists(name);
+
+ createTemplate();
//Type name
cy.umbracoEditorHeaderName(name);
+ /* Make an edit, if you don't the file will be create twice,
+ only happens in testing though, probably because the test is too fast
+ Certifiably mega wonk regardless */
+ cy.get('.ace_content').type("var num = 5;");
//Save
- cy.get("form[name='contentForm']").submit();
+ cy.get('.btn-success').click();
//Assert
cy.umbracoSuccessNotification().should('be.visible');
//Clean up
cy.umbracoEnsureTemplateNameNotExists(name);
- });
+ });
+
+ it('Unsaved changes stay', () => {
+ const name = "Templates Unsaved Changes Stay test";
+ const edit = "var num = 5;";
+ cy.umbracoEnsureTemplateNameNotExists(name);
+
+ const template = new TemplateBuilder()
+ .withName(name)
+ .withContent('@inherits Umbraco.Web.Mvc.UmbracoViewPage\n')
+ .build();
+
+ cy.saveTemplate(template);
+
+ navigateToSettings();
+
+ // Open partial view
+ cy.umbracoTreeItem("settings", ["Templates", name]).click();
+ // Edit
+ cy.get('.ace_content').type(edit);
+ // Navigate away
+ cy.umbracoSection('content');
+ // Click stay button
+ cy.get('umb-button[label="Stay"] button:enabled').click();
+
+ // Assert
+ // That the same document is open
+ cy.get('#headerName').should('have.value', name);
+ cy.get('.ace_content').contains(edit);
+
+ cy.umbracoEnsureTemplateNameNotExists(name);
+ });
+
+ it('Discard unsaved changes', () => {
+ const name = "Discard changes test";
+ const edit = "var num = 5;";
- it('Delete template', () => {
- const name = "Test template";
cy.umbracoEnsureTemplateNameNotExists(name);
const template = new TemplateBuilder()
.withName(name)
+ .withContent('@inherits Umbraco.Web.Mvc.UmbracoViewPage\n')
.build();
cy.saveTemplate(template);
+ navigateToSettings();
+
+ // Open partial view
+ cy.umbracoTreeItem("settings", ["Templates", name]).click();
+ // Edit
+ cy.get('.ace_content').type(edit);
+ // Navigate away
+ cy.umbracoSection('content');
+ // Click discard
+ cy.get('umb-button[label="Discard changes"] button:enabled').click();
+ // Navigate back
cy.umbracoSection('settings');
- cy.get('li .umb-tree-root:contains("Settings")').should("be.visible");
- cy.umbracoTreeItem("settings", ["Templates", name]).rightclick();
- cy.umbracoContextMenuAction("action-delete").click();
+ // Asserts
+ cy.get('.ace_content').should('not.contain', edit);
+ // cy.umbracoPartialViewExists(fileName).then(exists => { expect(exists).to.be.false; }); TODO: Switch to template
+ cy.umbracoEnsureTemplateNameNotExists(name);
+ });
+
+ it('Insert macro', () => {
+ const name = 'InsertMacroTest';
+
+ cy.umbracoEnsureTemplateNameNotExists(name);
+ cy.umbracoEnsureMacroNameNotExists(name);
+
+ const template = new TemplateBuilder()
+ .withName(name)
+ .withContent('')
+ .build();
+
+ cy.saveTemplate(template);
+
+ cy.saveMacro(name);
+
+ navigateToSettings();
+ cy.umbracoTreeItem("settings", ["Templates", name]).click();
+ // Insert macro
+ cy.umbracoButtonByLabelKey('general_insert').click();
+ cy.get('.umb-insert-code-box__title').contains('Macro').click();
+ cy.get('.umb-card-grid-item').contains(name).click();
- cy.umbracoButtonByLabelKey("general_ok").click();
+ // Assert
+ cy.get('.ace_content').contains('@Umbraco.RenderMacro("' + name + '")').should('exist');
- cy.contains(name).should('not.exist');
+ // Clean
+ cy.umbracoEnsureTemplateNameNotExists(name);
+ cy.umbracoEnsureMacroNameNotExists(name);
+ });
+
+ it('Insert value', () => {
+ const name = 'Insert Value Test';
cy.umbracoEnsureTemplateNameNotExists(name);
+
+ const partialView = new TemplateBuilder()
+ .withName(name)
+ .withContent('')
+ .build();
+
+ cy.saveTemplate(partialView);
+
+ navigateToSettings();
+ cy.umbracoTreeItem("settings", ["Templates", name]).click();
+
+ // Insert value
+ cy.umbracoButtonByLabelKey('general_insert').click();
+ cy.get('.umb-insert-code-box__title').contains('Value').click();
+ cy.get('select').select('umbracoBytes');
+ cy.umbracoButtonByLabelKey('general_submit').click();
+
+ // assert
+ cy.get('.ace_content').contains('@Model.Value("umbracoBytes")').should('exist');
+
+ // Clean
+ cy.umbracoEnsureTemplateNameNotExists(name);
});
+
});
From 2b73b3ddadcb13520e2b6e9858d68b8360ffe70e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Thu, 13 Aug 2020 13:12:07 +0200
Subject: [PATCH 54/89] include PublishedPendingChanges as Published state.
---
.../content/overlays/publish.controller.js | 21 ++++++++++---------
.../src/views/content/overlays/publish.html | 15 ++++++-------
2 files changed, 17 insertions(+), 19 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js
index decf05be5f94..37f005cd4778 100644
--- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js
@@ -11,13 +11,13 @@
/** Returns true if publish meets the requirements of mandatory languages */
function canPublish() {
-
+
var hasSomethingToPublish = false;
for (var i = 0; i < vm.variants.length; i++) {
var variant = vm.variants[i];
- // if varaint is mandatory and not already published:
+ // if varaint is mandatory and not already published, then we require it to be set to publish:
if (variant.publish === false && notPublishedMandatoryFilter(variant)) {
return false;
}
@@ -39,8 +39,9 @@
function hasAnyDataFilter(variant) {
- if (variant.name == null || variant.name.length === 0) {
- return false;
+ // if we have a name, then we have data.
+ if (variant.name != null && variant.name.length > 0) {
+ return true;
}
if(variant.isDirty === true) {
@@ -77,7 +78,7 @@
}
function notPublishedMandatoryFilter(variant) {
- return variant.state !== "Published" && isMandatoryFilter(variant);
+ return variant.state !== "Published" && variant.state !== "PublishedPendingChanges" && isMandatoryFilter(variant);
}
function isMandatoryFilter(variant) {
//determine a variant is 'dirty' (meaning it will show up as publish-able) if it's
@@ -98,11 +99,11 @@
vm.variants = $scope.model.variants;
_.each(vm.variants, (variant) => {
-
+
// reset to not be published
variant.publish = false;
variant.save = false;
-
+
variant.isMandatory = isMandatoryFilter(variant);
// If we have a variant thats not in the state of NotCreated, then we know we have adata and its not a new content node.
@@ -112,12 +113,12 @@
});
_.each(vm.variants, (variant) => {
-
+
// if this is a new node and we have data on this variant.
if(vm.isNew === true && hasAnyDataFilter(variant)) {
variant.save = true;
}
-
+
});
vm.availableVariants = vm.variants.filter(publishableVariantFilter);
@@ -139,7 +140,7 @@
if (a.language.name < b.language.name) {
return 1;
}
- }
+ }
if (a.segment && b.segment) {
if (a.segment > b.segment) {
return -1;
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html
index 71e19651d601..c3e0b90f5f09 100644
--- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html
+++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html
@@ -21,19 +21,16 @@
on-change="vm.changeSelection(variant)"
server-validation-field="{{variant.htmlId}}">
-
-
- *
-
-
-
- — {{variant.language.name}}
- *
+
+
+
+ — {{variant.language.name}}
+ *
-
-
+
{{publishVariantSelectorForm.publishVariantSelector.errorMsg}}
From dde735f75cc96979f3707743fa5c1f1468906e79 Mon Sep 17 00:00:00 2001
From: Sebastiaan Janssen
Date: Thu, 13 Aug 2020 14:33:19 +0200
Subject: [PATCH 55/89] Sync some dependencies that have been updated in
v8/contrib
---
src/Umbraco.Web.UI.Client/package.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json
index 21445e3cb331..454d081fe793 100644
--- a/src/Umbraco.Web.UI.Client/package.json
+++ b/src/Umbraco.Web.UI.Client/package.json
@@ -38,11 +38,11 @@
"lazyload-js": "1.0.0",
"moment": "2.22.2",
"ng-file-upload": "12.2.13",
- "nouislider": "14.4.0",
+ "nouislider": "14.6.0",
"npm": "^6.14.7",
"signalr": "2.4.0",
"spectrum-colorpicker": "1.8.0",
- "tinymce": "4.9.10",
+ "tinymce": "4.9.11",
"typeahead.js": "0.11.1",
"underscore": "1.9.1"
},
@@ -78,7 +78,7 @@
"karma-phantomjs-launcher": "1.0.4",
"karma-spec-reporter": "0.0.32",
"less": "3.10.3",
- "lodash": "4.17.15",
+ "lodash": "4.17.19",
"marked": "^0.7.0",
"merge-stream": "2.0.0",
"run-sequence": "2.2.1"
From 6d6f525343c9f3794063cd96e78a36b39893540c Mon Sep 17 00:00:00 2001
From: Warren Buckley
Date: Tue, 18 Aug 2020 12:43:29 +0100
Subject: [PATCH 56/89] Fix to ensure we use virtual paths for any blocks with
custom views (#8597)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Niels Lyngsø
Co-authored-by: Shannon
---
.../services/umbrequesthelper.service.js | 31 ++++++++++---------
...t.blockconfiguration.overlay.controller.js | 7 +++--
.../blocklist/umbblocklistblock.component.js | 23 +++++++-------
.../services/umb-request-helper.spec.js | 28 +++++++++++++++++
4 files changed, 59 insertions(+), 30 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js
index 7b43b239eadf..90125e7de642 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js
@@ -15,7 +15,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
*
* @description
* This will convert a virtual path (i.e. ~/App_Plugins/Blah/Test.html ) to an absolute path
- *
+ *
* @param {string} a virtual path, if this is already an absolute path it will just be returned, if this is a relative path an exception will be thrown
*/
convertVirtualToAbsolutePath: function(virtualPath) {
@@ -31,6 +31,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
return Umbraco.Sys.ServerVariables.application.applicationPath + virtualPath.trimStart("~/");
},
+
/**
* @ngdoc method
* @name umbraco.services.umbRequestHelper#dictionaryToQueryString
@@ -39,7 +40,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
*
* @description
* This will turn an array of key/value pairs or a standard dictionary into a query string
- *
+ *
* @param {Array} queryStrings An array of key/value pairs
*/
dictionaryToQueryString: function (queryStrings) {
@@ -76,9 +77,9 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
*
* @description
* This will return the webapi Url for the requested key based on the servervariables collection
- *
+ *
* @param {string} apiName The webapi name that is found in the servervariables["umbracoUrls"] dictionary
- * @param {string} actionName The webapi action name
+ * @param {string} actionName The webapi action name
* @param {object} queryStrings Can be either a string or an array containing key/value pairs
*/
getApiUrl: function (apiName, actionName, queryStrings) {
@@ -103,7 +104,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
*
* @description
* This returns a promise with an underlying http call, it is a helper method to reduce
- * the amount of duplicate code needed to query http resources and automatically handle any
+ * the amount of duplicate code needed to query http resources and automatically handle any
* Http errors. See /docs/source/using-promises-resources.md
*
* @param {object} opts A mixed object which can either be a string representing the error message to be
@@ -117,7 +118,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
* The error callback must return an object containing: {errorMsg: errorMessage, data: originalData, status: status }
*/
resourcePromise: function (httpPromise, opts) {
-
+
/** The default success callback used if one is not supplied in the opts */
function defaultSuccess(data, status, headers, config) {
//when it's successful, just return the data
@@ -151,7 +152,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
return httpPromise.then(function (response) {
- //invoke the callback
+ //invoke the callback
var result = callbacks.success.apply(this, [response.data, response.status, response.headers, response.config]);
formHelper.showNotifications(response.data);
@@ -183,7 +184,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
overlayService.ysod(error);
}
else {
- //show a simple error notification
+ //show a simple error notification
notificationsService.error("Server error", "Contact administrator, see log for full details.
" + result.errorMsg + "");
}
@@ -209,7 +210,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
*
* @description
* Used for saving content/media/members specifically
- *
+ *
* @param {Object} args arguments object
* @returns {Promise} http promise object.
*/
@@ -233,7 +234,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
if (args.showNotifications === null || args.showNotifications === undefined) {
args.showNotifications = true;
}
-
+
//save the active tab id so we can set it when the data is returned.
var activeTab = _.find(args.content.tabs, function (item) {
return item.active;
@@ -300,7 +301,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
overlayService.ysod(error);
}
else {
- //show a simple error notification
+ //show a simple error notification
notificationsService.error("Server error", "Contact administrator, see log for full details.
" + response.data.ExceptionMessage + "");
}
@@ -331,7 +332,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
});
}
else if (!jsonData.key || !jsonData.value) { throw "jsonData object must have both a key and a value property"; }
-
+
return $http({
method: 'POST',
url: url,
@@ -366,7 +367,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
return $q.reject(response);
});
},
-
+
/**
* @ngdoc method
* @name umbraco.resources.contentResource#downloadFile
@@ -374,7 +375,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
*
* @description
* Downloads a file to the client using AJAX/XHR
- *
+ *
* @param {string} httpPath the path (url) to the resource being downloaded
* @returns {Promise} http promise object.
*/
@@ -388,7 +389,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe
// Use an arraybuffer
return $http.get(httpPath, { responseType: 'arraybuffer' })
.then(function (response) {
-
+
var octetStreamMime = 'application/octet-stream';
var success = false;
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js
index b1937e718d76..48c21b4009ab 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js
@@ -160,7 +160,7 @@
},
select: function (node) {
const filepath = decodeURIComponent(node.id.replace(/\+/g, " "));
- block.view = filepath;
+ block.view = "~/" + filepath;
editorService.close();
},
close: function () {
@@ -206,7 +206,7 @@
},
select: function (node) {
const filepath = decodeURIComponent(node.id.replace(/\+/g, " "));
- block.stylesheet = filepath;
+ block.stylesheet = "~/" + filepath;
editorService.close();
},
close: function () {
@@ -252,7 +252,8 @@
return !(i.name.indexOf(".jpg") !== -1 || i.name.indexOf(".jpeg") !== -1 || i.name.indexOf(".png") !== -1 || i.name.indexOf(".svg") !== -1 || i.name.indexOf(".webp") !== -1 || i.name.indexOf(".gif") !== -1);
},
select: function (file) {
- block.thumbnail = file.name;
+ const id = decodeURIComponent(file.id.replace(/\+/g, " "));
+ block.thumbnail = "~/" + id;
editorService.close();
},
close: function () {
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbblocklistblock.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbblocklistblock.component.js
index 4474dbd55c42..64fd40459dea 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbblocklistblock.component.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbblocklistblock.component.js
@@ -5,11 +5,11 @@
* @ngdoc directive
* @name umbraco.directives.directive:umbBlockListBlock
* @description
- * The component to render the view for a block.
+ * The component to render the view for a block.
* If a stylesheet is used then this uses a ShadowDom to make a scoped element.
* This way the backoffice styling does not collide with the block style.
*/
-
+
angular
.module("umbraco")
.component("umbBlockListBlock", {
@@ -29,16 +29,16 @@
}
);
- function BlockListBlockController($scope, $compile, $element) {
+ function BlockListBlockController($scope, $compile, $element, umbRequestHelper) {
var model = this;
model.$onInit = function () {
- // This is ugly and is only necessary because we are not using components and instead
+ // This is ugly and is only necessary because we are not using components and instead
// relying on ng-include. It is definitely possible to compile the contents
- // of the view into the DOM using $templateCache and $http instead of using
- // ng - include which means that the controllerAs flows directly to the view.
- // This would mean that any custom components would need to be updated instead of relying on $scope.
- // Guess we'll leave it for now but means all things need to be copied to the $scope and then all
+ // of the view into the DOM using $templateCache and $http instead of using
+ // ng - include which means that the controllerAs flows directly to the view.
+ // This would mean that any custom components would need to be updated instead of relying on $scope.
+ // Guess we'll leave it for now but means all things need to be copied to the $scope and then all
// primitives need to be watched.
$scope.block = model.block;
@@ -48,8 +48,7 @@
$scope.valFormManager = model.valFormManager;
if (model.stylesheet) {
- // TODO: Not sure why this needs a prefixed /? this means it will never work in a virtual directory
- model.stylesheet = "/" + model.stylesheet;
+ model.stylesheet = umbRequestHelper.convertVirtualToAbsolutePath(model.stylesheet);
var shadowRoot = $element[0].attachShadow({ mode: 'open' });
shadowRoot.innerHTML = `