From 47986ec0f59a6f73544ac312739c4a79aa1fd66d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 30 Jul 2020 15:01:29 +0200 Subject: [PATCH 01/76] limit control-label effect to the first control-label, these 3 new lines covers all cases that i could find in CMS. --- src/Umbraco.Web.UI.Client/src/less/mixins.less | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/mixins.less b/src/Umbraco.Web.UI.Client/src/less/mixins.less index a87080a326cb..9739a90dae7a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/mixins.less +++ b/src/Umbraco.Web.UI.Client/src/less/mixins.less @@ -138,7 +138,9 @@ // additional targetting of the ng-invalid class. .formFieldState(@textColor: @gray-4, @borderColor: @gray-7, @backgroundColor: @gray-10) { // Set the text color - .control-label, + > .control-label, + > .umb-el-wrap > .control-label, + > .umb-el-wrap > .control-header > .control-label, .help-block, .help-inline { color: @textColor; From 55805eabc3ab87571f23b9f40e60cc8fa4b7ea6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 30 Jul 2020 15:26:40 +0200 Subject: [PATCH 02/76] make the required-star as bold as possible. --- src/Umbraco.Web.UI.Client/src/less/main.less | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/less/main.less b/src/Umbraco.Web.UI.Client/src/less/main.less index ce20b8dc88f5..2354e96d38c7 100644 --- a/src/Umbraco.Web.UI.Client/src/less/main.less +++ b/src/Umbraco.Web.UI.Client/src/less/main.less @@ -272,6 +272,7 @@ label:not([for]) { /* CONTROL VALIDATION */ .umb-control-required { color: @controlRequiredColor; + font-weight: 900; } .controls-row { From 33afbb8af6c4cb9127d46a36d447adb3e99b69b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 30 Jul 2020 16:13:22 +0200 Subject: [PATCH 03/76] added validation-error badge to navigation item --- .../src/less/components/umb-editor-navigation-item.less | 8 ++++++++ .../components/editor/umb-editor-navigation-item.html | 1 + 2 files changed, 9 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less index cb673e3c6f79..c2f3e0f04d15 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less @@ -101,6 +101,10 @@ height: 12px; min-width: 12px; } + &.--error-badge { + display: none; + font-weight: 900; + } } &-text { @@ -191,4 +195,8 @@ &::before { background-color: @red; } + .badge.--error-badge { + display: block; + } + } diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation-item.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation-item.html index 484e0175c560..9e5669f443e4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation-item.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation-item.html @@ -9,6 +9,7 @@ {{ vm.item.name }}
{{vm.item.badge.count}}
+
!
@param {string} name The content name. +@param {boolean=} nameRequired Require name to be defined. (True by default) @param {array=} tabs Array of tabs. See example above. @param {array=} navigation Array of sub views. See example above. @param {boolean=} nameLocked Set to true to lock the name. @@ -199,7 +200,7 @@ Use this directive to construct a header inside the main editor window. @param {boolean=} hideAlias Set to true to hide alias. @param {string=} description Add a description to the content. @param {boolean=} hideDescription Set to true to hide description. -@param {boolean=} setpagetitle If true the page title will be set to reflect the type of data the header is working with +@param {boolean=} setpagetitle If true the page title will be set to reflect the type of data the header is working with @param {string=} editorfor The localization to use to aid accessibility on the edit and create screen **/ @@ -207,7 +208,7 @@ Use this directive to construct a header inside the main editor window. 'use strict'; function EditorHeaderDirective(editorService, localizationService, editorState, $rootScope) { - + function link(scope, $injector) { scope.vm = {}; @@ -329,11 +330,11 @@ Use this directive to construct a header inside the main editor window. } scope.accessibility.a11yMessageVisible = !isEmptyOrSpaces(scope.accessibility.a11yMessage); scope.accessibility.a11yNameVisible = !isEmptyOrSpaces(scope.accessibility.a11yName); - + }); } - + function isEmptyOrSpaces(str) { return str === null || str===undefined || str.trim ===''; @@ -348,7 +349,7 @@ Use this directive to construct a header inside the main editor window. }); } - + var directive = { transclude: true, @@ -358,6 +359,7 @@ Use this directive to construct a header inside the main editor window. scope: { name: "=", nameLocked: "=", + nameRequired: "=?", menu: "=", hideActionsMenu: " From 2b73b3ddadcb13520e2b6e9858d68b8360ffe70e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 13 Aug 2020 13:12:07 +0200 Subject: [PATCH 42/76] include PublishedPendingChanges as Published state. --- .../content/overlays/publish.controller.js | 21 ++++++++++--------- .../src/views/content/overlays/publish.html | 15 ++++++------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js index decf05be5f94..37f005cd4778 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.controller.js @@ -11,13 +11,13 @@ /** Returns true if publish meets the requirements of mandatory languages */ function canPublish() { - + var hasSomethingToPublish = false; for (var i = 0; i < vm.variants.length; i++) { var variant = vm.variants[i]; - // if varaint is mandatory and not already published: + // if varaint is mandatory and not already published, then we require it to be set to publish: if (variant.publish === false && notPublishedMandatoryFilter(variant)) { return false; } @@ -39,8 +39,9 @@ function hasAnyDataFilter(variant) { - if (variant.name == null || variant.name.length === 0) { - return false; + // if we have a name, then we have data. + if (variant.name != null && variant.name.length > 0) { + return true; } if(variant.isDirty === true) { @@ -77,7 +78,7 @@ } function notPublishedMandatoryFilter(variant) { - return variant.state !== "Published" && isMandatoryFilter(variant); + return variant.state !== "Published" && variant.state !== "PublishedPendingChanges" && isMandatoryFilter(variant); } function isMandatoryFilter(variant) { //determine a variant is 'dirty' (meaning it will show up as publish-able) if it's @@ -98,11 +99,11 @@ vm.variants = $scope.model.variants; _.each(vm.variants, (variant) => { - + // reset to not be published variant.publish = false; variant.save = false; - + variant.isMandatory = isMandatoryFilter(variant); // If we have a variant thats not in the state of NotCreated, then we know we have adata and its not a new content node. @@ -112,12 +113,12 @@ }); _.each(vm.variants, (variant) => { - + // if this is a new node and we have data on this variant. if(vm.isNew === true && hasAnyDataFilter(variant)) { variant.save = true; } - + }); vm.availableVariants = vm.variants.filter(publishableVariantFilter); @@ -139,7 +140,7 @@ if (a.language.name < b.language.name) { return 1; } - } + } if (a.segment && b.segment) { if (a.segment > b.segment) { return -1; diff --git a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html index 71e19651d601..c3e0b90f5f09 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html @@ -21,19 +21,16 @@ on-change="vm.changeSelection(variant)" server-validation-field="{{variant.htmlId}}"> - - - * - - - - — {{variant.language.name}} - * + + + + — {{variant.language.name}} + * - - + {{publishVariantSelectorForm.publishVariantSelector.errorMsg}} From dde735f75cc96979f3707743fa5c1f1468906e79 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 13 Aug 2020 14:33:19 +0200 Subject: [PATCH 43/76] Sync some dependencies that have been updated in v8/contrib --- src/Umbraco.Web.UI.Client/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 21445e3cb331..454d081fe793 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -38,11 +38,11 @@ "lazyload-js": "1.0.0", "moment": "2.22.2", "ng-file-upload": "12.2.13", - "nouislider": "14.4.0", + "nouislider": "14.6.0", "npm": "^6.14.7", "signalr": "2.4.0", "spectrum-colorpicker": "1.8.0", - "tinymce": "4.9.10", + "tinymce": "4.9.11", "typeahead.js": "0.11.1", "underscore": "1.9.1" }, @@ -78,7 +78,7 @@ "karma-phantomjs-launcher": "1.0.4", "karma-spec-reporter": "0.0.32", "less": "3.10.3", - "lodash": "4.17.15", + "lodash": "4.17.19", "marked": "^0.7.0", "merge-stream": "2.0.0", "run-sequence": "2.2.1" From 6d6f525343c9f3794063cd96e78a36b39893540c Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Tue, 18 Aug 2020 12:43:29 +0100 Subject: [PATCH 44/76] Fix to ensure we use virtual paths for any blocks with custom views (#8597) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Niels Lyngsø Co-authored-by: Shannon --- .../services/umbrequesthelper.service.js | 31 ++++++++++--------- ...t.blockconfiguration.overlay.controller.js | 7 +++-- .../blocklist/umbblocklistblock.component.js | 23 +++++++------- .../services/umb-request-helper.spec.js | 28 +++++++++++++++++ 4 files changed, 59 insertions(+), 30 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js index 7b43b239eadf..90125e7de642 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js @@ -15,7 +15,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe * * @description * This will convert a virtual path (i.e. ~/App_Plugins/Blah/Test.html ) to an absolute path - * + * * @param {string} a virtual path, if this is already an absolute path it will just be returned, if this is a relative path an exception will be thrown */ convertVirtualToAbsolutePath: function(virtualPath) { @@ -31,6 +31,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe return Umbraco.Sys.ServerVariables.application.applicationPath + virtualPath.trimStart("~/"); }, + /** * @ngdoc method * @name umbraco.services.umbRequestHelper#dictionaryToQueryString @@ -39,7 +40,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe * * @description * This will turn an array of key/value pairs or a standard dictionary into a query string - * + * * @param {Array} queryStrings An array of key/value pairs */ dictionaryToQueryString: function (queryStrings) { @@ -76,9 +77,9 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe * * @description * This will return the webapi Url for the requested key based on the servervariables collection - * + * * @param {string} apiName The webapi name that is found in the servervariables["umbracoUrls"] dictionary - * @param {string} actionName The webapi action name + * @param {string} actionName The webapi action name * @param {object} queryStrings Can be either a string or an array containing key/value pairs */ getApiUrl: function (apiName, actionName, queryStrings) { @@ -103,7 +104,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe * * @description * This returns a promise with an underlying http call, it is a helper method to reduce - * the amount of duplicate code needed to query http resources and automatically handle any + * the amount of duplicate code needed to query http resources and automatically handle any * Http errors. See /docs/source/using-promises-resources.md * * @param {object} opts A mixed object which can either be a string representing the error message to be @@ -117,7 +118,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe * The error callback must return an object containing: {errorMsg: errorMessage, data: originalData, status: status } */ resourcePromise: function (httpPromise, opts) { - + /** The default success callback used if one is not supplied in the opts */ function defaultSuccess(data, status, headers, config) { //when it's successful, just return the data @@ -151,7 +152,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe return httpPromise.then(function (response) { - //invoke the callback + //invoke the callback var result = callbacks.success.apply(this, [response.data, response.status, response.headers, response.config]); formHelper.showNotifications(response.data); @@ -183,7 +184,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe overlayService.ysod(error); } else { - //show a simple error notification + //show a simple error notification notificationsService.error("Server error", "Contact administrator, see log for full details.
" + result.errorMsg + ""); } @@ -209,7 +210,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe * * @description * Used for saving content/media/members specifically - * + * * @param {Object} args arguments object * @returns {Promise} http promise object. */ @@ -233,7 +234,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe if (args.showNotifications === null || args.showNotifications === undefined) { args.showNotifications = true; } - + //save the active tab id so we can set it when the data is returned. var activeTab = _.find(args.content.tabs, function (item) { return item.active; @@ -300,7 +301,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe overlayService.ysod(error); } else { - //show a simple error notification + //show a simple error notification notificationsService.error("Server error", "Contact administrator, see log for full details.
" + response.data.ExceptionMessage + ""); } @@ -331,7 +332,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe }); } else if (!jsonData.key || !jsonData.value) { throw "jsonData object must have both a key and a value property"; } - + return $http({ method: 'POST', url: url, @@ -366,7 +367,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe return $q.reject(response); }); }, - + /** * @ngdoc method * @name umbraco.resources.contentResource#downloadFile @@ -374,7 +375,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe * * @description * Downloads a file to the client using AJAX/XHR - * + * * @param {string} httpPath the path (url) to the resource being downloaded * @returns {Promise} http promise object. */ @@ -388,7 +389,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe // Use an arraybuffer return $http.get(httpPath, { responseType: 'arraybuffer' }) .then(function (response) { - + var octetStreamMime = 'application/octet-stream'; var success = false; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js index b1937e718d76..48c21b4009ab 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/prevalue/blocklist.blockconfiguration.overlay.controller.js @@ -160,7 +160,7 @@ }, select: function (node) { const filepath = decodeURIComponent(node.id.replace(/\+/g, " ")); - block.view = filepath; + block.view = "~/" + filepath; editorService.close(); }, close: function () { @@ -206,7 +206,7 @@ }, select: function (node) { const filepath = decodeURIComponent(node.id.replace(/\+/g, " ")); - block.stylesheet = filepath; + block.stylesheet = "~/" + filepath; editorService.close(); }, close: function () { @@ -252,7 +252,8 @@ return !(i.name.indexOf(".jpg") !== -1 || i.name.indexOf(".jpeg") !== -1 || i.name.indexOf(".png") !== -1 || i.name.indexOf(".svg") !== -1 || i.name.indexOf(".webp") !== -1 || i.name.indexOf(".gif") !== -1); }, select: function (file) { - block.thumbnail = file.name; + const id = decodeURIComponent(file.id.replace(/\+/g, " ")); + block.thumbnail = "~/" + id; editorService.close(); }, close: function () { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbblocklistblock.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbblocklistblock.component.js index 4474dbd55c42..64fd40459dea 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbblocklistblock.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbblocklistblock.component.js @@ -5,11 +5,11 @@ * @ngdoc directive * @name umbraco.directives.directive:umbBlockListBlock * @description - * The component to render the view for a block. + * The component to render the view for a block. * If a stylesheet is used then this uses a ShadowDom to make a scoped element. * This way the backoffice styling does not collide with the block style. */ - + angular .module("umbraco") .component("umbBlockListBlock", { @@ -29,16 +29,16 @@ } ); - function BlockListBlockController($scope, $compile, $element) { + function BlockListBlockController($scope, $compile, $element, umbRequestHelper) { var model = this; model.$onInit = function () { - // This is ugly and is only necessary because we are not using components and instead + // This is ugly and is only necessary because we are not using components and instead // relying on ng-include. It is definitely possible to compile the contents - // of the view into the DOM using $templateCache and $http instead of using - // ng - include which means that the controllerAs flows directly to the view. - // This would mean that any custom components would need to be updated instead of relying on $scope. - // Guess we'll leave it for now but means all things need to be copied to the $scope and then all + // of the view into the DOM using $templateCache and $http instead of using + // ng - include which means that the controllerAs flows directly to the view. + // This would mean that any custom components would need to be updated instead of relying on $scope. + // Guess we'll leave it for now but means all things need to be copied to the $scope and then all // primitives need to be watched. $scope.block = model.block; @@ -48,8 +48,7 @@ $scope.valFormManager = model.valFormManager; if (model.stylesheet) { - // TODO: Not sure why this needs a prefixed /? this means it will never work in a virtual directory - model.stylesheet = "/" + model.stylesheet; + model.stylesheet = umbRequestHelper.convertVirtualToAbsolutePath(model.stylesheet); var shadowRoot = $element[0].attachShadow({ mode: 'open' }); shadowRoot.innerHTML = `