From 6cf697acb2ac38de4de78de15eef342b44455b59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 23 Oct 2019 11:48:13 +0200 Subject: [PATCH 01/26] Added property actions button --- src/Umbraco.Web.UI.Client/src/less/belle.less | 1 + .../less/components/umb-property-actions.less | 45 ++++++++++++++ .../umb-property-actions.html | 12 ++++ .../umbpropertyactions.component.js | 62 +++++++++++++++++++ .../components/property/umb-property.html | 3 + 5 files changed, 123 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umb-property-actions.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umbpropertyactions.component.js diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index 83d254c73cc0..e36a55bca024 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -137,6 +137,7 @@ @import "components/umb-grid.less"; @import "components/umb-empty-state.less"; @import "components/umb-property-editor.less"; +@import "components/umb-property-actions.less"; @import "components/umb-color-swatches.less"; @import "components/check-circle.less"; @import "components/umb-file-icon.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less new file mode 100644 index 000000000000..940daccbb692 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less @@ -0,0 +1,45 @@ +.umb-property-actions__toggle { + position: relative; + display: flex; + flex: 0 0 auto; + padding: 6px 6px; + text-align: center; + cursor: pointer; + border-radius: 3px; + + background-color: @ui-action-hover; + + i { + height: 3px !important; + width: 3px !important; + border-radius: 3px; + background: @ui-action-type; + display: inline-block; + margin: 0 2px 0 0; + + &:last-child { + margin: 0; + } + } + + &:hover { + i { + background: @ui-action-type-hover; + } + } +} + +.umb-property .umb-property-actions__toggle { + margin-top: 2px; + opacity: 0; + transition: opacity 120ms; +} +.umb-property:hover .umb-property-actions__toggle, +.umb-property .umb-property-actions__toggle:focus { + opacity: 1; +} + +.umb-property-actions .dropdown-menu { + left: auto; + top: auto; +} diff --git a/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umb-property-actions.html b/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umb-property-actions.html new file mode 100644 index 000000000000..8d2134bc37eb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umb-property-actions.html @@ -0,0 +1,12 @@ +
+ + + +
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umbpropertyactions.component.js b/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umbpropertyactions.component.js new file mode 100644 index 000000000000..7aad8f536109 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umbpropertyactions.component.js @@ -0,0 +1,62 @@ +(function () { + 'use strict'; + + /** + * A component to render the property action toggle + */ + + function umbPropertyActionsController(keyboardService) { + + var vm = this; + + vm.isOpen = false; + + function initDropDown() { + keyboardService.bind("esc", function() { + navigationService.hideNavigation(); + }); + } + function destroyDropDown() { + keyboardService.unbind("esc"); + } + + vm.toggle = function() { + if (vm.isOpen === true) { + vm.close(); + } else { + vm.open(); + } + } + vm.open = function() { + vm.isOpen = true; + initDropDown(); + } + vm.close = function() { + vm.isOpen = false; + destroyDropDown(); + } + + vm.executeAction = function(action) { + action.method(); + } + + vm.$onDestroy = function () { + if (vm.isOpen === true) { + destroyDropDown(); + } + } + + } + + var umbPropertyActionsComponent = { + templateUrl: 'views/components/property/property-actions/umb-property-actions.html', + bindings: { + actions: "<" + }, + controllerAs: 'vm', + controller: umbPropertyActionsController + }; + + angular.module('umbraco.directives').component('umbPropertyActions', umbPropertyActionsComponent); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property.html b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property.html index 9d2588484c16..4a7de0d8a76c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property.html @@ -18,6 +18,9 @@ * + + +
From 88a34f5bcd37f6b0f2efd37f0a879f92d99d6ff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 23 Oct 2019 14:28:06 +0200 Subject: [PATCH 02/26] current state, not complete. --- .../property/umbproperty.directive.js | 9 + .../src/common/services/clipboard.service.js | 462 ++++++++++-------- .../less/components/umb-property-actions.less | 2 +- .../umb-property-actions.html | 2 +- .../components/property/umb-property.html | 4 +- .../nestedcontent/nestedcontent.controller.js | 24 + 6 files changed, 296 insertions(+), 207 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js index 302378b8c08d..182aa664d482 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js @@ -32,6 +32,15 @@ angular.module("umbraco.directives") self.setPropertyError = function (errorMsg) { $scope.property.propertyErrorMessage = errorMsg; }; + + $scope.$on("ExposePropertyEditorAPI", function(event, api) { + + //avoid eventual parent properties to capture this. + event.stopPropagation(); + + $scope.propertyActions = api.propertyActions; + }); + } }; }); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js b/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js index 647133f0b76b..519bc4791e1c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js @@ -1,203 +1,259 @@ -/** - * @ngdoc service - * @name umbraco.services.clipboardService - * - * @requires notificationsService - * @requires eventsService - * - * @description - * Service to handle clipboard in general across the application. Responsible for handling the data both storing and retrive. - * The service has a set way for defining a data-set by a entryType and alias, which later will be used to retrive the posible entries for a paste scenario. - * - */ -function clipboardService(notificationsService, eventsService, localStorageService) { - - - var STORAGE_KEY = "umbClipboardService"; - - var retriveStorage = function() { - if (localStorageService.isSupported === false) { - return null; - } - var dataJSON; - var dataString = localStorageService.get(STORAGE_KEY); - if (dataString != null) { - dataJSON = JSON.parse(dataString); - } - - if(dataJSON == null) { - dataJSON = new Object(); - } - - if(dataJSON.entries === undefined) { - dataJSON.entries = []; - } - - return dataJSON; - } - - var saveStorage = function(storage) { - var storageString = JSON.stringify(storage); - - try { - var storageJSON = JSON.parse(storageString); - localStorageService.set(STORAGE_KEY, storageString); - - eventsService.emit("clipboardService.storageUpdate"); - - return true; - } catch(e) { - return false; - } - - return false; - } - - - var service = {}; - - /** - * @ngdoc method - * @name umbraco.services.clipboardService#copy - * @methodOf umbraco.services.clipboardService - * - * @param {string} type A string defining the type of data to storing, example: 'elementType', 'contentNode' - * @param {string} alias A string defining the alias of the data to store, example: 'product' - * @param {object} data A object containing the properties to be saved. - * - * @description - * Saves a single JS-object with a type and alias to the clipboard. - */ - service.copy = function(type, alias, data) { - - var storage = retriveStorage(); - - var shallowCloneData = Object.assign({}, data);// Notice only a shallow copy, since we dont need to deep copy. (that will happen when storing the data) - delete shallowCloneData.key; - delete shallowCloneData.$$hashKey; - - var key = data.key || data.$$hashKey || console.error("missing unique key for this content"); - - // remove previous copies of this entry: - storage.entries = storage.entries.filter( - (entry) => { - return entry.unique !== key; - } - ); - - var entry = {unique:key, type:type, alias:alias, data:shallowCloneData}; - storage.entries.push(entry); - - if (saveStorage(storage) === true) { - notificationsService.success("Clipboard", "Copied to clipboard."); - } else { - notificationsService.success("Clipboard", "Couldnt copy this data to clipboard."); - } - - }; - - - /** - * @ngdoc method - * @name umbraco.services.supportsCopy#supported - * @methodOf umbraco.services.clipboardService - * - * @description - * Determins wether the current browser is able to performe its actions. - */ - service.isSupported = function() { - return localStorageService.isSupported; - }; - - /** - * @ngdoc method - * @name umbraco.services.supportsCopy#hasEntriesOfType - * @methodOf umbraco.services.clipboardService - * - * @param {string} type A string defining the type of data test for. - * @param {string} aliases A array of strings providing the alias of the data you want to test for. - * - * @description - * Determines whether the current clipboard has entries that match a given type and one of the aliases. - */ - service.hasEntriesOfType = function(type, aliases) { - - if(service.retriveEntriesOfType(type, aliases).length > 0) { - return true; - } - - return false; - }; - - /** - * @ngdoc method - * @name umbraco.services.supportsCopy#retriveEntriesOfType - * @methodOf umbraco.services.clipboardService - * - * @param {string} type A string defining the type of data to recive. - * @param {string} aliases A array of strings providing the alias of the data you want to recive. - * - * @description - * Returns an array of entries matching the given type and one of the provided aliases. - */ - service.retriveEntriesOfType = function(type, aliases) { - - var storage = retriveStorage(); - - // Find entries that are fulfilling the criteria for this nodeType and nodeTypesAliases. - var filteretEntries = storage.entries.filter( - (entry) => { - return (entry.type === type && aliases.filter(alias => alias === entry.alias).length > 0); - } - ); - - return filteretEntries; - }; - - /** - * @ngdoc method - * @name umbraco.services.supportsCopy#retriveEntriesOfType - * @methodOf umbraco.services.clipboardService - * - * @param {string} type A string defining the type of data to recive. - * @param {string} aliases A array of strings providing the alias of the data you want to recive. - * - * @description - * Returns an array of data of entries matching the given type and one of the provided aliases. - */ - service.retriveDataOfType = function(type, aliases) { - return service.retriveEntriesOfType(type, aliases).map((x) => x.data); - }; - - /** - * @ngdoc method - * @name umbraco.services.supportsCopy#retriveEntriesOfType - * @methodOf umbraco.services.clipboardService - * - * @param {string} type A string defining the type of data to remove. - * @param {string} aliases A array of strings providing the alias of the data you want to remove. - * - * @description - * Removes entries matching the given type and one of the provided aliases. - */ - service.clearEntriesOfType = function(type, aliases) { - - var storage = retriveStorage(); - - // Find entries that are NOT fulfilling the criteria for this nodeType and nodeTypesAliases. - var filteretEntries = storage.entries.filter( - (entry) => { - return !(entry.type === type && aliases.filter(alias => alias === entry.alias).length > 0); - } - ); - - storage.entries = filteretEntries; - - saveStorage(storage); - }; - - - - return service; -} -angular.module("umbraco.services").factory("clipboardService", clipboardService); +/** + * @ngdoc service + * @name umbraco.services.clipboardService + * + * @requires notificationsService + * @requires eventsService + * + * @description + * Service to handle clipboard in general across the application. Responsible for handling the data both storing and retrive. + * The service has a set way for defining a data-set by a entryType and alias, which later will be used to retrive the posible entries for a paste scenario. + * + */ +function clipboardService(notificationsService, eventsService, localStorageService) { + + + var STORAGE_KEY = "umbClipboardService"; + + var retriveStorage = function() { + if (localStorageService.isSupported === false) { + return null; + } + var dataJSON; + var dataString = localStorageService.get(STORAGE_KEY); + if (dataString != null) { + dataJSON = JSON.parse(dataString); + } + + if(dataJSON == null) { + dataJSON = new Object(); + } + + if(dataJSON.entries === undefined) { + dataJSON.entries = []; + } + + return dataJSON; + } + + var saveStorage = function(storage) { + var storageString = JSON.stringify(storage); + + try { + var storageJSON = JSON.parse(storageString); + localStorageService.set(STORAGE_KEY, storageString); + + eventsService.emit("clipboardService.storageUpdate"); + + return true; + } catch(e) { + return false; + } + + return false; + } + + var prepareEntryForStorage = function(entryData) { + + var shallowCloneData = Object.assign({}, entryData);// Notice only a shallow copy, since we dont need to deep copy. (that will happen when storing the data) + delete shallowCloneData.key; + delete shallowCloneData.$$hashKey; + + return shallowCloneData; + } + + + var service = {}; + + /** + * @ngdoc method + * @name umbraco.services.clipboardService#copy + * @methodOf umbraco.services.clipboardService + * + * @param {string} type A string defining the type of data to storing, example: 'elementType', 'contentNode' + * @param {string} alias A string defining the alias of the data to store, example: 'product' or ['banana', 'apple'] + * @param {object} data A object containing the properties to be saved. + * + * @description + * Saves a single JS-object with a type and alias to the clipboard. + */ + service.copy = function(type, alias, entryData) { + + var storage = retriveStorage(); + + var key = entryData.key || entryData.$$hashKey || console.error("missing unique key for this content"); + + // remove previous copies of this entry: + storage.entries = storage.entries.filter( + (entry) => { + return entry.unique !== key; + } + ); + + var entry = {unique:key, type:type, alias:alias, data:prepareEntryForStorage(entryData)}; + storage.entries.push(entry); + + if (saveStorage(storage) === true) { + notificationsService.success("Clipboard", "Copied to clipboard."); + } else { + notificationsService.success("Clipboard", "Couldnt copy this data to clipboard."); + } + + }; + + + /** + * @ngdoc method + * @name umbraco.services.clipboardService#copyArray + * @methodOf umbraco.services.clipboardService + * + * @param {string} type A string defining the type of data to storing, example: 'elementTypeArray', 'contentNodeArray' + * @param {string} aliases An array of strings defining the alias of the data to store, example: 'product' or ['banana', 'apple'] + * @param {object} entries An array of objects of objects containing the properties to be saved. + * @param {string} displayLabel A string or array of string defining the alias of the data to store, example: 'product' or ['banana', 'apple'] + * + * @description + * Saves a single JS-object with a type and alias to the clipboard. + */ + service.copyArray = function(type, aliases, entries, displayLabel, key) { + + var storage = retriveStorage(); + + // Clean up each entry + var copiedEntries = entries.filter( + (entry) => { + return prepareEntryForStorage(entry); + } + ); + + var entry = {unique:key, type:type, aliases:aliases, data:copiedEntries}; + storage.entries.push(entry); + + if (saveStorage(storage) === true) { + notificationsService.success("Clipboard", "Copied to clipboard."); + } else { + notificationsService.success("Clipboard", "Couldnt copy this data to clipboard."); + } + +}; + + + /** + * @ngdoc method + * @name umbraco.services.supportsCopy#supported + * @methodOf umbraco.services.clipboardService + * + * @description + * Determins wether the current browser is able to performe its actions. + */ + service.isSupported = function() { + return localStorageService.isSupported; + }; + + /** + * @ngdoc method + * @name umbraco.services.supportsCopy#hasEntriesOfType + * @methodOf umbraco.services.clipboardService + * + * @param {string} type A string defining the type of data test for. + * @param {string} aliases A array of strings providing the alias of the data you want to test for. + * + * @description + * Determines whether the current clipboard has entries that match a given type and one of the aliases. + */ + service.hasEntriesOfType = function(type, aliases) { + + if(service.retriveEntriesOfType(type, aliases).length > 0) { + return true; + } + + return false; + }; + + /** + * @ngdoc method + * @name umbraco.services.supportsCopy#retriveEntriesOfType + * @methodOf umbraco.services.clipboardService + * + * @param {string} type A string defining the type of data to recive. + * @param {string} aliases A array of strings providing the alias of the data you want to recive. + * + * @description + * Returns an array of entries matching the given type and one of the provided aliases. + */ + service.retriveEntriesOfType = function(type, allowedAliases) { + + var storage = retriveStorage(); + + // Find entries that are fulfilling the criteria for this nodeType and nodeTypesAliases. + var filteretEntries = storage.entries.filter( + (entry) => { + return ( + entry.type === type + && + (entry.alias && allowedAliases.filter(allowedAlias => allowedAlias === entry.alias).length > 0) + || + (entry.aliases && entry.aliases.filter(entryAlias => allowedAliases.filter(allowedAlias => allowedAlias === entryAlias).length > 0).length > 0) + ); + } + ); + + return filteretEntries; + }; + + /** + * @ngdoc method + * @name umbraco.services.supportsCopy#retriveEntriesOfType + * @methodOf umbraco.services.clipboardService + * + * @param {string} type A string defining the type of data to recive. + * @param {string} aliases A array of strings providing the alias of the data you want to recive. + * + * @description + * Returns an array of data of entries matching the given type and one of the provided aliases. + */ + service.retriveDataOfType = function(type, aliases) { + return service.retriveEntriesOfType(type, aliases).map((x) => x.data); + }; + + /** + * @ngdoc method + * @name umbraco.services.supportsCopy#retriveEntriesOfType + * @methodOf umbraco.services.clipboardService + * + * @param {string} type A string defining the type of data to remove. + * @param {string} aliases A array of strings providing the alias of the data you want to remove. + * + * @description + * Removes entries matching the given type and one of the provided aliases. + */ + service.clearEntriesOfType = function(type, aliases) { + + var storage = retriveStorage(); + + // Find entries that are NOT fulfilling the criteria for this nodeType and nodeTypesAliases. + var filteretEntries = storage.entries.filter( + (entry) => { + return !( + entry.type === type + && + (entry.alias && allowedAliases.filter(allowedAlias => allowedAlias === entry.alias).length > 0) + || + (entry.aliases && entry.aliases.filter(entryAlias => allowedAliases.filter(allowedAlias => allowedAlias === entryAlias).length > 0).length > 0) + ); + } + ); + + storage.entries = filteretEntries; + + saveStorage(storage); + }; + + + + return service; +} + + +angular.module("umbraco.services").factory("clipboardService", clipboardService); + diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less index 940daccbb692..997da7f79f39 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less @@ -30,7 +30,7 @@ } .umb-property .umb-property-actions__toggle { - margin-top: 2px; + margin-top: 10px; opacity: 0; transition: opacity 120ms; } diff --git a/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umb-property-actions.html b/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umb-property-actions.html index 8d2134bc37eb..a1bc3d904dc1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umb-property-actions.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umb-property-actions.html @@ -5,7 +5,7 @@
  • diff --git a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property.html b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property.html index 4a7de0d8a76c..17bd37e468eb 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/property/umb-property.html @@ -7,7 +7,7 @@
    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 536169778ca3..4c0906735d7f 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 @@ -390,6 +390,18 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop $event.stopPropagation(); } + var copyAllEntries = function() { + + syncCurrentNode(); + + var aliases = _.reduce($scope.nodes, function (node) { + return node.contentTypeAlias; + }); + + clipboardService.copyArray("elementTypeArray", aliases, $scope.nodes); + $event.stopPropagation(); + } + $scope.pasteFromClipboard = function(newNode) { if (newNode === undefined) { @@ -575,6 +587,18 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop $scope.realCurrentNode = newVal; }); + + $scope.propertyActions = [ + { + labelKey: 'actions_copy', + icon: 'documents', + method: copyAllEntries + } + ]; + + $scope.$emit("ExposePropertyEditorAPI", $scope);// must be executed at a state where the API is set. + + var unsubscribe = $scope.$on("formSubmitting", function (ev, args) { updateModel(); }); From a42fc8fc8e159fd327adfdac226875a540299961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 23 Oct 2019 15:23:23 +0200 Subject: [PATCH 03/26] work on copyArray feature for clipboardService --- .../src/common/services/clipboard.service.js | 33 ++++++++++++------- .../umb-property-actions.html | 2 +- .../nestedcontent/nestedcontent.controller.js | 27 ++++++++++----- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js b/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js index 519bc4791e1c..ea7ef8cf787b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js @@ -71,26 +71,27 @@ function clipboardService(notificationsService, eventsService, localStorageServi * @methodOf umbraco.services.clipboardService * * @param {string} type A string defining the type of data to storing, example: 'elementType', 'contentNode' - * @param {string} alias A string defining the alias of the data to store, example: 'product' or ['banana', 'apple'] - * @param {object} data A object containing the properties to be saved. + * @param {string} alias A string defining the alias of the data to store, example: 'product' + * @param {object} entry A object containing the properties to be saved, this could be the object of a ElementType, ContentNode, ... + * @param {string} displayLabel (optional) A string swetting the label to display when showing paste entries. * * @description * Saves a single JS-object with a type and alias to the clipboard. */ - service.copy = function(type, alias, entryData) { + service.copy = function(type, alias, entry, displayLabel) { var storage = retriveStorage(); - var key = entryData.key || entryData.$$hashKey || console.error("missing unique key for this content"); + var uniqueKey = entry.key || entry.$$hashKey || console.error("missing unique key for this content"); // remove previous copies of this entry: storage.entries = storage.entries.filter( (entry) => { - return entry.unique !== key; + return entry.unique !== uniqueKey; } ); - var entry = {unique:key, type:type, alias:alias, data:prepareEntryForStorage(entryData)}; + var entry = {unique:uniqueKey, type:type, alias:alias, data:prepareEntryForStorage(entry), label:displayLabel || entry.name}; storage.entries.push(entry); if (saveStorage(storage) === true) { @@ -108,15 +109,16 @@ function clipboardService(notificationsService, eventsService, localStorageServi * @methodOf umbraco.services.clipboardService * * @param {string} type A string defining the type of data to storing, example: 'elementTypeArray', 'contentNodeArray' - * @param {string} aliases An array of strings defining the alias of the data to store, example: 'product' or ['banana', 'apple'] - * @param {object} entries An array of objects of objects containing the properties to be saved. - * @param {string} displayLabel A string or array of string defining the alias of the data to store, example: 'product' or ['banana', 'apple'] + * @param {string} aliases An array of strings defining the alias of the data to store, example: ['banana', 'apple'] + * @param {object} entries An array of objects of objects containing the properties to be saved, example: [ElementType, ElementType, ...] + * @param {string} displayLabel A string setting the label to display when showing paste entries. + * @param {string} uniqueKey A string prodiving an identifier for this entry, existing entries with this key will be removed to ensure that you only have the latest copy of this data. * * @description * Saves a single JS-object with a type and alias to the clipboard. */ - service.copyArray = function(type, aliases, entries, displayLabel, key) { - + service.copyArray = function(type, aliases, entries, displayLabel, displayIcon, uniqueKey) { + var storage = retriveStorage(); // Clean up each entry @@ -126,7 +128,14 @@ function clipboardService(notificationsService, eventsService, localStorageServi } ); - var entry = {unique:key, type:type, aliases:aliases, data:copiedEntries}; + // remove previous copies of this entry: + storage.entries = storage.entries.filter( + (entry) => { + return entry.unique !== uniqueKey; + } + ); + + var entry = {unique:uniqueKey, type:type, aliases:aliases, data:copiedEntries, label:displayLabel, icon:displayIcon}; storage.entries.push(entry); if (saveStorage(storage) === true) { diff --git a/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umb-property-actions.html b/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umb-property-actions.html index a1bc3d904dc1..1492cbd82090 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umb-property-actions.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umb-property-actions.html @@ -3,7 +3,7 @@
    -
    +
    • From 5dd7eda2ab7c0c86da58f3fb8090821763ffabb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 28 Oct 2019 10:25:51 +0100 Subject: [PATCH 13/26] Revert change. --- src/Umbraco.Web.UI.Client/src/less/main.less | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/main.less b/src/Umbraco.Web.UI.Client/src/less/main.less index f5424b034837..86a1acbeae27 100644 --- a/src/Umbraco.Web.UI.Client/src/less/main.less +++ b/src/Umbraco.Web.UI.Client/src/less/main.less @@ -117,7 +117,6 @@ h5.-black { } .umb-control-group { position: relative; - margin-top: 20px; &::after { content: ''; display:block; From ed909e9f93e1a087596261dee0bfad1d8ff25f5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 28 Oct 2019 15:55:02 +0100 Subject: [PATCH 14/26] updated look + ability to disable a property-action --- .../property/umbproperty.directive.js | 8 +- .../common/services/propertyeditor.service.js | 8 +- src/Umbraco.Web.UI.Client/src/less/belle.less | 1 + .../src/less/components/umb-contextmenu.less | 74 +++++++++++++++++ .../less/components/umb-property-actions.less | 49 +++--------- .../umb-property-actions.html | 6 +- .../components/property/umb-property.html | 2 +- .../nestedcontent/nestedcontent.controller.js | 80 ++++++++++++------- 8 files changed, 150 insertions(+), 78 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/umb-contextmenu.less diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js index 6030efadf186..90fcc7630bcb 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js @@ -16,6 +16,9 @@ angular.module("umbraco.directives") replace: true, templateUrl: 'views/components/property/umb-property.html', link: function (scope) { + + scope.propertyEditorAPI = {}; + userService.getCurrentUser().then(function (u) { var isAdmin = u.userGroups.indexOf('admin') !== -1; scope.propertyAlias = (Umbraco.Sys.ServerVariables.isDebuggingEnabled === true || isAdmin) ? scope.property.alias : null; @@ -32,13 +35,14 @@ angular.module("umbraco.directives") self.setPropertyError = function (errorMsg) { $scope.property.propertyErrorMessage = errorMsg; }; - + var unsubscribe = $scope.$on("ExposePropertyEditorAPI", function(event, api) { //avoid eventual parent properties to capture this. event.stopPropagation(); - $scope.propertyActions = api.propertyActions; + $scope.propertyEditorAPI = api; + //$scope.propertyActions = api.propertyActions; }); $scope.$on("$destroy", function () { diff --git a/src/Umbraco.Web.UI.Client/src/common/services/propertyeditor.service.js b/src/Umbraco.Web.UI.Client/src/common/services/propertyeditor.service.js index 29ec641f3b54..0b24e78567fe 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/propertyeditor.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/propertyeditor.service.js @@ -10,12 +10,14 @@ * * @param {object} scope An object containing API for the PropertyEditor */ - function exposeAPI(scope) { + function exposeAPI(scope, api) { if (!scope) { throw "scope cannot be null"; } - - scope.$emit("ExposePropertyEditorAPI", scope); + if (!api) { + throw "api cannot be null"; + } + scope.$emit("ExposePropertyEditorAPI", api); } return { diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index e36a55bca024..74326d6dfeaa 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -129,6 +129,7 @@ @import "components/umb-media-grid.less"; @import "components/umb-folder-grid.less"; @import "components/umb-content-grid.less"; +@import "components/umb-contextmenu.less"; @import "components/umb-layout-selector.less"; @import "components/tooltip/umb-tooltip.less"; @import "components/tooltip/umb-tooltip-list.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-contextmenu.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-contextmenu.less new file mode 100644 index 000000000000..00d289f4d796 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-contextmenu.less @@ -0,0 +1,74 @@ +.umb-contextmenu { + margin: 0; + list-style: none; + user-select: none; + + overflow: hidden; + border-radius: 3px; + border: 1px solid @dropdownBorder; + .box-shadow(0 5px 20px rgba(0,0,0,.3)); + + .sep { + display: block; + border-top: 1px solid @gray-9; + + &:first-child { + border-top: none; + } + } + +} + +.umb-contextmenu-item { + + .icon { + font-size: 18px; + vertical-align: middle; + } + + .menu-label { + display: inline-block; + vertical-align: middle; + margin-left: 5px; + } + + button { + + position: relative; + + display: block; + font-weight: normal; + line-height: @baseLineHeight; + white-space: nowrap; + + background-color: @ui-option; + border: 0; + padding: 7px 12px; + color: @ui-option-type; + width: 100%; + + font-size: 14px; + text-align: left; + + &:hover { + text-decoration: none; + color: @ui-option-type-hover; + background-color: @ui-option-hover; + } + } + + &.-opens-dialog { + .menu-label:after { + // adds an ellipsis (...) after the menu label for actions that open a dialog + content: '\2026'; + } + } + button:disabled { + cursor: not-allowed; + color: @ui-option-disabled-type; + &:hover { + color: @ui-option-disabled-type-hover; + background-color: @ui-option; + } + } +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less index 5f693977f100..cc11baebb025 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less @@ -26,8 +26,6 @@ margin: 0; } } -} -.umb-property-actions__toggle { &:hover { i { background: @ui-action-type-hover; @@ -42,12 +40,13 @@ top: -15px; border-radius: 3px 3px 0 0; - border-top: 1px solid @dropdownBorder; - border-left: 1px solid @dropdownBorder; - border-right: 1px solid @dropdownBorder; border-top-left-radius: 3px; border-top-right-radius: 3px; + border: 1px solid @dropdownBorder; + + border-bottom: 1px solid @gray-9; + .box-shadow(0 5px 20px rgba(0,0,0,.3)); background-color: white; @@ -69,51 +68,25 @@ .umb-property-actions__menu { - display: block; - border-radius: 3px; - position: absolute; z-index: 1000; + display: block; + float: left; min-width: 160px; list-style: none; - ul > { - - border: 1px solid @dropdownBorder; - - border-top-right-radius: 3px; - border-bottom-left-radius: 3px; - border-bottom-right-radius: 3px; - - overflow: hidden; + .umb-contextmenu { - .box-shadow(0 5px 20px rgba(0,0,0,.3)); + border-top-left-radius: 0; + margin-top:1px; + } - ul > li > button { + .umb-contextmenu-item > button { - position: relative; z-index:2;// need to stay on top of menu-toggle-open shadow. - display: block; - font-weight: normal; - line-height: @baseLineHeight; - white-space: nowrap; - cursor:pointer; - - background: @ui-option; - border: 0; - padding: 8px 20px; - color: @ui-option-type; - width: 100%; - text-align: left; - - &:hover { - text-decoration: none; - color: @ui-option-type-hover; - background: @ui-option-hover; - } } } diff --git a/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umb-property-actions.html b/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umb-property-actions.html index be9b8e127665..ebab65d573f8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umb-property-actions.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/property/property-actions/umb-property-actions.html @@ -3,9 +3,9 @@ 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 7903a0306248..6efafadd7ace 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 @@ -211,6 +211,39 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop $scope.labels.content_createEmpty = data[1]; }); + + + var copyAllEntries = function() { + + syncCurrentNode(); + + // list aliases + var aliases = $scope.nodes.map((node) => node.contentTypeAlias); + + // remove dublicates + aliases = aliases.filter((item, index) => aliases.indexOf(item) === index); + + // Retrive variant name + var culture = $routeParams.cculture ? $routeParams.cculture : $routeParams.mculture; + var activeVariant = _.find(editorState.current.variants, function (v) { + return !v.language || v.language.culture === culture; + }); + + localizationService.localize("clipboard_labelForArrayOfItemsFrom", [$scope.model.label, activeVariant.name]).then(function(data) { + clipboardService.copyArray("elementTypeArray", aliases, $scope.nodes, data, "icon-thumbnail-list", $scope.model.id); + }); + } + + var CopyAllEntriesAction = { + labelKey: 'clipboard_labelForCopyAllEntries', + labelTokens: [$scope.model.label], + icon: 'documents', + method: copyAllEntries, + isDisabled: true + } + + + // helper to force the current form into the dirty state $scope.setDirty = function () { if ($scope.propertyForm) { @@ -473,26 +506,6 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop $event.stopPropagation(); } - var copyAllEntries = function() { - - syncCurrentNode(); - - // list aliases - var aliases = $scope.nodes.map((node) => node.contentTypeAlias); - - // remove dublicates - aliases = aliases.filter((item, index) => aliases.indexOf(item) === index); - - // Retrive variant name - var culture = $routeParams.cculture ? $routeParams.cculture : $routeParams.mculture; - var activeVariant = _.find(editorState.current.variants, function (v) { - return !v.language || v.language.culture === culture; - }); - - localizationService.localize("clipboard_labelForArrayOfItemsFrom", [$scope.model.label, activeVariant.name]).then(function(data) { - clipboardService.copyArray("elementTypeArray", aliases, $scope.nodes, data, "icon-thumbnail-list", $scope.model.id); - }); - } $scope.pasteFromClipboard = function(newNode) { @@ -600,6 +613,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop $scope.inited = true; + updatePropertyActionStates(); checkAbilityToPasteContent(); } } @@ -656,6 +670,9 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop return obj; } + + + function syncCurrentNode() { if ($scope.realCurrentNode) { $scope.$broadcast("ncSyncVal", { key: $scope.realCurrentNode.key }); @@ -672,6 +689,12 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop } $scope.model.value = newValues; } + + updatePropertyActionStates(); + } + + function updatePropertyActionStates() { + CopyAllEntriesAction.isDisabled = $scope.model.value.length === 0; } $scope.$watch("currentNode", function (newVal) { @@ -680,18 +703,13 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop }); - $scope.propertyActions = [ - { - labelKey: 'clipboard_labelForCopyAllEntries', - labelTokens: [$scope.model.label], - icon: 'documents', - method: copyAllEntries - } + var api = {}; + api.propertyActions = [ + CopyAllEntriesAction ]; - - //$scope.$emit("ExposePropertyEditorAPI", $scope);// must be executed at a state where the API is set. - propertyEditorService.exposeAPI($scope);// must be executed at a state where the API is set. - + + propertyEditorService.exposeAPI($scope, api);// must be executed at a state where the API is set. + var unsubscribe = $scope.$on("formSubmitting", function (ev, args) { updateModel(); }); From 1c5d8efe772e8b6d126adf13b4030ab914b67117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 28 Oct 2019 17:18:08 +0100 Subject: [PATCH 15/26] corrected variable name for property-action --- .../nestedcontent/nestedcontent.controller.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js index 6efafadd7ace..f0ed98d8bca6 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 @@ -234,7 +234,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop }); } - var CopyAllEntriesAction = { + var copyAllEntriesAction = { labelKey: 'clipboard_labelForCopyAllEntries', labelTokens: [$scope.model.label], icon: 'documents', @@ -694,7 +694,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop } function updatePropertyActionStates() { - CopyAllEntriesAction.isDisabled = $scope.model.value.length === 0; + copyAllEntriesAction.isDisabled = $scope.model.value.length === 0; } $scope.$watch("currentNode", function (newVal) { @@ -705,7 +705,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop var api = {}; api.propertyActions = [ - CopyAllEntriesAction + copyAllEntriesAction ]; propertyEditorService.exposeAPI($scope, api);// must be executed at a state where the API is set. From 11560aa138577174cc46e8ef960cb673ef14d227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 28 Oct 2019 17:21:58 +0100 Subject: [PATCH 16/26] sligthly darker line in the bottom to enhance the depth --- .../src/less/components/umb-contextmenu.less | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-contextmenu.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-contextmenu.less index 00d289f4d796..c0932ecdab4b 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-contextmenu.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-contextmenu.less @@ -7,6 +7,7 @@ border-radius: 3px; border: 1px solid @dropdownBorder; .box-shadow(0 5px 20px rgba(0,0,0,.3)); + border-bottom: 1px solid rgba(0,0,0,.25); .sep { display: block; From 1f954fb9bee228c4528bacf00d7597dc3f17cd11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 29 Oct 2019 09:55:59 +0100 Subject: [PATCH 17/26] sligthly less bottom border on contextmenu. --- .../src/less/components/umb-contextmenu.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-contextmenu.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-contextmenu.less index c0932ecdab4b..8512e2020d42 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-contextmenu.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-contextmenu.less @@ -7,7 +7,7 @@ border-radius: 3px; border: 1px solid @dropdownBorder; .box-shadow(0 5px 20px rgba(0,0,0,.3)); - border-bottom: 1px solid rgba(0,0,0,.25); + border-bottom: 1px solid rgba(0,0,0,.2); .sep { display: block; From 3a8123f00c5a1f8cfc9fa7acbc325b28255d5ccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 29 Oct 2019 11:26:35 +0100 Subject: [PATCH 18/26] Update src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js Removed comment Co-Authored-By: Warren Buckley --- .../directives/components/property/umbproperty.directive.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js index 90fcc7630bcb..06b9e51fba92 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbproperty.directive.js @@ -42,7 +42,6 @@ angular.module("umbraco.directives") event.stopPropagation(); $scope.propertyEditorAPI = api; - //$scope.propertyActions = api.propertyActions; }); $scope.$on("$destroy", function () { From 338c4b7bcfacb7a7c5a1529be32c1a0944261afc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 29 Oct 2019 12:50:47 +0100 Subject: [PATCH 19/26] Set notification to error + removed console.logs --- .../src/common/services/clipboard.service.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js b/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js index c62c960b7a07..f1bda350e50d 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js @@ -97,7 +97,7 @@ function clipboardService(notificationsService, eventsService, localStorageServi if (saveStorage(storage) === true) { notificationsService.success("Clipboard", "Copied to clipboard."); } else { - notificationsService.success("Clipboard", "Couldnt copy this data to clipboard."); + notificationsService.error("Clipboard", "Couldnt copy this data to clipboard."); } }; @@ -134,14 +134,12 @@ function clipboardService(notificationsService, eventsService, localStorageServi var entry = {unique:uniqueKey, type:type, aliases:aliases, data:copiedDatas, label:displayLabel, icon:displayIcon}; - console.log(entry); - storage.entries.push(entry); if (saveStorage(storage) === true) { notificationsService.success("Clipboard", "Copied to clipboard."); } else { - notificationsService.success("Clipboard", "Couldnt copy this data to clipboard."); + notificationsService.error("Clipboard", "Couldnt copy this data to clipboard."); } }; @@ -241,8 +239,6 @@ function clipboardService(notificationsService, eventsService, localStorageServi service.clearEntriesOfType = function(type, allowedAliases) { var storage = retriveStorage(); - - console.log("BEFORE: ", storage.entries) // Find entries that are NOT fulfilling the criteria for this nodeType and nodeTypesAliases. var filteretEntries = storage.entries.filter( @@ -260,8 +256,6 @@ function clipboardService(notificationsService, eventsService, localStorageServi ); storage.entries = filteretEntries; - - console.log("AFTER: ", storage.entries) saveStorage(storage); }; From 0c29d57ef9f385edc57c33fdc69a5141b51005df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 29 Oct 2019 14:54:31 +0100 Subject: [PATCH 20/26] ensured that all entry aliases meets the allowed aliases + refactored the test method --- .../src/common/services/clipboard.service.js | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js b/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js index f1bda350e50d..c3a1ba643219 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js @@ -61,6 +61,16 @@ function clipboardService(notificationsService, eventsService, localStorageServi return shallowCloneData; } + + var isEntryCompatible = function(entry, type, allowedAliases) { + return entry.type === type + && + ( + (entry.alias && allowedAliases.filter(allowedAlias => allowedAlias === entry.alias).length > 0) + || + (entry.aliases && entry.aliases.filter(entryAlias => allowedAliases.filter(allowedAlias => allowedAlias === entryAlias).length > 0).length === entry.aliases.length) + ); + } var service = {}; @@ -195,15 +205,7 @@ function clipboardService(notificationsService, eventsService, localStorageServi // Find entries that are fulfilling the criteria for this nodeType and nodeTypesAliases. var filteretEntries = storage.entries.filter( (entry) => { - return ( - entry.type === type - && - ( - (entry.alias && allowedAliases.filter(allowedAlias => allowedAlias === entry.alias).length > 0) - || - (entry.aliases && entry.aliases.filter(entryAlias => allowedAliases.filter(allowedAlias => allowedAlias === entryAlias).length > 0).length > 0) - ) - ); + return isEntryCompatible(entry, type, allowedAliases); } ); @@ -243,15 +245,7 @@ function clipboardService(notificationsService, eventsService, localStorageServi // Find entries that are NOT fulfilling the criteria for this nodeType and nodeTypesAliases. var filteretEntries = storage.entries.filter( (entry) => { - return !( - entry.type === type - && - ( - (entry.alias && allowedAliases.filter(allowedAlias => allowedAlias === entry.alias).length > 0) - || - (entry.aliases && entry.aliases.filter(entryAlias => allowedAliases.filter(allowedAlias => allowedAlias === entryAlias).length > 0).length > 0) - ) - ); + return !isEntryCompatible(entry, type, allowedAliases); } ); From 3d542acc423e7df3f1f44b9ac5d4bc4667875ae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 29 Oct 2019 15:24:23 +0100 Subject: [PATCH 21/26] Revert-style-hack that ensures that we only show property-actions on properties that are directly begin hovered --- .../src/less/components/umb-property-actions.less | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less index cc11baebb025..3ce284870ebf 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less @@ -65,6 +65,10 @@ .umb-property .umb-property-actions__toggle:focus { opacity: 1; } +// Revert-style-hack that ensures that we only show property-actions on properties that are directly begin hovered. +.umb-property:hover .umb-property:not(:hover) .umb-property-actions__toggle { + opacity: 0; +} .umb-property-actions__menu { From 4cf42bbb68c52d88209629726532012495ee5b59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 29 Oct 2019 17:38:02 +0100 Subject: [PATCH 22/26] Added specific styling to the DataType Delete dialog for better looks and overview --- src/Umbraco.Web.UI.Client/src/less/belle.less | 2 ++ .../umb-dialog-datatype-delete.less | 33 +++++++++++++++++++ .../src/views/datatypes/delete.html | 14 ++++---- 3 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/contextdialogs/umb-dialog-datatype-delete.less diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index 83d254c73cc0..245ad394acb1 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -187,6 +187,8 @@ @import "components/users/umb-user-preview.less"; @import "components/users/umb-user-picker-list.less"; +@import "components/contextdialogs/umb-dialog-datatype-delete.less"; + // Utilities @import "utilities/layout/_display.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/contextdialogs/umb-dialog-datatype-delete.less b/src/Umbraco.Web.UI.Client/src/less/components/contextdialogs/umb-dialog-datatype-delete.less new file mode 100644 index 000000000000..0e0b8f22bd52 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/contextdialogs/umb-dialog-datatype-delete.less @@ -0,0 +1,33 @@ +.umb-dialog-datatype-delete { + + + .umb-dialog-datatype-delete__table-head-column-name { + width: 140px; + } + + .umb-table-body__icon { + margin-right: 5px; + vertical-align: top; + display: inline-block; + } + + .table tbody td { + vertical-align: top; + } + .table tbody td > span { + margin: 5px 0; + vertical-align: middle; + } + .table tbody p { + line-height: 12px; + margin: 5px 0; + vertical-align: middle; + } + + .table tbody .icon { + vertical-align: top; + margin-right: 5px; + display: inline-block; + } + +} diff --git a/src/Umbraco.Web.UI.Client/src/views/datatypes/delete.html b/src/Umbraco.Web.UI.Client/src/views/datatypes/delete.html index 6c415e9f3887..ce2e75e742d2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/datatypes/delete.html +++ b/src/Umbraco.Web.UI.Client/src/views/datatypes/delete.html @@ -1,4 +1,4 @@ -
      +
      @@ -44,14 +44,14 @@
      - + - +
      NameName Properties
      {{::relation.name}}{{::property.name}}{{$last ? '' : ', '}}

      {{::property.name}}

      @@ -68,14 +68,14 @@
      - + - +
      NameName Properties
      {{::relation.name}}{{::property.name}}{{$last ? '' : ', '}}

      {{::property.name}}

      @@ -92,14 +92,14 @@
      - + - +
      NameName Properties
      {{::relation.name}}{{::property.name}}{{$last ? '' : ', '}}

      {{::property.name}}

      From 0e308e1ad02a9456a1d7b790bea2e036916b85fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 30 Oct 2019 08:58:47 +0100 Subject: [PATCH 23/26] fixing umb-mediapicker-upload template to work with new CSS for umb-control-group --- .../mediapicker/mediapicker.html | 73 ++++++++++--------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html index 656c5f2ac19e..373dfbcba782 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html @@ -15,42 +15,40 @@
      -
      - - - - -