diff --git a/src/dom_components/model/Components.js b/src/dom_components/model/Components.js index 14021bdf8..69861c2fb 100644 --- a/src/dom_components/model/Components.js +++ b/src/dom_components/model/Components.js @@ -1,14 +1,5 @@ import Backbone from 'backbone'; -import { - isEmpty, - isArray, - isString, - each, - includes, - extend, - flatten, - debounce -} from 'underscore'; +import { isEmpty, isArray, isString, each, includes, extend, flatten, debounce } from 'underscore'; import Component, { keySymbol, keySymbols } from './Component'; const getIdsToKeep = (prev, res = []) => { @@ -28,6 +19,21 @@ const getNewIds = (items, res = []) => { return res; }; +const getComponentsFromDefs = (items, all = {}) => { + return items.map(item => { + const id = item.attributes?.id; + let result = item; + + if (id && all[id]) { + result = all[id]; + } else if (isArray(result.components)) { + result.components = getComponentsFromDefs(result.components, all); + } + + return result; + }); +}; + export default Backbone.Collection.extend({ initialize(models, opt = {}) { this.opt = opt; @@ -50,6 +56,23 @@ export default Backbone.Collection.extend({ models.each(model => this.onAdd(model)); }, + resetFromString(input = '', opts = {}) { + opts.keepIds = getIdsToKeep(this); + const { domc } = this; + const allByID = domc ? domc.allById() : {}; + const parsed = this.parseString(input, opts); + const cmps = isArray(parsed) ? parsed : [parsed]; + console.log({ + len: this.length, + input, + cmps, + allByID, + newCmp: getComponentsFromDefs(cmps, allByID), + keepIds: opts.keepIds, + }); + this.reset(cmps, opts); + }, + removeChildren(removed, coll, opts = {}) { // Removing a parent component can cause this function // to be called with an already removed child element @@ -83,7 +106,7 @@ export default Backbone.Collection.extend({ if (!removed.opt.temporary) { em.get('Commands').run('core:component-style-clear', { - target: removed + target: removed, }); removed.removed(); removed.trigger('removed'); @@ -128,7 +151,7 @@ export default Backbone.Collection.extend({ attrs.type && em.logWarning(`Component type '${attrs.type}' not found`, { attrs, - options + options, }); } @@ -146,7 +169,7 @@ export default Backbone.Collection.extend({ const { at, ...optsToPass } = opt; cssc.addCollection(parsed.css, { ...optsToPass, - extend: 1 + extend: 1, }); } @@ -170,9 +193,7 @@ export default Backbone.Collection.extend({ } const isMult = isArray(models); - models = (isMult ? models : [models]) - .filter(i => i) - .map(model => this.processDef(model)); + models = (isMult ? models : [models]).filter(i => i).map(model => this.processDef(model)); models = isMult ? flatten(models, 1) : models[0]; const result = Backbone.Collection.prototype.add.apply(this, [models, opt]); @@ -239,14 +260,7 @@ export default Backbone.Collection.extend({ const avoidInline = em && em.getConfig('avoidInlineStyle'); domc && domc.Component.ensureInList(model); - if ( - !isEmpty(style) && - !avoidInline && - em && - em.get && - em.getConfig('forceClass') && - !opts.temporary - ) { + if (!isEmpty(style) && !avoidInline && em && em.get && em.getConfig('forceClass') && !opts.temporary) { const name = model.cid; const rule = em.get('CssComposer').setClassRule(name, style); model.setStyle({}); @@ -257,7 +271,7 @@ export default Backbone.Collection.extend({ this.__onAddEnd(); }, - __onAddEnd: debounce(function() { + __onAddEnd: debounce(function () { // TODO to check symbols on load, probably this might be removed as symbols // are always recovered from the model // const { domc } = this; @@ -283,5 +297,5 @@ export default Backbone.Collection.extend({ // }); // }; // onAll(toCheck); - }) + }), }); diff --git a/src/utils/Sorter.js b/src/utils/Sorter.js index d306e644b..7efc183e8 100644 --- a/src/utils/Sorter.js +++ b/src/utils/Sorter.js @@ -1051,31 +1051,25 @@ export default Backbone.View.extend({ move(dst, src, pos) { const { em, activeTextModel, dropContent } = this; const srcEl = getElement(src); - em && em.trigger('component:dragEnd:before', dst, srcEl, pos); // @depricated - let index = pos.indexEl; - let modelToDrop, modelTemp, created; const warns = []; + const index = pos.method === 'after' ? pos.indexEl + 1 : pos.indexEl; const validResult = this.validTarget(dst, srcEl); const targetCollection = $(dst).data('collection'); - const model = validResult.srcModel; - let { droppable } = validResult; - const { trgModel, draggable } = validResult; - const dropInfo = validResult.dropInfo || (trgModel && trgModel.get('droppable')); - const dragInfo = validResult.dragInfo || (model && model.get('draggable')); - droppable = trgModel instanceof Backbone.Collection ? 1 : droppable; - const isTextableActive = this.isTextableActive(model, trgModel); + const { trgModel, srcModel, draggable } = validResult; + const droppable = trgModel instanceof Backbone.Collection ? 1 : validResult.droppable; + const isTextableActive = this.isTextableActive(srcModel, trgModel); + let modelToDrop, modelTemp, created; if (targetCollection && droppable && draggable) { - index = pos.method === 'after' ? index + 1 : index; - var opts = { at: index, noIncrement: 1 }; + const opts = { at: index, noIncrement: 1 }; if (!dropContent) { // Putting `avoidStore` here will make the UndoManager behave wrong opts.temporary = 1; modelTemp = targetCollection.add({}, { ...opts }); - if (model.collection) { - modelToDrop = model.collection.remove(model, { temporary: 1 }); + if (srcModel.collection) { + modelToDrop = srcModel.collection.remove(srcModel, { temporary: 1 }); } } else { modelToDrop = isFunction(dropContent) ? dropContent() : dropContent; @@ -1086,9 +1080,9 @@ export default Backbone.View.extend({ if (isTextableActive) { const viewActive = activeTextModel.getView(); activeTextModel.trigger('active'); - const modelEl = model.getEl(); - delete model.opt.temporary; - model.getView().render(); + const modelEl = srcModel.getEl(); + delete srcModel.opt.temporary; + srcModel.getView().render(); modelEl.setAttribute('data-gjs-textable', 'true'); const { outerHTML } = modelEl; activeTextModel.once('rte:enable', () => { @@ -1096,7 +1090,7 @@ export default Backbone.View.extend({ rte.insertHTML && rte.insertHTML(outerHTML); activeTextModel.trigger('disable'); }); - created = model; + created = srcModel; } else { created = targetCollection.add(modelToDrop, opts); } @@ -1110,28 +1104,28 @@ export default Backbone.View.extend({ // This will cause to recalculate children dimensions this.prevTarget = null; } else if (em) { + const dropInfo = validResult.dropInfo || trgModel?.get('droppable'); + const dragInfo = validResult.dragInfo || srcModel?.get('draggable'); + !targetCollection && warns.push('Target collection not found'); !droppable && dropInfo && warns.push(`Target is not droppable, accepts [${dropInfo}]`); !draggable && dragInfo && warns.push(`Component not draggable, acceptable by [${dragInfo}]`); em.logWarning('Invalid target position', { errors: warns, - model, + model: srcModel, context: 'sorter', target: trgModel, }); } - if (em) { - em.trigger('component:dragEnd', targetCollection, modelToDrop, warns); // @deprecated - em.trigger('sorter:drag:end', { - targetCollection, - modelToDrop, - warns, - validResult, - dst, - srcEl, - }); - } + em?.trigger('sorter:drag:end', { + targetCollection, + modelToDrop, + warns, + validResult, + dst, + srcEl, + }); return created; },