From afca2e70bd44ae0c6a812fdfdd7ff0df4d68822c Mon Sep 17 00:00:00 2001 From: elitsa Date: Tue, 13 Aug 2019 14:17:14 +0200 Subject: [PATCH 001/102] Removing the MiniProfiler routes if solution is not in debug mode. --- .../Profiling/WebProfilerProvider.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Profiling/WebProfilerProvider.cs b/src/Umbraco.Web/Profiling/WebProfilerProvider.cs index ffd1871ecc..68e1555884 100644 --- a/src/Umbraco.Web/Profiling/WebProfilerProvider.cs +++ b/src/Umbraco.Web/Profiling/WebProfilerProvider.cs @@ -1,7 +1,10 @@ using System; +using System.Linq; using System.Threading; using System.Web; +using System.Web.Routing; using StackExchange.Profiling; +using Umbraco.Core.Configuration; namespace Umbraco.Web.Profiling { @@ -24,6 +27,19 @@ namespace Umbraco.Web.Profiling { // booting... _bootPhase = BootPhase.Boot; + + // Remove Mini Profiler routes when not in debug mode + if (GlobalSettings.DebugMode == false) + { + var prefix = MiniProfiler.Settings.RouteBasePath.Replace("~/", string.Empty); + + using (RouteTable.Routes.GetWriteLock()) + { + var routes = RouteTable.Routes.Where(x => x is Route r && r.Url.StartsWith(prefix)).ToList(); + foreach(var r in routes) + RouteTable.Routes.Remove(r); + } + } } /// @@ -118,4 +134,4 @@ namespace Umbraco.Web.Profiling } } } -} \ No newline at end of file +} From f829ac4e6cfc9c20af70f0ce90e6c7a44e0111e8 Mon Sep 17 00:00:00 2001 From: Tom Pipe Date: Fri, 2 Aug 2019 13:32:19 +0100 Subject: [PATCH 002/102] Ensure a media type correctly inherits it's selected parent (cherry picked from commit 28dd9aa081a93e4d65e9ebc15ee890ebcb2974f4) --- src/Umbraco.Web/Editors/MediaTypeController.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web/Editors/MediaTypeController.cs b/src/Umbraco.Web/Editors/MediaTypeController.cs index a258c987f2..830d25f5c6 100644 --- a/src/Umbraco.Web/Editors/MediaTypeController.cs +++ b/src/Umbraco.Web/Editors/MediaTypeController.cs @@ -145,9 +145,18 @@ namespace Umbraco.Web.Editors } public MediaTypeDisplay GetEmpty(int parentId) { - var ct = new MediaType(parentId) {Icon = "icon-picture"}; + IMediaType mt; + if (parentId != Constants.System.Root) + { + var parent = Services.ContentTypeService.GetMediaType(parentId); + mt = parent != null ? new MediaType(parent, string.Empty) : new MediaType(parentId); + } + else + mt = new MediaType(parentId); - var dto = Mapper.Map(ct); + mt.Icon = "icon-picture"; + + var dto = Mapper.Map(mt); return dto; } From ea591c87a257d0b80c18d5d20336baaa79106f1f Mon Sep 17 00:00:00 2001 From: Matt Brailsford Date: Thu, 18 Jul 2019 11:04:06 +0100 Subject: [PATCH 003/102] Fixes #5932, showing "Return to ListView" for new content (cherry picked from commit f3fc83fae6f13b906df466904a32ac4003a4169b) --- .../common/directives/components/content/edit.controller.js | 4 ++++ 1 file changed, 4 insertions(+) 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 5bcab56f48..01e9b12c99 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 @@ -184,6 +184,10 @@ $scope.content = data; + if (data.isChildOfListView && data.trashed === false) { + $scope.page.listViewPath = $routeParams.page ? '/content/content/edit/' + data.parentId + '?page=' + $routeParams.page : '/content/content/edit/' + data.parentId; + } + init($scope.content); resetLastListPageNumber($scope.content); From 802e6d7979b521b2f6fc9ed78090fc1f348b4e31 Mon Sep 17 00:00:00 2001 From: Matt Brailsford Date: Thu, 18 Jul 2019 11:01:46 +0100 Subject: [PATCH 004/102] Fixes #5931, show breadcrumb for new content Could probably do with adding "Untitled" to translation file (cherry picked from commit 249126a2b5202e64c04b212a34fcea91b2260010) --- .../components/content/edit.controller.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) 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 01e9b12c99..db25399135 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 @@ -27,13 +27,18 @@ editorState.set($scope.content); //We fetch all ancestors of the node to generate the footer breadcrumb navigation - if (!$scope.page.isNew) { - if (content.parentId && content.parentId !== -1) { - entityResource.getAncestors(content.id, "document") - .then(function (anc) { - $scope.ancestors = anc; - }); + if (content.parentId && content.parentId !== -1) { + var ancestorIds = content.path.split(','); + ancestorIds.shift(); // Remove -1 + if ($scope.page.isNew) { + ancestorIds.pop(); // Remove 0 } + entityResource.getByIds(ancestorIds, 'document').then(function (anc) { + $scope.ancestors = anc; + if ($scope.page.isNew) { + $scope.ancestors.push({ name: "Untitled" }) + } + }); } evts.push(eventsService.on("editors.content.changePublishDate", function (event, args) { From 9ed1101f273baecfe9e75138e6802533a75cbee0 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 14 Aug 2019 11:16:24 +1000 Subject: [PATCH 005/102] whitespace changes --- .../users/changepassword.directive.js | 298 +++++++++--------- .../components/users/change-password.html | 10 +- 2 files changed, 154 insertions(+), 154 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js index f8dbefa5d7..8919a26dcb 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js @@ -1,167 +1,167 @@ (function () { - 'use strict'; + 'use strict'; - function ChangePasswordController($scope) { + function ChangePasswordController($scope) { - function resetModel(isNew) { - //the model config will contain an object, if it does not we'll create defaults - //NOTE: We will not support doing the password regex on the client side because the regex on the server side - //based on the membership provider cannot always be ported to js from .net directly. - /* - { - hasPassword: true/false, - requiresQuestionAnswer: true/false, - enableReset: true/false, - enablePasswordRetrieval: true/false, - minPasswordLength: 10 - } - */ + function resetModel(isNew) { + //the model config will contain an object, if it does not we'll create defaults + //NOTE: We will not support doing the password regex on the client side because the regex on the server side + //based on the membership provider cannot always be ported to js from .net directly. + /* + { + hasPassword: true/false, + requiresQuestionAnswer: true/false, + enableReset: true/false, + enablePasswordRetrieval: true/false, + minPasswordLength: 10 + } + */ - $scope.showReset = false; + $scope.showReset = false; - //set defaults if they are not available - if ($scope.config.disableToggle === undefined) { - $scope.config.disableToggle = false; - } - if ($scope.config.hasPassword === undefined) { - $scope.config.hasPassword = false; - } - if ($scope.config.enablePasswordRetrieval === undefined) { - $scope.config.enablePasswordRetrieval = true; - } - if ($scope.config.requiresQuestionAnswer === undefined) { - $scope.config.requiresQuestionAnswer = false; - } - //don't enable reset if it is new - that doesn't make sense - if (isNew === "true") { - $scope.config.enableReset = false; - } - else if ($scope.config.enableReset === undefined) { - $scope.config.enableReset = true; - } - - if ($scope.config.minPasswordLength === undefined) { - $scope.config.minPasswordLength = 0; - } - - //set the model defaults - if (!angular.isObject($scope.passwordValues)) { - //if it's not an object then just create a new one - $scope.passwordValues = { - newPassword: null, - oldPassword: null, - reset: null, - answer: null - }; - } - else { - //just reset the values + //set defaults if they are not available + if ($scope.config.disableToggle === undefined) { + $scope.config.disableToggle = false; + } + if ($scope.config.hasPassword === undefined) { + $scope.config.hasPassword = false; + } + if ($scope.config.enablePasswordRetrieval === undefined) { + $scope.config.enablePasswordRetrieval = true; + } + if ($scope.config.requiresQuestionAnswer === undefined) { + $scope.config.requiresQuestionAnswer = false; + } + //don't enable reset if it is new - that doesn't make sense + if (isNew === "true") { + $scope.config.enableReset = false; + } + else if ($scope.config.enableReset === undefined) { + $scope.config.enableReset = true; + } + + if ($scope.config.minPasswordLength === undefined) { + $scope.config.minPasswordLength = 0; + } + + //set the model defaults + if (!angular.isObject($scope.passwordValues)) { + //if it's not an object then just create a new one + $scope.passwordValues = { + newPassword: null, + oldPassword: null, + reset: null, + answer: null + }; + } + else { + //just reset the values + + if (!isNew) { + //if it is new, then leave the generated pass displayed + $scope.passwordValues.newPassword = null; + $scope.passwordValues.oldPassword = null; + } + $scope.passwordValues.reset = null; + $scope.passwordValues.answer = null; + } + + //the value to compare to match passwords + if (!isNew) { + $scope.passwordValues.confirm = ""; + } + else if ($scope.passwordValues.newPassword && $scope.passwordValues.newPassword.length > 0) { + //if it is new and a new password has been set, then set the confirm password too + $scope.passwordValues.confirm = $scope.passwordValues.newPassword; + } - if (!isNew) { - //if it is new, then leave the generated pass displayed - $scope.passwordValues.newPassword = null; - $scope.passwordValues.oldPassword = null; } - $scope.passwordValues.reset = null; - $scope.passwordValues.answer = null; - } - //the value to compare to match passwords - if (!isNew) { - $scope.passwordValues.confirm = ""; - } - else if ($scope.passwordValues.newPassword && $scope.passwordValues.newPassword.length > 0) { - //if it is new and a new password has been set, then set the confirm password too - $scope.passwordValues.confirm = $scope.passwordValues.newPassword; - } + resetModel($scope.isNew); + + //if there is no password saved for this entity , it must be new so we do not allow toggling of the change password, it is always there + //with validators turned on. + $scope.changing = $scope.config.disableToggle === true || !$scope.config.hasPassword; + + //we're not currently changing so set the model to null + if (!$scope.changing) { + $scope.passwordValues = null; + } + + $scope.doChange = function () { + resetModel(); + $scope.changing = true; + //if there was a previously generated password displaying, clear it + $scope.passwordValues.generatedPassword = null; + $scope.passwordValues.confirm = null; + }; + + $scope.cancelChange = function () { + $scope.changing = false; + //set model to null + $scope.passwordValues = null; + }; + + var unsubscribe = []; + + //listen for the saved event, when that occurs we'll + //change to changing = false; + unsubscribe.push($scope.$on("formSubmitted", function () { + if ($scope.config.disableToggle === false) { + $scope.changing = false; + } + })); + unsubscribe.push($scope.$on("formSubmitting", function () { + //if there was a previously generated password displaying, clear it + if ($scope.changing && $scope.passwordValues) { + $scope.passwordValues.generatedPassword = null; + } + else if (!$scope.changing) { + //we are not changing, so the model needs to be null + $scope.passwordValues = null; + } + })); + + //when the scope is destroyed we need to unsubscribe + $scope.$on('$destroy', function () { + for (var u in unsubscribe) { + unsubscribe[u](); + } + }); + + $scope.showOldPass = function () { + return $scope.config.hasPassword && + !$scope.config.allowManuallyChangingPassword && + !$scope.config.enablePasswordRetrieval && !$scope.showReset; + }; + + // TODO: I don't think we need this or the cancel button, this can be up to the editor rendering this directive + $scope.showCancelBtn = function () { + return $scope.config.disableToggle !== true && $scope.config.hasPassword; + }; } - resetModel($scope.isNew); + function ChangePasswordDirective() { - //if there is no password saved for this entity , it must be new so we do not allow toggling of the change password, it is always there - //with validators turned on. - $scope.changing = $scope.config.disableToggle === true || !$scope.config.hasPassword; + var directive = { + restrict: 'E', + replace: true, + templateUrl: 'views/components/users/change-password.html', + controller: 'Umbraco.Editors.Users.ChangePasswordDirectiveController', + scope: { + isNew: "=?", + passwordValues: "=", + config: "=" + } + }; + + return directive; - //we're not currently changing so set the model to null - if (!$scope.changing) { - $scope.passwordValues = null; } - $scope.doChange = function () { - resetModel(); - $scope.changing = true; - //if there was a previously generated password displaying, clear it - $scope.passwordValues.generatedPassword = null; - $scope.passwordValues.confirm = null; - }; - - $scope.cancelChange = function () { - $scope.changing = false; - //set model to null - $scope.passwordValues = null; - }; - - var unsubscribe = []; - - //listen for the saved event, when that occurs we'll - //change to changing = false; - unsubscribe.push($scope.$on("formSubmitted", function () { - if ($scope.config.disableToggle === false) { - $scope.changing = false; - } - })); - unsubscribe.push($scope.$on("formSubmitting", function () { - //if there was a previously generated password displaying, clear it - if ($scope.changing && $scope.passwordValues) { - $scope.passwordValues.generatedPassword = null; - } - else if (!$scope.changing) { - //we are not changing, so the model needs to be null - $scope.passwordValues = null; - } - })); - - //when the scope is destroyed we need to unsubscribe - $scope.$on('$destroy', function () { - for (var u in unsubscribe) { - unsubscribe[u](); - } - }); - - $scope.showOldPass = function () { - return $scope.config.hasPassword && - !$scope.config.allowManuallyChangingPassword && - !$scope.config.enablePasswordRetrieval && !$scope.showReset; - }; - - // TODO: I don't think we need this or the cancel button, this can be up to the editor rendering this directive - $scope.showCancelBtn = function () { - return $scope.config.disableToggle !== true && $scope.config.hasPassword; - }; - - } - - function ChangePasswordDirective() { - - var directive = { - restrict: 'E', - replace: true, - templateUrl: 'views/components/users/change-password.html', - controller: 'Umbraco.Editors.Users.ChangePasswordDirectiveController', - scope: { - isNew: "=?", - passwordValues: "=", - config: "=" - } - }; - - return directive; - - } - - angular.module('umbraco.directives').controller('Umbraco.Editors.Users.ChangePasswordDirectiveController', ChangePasswordController); - angular.module('umbraco.directives').directive('changePassword', ChangePasswordDirective); + angular.module('umbraco.directives').controller('Umbraco.Editors.Users.ChangePasswordDirectiveController', ChangePasswordController); + angular.module('umbraco.directives').directive('changePassword', ChangePasswordDirective); })(); diff --git a/src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html b/src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html index 7b6c7ca0e1..150fbf892b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html @@ -19,10 +19,10 @@ val-server-field="resetPassword" no-dirty-check ng-change="showReset = !showReset" /> - + {{passwordForm.resetPassword.errorMsg}} - + @@ -32,7 +32,7 @@ required val-server-field="oldPassword" no-dirty-check /> - + Required {{passwordForm.oldPassword.errorMsg}} @@ -45,7 +45,7 @@ val-server-field="password" ng-minlength="{{config.minPasswordLength}}" no-dirty-check /> - + Required Minimum {{config.minPasswordLength}} characters {{passwordForm.password.errorMsg}} @@ -57,7 +57,7 @@ class="input-block-level umb-textstring textstring" val-compare="password" no-dirty-check /> - + The confirmed password doesn't match the new password! From d2be30a228af13e34967e89fe11010749b1bad1b Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 14 Aug 2019 12:26:49 +1000 Subject: [PATCH 006/102] converting to component --- .../users/changepassword.directive.js | 191 +++++++++--------- .../components/users/change-password.html | 55 ++--- 2 files changed, 128 insertions(+), 118 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js index 8919a26dcb..97eb2bf708 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js @@ -3,6 +3,17 @@ function ChangePasswordController($scope) { + var vm = this; + + vm.$onInit = onInit; + vm.$onDestroy = onDestroy; + vm.doChange = doChange; + vm.cancelChange = cancelChange; + vm.showOldPass = showOldPass; + vm.showCancelBtn = showCancelBtn; + + var unsubscribe = []; + function resetModel(isNew) { //the model config will contain an object, if it does not we'll create defaults //NOTE: We will not support doing the password regex on the client side because the regex on the server side @@ -17,37 +28,37 @@ } */ - $scope.showReset = false; + vm.showReset = false; //set defaults if they are not available - if ($scope.config.disableToggle === undefined) { - $scope.config.disableToggle = false; + if (vm.config.disableToggle === undefined) { + vm.config.disableToggle = false; } - if ($scope.config.hasPassword === undefined) { - $scope.config.hasPassword = false; + if (vm.config.hasPassword === undefined) { + vm.config.hasPassword = false; } - if ($scope.config.enablePasswordRetrieval === undefined) { - $scope.config.enablePasswordRetrieval = true; + if (vm.config.enablePasswordRetrieval === undefined) { + vm.config.enablePasswordRetrieval = true; } - if ($scope.config.requiresQuestionAnswer === undefined) { - $scope.config.requiresQuestionAnswer = false; + if (vm.config.requiresQuestionAnswer === undefined) { + vm.config.requiresQuestionAnswer = false; } //don't enable reset if it is new - that doesn't make sense if (isNew === "true") { - $scope.config.enableReset = false; + vm.config.enableReset = false; } - else if ($scope.config.enableReset === undefined) { - $scope.config.enableReset = true; + else if (vm.config.enableReset === undefined) { + vm.config.enableReset = true; } - if ($scope.config.minPasswordLength === undefined) { - $scope.config.minPasswordLength = 0; + if (vm.config.minPasswordLength === undefined) { + vm.config.minPasswordLength = 0; } //set the model defaults - if (!angular.isObject($scope.passwordValues)) { + if (!angular.isObject(vm.passwordValues)) { //if it's not an object then just create a new one - $scope.passwordValues = { + vm.passwordValues = { newPassword: null, oldPassword: null, reset: null, @@ -59,109 +70,103 @@ if (!isNew) { //if it is new, then leave the generated pass displayed - $scope.passwordValues.newPassword = null; - $scope.passwordValues.oldPassword = null; + vm.passwordValues.newPassword = null; + vm.passwordValues.oldPassword = null; } - $scope.passwordValues.reset = null; - $scope.passwordValues.answer = null; + vm.passwordValues.reset = null; + vm.passwordValues.answer = null; } //the value to compare to match passwords if (!isNew) { - $scope.passwordValues.confirm = ""; + vm.passwordValues.confirm = ""; } - else if ($scope.passwordValues.newPassword && $scope.passwordValues.newPassword.length > 0) { + else if (vm.passwordValues.newPassword && vm.passwordValues.newPassword.length > 0) { //if it is new and a new password has been set, then set the confirm password too - $scope.passwordValues.confirm = $scope.passwordValues.newPassword; + vm.passwordValues.confirm = vm.passwordValues.newPassword; } } - resetModel($scope.isNew); - - //if there is no password saved for this entity , it must be new so we do not allow toggling of the change password, it is always there - //with validators turned on. - $scope.changing = $scope.config.disableToggle === true || !$scope.config.hasPassword; - - //we're not currently changing so set the model to null - if (!$scope.changing) { - $scope.passwordValues = null; - } - - $scope.doChange = function () { - resetModel(); - $scope.changing = true; - //if there was a previously generated password displaying, clear it - $scope.passwordValues.generatedPassword = null; - $scope.passwordValues.confirm = null; - }; - - $scope.cancelChange = function () { - $scope.changing = false; - //set model to null - $scope.passwordValues = null; - }; - - var unsubscribe = []; - - //listen for the saved event, when that occurs we'll - //change to changing = false; - unsubscribe.push($scope.$on("formSubmitted", function () { - if ($scope.config.disableToggle === false) { - $scope.changing = false; - } - })); - unsubscribe.push($scope.$on("formSubmitting", function () { - //if there was a previously generated password displaying, clear it - if ($scope.changing && $scope.passwordValues) { - $scope.passwordValues.generatedPassword = null; - } - else if (!$scope.changing) { - //we are not changing, so the model needs to be null - $scope.passwordValues = null; - } - })); - //when the scope is destroyed we need to unsubscribe - $scope.$on('$destroy', function () { + function onDestroy() { for (var u in unsubscribe) { unsubscribe[u](); } - }); + } - $scope.showOldPass = function () { - return $scope.config.hasPassword && - !$scope.config.allowManuallyChangingPassword && - !$scope.config.enablePasswordRetrieval && !$scope.showReset; - }; + function onInit() { + //listen for the saved event, when that occurs we'll + //change to changing = false; + unsubscribe.push($scope.$on("formSubmitted", function () { + if (vm.config.disableToggle === false) { + vm.changing = false; + } + })); - // TODO: I don't think we need this or the cancel button, this can be up to the editor rendering this directive - $scope.showCancelBtn = function () { - return $scope.config.disableToggle !== true && $scope.config.hasPassword; - }; + unsubscribe.push($scope.$on("formSubmitting", function () { + //if there was a previously generated password displaying, clear it + if (vm.changing && vm.passwordValues) { + vm.passwordValues.generatedPassword = null; + } + else if (!vm.changing) { + //we are not changing, so the model needs to be null + vm.passwordValues = null; + } + })); - } + resetModel(vm.isNew); - function ChangePasswordDirective() { + //if there is no password saved for this entity , it must be new so we do not allow toggling of the change password, it is always there + //with validators turned on. + vm.changing = vm.config.disableToggle === true || !vm.config.hasPassword; - var directive = { - restrict: 'E', - replace: true, - templateUrl: 'views/components/users/change-password.html', - controller: 'Umbraco.Editors.Users.ChangePasswordDirectiveController', - scope: { - isNew: "=?", - passwordValues: "=", - config: "=" + //we're not currently changing so set the model to null + if (!vm.changing) { + vm.passwordValues = null; } + } + + function doChange() { + resetModel(); + vm.changing = true; + //if there was a previously generated password displaying, clear it + vm.passwordValues.generatedPassword = null; + vm.passwordValues.confirm = null; }; - return directive; + function cancelChange() { + vm.changing = false; + //set model to null + vm.passwordValues = null; + }; + + function showOldPass() { + return vm.config.hasPassword && + !vm.config.allowManuallyChangingPassword && + !vm.config.enablePasswordRetrieval && !vm.showReset; + }; + + // TODO: I don't think we need this or the cancel button, this can be up to the editor rendering this component + function showCancelBtn() { + return vm.config.disableToggle !== true && vm.config.hasPassword; + }; } - angular.module('umbraco.directives').controller('Umbraco.Editors.Users.ChangePasswordDirectiveController', ChangePasswordController); - angular.module('umbraco.directives').directive('changePassword', ChangePasswordDirective); + var component = { + templateUrl: 'views/components/users/change-password.html', + controller: ChangePasswordController, + controllerAs: 'vm', + bindings: { + isNew: "<", + passwordValues: "=", //TODO: Do we need bi-directional vals? + config: "=" //TODO: Do we need bi-directional vals? + //TODO: Do we need callbacks? + } + }; + + angular.module('umbraco.directives').component('changePassword', component); })(); diff --git a/src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html b/src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html index 150fbf892b..026918231e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html @@ -1,68 +1,73 @@
-
+
Password has been reset to:
- {{passwordValues.generatedPassword}} + {{vm.passwordValues.generatedPassword}}
-
+
- - - Hello +
{{vm.showReset}}
+
{{vm.passwordValues | json}}
+ + + + - - {{passwordForm.resetPassword.errorMsg}} + ng-change="vm.showReset = !vm.showReset" /> + + {{vm.passwordForm.resetPassword.errorMsg}} - +
- - + - + Required - {{passwordForm.oldPassword.errorMsg}} + {{vm.passwordForm.oldPassword.errorMsg}} - - + - + Required - Minimum {{config.minPasswordLength}} characters - {{passwordForm.password.errorMsg}} + Minimum {{vm.config.minPasswordLength}} characters + {{vm.passwordForm.password.errorMsg}} - - + - + The confirmed password doesn't match the new password! - + Cancel From df391c86f379f6a7d514ac3a9238e4e0632f2613 Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 14 Aug 2019 12:45:39 +1000 Subject: [PATCH 007/102] Fixes re-syncing member and media data after saving --- .../src/common/services/contenteditinghelper.service.js | 4 ++-- .../src/views/components/users/change-password.html | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) 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 732f682082..a1c1bdcae4 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 @@ -484,7 +484,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt var savedVariants = []; if (origContent.variants) { isContent = true; - //it's contnet so assign the variants as they exist + //it's content so assign the variants as they exist origVariants = origContent.variants; savedVariants = savedContent.variants; } @@ -510,7 +510,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt //special case for content, don't sync this variant if it wasn't tagged //for saving in the first place - if (!origVariant.save) { + if (isContent && !origVariant.save) { continue; } diff --git a/src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html b/src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html index 026918231e..ef5f7a4159 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html @@ -12,10 +12,6 @@
-
Hello
-
{{vm.showReset}}
-
{{vm.passwordValues | json}}
- Date: Wed, 14 Aug 2019 14:49:05 +1000 Subject: [PATCH 008/102] Fixes dropping unique constraint indexes and oddly named FKs --- .../DeleteKeysAndIndexesBuilder.cs | 44 +++++++++++++++---- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Core/Migrations/Expressions/Delete/KeysAndIndexes/DeleteKeysAndIndexesBuilder.cs b/src/Umbraco.Core/Migrations/Expressions/Delete/KeysAndIndexes/DeleteKeysAndIndexesBuilder.cs index 9b13457b76..df74bf7c87 100644 --- a/src/Umbraco.Core/Migrations/Expressions/Delete/KeysAndIndexes/DeleteKeysAndIndexesBuilder.cs +++ b/src/Umbraco.Core/Migrations/Expressions/Delete/KeysAndIndexes/DeleteKeysAndIndexesBuilder.cs @@ -1,5 +1,7 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using NPoco; +using Umbraco.Core; using Umbraco.Core.Migrations.Expressions.Common; using Umbraco.Core.Persistence.SqlSyntax; @@ -27,31 +29,57 @@ namespace Umbraco.Core.Migrations.Expressions.Delete.KeysAndIndexes { _context.BuildingExpression = false; + //get a list of all constraints - this will include all PK, FK and unique constraints + var tableConstraints = _context.SqlContext.SqlSyntax.GetConstraintsPerTable(_context.Database).DistinctBy(x => x.Item2).ToList(); + + //get a list of defined indexes - this will include all indexes, unique indexes and unique constraint indexes + var indexes = _context.SqlContext.SqlSyntax.GetDefinedIndexesDefinitions(_context.Database).DistinctBy(x => x.IndexName).ToList(); + + var uniqueConstraintNames = tableConstraints.Where(x => !x.Item2.InvariantStartsWith("PK_") && !x.Item2.InvariantStartsWith("FK_")).Select(x => x.Item2); + var indexNames = indexes.Select(x => x.IndexName).ToList(); + // drop keys if (DeleteLocal || DeleteForeign) { // table, constraint - var tableKeys = _context.SqlContext.SqlSyntax.GetConstraintsPerTable(_context.Database).DistinctBy(x => x.Item2).ToList(); + if (DeleteForeign) { - foreach (var key in tableKeys.Where(x => x.Item1 == TableName && x.Item2.StartsWith("FK_"))) + //In some cases not all FK's are prefixed with "FK" :/ mostly with old upgraded databases so we need to check if it's either: + // * starts with FK OR + // * doesn't start with PK_ and doesn't exist in the list of indexes + + foreach (var key in tableConstraints.Where(x => x.Item1 == TableName + && (x.Item2.InvariantStartsWith("FK_") || (!x.Item2.InvariantStartsWith("PK_") && !indexNames.InvariantContains(x.Item2))))) + { Delete.ForeignKey(key.Item2).OnTable(key.Item1).Do(); + } + } if (DeleteLocal) { - foreach (var key in tableKeys.Where(x => x.Item1 == TableName && x.Item2.StartsWith("PK_"))) + foreach (var key in tableConstraints.Where(x => x.Item1 == TableName && x.Item2.InvariantStartsWith("PK_"))) Delete.PrimaryKey(key.Item2).FromTable(key.Item1).Do(); - // note: we do *not* delete the DEFAULT constraints + // note: we do *not* delete the DEFAULT constraints and if we wanted to we'd have to deal with that in interesting ways + // since SQL server has a specific way to handle that, see SqlServerSyntaxProvider.GetDefaultConstraintsPerColumn } } // drop indexes if (DeleteLocal) - { - var indexes = _context.SqlContext.SqlSyntax.GetDefinedIndexesDefinitions(_context.Database).DistinctBy(x => x.IndexName).ToList(); + { foreach (var index in indexes.Where(x => x.TableName == TableName)) - Delete.Index(index.IndexName).OnTable(index.TableName).Do(); + { + //if this is a unique constraint we need to drop the constraint, else drop the index + //to figure this out, the index must be tagged as unique and it must exist in the tableConstraints + + if (index.IsUnique && uniqueConstraintNames.InvariantContains(index.IndexName)) + Delete.UniqueConstraint(index.IndexName).FromTable(index.TableName).Do(); + else + Delete.Index(index.IndexName).OnTable(index.TableName).Do(); + } + } } From ee2068de568255145be396dd32f3e1094537cbb6 Mon Sep 17 00:00:00 2001 From: elitsa Date: Wed, 14 Aug 2019 14:03:32 +0200 Subject: [PATCH 009/102] Removing legacy service --- .../umbraco/webservices/legacyAjaxCalls.asmx.cs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/legacyAjaxCalls.asmx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/legacyAjaxCalls.asmx.cs index 1929477181..a29e44a92b 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/legacyAjaxCalls.asmx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/legacyAjaxCalls.asmx.cs @@ -36,19 +36,7 @@ namespace umbraco.presentation.webservices public class legacyAjaxCalls : UmbracoAuthorizedWebService { private User _currentUser; - - [WebMethod] - public bool ValidateUser(string username, string password) - { - if (ValidateCredentials(username, password)) - { - var u = new BusinessLogic.User(username); - BasePage.doLogin(u); - return true; - } - return false; - } - + /// /// method to accept a string value for the node id. Used for tree's such as python /// and xslt since the file names are the node IDs From 806d835a9008641c4ee418fdf2ed75a84c17532e Mon Sep 17 00:00:00 2001 From: Steve Megson Date: Wed, 14 Aug 2019 21:14:48 +0100 Subject: [PATCH 010/102] Handle null and missing grid values in migration --- .../V_8_1_0/ConvertTinyMceAndGridMediaUrlsToLocalLink.cs | 4 ++-- .../PropertyEditors/GridPropertyIndexValueFactory.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_1_0/ConvertTinyMceAndGridMediaUrlsToLocalLink.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_1_0/ConvertTinyMceAndGridMediaUrlsToLocalLink.cs index 1b6597a660..b68aa23d78 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_1_0/ConvertTinyMceAndGridMediaUrlsToLocalLink.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_1_0/ConvertTinyMceAndGridMediaUrlsToLocalLink.cs @@ -50,10 +50,10 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_1_0 var obj = JsonConvert.DeserializeObject(value); var allControls = obj.SelectTokens("$.sections..rows..areas..controls"); - foreach (var control in allControls.SelectMany(c => c)) + foreach (var control in allControls.SelectMany(c => c).OfType()) { var controlValue = control["value"]; - if (controlValue.Type == JTokenType.String) + if (controlValue?.Type == JTokenType.String) { control["value"] = UpdateMediaUrls(mediaLinkPattern, controlValue.Value()); } diff --git a/src/Umbraco.Web/PropertyEditors/GridPropertyIndexValueFactory.cs b/src/Umbraco.Web/PropertyEditors/GridPropertyIndexValueFactory.cs index 085d66f3c6..7e47d0dcd6 100644 --- a/src/Umbraco.Web/PropertyEditors/GridPropertyIndexValueFactory.cs +++ b/src/Umbraco.Web/PropertyEditors/GridPropertyIndexValueFactory.cs @@ -43,7 +43,7 @@ namespace Umbraco.Web.PropertyEditors // TODO: If it's not a string, then it's a json formatted value - // we cannot really index this in a smart way since it could be 'anything' - if (controlVal.Type == JTokenType.String) + if (controlVal?.Type == JTokenType.String) { var str = controlVal.Value(); str = XmlHelper.CouldItBeXml(str) ? str.StripHtml() : str; From 7e8364eae48be9bbd3a160c3f3aab03eb374ab1f Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Thu, 15 Aug 2019 13:10:17 +0200 Subject: [PATCH 011/102] V8: Support mixed element variance in Nested Content (#5952) (cherry picked from commit e7a9ee8142b45de6633a10b923d84e84f0b9d0ef) --- .../nestedcontent/nestedcontent.controller.js | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js index 7ead8974d8..aaf7ed08bb 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js @@ -489,32 +489,30 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop node.key = fromNcEntry && fromNcEntry.key ? fromNcEntry.key : String.CreateGuid(); - for (var v = 0; v < node.variants.length; v++) { - var variant = node.variants[v]; - - for (var t = 0; t < variant.tabs.length; t++) { - var tab = variant.tabs[t]; + var variant = node.variants[0]; + + for (var t = 0; t < variant.tabs.length; t++) { + var tab = variant.tabs[t]; - for (var p = 0; p < tab.properties.length; p++) { - var prop = tab.properties[p]; + for (var p = 0; p < tab.properties.length; p++) { + var prop = tab.properties[p]; - prop.propertyAlias = prop.alias; - prop.alias = $scope.model.alias + "___" + prop.alias; - // Force validation to occur server side as this is the - // only way we can have consistency between mandatory and - // regex validation messages. Not ideal, but it works. - prop.validation = { - mandatory: false, - pattern: "" - }; + prop.propertyAlias = prop.alias; + prop.alias = $scope.model.alias + "___" + prop.alias; + // Force validation to occur server side as this is the + // only way we can have consistency between mandatory and + // regex validation messages. Not ideal, but it works. + prop.validation = { + mandatory: false, + pattern: "" + }; - if (fromNcEntry && fromNcEntry[prop.propertyAlias]) { - prop.value = fromNcEntry[prop.propertyAlias]; - } + if (fromNcEntry && fromNcEntry[prop.propertyAlias]) { + prop.value = fromNcEntry[prop.propertyAlias]; } } } - + $scope.nodes.push(node); return node; From a0af474c757a48d6680ff005aa2e54f4090dadd2 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 15 Aug 2019 13:29:14 +0200 Subject: [PATCH 012/102] Bump version to 8.1.3 --- src/SolutionInfo.cs | 4 ++-- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index 5feffc0b57..2da07d523f 100644 --- a/src/SolutionInfo.cs +++ b/src/SolutionInfo.cs @@ -18,5 +18,5 @@ using System.Resources; [assembly: AssemblyVersion("8.0.0")] // these are FYI and changed automatically -[assembly: AssemblyFileVersion("8.1.2")] -[assembly: AssemblyInformationalVersion("8.1.2")] +[assembly: AssemblyFileVersion("8.1.3")] +[assembly: AssemblyInformationalVersion("8.1.3")] diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index b5d908f32e..fada1cf9c4 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -345,9 +345,9 @@ False True - 8120 + 8130 / - http://localhost:8120 + http://localhost:8130 False False From 8e2eccb3925f0f6d19322a09d314d87263c31e30 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 15 Aug 2019 13:32:09 +0200 Subject: [PATCH 013/102] Bump version to 7.15.2 --- src/SolutionInfo.cs | 4 ++-- src/Umbraco.Core/Configuration/UmbracoVersion.cs | 2 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index 3a85915cf5..ffaec90fa7 100644 --- a/src/SolutionInfo.cs +++ b/src/SolutionInfo.cs @@ -11,5 +11,5 @@ using System.Resources; [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("7.15.1")] -[assembly: AssemblyInformationalVersion("7.15.1")] +[assembly: AssemblyFileVersion("7.15.2")] +[assembly: AssemblyInformationalVersion("7.15.2")] diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs index f23078dbd0..b02e199313 100644 --- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs +++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration { public class UmbracoVersion { - private static readonly Version Version = new Version("7.15.1"); + private static readonly Version Version = new Version("7.15.2"); /// /// Gets the current version of Umbraco. diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 42f607d64e..4eddca0b8d 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -1028,9 +1028,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\" True True - 7151 + 7152 / - http://localhost:7151 + http://localhost:7152 False False From 3087eff147c12c73220515df53f0a264c489fc79 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 14 Aug 2019 21:25:02 +0200 Subject: [PATCH 014/102] Don't reuse previously used content templates --- .../src/views/content/content.create.controller.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.create.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.create.controller.js index f906369926..1413965a19 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.create.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.create.controller.js @@ -51,7 +51,10 @@ function contentCreateController($scope, .search("create", "true") /* when we create a new node we want to make sure it uses the same language as what is selected in the tree */ - .search("cculture", mainCulture); + .search("cculture", mainCulture) + /* when we create a new node we must make sure that any previously + used blueprint is reset */ + .search("blueprintId", null); close(); } From 455395154a569acc7a4c0c1f04d2f8849eae8a67 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 14 Aug 2019 21:25:02 +0200 Subject: [PATCH 015/102] Don't reuse previously used content templates (cherry picked from commit 3087eff147c12c73220515df53f0a264c489fc79) --- .../src/views/content/content.create.controller.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.create.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.create.controller.js index f906369926..1413965a19 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.create.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.create.controller.js @@ -51,7 +51,10 @@ function contentCreateController($scope, .search("create", "true") /* when we create a new node we want to make sure it uses the same language as what is selected in the tree */ - .search("cculture", mainCulture); + .search("cculture", mainCulture) + /* when we create a new node we must make sure that any previously + used blueprint is reset */ + .search("blueprintId", null); close(); } From f1f9e1742ebf529e18e9f87c22581195c95a4760 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 14 Aug 2019 08:50:25 +0200 Subject: [PATCH 016/102] Use an Umbraco confirm dialog when deleting groups --- .../users/views/groups/groups.controller.js | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js index 9c476103a5..1e51d4585e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js @@ -2,7 +2,7 @@ "use strict"; function UserGroupsController($scope, $timeout, $location, $filter, userService, userGroupsResource, - formHelper, localizationService, listViewHelper) { + formHelper, localizationService, listViewHelper, overlayService) { var vm = this; @@ -95,18 +95,26 @@ if(vm.selection.length > 0) { - localizationService.localize("defaultdialogs_confirmdelete") - .then(function(value) { - - var confirmResponse = confirm(value); - - if (confirmResponse === true) { - userGroupsResource.deleteUserGroups(_.pluck(vm.selection, "id")).then(function (data) { - clearSelection(); - onInit(); - }, angular.noop); - } - + localizationService.localizeMany(["general_delete", "defaultdialogs_confirmdelete", "general_cancel", "contentTypeEditor_yesDelete"]) + .then(function (data) { + const overlay = { + title: data[0], + content: data[1] + "?", + closeButtonLabel: data[2], + submitButtonLabel: data[3], + submitButtonStyle: "danger", + close: function () { + overlayService.close(); + }, + submit: function () { + userGroupsResource.deleteUserGroups(_.pluck(vm.selection, "id")).then(function (data) { + clearSelection(); + onInit(); + }, angular.noop); + overlayService.close(); + } + }; + overlayService.open(overlay); }); } From f8409be50673615f015f63efbe9e1b6962a40328 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 14 Aug 2019 08:50:25 +0200 Subject: [PATCH 017/102] Use an Umbraco confirm dialog when deleting groups (cherry picked from commit f1f9e1742ebf529e18e9f87c22581195c95a4760) --- .../users/views/groups/groups.controller.js | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js index 9c476103a5..1e51d4585e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js @@ -2,7 +2,7 @@ "use strict"; function UserGroupsController($scope, $timeout, $location, $filter, userService, userGroupsResource, - formHelper, localizationService, listViewHelper) { + formHelper, localizationService, listViewHelper, overlayService) { var vm = this; @@ -95,18 +95,26 @@ if(vm.selection.length > 0) { - localizationService.localize("defaultdialogs_confirmdelete") - .then(function(value) { - - var confirmResponse = confirm(value); - - if (confirmResponse === true) { - userGroupsResource.deleteUserGroups(_.pluck(vm.selection, "id")).then(function (data) { - clearSelection(); - onInit(); - }, angular.noop); - } - + localizationService.localizeMany(["general_delete", "defaultdialogs_confirmdelete", "general_cancel", "contentTypeEditor_yesDelete"]) + .then(function (data) { + const overlay = { + title: data[0], + content: data[1] + "?", + closeButtonLabel: data[2], + submitButtonLabel: data[3], + submitButtonStyle: "danger", + close: function () { + overlayService.close(); + }, + submit: function () { + userGroupsResource.deleteUserGroups(_.pluck(vm.selection, "id")).then(function (data) { + clearSelection(); + onInit(); + }, angular.noop); + overlayService.close(); + } + }; + overlayService.open(overlay); }); } From 4743fc0e1d4b76cbf19aa1af3f858ad2bb65e61b Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Tue, 13 Aug 2019 21:14:28 +0200 Subject: [PATCH 018/102] Don't change parent protection when editing child protection --- src/Umbraco.Web/Editors/ContentController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 4e420206d3..9d5af028e3 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -2297,7 +2297,7 @@ namespace Umbraco.Web.Editors } var entry = Services.PublicAccessService.GetEntryForContent(content); - if (entry == null) + if (entry == null || entry.ProtectedNodeId != content.Id) { return Request.CreateResponse(HttpStatusCode.OK); } @@ -2379,7 +2379,7 @@ namespace Umbraco.Web.Editors var entry = Services.PublicAccessService.GetEntryForContent(content); - if (entry == null) + if (entry == null || entry.ProtectedNodeId != content.Id) { entry = new PublicAccessEntry(content, loginPage, errorPage, new List()); From 16ac2c5589dabf65747b95e7122e58b9a82858d3 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Tue, 13 Aug 2019 21:14:28 +0200 Subject: [PATCH 019/102] Don't change parent protection when editing child protection (cherry picked from commit 4743fc0e1d4b76cbf19aa1af3f858ad2bb65e61b) --- src/Umbraco.Web/Editors/ContentController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index 4e420206d3..9d5af028e3 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -2297,7 +2297,7 @@ namespace Umbraco.Web.Editors } var entry = Services.PublicAccessService.GetEntryForContent(content); - if (entry == null) + if (entry == null || entry.ProtectedNodeId != content.Id) { return Request.CreateResponse(HttpStatusCode.OK); } @@ -2379,7 +2379,7 @@ namespace Umbraco.Web.Editors var entry = Services.PublicAccessService.GetEntryForContent(content); - if (entry == null) + if (entry == null || entry.ProtectedNodeId != content.Id) { entry = new PublicAccessEntry(content, loginPage, errorPage, new List()); From 0baf5eab0ac52c32c1c9900beeaad29cb6462d8c Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Thu, 15 Aug 2019 21:09:58 +0200 Subject: [PATCH 020/102] v8: Rename datetime picker component (#6110) --- ...tive.js => umbdatetimepicker.directive.js} | 27 ++++++++++--------- src/Umbraco.Web.UI.Client/src/less/belle.less | 2 +- ...atpickr.less => umb-date-time-picker.less} | 2 +- .../querybuilder/querybuilder.html | 4 +-- .../src/views/content/overlays/schedule.html | 16 +++++------ .../src/views/logviewer/overview.html | 4 +-- .../datepicker/datepicker.html | 4 +-- 7 files changed, 30 insertions(+), 29 deletions(-) rename src/Umbraco.Web.UI.Client/src/common/directives/components/{umbflatpickr.directive.js => umbdatetimepicker.directive.js} (93%) rename src/Umbraco.Web.UI.Client/src/less/components/{umb-flatpickr.less => umb-date-time-picker.less} (90%) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbflatpickr.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdatetimepicker.directive.js similarity index 93% rename from src/Umbraco.Web.UI.Client/src/common/directives/components/umbflatpickr.directive.js rename to src/Umbraco.Web.UI.Client/src/common/directives/components/umbdatetimepicker.directive.js index 79b29b407b..899b8f3c23 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbflatpickr.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdatetimepicker.directive.js @@ -1,13 +1,13 @@ /** @ngdoc directive -@name umbraco.directives.directive:umbFlatpickr +@name umbraco.directives.directive:umbDateTimePicker @restrict E @scope @description Added in Umbraco version 8.0 This directive is a wrapper of the flatpickr library. Use it to render a date time picker. -For extra details about options and events take a look here: https://flatpickr.js.org/ +For extra details about options and events take a look here: https://flatpickr.js.org Use this directive to render a date time picker @@ -15,11 +15,11 @@ Use this directive to render a date time picker
 	
- - +
@@ -70,12 +70,12 @@ Use this directive to render a date time picker (function() { 'use strict'; - var umbFlatpickr = { + var umbDateTimePicker = { template: '' + '' + '
' + '
', - controller: umbFlatpickrCtrl, + controller: umbDateTimePickerCtrl, transclude: true, bindings: { ngModel: '<', @@ -92,9 +92,9 @@ Use this directive to render a date time picker } }; - function umbFlatpickrCtrl($element, $timeout, $scope, assetsService, userService) { + function umbDateTimePickerCtrl($element, $timeout, $scope, assetsService, userService) { + var ctrl = this; - var loaded = false; var userLocale = null; ctrl.$onInit = function() { @@ -102,14 +102,14 @@ Use this directive to render a date time picker // load css file for the date picker assetsService.loadCss('lib/flatpickr/flatpickr.css', $scope).then(function () { userService.getCurrentUser().then(function (user) { + // init date picker userLocale = user.locale; if (userLocale.indexOf('-') > -1) { userLocale = userLocale.split('-')[0]; } - loaded = true; - grabElementAndRunFlatpickr(); + grabElementAndRunFlatpickr(); }); }); @@ -234,7 +234,8 @@ Use this directive to render a date time picker } } - - angular.module('umbraco.directives').component('umbFlatpickr', umbFlatpickr); - + + // umbFlatpickr (umb-flatpickr) is deprecated, but we keep it for backwards compatibility + angular.module('umbraco.directives').component('umbFlatpickr', umbDateTimePicker); + angular.module('umbraco.directives').component('umbDateTimePicker', umbDateTimePicker); })(); diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index bd1cdd5b4f..8ee842d6b5 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -112,7 +112,7 @@ @import "components/umb-editor-navigation-item.less"; @import "components/umb-editor-sub-views.less"; @import "components/editor/subheader/umb-editor-sub-header.less"; -@import "components/umb-flatpickr.less"; +@import "components/umb-date-time-picker.less"; @import "components/umb-grid-selector.less"; @import "components/umb-child-selector.less"; @import "components/umb-group-builder.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-flatpickr.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less similarity index 90% rename from src/Umbraco.Web.UI.Client/src/less/components/umb-flatpickr.less rename to src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less index 8cdcc8b877..2df0cc5fd8 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-flatpickr.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less @@ -1,4 +1,4 @@ -.flatpickr-calendar.flatpickr-calendar { +.flatpickr-calendar { border-radius: @baseBorderRadius; box-shadow: 0 5px 10px 0 rgba(0,0,0,0.16); } diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html index 8376f50713..779ca739d2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html @@ -109,10 +109,10 @@ - - + diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html b/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html index b573acaf52..a0fe7baec2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/schedule.html @@ -15,7 +15,7 @@
-
- + @@ -47,7 +47,7 @@
-
- +
@@ -112,7 +112,7 @@
Publish:  {{variant.releaseDateFormatted}}
- + @@ -138,7 +138,7 @@
Unpublish:  {{variant.expireDateFormatted}}
- Set date
- + diff --git a/src/Umbraco.Web.UI.Client/src/views/logviewer/overview.html b/src/Umbraco.Web.UI.Client/src/views/logviewer/overview.html index 533659e808..300c824329 100644 --- a/src/Umbraco.Web.UI.Client/src/views/logviewer/overview.html +++ b/src/Umbraco.Web.UI.Client/src/views/logviewer/overview.html @@ -74,11 +74,11 @@ - - +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html index 99961110aa..101f3254ab 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html @@ -4,7 +4,7 @@
-
- +
From 2b7154622ef99771cefa7e87b52513ea159c0a05 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Thu, 8 Aug 2019 23:35:58 +0200 Subject: [PATCH 021/102] Set media picker dirty when the value changes --- .../mediapicker/mediapicker.controller.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js index 120407ab10..e59e2bb26a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js @@ -1,7 +1,7 @@ //this controller simply tells the dialogs service to open a mediaPicker window //with a specified callback, this callback will receive an object with a selection on it angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerController", - function ($scope, entityResource, mediaHelper, $timeout, userService, localizationService, editorService) { + function ($scope, entityResource, mediaHelper, $timeout, userService, localizationService, editorService, angularHelper) { var vm = { labels: { @@ -92,6 +92,10 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl $scope.model.value = $scope.ids.join(); }; + function setDirty() { + angularHelper.getCurrentForm($scope).$setDirty(); + } + function reloadUpdatedMediaItems(updatedMediaNodes) { // because the images can be edited through the media picker we need to // reload. We only reload the images that is already picked but has been updated. @@ -152,6 +156,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl $scope.mediaItems.splice(index, 1); $scope.ids.splice(index, 1); sync(); + setDirty(); }; $scope.editItem = function (item) { @@ -215,6 +220,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl }); sync(); reloadUpdatedMediaItems(model.updatedMediaNodes); + setDirty(); }, close: function (model) { editorService.close(); @@ -233,6 +239,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl items: "li:not(.add-wrapper)", cancel: ".unsortable", update: function (e, ui) { + setDirty(); var r = []; // TODO: Instead of doing this with a half second delay would be better to use a watch like we do in the // content picker. Then we don't have to worry about setting ids, render models, models, we just set one and let the From 65b2d08997a44b6d10cff62b710e4257bdd92e3b Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Thu, 8 Aug 2019 23:35:58 +0200 Subject: [PATCH 022/102] Set media picker dirty when the value changes (cherry picked from commit 2b7154622ef99771cefa7e87b52513ea159c0a05) --- .../mediapicker/mediapicker.controller.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js index 120407ab10..e59e2bb26a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js @@ -1,7 +1,7 @@ //this controller simply tells the dialogs service to open a mediaPicker window //with a specified callback, this callback will receive an object with a selection on it angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerController", - function ($scope, entityResource, mediaHelper, $timeout, userService, localizationService, editorService) { + function ($scope, entityResource, mediaHelper, $timeout, userService, localizationService, editorService, angularHelper) { var vm = { labels: { @@ -92,6 +92,10 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl $scope.model.value = $scope.ids.join(); }; + function setDirty() { + angularHelper.getCurrentForm($scope).$setDirty(); + } + function reloadUpdatedMediaItems(updatedMediaNodes) { // because the images can be edited through the media picker we need to // reload. We only reload the images that is already picked but has been updated. @@ -152,6 +156,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl $scope.mediaItems.splice(index, 1); $scope.ids.splice(index, 1); sync(); + setDirty(); }; $scope.editItem = function (item) { @@ -215,6 +220,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl }); sync(); reloadUpdatedMediaItems(model.updatedMediaNodes); + setDirty(); }, close: function (model) { editorService.close(); @@ -233,6 +239,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl items: "li:not(.add-wrapper)", cancel: ".unsortable", update: function (e, ui) { + setDirty(); var r = []; // TODO: Instead of doing this with a half second delay would be better to use a watch like we do in the // content picker. Then we don't have to worry about setting ids, render models, models, we just set one and let the From 0d63b13bf0e29381bdc18d24d9944a034fc0260b Mon Sep 17 00:00:00 2001 From: skttl Date: Thu, 8 Aug 2019 09:32:23 +0200 Subject: [PATCH 023/102] Changes mode of styleselect to All --- src/Umbraco.Web.UI/config/tinyMceConfig.Release.config | 4 ++-- src/Umbraco.Web.UI/config/tinyMceConfig.config | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI/config/tinyMceConfig.Release.config b/src/Umbraco.Web.UI/config/tinyMceConfig.Release.config index 40630b7eb6..f6a26ee89a 100644 --- a/src/Umbraco.Web.UI/config/tinyMceConfig.Release.config +++ b/src/Umbraco.Web.UI/config/tinyMceConfig.Release.config @@ -1,4 +1,4 @@ - + @@ -8,7 +8,7 @@ - + diff --git a/src/Umbraco.Web.UI/config/tinyMceConfig.config b/src/Umbraco.Web.UI/config/tinyMceConfig.config index a686021cbf..7f7cb657e6 100644 --- a/src/Umbraco.Web.UI/config/tinyMceConfig.config +++ b/src/Umbraco.Web.UI/config/tinyMceConfig.config @@ -1,4 +1,4 @@ - + @@ -8,7 +8,7 @@ - + From 53c52abde5dbac3c61d2f7481340d28bd48b1780 Mon Sep 17 00:00:00 2001 From: Marc Goodson Date: Fri, 2 Aug 2019 21:34:22 +0100 Subject: [PATCH 024/102] Update GetPagedResultsByQuery to return id of the node the audit item relates to instead of table PK This was fixed previously in v7 - see https://github.com/umbraco/Umbraco-CMS/pull/3759 --- .../Persistence/Repositories/Implement/AuditRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs index c25328b10c..0788594e3a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs @@ -174,7 +174,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement totalRecords = page.TotalItems; var items = page.Items.Select( - dto => new AuditItem(dto.Id, Enum.ParseOrNull(dto.Header) ?? AuditType.Custom, dto.UserId ?? Constants.Security.UnknownUserId, dto.EntityType, dto.Comment, dto.Parameters)).ToList(); + dto => new AuditItem(dto.NodeId, Enum.ParseOrNull(dto.Header) ?? AuditType.Custom, dto.UserId ?? Constants.Security.UnknownUserId, dto.EntityType, dto.Comment, dto.Parameters)).ToList(); // map the DateStamp for (var i = 0; i < items.Count; i++) From cec4376d199e617546292d726829c0a456c75655 Mon Sep 17 00:00:00 2001 From: Marc Goodson Date: Fri, 2 Aug 2019 21:34:22 +0100 Subject: [PATCH 025/102] Update GetPagedResultsByQuery to return id of the node the audit item relates to instead of table PK This was fixed previously in v7 - see https://github.com/umbraco/Umbraco-CMS/pull/3759 (cherry picked from commit 53c52abde5dbac3c61d2f7481340d28bd48b1780) --- .../Persistence/Repositories/Implement/AuditRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs index c25328b10c..0788594e3a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/AuditRepository.cs @@ -174,7 +174,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement totalRecords = page.TotalItems; var items = page.Items.Select( - dto => new AuditItem(dto.Id, Enum.ParseOrNull(dto.Header) ?? AuditType.Custom, dto.UserId ?? Constants.Security.UnknownUserId, dto.EntityType, dto.Comment, dto.Parameters)).ToList(); + dto => new AuditItem(dto.NodeId, Enum.ParseOrNull(dto.Header) ?? AuditType.Custom, dto.UserId ?? Constants.Security.UnknownUserId, dto.EntityType, dto.Comment, dto.Parameters)).ToList(); // map the DateStamp for (var i = 0; i < items.Count; i++) From 5452ebaf6d95611dfa62cecacce112c2935b8cfb Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Fri, 2 Aug 2019 14:54:01 +0100 Subject: [PATCH 026/102] Import and export of document type and property variations setting in packages --- .../Packaging/PackageDataInstallation.cs | 19 +++++++++++++------ .../Services/Implement/EntityXmlSerializer.cs | 6 ++++-- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Core/Packaging/PackageDataInstallation.cs b/src/Umbraco.Core/Packaging/PackageDataInstallation.cs index c811f484bc..2f6b91edee 100644 --- a/src/Umbraco.Core/Packaging/PackageDataInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageDataInstallation.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Text.RegularExpressions; using System.Web; using System.Xml.Linq; using System.Xml.XPath; @@ -575,12 +574,11 @@ namespace Umbraco.Core.Packaging contentType.Thumbnail = infoElement.Element("Thumbnail").Value; contentType.Description = infoElement.Element("Description").Value; - //NOTE AllowAtRoot is a new property in the package xml so we need to verify it exists before using it. + //NOTE AllowAtRoot, IsListView, IsElement and Variations are new properties in the package xml so we need to verify it exists before using it. var allowAtRoot = infoElement.Element("AllowAtRoot"); if (allowAtRoot != null) contentType.AllowedAsRoot = allowAtRoot.Value.InvariantEquals("true"); - //NOTE IsListView is a new property in the package xml so we need to verify it exists before using it. var isListView = infoElement.Element("IsListView"); if (isListView != null) contentType.IsContainer = isListView.Value.InvariantEquals("true"); @@ -589,6 +587,10 @@ namespace Umbraco.Core.Packaging if (isElement != null) contentType.IsElement = isElement.Value.InvariantEquals("true"); + var variationsElement = infoElement.Element("Variations"); + if (variationsElement != null) + contentType.Variations = (ContentVariation)Enum.Parse(typeof(ContentVariation), variationsElement.Value); + //Name of the master corresponds to the parent and we need to ensure that the Parent Id is set var masterElement = infoElement.Element("Master"); if (masterElement != null) @@ -614,7 +616,7 @@ namespace Umbraco.Core.Packaging var compositionContentType = importedContentTypes.ContainsKey(compositionAlias) ? importedContentTypes[compositionAlias] : _contentTypeService.Get(compositionAlias); - var added = contentType.AddContentType(compositionContentType); + contentType.AddContentType(compositionContentType); } } } @@ -748,9 +750,14 @@ namespace Umbraco.Core.Packaging { Name = property.Element("Name").Value, Description = (string)property.Element("Description"), - Mandatory = property.Element("Mandatory") != null ? property.Element("Mandatory").Value.ToLowerInvariant().Equals("true") : false, + Mandatory = property.Element("Mandatory") != null + ? property.Element("Mandatory").Value.ToLowerInvariant().Equals("true") + : false, ValidationRegExp = (string)property.Element("Validation"), - SortOrder = sortOrder + SortOrder = sortOrder, + Variations = property.Element("Variations") != null + ? (ContentVariation)Enum.Parse(typeof(ContentVariation), property.Element("Variations").Value) + : ContentVariation.Nothing }; var tab = (string)property.Element("Tab"); diff --git a/src/Umbraco.Core/Services/Implement/EntityXmlSerializer.cs b/src/Umbraco.Core/Services/Implement/EntityXmlSerializer.cs index 863ecc0b1b..ace740a831 100644 --- a/src/Umbraco.Core/Services/Implement/EntityXmlSerializer.cs +++ b/src/Umbraco.Core/Services/Implement/EntityXmlSerializer.cs @@ -437,7 +437,8 @@ namespace Umbraco.Core.Services.Implement new XElement("Description", contentType.Description), new XElement("AllowAtRoot", contentType.AllowedAsRoot.ToString()), new XElement("IsListView", contentType.IsContainer.ToString()), - new XElement("IsElement", contentType.IsElement.ToString())); + new XElement("IsElement", contentType.IsElement.ToString()), + new XElement("Variations", contentType.Variations.ToString())); var masterContentType = contentType.ContentTypeComposition.FirstOrDefault(x => x.Id == contentType.ParentId); if(masterContentType != null) @@ -487,7 +488,8 @@ namespace Umbraco.Core.Services.Implement new XElement("SortOrder", propertyType.SortOrder), new XElement("Mandatory", propertyType.Mandatory.ToString()), propertyType.ValidationRegExp != null ? new XElement("Validation", propertyType.ValidationRegExp) : null, - propertyType.Description != null ? new XElement("Description", new XCData(propertyType.Description)) : null); + propertyType.Description != null ? new XElement("Description", new XCData(propertyType.Description)) : null, + new XElement("Variations", propertyType.Variations.ToString())); genericProperties.Add(genericProperty); } From cd355910b390b1200e2037154ea19525476519a5 Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 16 Aug 2019 15:34:49 +1000 Subject: [PATCH 027/102] strangely i need the fully qualified name here else i get an error, otherwise works great. --- src/Umbraco.Web/Profiling/WebProfilerProvider.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Profiling/WebProfilerProvider.cs b/src/Umbraco.Web/Profiling/WebProfilerProvider.cs index 68e1555884..e0dcfcf9b1 100644 --- a/src/Umbraco.Web/Profiling/WebProfilerProvider.cs +++ b/src/Umbraco.Web/Profiling/WebProfilerProvider.cs @@ -31,7 +31,8 @@ namespace Umbraco.Web.Profiling // Remove Mini Profiler routes when not in debug mode if (GlobalSettings.DebugMode == false) { - var prefix = MiniProfiler.Settings.RouteBasePath.Replace("~/", string.Empty); + //NOTE: Keep the global fully qualified name, for some reason without it I was getting null refs + var prefix = global::StackExchange.Profiling.MiniProfiler.Settings.RouteBasePath.Replace("~/", string.Empty); using (RouteTable.Routes.GetWriteLock()) { From 505b5410405bee415ea57cc9abf3e3a94f551e6c Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 16 Aug 2019 15:39:46 +1000 Subject: [PATCH 028/102] Removing the MiniProfiler routes if solution is not in debug mode. --- .../Profiling/WebProfilerProvider.cs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Profiling/WebProfilerProvider.cs b/src/Umbraco.Web/Profiling/WebProfilerProvider.cs index ffd1871ecc..e0dcfcf9b1 100644 --- a/src/Umbraco.Web/Profiling/WebProfilerProvider.cs +++ b/src/Umbraco.Web/Profiling/WebProfilerProvider.cs @@ -1,7 +1,10 @@ using System; +using System.Linq; using System.Threading; using System.Web; +using System.Web.Routing; using StackExchange.Profiling; +using Umbraco.Core.Configuration; namespace Umbraco.Web.Profiling { @@ -24,6 +27,20 @@ namespace Umbraco.Web.Profiling { // booting... _bootPhase = BootPhase.Boot; + + // Remove Mini Profiler routes when not in debug mode + if (GlobalSettings.DebugMode == false) + { + //NOTE: Keep the global fully qualified name, for some reason without it I was getting null refs + var prefix = global::StackExchange.Profiling.MiniProfiler.Settings.RouteBasePath.Replace("~/", string.Empty); + + using (RouteTable.Routes.GetWriteLock()) + { + var routes = RouteTable.Routes.Where(x => x is Route r && r.Url.StartsWith(prefix)).ToList(); + foreach(var r in routes) + RouteTable.Routes.Remove(r); + } + } } /// @@ -118,4 +135,4 @@ namespace Umbraco.Web.Profiling } } } -} \ No newline at end of file +} From 6e1314ae304a63b605ca62e87d74fdd3281eb1bb Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 16 Aug 2019 15:58:13 +1000 Subject: [PATCH 029/102] Removing legacy service --- .../umbraco/webservices/legacyAjaxCalls.asmx.cs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/legacyAjaxCalls.asmx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/legacyAjaxCalls.asmx.cs index 1929477181..a29e44a92b 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/legacyAjaxCalls.asmx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/legacyAjaxCalls.asmx.cs @@ -36,19 +36,7 @@ namespace umbraco.presentation.webservices public class legacyAjaxCalls : UmbracoAuthorizedWebService { private User _currentUser; - - [WebMethod] - public bool ValidateUser(string username, string password) - { - if (ValidateCredentials(username, password)) - { - var u = new BusinessLogic.User(username); - BasePage.doLogin(u); - return true; - } - return false; - } - + /// /// method to accept a string value for the node id. Used for tree's such as python /// and xslt since the file names are the node IDs From 438133ae1fdcaec26df913848ebdebe0fc6e123c Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Mon, 12 Aug 2019 21:52:00 +0200 Subject: [PATCH 030/102] Make sure treepicker URLs are displayed for the current editor culture --- .../src/common/resources/entity.resource.js | 9 +++++++-- src/Umbraco.Web/Editors/EntityController.cs | 7 +++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js index 7852180dfa..9cf1181cfa 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js @@ -104,21 +104,26 @@ function entityResource($q, $http, umbRequestHelper) { * * @param {Int} id Id of node to return the public url to * @param {string} type Object type name + * @param {string} culture Culture * @returns {Promise} resourcePromise object containing the url. * */ - getUrl: function (id, type) { + getUrl: function (id, type, culture) { if (id === -1 || id === "-1") { return ""; } + if (!culture) { + culture = ""; + } + return umbRequestHelper.resourcePromise( $http.get( umbRequestHelper.getApiUrl( "entityApiBaseUrl", "GetUrl", - [{ id: id }, {type: type }])), + [{ id: id }, {type: type }, {culture: culture }])), 'Failed to retrieve url for id:' + id); }, diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 5e094534d2..0513017b70 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -211,17 +211,20 @@ namespace Umbraco.Web.Editors /// /// Int id of the entity to fetch URL for /// The type of entity such as Document, Media, Member + /// The culture to fetch the URL for /// The URL or path to the item /// /// We are not restricting this with security because there is no sensitive data /// - public HttpResponseMessage GetUrl(int id, UmbracoEntityTypes type) + public HttpResponseMessage GetUrl(int id, UmbracoEntityTypes type, string culture = null) { + culture = culture ?? ClientCulture(); + var returnUrl = string.Empty; if (type == UmbracoEntityTypes.Document) { - var foundUrl = UmbracoContext.Url(id); + var foundUrl = UmbracoContext.Url(id, culture); if (string.IsNullOrEmpty(foundUrl) == false && foundUrl != "#") { returnUrl = foundUrl; From 0e565ddbf83811138712e38614caf208bd2f452c Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Mon, 12 Aug 2019 21:52:00 +0200 Subject: [PATCH 031/102] Make sure treepicker URLs are displayed for the current editor culture (cherry picked from commit 438133ae1fdcaec26df913848ebdebe0fc6e123c) --- .../src/common/resources/entity.resource.js | 9 +++++++-- src/Umbraco.Web/Editors/EntityController.cs | 7 +++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js index 234ed588c5..e8bdb9efb3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js @@ -104,21 +104,26 @@ function entityResource($q, $http, umbRequestHelper) { * * @param {Int} id Id of node to return the public url to * @param {string} type Object type name + * @param {string} culture Culture * @returns {Promise} resourcePromise object containing the url. * */ - getUrl: function (id, type) { + getUrl: function (id, type, culture) { if (id === -1 || id === "-1") { return ""; } + if (!culture) { + culture = ""; + } + return umbRequestHelper.resourcePromise( $http.get( umbRequestHelper.getApiUrl( "entityApiBaseUrl", "GetUrl", - [{ id: id }, {type: type }])), + [{ id: id }, {type: type }, {culture: culture }])), 'Failed to retrieve url for id:' + id); }, diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index b3edb308a2..f53251fb23 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -210,17 +210,20 @@ namespace Umbraco.Web.Editors /// /// Int id of the entity to fetch URL for /// The type of entity such as Document, Media, Member + /// The culture to fetch the URL for /// The URL or path to the item /// /// We are not restricting this with security because there is no sensitive data /// - public HttpResponseMessage GetUrl(int id, UmbracoEntityTypes type) + public HttpResponseMessage GetUrl(int id, UmbracoEntityTypes type, string culture = null) { + culture = culture ?? ClientCulture(); + var returnUrl = string.Empty; if (type == UmbracoEntityTypes.Document) { - var foundUrl = UmbracoContext.Url(id); + var foundUrl = UmbracoContext.Url(id, culture); if (string.IsNullOrEmpty(foundUrl) == false && foundUrl != "#") { returnUrl = foundUrl; From e4f19f71926ff1c0db427d6604798795fbe88f8c Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Fri, 16 Aug 2019 11:52:34 +0200 Subject: [PATCH 032/102] v8: Add umbLoader directive (#4987) --- .../components/umbloader.directive.js | 75 +++++++++++++++++++ .../components/umbloadindicator.directive.js | 2 +- src/Umbraco.Web.UI.Client/src/less/belle.less | 1 + .../less/components/application/umb-tour.less | 12 ++- .../src/less/components/umb-loader.less | 42 +++++++++++ src/Umbraco.Web.UI.Client/src/less/main.less | 36 --------- .../components/application/umb-tour.html | 3 +- .../src/views/components/umb-loader.html | 3 + .../src/views/content/copy.html | 4 +- .../src/views/content/emptyrecyclebin.html | 5 +- .../src/views/content/move.html | 4 +- .../src/views/datatypes/move.html | 4 +- .../src/views/documenttypes/copy.html | 4 +- .../src/views/documenttypes/move.html | 4 +- .../src/views/media/emptyrecyclebin.html | 5 +- .../src/views/mediatypes/copy.html | 4 +- .../src/views/mediatypes/move.html | 4 +- .../propertyeditors/listview/listview.html | 5 +- 18 files changed, 145 insertions(+), 72 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/umbloader.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/umb-loader.less create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/umb-loader.html diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbloader.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbloader.directive.js new file mode 100644 index 0000000000..e70f7b3cac --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbloader.directive.js @@ -0,0 +1,75 @@ +/** +@ngdoc directive +@name umbraco.directives.directive:umbLoader +@restrict E + +@description +Use this directive to generate a loading indicator. + +

Markup example

+
+    
+ + + + +
+

{{content}}

+
+ +
+
+ +

Controller example

+
+    (function () {
+        "use strict";
+
+        function Controller(myService) {
+
+            var vm = this;
+
+            vm.content = "";
+            vm.loading = true;
+
+            myService.getContent().then(function(content){
+                vm.content = content;
+                vm.loading = false;
+            });
+
+        }
+
+        angular.module("umbraco").controller("My.Controller", Controller);
+    })();
+
+ +@param {string=} position The loader position ("top", "bottom"). + +**/ + +(function() { + 'use strict'; + + function UmbLoaderDirective() { + + function link(scope, el, attr, ctrl) { + + } + + var directive = { + restrict: 'E', + replace: true, + templateUrl: 'views/components/umb-loader.html', + scope: { + position: "@?" + }, + link: link + }; + + return directive; + } + + angular.module('umbraco.directives').directive('umbLoader', UmbLoaderDirective); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbloadindicator.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbloadindicator.directive.js index 0671770796..c45b8f3f47 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbloadindicator.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbloadindicator.directive.js @@ -39,7 +39,7 @@ Use this directive to generate a loading indicator. }); } -½ + angular.module("umbraco").controller("My.Controller", Controller); })(); diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index 8ee842d6b5..b0b7e80762 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -124,6 +124,7 @@ @import "components/umb-form-check.less"; @import "components/umb-locked-field.less"; @import "components/umb-tabs.less"; +@import "components/umb-loader.less"; @import "components/umb-load-indicator.less"; @import "components/umb-breadcrumbs.less"; @import "components/umb-media-grid.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/application/umb-tour.less b/src/Umbraco.Web.UI.Client/src/less/components/application/umb-tour.less index 315cd91dbd..33a723a3f7 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/application/umb-tour.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/application/umb-tour.less @@ -1,8 +1,12 @@ -.umb-tour__loader { - background: @white; - z-index: @zindexTourModal; +.umb-loader-wrapper.umb-tour__loader { + margin: 0; position: fixed; - height: 5px; + z-index: @zindexTourModal; + + .umb-loader { + background-color: @white; + height: 5px; + } } .umb-tour__pulse { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-loader.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-loader.less new file mode 100644 index 0000000000..260710ce72 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-loader.less @@ -0,0 +1,42 @@ +// Loading Animation +// ------------------------ + +.umb-loader { + background-color: @blue; + margin-top: 0; + margin-left: -100%; + animation-name: bounce_loadingProgressG; + animation-duration: 1s; + animation-iteration-count: infinite; + animation-timing-function: linear; + width: 100%; + height: 2px; +} + +@keyframes bounce_loadingProgressG { + 0% { + margin-left: -100%; + } + + 100% { + margin-left: 100%; + } +} + +.umb-loader-wrapper { + position: absolute; + right: 0; + left: 0; + margin: 10px 0; + overflow: hidden; +} + +.umb-loader-wrapper.-top { + top: 0; + bottom: auto; +} + +.umb-loader-wrapper.-bottom { + top: auto; + bottom: 0; +} diff --git a/src/Umbraco.Web.UI.Client/src/less/main.less b/src/Umbraco.Web.UI.Client/src/less/main.less index c10f846ca5..920fcdb1eb 100644 --- a/src/Umbraco.Web.UI.Client/src/less/main.less +++ b/src/Umbraco.Web.UI.Client/src/less/main.less @@ -486,42 +486,6 @@ table thead a { color:@green; } -// Loading Animation -// ------------------------ - -.umb-loader{ - background-color: @blue; - margin-top:0; - margin-left:-100%; - animation-name:bounce_loadingProgressG; - animation-duration:1s; - animation-iteration-count:infinite; - animation-timing-function:linear; - width:100%; - height:2px; -} - -@keyframes bounce_loadingProgressG{ - 0%{ - margin-left:-100%; - } - 100%{ - margin-left:100%; - } -} - -.umb-loader-wrapper { - position: absolute; - right: 0; - left: 0; - margin: 10px 0; - overflow: hidden; -} - -.umb-loader-wrapper.-bottom { - bottom: 0; -} - // Helpers .strong { diff --git a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-tour.html b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-tour.html index 5410d453c4..9a2fe96289 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-tour.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-tour.html @@ -1,6 +1,7 @@
-
+ +
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-loader.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-loader.html new file mode 100644 index 0000000000..07aeb7fdfa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-loader.html @@ -0,0 +1,3 @@ +
+
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/copy.html b/src/Umbraco.Web.UI.Client/src/views/content/copy.html index 0ebe577ed8..111dacd7cb 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/copy.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/copy.html @@ -24,9 +24,7 @@ to in the tree structure below

-
-
-
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/emptyrecyclebin.html b/src/Umbraco.Web.UI.Client/src/views/content/emptyrecyclebin.html index 524bb06354..9ac7ef10fc 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/emptyrecyclebin.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/emptyrecyclebin.html @@ -1,9 +1,8 @@
-
-
-
+ +

When items are deleted from the recycle bin, they will be gone forever. diff --git a/src/Umbraco.Web.UI.Client/src/views/content/move.html b/src/Umbraco.Web.UI.Client/src/views/content/move.html index fd154f438a..3c073ba404 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/move.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/move.html @@ -24,9 +24,7 @@ to in the tree structure below

-
-
-
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/datatypes/move.html b/src/Umbraco.Web.UI.Client/src/views/datatypes/move.html index a5cf6b1a41..7e7e70d650 100644 --- a/src/Umbraco.Web.UI.Client/src/views/datatypes/move.html +++ b/src/Umbraco.Web.UI.Client/src/views/datatypes/move.html @@ -7,9 +7,7 @@ Select the folder to move {{source.name}} to in the tree structure below

-
-
-
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/copy.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/copy.html index 03b090fc54..8b81462ad5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/copy.html +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/copy.html @@ -7,9 +7,7 @@ Select the folder to copy {{source.name}} to in the tree structure below

-
-
-
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/move.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/move.html index 46626d924b..fe0bde7f1f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/move.html +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/move.html @@ -7,9 +7,7 @@ Select the folder to move {{source.name}} to in the tree structure below

-
-
-
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/media/emptyrecyclebin.html b/src/Umbraco.Web.UI.Client/src/views/media/emptyrecyclebin.html index 9d1b28edc9..33681f9269 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/emptyrecyclebin.html +++ b/src/Umbraco.Web.UI.Client/src/views/media/emptyrecyclebin.html @@ -2,9 +2,8 @@
-
-
-
+ +

When items are deleted from the recycle bin, they will be gone forever. diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/copy.html b/src/Umbraco.Web.UI.Client/src/views/mediatypes/copy.html index 5e7b9c6669..9c21f623b5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/copy.html +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/copy.html @@ -7,9 +7,7 @@ Select the folder to copy {{source.name}} to in the tree structure below

-
-
-
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/move.html b/src/Umbraco.Web.UI.Client/src/views/mediatypes/move.html index 0e02c7ad0e..5225a41a0d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/move.html +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/move.html @@ -7,9 +7,7 @@ Select the folder to move {{source.name}} to in the tree structure below

-
-
-
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html index 2c70ba5730..2d61e18a79 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html @@ -95,9 +95,8 @@ {{ selectedItemsCount() }} of {{ listViewResultSet.items.length }} selected -
-
-
+ + From defcb727f94301faa0b08496f88852bf75657791 Mon Sep 17 00:00:00 2001 From: elitsa Date: Fri, 16 Aug 2019 13:34:25 +0200 Subject: [PATCH 033/102] Add special checks and preview for svg files media files. --- .../media/umbmedianodeinfo.directive.js | 35 +++++++++++++++---- .../components/media/umb-media-node-info.html | 10 ++++-- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js index efdeceb78f..677dccf3bb 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js @@ -1,25 +1,29 @@ (function () { 'use strict'; - function MediaNodeInfoDirective($timeout, $location, eventsService, userService, dateHelper) { + function MediaNodeInfoDirective($timeout, $location, eventsService, userService, dateHelper, mediaHelper) { function link(scope, element, attrs, ctrl) { var evts = []; - + function onInit() { // If logged in user has access to the settings section // show the open anchors - if the user doesn't have // access, contentType is null, see MediaModelMapper scope.allowOpen = scope.node.contentType !== null; - + // get document type details scope.mediaType = scope.node.contentType; // set the media link initially setMediaLink(); + // make sure dates are formatted to the user's locale formatDatesToLocal(); + + // set media file extension initially + setMediaExtension(); } function formatDatesToLocal() { @@ -30,26 +34,43 @@ }); } - function setMediaLink(){ + function setMediaLink() { scope.nodeUrl = scope.node.mediaLink; } + function setMediaExtension() { + scope.node.extension = mediaHelper.getFileExtension(scope.nodeUrl); + } + scope.openMediaType = function (mediaType) { // remove first "#" from url if it is prefixed else the path won't work var url = "/settings/mediaTypes/edit/" + mediaType.id; $location.path(url); }; + scope.openSVG = function () { + var popup = window.open('', '_blank'); + var html = '' + + ''; + + popup.document.open(); + popup.document.write(html); + popup.document.close(); + } + // watch for content updates - reload content when node is saved, published etc. - scope.$watch('node.updateDate', function(newValue, oldValue){ - if(!newValue) { return; } - if(newValue === oldValue) { return; } + scope.$watch('node.updateDate', function (newValue, oldValue) { + if (!newValue) { return; } + if (newValue === oldValue) { return; } // Update the media link setMediaLink(); // Update the create and update dates formatDatesToLocal(); + + //Update the media file format + setMediaExtension(); }); //ensure to unregister from all events! diff --git a/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html b/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html index 7cfcb835a5..5ee68e5cff 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html @@ -12,9 +12,15 @@ From 7a7adfb61fd6e008fd5a0b402d90ea983d1001a1 Mon Sep 17 00:00:00 2001 From: Elitsa Marinovska <21998037+elit0451@users.noreply.github.com> Date: Sat, 17 Aug 2019 23:54:49 +0200 Subject: [PATCH 034/102] Fixed typo in "ng-container" --- .../src/views/components/media/umb-media-node-info.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html b/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html index 5ee68e5cff..3f71ae2d18 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html @@ -12,12 +12,12 @@
From 1089b4b9bb25e18140fc319e2cc0cfc228bf60ec Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Thu, 22 Aug 2019 20:36:26 +0200 Subject: [PATCH 049/102] Don't crash the linkpicker if only an anchor has been entered --- .../common/infiniteeditors/linkpicker/linkpicker.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js index 5da14fc6d3..b5043293e5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js @@ -93,7 +93,7 @@ angular.module("umbraco").controller("Umbraco.Editors.LinkPickerController", }); } - } else if ($scope.model.target.url.length) { + } else if ($scope.model.target.url && $scope.model.target.url.length) { // a url but no id/udi indicates an external link - trim the url to remove the anchor/qs // only do the substring if there's a # or a ? var indexOfAnchor = $scope.model.target.url.search(/(#|\?)/); From a2899b21b66b1bca9be193a03644596d6c94dc90 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Thu, 22 Aug 2019 20:36:26 +0200 Subject: [PATCH 050/102] Don't crash the linkpicker if only an anchor has been entered (cherry picked from commit 1089b4b9bb25e18140fc319e2cc0cfc228bf60ec) --- .../common/infiniteeditors/linkpicker/linkpicker.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js index 5a0ab51fd0..ece95593b0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/linkpicker/linkpicker.controller.js @@ -93,7 +93,7 @@ angular.module("umbraco").controller("Umbraco.Editors.LinkPickerController", }); } - } else if ($scope.model.target.url.length) { + } else if ($scope.model.target.url && $scope.model.target.url.length) { // a url but no id/udi indicates an external link - trim the url to remove the anchor/qs // only do the substring if there's a # or a ? var indexOfAnchor = $scope.model.target.url.search(/(#|\?)/); From d57ebf021cad88b218935654edd423d399500454 Mon Sep 17 00:00:00 2001 From: Nik Date: Thu, 22 Aug 2019 09:43:41 +0100 Subject: [PATCH 051/102] Added trck by $index to handle duplicate names in blueprints --- src/Umbraco.Web.UI.Client/src/views/content/create.html | 2 +- .../src/views/propertyeditors/listview/listview.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/content/create.html b/src/Umbraco.Web.UI.Client/src/views/content/create.html index 5bad56988d..e19ae32e6e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/create.html @@ -25,7 +25,7 @@
From 0aaf284f7f56f31ccee96e440f14925fd91f7b9f Mon Sep 17 00:00:00 2001 From: "B. Gunnarsson" Date: Mon, 19 Aug 2019 15:20:20 +0000 Subject: [PATCH 055/102] Update nestedcontent.editor.html forgot the "property-" prefix. --- .../propertyeditors/nestedcontent/nestedcontent.editor.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html index 480ae14dd4..f254c9f276 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html @@ -1,7 +1,7 @@ 
- + From d2649e935489bb0a6a0395323c3254082f786c25 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 22 Aug 2019 22:31:36 +0200 Subject: [PATCH 056/102] Update nestedcontent.editor.html forgot the "property-" prefix. (cherry picked from commit 0aaf284f7f56f31ccee96e440f14925fd91f7b9f) --- .../propertyeditors/nestedcontent/nestedcontent.editor.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html index 5d89da51b6..f254c9f276 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html @@ -1,7 +1,7 @@ 
- + @@ -10,4 +10,4 @@

{{property.notSupportedMessage}}

-
\ No newline at end of file +
From ac6e3998474ae4c92dbf3a7732982fee53d287b5 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 22 Aug 2019 22:31:36 +0200 Subject: [PATCH 057/102] Update nestedcontent.editor.html forgot the "property-" prefix. (cherry picked from commit 0aaf284f7f56f31ccee96e440f14925fd91f7b9f) (cherry picked from commit d2649e935489bb0a6a0395323c3254082f786c25) # Conflicts: # src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html --- .../propertyeditors/nestedcontent/nestedcontent.editor.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html index 0cf67022c6..db0e9a016e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html @@ -1,7 +1,7 @@ 
- + From 88145d70fc1cd919cebd0245ecc8ed0b0e1d967f Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 22 Aug 2019 22:31:36 +0200 Subject: [PATCH 058/102] Update nestedcontent.editor.html forgot the "property-" prefix. (cherry picked from commit 0aaf284f7f56f31ccee96e440f14925fd91f7b9f) (cherry picked from commit d2649e935489bb0a6a0395323c3254082f786c25) # Conflicts: # src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html (cherry picked from commit ac6e3998474ae4c92dbf3a7732982fee53d287b5) --- .../propertyeditors/nestedcontent/nestedcontent.editor.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html index 0cf67022c6..db0e9a016e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html @@ -1,7 +1,7 @@ 
- + From 9b212121e3c4f3d617fb0ba097c94e98681f4fd2 Mon Sep 17 00:00:00 2001 From: stevemegson Date: Thu, 22 Aug 2019 22:34:33 +0100 Subject: [PATCH 059/102] V8: Fix caching of macro results in RTE (#6010) --- .../ValueConverters/RteMacroRenderingValueConverter.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs index cb6ce6dd6d..d5e1f841ea 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.Macros; +using System.Web; namespace Umbraco.Web.PropertyEditors.ValueConverters { @@ -63,7 +64,14 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters } } - public override object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview) + public override object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview) + { + var converted = Convert(inter, preview); + + return new HtmlString(converted == null ? string.Empty : converted); + } + + private string Convert(object source, bool preview) { if (source == null) { From 703092c12c979a8902afe7676c18beade4005f99 Mon Sep 17 00:00:00 2001 From: stevemegson Date: Thu, 22 Aug 2019 22:34:33 +0100 Subject: [PATCH 060/102] V8: Fix caching of macro results in RTE (#6010) (cherry picked from commit 9b212121e3c4f3d617fb0ba097c94e98681f4fd2) --- .../ValueConverters/RteMacroRenderingValueConverter.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs index cb6ce6dd6d..d5e1f841ea 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/RteMacroRenderingValueConverter.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Cache; using Umbraco.Core.Services; using Umbraco.Web.Composing; using Umbraco.Web.Macros; +using System.Web; namespace Umbraco.Web.PropertyEditors.ValueConverters { @@ -63,7 +64,14 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters } } - public override object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview) + public override object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview) + { + var converted = Convert(inter, preview); + + return new HtmlString(converted == null ? string.Empty : converted); + } + + private string Convert(object source, bool preview) { if (source == null) { From d8355c368f2cacc1f292769bd6c544cc73d89be4 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 22 Aug 2019 23:40:24 +0200 Subject: [PATCH 061/102] Too many weird versions --- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 696d33cf0a..4141b60a3d 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -347,13 +347,7 @@ True 8200 / - http://localhost:8200 - 8120 - / - http://localhost:8120 - 7152 - / - http://localhost:7152 + http://localhost:8200/ False False From d09be604d99be75892be6b31d45a3994f3faeca5 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Tue, 20 Aug 2019 10:58:35 +0200 Subject: [PATCH 062/102] Allow plugin "Lang" folders to reside in nested directories --- src/Umbraco.Core/Composing/CompositionExtensions/Services.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Composing/CompositionExtensions/Services.cs b/src/Umbraco.Core/Composing/CompositionExtensions/Services.cs index 0baefe104b..d252c58730 100644 --- a/src/Umbraco.Core/Composing/CompositionExtensions/Services.cs +++ b/src/Umbraco.Core/Composing/CompositionExtensions/Services.cs @@ -96,7 +96,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions var pluginLangFolders = appPlugins.Exists == false ? Enumerable.Empty() : appPlugins.GetDirectories() - .SelectMany(x => x.GetDirectories("Lang")) + .SelectMany(x => x.GetDirectories("Lang", SearchOption.AllDirectories)) .SelectMany(x => x.GetFiles("*.xml", SearchOption.TopDirectoryOnly)) .Select(x => new LocalizedTextServiceSupplementaryFileSource(x, false)); From 11f28554428390cf1e518c298e9959bd767020b5 Mon Sep 17 00:00:00 2001 From: Steve Megson Date: Thu, 8 Aug 2019 08:56:08 +0100 Subject: [PATCH 063/102] Move CreateRoutes from WebFinalComponent to WebInitialComponent --- .../Routing/RenderRouteHandlerTests.cs | 2 +- src/Umbraco.Web/Runtime/WebFinalComponent.cs | 110 +----------------- .../Runtime/WebInitialComponent.cs | 102 +++++++++++++++- 3 files changed, 103 insertions(+), 111 deletions(-) diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index 935417c510..135172460d 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -40,7 +40,7 @@ namespace Umbraco.Tests.Routing { base.SetUp(); - WebFinalComponent.CreateRoutes( + WebInitialComponent.CreateRoutes( new TestUmbracoContextAccessor(), TestObjects.GetGlobalSettings(), new SurfaceControllerTypeCollection(Enumerable.Empty()), diff --git a/src/Umbraco.Web/Runtime/WebFinalComponent.cs b/src/Umbraco.Web/Runtime/WebFinalComponent.cs index 6177d9b868..2ba78b2080 100644 --- a/src/Umbraco.Web/Runtime/WebFinalComponent.cs +++ b/src/Umbraco.Web/Runtime/WebFinalComponent.cs @@ -1,39 +1,18 @@ using System; -using System.Linq; -using System.Web.Helpers; using System.Web.Http; -using System.Web.Mvc; -using System.Web.Routing; -using Umbraco.Core; using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; -using Umbraco.Web.Install; -using Umbraco.Web.Mvc; -using Umbraco.Web.Security; -using Umbraco.Web.WebApi; namespace Umbraco.Web.Runtime { public class WebFinalComponent : IComponent { - private readonly IUmbracoContextAccessor _umbracoContextAccessor; - private readonly SurfaceControllerTypeCollection _surfaceControllerTypes; - private readonly UmbracoApiControllerTypeCollection _apiControllerTypes; - private readonly IGlobalSettings _globalSettings; - public WebFinalComponent(IUmbracoContextAccessor umbracoContextAccessor, SurfaceControllerTypeCollection surfaceControllerTypes, UmbracoApiControllerTypeCollection apiControllerTypes, IGlobalSettings globalSettings) + public WebFinalComponent() { - _umbracoContextAccessor = umbracoContextAccessor; - _surfaceControllerTypes = surfaceControllerTypes; - _apiControllerTypes = apiControllerTypes; - _globalSettings = globalSettings; } public void Initialize() { - // set routes - CreateRoutes(_umbracoContextAccessor, _globalSettings, _surfaceControllerTypes, _apiControllerTypes); - // ensure WebAPI is initialized, after everything GlobalConfiguration.Configuration.EnsureInitialized(); } @@ -41,92 +20,5 @@ namespace Umbraco.Web.Runtime public void Terminate() { } - // internal for tests - internal static void CreateRoutes( - IUmbracoContextAccessor umbracoContextAccessor, - IGlobalSettings globalSettings, - SurfaceControllerTypeCollection surfaceControllerTypes, - UmbracoApiControllerTypeCollection apiControllerTypes) - { - var umbracoPath = globalSettings.GetUmbracoMvcArea(); - - // create the front-end route - var defaultRoute = RouteTable.Routes.MapRoute( - "Umbraco_default", - umbracoPath + "/RenderMvc/{action}/{id}", - new { controller = "RenderMvc", action = "Index", id = UrlParameter.Optional } - ); - defaultRoute.RouteHandler = new RenderRouteHandler(umbracoContextAccessor, ControllerBuilder.Current.GetControllerFactory()); - - // register install routes - RouteTable.Routes.RegisterArea(); - - // register all back office routes - RouteTable.Routes.RegisterArea(new BackOfficeArea(globalSettings)); - - // plugin controllers must come first because the next route will catch many things - RoutePluginControllers(globalSettings, surfaceControllerTypes, apiControllerTypes); - } - - private static void RoutePluginControllers( - IGlobalSettings globalSettings, - SurfaceControllerTypeCollection surfaceControllerTypes, - UmbracoApiControllerTypeCollection apiControllerTypes) - { - var umbracoPath = globalSettings.GetUmbracoMvcArea(); - - // need to find the plugin controllers and route them - var pluginControllers = surfaceControllerTypes.Concat(apiControllerTypes).ToArray(); - - // local controllers do not contain the attribute - var localControllers = pluginControllers.Where(x => PluginController.GetMetadata(x).AreaName.IsNullOrWhiteSpace()); - foreach (var s in localControllers) - { - if (TypeHelper.IsTypeAssignableFrom(s)) - RouteLocalSurfaceController(s, umbracoPath); - else if (TypeHelper.IsTypeAssignableFrom(s)) - RouteLocalApiController(s, umbracoPath); - } - - // get the plugin controllers that are unique to each area (group by) - var pluginSurfaceControlleres = pluginControllers.Where(x => PluginController.GetMetadata(x).AreaName.IsNullOrWhiteSpace() == false); - var groupedAreas = pluginSurfaceControlleres.GroupBy(controller => PluginController.GetMetadata(controller).AreaName); - // loop through each area defined amongst the controllers - foreach (var g in groupedAreas) - { - // create & register an area for the controllers (this will throw an exception if all controllers are not in the same area) - var pluginControllerArea = new PluginControllerArea(globalSettings, g.Select(PluginController.GetMetadata)); - RouteTable.Routes.RegisterArea(pluginControllerArea); - } - } - - private static void RouteLocalApiController(Type controller, string umbracoPath) - { - var meta = PluginController.GetMetadata(controller); - var url = umbracoPath + (meta.IsBackOffice ? "/BackOffice" : "") + "/Api/" + meta.ControllerName + "/{action}/{id}"; - var route = RouteTable.Routes.MapHttpRoute( - $"umbraco-api-{meta.ControllerName}", - url, // url to match - new { controller = meta.ControllerName, id = UrlParameter.Optional }, - new[] { meta.ControllerNamespace }); - if (route.DataTokens == null) // web api routes don't set the data tokens object - route.DataTokens = new RouteValueDictionary(); - route.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, "api"); //ensure the umbraco token is set - } - - private static void RouteLocalSurfaceController(Type controller, string umbracoPath) - { - var meta = PluginController.GetMetadata(controller); - var url = umbracoPath + "/Surface/" + meta.ControllerName + "/{action}/{id}"; - var route = RouteTable.Routes.MapRoute( - $"umbraco-surface-{meta.ControllerName}", - url, // url to match - new { controller = meta.ControllerName, action = "Index", id = UrlParameter.Optional }, - new[] { meta.ControllerNamespace }); // look in this namespace to create the controller - route.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, "surface"); // ensure the umbraco token is set - route.DataTokens.Add("UseNamespaceFallback", false); // don't look anywhere else except this namespace! - // make it use our custom/special SurfaceMvcHandler - route.RouteHandler = new SurfaceRouteHandler(); - } } } diff --git a/src/Umbraco.Web/Runtime/WebInitialComponent.cs b/src/Umbraco.Web/Runtime/WebInitialComponent.cs index e1e0f4d80a..ac813d7196 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComponent.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComponent.cs @@ -8,12 +8,14 @@ using System.Web.Configuration; using System.Web.Http; using System.Web.Http.Dispatcher; using System.Web.Mvc; +using System.Web.Routing; using ClientDependency.Core.CompositeFiles.Providers; using ClientDependency.Core.Config; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.IO; +using Umbraco.Web.Install; using Umbraco.Web.JavaScript; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; @@ -24,10 +26,16 @@ namespace Umbraco.Web.Runtime { public sealed class WebInitialComponent : IComponent { + private readonly IUmbracoContextAccessor _umbracoContextAccessor; + private readonly SurfaceControllerTypeCollection _surfaceControllerTypes; + private readonly UmbracoApiControllerTypeCollection _apiControllerTypes; private readonly IGlobalSettings _globalSettings; - public WebInitialComponent(IGlobalSettings globalSettings) + public WebInitialComponent(IUmbracoContextAccessor umbracoContextAccessor, SurfaceControllerTypeCollection surfaceControllerTypes, UmbracoApiControllerTypeCollection apiControllerTypes, IGlobalSettings globalSettings) { + _umbracoContextAccessor = umbracoContextAccessor; + _surfaceControllerTypes = surfaceControllerTypes; + _apiControllerTypes = apiControllerTypes; _globalSettings = globalSettings; } @@ -51,6 +59,9 @@ namespace Umbraco.Web.Runtime // add global filters ConfigureGlobalFilters(); + + // set routes + CreateRoutes(_umbracoContextAccessor, _globalSettings, _surfaceControllerTypes, _apiControllerTypes); } public void Terminate() @@ -131,5 +142,94 @@ namespace Umbraco.Web.Runtime ClientDependencySettings.Instance.MvcRendererCollection.Add(renderer); } + + // internal for tests + internal static void CreateRoutes( + IUmbracoContextAccessor umbracoContextAccessor, + IGlobalSettings globalSettings, + SurfaceControllerTypeCollection surfaceControllerTypes, + UmbracoApiControllerTypeCollection apiControllerTypes) + { + var umbracoPath = globalSettings.GetUmbracoMvcArea(); + + // create the front-end route + var defaultRoute = RouteTable.Routes.MapRoute( + "Umbraco_default", + umbracoPath + "/RenderMvc/{action}/{id}", + new { controller = "RenderMvc", action = "Index", id = UrlParameter.Optional } + ); + defaultRoute.RouteHandler = new RenderRouteHandler(umbracoContextAccessor, ControllerBuilder.Current.GetControllerFactory()); + + // register install routes + RouteTable.Routes.RegisterArea(); + + // register all back office routes + RouteTable.Routes.RegisterArea(new BackOfficeArea(globalSettings)); + + // plugin controllers must come first because the next route will catch many things + RoutePluginControllers(globalSettings, surfaceControllerTypes, apiControllerTypes); + } + + private static void RoutePluginControllers( + IGlobalSettings globalSettings, + SurfaceControllerTypeCollection surfaceControllerTypes, + UmbracoApiControllerTypeCollection apiControllerTypes) + { + var umbracoPath = globalSettings.GetUmbracoMvcArea(); + + // need to find the plugin controllers and route them + var pluginControllers = surfaceControllerTypes.Concat(apiControllerTypes).ToArray(); + + // local controllers do not contain the attribute + var localControllers = pluginControllers.Where(x => PluginController.GetMetadata(x).AreaName.IsNullOrWhiteSpace()); + foreach (var s in localControllers) + { + if (TypeHelper.IsTypeAssignableFrom(s)) + RouteLocalSurfaceController(s, umbracoPath); + else if (TypeHelper.IsTypeAssignableFrom(s)) + RouteLocalApiController(s, umbracoPath); + } + + // get the plugin controllers that are unique to each area (group by) + var pluginSurfaceControlleres = pluginControllers.Where(x => PluginController.GetMetadata(x).AreaName.IsNullOrWhiteSpace() == false); + var groupedAreas = pluginSurfaceControlleres.GroupBy(controller => PluginController.GetMetadata(controller).AreaName); + // loop through each area defined amongst the controllers + foreach (var g in groupedAreas) + { + // create & register an area for the controllers (this will throw an exception if all controllers are not in the same area) + var pluginControllerArea = new PluginControllerArea(globalSettings, g.Select(PluginController.GetMetadata)); + RouteTable.Routes.RegisterArea(pluginControllerArea); + } + } + + private static void RouteLocalApiController(Type controller, string umbracoPath) + { + var meta = PluginController.GetMetadata(controller); + var url = umbracoPath + (meta.IsBackOffice ? "/BackOffice" : "") + "/Api/" + meta.ControllerName + "/{action}/{id}"; + var route = RouteTable.Routes.MapHttpRoute( + $"umbraco-api-{meta.ControllerName}", + url, // url to match + new { controller = meta.ControllerName, id = UrlParameter.Optional }, + new[] { meta.ControllerNamespace }); + if (route.DataTokens == null) // web api routes don't set the data tokens object + route.DataTokens = new RouteValueDictionary(); + route.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, "api"); //ensure the umbraco token is set + } + + private static void RouteLocalSurfaceController(Type controller, string umbracoPath) + { + var meta = PluginController.GetMetadata(controller); + var url = umbracoPath + "/Surface/" + meta.ControllerName + "/{action}/{id}"; + var route = RouteTable.Routes.MapRoute( + $"umbraco-surface-{meta.ControllerName}", + url, // url to match + new { controller = meta.ControllerName, action = "Index", id = UrlParameter.Optional }, + new[] { meta.ControllerNamespace }); // look in this namespace to create the controller + route.DataTokens.Add(Core.Constants.Web.UmbracoDataToken, "surface"); // ensure the umbraco token is set + route.DataTokens.Add("UseNamespaceFallback", false); // don't look anywhere else except this namespace! + // make it use our custom/special SurfaceMvcHandler + route.RouteHandler = new SurfaceRouteHandler(); + } + } } From ac4128d89e34750ae9e26317bb7286b3a8adf6df Mon Sep 17 00:00:00 2001 From: elitsa Date: Fri, 23 Aug 2019 10:42:00 +0200 Subject: [PATCH 064/102] Add special checks and preview for svg files media files for v8 --- .../media/umbmedianodeinfo.directive.js | 22 ++++++++++++++++++- .../components/media/umb-media-node-info.html | 12 +++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js index 577ffe0176..4993b013c7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js @@ -1,7 +1,7 @@ (function () { 'use strict'; - function MediaNodeInfoDirective($timeout, $location, eventsService, userService, dateHelper, editorService) { + function MediaNodeInfoDirective($timeout, $location, eventsService, userService, dateHelper, editorService, mediaHelper) { function link(scope, element, attrs, ctrl) { @@ -28,6 +28,9 @@ // make sure dates are formatted to the user's locale formatDatesToLocal(); + + // set media file extension initially + setMediaExtension(); } function formatDatesToLocal() { @@ -49,6 +52,10 @@ } } + function setMediaExtension() { + scope.node.extension = mediaHelper.getFileExtension(scope.nodeUrl); + } + scope.openMediaType = function (mediaType) { var editor = { id: mediaType.id, @@ -62,6 +69,16 @@ editorService.mediaTypeEditor(editor); }; + scope.openSVG = function () { + var popup = window.open('', '_blank'); + var html = '' + + ''; + + popup.document.open(); + popup.document.write(html); + popup.document.close(); + } + // watch for content updates - reload content when node is saved, published etc. scope.$watch('node.updateDate', function(newValue, oldValue){ if(!newValue) { return; } @@ -72,6 +89,9 @@ // Update the create and update dates formatDatesToLocal(); + + //Update the media file format + setMediaExtension(); }); //ensure to unregister from all events! diff --git a/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html b/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html index f411437b1d..ee175c36f2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html @@ -12,9 +12,15 @@ From 8625c8da439332d57d2d57c49263b0949104198d Mon Sep 17 00:00:00 2001 From: elitsa Date: Fri, 23 Aug 2019 10:42:00 +0200 Subject: [PATCH 065/102] Add special checks and preview for svg files media files for v8 (cherry picked from commit ac4128d89e34750ae9e26317bb7286b3a8adf6df) --- .../media/umbmedianodeinfo.directive.js | 22 ++++++++++++++++++- .../components/media/umb-media-node-info.html | 12 +++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js index 577ffe0176..4993b013c7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js @@ -1,7 +1,7 @@ (function () { 'use strict'; - function MediaNodeInfoDirective($timeout, $location, eventsService, userService, dateHelper, editorService) { + function MediaNodeInfoDirective($timeout, $location, eventsService, userService, dateHelper, editorService, mediaHelper) { function link(scope, element, attrs, ctrl) { @@ -28,6 +28,9 @@ // make sure dates are formatted to the user's locale formatDatesToLocal(); + + // set media file extension initially + setMediaExtension(); } function formatDatesToLocal() { @@ -49,6 +52,10 @@ } } + function setMediaExtension() { + scope.node.extension = mediaHelper.getFileExtension(scope.nodeUrl); + } + scope.openMediaType = function (mediaType) { var editor = { id: mediaType.id, @@ -62,6 +69,16 @@ editorService.mediaTypeEditor(editor); }; + scope.openSVG = function () { + var popup = window.open('', '_blank'); + var html = '' + + ''; + + popup.document.open(); + popup.document.write(html); + popup.document.close(); + } + // watch for content updates - reload content when node is saved, published etc. scope.$watch('node.updateDate', function(newValue, oldValue){ if(!newValue) { return; } @@ -72,6 +89,9 @@ // Update the create and update dates formatDatesToLocal(); + + //Update the media file format + setMediaExtension(); }); //ensure to unregister from all events! diff --git a/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html b/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html index f411437b1d..ee175c36f2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html @@ -12,9 +12,15 @@ From c3e99205de17671f872f16d74f929983e1ba042d Mon Sep 17 00:00:00 2001 From: Claus Date: Mon, 26 Aug 2019 13:29:54 +0200 Subject: [PATCH 066/102] fixed typo. --- src/Umbraco.Web.UI.Client/src/main.controller.js | 5 ++--- src/Umbraco.Web.UI/Umbraco/js/main.controller.js | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/main.controller.js b/src/Umbraco.Web.UI.Client/src/main.controller.js index f4bac95767..93870f8a56 100644 --- a/src/Umbraco.Web.UI.Client/src/main.controller.js +++ b/src/Umbraco.Web.UI.Client/src/main.controller.js @@ -22,13 +22,12 @@ function MainController($scope, $location, appState, treeService, notificationsS $scope.login = {}; $scope.tabbingActive = false; - // Load TinyMCE Assets ahead of time in the background for the user - // To help woth first load of the RTE + // Load TinyMCE assets ahead of time in the background for the user + // To help with first load of the RTE tinyMceAssets.forEach(function (tinyJsAsset) { assetsService.loadJs(tinyJsAsset, $scope); }); - // There are a number of ways to detect when a focus state should be shown when using the tab key and this seems to be the simplest solution. // For more information about this approach, see https://hackernoon.com/removing-that-ugly-focus-ring-and-keeping-it-too-6c8727fefcd2 function handleFirstTab(evt) { diff --git a/src/Umbraco.Web.UI/Umbraco/js/main.controller.js b/src/Umbraco.Web.UI/Umbraco/js/main.controller.js index f4bac95767..93870f8a56 100644 --- a/src/Umbraco.Web.UI/Umbraco/js/main.controller.js +++ b/src/Umbraco.Web.UI/Umbraco/js/main.controller.js @@ -22,13 +22,12 @@ function MainController($scope, $location, appState, treeService, notificationsS $scope.login = {}; $scope.tabbingActive = false; - // Load TinyMCE Assets ahead of time in the background for the user - // To help woth first load of the RTE + // Load TinyMCE assets ahead of time in the background for the user + // To help with first load of the RTE tinyMceAssets.forEach(function (tinyJsAsset) { assetsService.loadJs(tinyJsAsset, $scope); }); - // There are a number of ways to detect when a focus state should be shown when using the tab key and this seems to be the simplest solution. // For more information about this approach, see https://hackernoon.com/removing-that-ugly-focus-ring-and-keeping-it-too-6c8727fefcd2 function handleFirstTab(evt) { From 3dc0bbeff32b57d743fb7ab36b87c6cfaabe7c60 Mon Sep 17 00:00:00 2001 From: Steve Megson Date: Tue, 27 Aug 2019 08:30:22 +0100 Subject: [PATCH 067/102] Multi Url Picker fix --- .../propertyeditors/multiurlpicker/multiurlpicker.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.controller.js index a5fc5c50d2..dcfeb4b1fa 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.controller.js @@ -72,7 +72,7 @@ function multiUrlPickerController($scope, angularHelper, localizationService, en view: "linkpicker", currentTarget: target, dataTypeId: ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null, - ignoreUserStartNodes : $scope.model.config.ignoreUserStartNodes, + ignoreUserStartNodes: ($scope.model.config && $scope.model.config.ignoreUserStartNodes) ? $scope.model.config.ignoreUserStartNodes : "1", show: true, submit: function (model) { if (model.target.url || model.target.anchor) { From 4ef55aa7d09be28f10758ffb289974b59387ec98 Mon Sep 17 00:00:00 2001 From: Steve Megson Date: Tue, 27 Aug 2019 08:30:22 +0100 Subject: [PATCH 068/102] Multi Url Picker fix (cherry picked from commit 3dc0bbeff32b57d743fb7ab36b87c6cfaabe7c60) --- .../propertyeditors/multiurlpicker/multiurlpicker.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.controller.js index a5fc5c50d2..dcfeb4b1fa 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.controller.js @@ -72,7 +72,7 @@ function multiUrlPickerController($scope, angularHelper, localizationService, en view: "linkpicker", currentTarget: target, dataTypeId: ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null, - ignoreUserStartNodes : $scope.model.config.ignoreUserStartNodes, + ignoreUserStartNodes: ($scope.model.config && $scope.model.config.ignoreUserStartNodes) ? $scope.model.config.ignoreUserStartNodes : "1", show: true, submit: function (model) { if (model.target.url || model.target.anchor) { From 3c7580ff7bfc87755295ece629757ae6746956ef Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 29 Aug 2019 11:55:43 +0200 Subject: [PATCH 069/102] Default for ignoreUserStartNodes should be false --- .../propertyeditors/multiurlpicker/multiurlpicker.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.controller.js index dcfeb4b1fa..0b8f783517 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.controller.js @@ -72,7 +72,7 @@ function multiUrlPickerController($scope, angularHelper, localizationService, en view: "linkpicker", currentTarget: target, dataTypeId: ($scope.model && $scope.model.dataTypeId) ? $scope.model.dataTypeId : null, - ignoreUserStartNodes: ($scope.model.config && $scope.model.config.ignoreUserStartNodes) ? $scope.model.config.ignoreUserStartNodes : "1", + ignoreUserStartNodes: ($scope.model.config && $scope.model.config.ignoreUserStartNodes) ? $scope.model.config.ignoreUserStartNodes : "0", show: true, submit: function (model) { if (model.target.url || model.target.anchor) { From 2cdeb38521337f1321a9bd6a2153472afe90db53 Mon Sep 17 00:00:00 2001 From: Cody Boucher Date: Mon, 26 Aug 2019 11:02:31 -0400 Subject: [PATCH 070/102] use SystemDirectories.Media instead of hardcoded string media --- src/Umbraco.Core/Persistence/Factories/MediaFactory.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs b/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs index 080a358657..f3300ba424 100644 --- a/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using System.Text.RegularExpressions; +using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; @@ -130,7 +131,7 @@ namespace Umbraco.Core.Persistence.Factories return nodeDto; } - private static readonly Regex MediaPathPattern = new Regex(@"(/media/.+?)(?:['""]|$)", RegexOptions.Compiled); + private static readonly Regex MediaPathPattern = new Regex($@"({SystemDirectories.Media.TrimStart("~")}/.+?)(?:['""]|$)", RegexOptions.Compiled); /// /// Try getting a media path out of the string being stored for media From f5a445101d88c632965c17d1e8b0b68e181696ed Mon Sep 17 00:00:00 2001 From: Cody Boucher Date: Mon, 26 Aug 2019 11:02:31 -0400 Subject: [PATCH 071/102] use SystemDirectories.Media instead of hardcoded string media (cherry picked from commit 2cdeb38521337f1321a9bd6a2153472afe90db53) --- src/Umbraco.Core/Persistence/Factories/MediaFactory.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs b/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs index 080a358657..f3300ba424 100644 --- a/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MediaFactory.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using System.Text.RegularExpressions; +using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Models.Rdbms; @@ -130,7 +131,7 @@ namespace Umbraco.Core.Persistence.Factories return nodeDto; } - private static readonly Regex MediaPathPattern = new Regex(@"(/media/.+?)(?:['""]|$)", RegexOptions.Compiled); + private static readonly Regex MediaPathPattern = new Regex($@"({SystemDirectories.Media.TrimStart("~")}/.+?)(?:['""]|$)", RegexOptions.Compiled); /// /// Try getting a media path out of the string being stored for media From 851a2a3de8dc94d99b5a1b3d1d232b70a722aa96 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 21 Aug 2019 10:07:08 +0000 Subject: [PATCH 072/102] Simplify svg check and make it a proper a href again. --- .../views/components/media/umb-media-node-info.html | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html b/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html index 3f71ae2d18..36fd86175f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html @@ -12,15 +12,9 @@ From 5d9e1087f4081595efa4db5e86a5fe773d9da5c4 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 29 Aug 2019 13:03:48 +0200 Subject: [PATCH 073/102] Cherry pick 851a2a3de8dc94d99b5a1b3d1d232b70a722aa96 --- .../src/views/components/media/umb-media-node-info.html | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html b/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html index ee175c36f2..4f7141559c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/media/umb-media-node-info.html @@ -12,15 +12,10 @@ From 93bb75511bd61351df100ccbdcc10e930a048ba6 Mon Sep 17 00:00:00 2001 From: Matt Brailsford Date: Thu, 18 Jul 2019 13:09:12 +0100 Subject: [PATCH 074/102] Fixed #5907 by reloading content on bulk publish / unpublish Fixes #5907 --- .../listview/listview.controller.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js index df7a574c49..9b4c01f4f9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js @@ -405,7 +405,7 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie }; $scope.publish = function () { - applySelected( + var attempt = applySelected( function (selected, index) { return contentResource.publishById(getIdCallback(selected[index])); }, function (count, total) { var key = (total === 1 ? "bulk_publishedItemOfItem" : "bulk_publishedItemOfItems"); @@ -415,10 +415,15 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie var key = (total === 1 ? "bulk_publishedItem" : "bulk_publishedItems"); return localizationService.localize(key, [total]); }); + if (attempt) { + attempt.then(function () { + $scope.getContent(); + }); + } }; $scope.unpublish = function() { - applySelected( + var attempt = applySelected( function(selected, index) { return contentResource.unPublish(getIdCallback(selected[index])); }, function(count, total) { var key = (total === 1 ? "bulk_unpublishedItemOfItem" : "bulk_unpublishedItemOfItems"); @@ -428,6 +433,11 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie var key = (total === 1 ? "bulk_unpublishedItem" : "bulk_unpublishedItems"); return localizationService.localize(key, [total]); }); + if (attempt) { + attempt.then(function () { + $scope.getContent(); + }); + } }; $scope.move = function() { From e92631c623aac925ce3b4571ee7f964b6f6f5ace Mon Sep 17 00:00:00 2001 From: Matt Brailsford Date: Thu, 18 Jul 2019 13:09:12 +0100 Subject: [PATCH 075/102] Fixed #5907 by reloading content on bulk publish / unpublish Fixes #5907 (cherry picked from commit 93bb75511bd61351df100ccbdcc10e930a048ba6) --- .../listview/listview.controller.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js index df7a574c49..9b4c01f4f9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js @@ -405,7 +405,7 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie }; $scope.publish = function () { - applySelected( + var attempt = applySelected( function (selected, index) { return contentResource.publishById(getIdCallback(selected[index])); }, function (count, total) { var key = (total === 1 ? "bulk_publishedItemOfItem" : "bulk_publishedItemOfItems"); @@ -415,10 +415,15 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie var key = (total === 1 ? "bulk_publishedItem" : "bulk_publishedItems"); return localizationService.localize(key, [total]); }); + if (attempt) { + attempt.then(function () { + $scope.getContent(); + }); + } }; $scope.unpublish = function() { - applySelected( + var attempt = applySelected( function(selected, index) { return contentResource.unPublish(getIdCallback(selected[index])); }, function(count, total) { var key = (total === 1 ? "bulk_unpublishedItemOfItem" : "bulk_unpublishedItemOfItems"); @@ -428,6 +433,11 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie var key = (total === 1 ? "bulk_unpublishedItem" : "bulk_unpublishedItems"); return localizationService.localize(key, [total]); }); + if (attempt) { + attempt.then(function () { + $scope.getContent(); + }); + } }; $scope.move = function() { From e9eecb2031bc50f58d1d971ae58f2b12aad38ff8 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Sat, 6 Jul 2019 08:32:04 +0200 Subject: [PATCH 076/102] Ensure correct icon for file types in search results --- src/Umbraco.Web/Search/UmbracoTreeSearcher.cs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs index 9cfa29985b..543499d054 100644 --- a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs +++ b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs @@ -301,19 +301,7 @@ namespace Umbraco.Web.Search /// /// private IEnumerable MediaFromSearchResults(IEnumerable results) - { - var mapped = Mapper.Map>(results).ToArray(); - //add additional data - foreach (var m in mapped) - { - //if no icon could be mapped, it will be set to document, so change it to picture - if (m.Icon == "icon-document") - { - m.Icon = "icon-picture"; - } - } - return mapped; - } + => Mapper.Map>(results).ToArray(); /// /// Returns a collection of entities for content based on search results From 531dee1e75c2f19bc77e309a5a4de1da063a3bc8 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Sat, 6 Jul 2019 08:26:08 +0200 Subject: [PATCH 077/102] Ensure correct icon for file types in search results --- src/Umbraco.Web/Search/UmbracoTreeSearcher.cs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs index 729b2c0a9d..c3c3dc75ce 100644 --- a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs +++ b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs @@ -384,19 +384,7 @@ namespace Umbraco.Web.Search /// /// private IEnumerable MediaFromSearchResults(IEnumerable results) - { - //add additional data - foreach (var result in results) - { - var m = _mapper.Map(result); - //if no icon could be mapped, it will be set to document, so change it to picture - if (m.Icon == Constants.Icons.DefaultIcon) - { - m.Icon = Constants.Icons.MediaImage; - } - yield return m; - } - } + => _mapper.Map>(results); /// /// Returns a collection of entities for content based on search results From 204a9c9d5386a9230e321504bf2e519fd26eee55 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 3 Jul 2019 12:33:03 +0200 Subject: [PATCH 078/102] Make sure Nested Content blueprints are listed in defined sort order --- .../common/overlays/itempicker/itempicker.controller.js | 5 +++++ .../src/views/common/overlays/itempicker/itempicker.html | 2 +- .../nestedcontent/nestedcontent.controller.js | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.controller.js index a848c0ae90..aa6fa8d42c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.controller.js @@ -4,6 +4,11 @@ function ItemPickerOverlay($scope, localizationService) { $scope.model.title = localizationService.localize("defaultdialogs_selectItem"); } + + if (!$scope.model.orderBy) { + $scope.model.orderBy = "name"; + } + $scope.model.hideSubmitButton = true; $scope.selectItem = function(item) { diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.html index aac4830d52..328344ea84 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.html @@ -12,7 +12,7 @@
/// The text. - /// The text with text line breaks replaced with HTML line breaks (
)
+ /// The text with text line breaks replaced with HTML line breaks (<br />). + [Obsolete("This method doesn't HTML encode the text. Use ReplaceLineBreaks instead.")] public HtmlString ReplaceLineBreaksForHtml(string text) { - return new HtmlString(text.Replace("\r\n", @"
").Replace("\n", @"
").Replace("\r", @"
")); + return new HtmlString(text.Replace("\r\n", @"
").Replace("\n", @"
").Replace("\r", @"
")); + } + + /// + /// HTML encodes the text and replaces text line breaks with HTML line breaks. + /// + /// The text. + /// The HTML encoded text with text line breaks replaced with HTML line breaks (<br />). + public IHtmlString ReplaceLineBreaks(string text) + { + var value = HttpUtility.HtmlEncode(text)? + .Replace("\r\n", "
") + .Replace("\r", "
") + .Replace("\n", "
"); + + return new HtmlString(value); } public HtmlString StripHtmlTags(string html, params string[] tags) From 24efa54481f98078740e20a5e84f70f587df2ab6 Mon Sep 17 00:00:00 2001 From: Kasper Christensen Date: Mon, 2 Sep 2019 10:00:44 +0200 Subject: [PATCH 100/102] =?UTF-8?q?Loginpage:=20Added=20an=20id=20to=20inp?= =?UTF-8?q?ut=20fields=20and=20a=20for=20attr=20on=20the=20la=E2=80=A6=20(?= =?UTF-8?q?#6247)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/application/umb-login.html | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-login.html b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-login.html index bc27196466..676b2efc38 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-login.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-login.html @@ -18,11 +18,11 @@

-
- - + + Required The confirmed password doesn't match the new password! @@ -152,13 +152,13 @@
- - + +
- - + +
Show password @@ -189,8 +189,8 @@
- - + +
@@ -220,13 +220,13 @@
- - + +
- - + +
From 3d3a836c5281de142d36febe49ced5b845b6b251 Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Fri, 30 Aug 2019 23:19:54 +0100 Subject: [PATCH 101/102] fix to the documentation link in create packages opening in same window --- src/Umbraco.Web.UI.Client/src/views/packages/edit.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2df95cec0d..7a95fd9214 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/edit.html @@ -298,7 +298,7 @@ description="Here you can add custom installer / uninstaller events to perform certain tasks during installation and uninstallation. All actions are formed as a xml node, containing data for the action to be performed.">
- Documentation + Documentation
From 157c0a2479b4566901b9bfa2d80f92dab8354fa1 Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Sat, 31 Aug 2019 21:22:12 +0100 Subject: [PATCH 102/102] Added Review process file --- .github/REVIEW_PROCESS.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/REVIEW_PROCESS.md diff --git a/.github/REVIEW_PROCESS.md b/.github/REVIEW_PROCESS.md new file mode 100644 index 0000000000..917d25b090 --- /dev/null +++ b/.github/REVIEW_PROCESS.md @@ -0,0 +1,25 @@ +# Review process + +You're an awesome person and have sent us your contribution in the form of a pull request! It's now time to relax for a bit and wait for our response. + +In order to set some expectations, here's what happens next. + +## Review process + +You will get an initial reply within 48 hours (workdays) to acknowledge that we’ve seen your PR and we’ll pick it up as soon as we can. + +You will get feedback within at most 14 days after opening the PR. You’ll most likely get feedback sooner though. Then there are a few possible outcomes: + +- Your proposed change is awesome! We merge it in and it will be included in the next minor release of Umbraco +- If the change is a high priority bug fix, we will cherry-pick it into the next patch release as well so that we can release it as soon as possible +- Your proposed change is awesome but needs a bit more work, we’ll give you feedback on the changes we’d like to see +- Your proposed change is awesome but.. not something we’re looking to include at this point. We’ll close your PR and the related issue (we’ll be nice about it!) + +## Are you still available? + +We understand you have other things to do and can't just drop everything to help us out. +So if we’re asking for your help to improve the PR we’ll wait for two weeks to give you a fair chance to make changes. We’ll ask for an update if we don’t hear back from you after that time. + +If we don’t hear back from you for 4 weeks, we’ll close the PR so that it doesn’t just hang around forever. You’re very welcome to re-open it once you have some more time to spend on it. + +There will be times that we really like your proposed changes and we’ll finish the final improvements we’d like to see ourselves. You still get the credits and your commits will live on in the git repository. \ No newline at end of file