From b8d1a5059d4d55405157fcd6c4b50098e21ec234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Wed, 11 Oct 2023 11:15:07 -0300 Subject: [PATCH 01/20] Add support for boundaries --- src/components/modeler/Modeler.vue | 7 ++- .../nodes/boundaryEvent/boundaryEvent.vue | 41 ++++++++++++++- src/multiplayer/multiplayer.js | 51 ++++++++++++++++++- src/portsUtils.js | 3 ++ 4 files changed, 99 insertions(+), 3 deletions(-) diff --git a/src/components/modeler/Modeler.vue b/src/components/modeler/Modeler.vue index 2e7b62f63..2d174c1aa 100644 --- a/src/components/modeler/Modeler.vue +++ b/src/components/modeler/Modeler.vue @@ -1064,9 +1064,14 @@ export default { diagram.bounds.y = y; const newNode = this.createNode(control.type, definition, diagram); - if (newNode.isBpmnType('bpmn:BoundaryEvent')) { this.setShapeCenterUnderCursor(diagram); + + const parentNode = this.nodes.find(n => n.definition.id === data.control.attachedToRef.id); + if (parentNode) { + console.log('parentnode found'); + console.log(parentNode); + } } if (selected) { this.highlightNode(newNode); diff --git a/src/components/nodes/boundaryEvent/boundaryEvent.vue b/src/components/nodes/boundaryEvent/boundaryEvent.vue index 9f7246225..126d6b8b3 100644 --- a/src/components/nodes/boundaryEvent/boundaryEvent.vue +++ b/src/components/nodes/boundaryEvent/boundaryEvent.vue @@ -65,6 +65,12 @@ export default { }, methods: { getTaskUnderShape() { + console.log('this.graphaaa'); + console.log(this.graph); + console.log('this.shapeaaa'); + console.log(this.shape); + console.log('this.graph.findModelsUnderElement(this.shape)'); + console.log(this.graph.findModelsUnderElement(this.shape)); return this.graph .findModelsUnderElement(this.shape) .find(model => isValidBoundaryEventTarget(model.component)); @@ -119,7 +125,8 @@ export default { if (!this.hasPositionChanged()) { return; } - + console.log('task'); + console.log(task); const { x, y } = getBoundaryAnchorPoint(this.getCenterPosition(), task); const { width, height } = this.shape.size(); this.shape.position(x - (width / 2), y - (height / 2)); @@ -202,6 +209,37 @@ export default { this.invalidTargetElement = targetElement; }, + addMultiplayerBoundaryEvent(task) { + console.log('Add multiplayerBoundaryEvent boundaryEvent.vue'); + console.log(this.node); + console.log('Add multiplayer boudnary is multiplayer and node is boundary'); + const control = { + bpmnType: this.node.diagram.$type, + // icon:, + id: this.node.diagram.id, + type: this.node.type, + attachedToRef: this.node.definition.get('attachedToRef'), + // task, + }; + + const { paper } = window.ProcessMaker.$modeler; + const { x: clientX, y: clientY } = paper.localToClientPoint(this.node.diagram.bounds); + + console.log({ + clientX, + clientY, + control, + id: this.node.definition.id,//`node_${this.nodeIdGenerator.getDefinitionNumber()}`, + }); + + window.ProcessMaker.EventBus.$emit('multiplayer-addBoundaryEvent', { + clientX: clientX + 18, + clientY: clientY + 18, + control, + type: this.node.type, + id: this.node.definition.id,//`node_${this.nodeIdGenerator.getDefinitionNumber()}`, + }); + }, }, async mounted() { this.shape = new EventShape(); @@ -214,6 +252,7 @@ export default { const task = this.getTaskUnderShape(); this.attachBoundaryEventToTask(task); this.updateShapePosition(task); + this.addMultiplayerBoundaryEvent(task); }, }; diff --git a/src/multiplayer/multiplayer.js b/src/multiplayer/multiplayer.js index 92762c0c9..ad2a99de8 100644 --- a/src/multiplayer/multiplayer.js +++ b/src/multiplayer/multiplayer.js @@ -6,6 +6,13 @@ import { faker } from '@faker-js/faker'; import MessageFlow from '@/components/nodes/genericFlow/MessageFlow'; import SequenceFlow from '@/components/nodes/genericFlow/SequenceFlow'; import DataOutputAssociation from '@/components/nodes/genericFlow/DataOutputAssociation'; +import { id as boundaryErrorEventId } from '@/components/nodes/boundaryErrorEvent'; +import { id as boundaryConditionalEventId } from '@/components/nodes/boundaryConditionalEvent'; +import { id as boundaryEscalationEventId } from '@/components/nodes/boundaryEscalationEvent'; +import { id as boundaryMessageEventId } from '@/components/nodes/boundaryMessageEvent'; +import { id as boundarySignalEventId } from '@/components/nodes/boundarySignalEvent'; +import { id as boundaryTimerEventId } from '@/components/nodes/boundaryTimerEvent'; + const BpmnFlows = [ { type: 'processmaker-modeler-text-annotation', @@ -87,6 +94,9 @@ export default class Multiplayer { // Listen for updates when a new element is added this.clientIO.on('createElement', async(payload) => { // Create the new element in the process + console.log('on createElement'); + console.log(payload); + console.log(payload.changes); await this.createRemoteShape(payload.changes); // Add the new element to the shared array Y.applyUpdate(this.yDoc, new Uint8Array(payload.updateDoc)); @@ -140,6 +150,10 @@ export default class Multiplayer { window.ProcessMaker.EventBus.$on('multiplayer-addFlow', ( data ) => { this.addFlow(data); }); + + window.ProcessMaker.EventBus.$on('multiplayer-addBoundaryEvent', ( data ) => { + this.addBoundaryEvent(data); + }); } addNode(data) { // Add the new element to the process @@ -158,6 +172,15 @@ export default class Multiplayer { this.modeler.handleDropProcedure(value, false); this.#nodeIdGenerator.updateCounters(); } + createBoundaryEvent(value) { + // create a different method instead handle drop procedure + // This method should: + // Find the parent node using an id + // create the boundary node + // attach the boundary to the parent node found + this.modeler.handleDropProcedure(value, false); + this.#nodeIdGenerator.updateCounters(); + } createRemoteShape(changes) { const flows = [ 'processmaker-modeler-sequence-flow', @@ -165,11 +188,25 @@ export default class Multiplayer { 'processmaker-modeler-message-flow', 'processmaker-modeler-data-input-association', ]; + + const boundaries = [ + boundaryErrorEventId, + boundaryConditionalEventId, + boundaryEscalationEventId, + boundaryMessageEventId, + boundarySignalEventId, + boundaryTimerEventId, + ]; + return new Promise(resolve => { changes.map((data) => { if (flows.includes(data.type)) { this.createFlow(data); - } else { + } + else if (boundaries.includes(data.type)) { + this.createBoundaryEvent(data); + } + else { this.createShape(data); } }); @@ -312,4 +349,16 @@ export default class Multiplayer { } } + addBoundaryEvent(data) { + const yMapNested = new Y.Map(); + this.doTransact(yMapNested, data); + this.yArray.push([yMapNested]); + // Encode the state as an update and send it to the server + const stateUpdate = Y.encodeStateAsUpdate(this.yDoc); + // Send the update to the web socket server + console.log('addBoundaryEvent Multiplayer.js'); + console.log(data); + this.clientIO.emit('createElement', stateUpdate); + this.#nodeIdGenerator.updateCounters(); + } } diff --git a/src/portsUtils.js b/src/portsUtils.js index 99d9f3a39..a694e3a61 100644 --- a/src/portsUtils.js +++ b/src/portsUtils.js @@ -4,6 +4,8 @@ import differenceWith from 'lodash/differenceWith'; import isEqual from 'lodash/isEqual'; function getModelPortPoints(model, group) { + + console.log(model, group); const { x: modelX, y: modelY } = model.position(); const points = Object.values(model.getPortsPositions(group)) .map(({ x, y }) => new g.Point(modelX + x, modelY + y)); @@ -16,6 +18,7 @@ function getModelPortPoints(model, group) { } function getClosestAnchorPoint(model, coords, group) { + console.log(coords); const referencePoint = new g.Point(coords.x, coords.y); return referencePoint.chooseClosest(getModelPortPoints(model, group)); } From be8fcda8b659b920a9fcf6c7dc07b48112e212b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Wed, 11 Oct 2023 11:19:46 -0300 Subject: [PATCH 02/20] Remove unused parameter --- src/components/nodes/boundaryEvent/boundaryEvent.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/nodes/boundaryEvent/boundaryEvent.vue b/src/components/nodes/boundaryEvent/boundaryEvent.vue index 126d6b8b3..af13e2af3 100644 --- a/src/components/nodes/boundaryEvent/boundaryEvent.vue +++ b/src/components/nodes/boundaryEvent/boundaryEvent.vue @@ -209,7 +209,7 @@ export default { this.invalidTargetElement = targetElement; }, - addMultiplayerBoundaryEvent(task) { + addMultiplayerBoundaryEvent() { console.log('Add multiplayerBoundaryEvent boundaryEvent.vue'); console.log(this.node); console.log('Add multiplayer boudnary is multiplayer and node is boundary'); @@ -252,7 +252,7 @@ export default { const task = this.getTaskUnderShape(); this.attachBoundaryEventToTask(task); this.updateShapePosition(task); - this.addMultiplayerBoundaryEvent(task); + this.addMultiplayerBoundaryEvent(); }, }; From 0ef9b593527efa16936c08a5137297d68ea7b9d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Wed, 11 Oct 2023 12:39:15 -0300 Subject: [PATCH 03/20] Emit only if boundary was created from crown --- .../crownBoundaryEventDropdown.vue | 1 + .../nodes/boundaryEvent/boundaryEvent.vue | 26 +++++-------------- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/src/components/crown/crownButtons/crownBoundaryEventDropdown.vue b/src/components/crown/crownButtons/crownBoundaryEventDropdown.vue index 300596542..828f9e8be 100644 --- a/src/components/crown/crownButtons/crownBoundaryEventDropdown.vue +++ b/src/components/crown/crownButtons/crownBoundaryEventDropdown.vue @@ -90,6 +90,7 @@ export default { const node = new Node(nodeType, definition, diagram); node.pool = this.node.pool; + node.fromCrown = true; store.commit('highlightNode', node); diff --git a/src/components/nodes/boundaryEvent/boundaryEvent.vue b/src/components/nodes/boundaryEvent/boundaryEvent.vue index af13e2af3..4d8271b92 100644 --- a/src/components/nodes/boundaryEvent/boundaryEvent.vue +++ b/src/components/nodes/boundaryEvent/boundaryEvent.vue @@ -65,12 +65,6 @@ export default { }, methods: { getTaskUnderShape() { - console.log('this.graphaaa'); - console.log(this.graph); - console.log('this.shapeaaa'); - console.log(this.shape); - console.log('this.graph.findModelsUnderElement(this.shape)'); - console.log(this.graph.findModelsUnderElement(this.shape)); return this.graph .findModelsUnderElement(this.shape) .find(model => isValidBoundaryEventTarget(model.component)); @@ -125,8 +119,7 @@ export default { if (!this.hasPositionChanged()) { return; } - console.log('task'); - console.log(task); + const { x, y } = getBoundaryAnchorPoint(this.getCenterPosition(), task); const { width, height } = this.shape.size(); this.shape.position(x - (width / 2), y - (height / 2)); @@ -210,9 +203,6 @@ export default { this.invalidTargetElement = targetElement; }, addMultiplayerBoundaryEvent() { - console.log('Add multiplayerBoundaryEvent boundaryEvent.vue'); - console.log(this.node); - console.log('Add multiplayer boudnary is multiplayer and node is boundary'); const control = { bpmnType: this.node.diagram.$type, // icon:, @@ -224,20 +214,13 @@ export default { const { paper } = window.ProcessMaker.$modeler; const { x: clientX, y: clientY } = paper.localToClientPoint(this.node.diagram.bounds); - - console.log({ - clientX, - clientY, - control, - id: this.node.definition.id,//`node_${this.nodeIdGenerator.getDefinitionNumber()}`, - }); window.ProcessMaker.EventBus.$emit('multiplayer-addBoundaryEvent', { clientX: clientX + 18, clientY: clientY + 18, control, type: this.node.type, - id: this.node.definition.id,//`node_${this.nodeIdGenerator.getDefinitionNumber()}`, + id: this.node.definition.id, }); }, }, @@ -252,7 +235,10 @@ export default { const task = this.getTaskUnderShape(); this.attachBoundaryEventToTask(task); this.updateShapePosition(task); - this.addMultiplayerBoundaryEvent(); + + if (this.node.fromCrown) { + this.addMultiplayerBoundaryEvent(); + } }, }; From 38e9e1bfb4784516db4e4aa9430356a4b9dd1f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Wed, 11 Oct 2023 12:39:32 -0300 Subject: [PATCH 04/20] Remove comments and unneeded code --- src/components/modeler/Modeler.vue | 6 ------ src/multiplayer/multiplayer.js | 7 ++----- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/components/modeler/Modeler.vue b/src/components/modeler/Modeler.vue index 2d174c1aa..7634a187f 100644 --- a/src/components/modeler/Modeler.vue +++ b/src/components/modeler/Modeler.vue @@ -1066,12 +1066,6 @@ export default { const newNode = this.createNode(control.type, definition, diagram); if (newNode.isBpmnType('bpmn:BoundaryEvent')) { this.setShapeCenterUnderCursor(diagram); - - const parentNode = this.nodes.find(n => n.definition.id === data.control.attachedToRef.id); - if (parentNode) { - console.log('parentnode found'); - console.log(parentNode); - } } if (selected) { this.highlightNode(newNode); diff --git a/src/multiplayer/multiplayer.js b/src/multiplayer/multiplayer.js index ad2a99de8..6306f59bf 100644 --- a/src/multiplayer/multiplayer.js +++ b/src/multiplayer/multiplayer.js @@ -94,9 +94,6 @@ export default class Multiplayer { // Listen for updates when a new element is added this.clientIO.on('createElement', async(payload) => { // Create the new element in the process - console.log('on createElement'); - console.log(payload); - console.log(payload.changes); await this.createRemoteShape(payload.changes); // Add the new element to the shared array Y.applyUpdate(this.yDoc, new Uint8Array(payload.updateDoc)); @@ -249,6 +246,8 @@ export default class Multiplayer { }); } updateNodes(data) { + console.log('updateNodes multiplayer.js'); + console.log(data); data.forEach((value) => { const index = this.getIndex(value.id); const nodeToUpdate = this.yArray.get(index); @@ -356,8 +355,6 @@ export default class Multiplayer { // Encode the state as an update and send it to the server const stateUpdate = Y.encodeStateAsUpdate(this.yDoc); // Send the update to the web socket server - console.log('addBoundaryEvent Multiplayer.js'); - console.log(data); this.clientIO.emit('createElement', stateUpdate); this.#nodeIdGenerator.updateCounters(); } From d8338bcbfbd036b0189a264c401dbbd883a4d86a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Wed, 11 Oct 2023 12:40:16 -0300 Subject: [PATCH 05/20] Add position change when dragging the boundary --- src/components/modeler/Selection.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/modeler/Selection.vue b/src/components/modeler/Selection.vue index 4707c5f8a..a12054f68 100644 --- a/src/components/modeler/Selection.vue +++ b/src/components/modeler/Selection.vue @@ -588,7 +588,6 @@ export default { const shapesToNotTranslate = [ 'PoolLane', 'standard.Link', - 'processmaker.components.nodes.boundaryEvent.Shape', ]; this.selected.filter(shape => !shapesToNotTranslate.includes(shape.model.get('type'))) .forEach(shape => { From c2ae3a1b878205ff9d6f551438e41e93f4a196b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Thu, 12 Oct 2023 10:57:43 -0300 Subject: [PATCH 06/20] Remove logs and unused code --- src/components/nodes/boundaryEvent/boundaryEvent.vue | 2 -- src/multiplayer/multiplayer.js | 2 -- src/portsUtils.js | 2 -- 3 files changed, 6 deletions(-) diff --git a/src/components/nodes/boundaryEvent/boundaryEvent.vue b/src/components/nodes/boundaryEvent/boundaryEvent.vue index 4d8271b92..02a013d60 100644 --- a/src/components/nodes/boundaryEvent/boundaryEvent.vue +++ b/src/components/nodes/boundaryEvent/boundaryEvent.vue @@ -205,11 +205,9 @@ export default { addMultiplayerBoundaryEvent() { const control = { bpmnType: this.node.diagram.$type, - // icon:, id: this.node.diagram.id, type: this.node.type, attachedToRef: this.node.definition.get('attachedToRef'), - // task, }; const { paper } = window.ProcessMaker.$modeler; diff --git a/src/multiplayer/multiplayer.js b/src/multiplayer/multiplayer.js index 6306f59bf..9cb2a6ad1 100644 --- a/src/multiplayer/multiplayer.js +++ b/src/multiplayer/multiplayer.js @@ -246,8 +246,6 @@ export default class Multiplayer { }); } updateNodes(data) { - console.log('updateNodes multiplayer.js'); - console.log(data); data.forEach((value) => { const index = this.getIndex(value.id); const nodeToUpdate = this.yArray.get(index); diff --git a/src/portsUtils.js b/src/portsUtils.js index a694e3a61..768dcd73b 100644 --- a/src/portsUtils.js +++ b/src/portsUtils.js @@ -5,7 +5,6 @@ import isEqual from 'lodash/isEqual'; function getModelPortPoints(model, group) { - console.log(model, group); const { x: modelX, y: modelY } = model.position(); const points = Object.values(model.getPortsPositions(group)) .map(({ x, y }) => new g.Point(modelX + x, modelY + y)); @@ -18,7 +17,6 @@ function getModelPortPoints(model, group) { } function getClosestAnchorPoint(model, coords, group) { - console.log(coords); const referencePoint = new g.Point(coords.x, coords.y); return referencePoint.chooseClosest(getModelPortPoints(model, group)); } From e78fdd63cff4e83797e38113793e9e2961333f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Thu, 12 Oct 2023 10:58:12 -0300 Subject: [PATCH 07/20] Fix issue with position when moving the parent task --- src/components/modeler/Selection.vue | 42 +++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/components/modeler/Selection.vue b/src/components/modeler/Selection.vue index a12054f68..ad12c5d80 100644 --- a/src/components/modeler/Selection.vue +++ b/src/components/modeler/Selection.vue @@ -35,8 +35,15 @@ import { id as associationId } from '@/components/nodes/association'; import { id as messageFlowId } from '@/components/nodes/messageFlow/config'; import { id as dataOutputAssociationFlowId } from '@/components/nodes/dataOutputAssociation/config'; import { id as dataInputAssociationFlowId } from '@/components/nodes/dataInputAssociation/config'; +import { id as boundaryErrorEventId } from '@/components/nodes/boundaryErrorEvent'; +import { id as boundaryConditionalEventId } from '@/components/nodes/boundaryConditionalEvent'; +import { id as boundaryEscalationEventId } from '@/components/nodes/boundaryEscalationEvent'; +import { id as boundaryMessageEventId } from '@/components/nodes/boundaryMessageEvent'; +import { id as boundarySignalEventId } from '@/components/nodes/boundarySignalEvent'; +import { id as boundaryTimerEventId } from '@/components/nodes/boundaryTimerEvent'; import { labelWidth, poolPadding } from '../nodes/pool/poolSizes'; import { invalidNodeColor, poolColor } from '@/components/nodeColors'; +import { log } from '@processmaker/screen-builder'; export default { name: 'Selection', @@ -584,7 +591,7 @@ export default { }, getProperties() { - const changed = []; + let changed = []; const shapesToNotTranslate = [ 'PoolLane', 'standard.Link', @@ -598,9 +605,42 @@ export default { clientY: shape.model.get('position').y, }, }); + const boundariesChanges = this.getBoundariesChangesForShape(shape); + changed = changed.concat(boundariesChanges); }); return changed; }, + + /** + * Get properties for each boundary inside a shape + */ + getBoundariesChangesForShape(shape) { + let boundariesChanged = []; + const boundaryEventTypes = [ + boundaryErrorEventId, + boundaryConditionalEventId, + boundaryEscalationEventId, + boundaryMessageEventId, + boundarySignalEventId, + boundaryTimerEventId, + ]; + + const boundaryNodes = window.ProcessMaker.$modeler.nodes.filter(node => boundaryEventTypes.includes(node.type)); + + boundaryNodes.forEach(boundaryNode => { + if (boundaryNode.definition.attachedToRef.id === shape.model.component.node.definition.id) { + boundariesChanged.push({ + id: boundaryNode.definition.id, + properties: { + clientX: boundaryNode.diagram.bounds.x, + clientY: boundaryNode.diagram.bounds.y, + }, + }); + } + }); + + return boundariesChanged; + }, /** * Selector will update the waypoints of the related flows */ From 0e1ae3f69161082102f5dbce9890b80f45a07c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Thu, 12 Oct 2023 11:02:22 -0300 Subject: [PATCH 08/20] Remove unused --- src/components/modeler/Selection.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/modeler/Selection.vue b/src/components/modeler/Selection.vue index ad12c5d80..f86a50009 100644 --- a/src/components/modeler/Selection.vue +++ b/src/components/modeler/Selection.vue @@ -43,7 +43,6 @@ import { id as boundarySignalEventId } from '@/components/nodes/boundarySignalEv import { id as boundaryTimerEventId } from '@/components/nodes/boundaryTimerEvent'; import { labelWidth, poolPadding } from '../nodes/pool/poolSizes'; import { invalidNodeColor, poolColor } from '@/components/nodeColors'; -import { log } from '@processmaker/screen-builder'; export default { name: 'Selection', From 49a4d5c837e591dd87456367ba1aa4cbc1687a57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Thu, 12 Oct 2023 11:05:14 -0300 Subject: [PATCH 09/20] Improve code --- src/multiplayer/multiplayer.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/multiplayer/multiplayer.js b/src/multiplayer/multiplayer.js index 9cb2a6ad1..eadf997e5 100644 --- a/src/multiplayer/multiplayer.js +++ b/src/multiplayer/multiplayer.js @@ -169,15 +169,6 @@ export default class Multiplayer { this.modeler.handleDropProcedure(value, false); this.#nodeIdGenerator.updateCounters(); } - createBoundaryEvent(value) { - // create a different method instead handle drop procedure - // This method should: - // Find the parent node using an id - // create the boundary node - // attach the boundary to the parent node found - this.modeler.handleDropProcedure(value, false); - this.#nodeIdGenerator.updateCounters(); - } createRemoteShape(changes) { const flows = [ 'processmaker-modeler-sequence-flow', @@ -200,9 +191,6 @@ export default class Multiplayer { if (flows.includes(data.type)) { this.createFlow(data); } - else if (boundaries.includes(data.type)) { - this.createBoundaryEvent(data); - } else { this.createShape(data); } From 2b6bbb39fc1b7a7172b08303f743f5859d63c724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Thu, 12 Oct 2023 11:05:57 -0300 Subject: [PATCH 10/20] Remove unused const --- src/multiplayer/multiplayer.js | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/multiplayer/multiplayer.js b/src/multiplayer/multiplayer.js index eadf997e5..67957d715 100644 --- a/src/multiplayer/multiplayer.js +++ b/src/multiplayer/multiplayer.js @@ -6,12 +6,6 @@ import { faker } from '@faker-js/faker'; import MessageFlow from '@/components/nodes/genericFlow/MessageFlow'; import SequenceFlow from '@/components/nodes/genericFlow/SequenceFlow'; import DataOutputAssociation from '@/components/nodes/genericFlow/DataOutputAssociation'; -import { id as boundaryErrorEventId } from '@/components/nodes/boundaryErrorEvent'; -import { id as boundaryConditionalEventId } from '@/components/nodes/boundaryConditionalEvent'; -import { id as boundaryEscalationEventId } from '@/components/nodes/boundaryEscalationEvent'; -import { id as boundaryMessageEventId } from '@/components/nodes/boundaryMessageEvent'; -import { id as boundarySignalEventId } from '@/components/nodes/boundarySignalEvent'; -import { id as boundaryTimerEventId } from '@/components/nodes/boundaryTimerEvent'; const BpmnFlows = [ { @@ -177,15 +171,6 @@ export default class Multiplayer { 'processmaker-modeler-data-input-association', ]; - const boundaries = [ - boundaryErrorEventId, - boundaryConditionalEventId, - boundaryEscalationEventId, - boundaryMessageEventId, - boundarySignalEventId, - boundaryTimerEventId, - ]; - return new Promise(resolve => { changes.map((data) => { if (flows.includes(data.type)) { From a377c7452739a0074019dd604e32bdc1826d56b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Thu, 12 Oct 2023 16:59:38 -0300 Subject: [PATCH 11/20] Attach boundary to new task --- src/components/modeler/Modeler.vue | 1 + src/components/modeler/Selection.vue | 3 ++- .../nodes/boundaryEvent/boundaryEvent.vue | 1 + src/multiplayer/multiplayer.js | 24 ++++++++++++++++++- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/components/modeler/Modeler.vue b/src/components/modeler/Modeler.vue index 7634a187f..cab87631f 100644 --- a/src/components/modeler/Modeler.vue +++ b/src/components/modeler/Modeler.vue @@ -1043,6 +1043,7 @@ export default { clientY, control, id: `node_${this.nodeIdGenerator.getDefinitionNumber()}`, + attachedToRefId: null, }); } else { this.handleDropProcedure(data); diff --git a/src/components/modeler/Selection.vue b/src/components/modeler/Selection.vue index f86a50009..f6808f780 100644 --- a/src/components/modeler/Selection.vue +++ b/src/components/modeler/Selection.vue @@ -602,6 +602,7 @@ export default { properties: { clientX: shape.model.get('position').x, clientY: shape.model.get('position').y, + attachedToRefId: shape.model.component.node.definition.get('attachedToRef')?.id ?? null, }, }); const boundariesChanges = this.getBoundariesChangesForShape(shape); @@ -633,11 +634,11 @@ export default { properties: { clientX: boundaryNode.diagram.bounds.x, clientY: boundaryNode.diagram.bounds.y, + attachedToRefId: boundaryNode.definition.get('attachedToRef')?.id ?? null, }, }); } }); - return boundariesChanged; }, /** diff --git a/src/components/nodes/boundaryEvent/boundaryEvent.vue b/src/components/nodes/boundaryEvent/boundaryEvent.vue index 02a013d60..e669e36a1 100644 --- a/src/components/nodes/boundaryEvent/boundaryEvent.vue +++ b/src/components/nodes/boundaryEvent/boundaryEvent.vue @@ -216,6 +216,7 @@ export default { window.ProcessMaker.EventBus.$emit('multiplayer-addBoundaryEvent', { clientX: clientX + 18, clientY: clientY + 18, + attachedToRefId: this.node.definition.get('attachedToRef')?.id, control, type: this.node.type, id: this.node.definition.id, diff --git a/src/multiplayer/multiplayer.js b/src/multiplayer/multiplayer.js index 67957d715..ebfe515c5 100644 --- a/src/multiplayer/multiplayer.js +++ b/src/multiplayer/multiplayer.js @@ -243,7 +243,6 @@ export default class Multiplayer { // Encode the state as an update and send it to the server const stateUpdate = Y.encodeStateAsUpdate(this.yDoc); - this.clientIO.emit('updateElement', { updateDoc: stateUpdate, isReplaced: true }); } replaceShape(updatedNode) { @@ -281,9 +280,32 @@ export default class Multiplayer { const element = this.getJointElement(paper.model, data.id); // Update the element's position attribute element.set('position', { x:data.clientX, y:data.clientY }); + + if (element.component.node.definition.$type === 'bpmn:BoundaryEvent') { + this.attachBoundaryEventToNode(element, data); + } + // Trigger a rendering of the element on the paper paper.findViewByModel(element).update(); } + attachBoundaryEventToNode(element, data) { + const { paper } = this.modeler; + let node = this.getNodeById(data.attachedToRefId); + + // Find previous attached task + const previousAttachedTask = element.getParentCell(); + + // Find new attached task + const newAttachedTask = this.getJointElement(paper.model, data.attachedToRefId); + + if (previousAttachedTask) { + previousAttachedTask.unembed(element); + } + newAttachedTask.embed(element); + + element.component.node.definition.set('attachedToRef', node.definition); + } + getJointElement(graph, targetValue) { const cells = graph.getCells(); for (const cell of cells) { From 3430b2d9690170f24cb6086853bf308f57b74b99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Thu, 12 Oct 2023 17:26:16 -0300 Subject: [PATCH 12/20] Address comments --- src/multiplayer/multiplayer.js | 5 ++--- src/portsUtils.js | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/multiplayer/multiplayer.js b/src/multiplayer/multiplayer.js index ebfe515c5..a19d11d53 100644 --- a/src/multiplayer/multiplayer.js +++ b/src/multiplayer/multiplayer.js @@ -175,8 +175,7 @@ export default class Multiplayer { changes.map((data) => { if (flows.includes(data.type)) { this.createFlow(data); - } - else { + } else { this.createShape(data); } }); @@ -290,7 +289,7 @@ export default class Multiplayer { } attachBoundaryEventToNode(element, data) { const { paper } = this.modeler; - let node = this.getNodeById(data.attachedToRefId); + const node = this.getNodeById(data.attachedToRefId); // Find previous attached task const previousAttachedTask = element.getParentCell(); diff --git a/src/portsUtils.js b/src/portsUtils.js index 768dcd73b..99d9f3a39 100644 --- a/src/portsUtils.js +++ b/src/portsUtils.js @@ -4,7 +4,6 @@ import differenceWith from 'lodash/differenceWith'; import isEqual from 'lodash/isEqual'; function getModelPortPoints(model, group) { - const { x: modelX, y: modelY } = model.position(); const points = Object.values(model.getPortsPositions(group)) .map(({ x, y }) => new g.Point(modelX + x, modelY + y)); From 4e380f836d9a77c84a1e52d7c6d26c9cbcdcaa4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Mon, 16 Oct 2023 09:34:13 -0300 Subject: [PATCH 13/20] Comments addressed --- src/components/modeler/Selection.vue | 2 +- src/components/nodes/boundaryEvent/boundaryEvent.vue | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/modeler/Selection.vue b/src/components/modeler/Selection.vue index f6808f780..2ef426def 100644 --- a/src/components/modeler/Selection.vue +++ b/src/components/modeler/Selection.vue @@ -625,7 +625,7 @@ export default { boundaryTimerEventId, ]; - const boundaryNodes = window.ProcessMaker.$modeler.nodes.filter(node => boundaryEventTypes.includes(node.type)); + const boundaryNodes = store.getters.nodes.filter(node => boundaryEventTypes.includes(node.type)); boundaryNodes.forEach(boundaryNode => { if (boundaryNode.definition.attachedToRef.id === shape.model.component.node.definition.id) { diff --git a/src/components/nodes/boundaryEvent/boundaryEvent.vue b/src/components/nodes/boundaryEvent/boundaryEvent.vue index e669e36a1..340b935b3 100644 --- a/src/components/nodes/boundaryEvent/boundaryEvent.vue +++ b/src/components/nodes/boundaryEvent/boundaryEvent.vue @@ -210,8 +210,7 @@ export default { attachedToRef: this.node.definition.get('attachedToRef'), }; - const { paper } = window.ProcessMaker.$modeler; - const { x: clientX, y: clientY } = paper.localToClientPoint(this.node.diagram.bounds); + const { x: clientX, y: clientY } = store.getters.paper.localToClientPoint(this.node.diagram.bounds); window.ProcessMaker.EventBus.$emit('multiplayer-addBoundaryEvent', { clientX: clientX + 18, From a29003899e65a829125610b4d2e34adbacfc37e0 Mon Sep 17 00:00:00 2001 From: Rodrigo Quelca Date: Tue, 17 Oct 2023 16:41:53 -0400 Subject: [PATCH 14/20] merge boundary with containers --- checkForOnlyrrrr.sh | 33 ++++ src/components/crown/utils.js | 19 +- src/components/modeler/Modeler.vue | 108 ++++++++--- src/components/modeler/Selection.vue | 63 +++++-- .../nodes/boundaryEvent/boundaryEvent.vue | 8 +- .../nodes/genericFlow/genericFlow.vue | 11 -- src/components/nodes/messageFlow/index.js | 16 ++ src/components/nodes/pool/pool.vue | 49 ++++- src/components/nodes/poolLane/index.js | 36 ++++ src/components/nodes/sequenceFlow/index.js | 15 ++ src/mixins/linkConfig.js | 14 -- src/mixins/poolLaneCrownConfig.js | 2 - src/multiplayer/multiplayer.js | 178 +++++++++--------- 13 files changed, 372 insertions(+), 180 deletions(-) create mode 100755 checkForOnlyrrrr.sh diff --git a/checkForOnlyrrrr.sh b/checkForOnlyrrrr.sh new file mode 100755 index 000000000..6b4dd4d36 --- /dev/null +++ b/checkForOnlyrrrr.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +# ================================================================= +# Check that we never commit a .only on a test +# Also check that we never pass a --spec directive in package.json +# ================================================================= + +stagedFiles=$(git status --porcelain | grep '^M' | awk '{print $2}') + +for file in $stagedFiles; do + if [[ $file == "checkForOnly.sh" ]]; then + continue + fi + + if [[ $file == "package.json" ]]; then + specDirectiveCount=$(grep "\-\-spec" package.json | wc -l) + if [[ $specDirectiveCount -gt 0 ]]; then + echo "package.json contains a spec directive." + exit 255 + else + echo "package.json is OK" + fi + fi + + numberOfOnlys=$(grep "\.only" $file | wc -l) + if [[ $numberOfOnlys -gt 0 ]]; then + echo "$file contains .only(s)" + grep -n "\.only" $file --color=auto + exit 255 + fi +done + +echo "No staged files contain .only" diff --git a/src/components/crown/utils.js b/src/components/crown/utils.js index 16bc84237..464af592f 100644 --- a/src/components/crown/utils.js +++ b/src/components/crown/utils.js @@ -62,15 +62,16 @@ export function removeNodeAssociations(node, modeler) { export function removeBoundaryEvents(graph, node, removeNode) { const nodeShape = graph.getCells().find(el => el.component && el.component.node === node); - - nodeShape.getEmbeddedCells({ deep: true }) - .filter(cell => { - return cell.component && cell.component.node.isBpmnType('bpmn:BoundaryEvent'); - }) - .forEach(boundaryEventShape => { - graph.getConnectedLinks(boundaryEventShape).forEach(shape => removeNode(shape.component.node)); - removeNode(boundaryEventShape.component.node); - }); + if (nodeShape) { + nodeShape.getEmbeddedCells({ deep: true }) + .filter(cell => { + return cell.component && cell.component.node.isBpmnType('bpmn:BoundaryEvent'); + }) + .forEach(boundaryEventShape => { + graph.getConnectedLinks(boundaryEventShape).forEach(shape => removeNode(shape.component.node)); + removeNode(boundaryEventShape.component.node); + }); + } } export function removeOutgoingAndIncomingRefsToFlow(node){ diff --git a/src/components/modeler/Modeler.vue b/src/components/modeler/Modeler.vue index 1f427922e..5871af51c 100644 --- a/src/components/modeler/Modeler.vue +++ b/src/components/modeler/Modeler.vue @@ -529,6 +529,10 @@ export default { return this.paper.findViewByModel(shape); }); }, + getElementByNodeId(id) { + const cells = this.paper.model.getCells(); + return cells.find((cell) => cell.component && cell.component.id === id); + }, async close() { this.$emit('close'); }, @@ -1035,22 +1039,23 @@ export default { control, }); }, - handleDrop(data) { - const { clientX, clientY, control } = data; - if (this.isMultiplayer) { - window.ProcessMaker.EventBus.$emit('multiplayer-addNode', { - clientX, - clientY, - control, - id: `node_${this.nodeIdGenerator.getDefinitionNumber()}`, - attachedToRefId: null, - }); - } else { - this.handleDropProcedure(data); + async addRemoteNode(data){ + const definition = this.nodeRegistry[data.type].definition(this.moddle, this.$t); + const diagram = this.nodeRegistry[data.type].diagram(this.moddle); + diagram.bounds.x = data.x; + diagram.bounds.y = data.y; + const newNode = this.createNode(data.type, definition, diagram); + await this.addNode(newNode, data.id, true); + await this.$nextTick(); + await this.paperManager.awaitScheduledUpdates(); + //}); + if (this.autoValidate) { + this.validateBpmnDiagram(); } }, - async handleDropProcedure(data, selected=true) { - const { clientX, clientY, control, nodeThatWillBeReplaced, id } = data; + + async handleDrop(data) { + const { clientX, clientY, control, nodeThatWillBeReplaced } = data; this.validateDropTarget({ clientX, clientY, control }); if (!this.allowDrop) { return; @@ -1068,11 +1073,10 @@ export default { if (newNode.isBpmnType('bpmn:BoundaryEvent')) { this.setShapeCenterUnderCursor(diagram); } - if (selected) { - this.highlightNode(newNode); - } - await this.addNode(newNode, id, selected); + this.highlightNode(newNode); + + await this.addNode(newNode); if (!nodeThatWillBeReplaced) { return; } @@ -1101,7 +1105,55 @@ export default { const view = newNodeComponent.shapeView; await this.$refs.selector.selectElement(view); }, - async addNode(node, id = null, selected = true) { + multiplayerHook(node, fromClient) { + const blackList = [ + 'processmaker-modeler-lane', + 'processmaker-modeler-generic-flow', + 'processmaker-modeler-sequence-flow', + 'processmaker-modeler-association', + 'processmaker-modeler-data-input-association', + 'processmaker-modeler-data-input-association', + 'processmaker-modeler-boundary-timer-event', + 'processmaker-modeler-boundary-error-event', + 'processmaker-modeler-boundary-signal-event', + 'processmaker-modeler-boundary-conditional-even', + 'processmaker-modeler-boundary-message-event', + ]; + const flowTypes = [ + 'processmaker-modeler-sequence-flow', + 'processmaker-modeler-message-flow', + ]; + if (!this.isMultiplayer) { + return; + } + if (!fromClient) { + if (!blackList.includes(node.type) && !flowTypes.includes(node.type)) { + const defaultData = { + x: node.diagram.bounds.x, + y: node.diagram.bounds.y, + height: node.diagram.bounds.height, + width: node.diagram.bounds.width, + type: node.type, + id: node.definition.id, + isAddingLaneAbove: true, + }; + if (node?.pool?.component) { + defaultData['poolId'] = node.pool.component.id; + } + window.ProcessMaker.EventBus.$emit('multiplayer-addNode', defaultData); + } + if (flowTypes.includes(node.type)) { + window.ProcessMaker.EventBus.$emit('multiplayer-addFlow', { + id: node.definition.id, + type: node.type, + sourceRefId: node.definition.sourceRef.id, + targetRefId: node.definition.targetRef.id, + waypoint: node.diagram.waypoint, + }); + } + } + }, + async addNode(node, id = null, fromClient = false) { if (!node.pool) { node.pool = this.poolTarget; } @@ -1111,6 +1163,9 @@ export default { node.setIds(this.nodeIdGenerator, id); this.planeElements.push(node.diagram); + // add multiplayer logic as a hook + this.multiplayerHook(node, fromClient); + store.commit('addNode', node); this.poolTarget = null; @@ -1126,7 +1181,7 @@ export default { ].includes(node.type)) { return; } - if (selected) { + if (!fromClient) { // Select the node after it has been added to the store (does not apply to flows) this.selectNewNode(node); } @@ -1148,6 +1203,7 @@ export default { addNodeToProcess(node, targetProcess); this.planeElements.push(node.diagram); + this.multiplayerHook(node, false); store.commit('addNode', node); this.poolTarget = null; }); @@ -1207,10 +1263,10 @@ export default { replaceNode({ node, typeToReplaceWith }) { this.performSingleUndoRedoTransaction(async() => { await this.paperManager.performAtomicAction(async() => { - const { x: clientX, y: clientY } = this.paper.localToClientPoint(node.diagram.bounds); + const { x, y } = node.diagram.bounds; const nodeData = { - clientX, clientY, + x, y, control: { type: typeToReplaceWith }, nodeThatWillBeReplaced: node, }; @@ -1224,10 +1280,10 @@ export default { }).filter(Boolean); // If the new control is found, emit event to server to replace node if (newControl.length === 1) { - window.ProcessMaker.EventBus.$emit('multiplayer-replaceNode', { nodeData, newControl: newControl[0] }); + window.ProcessMaker.EventBus.$emit('multiplayer-replaceNode', { nodeData, newControl: newControl[0].type }); } } else { - await this.replaceNodeProcedure(nodeData); + await this.replaceNodeProcedure(nodeData, true); } }); }); @@ -1240,7 +1296,7 @@ export default { data.clientY = clientY; } - const newNode = await this.handleDropProcedure(data); + const newNode = await this.handleDrop(data); await this.removeNode(data.nodeThatWillBeReplaced, { removeRelationships: false, isReplaced }); this.highlightNode(newNode); @@ -1250,7 +1306,7 @@ export default { this.performSingleUndoRedoTransaction(async() => { await this.paperManager.performAtomicAction(async() => { const { x: clientX, y: clientY } = this.paper.localToClientPoint(node.diagram.bounds); - const newNode = await this.handleDropProcedure({ + const newNode = await this.handleDrop({ clientX, clientY, control: { type: typeToReplaceWith }, nodeThatWillBeReplaced: node, diff --git a/src/components/modeler/Selection.vue b/src/components/modeler/Selection.vue index 2ef426def..0b332a8a7 100644 --- a/src/components/modeler/Selection.vue +++ b/src/components/modeler/Selection.vue @@ -584,33 +584,45 @@ export default { this.overPoolStopDrag(); this.updateSelectionBox(); if (this.isMultiplayer) { - window.ProcessMaker.EventBus.$emit('multiplayer-updateNodes', this.getProperties()); + window.ProcessMaker.EventBus.$emit('multiplayer-updateNodes', this.getProperties(this.selected)); } - - }, - getProperties() { + + getProperties(shapes) { let changed = []; const shapesToNotTranslate = [ 'PoolLane', 'standard.Link', ]; - this.selected.filter(shape => !shapesToNotTranslate.includes(shape.model.get('type'))) + + shapes.filter(shape => !shapesToNotTranslate.includes(shape.model.get('type'))) .forEach(shape => { - changed.push({ - id: shape.model.component.node.definition.id, - properties: { - clientX: shape.model.get('position').x, - clientY: shape.model.get('position').y, - attachedToRefId: shape.model.component.node.definition.get('attachedToRef')?.id ?? null, - }, - }); + if (shape.model.get('type') === 'processmaker.modeler.bpmn.pool') { + const children = shape.model.component.getElementsUnderArea(shape.model, this.graph); + changed = [...changed, ...this.getContainerProperties(children, changed)]; + } else { + const { node } = shape.model.component; + const defaultData = { + id: node.definition.id, + properties: { + x: shape.model.get('position').x, + y: shape.model.get('position').y, + height: shape.model.get('size').height, + width: shape.model.get('size').width, + attachedToRefId: shape.model.component.node.definition.get('attachedToRef')?.id ?? null, + }, + }; + if (node?.pool?.component) { + defaultData['poolId'] = node.pool.component.id; + } + changed.push(defaultData); + } const boundariesChanges = this.getBoundariesChangesForShape(shape); changed = changed.concat(boundariesChanges); }); + return changed; }, - /** * Get properties for each boundary inside a shape */ @@ -624,16 +636,16 @@ export default { boundarySignalEventId, boundaryTimerEventId, ]; - const boundaryNodes = store.getters.nodes.filter(node => boundaryEventTypes.includes(node.type)); - boundaryNodes.forEach(boundaryNode => { if (boundaryNode.definition.attachedToRef.id === shape.model.component.node.definition.id) { boundariesChanged.push({ id: boundaryNode.definition.id, properties: { - clientX: boundaryNode.diagram.bounds.x, - clientY: boundaryNode.diagram.bounds.y, + x: boundaryNode.diagram.bounds.x, + y: boundaryNode.diagram.bounds.y, + height: boundaryNode.diagram.bounds.height, + width: boundaryNode.diagram.bounds.width, attachedToRefId: boundaryNode.definition.get('attachedToRef')?.id ?? null, }, }); @@ -641,6 +653,21 @@ export default { }); return boundariesChanged; }, + getContainerProperties(children) { + const changed = []; + children.forEach(model => { + changed.push({ + id: model.component.node.definition.id, + properties: { + x: model.get('position').x, + y: model.get('position').y, + height: model.get('size').height, + width: model.get('size').width, + }, + }); + }); + return changed; + }, /** * Selector will update the waypoints of the related flows */ diff --git a/src/components/nodes/boundaryEvent/boundaryEvent.vue b/src/components/nodes/boundaryEvent/boundaryEvent.vue index 340b935b3..78ff3b97b 100644 --- a/src/components/nodes/boundaryEvent/boundaryEvent.vue +++ b/src/components/nodes/boundaryEvent/boundaryEvent.vue @@ -210,11 +210,11 @@ export default { attachedToRef: this.node.definition.get('attachedToRef'), }; - const { x: clientX, y: clientY } = store.getters.paper.localToClientPoint(this.node.diagram.bounds); - window.ProcessMaker.EventBus.$emit('multiplayer-addBoundaryEvent', { - clientX: clientX + 18, - clientY: clientY + 18, + x: this.node.diagram.bounds.x, + y: this.node.diagram.bounds.y, + height: this.node.diagram.bounds.height, + width: this.node.diagram.bounds.width, attachedToRefId: this.node.definition.get('attachedToRef')?.id, control, type: this.node.type, diff --git a/src/components/nodes/genericFlow/genericFlow.vue b/src/components/nodes/genericFlow/genericFlow.vue index 659e22ff6..e31f7a56e 100644 --- a/src/components/nodes/genericFlow/genericFlow.vue +++ b/src/components/nodes/genericFlow/genericFlow.vue @@ -109,17 +109,6 @@ export default { const flow = new bpmnFlow.factory(this.nodeRegistry, this.moddle, this.paper); const genericLink = this.shape.findView(this.paper); const waypoint = [genericLink.sourceAnchor.toJSON(), genericLink.targetAnchor.toJSON()]; - // Multiplayer hook - if (this.$parent.isMultiplayer) { - window.ProcessMaker.EventBus.$emit('multiplayer-addFlow', { - type: bpmnFlow.type, - id: `node_${this.$parent.nodeIdGenerator.getDefinitionNumber()}`, - sourceRefId: this.sourceNode.definition.id, - targetRefId: this.targetNode.definition.id, - waypoint, - }); - } - this.$emit('replace-generic-flow', { actualFlow: flow.makeFlowNode(this.sourceShape, this.target, waypoint), genericFlow: this.node, diff --git a/src/components/nodes/messageFlow/index.js b/src/components/nodes/messageFlow/index.js index 1c7354fbe..ca2435b40 100644 --- a/src/components/nodes/messageFlow/index.js +++ b/src/components/nodes/messageFlow/index.js @@ -2,6 +2,9 @@ import component from './messageFlow.vue'; import nameConfigSettings from '@/components/inspectors/nameConfigSettings'; import advancedAccordionConfig from '@/components/inspectors/advancedAccordionConfig'; import documentationAccordionConfig from '@/components/inspectors/documentationAccordionConfig'; +import { getNodeIdGenerator } from '@/NodeIdGenerator'; +import MessageFlow from '@/components/nodes/genericFlow/MessageFlow'; + import { id } from '@/components/nodes/messageFlow/config'; export default { @@ -42,4 +45,17 @@ export default { ], }, ], + async multiplayerClient(modeler, data) { + const { paper } = modeler; + const sourceElem = modeler.getElementByNodeId( data.sourceRefId); + const targetElem = modeler.getElementByNodeId( data.targetRefId); + if (sourceElem && targetElem) { + const flow = new MessageFlow(modeler.nodeRegistry, modeler.moddle, paper); + const actualFlow = flow.makeFlowNode(sourceElem, targetElem, data.waypoint); + // add Nodes + modeler.addNode(actualFlow, data.id, true); + const nodeIdereator = getNodeIdGenerator(modeler.definitions); + nodeIdereator.updateCounters(); + } + }, }; diff --git a/src/components/nodes/pool/pool.vue b/src/components/nodes/pool/pool.vue index 6abb1c522..df6156ed1 100644 --- a/src/components/nodes/pool/pool.vue +++ b/src/components/nodes/pool/pool.vue @@ -133,6 +133,30 @@ export default { pull(this.containingProcess.get('flowElements'), elementDefinition); toPool.component.containingProcess.get('flowElements').push(elementDefinition); }, + moveElementRemote(element, toPool) { + const elementDefinition = element.component.node.definition; + + if (this.laneSet) { + /* Remove references to the element from the current Lane */ + const containingLane = this.laneSet.get('lanes').find(lane => { + return lane.get('flowNodeRef').includes(elementDefinition); + }); + + pull(containingLane.get('flowNodeRef'), elementDefinition); + } + + /* Remove references to the element from the current process */ + pull(this.containingProcess.get('flowElements'), elementDefinition); + + element.component.node.pool = toPool; + + this.shape.unembed(element); + toPool.component.shape.embed(element); + if (element.component.node.type !== laneId && toPool.component.laneSet) { + toPool.component.updateLaneChildren(); + } + }, + moveElement(element, toPool) { const elementDefinition = element.component.node.definition; @@ -155,7 +179,7 @@ export default { this.shape.unembed(element); toPool.component.addToPool(element); }, - async addLane() { + async addLane(emitMultiplayer = true) { /* A Lane element must be contained in a LaneSet element. * Get the current laneSet element or create a new one. */ @@ -177,35 +201,40 @@ export default { lanes.push(this.pushNewLane()); - await Promise.all(lanes); + await Promise.all(lanes) + .then((val) => { + if (emitMultiplayer && this.$parent.isMultiplayer) { + window.ProcessMaker.EventBus.$emit('multiplayer-addLanes', val); + } + }); this.$emit('set-shape-stacking', this.shape); this.graph.getLinks().forEach(link => { this.$emit('set-shape-stacking', link); }); this.$emit('save-state'); }, - createLaneSet() { + createLaneSet(id) { const laneSet = this.moddle.create('bpmn:LaneSet'); this.laneSet = laneSet; const generator = this.nodeIdGenerator; - const [laneSetId] = generator.generate(); + const [laneSetId] = id ?? generator.generate(); this.laneSet.set('id', laneSetId); this.containingProcess.get('laneSets').push(laneSet); }, - pushNewLane(definition = Lane.definition(this.moddle, this.$t)) { + async pushNewLane(definition = Lane.definition(this.moddle, this.$t)) { definition.set('color', this.node.definition.get('color')); this.$emit('set-pool-target', this.shape); const diagram = Lane.diagram(this.moddle); diagram.bounds.width = this.shape.getBBox().width; - - this.$emit('add-node', new Node( + const node = new Node( Lane.id, definition, diagram, - )); - - return this.$nextTick(); + ); + this.$emit('add-node', node); + await this.$nextTick(); + return node; }, addToPool(element) { if (element.component.node.isBpmnType('bpmn:BoundaryEvent')) { diff --git a/src/components/nodes/poolLane/index.js b/src/components/nodes/poolLane/index.js index b2a8653db..3645c7f5f 100644 --- a/src/components/nodes/poolLane/index.js +++ b/src/components/nodes/poolLane/index.js @@ -3,6 +3,9 @@ import nameConfigSettings from '@/components/inspectors/nameConfigSettings'; import advancedAccordionConfig from '@/components/inspectors/advancedAccordionConfig'; import documentationAccordionConfig from '@/components/inspectors/documentationAccordionConfig'; import { id } from '@/components/nodes/poolLane/config'; +import Node from '@/components/nodes/node'; +import { elementShouldHaveFlowNodeRef } from '@/components/nodes/pool/poolUtils'; +import { getNodeIdGenerator } from '@/NodeIdGenerator'; export default { id, @@ -49,4 +52,37 @@ export default { ], }, ], + + async multiplayerClient(modeler, data) { + const pool = modeler.getElementByNodeId(data.poolId); + const definition = modeler.moddle.create('bpmn:Lane', { + name: data.name, + }); + if (!pool.component.laneSet && pool.component.createLaneSet) { + pool.component.createLaneSet([data.laneSetId]); + /* If there are currently elements in the pool, add them to the first lane */ + pool.component.shape.getEmbeddedCells().filter(element => elementShouldHaveFlowNodeRef(element)) + .forEach(element => { + definition.get('flowNodeRef').push(element.component.node.definition); + }); + const nodeIdereator = getNodeIdGenerator(modeler.definitions); + nodeIdereator.updateCounters(); + } + const diagram = modeler.moddle.create('bpmndi:BPMNShape', { + bounds: modeler.moddle.create('dc:Bounds', { + height: data.height, + width: data.width, + x: data.x, + y: data.y, + }), + }); + const node = new Node( + data.type, + definition, + diagram, + ); + await modeler.addNode(node, data.id, true); + modeler.setShapeStacking(pool.component.shape); + + }, }; diff --git a/src/components/nodes/sequenceFlow/index.js b/src/components/nodes/sequenceFlow/index.js index dd21c88a9..fdf7d9418 100644 --- a/src/components/nodes/sequenceFlow/index.js +++ b/src/components/nodes/sequenceFlow/index.js @@ -2,6 +2,8 @@ import component from './sequenceFlow.vue'; import nameConfigSettings from '@/components/inspectors/nameConfigSettings'; import advancedAccordionConfig from '@/components/inspectors/advancedAccordionConfig'; import documentationAccordionConfig from '@/components/inspectors/documentationAccordionConfig'; +import { getNodeIdGenerator } from '@/NodeIdGenerator'; +import SequenceFlow from '@/components/nodes/genericFlow/SequenceFlow'; export const id = 'processmaker-modeler-sequence-flow'; @@ -82,4 +84,17 @@ export default { ], }, ], + async multiplayerClient(modeler, data) { + const { paper } = modeler; + const sourceElem = modeler.getElementByNodeId(data.sourceRefId); + const targetElem = modeler.getElementByNodeId(data.targetRefId); + if (sourceElem && targetElem) { + const flow = new SequenceFlow(modeler.nodeRegistry, modeler.moddle, paper); + const actualFlow = flow.makeFlowNode(sourceElem, targetElem, data.waypoint); + // add Nodes + modeler.addNode(actualFlow, data.id, true); + const nodeIdereator = getNodeIdGenerator(modeler.definitions); + nodeIdereator.updateCounters(); + } + }, }; diff --git a/src/mixins/linkConfig.js b/src/mixins/linkConfig.js index db72d123e..d9729751d 100644 --- a/src/mixins/linkConfig.js +++ b/src/mixins/linkConfig.js @@ -239,20 +239,6 @@ export default { if (this.updateDefinitionLinks) { this.updateDefinitionLinks(); } - if (this.shape.component.node.type === 'processmaker-modeler-data-input-association') { - if (this.$parent.isMultiplayer) { - const genericLink = this.shape.findView(this.paper); - const waypoint = [genericLink.sourceAnchor.toJSON(), genericLink.targetAnchor.toJSON()]; - window.ProcessMaker.EventBus.$emit('multiplayer-addFlow', { - type: this.shape.component.node.type, - id: `node_${this.$parent.nodeIdGenerator.getDefinitionNumber()}`, - sourceRefId: this.sourceNode.definition.id, - targetRefId: this.targetNode.definition.id, - waypoint, - }); - } - } - this.$emit('save-state'); }); diff --git a/src/mixins/poolLaneCrownConfig.js b/src/mixins/poolLaneCrownConfig.js index f35cd8ea2..6f450798d 100644 --- a/src/mixins/poolLaneCrownConfig.js +++ b/src/mixins/poolLaneCrownConfig.js @@ -14,7 +14,6 @@ export default { ].includes(this.node.type)) { return; } - if (this.node.pool) { if (!this.graph.getCell(this.node.pool)) { this.node.pool = this.graph.getElements().find(element => { @@ -27,7 +26,6 @@ export default { if (this.isLane) { this.configureLaneInParentPool(); } - return; } diff --git a/src/multiplayer/multiplayer.js b/src/multiplayer/multiplayer.js index 63a5d5a14..f425e59da 100644 --- a/src/multiplayer/multiplayer.js +++ b/src/multiplayer/multiplayer.js @@ -3,28 +3,6 @@ import * as Y from 'yjs'; import { getNodeIdGenerator } from '../NodeIdGenerator'; import Room from './room'; import { faker } from '@faker-js/faker'; -import MessageFlow from '@/components/nodes/genericFlow/MessageFlow'; -import SequenceFlow from '@/components/nodes/genericFlow/SequenceFlow'; -import DataOutputAssociation from '@/components/nodes/genericFlow/DataOutputAssociation'; - -const BpmnFlows = [ - { - type: 'processmaker-modeler-text-annotation', - factory: DataOutputAssociation, - }, - { - type: 'processmaker-modeler-sequence-flow', - factory: SequenceFlow, - }, - { - type: 'processmaker-modeler-message-flow', - factory: MessageFlow, - }, - { - type: 'processmaker-modeler-data-input-association', - factory: DataOutputAssociation, - }, -]; export default class Multiplayer { clientIO = null; yDoc = null; @@ -145,12 +123,13 @@ export default class Multiplayer { window.ProcessMaker.EventBus.$on('multiplayer-addBoundaryEvent', ( data ) => { this.addBoundaryEvent(data); }); + + window.ProcessMaker.EventBus.$on('multiplayer-addLanes', ( lanes ) => { + this.addLaneNodes(lanes); + }); } addNode(data) { - // Add the new element to the process - this.createShape(data); // Add the new element to the shared array - // this.yArray.push([data]); const yMapNested = new Y.Map(); this.doTransact(yMapNested, data); this.yArray.push([yMapNested]); @@ -159,48 +138,45 @@ export default class Multiplayer { // Send the update to the web socket server this.clientIO.emit('createElement', stateUpdate); } - createShape(value) { - this.modeler.handleDropProcedure(value, false); + createShape(value){ + if (this.modeler.nodeRegistry[value.type] && this.modeler.nodeRegistry[value.type].multiplayerClient) { + this.modeler.nodeRegistry[value.type].multiplayerClient(this.modeler, value); + } else { + this.modeler.addRemoteNode(value); + } this.#nodeIdGenerator.updateCounters(); + } createRemoteShape(changes) { - const flows = [ - 'processmaker-modeler-sequence-flow', - 'processmaker-modeler-text-annotation', - 'processmaker-modeler-message-flow', - 'processmaker-modeler-data-input-association', - ]; - return new Promise(resolve => { changes.map((data) => { - if (flows.includes(data.type)) { - this.createFlow(data); - } else { - this.createShape(data); - } + this.createShape(data); }); resolve(); }); } removeNode(data) { const index = this.getIndex(data.definition.id); - this.removeShape(data); - this.yArray.delete(index, 1); // delete one element - - // Encode the state as an update and send it to the server - const stateUpdate = Y.encodeStateAsUpdate(this.yDoc); - // Send the update to the web socket server - this.clientIO.emit('removeElement', stateUpdate); + if (index >= 0) { + this.removeShape(data); + this.yArray.delete(index, 1); // delete one element + // Encode the state as an update and send it to the server + const stateUpdate = Y.encodeStateAsUpdate(this.yDoc); + // Send the update to the web socket server + this.clientIO.emit('removeElement', stateUpdate); + } } getIndex(id) { let index = -1; + let found = false; for (const value of this.yArray) { index ++; if (value.get('id') === id) { + found = true; break ; } } - return index; + return found ? index : -1; } getNodeById(nodeId) { const node = this.modeler.nodes.find((element) => element.definition && element.definition.id === nodeId); @@ -221,7 +197,8 @@ export default class Multiplayer { data.forEach((value) => { const index = this.getIndex(value.id); const nodeToUpdate = this.yArray.get(index); - this.doTransact(nodeToUpdate, value.properties); + const updateData = value.poolId ? { ...value.properties, ...{ poolId: value.poolId } } : value.properties; + this.doTransact(nodeToUpdate, updateData); }); } replaceNode(nodeData, newControl) { @@ -230,13 +207,11 @@ export default class Multiplayer { const nodeToUpdate = this.yArray.get(index); // Update the node id in the nodeData nodeData.id = `node_${this.#nodeIdGenerator.getDefinitionNumber()}`; - // Replace the node in the process - this.modeler.replaceNodeProcedure(nodeData, true); // Update the node id generator this.#nodeIdGenerator.updateCounters(); // Update the node in the shared array this.yDoc.transact(() => { - nodeToUpdate.set('control', newControl); + nodeToUpdate.set('type', newControl); nodeToUpdate.set('id', nodeData.id); }); @@ -245,13 +220,14 @@ export default class Multiplayer { this.clientIO.emit('updateElement', { updateDoc: stateUpdate, isReplaced: true }); } replaceShape(updatedNode) { + const { x: clientX, y: clientY } = this.modeler.paper.localToClientPoint(updatedNode); // Get the node to update const node = this.getNodeById(updatedNode.oldNodeId); // Update the node id in the nodeData const nodeData = { - clientX: updatedNode.clientX, - clientY: updatedNode.clientY, - control: { type: updatedNode.control.type }, + clientX, + clientY, + control: { type: updatedNode.type }, nodeThatWillBeReplaced: node, id: updatedNode.id, }; @@ -274,28 +250,38 @@ export default class Multiplayer { // Send the update to the web socket server this.clientIO.emit('updateElement', { updateDoc: stateUpdate, isReplaced: false }); } - updateShapes(data) { + async updateShapes(data) { const { paper } = this.modeler; - const element = this.getJointElement(paper.model, data.id); + const element = this.modeler.getElementByNodeId(data.id); + const newPool = this.modeler.getElementByNodeId(data.poolId); // Update the element's position attribute - element.set('position', { x:data.clientX, y:data.clientY }); - + element.resize( + /* Add labelWidth to ensure elements don't overlap with the pool label */ + data.width, + data.height, + ); + element.set('position', { x: data.x, y: data.y }); if (element.component.node.definition.$type === 'bpmn:BoundaryEvent') { this.attachBoundaryEventToNode(element, data); } - // Trigger a rendering of the element on the paper - paper.findViewByModel(element).update(); + await paper.findViewByModel(element).update(); + // validate if the parent pool was updated + await element.component.$nextTick(); + await this.modeler.paperManager.awaitScheduledUpdates(); + if (newPool && element.component.node.pool && element.component.node.pool.component.id !== data.poolId) { + element.component.node.pool.component.moveElementRemote(element, newPool); + } } attachBoundaryEventToNode(element, data) { - const { paper } = this.modeler; + console.log('attachBoundaryEventToNode', element); const node = this.getNodeById(data.attachedToRefId); // Find previous attached task const previousAttachedTask = element.getParentCell(); // Find new attached task - const newAttachedTask = this.getJointElement(paper.model, data.attachedToRefId); + const newAttachedTask = this.modeler.getElementByNodeId(data.attachedToRefId); if (previousAttachedTask) { previousAttachedTask.unembed(element); @@ -304,16 +290,7 @@ export default class Multiplayer { element.component.node.definition.set('attachedToRef', node.definition); } - - getJointElement(graph, targetValue) { - const cells = graph.getCells(); - for (const cell of cells) { - if (cell.component.id === targetValue) { - return cell; - } - } - return null; // Return null if no matching element is found - } + addFlow(data) { const yMapNested = new Y.Map(); this.doTransact(yMapNested, data); @@ -324,21 +301,29 @@ export default class Multiplayer { this.clientIO.emit('createElement', stateUpdate); this.#nodeIdGenerator.updateCounters(); } - createFlow(data){ - const { paper } = this.modeler; - const sourceElem = this.getJointElement(paper.model, data.sourceRefId); - const targetElem = this.getJointElement(paper.model, data.targetRefId); - if (sourceElem && targetElem) { - const bpmnFlow = BpmnFlows.find(FlowClass => { - return FlowClass.type === data.type; - }); - const flow = new bpmnFlow.factory(this.modeler.nodeRegistry, this.modeler.moddle, this.modeler.paper); - const actualFlow = flow.makeFlowNode(sourceElem, targetElem, data.waypoint); - // add Nodes - this.modeler.addNode(actualFlow, data.id); - this.#nodeIdGenerator.updateCounters(); - } + addLaneNodes(lanes) { + const pool = this.getPool(lanes); + window.ProcessMaker.EventBus.$emit('multiplayer-updateNodes', [{ + id: pool.component.node.definition.id, + properties: { + x: pool.component.node.diagram.bounds.x, + y: pool.component.node.diagram.bounds.y, + height: pool.component.node.diagram.bounds.height, + width: pool.component.node.diagram.bounds.width, + isAddingLaneAbove: pool.isAddingLaneAbove, + }, + }]); + this.yDoc.transact(() => { + lanes.forEach((lane) => { + const yMapNested = new Y.Map(); + const data = this.prepareLaneData(lane); + this.doTransact(yMapNested, data); + this.yArray.push([yMapNested]); + const stateUpdate = Y.encodeStateAsUpdate(this.yDoc); + this.clientIO.emit('createElement', stateUpdate); + }); + }); } addBoundaryEvent(data) { const yMapNested = new Y.Map(); @@ -350,4 +335,25 @@ export default class Multiplayer { this.clientIO.emit('createElement', stateUpdate); this.#nodeIdGenerator.updateCounters(); } + prepareLaneData(lane) { + const data = { + type: lane.type, + id: lane.definition.id, + name: lane.definition.name, + x: lane.diagram.bounds.x, + y: lane.diagram.bounds.y, + width: lane.diagram.bounds.width, + height: lane.diagram.bounds.height, + poolId: lane.pool.component.node.definition.id, + laneSetId: lane.pool.component.laneSet.id, + }; + return data; + } + getPool(lanes) { + if (lanes && lanes.length > 0) { + return lanes[0].pool; + } + return false; + } + } From 95c00179d39602e9b76bc7899320ad4e80cf7e11 Mon Sep 17 00:00:00 2001 From: Rodrigo Quelca Date: Tue, 17 Oct 2023 16:46:39 -0400 Subject: [PATCH 15/20] remove unsed file --- checkForOnlyrrrr.sh | 33 --------------------------------- 1 file changed, 33 deletions(-) delete mode 100755 checkForOnlyrrrr.sh diff --git a/checkForOnlyrrrr.sh b/checkForOnlyrrrr.sh deleted file mode 100755 index 6b4dd4d36..000000000 --- a/checkForOnlyrrrr.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh - -# ================================================================= -# Check that we never commit a .only on a test -# Also check that we never pass a --spec directive in package.json -# ================================================================= - -stagedFiles=$(git status --porcelain | grep '^M' | awk '{print $2}') - -for file in $stagedFiles; do - if [[ $file == "checkForOnly.sh" ]]; then - continue - fi - - if [[ $file == "package.json" ]]; then - specDirectiveCount=$(grep "\-\-spec" package.json | wc -l) - if [[ $specDirectiveCount -gt 0 ]]; then - echo "package.json contains a spec directive." - exit 255 - else - echo "package.json is OK" - fi - fi - - numberOfOnlys=$(grep "\.only" $file | wc -l) - if [[ $numberOfOnlys -gt 0 ]]; then - echo "$file contains .only(s)" - grep -n "\.only" $file --color=auto - exit 255 - fi -done - -echo "No staged files contain .only" From 7e4d1ce1a7dc9b998a19e6d272c7966b0deeef11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Agust=C3=ADn=20Busso?= <90727999+agustinbusso@users.noreply.github.com> Date: Fri, 20 Oct 2023 12:29:12 -0300 Subject: [PATCH 16/20] Fix color issue in boundaries --- src/components/crown/crownButtons/crownColorDropdown.vue | 3 ++- src/components/modeler/Selection.vue | 1 + src/components/nodes/boundaryEvent/boundaryEvent.vue | 1 + src/multiplayer/multiplayer.js | 5 ++++- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/crown/crownButtons/crownColorDropdown.vue b/src/components/crown/crownButtons/crownColorDropdown.vue index 59721fb09..c4aeb970c 100644 --- a/src/components/crown/crownButtons/crownColorDropdown.vue +++ b/src/components/crown/crownButtons/crownColorDropdown.vue @@ -137,7 +137,7 @@ export default { store.commit('updateNodeProp', { node: this.node, key: 'color', value: color }); Vue.set(this.node.definition, 'color', color); this.$emit('save-state'); - + const properties = { id: this.node.definition.id, properties: { @@ -148,6 +148,7 @@ export default { width: this.node.diagram.bounds.width, type: this.node.type, id: this.node.definition.id, + attachedToRefId: this.node.definition.get('attachedToRef')?.id, }, }; window.ProcessMaker.EventBus.$emit('multiplayer-updateNodes', [properties]); diff --git a/src/components/modeler/Selection.vue b/src/components/modeler/Selection.vue index d481f2a8d..8b7000f2f 100644 --- a/src/components/modeler/Selection.vue +++ b/src/components/modeler/Selection.vue @@ -648,6 +648,7 @@ export default { height: boundaryNode.diagram.bounds.height, width: boundaryNode.diagram.bounds.width, attachedToRefId: boundaryNode.definition.get('attachedToRef')?.id ?? null, + color: boundaryNode.definition.get('color') ?? null, }, }); } diff --git a/src/components/nodes/boundaryEvent/boundaryEvent.vue b/src/components/nodes/boundaryEvent/boundaryEvent.vue index 78ff3b97b..9910fbe17 100644 --- a/src/components/nodes/boundaryEvent/boundaryEvent.vue +++ b/src/components/nodes/boundaryEvent/boundaryEvent.vue @@ -219,6 +219,7 @@ export default { control, type: this.node.type, id: this.node.definition.id, + color: this.node.definition.get('color'), }); }, }, diff --git a/src/multiplayer/multiplayer.js b/src/multiplayer/multiplayer.js index 8a4e464b8..b1f377376 100644 --- a/src/multiplayer/multiplayer.js +++ b/src/multiplayer/multiplayer.js @@ -327,7 +327,10 @@ export default class Multiplayer { if (previousAttachedTask) { previousAttachedTask.unembed(element); } - newAttachedTask.embed(element); + + if (newAttachedTask) { + newAttachedTask.embed(element); + } element.component.node.definition.set('attachedToRef', node.definition); } From 16b7f1296e03a6a89042b9c480d2ad956727320e Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Mon, 23 Oct 2023 10:51:32 -0400 Subject: [PATCH 17/20] test: update boundary timer event, message flow e2e --- tests/e2e/specs/BoundaryTimerEvent.cy.js | 18 +++++++++--------- tests/e2e/specs/MessageFlows.cy.js | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/e2e/specs/BoundaryTimerEvent.cy.js b/tests/e2e/specs/BoundaryTimerEvent.cy.js index 6b39b3cba..17953e143 100644 --- a/tests/e2e/specs/BoundaryTimerEvent.cy.js +++ b/tests/e2e/specs/BoundaryTimerEvent.cy.js @@ -18,14 +18,14 @@ import { nodeTypes } from '../support/constants'; import { CommonBoundaryEventBehaviour } from '../support/BoundaryEventCommonBehaviour'; describe('Boundary Timer Event', { scrollBehavior: false }, () => { - it('update boundary timer event properties element', () => { + it.skip('update boundary timer event properties element', () => { const taskPosition = { x: 300, y: 200 }; clickAndDropElement(nodeTypes.task, taskPosition); const boundaryTimerEventPosition = { x: 360, y: 260 }; setBoundaryEvent(nodeTypes.boundaryTimerEvent, taskPosition); moveElement(taskPosition, boundaryTimerEventPosition.x, boundaryTimerEventPosition.y); - cy.wait(500); + cy.wait.skip(500); toggleInspector(); @@ -52,7 +52,7 @@ describe('Boundary Timer Event', { scrollBehavior: false }, () => { R/P6D`); }); - it('Can add boundary timer events to valid targets', () => { + it.skip('Can add boundary timer events to valid targets', () => { const initialNumberOfElements = 1; const startEventPosition = { x: 210, y: 200 }; @@ -98,7 +98,7 @@ describe('Boundary Timer Event', { scrollBehavior: false }, () => { getGraphElements().should('have.length', numberOfElementsAfterAddingTasksAndBoundaryTimerEvents); }); - it('can toggle interrupting on Boundary Timer Events', () => { + it.skip('can toggle interrupting on Boundary Timer Events', () => { const taskPosition = { x: 300, y: 200 }; clickAndDropElement(nodeTypes.task, taskPosition); @@ -122,7 +122,7 @@ describe('Boundary Timer Event', { scrollBehavior: false }, () => { }); - it('can update the node identifier and this persists correctly', () => { + it.skip('can update the node identifier and this persists correctly', () => { uploadXml('taskWithBoundaryTimerEvent.xml'); cy.get('.main-paper [data-type="processmaker.components.nodes.boundaryEvent.Shape"]') @@ -145,7 +145,7 @@ describe('Boundary Timer Event', { scrollBehavior: false }, () => { ); }); - it('can toggle interrupting on Boundary Timer Events in multiple processes', () => { + it.skip('can toggle interrupting on Boundary Timer Events in multiple processes', () => { uploadXml('boundaryTimersInPools.xml'); const boundaryTimerEventPositions = [{ x: 277, y: 162 }, { x: 225, y: 379 }]; @@ -196,8 +196,8 @@ describe('Boundary Timer Event', { scrollBehavior: false }, () => { .trigger('mouseup') .then(waitToRenderAllShapes) .then(() => { - const task2Xml = ''; - const boundaryEventOnTask2Xml = ''; + const task2Xml = ''; + const boundaryEventOnTask2Xml = ''; assertDownloadedXmlContainsExpected(task2Xml, boundaryEventOnTask2Xml); assertDownloadedXmlDoesNotContainExpected(boundaryEventOnTaskXml); @@ -218,7 +218,7 @@ describe('Boundary Timer Event', { scrollBehavior: false }, () => { }); }); - it('keeps Boundary Timer Event in correct position when dragging and dropping', () => { + it.skip('keeps Boundary Timer Event in correct position when dragging and dropping', () => { const taskPosition = { x: 300, y: 300 }; clickAndDropElement(nodeTypes.task, taskPosition); waitToRenderAllShapes(); diff --git a/tests/e2e/specs/MessageFlows.cy.js b/tests/e2e/specs/MessageFlows.cy.js index 0dfc97c39..c6d8e5f3c 100644 --- a/tests/e2e/specs/MessageFlows.cy.js +++ b/tests/e2e/specs/MessageFlows.cy.js @@ -259,7 +259,7 @@ describe('Message Flows', { scrollBehavior: false }, () => { const boundaryEventId = 'node_22'; const endEventXml = ``; const boundaryEventXml = ``; - const messageFlowXml = ``; + const messageFlowXml = ``; assertDownloadedXmlContainsExpected(endEventXml, boundaryEventXml, messageFlowXml); }); From e9617aa6119f7234b8d2470daf539067438e582b Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Mon, 23 Oct 2023 11:16:48 -0400 Subject: [PATCH 18/20] feat: refactor multiplayer for boundary events and flows --- src/multiplayer/multiplayer.js | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/src/multiplayer/multiplayer.js b/src/multiplayer/multiplayer.js index 101dca26b..6345c665f 100644 --- a/src/multiplayer/multiplayer.js +++ b/src/multiplayer/multiplayer.js @@ -150,11 +150,11 @@ export default class Multiplayer { }); window.ProcessMaker.EventBus.$on('multiplayer-addFlow', ( data ) => { - this.addFlow(data); + this.addFlowOrBoundaryEvent(data); }); window.ProcessMaker.EventBus.$on('multiplayer-addBoundaryEvent', ( data ) => { - this.addBoundaryEvent(data); + this.addFlowOrBoundaryEvent(data); }); window.ProcessMaker.EventBus.$on('multiplayer-addLanes', ( lanes ) => { @@ -330,11 +330,11 @@ export default class Multiplayer { const node = this.getNodeById(data.id); store.commit('updateNodeProp', { node, key: 'color', value: data.color }); - // boundary type + // boundary type if (element.component.node.definition.$type === 'bpmn:BoundaryEvent') { this.attachBoundaryEventToNode(element, data); } - + // Trigger a rendering of the element on the paper await paper.findViewByModel(element).update(); // validate if the parent pool was updated @@ -357,14 +357,15 @@ export default class Multiplayer { if (previousAttachedTask) { previousAttachedTask.unembed(element); } - + if (newAttachedTask) { newAttachedTask.embed(element); } element.component.node.definition.set('attachedToRef', node.definition); } - addFlow(data) { + addFlowOrBoundaryEvent(data) { + // Add a new flow / boundary event to the shared array const yMapNested = new Y.Map(); this.doTransact(yMapNested, data); this.yArray.push([yMapNested]); @@ -374,7 +375,6 @@ export default class Multiplayer { this.clientIO.emit('createElement', { updateDoc: stateUpdate }); this.#nodeIdGenerator.updateCounters(); } - addLaneNodes(lanes) { const pool = this.getPool(lanes); window.ProcessMaker.EventBus.$emit('multiplayer-updateNodes', [{ @@ -398,17 +398,6 @@ export default class Multiplayer { }); }); } - addBoundaryEvent(data) { - const yMapNested = new Y.Map(); - this.doTransact(yMapNested, data); - this.yArray.push([yMapNested]); - // Encode the state as an update and send it to the server - const stateUpdate = Y.encodeStateAsUpdate(this.yDoc); - // Send the update to the web socket server - this.clientIO.emit('createElement', stateUpdate); - this.#nodeIdGenerator.updateCounters(); - } - prepareLaneData(lane) { const data = { type: lane.type, From dc316628a639a87e7dddeb44ffcbe890840f5102 Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Mon, 23 Oct 2023 11:20:06 -0400 Subject: [PATCH 19/20] ref: rename fn for common elements --- src/multiplayer/multiplayer.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/multiplayer/multiplayer.js b/src/multiplayer/multiplayer.js index 6345c665f..b34c72636 100644 --- a/src/multiplayer/multiplayer.js +++ b/src/multiplayer/multiplayer.js @@ -150,11 +150,11 @@ export default class Multiplayer { }); window.ProcessMaker.EventBus.$on('multiplayer-addFlow', ( data ) => { - this.addFlowOrBoundaryEvent(data); + this.addCommonElement(data); }); window.ProcessMaker.EventBus.$on('multiplayer-addBoundaryEvent', ( data ) => { - this.addFlowOrBoundaryEvent(data); + this.addCommonElement(data); }); window.ProcessMaker.EventBus.$on('multiplayer-addLanes', ( lanes ) => { @@ -364,7 +364,7 @@ export default class Multiplayer { element.component.node.definition.set('attachedToRef', node.definition); } - addFlowOrBoundaryEvent(data) { + addCommonElement(data) { // Add a new flow / boundary event to the shared array const yMapNested = new Y.Map(); this.doTransact(yMapNested, data); From 4c7ce8492cfcb3c4d10ae216fd89556f7158d8cc Mon Sep 17 00:00:00 2001 From: Miguel Angel Date: Mon, 23 Oct 2023 13:13:24 -0400 Subject: [PATCH 20/20] test: enable skiped tests in boundary timer event --- tests/e2e/specs/BoundaryTimerEvent.cy.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/e2e/specs/BoundaryTimerEvent.cy.js b/tests/e2e/specs/BoundaryTimerEvent.cy.js index 17953e143..43ce7f705 100644 --- a/tests/e2e/specs/BoundaryTimerEvent.cy.js +++ b/tests/e2e/specs/BoundaryTimerEvent.cy.js @@ -18,14 +18,14 @@ import { nodeTypes } from '../support/constants'; import { CommonBoundaryEventBehaviour } from '../support/BoundaryEventCommonBehaviour'; describe('Boundary Timer Event', { scrollBehavior: false }, () => { - it.skip('update boundary timer event properties element', () => { + it('update boundary timer event properties element', () => { const taskPosition = { x: 300, y: 200 }; clickAndDropElement(nodeTypes.task, taskPosition); const boundaryTimerEventPosition = { x: 360, y: 260 }; setBoundaryEvent(nodeTypes.boundaryTimerEvent, taskPosition); moveElement(taskPosition, boundaryTimerEventPosition.x, boundaryTimerEventPosition.y); - cy.wait.skip(500); + cy.wait(500); toggleInspector(); @@ -52,7 +52,7 @@ describe('Boundary Timer Event', { scrollBehavior: false }, () => { R/P6D`); }); - it.skip('Can add boundary timer events to valid targets', () => { + it('Can add boundary timer events to valid targets', () => { const initialNumberOfElements = 1; const startEventPosition = { x: 210, y: 200 }; @@ -98,7 +98,7 @@ describe('Boundary Timer Event', { scrollBehavior: false }, () => { getGraphElements().should('have.length', numberOfElementsAfterAddingTasksAndBoundaryTimerEvents); }); - it.skip('can toggle interrupting on Boundary Timer Events', () => { + it('can toggle interrupting on Boundary Timer Events', () => { const taskPosition = { x: 300, y: 200 }; clickAndDropElement(nodeTypes.task, taskPosition); @@ -122,7 +122,7 @@ describe('Boundary Timer Event', { scrollBehavior: false }, () => { }); - it.skip('can update the node identifier and this persists correctly', () => { + it('can update the node identifier and this persists correctly', () => { uploadXml('taskWithBoundaryTimerEvent.xml'); cy.get('.main-paper [data-type="processmaker.components.nodes.boundaryEvent.Shape"]') @@ -145,7 +145,7 @@ describe('Boundary Timer Event', { scrollBehavior: false }, () => { ); }); - it.skip('can toggle interrupting on Boundary Timer Events in multiple processes', () => { + it('can toggle interrupting on Boundary Timer Events in multiple processes', () => { uploadXml('boundaryTimersInPools.xml'); const boundaryTimerEventPositions = [{ x: 277, y: 162 }, { x: 225, y: 379 }]; @@ -218,7 +218,7 @@ describe('Boundary Timer Event', { scrollBehavior: false }, () => { }); }); - it.skip('keeps Boundary Timer Event in correct position when dragging and dropping', () => { + it('keeps Boundary Timer Event in correct position when dragging and dropping', () => { const taskPosition = { x: 300, y: 300 }; clickAndDropElement(nodeTypes.task, taskPosition); waitToRenderAllShapes();