From 46488836f4caa12c7fce1286e5b2092418b21d38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 3 Sep 2020 14:37:51 +0200 Subject: [PATCH 1/3] Changed clipboardService property resolvers to be specific for clipboard-entry-types --- .../common/services/blockeditor.service.js | 26 ++-- .../blockeditormodelobject.service.js | 2 +- .../src/common/services/clipboard.service.js | 139 +++++++++++++----- .../umb-block-list-property-editor.less | 24 +-- .../umbBlockListPropertyEditor.component.js | 54 +++---- .../nestedcontent/nestedcontent.controller.js | 39 ++--- 6 files changed, 158 insertions(+), 126 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/blockeditor.service.js b/src/Umbraco.Web.UI.Client/src/common/services/blockeditor.service.js index 0a4e3b1af4..dfa0eae297 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/blockeditor.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/blockeditor.service.js @@ -49,6 +49,7 @@ } else if(k === "settingsUdi") { replaceUdi(obj, k, propValue.settingsData); } else { + // lets crawl through all properties of layout to make sure get captured all `contentUdi` and `settingsUdi` properties. var propType = typeof obj[k]; if(propType === "object" || propType === "array") { replaceUdisOfObject(obj[k], propValue) @@ -56,22 +57,15 @@ } } } + function replaceElementTypeBlockListUDIsResolver(obj, propClearingMethod) { + replaceRawBlockListUDIsResolver(obj.value, propClearingMethod); + } - function replaceBlockListUDIsResolver(obj, propClearingMethod) { + clipboardService.registerPastePropertyResolver(replaceElementTypeBlockListUDIsResolver, clipboardService.TYPES.ELEMENT_TYPE); - if (typeof obj === "object") { - // 'obj' can both be a property object or the raw value of a inner property. - var value = obj; - - // if we got a property object from a ContentTypeModel we need to look at the value. We check for value and editor to, sort of, ensure this is the case. - if(obj.value !== undefined && obj.editor !== undefined) { - value = obj.value; - // If value isnt a object, lets break out. - if(typeof obj.value !== "object") { - return; - } - } + function replaceRawBlockListUDIsResolver(value, propClearingMethod) { + if (typeof value === "object") { // we got an object, and it has these three props then we are most likely dealing with a Block Editor. if ((value.layout !== undefined && value.contentData !== undefined && value.settingsData !== undefined)) { @@ -82,7 +76,7 @@ if(value.contentData.length > 0) { value.contentData.forEach((item) => { for (var k in item) { - propClearingMethod(item[k]); + propClearingMethod(item[k], clipboardService.TYPES.RAW); } }); } @@ -90,7 +84,7 @@ if(value.settingsData.length > 0) { value.settingsData.forEach((item) => { for (var k in item) { - propClearingMethod(item[k]); + propClearingMethod(item[k], clipboardService.TYPES.RAW); } }); } @@ -99,7 +93,7 @@ } } - clipboardService.registerPastePropertyResolver(replaceBlockListUDIsResolver) + clipboardService.registerPastePropertyResolver(replaceRawBlockListUDIsResolver, clipboardService.TYPES.RAW); }]); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js b/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js index 988e8f9fa9..a03c64ff9d 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js @@ -745,7 +745,7 @@ */ createFromElementType: function (elementTypeDataModel) { - elementTypeDataModel = clipboardService.parseContentForPaste(elementTypeDataModel); + elementTypeDataModel = clipboardService.parseContentForPaste(clipboardService.TYPES.ELEMENT_TYPE, elementTypeDataModel); var contentElementTypeKey = elementTypeDataModel.contentTypeKey; 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 2ad4bec1ea..f2e8a86361 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 @@ -13,8 +13,28 @@ function clipboardService(notificationsService, eventsService, localStorageService, iconHelper) { - var clearPropertyResolvers = []; - var pastePropertyResolvers = []; + const TYPES = {}; + TYPES.ELEMENT_TYPE = "elementType"; + TYPES.RAW = "raw"; + + var clearPropertyResolvers = {}; + var pastePropertyResolvers = {}; + var pasteTypeResolvers = {}; + + pasteTypeResolvers[TYPES.ELEMENT_TYPE] = function(data, propMethod) { + for (var t = 0; t < data.variants[0].tabs.length; t++) { + var tab = data.variants[0].tabs[t]; + for (var p = 0; p < tab.properties.length; p++) { + var prop = tab.properties[p]; + propMethod(prop, TYPES.ELEMENT_TYPE); + } + } + } + pasteTypeResolvers[TYPES.RAW] = function(data, propMethod) { + for (var p = 0; p < data.length; p++) { + propMethod(data[p], TYPES.RAW); + } + } var STORAGE_KEY = "umbClipboardService"; @@ -58,28 +78,29 @@ function clipboardService(notificationsService, eventsService, localStorageServi } - function clearPropertyForStorage(prop) { + function resolvePropertyForStorage(prop, type) { - for (var i=0; i prepareEntryForStorage(data, firstLevelClearupMethod)); + var copiedDatas = datas.map(data => prepareEntryForStorage(type, data, firstLevelClearupMethod)); // remove previous copies of this entry: storage.entries = storage.entries.filter( diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.less index a2c124a6ea..b8ac443047 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.less +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umb-block-list-property-editor.less @@ -187,25 +187,29 @@ ng-form.ng-invalid-val-server-match-settings > .umb-block-list__block > .umb-blo > .__plus { position: absolute; - pointer-events: none; // lets stop avoiding the mouse values in JS move event. - width: 24px; - height: 24px; - padding: 0; - border-radius: 3em; - border: 2px solid @blueMid; display: flex; justify-content: center; align-items: center; + pointer-events: none; // lets stop avoiding the mouse values in JS move event. + box-sizing: border-box; + width: 28px; + height: 28px; + margin-left: -16px - 8px; + margin-top: -16px; + padding: 0; + border-radius: 3em; + border: 2px solid @blueMid; color: @blueMid; + line-height: 22px; font-size: 20px; font-weight: 800; background-color: rgba(255, 255, 255, .96); box-shadow: 0 0 0 2px rgba(255, 255, 255, .96); - transform: scale(0) translate(-80%, -50%); + transform: scale(0); transition: transform 240ms ease-in; - animation: umb-block-list__block--create-button_after 800ms ease-in-out infinite; + animation: umb-block-list__block--create-button__plus 400ms ease-in-out infinite; - @keyframes umb-block-list__block--create-button_after { + @keyframes umb-block-list__block--create-button__plus { 0% { color: rgba(@blueMid, 0.8); } 50% { color: rgba(@blueMid, 1); } 100% { color: rgba(@blueMid, 0.8); } @@ -223,7 +227,7 @@ ng-form.ng-invalid-val-server-match-settings > .umb-block-list__block > .umb-blo transition-duration: 120ms; > .__plus { - transform: scale(1) translate(-80%, -50%); + transform: scale(1); transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275); } } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js index bfe5b43521..9cb5f95f79 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js @@ -406,7 +406,7 @@ size: (amountOfAvailableTypes > 8 ? "medium" : "small"), filter: (amountOfAvailableTypes > 8), clickPasteItem: function(item, mouseEvent) { - if (item.type === "elementTypeArray") { + if (Array.isArray(item.pasteData)) { var indexIncrementor = 0; item.pasteData.forEach(function (entry) { if (requestPasteFromClipboard(createIndex + indexIncrementor, entry)) { @@ -448,42 +448,28 @@ }; blockPickerModel.clickClearClipboard = function ($event) { - clipboardService.clearEntriesOfType("elementType", vm.availableContentTypesAliases); - clipboardService.clearEntriesOfType("elementTypeArray", vm.availableContentTypesAliases); + clipboardService.clearEntriesOfType(clipboardService.TYPES.ELEMENT_TYPE, vm.availableContentTypesAliases); }; blockPickerModel.clipboardItems = []; - var singleEntriesForPaste = clipboardService.retriveEntriesOfType("elementType", vm.availableContentTypesAliases); - singleEntriesForPaste.forEach(function (entry) { - blockPickerModel.clipboardItems.push( - { - type: "elementType", - date: entry.date, - pasteData: entry.data, - blockConfigModel: modelObject.getScaffoldFromAlias(entry.alias), - elementTypeModel: { - name: entry.label, - icon: entry.icon - } + var entriesForPaste = clipboardService.retriveEntriesOfType(clipboardService.TYPES.ELEMENT_TYPE, vm.availableContentTypesAliases); + entriesForPaste.forEach(function (entry) { + var pasteEntry = { + type: clipboardService.TYPES.ELEMENT_TYPE, + date: entry.date, + pasteData: entry.data, + elementTypeModel: { + name: entry.label, + icon: entry.icon } - ); - }); - - var arrayEntriesForPaste = clipboardService.retriveEntriesOfType("elementTypeArray", vm.availableContentTypesAliases); - arrayEntriesForPaste.forEach(function (entry) { - blockPickerModel.clipboardItems.push( - { - type: "elementTypeArray", - date: entry.date, - pasteData: entry.data, - blockConfigModel: {}, // no block configuration for paste items of elementTypeArray. - elementTypeModel: { - name: entry.label, - icon: entry.icon - } - } - ); + } + if(Array.isArray(pasteEntry.data) === false) { + pasteEntry.blockConfigModel = modelObject.getScaffoldFromAlias(entry.alias); + } else { + pasteEntry.blockConfigModel = {}; + } + blockPickerModel.clipboardItems.push(pasteEntry); }); blockPickerModel.clipboardItems.sort( (a, b) => { @@ -513,11 +499,11 @@ } localizationService.localize("clipboard_labelForArrayOfItemsFrom", [vm.model.label, contentNodeName]).then(function(localizedLabel) { - clipboardService.copyArray("elementTypeArray", aliases, elementTypesToCopy, localizedLabel, "icon-thumbnail-list", vm.model.id); + clipboardService.copyArray(clipboardService.TYPES.ELEMENT_TYPE, aliases, elementTypesToCopy, localizedLabel, "icon-thumbnail-list", vm.model.id); }); } function copyBlock(block) { - clipboardService.copy("elementType", block.content.contentTypeAlias, block.content, block.label); + clipboardService.copy(clipboardService.TYPES.ELEMENT_TYPE, block.content.contentTypeAlias, block.content, block.label); } function requestPasteFromClipboard(index, pasteEntry) { 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 1742496f75..2d39e3a4c0 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 @@ -22,18 +22,18 @@ // Loop through all inner properties: for (var k in obj) { - propClearingMethod(obj[k]); + propClearingMethod(obj[k], clipboardService.TYPES.RAW); } } } } - clipboardService.registerClearPropertyResolver(clearNestedContentPropertiesForStorage) + clipboardService.registerClearPropertyResolver(clearNestedContentPropertiesForStorage, clipboardService.TYPES.ELEMENT_TYPE) function clearInnerNestedContentPropertiesForStorage(prop, propClearingMethod) { - // if we got an array, and it has a entry with ncContentTypeAlias this meants that we are dealing with a NestedContent property inside a NestedContent property. + // if we got an array, and it has a entry with ncContentTypeAlias this meants that we are dealing with a NestedContent property data. if ((Array.isArray(prop) && prop.length > 0 && prop[0].ncContentTypeAlias !== undefined)) { for (var i = 0; i < prop.length; i++) { @@ -44,13 +44,13 @@ // Loop through all inner properties: for (var k in obj) { - propClearingMethod(obj[k]); + propClearingMethod(obj[k], clipboardService.TYPES.RAW); } } } } - clipboardService.registerClearPropertyResolver(clearInnerNestedContentPropertiesForStorage) + clipboardService.registerClearPropertyResolver(clearInnerNestedContentPropertiesForStorage, clipboardService.TYPES.RAW) }]); angular @@ -128,7 +128,7 @@ } localizationService.localize("clipboard_labelForArrayOfItemsFrom", [model.label, nodeName]).then(function (data) { - clipboardService.copyArray("elementTypeArray", aliases, vm.nodes, data, "icon-thumbnail-list", model.id, clearNodeForCopy); + clipboardService.copyArray(clipboardService.TYPES.ELEMENT_TYPE, aliases, vm.nodes, data, "icon-thumbnail-list", model.id, clearNodeForCopy); }); } @@ -197,7 +197,7 @@ view: "itempicker", event: $event, clickPasteItem: function (item) { - if (item.type === "elementTypeArray") { + if (Array.isArray(item.data)) { _.each(item.data, function (entry) { pasteFromClipboard(entry); }); @@ -239,21 +239,9 @@ vm.overlayMenu.pasteItems = []; - var singleEntriesForPaste = clipboardService.retriveEntriesOfType("elementType", contentTypeAliases); - _.each(singleEntriesForPaste, function (entry) { + var entriesForPaste = clipboardService.retriveEntriesOfType(clipboardService.TYPES.ELEMENT_TYPE, contentTypeAliases); + _.each(entriesForPaste, function (entry) { vm.overlayMenu.pasteItems.push({ - type: "elementType", - date: entry.date, - name: entry.label, - data: entry.data, - icon: entry.icon - }); - }); - - var arrayEntriesForPaste = clipboardService.retriveEntriesOfType("elementTypeArray", contentTypeAliases); - _.each(arrayEntriesForPaste, function (entry) { - vm.overlayMenu.pasteItems.push({ - type: "elementTypeArray", date: entry.date, name: entry.label, data: entry.data, @@ -271,8 +259,7 @@ vm.overlayMenu.clickClearPaste = function ($event) { $event.stopPropagation(); $event.preventDefault(); - clipboardService.clearEntriesOfType("elementType", contentTypeAliases); - clipboardService.clearEntriesOfType("elementTypeArray", contentTypeAliases); + clipboardService.clearEntriesOfType(clipboardService.TYPES.ELEMENT_TYPE, contentTypeAliases); vm.overlayMenu.pasteItems = [];// This dialog is not connected via the clipboardService events, so we need to update manually. vm.overlayMenu.hideHeader = false; }; @@ -463,7 +450,7 @@ syncCurrentNode(); - clipboardService.copy("elementType", node.contentTypeAlias, node, null, null, null, clearNodeForCopy); + clipboardService.copy(clipboardService.TYPES.ELEMENT_TYPE, node.contentTypeAlias, node, null, null, null, clearNodeForCopy); $event.stopPropagation(); } @@ -474,7 +461,7 @@ return; } - newNode = clipboardService.parseContentForPaste(newNode); + newNode = clipboardService.parseContentForPaste(newNode, clipboardService.TYPES.ELEMENT_TYPE); // generate a new key. newNode.key = String.CreateGuid(); @@ -487,7 +474,7 @@ } function checkAbilityToPasteContent() { - vm.showPaste = clipboardService.hasEntriesOfType("elementType", contentTypeAliases) || clipboardService.hasEntriesOfType("elementTypeArray", contentTypeAliases); + vm.showPaste = clipboardService.hasEntriesOfType(clipboardService.TYPES.ELEMENT_TYPE, contentTypeAliases); } eventsService.on("clipboardService.storageUpdate", checkAbilityToPasteContent); From 906f3eac2febd53d7e6eafea83f0d4500bd78612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 3 Sep 2020 14:41:23 +0200 Subject: [PATCH 2/3] putting the attributes right --- .../src/common/services/blockeditormodelobject.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js b/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js index a03c64ff9d..6bce7ec89b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js @@ -745,7 +745,7 @@ */ createFromElementType: function (elementTypeDataModel) { - elementTypeDataModel = clipboardService.parseContentForPaste(clipboardService.TYPES.ELEMENT_TYPE, elementTypeDataModel); + elementTypeDataModel = clipboardService.parseContentForPaste(elementTypeDataModel, clipboardService.TYPES.ELEMENT_TYPE); var contentElementTypeKey = elementTypeDataModel.contentTypeKey; From 208edfc3a266a7004b868a333cb37f6e8daf984c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 3 Sep 2020 21:36:30 +0200 Subject: [PATCH 3/3] rename pasteTypeResolvers to clipboardTypeResolvers. as its not specific to paste, but clipboard. --- .../src/common/services/clipboard.service.js | 16 ++++++++-------- 1 file changed, 8 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 f2e8a86361..58ed07367e 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 @@ -19,9 +19,9 @@ function clipboardService(notificationsService, eventsService, localStorageServi var clearPropertyResolvers = {}; var pastePropertyResolvers = {}; - var pasteTypeResolvers = {}; + var clipboardTypeResolvers = {}; - pasteTypeResolvers[TYPES.ELEMENT_TYPE] = function(data, propMethod) { + clipboardTypeResolvers[TYPES.ELEMENT_TYPE] = function(data, propMethod) { for (var t = 0; t < data.variants[0].tabs.length; t++) { var tab = data.variants[0].tabs[t]; for (var p = 0; p < tab.properties.length; p++) { @@ -30,7 +30,7 @@ function clipboardService(notificationsService, eventsService, localStorageServi } } } - pasteTypeResolvers[TYPES.RAW] = function(data, propMethod) { + clipboardTypeResolvers[TYPES.RAW] = function(data, propMethod) { for (var p = 0; p < data.length; p++) { propMethod(data[p], TYPES.RAW); } @@ -96,7 +96,7 @@ function clipboardService(notificationsService, eventsService, localStorageServi firstLevelClearupMethod(cloneData); } - var typeResolver = pasteTypeResolvers[type]; + var typeResolver = clipboardTypeResolvers[type]; if(typeResolver) { typeResolver(cloneData, resolvePropertyForStorage); } else { @@ -153,7 +153,7 @@ function clipboardService(notificationsService, eventsService, localStorageServi service.parseContentForPaste = function(pasteEntryData, type) { var cloneData = Utilities.copy(pasteEntryData); - var typeResolver = pasteTypeResolvers[type]; + var typeResolver = clipboardTypeResolvers[type]; if(typeResolver) { typeResolver(cloneData, resolvePropertyForPaste); } else { @@ -232,10 +232,10 @@ function clipboardService(notificationsService, eventsService, localStorageServi * Executed for all properties including inner properties when performing a paste action. */ service.registrerTypeResolvers = function(resolver, type) { - if(!pasteTypeResolvers[type]) { - pasteTypeResolvers[type] = []; + if(!clipboardTypeResolvers[type]) { + clipboardTypeResolvers[type] = []; } - pasteTypeResolvers[type].push(resolver); + clipboardTypeResolvers[type].push(resolver); };