From 9c13dc432025310a182915782b68242ac136f8c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 21 Oct 2020 17:35:02 +0200 Subject: [PATCH 01/11] prototype --- .../common/services/blockeditor.service.js | 1 + .../src/common/services/clipboard.service.js | 9 +++++ .../umbBlockListPropertyEditor.component.js | 37 +++++++++++++++++-- 3 files changed, 43 insertions(+), 4 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 12e1144acc..916c5b5a79 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 @@ -58,6 +58,7 @@ } } function replaceElementTypeBlockListUDIsResolver(obj, propClearingMethod) { + // we could filter for specific Property Editor Aliases, but as the Block Editor structure can be used by many Property Editor we do not in this code know a good way to detect that this is a Block Editor and will therefor leave it to the value structure to determin this. replaceRawBlockListUDIsResolver(obj.value, propClearingMethod); } 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 58ed07367e..105e3b1ee6 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 @@ -15,6 +15,7 @@ function clipboardService(notificationsService, eventsService, localStorageServi const TYPES = {}; TYPES.ELEMENT_TYPE = "elementType"; + TYPES.BLOCK = "block"; TYPES.RAW = "raw"; var clearPropertyResolvers = {}; @@ -30,6 +31,14 @@ function clipboardService(notificationsService, eventsService, localStorageServi } } } + clipboardTypeResolvers[TYPES.BLOCK] = function(data, propMethod) { + if (data.data != null) { + clipboardTypeResolvers[TYPES.RAW](data.data, propMethod); + } + if (data.settingsData != null) { + clipboardTypeResolvers[TYPES.RAW](data.settingsData, propMethod); + } + } clipboardTypeResolvers[TYPES.RAW] = function(data, propMethod) { for (var p = 0; p < data.length; p++) { propMethod(data[p], TYPES.RAW); 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 a162814f52..fe99ccfc41 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 @@ -493,6 +493,25 @@ blockPickerModel.clipboardItems.push(pasteEntry); }); + var entriesForPaste = clipboardService.retriveEntriesOfType(clipboardService.TYPES.BLOCK, vm.availableContentTypesAliases); + entriesForPaste.forEach(function (entry) { + var pasteEntry = { + type: clipboardService.TYPES.BLOCK, + date: entry.date, + pasteData: entry.data, + 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) => { return b.date - a.date }); @@ -504,7 +523,12 @@ var requestCopyAllBlocks = function() { - var elementTypesToCopy = vm.layout.filter(entry => entry.$block.config.unsupported !== true).map(entry => entry.$block.content); + var elementTypesToCopy = vm.layout.filter(entry => entry.$block.config.unsupported !== true).map( + (entry) => { + // No need to clone the data as its begin handled by the clipboardService. + return {"data": entry.$block.data, "settingsData":entry.$block.settingsData} + } + ); // list aliases var aliases = elementTypesToCopy.map(content => content.contentTypeAlias); @@ -515,16 +539,21 @@ var contentNodeName = ""; if(vm.umbVariantContent) { contentNodeName = vm.umbVariantContent.editor.content.name; + contentNodeIcon = vm.umbVariantContent.editor.content.icon; } else if (vm.umbElementEditorContent) { - contentNodeName = vm.umbElementEditorContent.model.documentType.name + contentNodeName = vm.umbElementEditorContent.model.documentType.name; + contentNodeIcon = vm.umbElementEditorContent.model.documentType.icon; } + console.log("contentNodeIcon", contentNodeIcon) + localizationService.localize("clipboard_labelForArrayOfItemsFrom", [vm.model.label, contentNodeName]).then(function(localizedLabel) { - clipboardService.copyArray(clipboardService.TYPES.ELEMENT_TYPE, aliases, elementTypesToCopy, localizedLabel, "icon-thumbnail-list", vm.model.id); + clipboardService.copyArray(clipboardService.TYPES.BLOCK, aliases, elementTypesToCopy, localizedLabel, contentNodeIcon || "icon-thumbnail-list", vm.model.id); }); } function copyBlock(block) { - clipboardService.copy(clipboardService.TYPES.ELEMENT_TYPE, block.content.contentTypeAlias, block.content, block.label); + console.log(block) + clipboardService.copy(clipboardService.TYPES.BLOCK, block.content.contentTypeAlias, {"data": block.data, "settingsData":block.settingsData}, block.label, block.content.icon, block.content.udi); } function requestPasteFromClipboard(index, pasteEntry) { From 24f07af0e127606d17cf571f3c04224b45964bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 22 Oct 2020 08:35:12 +0200 Subject: [PATCH 02/11] ability to create from Block Data --- .../common/services/blockeditor.service.js | 43 +++++++++++++++---- .../blockeditormodelobject.service.js | 31 +++++++++++++ .../umbBlockListPropertyEditor.component.js | 26 ++++++++--- 3 files changed, 84 insertions(+), 16 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 916c5b5a79..08c9803ff3 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 @@ -57,15 +57,15 @@ } } } - function replaceElementTypeBlockListUDIsResolver(obj, propClearingMethod) { + function elementTypeBlockResolver(obj, propPasteResolverMethod) { // we could filter for specific Property Editor Aliases, but as the Block Editor structure can be used by many Property Editor we do not in this code know a good way to detect that this is a Block Editor and will therefor leave it to the value structure to determin this. - replaceRawBlockListUDIsResolver(obj.value, propClearingMethod); + rawBlockResolver(obj.value, propPasteResolverMethod); } - clipboardService.registerPastePropertyResolver(replaceElementTypeBlockListUDIsResolver, clipboardService.TYPES.ELEMENT_TYPE); + clipboardService.registerPastePropertyResolver(elementTypeBlockResolver, clipboardService.TYPES.ELEMENT_TYPE); - function replaceRawBlockListUDIsResolver(value, propClearingMethod) { + function rawBlockResolver(value, propPasteResolverMethod) { if (value != null && typeof value === "object") { // we got an object, and it has these three props then we are most likely dealing with a Block Editor. @@ -73,19 +73,19 @@ replaceUdisOfObject(value.layout, value); - // replace UDIs for inner properties of this Block Editors content data. + // run resolvers for inner properties of this Blocks content data. if(value.contentData.length > 0) { value.contentData.forEach((item) => { for (var k in item) { - propClearingMethod(item[k], clipboardService.TYPES.RAW); + propPasteResolverMethod(item[k], clipboardService.TYPES.RAW); } }); } - // replace UDIs for inner properties of this Block Editors settings data. + // run resolvers for inner properties of this Blocks settings data. if(value.settingsData.length > 0) { value.settingsData.forEach((item) => { for (var k in item) { - propClearingMethod(item[k], clipboardService.TYPES.RAW); + propPasteResolverMethod(item[k], clipboardService.TYPES.RAW); } }); } @@ -94,7 +94,32 @@ } } - clipboardService.registerPastePropertyResolver(replaceRawBlockListUDIsResolver, clipboardService.TYPES.RAW); + clipboardService.registerPastePropertyResolver(rawBlockResolver, clipboardService.TYPES.RAW); + + + function blockResolver(block, propPasteResolverMethod) { + + if(block.data) { + + // Make new UDI for content-element + block.data.udi = block.layout.contentUdi = udiService.create("element"); + + // run resolvers for inner properties of this Blocks content data. + propPasteResolverMethod(block.data, clipboardService.TYPES.RAW); + } + + if(block.settingsData) { + + // Make new UDI for settings-element + block.settingsData.udi = block.layout.settingsUdi = udiService.create("element"); + + // run resolvers for inner properties of this Blocks settings data. + propPasteResolverMethod(block.settingsData, clipboardService.TYPES.RAW); + } + + } + + clipboardService.registerPastePropertyResolver(blockResolver, clipboardService.TYPES.BLOCK); }]); 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 77ed357c35..ac6bfb9135 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 @@ -773,6 +773,37 @@ return layoutEntry; + }, + /** + * @ngdoc method + * @name createFromRawData + * @methodOf umbraco.services.blockEditorModelObject + * @description Insert data from raw models + * @return {Object | null} Layout entry object, to be inserted at a decired location in the layout object. Or ´null´ if the given ElementType isnt supported by the block configuration. + */ + createFromBlockData: function (blockData) { + + blockData = clipboardService.parseContentForPaste(blockData, clipboardService.TYPES.BLOCK); + + // As the blockData is a cloned object we can use its layout part for our layout entry. + var layoutEntry = blockData.layout; + if (layoutEntry === null) { + return null; + } + + if (blockData.data) { + this.value.contentData.push(blockData.data); + } else { + // We do not have data, this cannot be succesful paste. + return null; + } + + if (blockData.settingsData) { + this.value.settingsData.push(blockData.settingsData); + } + + return layoutEntry; + }, /** 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 fe99ccfc41..7cac113b6f 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 @@ -430,12 +430,12 @@ if (Array.isArray(item.pasteData)) { var indexIncrementor = 0; item.pasteData.forEach(function (entry) { - if (requestPasteFromClipboard(createIndex + indexIncrementor, entry)) { + if (requestPasteFromClipboard(createIndex + indexIncrementor, entry, item.type)) { indexIncrementor++; } }); } else { - requestPasteFromClipboard(createIndex, item.pasteData); + requestPasteFromClipboard(createIndex, item.pasteData, item.type); } if(!(mouseEvent.ctrlKey || mouseEvent.metaKey)) { blockPickerModel.close(); @@ -470,6 +470,7 @@ blockPickerModel.clickClearClipboard = function ($event) { clipboardService.clearEntriesOfType(clipboardService.TYPES.ELEMENT_TYPE, vm.availableContentTypesAliases); + clipboardService.clearEntriesOfType(clipboardService.TYPES.BLOCK, vm.availableContentTypesAliases); }; blockPickerModel.clipboardItems = []; @@ -526,7 +527,7 @@ var elementTypesToCopy = vm.layout.filter(entry => entry.$block.config.unsupported !== true).map( (entry) => { // No need to clone the data as its begin handled by the clipboardService. - return {"data": entry.$block.data, "settingsData":entry.$block.settingsData} + return {"layout": block.layout, "data": entry.$block.data, "settingsData":entry.$block.settingsData} } ); @@ -552,23 +553,33 @@ }); } function copyBlock(block) { - console.log(block) - clipboardService.copy(clipboardService.TYPES.BLOCK, block.content.contentTypeAlias, {"data": block.data, "settingsData":block.settingsData}, block.label, block.content.icon, block.content.udi); + clipboardService.copy(clipboardService.TYPES.BLOCK, block.content.contentTypeAlias, {"layout": block.layout, "data": block.data, "settingsData":block.settingsData}, block.label, block.content.icon, block.content.udi); } - function requestPasteFromClipboard(index, pasteEntry) { + function requestPasteFromClipboard(index, pasteEntry, pasteType) { if (pasteEntry === undefined) { return false; } - var layoutEntry = modelObject.createFromElementType(pasteEntry); + var layoutEntry; + if (pasteType === clipboardService.TYPES.ELEMENT_TYPE) { + layoutEntry = modelObject.createFromElementType(pasteEntry); + } else if (pasteType === clipboardService.TYPES.BLOCK) { + layoutEntry = modelObject.createFromBlockData(pasteEntry); + } else { + // Not a supported paste type. + return false; + } + if (layoutEntry === null) { + // Pasting did not go well. return false; } // make block model var blockObject = getBlockObject(layoutEntry); if (blockObject === null) { + // Initalization of the Block Object didnt go well, therefor we will fail the paste action. return false; } @@ -583,6 +594,7 @@ return true; } + function requestDeleteBlock(block) { localizationService.localizeMany(["general_delete", "blockEditor_confirmDeleteBlockMessage", "contentTypeEditor_yesDelete"]).then(function (data) { const overlay = { From 3025fbd8b6680e0059fb7c8164e465095fb83345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 22 Oct 2020 11:16:37 +0200 Subject: [PATCH 03/11] further progress, need to switch branch. --- .../common/services/blockeditor.service.js | 34 +++++++--- .../blockeditormodelobject.service.js | 4 ++ .../src/common/services/clipboard.service.js | 66 +++++++++++++------ .../umbBlockListPropertyEditor.component.js | 16 +++-- 4 files changed, 86 insertions(+), 34 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 08c9803ff3..122d430165 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 @@ -57,6 +57,23 @@ } } } + function removeBlockReferences(obj) { + for (var k in obj) { + if(k === "contentUdi") { + delete obj[k]; + } else if(k === "settingsUdi") { + delete obj[k]; + } 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 != null && (propType === "object" || propType === "array")) { + removeBlockReferences(obj[k]) + } + } + } + } + + function elementTypeBlockResolver(obj, propPasteResolverMethod) { // we could filter for specific Property Editor Aliases, but as the Block Editor structure can be used by many Property Editor we do not in this code know a good way to detect that this is a Block Editor and will therefor leave it to the value structure to determin this. rawBlockResolver(obj.value, propPasteResolverMethod); @@ -97,29 +114,26 @@ clipboardService.registerPastePropertyResolver(rawBlockResolver, clipboardService.TYPES.RAW); - function blockResolver(block, propPasteResolverMethod) { + function provideNewUdisForBlockResolver(block, propPasteResolverMethod) { + + if(block.layout) { + // We do not support layout child blocks currently, these should be stripped out as we only will be copying a single entry. + removeBlockReferences(block.layout); + } if(block.data) { - // Make new UDI for content-element block.data.udi = block.layout.contentUdi = udiService.create("element"); - - // run resolvers for inner properties of this Blocks content data. - propPasteResolverMethod(block.data, clipboardService.TYPES.RAW); } if(block.settingsData) { - // Make new UDI for settings-element block.settingsData.udi = block.layout.settingsUdi = udiService.create("element"); - - // run resolvers for inner properties of this Blocks settings data. - propPasteResolverMethod(block.settingsData, clipboardService.TYPES.RAW); } } - clipboardService.registerPastePropertyResolver(blockResolver, clipboardService.TYPES.BLOCK); + clipboardService.registerPastePropertyResolver(provideNewUdisForBlockResolver, clipboardService.TYPES.BLOCK); }]); 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 ac6bfb9135..57aaeaa42d 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 @@ -783,8 +783,12 @@ */ createFromBlockData: function (blockData) { + console.log("createFromBlockData", blockData); + blockData = clipboardService.parseContentForPaste(blockData, clipboardService.TYPES.BLOCK); + console.log("createFromBlockData", blockData); + // As the blockData is a cloned object we can use its layout part for our layout entry. var layoutEntry = blockData.layout; if (layoutEntry === null) { 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 105e3b1ee6..6eb8503319 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 @@ -10,7 +10,7 @@ * 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, iconHelper) { +function clipboardService($window, notificationsService, eventsService, localStorageService, iconHelper) { const TYPES = {}; @@ -22,21 +22,35 @@ function clipboardService(notificationsService, eventsService, localStorageServi var pastePropertyResolvers = {}; var clipboardTypeResolvers = {}; - 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]; + clipboardTypeResolvers[TYPES.ELEMENT_TYPE] = function(element, propMethod) { + for (var t = 0; t < element.variants[0].tabs.length; t++) { + var tab = element.variants[0].tabs[t]; for (var p = 0; p < tab.properties.length; p++) { var prop = tab.properties[p]; propMethod(prop, TYPES.ELEMENT_TYPE); } } } - clipboardTypeResolvers[TYPES.BLOCK] = function(data, propMethod) { - if (data.data != null) { - clipboardTypeResolvers[TYPES.RAW](data.data, propMethod); + clipboardTypeResolvers[TYPES.BLOCK] = function (block, propMethod) { + + propMethod(block, TYPES.BLOCK); + + if(block.data) { + Object.keys(block.data).forEach( key => { + if(key === 'udi' || key === 'contentTypeKey') { + return; + } + propMethod(block.data[key], TYPES.RAW); + }); } - if (data.settingsData != null) { - clipboardTypeResolvers[TYPES.RAW](data.settingsData, propMethod); + + if(block.settingsData) { + Object.keys(block.settingsData).forEach( key => { + if(key === 'udi' || key === 'contentTypeKey') { + return; + } + propMethod(block.settingsData[key], TYPES.RAW); + }); } } clipboardTypeResolvers[TYPES.RAW] = function(data, propMethod) { @@ -45,7 +59,6 @@ function clipboardService(notificationsService, eventsService, localStorageServi } } - var STORAGE_KEY = "umbClipboardService"; var retriveStorage = function() { @@ -73,10 +86,13 @@ function clipboardService(notificationsService, eventsService, localStorageServi var storageString = JSON.stringify(storage); try { + // Check that we can parse the JSON: var storageJSON = JSON.parse(storageString); + + // Store the string: localStorageService.set(STORAGE_KEY, storageString); - eventsService.emit("clipboardService.storageUpdate"); + //eventsService.emit("clipboardService.storageUpdate"); return true; } catch(e) { @@ -91,11 +107,11 @@ function clipboardService(notificationsService, eventsService, localStorageServi type = type || "raw"; var resolvers = clearPropertyResolvers[type]; - - for (var i=0; i entry.$block.config.unsupported !== true).map( (entry) => { // No need to clone the data as its begin handled by the clipboardService. - return {"layout": block.layout, "data": entry.$block.data, "settingsData":entry.$block.settingsData} + return {"layout": entry.$block.layout, "data": entry.$block.data, "settingsData":entry.$block.settingsData} } ); @@ -537,16 +537,21 @@ // remove dublicates aliases = aliases.filter((item, index) => aliases.indexOf(item) === index); - var contentNodeName = ""; + var contentNodeName = "?"; + var contentNodeIcon = null; if(vm.umbVariantContent) { contentNodeName = vm.umbVariantContent.editor.content.name; - contentNodeIcon = vm.umbVariantContent.editor.content.icon; + if(vm.umbVariantContentEditors) { + contentNodeIcon = vm.umbVariantContentEditors.content.icon.split(" ")[0]; + } } else if (vm.umbElementEditorContent) { contentNodeName = vm.umbElementEditorContent.model.documentType.name; - contentNodeIcon = vm.umbElementEditorContent.model.documentType.icon; + contentNodeIcon = vm.umbElementEditorContent.model.documentType.icon.split(" ")[0]; + console.log(vm.umbElementEditorContent.model.documentType) } - console.log("contentNodeIcon", contentNodeIcon) + + console.log("check that we get the right contentNodeIcon", contentNodeIcon) localizationService.localize("clipboard_labelForArrayOfItemsFrom", [vm.model.label, contentNodeName]).then(function(localizedLabel) { clipboardService.copyArray(clipboardService.TYPES.BLOCK, aliases, elementTypesToCopy, localizedLabel, contentNodeIcon || "icon-thumbnail-list", vm.model.id); @@ -566,6 +571,7 @@ layoutEntry = modelObject.createFromElementType(pasteEntry); } else if (pasteType === clipboardService.TYPES.BLOCK) { layoutEntry = modelObject.createFromBlockData(pasteEntry); + console.log("pasteEntry", pasteEntry) } else { // Not a supported paste type. return false; From 310c8ec92451f21fd5eed52cfa84c0b00f35c38d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 22 Oct 2020 15:02:25 +0200 Subject: [PATCH 04/11] finish feature + clean up --- .../blockeditormodelobject.service.js | 4 --- .../umbBlockListPropertyEditor.component.js | 32 +++++++++---------- 2 files changed, 15 insertions(+), 21 deletions(-) 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 57aaeaa42d..ac6bfb9135 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 @@ -783,12 +783,8 @@ */ createFromBlockData: function (blockData) { - console.log("createFromBlockData", blockData); - blockData = clipboardService.parseContentForPaste(blockData, clipboardService.TYPES.BLOCK); - console.log("createFromBlockData", blockData); - // As the blockData is a cloned object we can use its layout part for our layout entry. var layoutEntry = blockData.layout; if (layoutEntry === null) { 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 f22ecd8d97..d766808049 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 @@ -486,10 +486,11 @@ icon: entry.icon } } - if(Array.isArray(pasteEntry.data) === false) { - pasteEntry.blockConfigModel = modelObject.getScaffoldFromAlias(entry.alias); - } else { - pasteEntry.blockConfigModel = {}; + if(Array.isArray(entry.data) === false) { + var scaffold = modelObject.getScaffoldFromAlias(entry.alias); + if(scaffold) { + pasteEntry.blockConfigModel = modelObject.getBlockConfiguration(scaffold.contentTypeKey); + } } blockPickerModel.clipboardItems.push(pasteEntry); }); @@ -505,10 +506,8 @@ icon: entry.icon } } - if(Array.isArray(pasteEntry.data) === false) { - pasteEntry.blockConfigModel = modelObject.getScaffoldFromAlias(entry.alias); - } else { - pasteEntry.blockConfigModel = {}; + if(Array.isArray(entry.data) === false) { + pasteEntry.blockConfigModel = modelObject.getBlockConfiguration(entry.data.data.contentTypeKey); } blockPickerModel.clipboardItems.push(pasteEntry); }); @@ -524,17 +523,19 @@ var requestCopyAllBlocks = function() { + var aliases = []; + var elementTypesToCopy = vm.layout.filter(entry => entry.$block.config.unsupported !== true).map( (entry) => { + + aliases.push(entry.$block.content.contentTypeAlias); + // No need to clone the data as its begin handled by the clipboardService. return {"layout": entry.$block.layout, "data": entry.$block.data, "settingsData":entry.$block.settingsData} } ); - // list aliases - var aliases = elementTypesToCopy.map(content => content.contentTypeAlias); - - // remove dublicates + // remove dublicate aliases aliases = aliases.filter((item, index) => aliases.indexOf(item) === index); var contentNodeName = "?"; @@ -543,16 +544,14 @@ contentNodeName = vm.umbVariantContent.editor.content.name; if(vm.umbVariantContentEditors) { contentNodeIcon = vm.umbVariantContentEditors.content.icon.split(" ")[0]; + } else if (vm.umbElementEditorContent) { + contentNodeIcon = vm.umbElementEditorContent.model.documentType.icon.split(" ")[0]; } } else if (vm.umbElementEditorContent) { contentNodeName = vm.umbElementEditorContent.model.documentType.name; contentNodeIcon = vm.umbElementEditorContent.model.documentType.icon.split(" ")[0]; - console.log(vm.umbElementEditorContent.model.documentType) } - - console.log("check that we get the right contentNodeIcon", contentNodeIcon) - localizationService.localize("clipboard_labelForArrayOfItemsFrom", [vm.model.label, contentNodeName]).then(function(localizedLabel) { clipboardService.copyArray(clipboardService.TYPES.BLOCK, aliases, elementTypesToCopy, localizedLabel, contentNodeIcon || "icon-thumbnail-list", vm.model.id); }); @@ -571,7 +570,6 @@ layoutEntry = modelObject.createFromElementType(pasteEntry); } else if (pasteType === clipboardService.TYPES.BLOCK) { layoutEntry = modelObject.createFromBlockData(pasteEntry); - console.log("pasteEntry", pasteEntry) } else { // Not a supported paste type. return false; From 99e2990d07e56b85c4cb313808f6ba685184321f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 22 Oct 2020 15:07:45 +0200 Subject: [PATCH 05/11] Emit event if localStorage changes from another tab --- .../src/common/services/clipboard.service.js | 7 ++----- 1 file changed, 2 insertions(+), 5 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 6eb8503319..85d70b530c 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 @@ -92,7 +92,7 @@ function clipboardService($window, notificationsService, eventsService, localSto // Store the string: localStorageService.set(STORAGE_KEY, storageString); - //eventsService.emit("clipboardService.storageUpdate"); + eventsService.emit("clipboardService.storageUpdate"); return true; } catch(e) { @@ -454,12 +454,9 @@ function clipboardService($window, notificationsService, eventsService, localSto - - + // Fires if LocalStorage was changed from another tab than this one. $window.addEventListener("storage", localStorageChanged); function localStorageChanged() { - console.log("clipboardService.storageUpdate"); - // TODO: Check if its the right value that was changed... eventsService.emit("clipboardService.storageUpdate"); } From cb902c4e08487d8eb8157cde749d36117ef8665a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 23 Oct 2020 15:08:27 +0200 Subject: [PATCH 06/11] Fail if settings elementType isnt supported + concept for inner-blocks + debounce for storage update --- .../blockeditormodelobject.service.js | 22 ++++++++++++++++++- .../src/common/services/clipboard.service.js | 20 +++++++++++++---- 2 files changed, 37 insertions(+), 5 deletions(-) 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 ac6bfb9135..dbbaac95db 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 @@ -791,7 +791,15 @@ return null; } + var blockConfiguration; + if (blockData.data) { + // Ensure that we support the alias: + blockConfiguration = this.getBlockConfiguration(blockData.data.contentTypeKey); + if(blockConfiguration === null) { + return null; + } + this.value.contentData.push(blockData.data); } else { // We do not have data, this cannot be succesful paste. @@ -799,7 +807,19 @@ } if (blockData.settingsData) { - this.value.settingsData.push(blockData.settingsData); + // Ensure that we support the alias: + if(blockConfiguration.settingsElementTypeKey) { + // If we have settings for this Block Configuration, we need to check that they align, if we dont we do not want to fail. + if(blockConfiguration.settingsElementTypeKey === blockData.settingsData.contentTypeKey) { + this.value.settingsData.push(blockData.settingsData); + } else { + // Settings ElementType does not align, so we will fail. + return null; + } + } else { + // We do not have settings currently, so lets get rid of the settings part and move on with the paste. + delete layoutEntry.settingUdi; + } } return layoutEntry; 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 85d70b530c..0da1867cbd 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 @@ -52,6 +52,18 @@ function clipboardService($window, notificationsService, eventsService, localSto propMethod(block.settingsData[key], TYPES.RAW); }); } + + /* + // Concept for supporting Block that contains other Blocks. + // Missing clearifications: + // How do we ensure that the inner blocks of a block is supported in the new scenario. Not that likely but still relevant, so conciderations should be made. + if(block.references) { + // A Block clipboard entry can contain other Block Clipboard Entries, here we will make sure to resolve those identical to the main entry. + for (var r = 0; r < block.references.length; r++) { + clipboardTypeResolvers[TYPES.BLOCK](block.references[r], propMethod); + } + } + */ } clipboardTypeResolvers[TYPES.RAW] = function(data, propMethod) { for (var p = 0; p < data.length; p++) { @@ -453,12 +465,12 @@ function clipboardService($window, notificationsService, eventsService, localSto }; + var emitClipboardStorageUpdate = _.debounce(function(e) { + eventsService.emit("clipboardService.storageUpdate"); + }, 1000); // Fires if LocalStorage was changed from another tab than this one. - $window.addEventListener("storage", localStorageChanged); - function localStorageChanged() { - eventsService.emit("clipboardService.storageUpdate"); - } + $window.addEventListener("storage", emitClipboardStorageUpdate); From 016f883ee39715c5a0318cdaea5f4cb66172925e Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 2 Nov 2020 13:29:27 +0000 Subject: [PATCH 07/11] Update src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js --- .../src/common/services/clipboard.service.js | 3 +-- 1 file changed, 1 insertion(+), 2 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 0da1867cbd..862f58507d 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 @@ -55,7 +55,7 @@ function clipboardService($window, notificationsService, eventsService, localSto /* // Concept for supporting Block that contains other Blocks. - // Missing clearifications: + // Missing clarifications: // How do we ensure that the inner blocks of a block is supported in the new scenario. Not that likely but still relevant, so conciderations should be made. if(block.references) { // A Block clipboard entry can contain other Block Clipboard Entries, here we will make sure to resolve those identical to the main entry. @@ -479,4 +479,3 @@ function clipboardService($window, notificationsService, eventsService, localSto angular.module("umbraco.services").factory("clipboardService", clipboardService); - From 99441789d80268a1e91c341d7aa63408b272e8d5 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 2 Nov 2020 13:30:02 +0000 Subject: [PATCH 08/11] Update src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js --- .../src/common/services/clipboard.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 862f58507d..83fd3d08c2 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 @@ -56,7 +56,7 @@ function clipboardService($window, notificationsService, eventsService, localSto /* // Concept for supporting Block that contains other Blocks. // Missing clarifications: - // How do we ensure that the inner blocks of a block is supported in the new scenario. Not that likely but still relevant, so conciderations should be made. + // How do we ensure that the inner blocks of a block is supported in the new scenario. Not that likely but still relevant, so considerations should be made. if(block.references) { // A Block clipboard entry can contain other Block Clipboard Entries, here we will make sure to resolve those identical to the main entry. for (var r = 0; r < block.references.length; r++) { From 3a41861aa0c04475c40b00964b7df9a6c77a5709 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 2 Nov 2020 13:34:34 +0000 Subject: [PATCH 09/11] Update src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js --- .../blocklist/umbBlockListPropertyEditor.component.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 d766808049..fb0018d099 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 @@ -535,7 +535,7 @@ } ); - // remove dublicate aliases + // remove duplicate aliases aliases = aliases.filter((item, index) => aliases.indexOf(item) === index); var contentNodeName = "?"; From 9c820c7939c7b9f87245affce9f499df736c6b4f Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 2 Nov 2020 13:37:27 +0000 Subject: [PATCH 10/11] Update src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js --- .../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 dbbaac95db..decd5cbad5 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 @@ -776,7 +776,7 @@ }, /** * @ngdoc method - * @name createFromRawData + * @name createFromBlockData * @methodOf umbraco.services.blockEditorModelObject * @description Insert data from raw models * @return {Object | null} Layout entry object, to be inserted at a decired location in the layout object. Or ´null´ if the given ElementType isnt supported by the block configuration. From 67367fe111720063ca7a7a95bc1a3645bb2bc29a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 3 Nov 2020 13:38:54 +0100 Subject: [PATCH 11/11] display an error message if settings does not align. --- .../src/common/services/blockeditormodelobject.service.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 decd5cbad5..8a2b230a27 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 @@ -13,7 +13,7 @@ (function () { 'use strict'; - function blockEditorModelObjectFactory($interpolate, $q, udiService, contentResource, localizationService, umbRequestHelper, clipboardService) { + function blockEditorModelObjectFactory($interpolate, $q, udiService, contentResource, localizationService, umbRequestHelper, clipboardService, notificationsService) { /** * Simple mapping from property model content entry to editing model, @@ -813,7 +813,7 @@ if(blockConfiguration.settingsElementTypeKey === blockData.settingsData.contentTypeKey) { this.value.settingsData.push(blockData.settingsData); } else { - // Settings ElementType does not align, so we will fail. + notificationsService.error("Clipboard", "Couldn't paste because settings-data is not compatible."); return null; } } else {