Merge pull request #8736 from umbraco/v8/bugfix/block-list-recreate-udis-on-paste
V8.7RC: Recreate UDIs for pasted Block Editor entries
This commit is contained in:
@@ -4,39 +4,119 @@
|
||||
*
|
||||
* @description
|
||||
* <b>Added in Umbraco 8.7</b>. Service for dealing with Block Editors.
|
||||
*
|
||||
*
|
||||
* Block Editor Service provides the basic features for a block editor.
|
||||
* The main feature is the ability to create a Model Object which takes care of your data for your Block Editor.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* ##Samples
|
||||
*
|
||||
* ####Instantiate a Model Object for your property editor:
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* modelObject = blockEditorService.createModelObject(vm.model.value, vm.model.editor, vm.model.config.blocks, $scope);
|
||||
* modelObject.load().then(onLoaded);
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*
|
||||
* See {@link umbraco.services.blockEditorModelObject BlockEditorModelObject} for more samples.
|
||||
*
|
||||
*
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* When performing a runtime copy of Block Editors entries, we copy the ElementType Data Model and inner IDs are kept identical, to ensure new IDs are changed on paste we need to provide a resolver for the ClipboardService.
|
||||
*/
|
||||
angular.module('umbraco').run(['clipboardService', 'udiService', function (clipboardService, udiService) {
|
||||
|
||||
function replaceUdi(obj, key, dataObject) {
|
||||
var udi = obj[key];
|
||||
var newUdi = udiService.create("element");
|
||||
obj[key] = newUdi;
|
||||
dataObject.forEach((data) => {
|
||||
if (data.udi === udi) {
|
||||
data.udi = newUdi;
|
||||
}
|
||||
});
|
||||
}
|
||||
function replaceUdisOfObject(obj, propValue) {
|
||||
for (var k in obj) {
|
||||
if(k === "contentUdi") {
|
||||
replaceUdi(obj, k, propValue.contentData);
|
||||
} else if(k === "settingsUdi") {
|
||||
replaceUdi(obj, k, propValue.settingsData);
|
||||
} else {
|
||||
var propType = typeof obj[k];
|
||||
if(propType === "object" || propType === "array") {
|
||||
replaceUdisOfObject(obj[k], propValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function replaceBlockListUDIsResolver(obj, propClearingMethod) {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
|
||||
replaceUdisOfObject(value.layout, value);
|
||||
|
||||
// replace UDIs for inner properties of this Block Editors content data.
|
||||
if(value.contentData.length > 0) {
|
||||
value.contentData.forEach((item) => {
|
||||
for (var k in item) {
|
||||
propClearingMethod(item[k]);
|
||||
}
|
||||
});
|
||||
}
|
||||
// replace UDIs for inner properties of this Block Editors settings data.
|
||||
if(value.settingsData.length > 0) {
|
||||
value.settingsData.forEach((item) => {
|
||||
for (var k in item) {
|
||||
propClearingMethod(item[k]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clipboardService.registerPastePropertyResolver(replaceBlockListUDIsResolver)
|
||||
|
||||
}]);
|
||||
|
||||
|
||||
|
||||
|
||||
function blockEditorService(blockEditorModelObject) {
|
||||
|
||||
/**
|
||||
* @ngdocs function
|
||||
* @name createModelObject
|
||||
* @methodOf umbraco.services.blockEditorService
|
||||
*
|
||||
*
|
||||
* @description
|
||||
* Create a new Block Editor Model Object.
|
||||
* See {@link umbraco.services.blockEditorModelObject blockEditorModelObject}
|
||||
*
|
||||
*
|
||||
* @see umbraco.services.blockEditorModelObject
|
||||
* @param {object} propertyModelValue data object of the property editor, usually model.value.
|
||||
* @param {string} propertyEditorAlias alias of the property.
|
||||
|
||||
@@ -13,8 +13,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
|
||||
function blockEditorModelObjectFactory($interpolate, $q, udiService, contentResource, localizationService, umbRequestHelper) {
|
||||
function blockEditorModelObjectFactory($interpolate, $q, udiService, contentResource, localizationService, umbRequestHelper, clipboardService) {
|
||||
|
||||
/**
|
||||
* Simple mapping from property model content entry to editing model,
|
||||
@@ -746,7 +745,7 @@
|
||||
*/
|
||||
createFromElementType: function (elementTypeDataModel) {
|
||||
|
||||
elementTypeDataModel = Utilities.copy(elementTypeDataModel);
|
||||
elementTypeDataModel = clipboardService.parseContentForPaste(elementTypeDataModel);
|
||||
|
||||
var contentElementTypeKey = elementTypeDataModel.contentTypeKey;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ function clipboardService(notificationsService, eventsService, localStorageServi
|
||||
|
||||
|
||||
var clearPropertyResolvers = [];
|
||||
var pastePropertyResolvers = [];
|
||||
|
||||
|
||||
var STORAGE_KEY = "umbClipboardService";
|
||||
@@ -95,8 +96,46 @@ function clipboardService(notificationsService, eventsService, localStorageServi
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function resolvePropertyForPaste(prop) {
|
||||
for (var i=0; i<pastePropertyResolvers.length; i++) {
|
||||
pastePropertyResolvers[i](prop, resolvePropertyForPaste);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
var service = {};
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.clipboardService#parseContentForPaste
|
||||
* @methodOf umbraco.services.clipboardService
|
||||
*
|
||||
* @param {object} function The content entry to be cloned and resolved.
|
||||
*
|
||||
* @description
|
||||
* Executed registered property resolvers for inner properties, to be done on pasting a clipbaord content entry.
|
||||
*
|
||||
*/
|
||||
service.parseContentForPaste = function(contentEntryData) {
|
||||
|
||||
|
||||
var cloneData = Utilities.copy(contentEntryData);
|
||||
|
||||
// remove keys from sub-entries
|
||||
for (var t = 0; t < cloneData.variants[0].tabs.length; t++) {
|
||||
var tab = cloneData.variants[0].tabs[t];
|
||||
for (var p = 0; p < tab.properties.length; p++) {
|
||||
var prop = tab.properties[p];
|
||||
resolvePropertyForPaste(prop);
|
||||
}
|
||||
}
|
||||
|
||||
return cloneData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
@@ -119,7 +158,7 @@ function clipboardService(notificationsService, eventsService, localStorageServi
|
||||
* @name umbraco.services.clipboardService#registerClearPropertyResolver
|
||||
* @methodOf umbraco.services.clipboardService
|
||||
*
|
||||
* @param {string} function A method executed for every property and inner properties copied.
|
||||
* @param {string} function A method executed for every property and inner properties copied. Notice the method both needs to deal with retriving a property object {alias:..editor:..value:... ,...} and the raw property value as if the property is an inner property of a nested property.
|
||||
*
|
||||
* @description
|
||||
* Executed for all properties including inner properties when performing a copy action.
|
||||
@@ -128,19 +167,18 @@ function clipboardService(notificationsService, eventsService, localStorageServi
|
||||
clearPropertyResolvers.push(resolver);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.clipboardService#registrerPropertyClearingResolver
|
||||
* @name umbraco.services.clipboardService#registerPastePropertyResolver
|
||||
* @methodOf umbraco.services.clipboardService
|
||||
*
|
||||
* @param {string} function A method executed for every property and inner properties copied.
|
||||
* @param {string} function A method executed for every property and inner properties pasted. Notice the method both needs to deal with retriving a property object {alias:..editor:..value:... ,...} and the raw property value as if the property is an inner property of a nested property.
|
||||
*
|
||||
* @description
|
||||
* Executed for all properties including inner properties when performing a copy action.
|
||||
* Executed for all properties including inner properties when performing a paste action.
|
||||
*/
|
||||
service.registrerClearPropertyResolver = function(resolver) {
|
||||
clearPropertyResolvers.push(resolver);
|
||||
service.registerPastePropertyResolver = function(resolver) {
|
||||
pastePropertyResolvers.push(resolver);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
clipboardService.registrerClearPropertyResolver(clearNestedContentPropertiesForStorage)
|
||||
clipboardService.registerClearPropertyResolver(clearNestedContentPropertiesForStorage)
|
||||
|
||||
|
||||
function clearInnerNestedContentPropertiesForStorage(prop, propClearingMethod) {
|
||||
@@ -50,7 +50,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
clipboardService.registrerClearPropertyResolver(clearInnerNestedContentPropertiesForStorage)
|
||||
clipboardService.registerClearPropertyResolver(clearInnerNestedContentPropertiesForStorage)
|
||||
}]);
|
||||
|
||||
angular
|
||||
@@ -474,6 +474,8 @@
|
||||
return;
|
||||
}
|
||||
|
||||
newNode = clipboardService.parseContentForPaste(newNode);
|
||||
|
||||
// generate a new key.
|
||||
newNode.key = String.CreateGuid();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user