From 06ca4294b19abdecdb5de433a41539dc5dffe0ef Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 30 Oct 2019 08:52:23 +0100 Subject: [PATCH 01/55] Styling updates to image cropper and upload property editors --- .../src/less/components/umb-property-file-upload.less | 1 + src/Umbraco.Web.UI.Client/src/less/mixins.less | 2 +- src/Umbraco.Web.UI.Client/src/less/property-editors.less | 4 ++++ src/Umbraco.Web.UI.Client/src/less/variables.less | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less index 08b1a1b5e1..9550acfb1b 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less @@ -1,6 +1,7 @@ .umb-property-file-upload { .umb-upload-button-big { + max-width: (@propertyEditorLimitedWidth - 40); display: block; padding: 20px; opacity: 1; diff --git a/src/Umbraco.Web.UI.Client/src/less/mixins.less b/src/Umbraco.Web.UI.Client/src/less/mixins.less index e49755338b..52638c82dc 100644 --- a/src/Umbraco.Web.UI.Client/src/less/mixins.less +++ b/src/Umbraco.Web.UI.Client/src/less/mixins.less @@ -419,7 +419,7 @@ // -------------------------------------------------- // Limit width of specific property editors .umb-property-editor--limit-width { - max-width: 800px; + max-width: @propertyEditorLimitedWidth; } // Horizontal dividers diff --git a/src/Umbraco.Web.UI.Client/src/less/property-editors.less b/src/Umbraco.Web.UI.Client/src/less/property-editors.less index dc2d402671..b7cf22be62 100644 --- a/src/Umbraco.Web.UI.Client/src/less/property-editors.less +++ b/src/Umbraco.Web.UI.Client/src/less/property-editors.less @@ -721,6 +721,10 @@ // // File upload // -------------------------------------------------- +.umb-fileupload { + display: flex; +} + .umb-fileupload .preview { border-radius: 5px; border: 1px solid @gray-6; diff --git a/src/Umbraco.Web.UI.Client/src/less/variables.less b/src/Umbraco.Web.UI.Client/src/less/variables.less index 166640829b..a3f2183f83 100644 --- a/src/Umbraco.Web.UI.Client/src/less/variables.less +++ b/src/Umbraco.Web.UI.Client/src/less/variables.less @@ -322,6 +322,7 @@ @paddingSmall: 2px 10px; // 26px @paddingMini: 0 6px; // 22px +@propertyEditorLimitedWidth: 800px; // Disabled this to keep consistency throughout the backoffice UI. Untill a better solution is thought up, this will do. @baseBorderRadius: 3px; // 2px; From da3a971906f9c3b455ca912edf106893a31c7f79 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Wed, 30 Oct 2019 18:57:33 +0100 Subject: [PATCH 02/55] Do not show breadcrumb for immediate children in the recycle bin --- .../src/common/directives/components/content/edit.controller.js | 2 +- .../src/views/media/media.edit.controller.js | 2 +- 2 files changed, 2 insertions(+), 2 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 cab71842b1..d3f65d8f63 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 @@ -42,7 +42,7 @@ $scope.page.isNew = Object.toBoolean(newVal); //We fetch all ancestors of the node to generate the footer breadcrumb navigation - if (content.parentId && content.parentId !== -1) { + if (content.parentId && content.parentId !== -1 && content.parentId !== -20) { loadBreadcrumb(); if (!watchingCulture) { $scope.$watch('culture', diff --git a/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js index a5884c2355..b8c38e923b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js @@ -245,7 +245,7 @@ function mediaEditController($scope, $routeParams, $q, appState, mediaResource, syncTreeNode($scope.content, data.path, true); } - if ($scope.content.parentId && $scope.content.parentId != -1) { + if ($scope.content.parentId && $scope.content.parentId !== -1 && $scope.content.parentId !== -21) { //We fetch all ancestors of the node to generate the footer breadcrump navigation entityResource.getAncestors(nodeId, "media") .then(function (anc) { From 486dd0b8eaacbface476cac7aa7738aca0b95f61 Mon Sep 17 00:00:00 2001 From: Steve Megson Date: Thu, 31 Oct 2019 11:39:52 +0000 Subject: [PATCH 03/55] PublishedSnapshotService.OnMemberRefreshedEntity stores data as published rather than edited --- .../PublishedCache/NuCache/PublishedSnapshotService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs index e76b526492..742841aeb5 100755 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedSnapshotService.cs @@ -1218,7 +1218,7 @@ namespace Umbraco.Web.PublishedCache.NuCache var member = args.Entity; // refresh the edited data - OnRepositoryRefreshed(db, member, true); + OnRepositoryRefreshed(db, member, false); } private void OnRepositoryRefreshed(IUmbracoDatabase db, IContentBase content, bool published) From ce969aad3b62ec12a257a4d9cd3566287e88a825 Mon Sep 17 00:00:00 2001 From: Jeffrey Schoemaker Date: Thu, 7 Nov 2019 13:34:26 +0100 Subject: [PATCH 04/55] Make it a bit less complex --- .github/BUILD.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/BUILD.md b/.github/BUILD.md index c6e870f396..ad33872423 100644 --- a/.github/BUILD.md +++ b/.github/BUILD.md @@ -43,6 +43,8 @@ If you only see a build.bat-file, you're probably on the wrong branch. If you sw You might run into [Powershell quirks](#powershell-quirks). +If it runs without errors; Hooray! Now you can continue with [the next step](CONTRIBUTING.md#how-do-i-begin) and open the solution and build it. + ### Build Infrastructure The Umbraco Build infrastructure relies on a PowerShell object. The object can be retrieved with: From ccc6f3877820daf4e57494d76bfd4959dea35f3c Mon Sep 17 00:00:00 2001 From: Nathan Woulfe Date: Mon, 13 Jan 2020 09:15:02 +1000 Subject: [PATCH 05/55] guard code for non-infinite editing to prevent route change --- .../src/views/media/media.edit.controller.js | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js index a5884c2355..2ed43f7495 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js @@ -73,14 +73,14 @@ function mediaEditController($scope, $routeParams, $q, appState, mediaResource, var content = $scope.content; - // we need to check wether an app is present in the current data, if not we will present the default app. + // we need to check whether an app is present in the current data, if not we will present the default app. var isAppPresent = false; // on first init, we dont have any apps. but if we are re-initializing, we do, but ... if ($scope.app) { // lets check if it still exists as part of our apps array. (if not we have made a change to our docType, even just a re-save of the docType it will turn into new Apps.) - _.forEach(content.apps, function(app) { + content.apps.forEach(app => { if (app === $scope.app) { isAppPresent = true; } @@ -88,7 +88,7 @@ function mediaEditController($scope, $routeParams, $q, appState, mediaResource, // if we did reload our DocType, but still have the same app we will try to find it by the alias. if (isAppPresent === false) { - _.forEach(content.apps, function(app) { + content.apps.forEach(app => { if (app.alias === $scope.app.alias) { isAppPresent = true; app.active = true; @@ -182,24 +182,26 @@ function mediaEditController($scope, $routeParams, $q, appState, mediaResource, formHelper.resetForm({ scope: $scope }); - contentEditingHelper.handleSuccessfulSave({ - scope: $scope, - savedContent: data, - rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, data) - }); - - editorState.set($scope.content); - - syncTreeNode($scope.content, data.path); - - init(); - - $scope.page.saveButtonState = "success"; - // close the editor if it's infinite mode + // submit function manages rebinding changes if(infiniteMode && $scope.model.submit) { $scope.model.mediaNode = $scope.content; $scope.model.submit($scope.model); + } else { + // if not infinite mode, rebind changed props etc + contentEditingHelper.handleSuccessfulSave({ + scope: $scope, + savedContent: data, + rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, data) + }); + + editorState.set($scope.content); + + syncTreeNode($scope.content, data.path); + + $scope.page.saveButtonState = "success"; + + init(); } }, function(err) { From 21aa8fd95921f44d07064738a3c838775895d366 Mon Sep 17 00:00:00 2001 From: Nathan Woulfe Date: Mon, 13 Jan 2020 09:15:27 +1000 Subject: [PATCH 06/55] remove lodash in favor of native es6 methods, adds type attribute to buttons --- .../mediapicker/mediapicker.controller.js | 121 +++++++++--------- .../mediapicker/mediapicker.html | 6 +- 2 files changed, 60 insertions(+), 67 deletions(-) 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 c9d4caf312..ec6ab05cbd 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 @@ -48,49 +48,45 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl // This is done by remapping the int/guid ids into a new array of items, where we create "Deleted item" placeholders // when there is no match for a selected id. This will ensure that the values being set on save, are the same as before. - medias = _.map(ids, - function (id) { - var found = _.find(medias, - function (m) { - // We could use coercion (two ='s) here .. but not sure if this works equally well in all browsers and - // it's prone to someone "fixing" it at some point without knowing the effects. Rather use toString() - // compares and be completely sure it works. - return m.udi.toString() === id.toString() || m.id.toString() === id.toString(); - }); - if (found) { - return found; - } else { - return { - name: vm.labels.deletedItem, - id: $scope.model.config.idType !== "udi" ? id : null, - udi: $scope.model.config.idType === "udi" ? id : null, - icon: "icon-picture", - thumbnail: null, - trashed: true - }; - } - }); + medias = ids.map(id => { + var found = medias.find(m => + // We could use coercion (two ='s) here .. but not sure if this works equally well in all browsers and + // it's prone to someone "fixing" it at some point without knowing the effects. Rather use toString() + // compares and be completely sure it works. + m.udi.toString() === id.toString() || m.id.toString() === id.toString()); + + if (found) { + return found; + } else { + return { + name: vm.labels.deletedItem, + id: $scope.model.config.idType !== "udi" ? id : null, + udi: $scope.model.config.idType === "udi" ? id : null, + icon: "icon-picture", + thumbnail: null, + trashed: true + }; + } + }); - _.each(medias, - function (media, i) { + medias.forEach(media => { + if (!media.extension && media.id && media.metaData) { + media.extension = mediaHelper.getFileExtension(media.metaData.MediaPath); + } - if (!media.extension && media.id && media.metaData) { - media.extension = mediaHelper.getFileExtension(media.metaData.MediaPath); - } + // if there is no thumbnail, try getting one if the media is not a placeholder item + if (!media.thumbnail && media.id && media.metaData) { + media.thumbnail = mediaHelper.resolveFileFromEntity(media, true); + } - // if there is no thumbnail, try getting one if the media is not a placeholder item - if (!media.thumbnail && media.id && media.metaData) { - media.thumbnail = mediaHelper.resolveFileFromEntity(media, true); - } + $scope.mediaItems.push(media); - $scope.mediaItems.push(media); - - if ($scope.model.config.idType === "udi") { - $scope.ids.push(media.udi); - } else { - $scope.ids.push(media.id); - } - }); + if ($scope.model.config.idType === "udi") { + $scope.ids.push(media.udi); + } else { + $scope.ids.push(media.id); + } + }); sync(); }); @@ -100,7 +96,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl function sync() { $scope.model.value = $scope.ids.join(); removeAllEntriesAction.isDisabled = $scope.ids.length === 0; - }; + } function setDirty() { angularHelper.getCurrentForm($scope).$setDirty(); @@ -111,18 +107,17 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl // reload. We only reload the images that is already picked but has been updated. // We have to get the entities from the server because the media // can be edited without being selected - _.each($scope.images, - function (image, i) { - if (updatedMediaNodes.indexOf(image.udi) !== -1) { - image.loading = true; - entityResource.getById(image.udi, "media") - .then(function (mediaEntity) { - angular.extend(image, mediaEntity); - image.thumbnail = mediaHelper.resolveFileFromEntity(image, true); - image.loading = false; - }); - } - }); + $scope.mediaItems.forEach(media => { + if (updatedMediaNodes.indexOf(media.udi) !== -1) { + media.loading = true; + entityResource.getById(media.udi, "Media") + .then(function (mediaEntity) { + angular.extend(media, mediaEntity); + media.thumbnail = mediaHelper.resolveFileFromEntity(media, true); + media.loading = false; + }); + } + }); } function init() { @@ -177,20 +172,20 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl // the media picker is using media entities so we get the // entity so we easily can format it for use in the media grid if (model && model.mediaNode) { - entityResource.getById(model.mediaNode.id, "media") + entityResource.getById(model.mediaNode.id, "Media") .then(function (mediaEntity) { // if an image is selecting more than once // we need to update all the media items - angular.forEach($scope.images, function (image) { - if (image.id === model.mediaNode.id) { - angular.extend(image, mediaEntity); - image.thumbnail = mediaHelper.resolveFileFromEntity(image, true); + $scope.mediaItems.forEach(media => { + if (media.id === model.mediaNode.id) { + angular.extend(media, mediaEntity); + media.thumbnail = mediaHelper.resolveFileFromEntity(media, true); } }); }); } }, - close: function (model) { + close: function () { editorService.close(); } }; @@ -210,7 +205,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl editorService.close(); - _.each(model.selection, function (media, i) { + model.selection.forEach(media => { // if there is no thumbnail, try getting one if the media is not a placeholder item if (!media.thumbnail && media.id && media.metaData) { media.thumbnail = mediaHelper.resolveFileFromEntity(media, true); @@ -280,16 +275,14 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl disabled: !multiPicker, items: "li:not(.add-wrapper)", cancel: ".unsortable", - update: function (e, ui) { + update: function () { setDirty(); $timeout(function() { // TODO: Instead of doing this with a timeout 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 // watch do all the rest. - $scope.ids = _.map($scope.mediaItems, - function (item) { - return $scope.model.config.idType === "udi" ? item.udi : item.id; - }); + $scope.ids = $scope.mediaItems.map(media => $scope.model.config.idType === "udi" ? media.udi : media.id); + sync(); }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html index 1f9bd4e3c0..b4da03d30b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html @@ -36,16 +36,16 @@
- -
  • -
  • From 377f1925eaa7add6b8c94bb29174da6873541d0e Mon Sep 17 00:00:00 2001 From: Steve Temple Date: Fri, 31 Jan 2020 09:34:08 +0000 Subject: [PATCH 07/55] Obsolete CreatorName and WriterName on IPublishedContent --- .../PublishedContent/IPublishedContent.cs | 2 ++ .../PublishedContentHashtableConverter.cs | 2 ++ src/Umbraco.Web/Models/PublishedContentBase.cs | 4 ++++ .../PublishedCache/NuCache/PublishedContent.cs | 4 ++++ .../PublishedCache/PublishedMember.cs | 4 ++++ src/Umbraco.Web/PublishedContentExtensions.cs | 18 ++++++++++++++++-- 6 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs index 1c0d39a8b8..e8bee90d7c 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs @@ -63,6 +63,7 @@ namespace Umbraco.Core.Models.PublishedContent /// /// Gets the name of the user who created the content item. /// + [Obsolete("Use CreatorName(IUserService) extension instead")] string CreatorName { get; } /// @@ -78,6 +79,7 @@ namespace Umbraco.Core.Models.PublishedContent /// /// Gets the name of the user who last updated the content item. /// + [Obsolete("Use WriterName(IUserService) extension instead")] string WriterName { get; } /// diff --git a/src/Umbraco.Web/Macros/PublishedContentHashtableConverter.cs b/src/Umbraco.Web/Macros/PublishedContentHashtableConverter.cs index 41f0e2fb65..3bbc4a793b 100644 --- a/src/Umbraco.Web/Macros/PublishedContentHashtableConverter.cs +++ b/src/Umbraco.Web/Macros/PublishedContentHashtableConverter.cs @@ -248,8 +248,10 @@ namespace Umbraco.Web.Macros public string UrlSegment => throw new NotImplementedException(); + [Obsolete("Use WriterName(IUserService) extension instead")] public string WriterName { get; } + [Obsolete("Use CreatorName(IUserService) extension instead")] public string CreatorName { get; } public int WriterId => _inner.WriterId; diff --git a/src/Umbraco.Web/Models/PublishedContentBase.cs b/src/Umbraco.Web/Models/PublishedContentBase.cs index 148bab11c0..032a1a6fda 100644 --- a/src/Umbraco.Web/Models/PublishedContentBase.cs +++ b/src/Umbraco.Web/Models/PublishedContentBase.cs @@ -54,6 +54,8 @@ namespace Umbraco.Web.Models public abstract int CreatorId { get; } /// + [Obsolete("Use CreatorName(IUserService) extension instead")] + public abstract string CreatorName { get; } /// @@ -63,6 +65,8 @@ namespace Umbraco.Web.Models public abstract int WriterId { get; } /// + [Obsolete("Use WriterName(IUserService) extension instead")] + public abstract string WriterName { get; } /// diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs index 3c3c3ac54f..c84d49d685 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs @@ -163,6 +163,8 @@ namespace Umbraco.Web.PublishedCache.NuCache public override int CreatorId => _contentNode.CreatorId; /// + [Obsolete("Use CreatorName(IUserService) extension instead")] + public override string CreatorName => GetProfileNameById(_contentNode.CreatorId); /// @@ -172,6 +174,8 @@ namespace Umbraco.Web.PublishedCache.NuCache public override int WriterId => ContentData.WriterId; /// + [Obsolete("Use WriterName(IUserService) extension instead")] + public override string WriterName => GetProfileNameById(ContentData.WriterId); /// diff --git a/src/Umbraco.Web/PublishedCache/PublishedMember.cs b/src/Umbraco.Web/PublishedCache/PublishedMember.cs index 6e9ec61c62..30e5882ea8 100644 --- a/src/Umbraco.Web/PublishedCache/PublishedMember.cs +++ b/src/Umbraco.Web/PublishedCache/PublishedMember.cs @@ -140,9 +140,13 @@ namespace Umbraco.Web.PublishedCache public override string UrlSegment => throw new NotSupportedException(); // TODO: ARGH! need to fix this - this is not good because it uses ApplicationContext.Current + [Obsolete("Use WriterName(IUserService) extension instead")] + public override string WriterName => _member.GetCreatorProfile().Name; // TODO: ARGH! need to fix this - this is not good because it uses ApplicationContext.Current + [Obsolete("Use CreatorName(IUserService) extension instead")] + public override string CreatorName => _member.GetCreatorProfile().Name; public override int WriterId => _member.CreatorId; diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index 061422859c..4e9735b0bd 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -28,6 +28,20 @@ namespace Umbraco.Web private static UmbracoContext UmbracoContext => Current.UmbracoContext; private static ISiteDomainHelper SiteDomainHelper => Current.Factory.GetInstance(); + #region Creator/Writer Names + + public static string CreatorName(this IPublishedContent content, IUserService userService) + { + return userService.GetProfileById(content.CreatorId)?.Name; + } + + public static string WriterName(this IPublishedContent content, IUserService userService) + { + return userService.GetProfileById(content.WriterId)?.Name; + } + + #endregion + #region IsComposedOf /// @@ -1004,8 +1018,8 @@ namespace Umbraco.Web { "NodeTypeAlias", n.ContentType.Alias }, { "CreateDate", n.CreateDate }, { "UpdateDate", n.UpdateDate }, - { "CreatorName", n.CreatorName }, - { "WriterName", n.WriterName }, + { "CreatorName", n.CreatorName(services.UserService) }, + { "WriterName", n.WriterName(services.UserService) }, { "Url", n.Url() } }; From b95d674092e8c71a8d135d8799746ffa6dfc29b8 Mon Sep 17 00:00:00 2001 From: Steve Temple Date: Fri, 31 Jan 2020 09:50:37 +0000 Subject: [PATCH 08/55] Tidy up formatting --- src/Umbraco.Web/Models/PublishedContentBase.cs | 2 -- src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs | 2 -- src/Umbraco.Web/PublishedCache/PublishedMember.cs | 2 -- 3 files changed, 6 deletions(-) diff --git a/src/Umbraco.Web/Models/PublishedContentBase.cs b/src/Umbraco.Web/Models/PublishedContentBase.cs index 032a1a6fda..4bdea8b920 100644 --- a/src/Umbraco.Web/Models/PublishedContentBase.cs +++ b/src/Umbraco.Web/Models/PublishedContentBase.cs @@ -55,7 +55,6 @@ namespace Umbraco.Web.Models /// [Obsolete("Use CreatorName(IUserService) extension instead")] - public abstract string CreatorName { get; } /// @@ -66,7 +65,6 @@ namespace Umbraco.Web.Models /// [Obsolete("Use WriterName(IUserService) extension instead")] - public abstract string WriterName { get; } /// diff --git a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs index c84d49d685..d80affbfa9 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/PublishedContent.cs @@ -164,7 +164,6 @@ namespace Umbraco.Web.PublishedCache.NuCache /// [Obsolete("Use CreatorName(IUserService) extension instead")] - public override string CreatorName => GetProfileNameById(_contentNode.CreatorId); /// @@ -175,7 +174,6 @@ namespace Umbraco.Web.PublishedCache.NuCache /// [Obsolete("Use WriterName(IUserService) extension instead")] - public override string WriterName => GetProfileNameById(ContentData.WriterId); /// diff --git a/src/Umbraco.Web/PublishedCache/PublishedMember.cs b/src/Umbraco.Web/PublishedCache/PublishedMember.cs index 30e5882ea8..e7cdb65f2e 100644 --- a/src/Umbraco.Web/PublishedCache/PublishedMember.cs +++ b/src/Umbraco.Web/PublishedCache/PublishedMember.cs @@ -141,12 +141,10 @@ namespace Umbraco.Web.PublishedCache // TODO: ARGH! need to fix this - this is not good because it uses ApplicationContext.Current [Obsolete("Use WriterName(IUserService) extension instead")] - public override string WriterName => _member.GetCreatorProfile().Name; // TODO: ARGH! need to fix this - this is not good because it uses ApplicationContext.Current [Obsolete("Use CreatorName(IUserService) extension instead")] - public override string CreatorName => _member.GetCreatorProfile().Name; public override int WriterId => _member.CreatorId; From 6b461671800c2224376d90ef201ad582ec05994c Mon Sep 17 00:00:00 2001 From: Steve Temple Date: Fri, 31 Jan 2020 14:40:37 +0000 Subject: [PATCH 09/55] In GetDataTable use Obsolete CreatorName and WriterName for now --- src/Umbraco.Web/PublishedContentExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs index 4e9735b0bd..8d85c4615a 100644 --- a/src/Umbraco.Web/PublishedContentExtensions.cs +++ b/src/Umbraco.Web/PublishedContentExtensions.cs @@ -1018,8 +1018,8 @@ namespace Umbraco.Web { "NodeTypeAlias", n.ContentType.Alias }, { "CreateDate", n.CreateDate }, { "UpdateDate", n.UpdateDate }, - { "CreatorName", n.CreatorName(services.UserService) }, - { "WriterName", n.WriterName(services.UserService) }, + { "CreatorName", n.CreatorName }, + { "WriterName", n.WriterName }, { "Url", n.Url() } }; From a8672790d3d5b12717b909b2ef00569d47516253 Mon Sep 17 00:00:00 2001 From: Steve Temple Date: Fri, 31 Jan 2020 13:08:32 +0000 Subject: [PATCH 10/55] Obsolete Url on IPublishedContent --- src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs | 1 + .../Models/PublishedContent/PublishedContentWrapped.cs | 1 + src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs | 1 + src/Umbraco.Web/Controllers/UmbLoginController.cs | 2 +- src/Umbraco.Web/Models/PublishedContentBase.cs | 1 + src/Umbraco.Web/PropertyEditors/RichTextEditorPastedImages.cs | 2 +- 6 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs index 1c0d39a8b8..3f8b1c2ff3 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedContent.cs @@ -97,6 +97,7 @@ namespace Umbraco.Core.Models.PublishedContent /// The value of this property is contextual. It depends on the 'current' request uri, /// if any. /// + [Obsolete("Use the Url() extension instead")] string Url { get; } /// diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs index fb41c95419..b83dc7a013 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedContentWrapped.cs @@ -94,6 +94,7 @@ namespace Umbraco.Core.Models.PublishedContent public virtual DateTime UpdateDate => _content.UpdateDate; /// + [Obsolete("Use the Url() extension instead")] public virtual string Url => _content.Url; /// diff --git a/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs b/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs index 860b9b9179..a7b6d3d18a 100644 --- a/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs +++ b/src/Umbraco.Tests/PublishedContent/SolidPublishedSnapshot.cs @@ -199,6 +199,7 @@ namespace Umbraco.Tests.PublishedContent public DateTime UpdateDate { get; set; } public Guid Version { get; set; } public int Level { get; set; } + [Obsolete("Use the Url() extension instead")] public string Url { get; set; } public PublishedItemType ItemType => PublishedItemType.Content; diff --git a/src/Umbraco.Web/Controllers/UmbLoginController.cs b/src/Umbraco.Web/Controllers/UmbLoginController.cs index 2ff80e2668..88bc17abff 100644 --- a/src/Umbraco.Web/Controllers/UmbLoginController.cs +++ b/src/Umbraco.Web/Controllers/UmbLoginController.cs @@ -46,7 +46,7 @@ namespace Umbraco.Web.Controllers // if it's not a local url we'll redirect to the root of the current site return Redirect(Url.IsLocalUrl(model.RedirectUrl) ? model.RedirectUrl - : CurrentPage.AncestorOrSelf(1).Url); + : CurrentPage.AncestorOrSelf(1).Url()); } //redirect to current page by default diff --git a/src/Umbraco.Web/Models/PublishedContentBase.cs b/src/Umbraco.Web/Models/PublishedContentBase.cs index 148bab11c0..7f62c72004 100644 --- a/src/Umbraco.Web/Models/PublishedContentBase.cs +++ b/src/Umbraco.Web/Models/PublishedContentBase.cs @@ -69,6 +69,7 @@ namespace Umbraco.Web.Models public abstract DateTime UpdateDate { get; } /// + [Obsolete("Use the Url() extension instead")] public virtual string Url => this.Url(); /// diff --git a/src/Umbraco.Web/PropertyEditors/RichTextEditorPastedImages.cs b/src/Umbraco.Web/PropertyEditors/RichTextEditorPastedImages.cs index 0b2a607f8b..2a891ff1c7 100644 --- a/src/Umbraco.Web/PropertyEditors/RichTextEditorPastedImages.cs +++ b/src/Umbraco.Web/PropertyEditors/RichTextEditorPastedImages.cs @@ -101,7 +101,7 @@ namespace Umbraco.Web.PropertyEditors if (mediaTyped == null) throw new PanicException($"Could not find media by id {udi.Guid} or there was no UmbracoContext available."); - var location = mediaTyped.Url; + var location = mediaTyped.Url(); // Find the width & height attributes as we need to set the imageprocessor QueryString var width = img.GetAttributeValue("width", int.MinValue); From c5e0ef90c3f8aa88fb28bd289dd2358866ba7e07 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 10 Feb 2020 14:27:54 +0000 Subject: [PATCH 11/55] Verify & check SecurityStamp --- src/Umbraco.Web/Editors/AuthenticationController.cs | 7 ++++--- src/Umbraco.Web/Editors/BackOfficeController.cs | 12 +++++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs index c2c481e8e4..c7c08d1b42 100644 --- a/src/Umbraco.Web/Editors/AuthenticationController.cs +++ b/src/Umbraco.Web/Editors/AuthenticationController.cs @@ -301,7 +301,7 @@ namespace Umbraco.Web.Editors if (user != null) { var code = await UserManager.GeneratePasswordResetTokenAsync(identityUser.Id); - var callbackUrl = ConstructCallbackUrl(identityUser.Id, code); + var callbackUrl = ConstructCallbackUrl(identityUser.Id, code, identityUser.SecurityStamp.GenerateHash()); var message = Services.TextService.Localize("resetPasswordEmailCopyFormat", // Ensure the culture of the found user is used for the email! @@ -506,7 +506,7 @@ namespace Umbraco.Web.Editors return response; } - private string ConstructCallbackUrl(int userId, string code) + private string ConstructCallbackUrl(int userId, string code, string userSecurityStamp) { // Get an mvc helper to get the url var http = EnsureHttpContext(); @@ -516,7 +516,8 @@ namespace Umbraco.Web.Editors { area = GlobalSettings.GetUmbracoMvcArea(), u = userId, - r = code + r = code, + s = userSecurityStamp }); // Construct full URL using configured application URL (which will fall back to request) diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index e77a1b70f2..04c4627d85 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -296,11 +296,21 @@ namespace Umbraco.Web.Editors } [HttpGet] - public async Task ValidatePasswordResetCode([Bind(Prefix = "u")]int userId, [Bind(Prefix = "r")]string resetCode) + public async Task ValidatePasswordResetCode([Bind(Prefix = "u")]int userId, [Bind(Prefix = "r")]string resetCode, [Bind(Prefix = "s")]string stampHash) { var user = UserManager.FindById(userId); if (user != null) { + // Check security stamp that has been generated in forgotten password email link is the same we have stored for user + // ie the user has not been marked inactive or password changed by an admin etc + if(user.SecurityStamp.GenerateHash() != stampHash) + { + // Password, email or something changed to the user since the password reset email requested + // Add error and redirect for it to be displayed + TempData[ViewDataExtensions.TokenPasswordResetCode] = new[] { Services.TextService.Localize("login/resetCodeExpired") }; + return RedirectToLocal(Url.Action("Default", "BackOffice")); + } + var result = await UserManager.UserTokenProvider.ValidateAsync("ResetPassword", resetCode, UserManager, user); if (result) { From 4a0ce8572c1b1e2fb1181bd0565a637fde19368c Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Mon, 10 Feb 2020 17:29:31 +0100 Subject: [PATCH 12/55] Nested Content can't add multiple items when configured with a single element type --- .../propertyeditors/nestedcontent/nestedcontent.controller.js | 1 + 1 file changed, 1 insertion(+) 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 7de3a5b567..1c6d305c6b 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 @@ -221,6 +221,7 @@ if (vm.overlayMenu.availableItems.length === 1 && vm.overlayMenu.pasteItems.length === 0) { // only one scaffold type - no need to display the picker addNode(vm.scaffolds[0].contentTypeAlias); + vm.overlayMenu = null; return; } From c5ddba47a87ed5151dc94fc404b5c16c1d347917 Mon Sep 17 00:00:00 2001 From: emma burstow <37150989+emmaburstow@users.noreply.github.com> Date: Mon, 10 Feb 2020 16:21:03 +0000 Subject: [PATCH 13/55] Update SetUmbracoVersionStep.cs Punctuation fix --- src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs b/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs index b5fdea32b7..17191d2521 100644 --- a/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs +++ b/src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs @@ -13,7 +13,7 @@ using Umbraco.Web.Security; namespace Umbraco.Web.Install.InstallSteps { [InstallSetupStep(InstallationType.NewInstall | InstallationType.Upgrade, - "UmbracoVersion", 50, "Installation is complete!, get ready to be redirected to your new CMS.", + "UmbracoVersion", 50, "Installation is complete! Get ready to be redirected to your new CMS.", PerformsAppRestart = true)] internal class SetUmbracoVersionStep : InstallSetupStep { From 2c9c5baae51ef6b7ec86435892564fdb3aaa843e Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Mon, 10 Feb 2020 13:59:11 +0100 Subject: [PATCH 14/55] Prevent multi URL picker from crashing with JS errors when absolute (non-local) links are added. --- .../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 2e4313ec76..172f9b2249 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 @@ -147,7 +147,7 @@ function multiUrlPickerController($scope, angularHelper, localizationService, en _.each($scope.model.value, function (item){ // we must reload the "document" link URLs to match the current editor culture - if (item.udi.indexOf("/document/") > 0) { + if (item.udi && item.udi.indexOf("/document/") > 0) { item.url = null; entityResource.getUrlByUdi(item.udi).then(function (data) { item.url = data; From 8e2ed68b887f78c20a740cf3c9684f2dd15ab988 Mon Sep 17 00:00:00 2001 From: Arkadiusz Biel Date: Tue, 11 Feb 2020 09:20:30 +0000 Subject: [PATCH 15/55] Add more descriptive exception (#7591) * Add more descriptive exepection * Finish with . * Update src/Umbraco.Core/Collections/TopoGraph.cs Co-Authored-By: Sebastiaan Janssen * Update src/Umbraco.Core/Collections/TopoGraph.cs Co-Authored-By: Sebastiaan Janssen Co-authored-by: Sebastiaan Janssen --- src/Umbraco.Core/Collections/TopoGraph.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/Collections/TopoGraph.cs b/src/Umbraco.Core/Collections/TopoGraph.cs index b8ded4a458..955a210465 100644 --- a/src/Umbraco.Core/Collections/TopoGraph.cs +++ b/src/Umbraco.Core/Collections/TopoGraph.cs @@ -126,7 +126,7 @@ namespace Umbraco.Core.Collections if (_items.TryGetValue(key, out value)) yield return value; else if (throwOnMissing) - throw new Exception(MissingDependencyError); + throw new Exception($"{MissingDependencyError} Error in type {typeof(TItem).Name}, with key {key}"); } } } From 6ae88f6c76373ca79939e28993572eb1c378d4f7 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Tue, 11 Feb 2020 09:56:30 +0000 Subject: [PATCH 16/55] Revert "Verify & check SecurityStamp" This reverts commit c5e0ef90c3f8aa88fb28bd289dd2358866ba7e07. --- src/Umbraco.Web/Editors/AuthenticationController.cs | 7 +++---- src/Umbraco.Web/Editors/BackOfficeController.cs | 12 +----------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs index c7c08d1b42..c2c481e8e4 100644 --- a/src/Umbraco.Web/Editors/AuthenticationController.cs +++ b/src/Umbraco.Web/Editors/AuthenticationController.cs @@ -301,7 +301,7 @@ namespace Umbraco.Web.Editors if (user != null) { var code = await UserManager.GeneratePasswordResetTokenAsync(identityUser.Id); - var callbackUrl = ConstructCallbackUrl(identityUser.Id, code, identityUser.SecurityStamp.GenerateHash()); + var callbackUrl = ConstructCallbackUrl(identityUser.Id, code); var message = Services.TextService.Localize("resetPasswordEmailCopyFormat", // Ensure the culture of the found user is used for the email! @@ -506,7 +506,7 @@ namespace Umbraco.Web.Editors return response; } - private string ConstructCallbackUrl(int userId, string code, string userSecurityStamp) + private string ConstructCallbackUrl(int userId, string code) { // Get an mvc helper to get the url var http = EnsureHttpContext(); @@ -516,8 +516,7 @@ namespace Umbraco.Web.Editors { area = GlobalSettings.GetUmbracoMvcArea(), u = userId, - r = code, - s = userSecurityStamp + r = code }); // Construct full URL using configured application URL (which will fall back to request) diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index 04c4627d85..e77a1b70f2 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -296,21 +296,11 @@ namespace Umbraco.Web.Editors } [HttpGet] - public async Task ValidatePasswordResetCode([Bind(Prefix = "u")]int userId, [Bind(Prefix = "r")]string resetCode, [Bind(Prefix = "s")]string stampHash) + public async Task ValidatePasswordResetCode([Bind(Prefix = "u")]int userId, [Bind(Prefix = "r")]string resetCode) { var user = UserManager.FindById(userId); if (user != null) { - // Check security stamp that has been generated in forgotten password email link is the same we have stored for user - // ie the user has not been marked inactive or password changed by an admin etc - if(user.SecurityStamp.GenerateHash() != stampHash) - { - // Password, email or something changed to the user since the password reset email requested - // Add error and redirect for it to be displayed - TempData[ViewDataExtensions.TokenPasswordResetCode] = new[] { Services.TextService.Localize("login/resetCodeExpired") }; - return RedirectToLocal(Url.Action("Default", "BackOffice")); - } - var result = await UserManager.UserTokenProvider.ValidateAsync("ResetPassword", resetCode, UserManager, user); if (result) { From a7ff82f29a9fb41cba693d023b391ef17ae1e25a Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Tue, 11 Feb 2020 11:52:44 +0000 Subject: [PATCH 17/55] Implements Shans notes on changins security stamp for chaning email/username --- .../Repositories/Implement/UserRepository.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs index 96abc37662..3be5102b83 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs @@ -557,6 +557,16 @@ ORDER BY colName"; } } + // If userlogin or the email has changed then need to reset security stamp + if (changedCols.Contains("userLogin") || changedCols.Contains("userEmail")) + { + userDto.EmailConfirmedDate = null; + userDto.SecurityStampToken = entity.SecurityStamp = Guid.NewGuid().ToString(); + + changedCols.Add("emailConfirmedDate"); + changedCols.Add("securityStampToken"); + } + //only update the changed cols if (changedCols.Count > 0) { From 4ff91ed4d1e4643998897dc6e347c132003839c9 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Tue, 11 Feb 2020 20:15:22 +0100 Subject: [PATCH 18/55] Use button element in user detail and user group views (#7584) * Use button element on user detail page * Use button element on user group page --- .../src/views/users/group.html | 59 ++++++++----------- .../src/views/users/views/user/details.html | 32 +++++----- 2 files changed, 40 insertions(+), 51 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/users/group.html b/src/Umbraco.Web.UI.Client/src/views/users/group.html index 0244819655..8333528ddd 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/group.html +++ b/src/Umbraco.Web.UI.Client/src/views/users/group.html @@ -40,13 +40,12 @@ on-remove="vm.removeSelectedItem($index, vm.userGroup.sections)"> - + @@ -61,15 +60,13 @@ on-remove="vm.clearStartNode('content')"> - + @@ -85,14 +82,13 @@ on-remove="vm.clearStartNode('media')"> - + @@ -127,13 +123,12 @@ on-edit="vm.setPermissionsForNode(node)"> - + @@ -155,13 +150,11 @@ on-remove="vm.removeSelectedItem($index, vm.userGroup.users)"> - + diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/user/details.html b/src/Umbraco.Web.UI.Client/src/views/users/views/user/details.html index e0cf09da50..bb3efaede2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/views/user/details.html +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/user/details.html @@ -75,13 +75,11 @@ on-remove="model.removeSelectedItem($index, model.user.userGroups)"> - + @@ -100,13 +98,12 @@ name="model.labels.noStartNodes"> - + @@ -125,13 +122,12 @@ name="model.labels.noStartNodes"> - + From b2141b665768b289e5fe2a1385f27cae12f6843e Mon Sep 17 00:00:00 2001 From: Steve Megson Date: Wed, 5 Feb 2020 15:00:46 +0000 Subject: [PATCH 19/55] Slider format function should return a number --- .../src/views/propertyeditors/slider/slider.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js index a20289d076..f5f0f7f2a2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js @@ -56,7 +56,7 @@ return value.toFixed(stepDecimalPlaces); }, from: function (value) { - return value; + return Number(value); } }, "range": { From 53ca5eec88694f5c062357717b428e429a91f11b Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Tue, 11 Feb 2020 20:36:42 +0100 Subject: [PATCH 20/55] Adjust child selector sorting (#7582) * Only add move cursor to sortable child elements * Don't sort add button * Add missing docs for onSort * Change add button to use button element * Use button element for remove button and add aria-hidden to icons * Reset styling of button element * Ensure add button is full width * Remove unnecessary cursor styles since these now inherit from button element --- .../components/umbchildselector.directive.js | 17 ++++++++----- .../less/components/umb-child-selector.less | 24 ++++++++++--------- .../views/components/umb-child-selector.html | 12 ++++++---- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbchildselector.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbchildselector.directive.js index a33fd4be53..96ce8735eb 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbchildselector.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbchildselector.directive.js @@ -99,13 +99,18 @@ Use this directive to render a ui component for selecting child items to a paren @param {string} parentName (binding): The parent name. @param {string} parentIcon (binding): The parent icon. @param {number} parentId (binding): The parent id. -@param {callback} onRemove (binding): Callback when the remove button is clicked on an item. +@param {callback} onRemove (binding): Callback when removing an item.

    The callback returns:

    • child: The selected item.
    • $index: The selected item index.
    -@param {callback} onAdd (binding): Callback when the add button is clicked. +@param {callback} onAdd (binding): Callback when adding an item. +

    The callback returns:

    +
      +
    • $event: The select event.
    • +
    +@param {callback} onSort (binding): Callback when sorting an item.

    The callback returns:

    • $event: The select event.
    • @@ -174,16 +179,15 @@ Use this directive to render a ui component for selecting child items to a paren eventBindings.push(scope.$watch('parentName', function(newValue, oldValue){ if (newValue === oldValue) { return; } - if ( oldValue === undefined || newValue === undefined) { return; } + if (oldValue === undefined || newValue === undefined) { return; } syncParentName(); - })); eventBindings.push(scope.$watch('parentIcon', function(newValue, oldValue){ if (newValue === oldValue) { return; } - if ( oldValue === undefined || newValue === undefined) { return; } + if (oldValue === undefined || newValue === undefined) { return; } syncParentIcon(); })); @@ -191,6 +195,7 @@ Use this directive to render a ui component for selecting child items to a paren // sortable options for allowed child content types scope.sortableOptions = { axis: "y", + cancel: ".unsortable", containment: "parent", distance: 10, opacity: 0.7, @@ -199,7 +204,7 @@ Use this directive to render a ui component for selecting child items to a paren zIndex: 6000, update: function (e, ui) { if(scope.onSort) { - scope.onSort(); + scope.onSort(); } } }; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-child-selector.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-child-selector.less index da690663d0..937f746c56 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-child-selector.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-child-selector.less @@ -16,23 +16,24 @@ .umb-child-selector__child.-placeholder { border: 1px dashed @gray-8; background: none; - cursor: pointer; text-align: center; justify-content: center; - - color:@ui-action-type; + width: 100%; + color: @ui-action-type; + &:hover { - color:@ui-action-type-hover; - border-color:@ui-action-type-hover; - text-decoration:none; + color: @ui-action-type-hover; + border-color: @ui-action-type-hover; + text-decoration: none; } } .umb-child-selector__children-container { - margin-left: 30px; - .umb-child-selector__child { - cursor: move; - } + margin-left: 30px; + + .umb-child-selector__child.ui-sortable-handle { + cursor: move; + } } .umb-child-selector__child-description { @@ -65,5 +66,6 @@ } .umb-child-selector__child-remove { - cursor: pointer; + background: none; + border: none; } diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-child-selector.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-child-selector.html index 0866e1bdf7..1d88c0eb96 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-child-selector.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-child-selector.html @@ -19,18 +19,20 @@
      - +
      - {{ selectedChild.name }} + {{selectedChild.name}}
      - +
      - + From 32960219078bc599deb461ec26a1b008d726a8ad Mon Sep 17 00:00:00 2001 From: Mark Drake Date: Tue, 11 Feb 2020 15:10:28 -0500 Subject: [PATCH 21/55] Add an Active State for Expand (...) in the Top Section Navigation --- .../components/application/umbsections.directive.js | 11 +++++++++++ src/Umbraco.Web.UI.Client/src/less/sections.less | 9 ++++++++- .../views/components/application/umb-sections.html | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsections.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsections.directive.js index b8ee797c82..a33796ab6d 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsections.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsections.directive.js @@ -133,6 +133,17 @@ function sectionsDirective($timeout, $window, navigationService, treeService, se } }; + scope.currentSectionInOverflow = function () { + if (scope.overflowingSections === 0) { + return false; + } + + var currentSection = scope.sections.filter(s => s.alias === scope.currentSection); + + return (scope.sections.indexOf(currentSection[0]) >= scope.maxSections); + + }; + loadSections(); } diff --git a/src/Umbraco.Web.UI.Client/src/less/sections.less b/src/Umbraco.Web.UI.Client/src/less/sections.less index 27b11b1c3b..1f19786b3c 100644 --- a/src/Umbraco.Web.UI.Client/src/less/sections.less +++ b/src/Umbraco.Web.UI.Client/src/less/sections.less @@ -55,7 +55,7 @@ ul.sections { transition: opacity .1s linear, box-shadow .1s; } - &.current a { + &.current > a { color: @ui-active; &::after { @@ -76,6 +76,13 @@ ul.sections { transition: opacity .1s linear; } + &.current { + i { + opacity: 1; + background: @ui-active; + } + } + &:hover i { opacity: 1; } diff --git a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-sections.html b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-sections.html index 5688ba0e3b..0dac7176ee 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-sections.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-sections.html @@ -11,7 +11,7 @@ -
    • +
    • From 2fc495128e21aaadf1fad80fd12859680998c492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 29 Jan 2020 10:51:56 +0100 Subject: [PATCH 22/55] make icon of umb-preview-node align vertically. --- .../src/less/components/umb-node-preview.less | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-node-preview.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-node-preview.less index f754a09368..939fd79826 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-node-preview.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-node-preview.less @@ -29,7 +29,8 @@ .umb-node-preview__icon { display: flex; width: 25px; - height: 25px; + min-height: 25px; + height: 100%; justify-content: center; align-items: center; font-size: 20px; From e90e32b871b1d86269f47f7b60b159f8629a4773 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Wed, 12 Feb 2020 10:11:28 +0000 Subject: [PATCH 23/55] Add unit test to verify SecurityStamp changes/invalidates when the userlogin changes --- .../Repositories/UserRepositoryTest.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs index 3ba00e54cf..bbefb79f6b 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs @@ -421,6 +421,35 @@ namespace Umbraco.Tests.Persistence.Repositories } } + [Test] + public void Can_Invalidate_SecurityStamp_On_Username_Change() + { + // Arrange + var provider = TestObjects.GetScopeProvider(Logger); + using (var scope = provider.CreateScope()) + { + var repository = CreateRepository(provider); + var userGroupRepository = CreateUserGroupRepository(provider); + + var user = CreateAndCommitUserWithGroup(repository, userGroupRepository); + var originalSecurityStamp = user.SecurityStamp; + + // Ensure when user generated a security stamp is present + Assert.That(user.SecurityStamp, Is.Not.Null); + Assert.That(user.SecurityStamp, Is.Not.Empty); + + // Update username + user.Username = user.Username + "UPDATED"; + repository.Save(user); + + // Get the user + var updatedUser = repository.Get(user.Id); + + // Ensure the Security Stamp is invalidated & no longer the same + Assert.AreNotEqual(originalSecurityStamp, updatedUser.SecurityStamp); + } + } + private void AssertPropertyValues(IUser updatedItem, IUser originalUser) { Assert.That(updatedItem.Id, Is.EqualTo(originalUser.Id)); From a7ad464b40f3b3039f0137317cdc6a8170b181c0 Mon Sep 17 00:00:00 2001 From: abi Date: Sun, 2 Feb 2020 01:43:15 +0000 Subject: [PATCH 24/55] Remove Empty Statements --- src/Umbraco.Core/Cache/WebCachingAppCache.cs | 2 +- src/Umbraco.Core/HashGenerator.cs | 2 +- .../MergeDateAndDateTimePropertyEditor.cs | 2 +- .../Packaging/ConflictingPackageData.cs | 4 ++-- .../Packaging/PackagesRepository.cs | 11 ++++----- .../Repositories/Implement/MacroRepository.cs | 3 +-- .../Implement/TemplateRepository.cs | 1 - src/Umbraco.Core/Xml/XmlHelper.cs | 6 ++--- .../UmbracoTestDataController.cs | 14 +++++------ src/Umbraco.Tests/Logging/LogviewerTests.cs | 2 +- .../Repositories/MacroRepositoryTest.cs | 3 +-- .../Templates/Gallery.cshtml | 4 ++-- .../Partials/Grid/Bootstrap3-Fluid.cshtml | 14 +++++------ .../Views/Partials/Grid/Bootstrap3.cshtml | 4 ++-- src/Umbraco.Web/Cache/MacroCacheRefresher.cs | 2 +- src/Umbraco.Web/Editors/DataTypeController.cs | 2 +- .../Editors/PackageInstallController.cs | 4 ++-- .../Media/Exif/ExifBitConverter.cs | 2 +- .../Media/Exif/ExifExtendedProperty.cs | 24 +++++++++---------- .../Media/Exif/JFIFExtendedProperty.cs | 2 +- src/Umbraco.Web/Media/Exif/JPEGSection.cs | 2 +- src/Umbraco.Web/Media/Exif/MathEx.cs | 24 +++++++++---------- 22 files changed, 65 insertions(+), 69 deletions(-) diff --git a/src/Umbraco.Core/Cache/WebCachingAppCache.cs b/src/Umbraco.Core/Cache/WebCachingAppCache.cs index c6e104221a..044aab4c42 100644 --- a/src/Umbraco.Core/Cache/WebCachingAppCache.cs +++ b/src/Umbraco.Core/Cache/WebCachingAppCache.cs @@ -86,7 +86,7 @@ namespace Umbraco.Core.Cache protected override void EnterWriteLock() { - _locker.EnterWriteLock();; + _locker.EnterWriteLock(); } protected override void ExitReadLock() diff --git a/src/Umbraco.Core/HashGenerator.cs b/src/Umbraco.Core/HashGenerator.cs index 80cc3c3de4..58034f05d7 100644 --- a/src/Umbraco.Core/HashGenerator.cs +++ b/src/Umbraco.Core/HashGenerator.cs @@ -41,7 +41,7 @@ namespace Umbraco.Core internal void AddDateTime(DateTime d) { - _writer.Write(d.Ticks);; + _writer.Write(d.Ticks); } internal void AddString(string s) diff --git a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/MergeDateAndDateTimePropertyEditor.cs b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/MergeDateAndDateTimePropertyEditor.cs index 0d451e8460..37a83bdd67 100644 --- a/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/MergeDateAndDateTimePropertyEditor.cs +++ b/src/Umbraco.Core/Migrations/Upgrade/V_8_0_0/MergeDateAndDateTimePropertyEditor.cs @@ -32,7 +32,7 @@ namespace Umbraco.Core.Migrations.Upgrade.V_8_0_0 if (string.IsNullOrEmpty(dataType.Configuration)) { config.Format = "YYYY-MM-DD"; - }; + } } catch (Exception ex) { diff --git a/src/Umbraco.Core/Packaging/ConflictingPackageData.cs b/src/Umbraco.Core/Packaging/ConflictingPackageData.cs index 82693677fb..33cb9c40d3 100644 --- a/src/Umbraco.Core/Packaging/ConflictingPackageData.cs +++ b/src/Umbraco.Core/Packaging/ConflictingPackageData.cs @@ -7,7 +7,7 @@ using Umbraco.Core.Services; namespace Umbraco.Core.Packaging { - internal class ConflictingPackageData + internal class ConflictingPackageData { private readonly IMacroService _macroService; private readonly IFileService _fileService; @@ -23,7 +23,7 @@ namespace Umbraco.Core.Packaging return stylesheetNodes .Select(n => { - var xElement = n.Element("Name") ?? n.Element("name"); ; + var xElement = n.Element("Name") ?? n.Element("name"); if (xElement == null) throw new FormatException("Missing \"Name\" element"); diff --git a/src/Umbraco.Core/Packaging/PackagesRepository.cs b/src/Umbraco.Core/Packaging/PackagesRepository.cs index 72954b238d..5549b502fa 100644 --- a/src/Umbraco.Core/Packaging/PackagesRepository.cs +++ b/src/Umbraco.Core/Packaging/PackagesRepository.cs @@ -82,7 +82,7 @@ namespace Umbraco.Core.Packaging { var packagesXml = EnsureStorage(out _); if (packagesXml?.Root == null) - yield break;; + yield break; foreach (var packageXml in packagesXml.Root.Elements("package")) yield return _parser.ToPackageDefinition(packageXml); @@ -139,7 +139,7 @@ namespace Umbraco.Core.Packaging var updatedXml = _parser.ToXml(definition); packageXml.ReplaceWith(updatedXml); } - + packagesXml.Save(packagesFile); return true; @@ -212,7 +212,7 @@ namespace Umbraco.Core.Packaging compiledPackageXml.Save(packageXmlFileName); // check if there's a packages directory below media - + if (Directory.Exists(IOHelper.MapPath(_mediaFolderPath)) == false) Directory.CreateDirectory(IOHelper.MapPath(_mediaFolderPath)); @@ -510,7 +510,6 @@ namespace Umbraco.Core.Packaging private XElement GetStylesheetXml(string name, bool includeProperties) { if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(name)); -; var sts = _fileService.GetStylesheetByName(name); if (sts == null) return null; var stylesheetXml = new XElement("Stylesheet"); @@ -562,7 +561,7 @@ namespace Umbraco.Core.Packaging package.Add(new XElement("url", definition.Url)); var requirements = new XElement("requirements"); - + requirements.Add(new XElement("major", definition.UmbracoVersion == null ? UmbracoVersion.SemanticVersion.Major.ToInvariantString() : definition.UmbracoVersion.Major.ToInvariantString())); requirements.Add(new XElement("minor", definition.UmbracoVersion == null ? UmbracoVersion.SemanticVersion.Minor.ToInvariantString() : definition.UmbracoVersion.Minor.ToInvariantString())); requirements.Add(new XElement("patch", definition.UmbracoVersion == null ? UmbracoVersion.SemanticVersion.Patch.ToInvariantString() : definition.UmbracoVersion.Build.ToInvariantString())); @@ -589,7 +588,7 @@ namespace Umbraco.Core.Packaging contributors.Add(new XElement("contributor", contributor)); } } - + info.Add(contributors); info.Add(new XElement("readme", new XCData(definition.Readme))); diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MacroRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MacroRepository.cs index f0044e225d..1f0b45614b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MacroRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MacroRepository.cs @@ -40,7 +40,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (macroDto == null) return null; - + var entity = MacroFactory.BuildEntity(macroDto); // reset dirty initial properties (U4-1946) @@ -153,7 +153,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected override void PersistUpdatedItem(IMacro entity) { entity.UpdatingEntity(); -; var dto = MacroFactory.BuildDto(entity); Database.Update(dto); diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs index b348317989..2175780916 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/TemplateRepository.cs @@ -215,7 +215,6 @@ namespace Umbraco.Core.Persistence.Repositories.Implement //Save updated entity to db template.UpdateDate = DateTime.Now; - ; var dto = TemplateFactory.BuildDto(template, NodeObjectTypeId, templateDto.PrimaryKey); Database.Update(dto.NodeDto); diff --git a/src/Umbraco.Core/Xml/XmlHelper.cs b/src/Umbraco.Core/Xml/XmlHelper.cs index 2dd955086d..d6461ec8c6 100644 --- a/src/Umbraco.Core/Xml/XmlHelper.cs +++ b/src/Umbraco.Core/Xml/XmlHelper.cs @@ -214,9 +214,9 @@ namespace Umbraco.Core.Xml var xmlDoc = new XmlDocument(); //Load the file into the XmlDocument xmlDoc.Load(reader); - + return xmlDoc; - } + } } /// @@ -335,7 +335,7 @@ namespace Umbraco.Core.Xml var child = parent.SelectSingleNode(name); if (child != null) { - child.InnerXml = ""; ; + child.InnerXml = ""; return child; } return AddCDataNode(xd, name, value); diff --git a/src/Umbraco.TestData/UmbracoTestDataController.cs b/src/Umbraco.TestData/UmbracoTestDataController.cs index 402c05cc1c..02949d5345 100644 --- a/src/Umbraco.TestData/UmbracoTestDataController.cs +++ b/src/Umbraco.TestData/UmbracoTestDataController.cs @@ -68,7 +68,7 @@ namespace Umbraco.TestData scope.Complete(); } - + return Content("Done"); } @@ -89,7 +89,7 @@ namespace Umbraco.TestData message = "Count not high enough for specified for number of levels required"; return false; } - + return true; } @@ -140,7 +140,7 @@ namespace Umbraco.TestData currChildCount = prev.childCount; // restore the parent parent = prev.parent; - + } else if (contentItem.Level < depth) { @@ -149,10 +149,10 @@ namespace Umbraco.TestData // not at max depth, create below parent = created.container(); - + currChildCount = 0; } - + } } @@ -219,7 +219,7 @@ namespace Umbraco.TestData { var content = Services.ContentService.Create(faker.Commerce.ProductName(), currParent, docType.Alias); content.SetValue("review", faker.Rant.Review()); - content.SetValue("desc", string.Join(", ", Enumerable.Range(0, 5).Select(x => faker.Commerce.ProductAdjective()))); ; + content.SetValue("desc", string.Join(", ", Enumerable.Range(0, 5).Select(x => faker.Commerce.ProductAdjective()))); content.SetValue("media", imageIds[random.Next(0, imageIds.Count - 1)]); Services.ContentService.Save(content); @@ -259,7 +259,7 @@ namespace Umbraco.TestData return docType; } - private IDataType GetOrCreateRichText() => GetOrCreateDataType(RichTextDataTypeName, Constants.PropertyEditors.Aliases.TinyMce); + private IDataType GetOrCreateRichText() => GetOrCreateDataType(RichTextDataTypeName, Constants.PropertyEditors.Aliases.TinyMce); private IDataType GetOrCreateMediaPicker() => GetOrCreateDataType(MediaPickerDataTypeName, Constants.PropertyEditors.Aliases.MediaPicker); diff --git a/src/Umbraco.Tests/Logging/LogviewerTests.cs b/src/Umbraco.Tests/Logging/LogviewerTests.cs index ed9deec177..08ba070b70 100644 --- a/src/Umbraco.Tests/Logging/LogviewerTests.cs +++ b/src/Umbraco.Tests/Logging/LogviewerTests.cs @@ -163,7 +163,7 @@ namespace Umbraco.Tests.Logging //Query @Level='Warning' BUT we pass in array of LogLevels for Debug & Info (Expect to get 0 results) string[] logLevelMismatch = { "Debug", "Information" }; - var filterLevelQuery = _logViewer.GetLogs(_logTimePeriod, pageNumber: 1, filterExpression: "@Level='Warning'", logLevels: logLevelMismatch); ; + var filterLevelQuery = _logViewer.GetLogs(_logTimePeriod, pageNumber: 1, filterExpression: "@Level='Warning'", logLevels: logLevelMismatch); Assert.AreEqual(0, filterLevelQuery.TotalItems); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs index 6f215f4a35..9eca06d4e0 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MacroRepositoryTest.cs @@ -38,7 +38,6 @@ namespace Umbraco.Tests.Persistence.Repositories var repository = new MacroRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of()); var macro = new Macro("test1", "Test", "~/views/macropartials/test.cshtml", MacroTypes.PartialView); - ; Assert.Throws(() => repository.Save(macro)); } @@ -56,7 +55,7 @@ namespace Umbraco.Tests.Persistence.Repositories var macro = repository.Get(1); macro.Alias = "test2"; - + Assert.Throws(() => repository.Save(macro)); } diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Gallery.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Gallery.cshtml index 5aa09a3cb3..64be8eb60c 100755 --- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Gallery.cshtml +++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Gallery.cshtml @@ -29,13 +29,13 @@ @* a single image *@ if (media.IsDocumentType("Image")) { - @Render(media); + @Render(media) } @* a folder with images under it *@ foreach (var image in media.Children()) { - @Render(image); + @Render(image) } } diff --git a/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3-Fluid.cshtml b/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3-Fluid.cshtml index defe59d808..131b0515ae 100644 --- a/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3-Fluid.cshtml +++ b/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3-Fluid.cshtml @@ -2,31 +2,31 @@ @using Umbraco.Web.Templates @using Newtonsoft.Json.Linq -@* +@* Razor helpers located at the bottom of this file *@ @if (Model != null && Model.sections != null) { var oneColumn = ((System.Collections.ICollection)Model.sections).Count == 1; - +
      @if (oneColumn) { foreach (var section in Model.sections) {
      @foreach (var row in section.rows) { - @renderRow(row); + @renderRow(row) }
      - } - }else { + } + }else {
      @foreach (var s in Model.sections) {
      @foreach (var row in s.rows) { - @renderRow(row); + @renderRow(row) }
      @@ -85,4 +85,4 @@ return new MvcHtmlString(string.Join(" ", attrs)); } -} \ No newline at end of file +} diff --git a/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3.cshtml b/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3.cshtml index 9333628ed6..23fee33043 100644 --- a/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3.cshtml +++ b/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3.cshtml @@ -12,7 +12,7 @@ foreach (var section in Model.sections) {
      @foreach (var row in section.rows) { - @renderRow(row, true); + @renderRow(row, true) }
      } @@ -23,7 +23,7 @@
      @foreach (var row in s.rows) { - @renderRow(row, false); + @renderRow(row, false) }
      diff --git a/src/Umbraco.Web/Cache/MacroCacheRefresher.cs b/src/Umbraco.Web/Cache/MacroCacheRefresher.cs index 24479b8415..0cecba7b7b 100644 --- a/src/Umbraco.Web/Cache/MacroCacheRefresher.cs +++ b/src/Umbraco.Web/Cache/MacroCacheRefresher.cs @@ -53,7 +53,7 @@ namespace Umbraco.Web.Cache { macroRepoCache.Result.Clear(RepositoryCacheKeys.GetKey(payload.Id)); } - }; + } base.Refresh(json); } diff --git a/src/Umbraco.Web/Editors/DataTypeController.cs b/src/Umbraco.Web/Editors/DataTypeController.cs index 5f5f5104cb..ad92d40ecf 100644 --- a/src/Umbraco.Web/Editors/DataTypeController.cs +++ b/src/Umbraco.Web/Editors/DataTypeController.cs @@ -427,7 +427,7 @@ namespace Umbraco.Web.Editors { var propertyEditor = propertyEditors.SingleOrDefault(x => x.Alias == dataType.Alias); if (propertyEditor != null) - dataType.HasPrevalues = propertyEditor.GetConfigurationEditor().Fields.Any(); ; + dataType.HasPrevalues = propertyEditor.GetConfigurationEditor().Fields.Any(); } var grouped = dataTypes diff --git a/src/Umbraco.Web/Editors/PackageInstallController.cs b/src/Umbraco.Web/Editors/PackageInstallController.cs index 6b2bd07fbd..1030498734 100644 --- a/src/Umbraco.Web/Editors/PackageInstallController.cs +++ b/src/Umbraco.Web/Editors/PackageInstallController.cs @@ -102,8 +102,8 @@ namespace Umbraco.Web.Editors model.LicenseUrl = ins.LicenseUrl; model.Readme = ins.Readme; model.ConflictingMacroAliases = ins.Warnings.ConflictingMacros.ToDictionary(x => x.Name, x => x.Alias); - model.ConflictingStyleSheetNames = ins.Warnings.ConflictingStylesheets.ToDictionary(x => x.Name, x => x.Alias); ; - model.ConflictingTemplateAliases = ins.Warnings.ConflictingTemplates.ToDictionary(x => x.Name, x => x.Alias); ; + model.ConflictingStyleSheetNames = ins.Warnings.ConflictingStylesheets.ToDictionary(x => x.Name, x => x.Alias); + model.ConflictingTemplateAliases = ins.Warnings.ConflictingTemplates.ToDictionary(x => x.Name, x => x.Alias); model.ContainsUnsecureFiles = ins.Warnings.UnsecureFiles.Any(); model.Url = ins.Url; model.Version = ins.Version; diff --git a/src/Umbraco.Web/Media/Exif/ExifBitConverter.cs b/src/Umbraco.Web/Media/Exif/ExifBitConverter.cs index 86bd12c15e..1dcae62acd 100644 --- a/src/Umbraco.Web/Media/Exif/ExifBitConverter.cs +++ b/src/Umbraco.Web/Media/Exif/ExifBitConverter.cs @@ -12,7 +12,7 @@ namespace Umbraco.Web.Media.Exif public ExifBitConverter(ByteOrder from, ByteOrder to) : base(from, to) { - ; + } #endregion diff --git a/src/Umbraco.Web/Media/Exif/ExifExtendedProperty.cs b/src/Umbraco.Web/Media/Exif/ExifExtendedProperty.cs index 63c1ce3365..8889a13e1d 100644 --- a/src/Umbraco.Web/Media/Exif/ExifExtendedProperty.cs +++ b/src/Umbraco.Web/Media/Exif/ExifExtendedProperty.cs @@ -28,7 +28,7 @@ namespace Umbraco.Web.Media.Exif public ExifEnumProperty(ExifTag tag, T value) : this(tag, value, false) { - ; + } public override ExifInterOperability Interoperability @@ -210,13 +210,13 @@ namespace Umbraco.Web.Media.Exif public ExifPointSubjectArea(ExifTag tag, ushort[] value) : base(tag, value) { - ; + } public ExifPointSubjectArea(ExifTag tag, ushort x, ushort y) - : base(tag, new ushort[] { x, y }) + : base(tag, new ushort[] {x, y}) { - ; + } } @@ -239,13 +239,13 @@ namespace Umbraco.Web.Media.Exif public ExifCircularSubjectArea(ExifTag tag, ushort[] value) : base(tag, value) { - ; + } public ExifCircularSubjectArea(ExifTag tag, ushort x, ushort y, ushort d) : base(tag, new ushort[] { x, y, d }) { - ; + } } @@ -269,13 +269,13 @@ namespace Umbraco.Web.Media.Exif public ExifRectangularSubjectArea(ExifTag tag, ushort[] value) : base(tag, value) { - ; + } public ExifRectangularSubjectArea(ExifTag tag, ushort x, ushort y, ushort w, ushort h) : base(tag, new ushort[] { x, y, w, h }) { - ; + } } @@ -303,13 +303,13 @@ namespace Umbraco.Web.Media.Exif public GPSLatitudeLongitude(ExifTag tag, MathEx.UFraction32[] value) : base(tag, value) { - ; + } public GPSLatitudeLongitude(ExifTag tag, float d, float m, float s) : base(tag, new MathEx.UFraction32[] { new MathEx.UFraction32(d), new MathEx.UFraction32(m), new MathEx.UFraction32(s) }) { - ; + } } @@ -331,13 +331,13 @@ namespace Umbraco.Web.Media.Exif public GPSTimeStamp(ExifTag tag, MathEx.UFraction32[] value) : base(tag, value) { - ; + } public GPSTimeStamp(ExifTag tag, float h, float m, float s) : base(tag, new MathEx.UFraction32[] { new MathEx.UFraction32(h), new MathEx.UFraction32(m), new MathEx.UFraction32(s) }) { - ; + } } diff --git a/src/Umbraco.Web/Media/Exif/JFIFExtendedProperty.cs b/src/Umbraco.Web/Media/Exif/JFIFExtendedProperty.cs index 94b255f4d1..24b3ac74be 100644 --- a/src/Umbraco.Web/Media/Exif/JFIFExtendedProperty.cs +++ b/src/Umbraco.Web/Media/Exif/JFIFExtendedProperty.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web.Media.Exif public JFIFVersion(ExifTag tag, ushort value) : base(tag, value) { - ; + } public override string ToString() diff --git a/src/Umbraco.Web/Media/Exif/JPEGSection.cs b/src/Umbraco.Web/Media/Exif/JPEGSection.cs index a1bc420fe4..78565d2bfa 100644 --- a/src/Umbraco.Web/Media/Exif/JPEGSection.cs +++ b/src/Umbraco.Web/Media/Exif/JPEGSection.cs @@ -45,7 +45,7 @@ public JPEGSection(JPEGMarker marker) : this(marker, new byte[0], new byte[0]) { - ; + } #endregion diff --git a/src/Umbraco.Web/Media/Exif/MathEx.cs b/src/Umbraco.Web/Media/Exif/MathEx.cs index 735358c40a..94cbccfbda 100644 --- a/src/Umbraco.Web/Media/Exif/MathEx.cs +++ b/src/Umbraco.Web/Media/Exif/MathEx.cs @@ -403,37 +403,37 @@ namespace Umbraco.Web.Media.Exif public Fraction32(int numerator, int denominator) : this(numerator, denominator, 0) { - ; + } public Fraction32(int numerator) : this(numerator, (int)1) { - ; + } public Fraction32(Fraction32 f) : this(f.Numerator, f.Denominator, f.Error) { - ; + } public Fraction32(float value) : this((double)value) { - ; + } public Fraction32(double value) : this(FromDouble(value)) { - ; + } public Fraction32(string s) : this(FromString(s)) { - ; + } #endregion @@ -1033,37 +1033,37 @@ namespace Umbraco.Web.Media.Exif public UFraction32(uint numerator, uint denominator) : this(numerator, denominator, 0) { - ; + } public UFraction32(uint numerator) : this(numerator, (uint)1) { - ; + } public UFraction32(UFraction32 f) : this(f.Numerator, f.Denominator, f.Error) { - ; + } public UFraction32(float value) : this((double)value) { - ; + } public UFraction32(double value) : this(FromDouble(value)) { - ; + } public UFraction32(string s) : this(FromString(s)) { - ; + } #endregion From 450a77fff56b17dca9e714ad6153bbb4778331ef Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Wed, 12 Feb 2020 15:21:03 +0100 Subject: [PATCH 25/55] Missing onClose for tour (#7595) --- .../components/application/umbtour/umbtourstep.directive.js | 6 +++--- .../src/views/components/application/umb-tour.html | 2 +- .../views/components/application/umbtour/umb-tour-step.html | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstep.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstep.directive.js index 2dc0ebdf93..381ecc76c3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstep.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbtour/umbtourstep.directive.js @@ -18,9 +18,9 @@ function link(scope, element, attrs, ctrl) { - scope.close = function() { - if(scope.onClose) { - scope.onClose(); + scope.close = function () { + if (scope.onClose) { + scope.onClose(); } } 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 e358d75b9e..064dcf6945 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 @@ -70,7 +70,7 @@
      - +

      Oh, we got lost!

      diff --git a/src/Umbraco.Web.UI.Client/src/views/components/application/umbtour/umb-tour-step.html b/src/Umbraco.Web.UI.Client/src/views/components/application/umbtour/umb-tour-step.html index a2caff4ff2..9e161d6b4e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/application/umbtour/umb-tour-step.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/application/umbtour/umb-tour-step.html @@ -1,8 +1,7 @@
      -
      - -
    • -
    • From 69a1729967da863219326292da959d0686a7928e Mon Sep 17 00:00:00 2001 From: Paul Seal Date: Thu, 13 Feb 2020 08:07:46 +0000 Subject: [PATCH 27/55] Change the icon in the Document Types Tree to be the chosen icon instead of a default one. (#7358) * - changed the icon in the document types tree to be the icon chose rather than the default doc type icon * - rendered icons for media types and member types * - used null coalescing for icon setting for better null handling Co-authored-by: paulmoriyama <48755798+paulmoriyama@users.noreply.github.com> --- src/Umbraco.Web/Trees/ContentTypeTreeController.cs | 9 ++++++--- src/Umbraco.Web/Trees/MediaTypeTreeController.cs | 9 +++++++-- src/Umbraco.Web/Trees/MemberTypeTreeController.cs | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs index e8f8fb9f75..ece16229b2 100644 --- a/src/Umbraco.Web/Trees/ContentTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/ContentTypeTreeController.cs @@ -69,15 +69,18 @@ namespace Umbraco.Web.Trees .OrderBy(entity => entity.Name) .Select(dt => { + // get the content type here so we can get the icon from it to use when we create the tree node + // and we can enrich the result with content type data that's not available in the entity service output + var contentType = contentTypes[dt.Id]; + // since 7.4+ child type creation is enabled by a config option. It defaults to on, but can be disabled if we decide to. // need this check to keep supporting sites where children have already been created. var hasChildren = dt.HasChildren; - var node = CreateTreeNode(dt, Constants.ObjectTypes.DocumentType, id, queryStrings, Constants.Icons.ContentType, hasChildren); + var node = CreateTreeNode(dt, Constants.ObjectTypes.DocumentType, id, queryStrings, contentType?.Icon ?? Constants.Icons.ContentType, hasChildren); node.Path = dt.Path; - // enrich the result with content type data that's not available in the entity service output - var contentType = contentTypes[dt.Id]; + // now we can enrich the result with content type data that's not available in the entity service output node.Alias = contentType.Alias; node.AdditionalData["isElement"] = contentType.IsElement; diff --git a/src/Umbraco.Web/Trees/MediaTypeTreeController.cs b/src/Umbraco.Web/Trees/MediaTypeTreeController.cs index 3d0046c319..7a9a80c8fc 100644 --- a/src/Umbraco.Web/Trees/MediaTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/MediaTypeTreeController.cs @@ -25,10 +25,12 @@ namespace Umbraco.Web.Trees public class MediaTypeTreeController : TreeController, ISearchableTree { private readonly UmbracoTreeSearcher _treeSearcher; + private readonly IMediaTypeService _mediaTypeService; - public MediaTypeTreeController(UmbracoTreeSearcher treeSearcher, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) + public MediaTypeTreeController(UmbracoTreeSearcher treeSearcher, IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoHelper umbracoHelper, IMediaTypeService mediaTypeService) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoHelper) { _treeSearcher = treeSearcher; + _mediaTypeService = mediaTypeService; } protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings) @@ -54,6 +56,8 @@ namespace Umbraco.Web.Trees // if the request is for folders only then just return if (queryStrings["foldersonly"].IsNullOrWhiteSpace() == false && queryStrings["foldersonly"] == "1") return nodes; + var mediaTypes = _mediaTypeService.GetAll(); + nodes.AddRange( Services.EntityService.GetChildren(intId.Result, UmbracoObjectTypes.MediaType) .OrderBy(entity => entity.Name) @@ -62,7 +66,8 @@ namespace Umbraco.Web.Trees // since 7.4+ child type creation is enabled by a config option. It defaults to on, but can be disabled if we decide to. // need this check to keep supporting sites where children have already been created. var hasChildren = dt.HasChildren; - var node = CreateTreeNode(dt, Constants.ObjectTypes.MediaType, id, queryStrings, Constants.Icons.MediaType, hasChildren); + var mt = mediaTypes.FirstOrDefault(x => x.Id == dt.Id); + var node = CreateTreeNode(dt, Constants.ObjectTypes.MediaType, id, queryStrings, mt?.Icon ?? Constants.Icons.MediaType, hasChildren); node.Path = dt.Path; return node; diff --git a/src/Umbraco.Web/Trees/MemberTypeTreeController.cs b/src/Umbraco.Web/Trees/MemberTypeTreeController.cs index 2046baf2d3..5db9088f20 100644 --- a/src/Umbraco.Web/Trees/MemberTypeTreeController.cs +++ b/src/Umbraco.Web/Trees/MemberTypeTreeController.cs @@ -33,7 +33,7 @@ namespace Umbraco.Web.Trees { return Services.MemberTypeService.GetAll() .OrderBy(x => x.Name) - .Select(dt => CreateTreeNode(dt, Constants.ObjectTypes.MemberType, id, queryStrings, Constants.Icons.MemberType, false)); + .Select(dt => CreateTreeNode(dt, Constants.ObjectTypes.MemberType, id, queryStrings, dt?.Icon ?? Constants.Icons.MemberType, false)); } public IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null) From 68ee537520cee054adbb5ca1151a7a7caf99aaab Mon Sep 17 00:00:00 2001 From: Poornima Nayar Date: Thu, 13 Feb 2020 08:10:06 +0000 Subject: [PATCH 28/55] Accessibility improvements to user group screen (#7414) --- .../components/users/umb-user-preview.html | 18 ++++++++---------- .../src/views/users/group.html | 3 +++ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/users/umb-user-preview.html b/src/Umbraco.Web.UI.Client/src/views/components/users/umb-user-preview.html index 32aa5ed1a2..014297ae51 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/users/umb-user-preview.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/users/umb-user-preview.html @@ -1,12 +1,11 @@
      - +
      @@ -15,7 +14,6 @@
      - Remove -
      - -
      \ No newline at end of file + +
      + diff --git a/src/Umbraco.Web.UI.Client/src/views/users/group.html b/src/Umbraco.Web.UI.Client/src/views/users/group.html index 8333528ddd..eae6dbd75c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/group.html +++ b/src/Umbraco.Web.UI.Client/src/views/users/group.html @@ -60,6 +60,7 @@ on-remove="vm.clearStartNode('content')"> + + @@ -82,6 +84,7 @@ on-remove="vm.clearStartNode('media')"> +