From fc4cb9cd831459b5465b396241b5cb16402a35ea Mon Sep 17 00:00:00 2001 From: Paulo Gustavo Veiga Date: Wed, 15 Dec 2021 17:59:51 -0800 Subject: [PATCH] Fix loading of relationships --- packages/mindplot/package.json | 6 ++- packages/mindplot/src/components/Designer.js | 14 +++--- packages/mindplot/src/components/LinkIcon.js | 2 +- packages/mindplot/src/components/Options.js | 4 +- .../src/components/model/FeatureModel.js | 1 + .../src/components/model/INodeModel.js | 3 +- .../mindplot/src/components/model/Mindmap.js | 20 +++----- .../src/components/model/NodeModel.js | 13 ++--- .../src/components/model/RelationshipModel.js | 2 + .../persistence/XMLSerializer_Pela.js | 50 +++++++++---------- 10 files changed, 53 insertions(+), 62 deletions(-) diff --git a/packages/mindplot/package.json b/packages/mindplot/package.json index 3fa20531..31280a6d 100644 --- a/packages/mindplot/package.json +++ b/packages/mindplot/package.json @@ -33,8 +33,10 @@ "dependencies": { "@wisemapping/core-js": "^0.0.1", "@wisemapping/web2d": "^0.0.1", + "add": "^2.0.6", "jest": "^27.4.3", - "jquery": "^3.6.0" + "jquery": "^3.6.0", + "lodash": "^4.17.21" }, "devDependencies": { "@babel/core": "^7.14.6", @@ -55,9 +57,9 @@ "eslint-plugin-only-warn": "^1.0.3", "html-webpack-plugin": "^5.3.2", "jest-webpack": "^0.5.1", - "mocha": "^9.1.3", "less": "^4.1.2", "less-loader": "^10.2.0", + "mocha": "^9.1.3", "nodemon": "^2.0.12", "start-server-and-test": "^1.14.0", "webpack": "^5.44.0", diff --git a/packages/mindplot/src/components/Designer.js b/packages/mindplot/src/components/Designer.js index 97995ccd..3cc2b49b 100644 --- a/packages/mindplot/src/components/Designer.js +++ b/packages/mindplot/src/components/Designer.js @@ -635,16 +635,16 @@ class Designer extends Events { } /** - * @param {mindplot.Mindmap} mindmapModel + * @param {mindplot.Mindmap} model * @throws will throw an error if mindmapModel is null or undefined */ - loadMap(mindmapModel) { - $assert(mindmapModel, 'mindmapModel can not be null'); - this._mindmap = mindmapModel; + loadMap(model) { + $assert(model, 'mindmapModel can not be null'); + this._mindmap = model; // Init layout manager ... const size = { width: 25, height: 25 }; - const layoutManager = new LayoutManager(mindmapModel.getCentralTopic().getId(), size); + const layoutManager = new LayoutManager(model.getCentralTopic().getId(), size); const me = this; layoutManager.addEvent('change', (event) => { const id = event.getId(); @@ -655,14 +655,14 @@ class Designer extends Events { this._eventBussDispatcher.setLayoutManager(layoutManager); // Building node graph ... - const branches = mindmapModel.getBranches(); + const branches = model.getBranches(); branches.forEach((branch) => { const nodeGraph = this.nodeModelToNodeGraph(branch); nodeGraph.setBranchVisibility(true); }); // Connect relationships ... - const relationships = mindmapModel.getRelationships(); + const relationships = model.getRelationships(); relationships.forEach((relationship) => this._relationshipModelToRelationship(relationship)); // Place the focus on the Central Topic diff --git a/packages/mindplot/src/components/LinkIcon.js b/packages/mindplot/src/components/LinkIcon.js index fd6b1bbe..d1ad72eb 100644 --- a/packages/mindplot/src/components/LinkIcon.js +++ b/packages/mindplot/src/components/LinkIcon.js @@ -47,7 +47,7 @@ class LinkIcon extends Icon { }); // FIXME: we shouldn't have timeout of that.. this.addEvent('mouseleave', (event) => { - window.setTimeout(() => { + setTimeout(() => { if (!$('#linkPopover:hover').length) { me._tip.hide(); } diff --git a/packages/mindplot/src/components/Options.js b/packages/mindplot/src/components/Options.js index 84c84469..a62cb87f 100644 --- a/packages/mindplot/src/components/Options.js +++ b/packages/mindplot/src/components/Options.js @@ -1,12 +1,11 @@ class Options { - setOptions(...args) { this.options = { ...this.options, ...args }; const { options } = this; if (this.addEvent) { for (const option in options) { - if (typeof (options[option]) != 'function' || !(/^on[A-Z]/).test(option) ){ + if (typeof (options[option]) !== 'function' || !(/^on[A-Z]/).test(option)) { continue; } this.addEvent(option, options[option]); @@ -15,7 +14,6 @@ class Options { } return this; } - } export default Options; diff --git a/packages/mindplot/src/components/model/FeatureModel.js b/packages/mindplot/src/components/model/FeatureModel.js index 2d0f31f8..90f1d3d2 100644 --- a/packages/mindplot/src/components/model/FeatureModel.js +++ b/packages/mindplot/src/components/model/FeatureModel.js @@ -74,6 +74,7 @@ class FeatureModel { /** */ setId(id) { + $assert(Number.isFinite(id)); this._id = id; } diff --git a/packages/mindplot/src/components/model/INodeModel.js b/packages/mindplot/src/components/model/INodeModel.js index e9f79c13..bffece9d 100644 --- a/packages/mindplot/src/components/model/INodeModel.js +++ b/packages/mindplot/src/components/model/INodeModel.js @@ -31,6 +31,7 @@ class INodeModel { /** */ setId(id) { + $assert(Number.isFinite(id)); if ($defined(id) && id > INodeModel._uuid) { INodeModel._uuid = id; } @@ -140,7 +141,7 @@ class INodeModel { /** */ setOrder(value) { $assert( - (typeof value === 'number' && isFinite(value)) || value == null, + (typeof value === 'number' && Number.isFinite(value)) || value == null, 'Order must be null or a number', ); this.putProperty('order', value); diff --git a/packages/mindplot/src/components/model/Mindmap.js b/packages/mindplot/src/components/model/Mindmap.js index 9f784e37..bf3760ab 100644 --- a/packages/mindplot/src/components/model/Mindmap.js +++ b/packages/mindplot/src/components/model/Mindmap.js @@ -127,12 +127,12 @@ class Mindmap extends IMindmap { } /** - * @param sourceNodeId - * @param targetNodeId - * @throws will throw an error if source node is null or undefined - * @throws will throw an error if target node is null or undefined - * @return the relationship model created - */ + * @param sourceNodeId + * @param targetNodeId + * @throws will throw an error if source node is null or undefined + * @throws will throw an error if target node is null or undefined + * @return the relationship model created + */ createRelationship(sourceNodeId, targetNodeId) { $assert($defined(sourceNodeId), 'from node cannot be null'); $assert($defined(targetNodeId), 'to node cannot be null'); @@ -141,8 +141,8 @@ class Mindmap extends IMindmap { } /** - * @param relationship - */ + * @param relationship + */ addRelationship(relationship) { this._relationships.push(relationship); } @@ -154,10 +154,6 @@ class Mindmap extends IMindmap { this._relationships = this._branches.filter((r) => r !== relationship); } - /** - * @param id - * @return the node with the respective id or null if not in the mindmap - */ findNodeById(id) { let result = null; for (let i = 0; i < this._branches.length; i++) { diff --git a/packages/mindplot/src/components/model/NodeModel.js b/packages/mindplot/src/components/model/NodeModel.js index 286c90c6..5f4370dd 100644 --- a/packages/mindplot/src/components/model/NodeModel.js +++ b/packages/mindplot/src/components/model/NodeModel.js @@ -16,6 +16,7 @@ * limitations under the License. */ import { $assert, $defined } from '@wisemapping/core-js'; +import { cloneDeep } from 'lodash'; import INodeModel from './INodeModel'; import TopicFeature from '../TopicFeature'; @@ -121,16 +122,7 @@ class NodeModel extends INodeModel { * @return {mindplot.model.NodeModel} an identical clone of the NodeModel */ clone() { - const result = new NodeModel(this.getType(), this._mindmap); - result._children = this._children.map((node) => { - const cnode = node.clone(); - cnode._parent = result; - return cnode; - }); - - result._properties = { ...this._properties }; - result._feature = { ...this._feature }; - return result; + return cloneDeep(this); } /** @@ -211,6 +203,7 @@ class NodeModel extends INodeModel { * @return {mindplot.model.NodeModel} the node with the respective id */ findNodeById(id) { + $assert(Number.isFinite(id)); let result = null; if (this.getId() === id) { result = this; diff --git a/packages/mindplot/src/components/model/RelationshipModel.js b/packages/mindplot/src/components/model/RelationshipModel.js index a787f24d..687b3fad 100644 --- a/packages/mindplot/src/components/model/RelationshipModel.js +++ b/packages/mindplot/src/components/model/RelationshipModel.js @@ -22,6 +22,8 @@ class RelationshipModel { constructor(sourceTopicId, targetTopicId) { $assert($defined(sourceTopicId), 'from node type can not be null'); $assert($defined(targetTopicId), 'to node type can not be null'); + $assert(Number.isFinite(sourceTopicId), 'sourceTopicId is not a number'); + $assert(Number.isFinite(targetTopicId), 'targetTopicId is not a number'); this._id = RelationshipModel._nextUUID(); this._sourceTargetId = sourceTopicId; diff --git a/packages/mindplot/src/components/persistence/XMLSerializer_Pela.js b/packages/mindplot/src/components/persistence/XMLSerializer_Pela.js index ab2736da..72f9f495 100644 --- a/packages/mindplot/src/components/persistence/XMLSerializer_Pela.js +++ b/packages/mindplot/src/components/persistence/XMLSerializer_Pela.js @@ -247,30 +247,28 @@ class XMLSerializer_Pela { this._idsMap = {}; // Start the loading process ... const version = rootElem.getAttribute('version'); - const mindmap = new Mindmap(mapId, version); - const children = rootElem.childNodes; - for (let i = 0; i < children.length; i++) { - const child = children[i]; - if (child.nodeType === 1) { - switch (child.tagName) { - case 'topic': { - const topic = this._deserializeNode(child, mindmap); - mindmap.addBranch(topic); - break; - } - case 'relationship': { - const relationship = XMLSerializer_Pela._deserializeRelationship(child, mindmap); - if (relationship != null) { - mindmap.addRelationship(relationship); - } - break; - } - default: - break; - } + + // Add all the topics nodes ... + const childNodes = Array.from(rootElem.childNodes); + const topicsNodes = childNodes.filter((child) => (child.nodeType === 1 && child.tagName === 'topic')); + topicsNodes.forEach((child) => { + const topic = this._deserializeNode(child, mindmap); + mindmap.addBranch(topic); + }); + + // Then all relationshops, they are connected to topics ... + const relationshipsNodes = childNodes.filter((child) => (child.nodeType === 1 && child.tagName === 'relationship')); + relationshipsNodes.forEach((child) => { + try { + const relationship = XMLSerializer_Pela._deserializeRelationship(child, mindmap); + mindmap.addRelationship(relationship); + } catch (e) { + console.error(e); } - } + }); + + // Clean up from the recursion ... this._idsMap = null; mindmap.setId(mapId); return mindmap; @@ -446,19 +444,19 @@ class XMLSerializer_Pela { } static _deserializeRelationship(domElement, mindmap) { - const srcId = domElement.getAttribute('srcTopicId'); - const destId = domElement.getAttribute('destTopicId'); + const srcId = Number.parseInt(domElement.getAttribute('srcTopicId'), 10); + const destId = Number.parseInt(domElement.getAttribute('destTopicId'), 10); const lineType = domElement.getAttribute('lineType'); const srcCtrlPoint = domElement.getAttribute('srcCtrlPoint'); const destCtrlPoint = domElement.getAttribute('destCtrlPoint'); // If for some reason a relationship lines has source and dest nodes the same, don't import it. if (srcId === destId) { - return null; + throw new Error('Invalid relationship, dest and source are equals'); } // Is the connections points valid ?. If it's not, do not load the relationship ... if (mindmap.findNodeById(srcId) == null || mindmap.findNodeById(destId) == null) { - return null; + throw new Error('Transition could not created, missing node for relationship'); } const model = mindmap.createRelationship(srcId, destId);