Repository: ProcessMaker/modeler
Pull request #1478 (2023-03-29 00:18:35)

Add TCP4-2662
## Issue & Reproduction Steps

Expected behavior: 

Actual behavior: 

## Solution
-

## How to Test
Test the steps above

## Related Tickets & Packages
- 

## Code Review Checklist
- [ ] I have pulled this code locally and tested it on my instance, along with any associated packages.
- [ ] This code adheres to [ProcessMaker Coding Guidelines](https://github.com/ProcessMaker/processmaker/wiki/Coding-Guidelines).
- [ ] This code includes a unit test or an E2E test that tests its functionality, or is covered by an existing test.
- [ ] This solution fixes the bug reported in the original ticket.
- [ ] This solution does not alter the expected output of a component in a way that would break existing Processes.
- [ ] This solution does not implement any breaking changes that would invalidate documentation or cause existing Processes to fail.
- [ ] This solution has been tested with enterprise packages that rely on its functionality and does not introduce bugs in those packages.
- [ ] This code does not duplicate functionality that already exists in the framework or in ProcessMaker.
- [ ] This ticket conforms to the PRD associated with this part of ProcessMaker.



Patch:
diff --git a/.eslintrc.js b/.eslintrc.js
index 6ca9e1ec..337bb94c 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -17,6 +17,7 @@ module.exports = {
     quotes: ['error', 'single'],
     'object-curly-spacing': ['warn', 'always', { 'arraysInObjects': false }],
     'no-debugger': 'off',
+    'no-console': 'off',
     'object-shorthand': 'error',
     'space-before-function-paren': ['error', 'never'],
     'keyword-spacing': 'error',
diff --git a/src/components/controls/controls.scss b/src/components/controls/controls.scss
index e8a1b412..3efd559f 100644
--- a/src/components/controls/controls.scss
+++ b/src/components/controls/controls.scss
@@ -3,7 +3,7 @@ $controls-column-compressed-max-width: 95px;
 $controls-transition: 0.3s;
 
 .controls {
-  z-index: 2;
+  z-index: 1;
   padding-bottom: $toolbar-height;
 
   &-column {
@@ -27,13 +27,8 @@ $controls-transition: 0.3s;
   background: #f7f7f7;
 }
 
-.list-group-item {
-  &:focus-visible {
-    outline: none;
-  }
-  &:first-child {
-    border-top: 0;
-  }
+.list-group-item:first-child {
+  border-top: 0;
 }
 
 .tool {
diff --git a/src/components/crown/crownMultiselect/crownMultiselect.vue b/src/components/crown/crownMultiselect/crownMultiselect.vue
index 802d1711..a97dbc5c 100644
--- a/src/components/crown/crownMultiselect/crownMultiselect.vue
+++ b/src/components/crown/crownMultiselect/crownMultiselect.vue
@@ -67,14 +67,20 @@ export default {
       const countSelected = store.getters.highlightedShapes.length;
       return countSelected > 1;
     },
+    isFlow() {
+      return false;
+    },
     highlightedShapes: () => store.getters.highlightedShapes,
   },
   methods: {
     copyElement() {
       // @todo: Implement copyElement
+      console.log('@todo: Implement copyElement');
       this.$emit('copy-nodes');
     },
     deleteElement() {
+      // @todo: Implement deleteElement
+      console.log('@todo: Implement deleteElement');
       this.$emit('remove-nodes');
     },
     paperNotRendered() {
@@ -94,6 +100,7 @@ export default {
 
       this.$emit('save-state');
     },
+    repositionCrown() {},
     paperDoneRendering() {
       if (!this.isRendering) {
         return;
@@ -114,6 +121,7 @@ export default {
     await this.paperDoneRendering();
     this.setUpCrownConfig();
   },
+  destroyed() {},
 };
 </script>
 
diff --git a/src/components/hotkeys/main.js b/src/components/hotkeys/main.js
deleted file mode 100644
index 1a4cde0f..00000000
--- a/src/components/hotkeys/main.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import ZoomInOut from './zoomInOut';
-import store from '@/store';
-import moveShapeByKeypress from './moveWithArrowKeys';
-
-export default {
-  mixins: [ZoomInOut],
-  mounted() {
-    document.addEventListener('keydown', this.keydownListener);
-    document.addEventListener('keyup', this.keyupListener);
-  },
-  methods: {
-    handleHotkeys(event, options) {
-      // Pass event to all handlers
-      this.zoomInOutHandler(event, options);
-    },
-    keyupListener(event) {
-      if (event.code === 'Space') {
-        this.isGrabbing = false;
-        this.paperManager.removeEventHandler('blank:pointermove');
-      }
-    },
-    keydownListener(event) {
-      // Check if either the Control key (Windows/Linux) or the Meta key (macOS) is pressed
-      const isAppleOS = this.isAppleOS();
-      const mod = isAppleOS ? event.metaKey : event.ctrlKey;
-      let options = { mod, isAppleOS, modeler: this };
-      try {
-        this.handleHotkeys(event, options);
-      } catch (error) {
-        // eslint-disable-next-line no-console
-        console.error(error);
-      }
-
-      const focusIsOutsideDiagram = !event.target.toString().toLowerCase().includes('body');
-      if (focusIsOutsideDiagram) {
-        return;
-      }
-
-      if (event.code === 'Space') {
-        this.isGrabbing = true;
-        this.paperManager.addEventHandler('blank:pointermove', (event, x, y) => {
-          if (!this.canvasDragPosition) {
-            const scale = this.paperManager.scale;
-            this.canvasDragPosition = { x: x * scale.sx, y: y * scale.sy };
-          }
-          if (this.canvasDragPosition) {
-            this.paperManager.translate(
-              event.offsetX - this.canvasDragPosition.x,
-              event.offsetY - this.canvasDragPosition.y
-            );
-          }
-        });
-      }
-
-      moveShapeByKeypress(
-        event.key,
-        store.getters.highlightedShapes,
-        this.pushToUndoStack,
-      );
-    },
-  },
-};
diff --git a/src/components/hotkeys/zoomInOut.js b/src/components/hotkeys/zoomInOut.js
deleted file mode 100644
index 7c5c3b5c..00000000
--- a/src/components/hotkeys/zoomInOut.js
+++ /dev/null
@@ -1,29 +0,0 @@
-export default {
-  methods: {
-    zoomInOutHandler(event, options) {
-      const isPlus = 
-        (event.key === '+' || event.key === 'NumpadAdd')
-        || (event.keyCode === 107 || event.keyCode === 187);
-
-      const isMinus = 
-        (event.key === '-' || event.key === 'NumpadSubtract')
-        || (event.keyCode === 109 || event.keyCode === 189);
-
-
-      if (isPlus && options.mod) {
-        this.zoomIn(event);
-      }
-      if (isMinus && options.mod) {
-        this.zoomOut(event);
-      }
-    },
-    zoomIn(event) {
-      event.preventDefault();
-      this.canvasScale = this.paperManager.scale.sx + this.scaleStep;
-    },
-    zoomOut(event) {
-      event.preventDefault();
-      this.canvasScale = Math.max(this.minimumScale, this.paperManager.scale.sx -= this.scaleStep);
-    },
-  },
-};
\ No newline at end of file
diff --git a/src/components/inspectors/InspectorPanel.vue b/src/components/inspectors/InspectorPanel.vue
index 2e135ea5..928e53fa 100644
--- a/src/components/inspectors/InspectorPanel.vue
+++ b/src/components/inspectors/InspectorPanel.vue
@@ -212,7 +212,6 @@ export default {
       return this.defaultInspectorHandler(omit(value, ['artifacts', 'flowElements', 'laneSets']));
     },
     setNodeProp(node, key, value) {
-      this.$emit('shape-resize');
       store.commit('updateNodeProp', { node, key, value });
     },
     defaultInspectorHandler(value) {
diff --git a/src/components/modeler/Modeler.vue b/src/components/modeler/Modeler.vue
index 7a480b82..d5df59b0 100644
--- a/src/components/modeler/Modeler.vue
+++ b/src/components/modeler/Modeler.vue
@@ -51,7 +51,6 @@
 
       <InspectorPanel
         ref="inspector-panel"
-        v-show="!(highlightedNodes.length > 1)"
         :style="{ height: parentHeight }"
         :nodeRegistry="nodeRegistry"
         :moddle="moddle"
@@ -62,14 +61,12 @@
         :parent-height="parentHeight"
         :canvas-drag-position="canvasDragPosition"
         :compressed="panelsCompressed && noElementsSelected"
-        @shape-resize="shapeResize"
       />
 
       <component
         v-for="node in nodes"
         :is="node.type"
         :key="node._modelerId"
-        ref="nodeComponent"
         :graph="graph"
         :paper="paper"
         :node="node"
@@ -93,6 +90,7 @@
         @remove-node="removeNode"
         @set-cursor="cursor = $event"
         @set-pool-target="poolTarget = $event"
+        @click="highlightNode(node, $event)"
         @unset-pools="unsetPools"
         @clearSelection="clearSelection"
         @set-pools="setPools"
@@ -103,11 +101,11 @@
         @replace-generic-flow="replaceGenericFlow"
         @copy-element="copyElement"
         @default-flow="toggleDefaultFlow"
-        @shape-resize="shapeResize"
       />
       <selection
         v-if="paper"
-        ref="selector"
+        ref="selector" 
+        :options="selectorOptions"
         :graph="graph"
         :paperManager="paperManager"
         :useModelGeometry="false"
@@ -153,7 +151,8 @@ import ensureShapeIsNotCovered from '@/components/shapeStackUtils';
 import ToolBar from '@/components/toolbar/ToolBar';
 import Node from '@/components/nodes/node';
 import { addNodeToProcess } from '@/components/nodeManager';
-import hotkeys from '@/components/hotkeys/main';
+import moveShapeByKeypress from '@/components/modeler/moveWithArrowKeys';
+// import setUpSelectionBox from '@/components/modeler/setUpSelectionBox';
 import TimerEventNode from '@/components/nodes/timerEventNode';
 import focusNameInputAndHighlightLabel from '@/components/modeler/focusNameInputAndHighlightLabel';
 import XMLManager from '@/components/modeler/XMLManager';
@@ -184,7 +183,6 @@ export default {
       },
     },
   },
-  mixins: [hotkeys],
   data() {
     return {
       tooltipTarget: null,
@@ -227,15 +225,13 @@ export default {
       activeNode: null,
       xmlManager: null,
       previouslyStackedShape: null,
-      keyMod: this.isAppleOS() ? 'Command' : 'Control',
-      canvasScale: 1,
-      initialScale: 1,
-      minimumScale: 0.2,
-      scaleStep: 0.1,
-      isDragging: false,
       isSelecting: false,
-      isIntoTheSelection: false,
-      dragStart: null,
+      selectorOptions: {
+        top: 100,
+        left: 300,
+        height: 100,
+        width: 100,
+      },
     };
   },
   watch: {
@@ -264,10 +260,6 @@ export default {
     autoValidate() {
       this.validateIfAutoValidateIsOn();
     },
-    canvasScale(canvasScale) {
-      this.paperManager.scale = canvasScale;
-    },
-
   },
   computed: {
     noElementsSelected() {
@@ -292,14 +284,6 @@ export default {
     },
   },
   methods: {
-    isAppleOS() {
-      return typeof navigator !== 'undefined' && /Mac|iPad|iPhone/.test(navigator.platform);
-    },
-    async shapeResize() {
-      await this.$nextTick();
-      await this.paperManager.awaitScheduledUpdates();
-      this.$refs.selector.updateSelectionBox(true);
-    },
     toggleDefaultFlow(flow) {
       const source = flow.definition.sourceRef;
       if (source.default && source.default.id === flow.id) {
@@ -428,20 +412,21 @@ export default {
       this.plane.set('bpmnElement', this.processNode.definition);
       this.collaboration = null;
     },
-    highlightNode(node, event) {
+    highlightNode(node) {
       if (!node || !this.highlightedNode) {
         return;
       }
 
-      if (event && event.shiftKey) {
-        store.commit('addToHighlightedNodes', [node]);
-        return;
-      }
+      // if (event && event.shiftKey) {
+      //   store.commit('addToHighlightedNodes', [node]);
+      //   return;
+      // }
 
       let isSameHighlightedNode = _.isEqual(node.id, this.highlightedNode.id);
 
       if (!isSameHighlightedNode) {
-        store.commit('highlightNode', node);
+        // this.$refs.selector.selectElement(node);
+        store.commit('highlightNode', node);  
       }
 
       return;
@@ -784,6 +769,11 @@ export default {
 
       this.highlightNode(newNode);
       await this.addNode(newNode);
+      const point = {
+        clientX: clientX + 5,
+        clientY: clientY + 5,
+      };
+      this.$refs.selector.markSelectedByPoint(point);
       if (!nodeThatWillBeReplaced) {
         return;
       }
@@ -804,14 +794,7 @@ export default {
       diagram.bounds.x -= (diagram.bounds.width / 2);
       diagram.bounds.y -= (diagram.bounds.height / 2);
     },
-    async selectNewNode(node) {
-      await this.$nextTick();
-      await this.paperManager.awaitScheduledUpdates();
-      const newNodeComponent = this.$refs.nodeComponent.find(component => component.node === node);
-      const view = newNodeComponent.shapeView;
-      await this.$refs.selector.selectElement(view);
-    },
-    async addNode(node) {
+    addNode(node) {
       if (!node.pool) {
         node.pool = this.poolTarget;
       }
@@ -821,9 +804,11 @@ export default {
       node.setIds(this.nodeIdGenerator);
 
       this.planeElements.push(node.diagram);
+      this.$refs.selector.clearSelection();
       store.commit('addNode', node);
       this.poolTarget = null;
-
+      // Clear the selction box
+      
       // add processmaker-modeler-generic-flow
       if ([
         sequenceFlowId,
@@ -837,9 +822,6 @@ export default {
         return;
       }
 
-      // Select the node after it has been added to the store (does not apply to flows)
-      this.selectNewNode(node);
-
       return new Promise(resolve => {
         setTimeout(() => {
           this.pushToUndoStack();
@@ -889,7 +871,6 @@ export default {
 
           await this.removeNode(node, { removeRelationships: false });
           this.highlightNode(newNode);
-          this.selectNewNode(newNode);
         });
       });
     },
@@ -959,6 +940,18 @@ export default {
 
       this.paperManager.setPaperDimensions(clientWidth, clientHeight);
     },
+    keydownListener(event) {
+      const focusIsOutsideDiagram = !event.target.toString().toLowerCase().includes('body');
+      if (focusIsOutsideDiagram) {
+        return;
+      }
+
+      moveShapeByKeypress(
+        event.key,
+        store.getters.highlightedShapes,
+        this.pushToUndoStack,
+      );
+    },
     validateDropTarget({ clientX, clientY, control }) {
       const { allowDrop, poolTarget } = getValidationProperties(clientX, clientY, control, this.paperManager.paper, this.graph, this.collaboration, this.$refs['paper-container']);
       this.allowDrop = allowDrop;
@@ -978,91 +971,6 @@ export default {
     clearSelection(){
       this.$refs.selector.clearSelection();
     },
-    isPointInSelection(event) {
-      const selector = this.$refs.selector.$el;
-      if (typeof selector.getBoundingClientRect === 'function') {
-        // check if mouse was clicked inside the selector
-        const { x: sx, y: sy, width:swidth, height: sheight } = selector.getBoundingClientRect();
-        if (event.clientX >= sx && event.clientX <= sx + swidth && event.clientY >= sy && event.clientY <= sy + sheight) {
-          return true;
-        }
-      }
-      return false;
-    },
-    async pointerDowInShape(event, element) {
-      const { clientX: x, clientY: y } = event;
-      const shapeView = this.paper.findViewByModel(element);
-      this.isDragging = false;
-      this.isSelecting = false;
-      this.isIntoTheSelection = false;
-      this.dragStart = { x, y };
-      // Verify if is in the selection box
-      if (this.isPointInSelection(event)) {
-        this.isIntoTheSelection = true;
-      } else {
-        if (!event.shiftKey) {
-          await this.$refs.selector.selectElement(shapeView);
-          await this.$nextTick();
-        }
-      }
-      this.$refs.selector.startDrag({
-        clientX: event.clientX,
-        clientY: event.clientY,
-      });
-    },
-    pointerDownHandler(event) {
-      const { clientX: x, clientY: y } = event;
-      this.isDragging = false;
-      this.isSelecting = false;
-      this.isIntoTheSelection = false;
-      this.dragStart = { x, y };
-      // Verify if is in the selection box
-      if (this.isPointInSelection(event)) {
-        this.isIntoTheSelection = true;
-        this.$refs.selector.startDrag({
-          clientX: event.clientX,
-          clientY: event.clientY,
-        });
-      } else {
-        this.isSelecting = true;
-        this.$refs.selector.startSelection(event);
-      }
-    },
-    pointerMoveHandler(event) {
-      const { clientX: x, clientY: y } = event;
-      if (this.dragStart && (Math.abs(x - this.dragStart.x) > 5 || Math.abs(y - this.dragStart.y) > 5)) {
-        this.isDragging = true;
-        this.dragStart = null;
-      } else {
-        if (this.isSelecting) {
-          this.$refs.selector.updateSelection(event);
-        } else {
-          if (this.isDragging) {
-            this.$refs.selector.drag(event);
-          }
-        }
-      }
-    },
-    pointerUpHandler(event, cellView) {
-      if (!this.isDragging && this.dragStart) {
-        // is clicked over the shape
-        if (cellView) {
-          this.$refs.selector.stopDrag(event);
-          this.$refs.selector.selectElement(cellView, event.shiftKey);
-        } else {
-          this.clearSelection();
-        }
-      } else {
-        if (this.isSelecting) {
-          this.$refs.selector.endSelection(this.paperManager.paper);
-        } else {
-          this.$refs.selector.stopDrag(event);
-        }
-      }
-      this.isDragging = false;
-      this.dragStart = null;
-      this.isSelecting = false;
-    },
   },
   created() {
     if (runningInCypressTest()) {
@@ -1096,19 +1004,20 @@ export default {
     this.$emit('set-xml-manager', this.xmlManager);
   },
   mounted() {
+    document.addEventListener('keydown', this.keydownListener);
+
     this.graph = new dia.Graph();
     store.commit('setGraph', this.graph);
     this.graph.set('interactiveFunc', cellView => {
-      const isPoolEdge = cellView.model.get('type') === 'standard.EmbeddedImage';
       return {
-        elementMove: isPoolEdge,
+        elementMove: cellView.model.get('elementMove'),
         labelMove: false,
       };
     });
 
     this.paperManager = PaperManager.factory(this.$refs.paper, this.graph.get('interactiveFunc'), this.graph);
     this.paper = this.paperManager.paper;
-
+    
     this.paperManager.addEventHandler('cell:pointerdblclick', focusNameInputAndHighlightLabel);
 
     this.handleResize();
@@ -1116,29 +1025,38 @@ export default {
 
     store.commit('setPaper', this.paperManager.paper);
 
+    this.paperManager.addEventHandler('blank:pointerclick', () => {
+      store.commit('highlightNode', this.processNode);
+    }, this);
+
     this.paperManager.addEventHandler('element:pointerclick', this.blurFocusedScreenBuilderElement, this);
 
     this.paperManager.addEventHandler('blank:pointerdown', (event, x, y) => {
-      if (this.isGrabbing) return;
       const scale = this.paperManager.scale;
       this.canvasDragPosition = { x: x * scale.sx, y: y * scale.sy };
-      this.isOverShape = false;
-      this.pointerDownHandler(event);
-    }, this);
-    this.paperManager.addEventHandler('blank:pointerup', (event) => {
-      this.canvasDragPosition = null;
-      this.activeNode = null;
-      this.pointerUpHandler(event);
+      this.$refs.selector.startSelection(event, this.paperManager.paper);
+      // this.isGrabbing = true;
     }, this);
-    this.paperManager.addEventHandler('cell:pointerup', (cellView, event) => {
+    this.paperManager.addEventHandler('cell:pointerup blank:pointerup', () => {
       this.canvasDragPosition = null;
+      // this.isGrabbing = false;
+      this.isSelecting = false;
       this.activeNode = null;
-      this.pointerUpHandler(event, cellView);
+      this.$refs.selector.endSelection(this.paperManager.paper);
     }, this);
 
     this.$el.addEventListener('mousemove', event => {
-      this.pointerMoveHandler(event);
+      this.$refs.selector.updateSelection(event, this.paperManager.paper);
     });
+    
+    // this.$el.addEventListener('mousemove', event => {
+    //   if (this.canvasDragPosition) {
+    //     this.paperManager.translate(
+    //       event.offsetX - this.canvasDragPosition.x,
+    //       event.offsetY - this.canvasDragPosition.y,
+    //     );
+    //   }
+    // }, this);
 
     this.paperManager.addEventHandler('cell:pointerclick', (cellView, evt, x, y) => {
       const clickHandler = cellView.model.get('onClick');
@@ -1155,16 +1073,23 @@ export default {
       shape.component.$emit('click', event);
     });
 
-    this.paperManager.addEventHandler('cell:pointerdown', ({ model: shape }, event) => {
+    this.paperManager.addEventHandler('cell:pointerdown', ({ model: shape }) => {
       if (!this.isBpmnNode(shape)) {
         return;
       }
+
       this.setShapeStacking(shape);
       this.activeNode = shape.component.node;
-      this.isOverShape = true;
-      this.pointerDowInShape(event, shape);
     });
 
+    // let cursor;
+    // const setCursor = () => {
+    //   cursor = this.cursor;
+    //   this.cursor = 'crosshair';
+    // };
+    // const resetCursor = () => this.cursor = cursor;
+    // setUpSelectionBox(setCursor, resetCursor, this.paperManager, this.graph);
+
     /* Register custom nodes */
     window.ProcessMaker.EventBus.$emit('modeler-start', {
       loadXML: xml => {
diff --git a/src/components/modeler/Selection.vue b/src/components/modeler/Selection.vue
index c7ad6411..91ca4273 100644
--- a/src/components/modeler/Selection.vue
+++ b/src/components/modeler/Selection.vue
@@ -5,8 +5,9 @@
     class="box"
     data-cy="selection-box"
     :data-length="selected.length"
+    @mousedown="startDrag"
     :style="style"
-  >
+  > 
     <crown-multiselect
       :paper="paperManager.paper"
       :graph="$parent.graph"
@@ -27,7 +28,6 @@ import store from '@/store';
 import CrownMultiselect from '@/components/crown/crownMultiselect/crownMultiselect';
 import { id as poolId } from '@/components/nodes/pool/config';
 import { id as laneId } from '@/components/nodes/poolLane/config';
-import { id as genericFlowId } from '@/components/nodes/genericFlow/config';
 import { labelWidth, poolPadding } from '../nodes/pool/poolSizes';
 export default {
   name: 'Selection',
@@ -35,6 +35,7 @@ export default {
     CrownMultiselect,
   },
   props: {
+    options: Object,
     graph: Object,
     paperManager: Object,
     useModelGeometry: Boolean,
@@ -61,95 +62,18 @@ export default {
       hasMouseDown: false,
       hasMouseMoved: false,
       showLasso: false,
+      shiftKeyPressed: false,
       isOutOfThePool: false,
-      stopForceMove: false,
-      draggableBlackList: [
-        laneId,
-      ],
-      selectionBlackList:[
-        genericFlowId,
-      ],
-      selectableBlackList:[
-        genericFlowId,
-      ],
     };
   },
   mounted(){
     this.paperManager.paper.on('scale:changed ', this.updateSelectionBox);
     this.paperManager.paper.on('translate:changed ', this.translateChanged);
-  },
-  watch: {
-    // whenever selected changes
-    selected(newSelected) {
-      this.addToHighlightedNodes(newSelected);
-    },
+    this.paperManager.paper.on('element:pointerclick', this.elementClickHandler);
+    document.addEventListener('keydown', this.shiftKeyDownListener);
+    document.addEventListener('keyup', this.shiftKeyUpListener);
   },
   methods: {
-    /**
-     * Select an element dinamically.
-     * Shift key will manage the condition to push to selection
-     * @param {Object} view
-     * @param {Boolean} shiftKey
-     */
-    async selectElement(view, shiftKey = false) {
-      if (view.model.component && this.selectableBlackList.includes(view.model.component.node.type)) {
-        return;
-      }
-      this.showLasso = true;
-      this.isSelected = true;
-      this.isSelecting = true;
-      this.start = null;
-      if (shiftKey) {
-        this.shiftKeySelectionHandler(view);
-      } else {
-        this.selected = [view];
-      }
-      this.filterSelected();
-      await this.$nextTick();
-      this.updateSelectionBox();
-    },
-    /**
-     * Select or unselect an element with shift key pressed
-     * @param {Object} view
-     */
-    shiftKeySelectionHandler(view){
-      // validate if current shape is black listed
-      if (view && view.model && view.model.component &&
-        this.draggableBlackList.includes(view.model.component.node.type)) {
-        return;
-      }
-      // validate if there is a lane previously selected
-      let lane = this.selected.find(view => {
-        return this.draggableBlackList.includes(view.model.component.node.type);
-      });
-      if (lane) {
-        this.selected = [view];
-        return;
-      } 
-      // validate if the current selection is a pool
-      if (view.model.component && view.model.component.node.type === poolId) {
-        //validate if previous selection are all pools
-        if (this.hasOnlyPools(this.selected)) {
-          this.selectOrUnselectShape(view);
-        } else {
-          this.selected = [view];
-        }
-        return;
-      }
-      this.selectOrUnselectShape(view);
-    },
-    /**
-     * Select an shape if it is not in the collection
-     * Unselect an shape if it is in the collection
-     */
-    selectOrUnselectShape(view){
-      const element = this.selected.find( item => item.id === view.id);
-      if (element) {
-        this.selected = this.selected.filter(item => item.id !== view.id);
-      } else {
-        this.selected.push(view);
-      }     
-    },
     clearSelection() {
       this.initSelection();
     },
@@ -221,7 +145,7 @@ export default {
 
       const selectorOffset = {
         left: this.$el.offsetLeft + paperOffset.left,
-        top: this.$el.offsetTop + paperOffset.top,
+        top: this.$el.offsetTop + paperOffset.top, 
       };
       let width = this.$el.clientWidth;
       let height = this.$el.clientHeight;
@@ -234,7 +158,7 @@ export default {
       height /= scale.sy;
 
       let selectedArea = g.rect(f.x, f.y, width, height);
-      this.selected = this.getElementsInSelectedArea(selectedArea, { strict: false });
+      this.selected= this.getElementsInSelectedArea(selectedArea, { strict: false });
       this.filterSelected();
       if (this.selected && this.selected.length > 0) {
         this.updateSelectionBox();
@@ -245,51 +169,34 @@ export default {
         this.start = null;
       }
       this.start = null;
+      this.addToHighlightedNodes();
+
     },
     /**
      * Get elements into a selected area
-     * @param {Object} area
+     * @param {Object} area 
      */
-    getElementsInSelectedArea(area, options, addLinks=true) {
+    getElementsInSelectedArea(area, options) {
       const { paper } = this.paperManager;
-      const elements =  paper.findViewsInArea(area, options);
-
-      if (!addLinks) {
-        return elements;
-      }
-      // get flows
-      this.graph.getLinks().forEach(function(link) {
-        // Check if the link is within the selected area
-        if (area.intersect(link.getBBox())) {
-          // The link is within the selected area
-          // Do something with the link, such as highlighting it
-          elements.push(paper.findViewByModel(link));
-        }
-      });
-      return elements;
+      return paper.findViewsInArea(area, options);
     },
     /**
      * Return the bounding box of the selected elements,
-     * @param {Array} selected
+     * @param {Array} selected 
      */
-    getSelectionVertex(selected, byModel = false, includeAll = false) {
+    getSelectionVertex(selected, byModel = false) {
       const point = { x : 1 / 0, y: 1 / 0 };
       const size = { width: 0, height: 0 };
       const useModelGeometry = this.useModelGeometry;
-      const shapesToNotTranslate = [
-        'PoolLane',
-        'standard.Link',
-      ];
-      selected.filter(shape => includeAll || !shapesToNotTranslate.includes(shape.model.get('type')))
-        .map(function(view) {
-          const box = byModel ?
-            view.model.getBBox({ useModelGeometry }) :
-            view.getBBox({ useModelGeometry }).inflate(7);
-          point.x = Math.min(point.x, box.x);
-          point.y = Math.min(point.y, box.y);
-          size.width = Math.max(size.width, box.x + box.width);
-          size.height= Math.max(size.height, box.y + box.height);
-        });
+      selected.map(function(view) {
+        const box = byModel ?
+          view.model.getBBox({ useModelGeometry }) :
+          view.getBBox({ useModelGeometry }).inflate(4);
+        point.x = Math.min(point.x, box.x);
+        point.y = Math.min(point.y, box.y);
+        size.width = Math.max(size.width, box.x + box.width);
+        size.height= Math.max(size.height, box.y + box.height);
+      });
       return {
         minX: point.x,
         minY: point.y,
@@ -300,26 +207,38 @@ export default {
     /**
      * Update the selection Box
      */
-    updateSelectionBox(force=false) {
-      if (force || this.isSelecting && this.style) {
-        if (this.selected.length > 0) {
-          const box = this.getSelectionVertex(this.selected, false, true);
-          // Set the position of the element
-          this.style.left = `${box.minX}px`;
-          this.style.top = `${box.minY}px`;
-          this.left = parseInt(this.style.left);
-          this.top = parseInt(this.style.top);
-          // Set the dimensions of the element
-          this.style.width = `${box.maxX - box.minX}px`;
-          this.style.height = `${box.maxY - box.minY}px`;
-        } else {
-          this.clearSelection();
-        }
+    updateSelectionBox() {
+      if (this.isSelecting && this.style) {
+        const box = this.getSelectionVertex(this.selected);
+        // Set the position of the element
+        this.style.left = `${box.minX}px`;
+        this.style.top = `${box.minY}px`;
+        // Set the dimensions of the element
+        this.style.width = `${box.maxX - box.minX}px`;
+        this.style.height = `${box.maxY - box.minY}px`;
       }
     },
     /**
-     * Filter the selected elements
+     * Update the selected box if a user select a element with shift key pressed 
+     * @param {Object} elementView 
      */
+    elementClickHandler(elementView) {
+      if (this.shiftKeyPressed) {
+        const element = this.selected.find( item => item.id === elementView.id);
+        if (!element) {
+          this.selected.push(elementView);
+          this.filterSelected();
+          this.addToHighlightedNodes();
+        }
+      } else {
+        this.selected = [elementView];
+        store.commit('highlightNode', this.selected[0].model.component.node);
+      }
+      this.isSelecting = true;
+      this.isSelected = true;
+      this.showLasso = true;
+      this.updateSelectionBox();
+    },
     filterSelected() {
       // remove from selection the selected child nodes in the pool
       const selectedPoolsIds = this.selected
@@ -328,93 +247,46 @@ export default {
         .map(shape => shape.model.component.node.id);
       this.selected = this.selected.filter(shape => {
         if (shape.model.component && shape.model.component.node.pool) {
-          return shape.model.component.node.pool && !selectedPoolsIds.includes(shape.model.component.node.pool.component.node.id);
+          return !selectedPoolsIds.includes(shape.model.component.node.pool?.component?.node?.id);
         }
         return true;
-      }).filter(shape => {
-        return !(shape.model.getParentCell() && shape.model.getParentCell().get('parent'));
       });
     },
     /**
-     * Pan paper handler
+     * Pan papae handler
      */
     translateChanged() {
       if (this.isSelecting) {
         this.updateSelectionBox();
       }
-    },
-    /**
-     * Verify if has selected lanes
-     */
-    hasLanes(selected) {
-      const shapesToNotTranslate = [
-        'processmaker-modeler-lane',
-      ];
-      const shapes = selected.find(shape => {
-        return shapesToNotTranslate.includes(shape.model.component.node.type);
-      });
-      if (shapes) {
-        return true;
-      } 
-      return false;
-    },
-    /**
-     * Verify if has only flows
-     */
-    hasOnlyLinks(selected) {
-      let shapes = this.selected.filter(shape => {
-        return shape.model.get('type') === 'standard.Link';
-      });
-      return shapes && selected.length === shapes.length;
-    },
-    /**
-     * Verify if has selected one Pools
-     */
-    hasOnlyPools(selected) {
-      let shapes = this.selected.filter(shape => {
-        return shape.model.component && shape.model.component.node.type === poolId;
-      });
-      return shapes && selected.length === shapes.length;
-    },
+    },  
     /**
      * Start the drag procedure for the selext box
-     * @param {Object} event
+     * @param {Object} event 
      */
     startDrag(event) {
-      if (!this.$refs.drag){
-        return;
-      }
-      this.stopForceMove = false;
       this.dragging = true;
       this.hasMouseMoved = false;
-      const nEvent= util.normalizeEvent(event);
-      this.mouseX = nEvent.clientX;
-      this.mouseY = nEvent.clientY;
+      this.mouseX = event.clientX;
+      this.mouseY = event.clientY;
       this.top = this.$refs.drag.offsetTop;
       this.left = this.$refs.drag.offsetLeft;
       this.initialPosition = {
         top: this.top,
         left: this.left,
-      };
-      if (this.hasLanes(this.selected)) {
-        this.stopForceMove = true;
-        return;
-      }
-      if (this.hasOnlyLinks(this.selected)) {
-        this.stopForceMove = true;
-        return;
-      }
-      if (this.selected && this.selected.length === 1 &&
-        this.selected[0].model.get('type') === 'processmaker.components.nodes.boundaryEvent.Shape') {
-        this.selected[0].model.component.attachToValidTarget(this.selected[0]);
-      }
+      },
+      window.addEventListener('mousemove', this.drag);
+      window.addEventListener('mouseup', this.stopDrag);
+      
     },
     /**
      * on Drag procedure
-     * @param {*} event
+     * @param {*} event 
      */
     drag(event) {
-      if (this.stopForceMove) return;
+      const shapesToNotTranslate = [
+        'PoolLane',
+      ];
       if (!this.dragging) return;
       this.hasMouseMoved = true;
       const nEvent= util.normalizeEvent(event);
@@ -422,53 +294,43 @@ export default {
       const deltaY = nEvent.clientY - this.mouseY;
       this.top += deltaY;
       this.left += deltaX;
-      this.mouseX = nEvent.clientX;
-      this.mouseY = nEvent.clientY;
+      this.mouseX = event.clientX;
+      this.mouseY = event.clientY;
       // Set the position of the element
       const scale = this.paperManager.paper.scale();
       this.style.left =`${this.left}px`;
       this.style.top = `${this.top}px`;
-      this.translateSelectedShapes(deltaX/scale.sx, deltaY/scale.sy);
+      this.selected.forEach(shape => {
+        if (!shapesToNotTranslate.includes(shape.model.get('type'))) {
+          shape.model.translate(deltaX/scale.sx, deltaY/scale.sy);
+        }
+      });
       this.overPoolDrag(event);
     },
     /**
      * Stop drag procedure
-     * @param {Object} event
+     * @param {Object} event 
      */
-    stopDrag() {
+    stopDrag(event) {
+      if (this.hasMouseMoved) {
+        this.hasMouseDown = false;
+        
+        this.updateSelectionBox();
+      } else {
+        if (!this.shiftKeyPressed) {
+          this.selectShapeInLasso(event);
+          this.removeListeners();
+        } else {
+          this.unselectShapeInLasso(event);
+        }
+      }
       this.overPoolStopDrag();
       this.$emit('save-state');
       this.dragging = false;
-      this.stopForceMove = false;
-    },
-    /**
-     * Translate the Selected shapes adding some custom validations
-     */
-    translateSelectedShapes(x, y, drafRef) {
-      const shapesToNotTranslate = [
-        'PoolLane',
-        'standard.Link',
-        'processmaker.components.nodes.boundaryEvent.Shape',
-      ];
-      let shapes = this.selected.filter(shape => {
-        return !shapesToNotTranslate.includes(shape.model.get('type'));
-      });
-      if (drafRef) {
-        shapes.filter(shape =>{
-          return drafRef.model.get('id') !== shape.model.get('id');
-        });
-      }
-      // allow movement only if one lane boundary event is selected;
-      if (this.selected && this.selected.length === 1 && 
-        this.selected[0].model.get('type') === 'processmaker.components.nodes.boundaryEvent.Shape') {
-        this.selected[0].model.translate(x, y);
-        return;
-      }
-      shapes.forEach((shape)=> shape.model.translate(x, y));
     },
     /**
      * Gets shape from a point object
-     * @param {Object} event
+     * @param {Object} event 
      */
     getShapesFromPoint(event){
       const nEvent= util.normalizeEvent(event);
@@ -478,42 +340,100 @@ export default {
       return this.paperManager.paper.findViewsFromPoint(point);
     },
     /**
-     * Add an element into the highlighted nodes
+     * Select a element that is into the selection box
+     * @param {*} event 
      */
-    addToHighlightedNodes(selected){
-      store.commit('highlightNode');
-      if (selected.length > 0) {
-        const selectedNodes = selected.filter(shape => shape.model.component)
-          .map(shape => shape.model.component.node);
-        store.commit('addToHighlightedNodes', selectedNodes);
+    selectShapeInLasso(event) {
+      const element = this.getNotEmbeddedShape(event);
+      this.selected = [];
+      if (element) { 
+        this.selected = [element];
+      }
+      if (this.selected && this.selected.length > 0) {
+        this.updateSelectionBox();
+        store.commit('highlightNode', this.selected[0].model.component.node);
       } else {
+        this.clearSelection();
+        this.removeListeners();
+        store.commit('highlightNode', this.processNode);
+      }
+    },
+    /**
+     * Unselect an element that is not into the selection box
+     * @param {Object} event 
+     */
+    unselectShapeInLasso(event){
+      const elements = this.getShapesFromPoint(event);
+      if (this.shiftKeyPressed && elements) {
         store.commit('highlightNode', this.processNode);
+        this.selected = this.selected.filter(item => {
+          return !elements.some(otherItem => {
+            return item.id === otherItem.id && item.name === otherItem.name;
+          });
+        });
+        if (this.selected.length > 0) {
+          this. updateSelectionBox();
+          this.addToHighlightedNodes();
+        } else {
+          this.clearSelection();
+        }
+      }
+    },
+    /**
+     * Add an element into the highlighted nodes
+     */
+    addToHighlightedNodes(){
+      store.commit('highlightNode');
+      const selectedNodes = this.selected.filter(shape => shape.model.component)
+        .map(shape => shape.model.component.node);
+      store.commit('addToHighlightedNodes', selectedNodes);
+    },
+    /**
+     * remove window listeners
+     */
+    removeListeners(){
+      window.removeEventListener('mousemove', this.drag);
+      window.removeEventListener('mouseup', this.stopDrag);
+    },
+    /**
+     * Shift Key Down Handler
+     * @param {*} event 
+     */
+    shiftKeyDownListener(event) {
+      // check if shift key is pressed without any other key
+      if (event.key === 'Shift' && !event.ctrlKey && !event.altKey && !event.metaKey) {
+        this.shiftKeyPressed = true;
       }
     },
     /**
-     * Gets the child shape
-     * @param {object} point
+     * Shift Key Up Handler
      */
-    getChildShape(point) {
+    shiftKeyUpListener({ key }) {
+      if (key === 'Shift') {
+        this.shiftKeyPressed = false;
+      }
+    },
+    /**
+     * Gets the not embedded shape
+     * @param {object} point 
+     */
+    getNotEmbeddedShape(point){
       let result = null;
       const views = this.getShapesFromPoint(point);
-      if (views.length === 1 ) {
-        return views[0];
-      }
       views.forEach(shape => {
-        if (shape.model.get('parent') && shape.model.component.node.type !== laneId) {
+        if (shape.model.getEmbeddedCells().length === 0){
           result = shape;
-        }
+        } 
       });
       return result;
     },
     /**
-     * Mark a shape as selected
-     * @param {object} point
+     * 
+     * @param {object} point 
      */
     markSelectedByPoint(point) {
-      const element = this.getChildShape(point);
-      if (element) {
+      const element = this.getNotEmbeddedShape(point);
+      if (element) { 
         this.selected = [element];
       }
       if (this.selected.length > 0) {
@@ -532,7 +452,7 @@ export default {
 
       const selectorOffset = {
         left: this.$el.offsetLeft + paperOffset.left,
-        top: this.$el.offsetTop + paperOffset.top,
+        top: this.$el.offsetTop + paperOffset.top, 
       };
       let width = this.$el.clientWidth;
       let height = this.$el.clientHeight;
@@ -550,17 +470,13 @@ export default {
     /**
      * Check that they are not in a pool
      * @param {Array} elements 
-     * @return true if there is a pool in the selection or if none of the selected elements are in a pool
      */
     isNotPoolChilds(elements) {
       if (elements.length > 0) {
-        const poolInSelection = elements.find(({ model }) => {
-          return model.component && model.component.node.type === poolId;
-        });
-        const elementInAPool = elements.find(({ model }) => {
-          return (model.getParentCell() && model.getParentCell().component.node.type === poolId);
-        });
-        return !!poolInSelection || !elementInAPool;
+        const model = elements[0].model;
+        return !(model.component &&
+          model.component.node.type !== laneId &&
+          model.getParentCell() && model.getParentCell().component.node.type === poolId);
       }
       return false;
     },
@@ -607,14 +523,9 @@ export default {
       this.style.left = `${this.initialPosition.left}px`;
       this.style.top = `${this.initialPosition.top}px`;
       const scale = this.paperManager.paper.scale();
-      const shapesToNotTranslate = [
-        'PoolLane',
-        'standard.Link',
-      ];
-      this.selected.filter(shape => !shapesToNotTranslate.includes(shape.model.get('type')))
-        .forEach(shape => {
-          shape.model.translate(deltaX/scale.sx, deltaY/scale.sy);
-        });
+      this.selected.forEach(shape => {
+        shape.model.translate(deltaX/scale.sx, deltaY/scale.sy);
+      });
       this.isOutOfThePool = false;
       store.commit('allowSavingElementPosition');
       this.paperManager.setStateValid();
@@ -624,18 +535,14 @@ export default {
      */
     expandToFitElement(selected) {
       if (selected.length > 0) {
-        const pool = selected.find(({ model }) => {
-          if (model.getParentCell()) {
-            return model.getParentCell().component.node.type === poolId;
-          }
-          return false;
-        }).model.getParentCell();
+        const model = selected[0].model;
+        const pool = model.getParentCell();
         const selectionBBox = this.getSelectionVertex(this.selected, true);
         const { x: poolX, y: poolY, width, height } = pool.getBBox();
 
         const elementWidth = selectionBBox.maxX - selectionBBox.minX;
         const elementHeight = selectionBBox.maxY - selectionBBox.minY;
-
+       
         const relativeX = selectionBBox.minX - poolX;
         const relativeY = selectionBBox.minY  - poolY;
 
@@ -689,9 +596,11 @@ export default {
             bounds: pool.getBBox(),
           });
           this.$emit('save-state');
-        }
+        } 
+
       }
     },
+
   },
 };
 </script>
@@ -700,6 +609,5 @@ export default {
 .box {
   border: 1px solid #5faaee;
   position: absolute;
-  pointer-events: none;
 }
 </style>
diff --git a/src/components/modeler/modeler.scss b/src/components/modeler/modeler.scss
index 46258326..159cf47f 100644
--- a/src/components/modeler/modeler.scss
+++ b/src/components/modeler/modeler.scss
@@ -18,6 +18,7 @@
 
   .paper-container {
     position: initial !important;
+    // cursor: grab;
     user-select: none;
   }
 
diff --git a/src/components/hotkeys/moveWithArrowKeys.js b/src/components/modeler/moveWithArrowKeys.js
similarity index 100%
rename from src/components/hotkeys/moveWithArrowKeys.js
rename to src/components/modeler/moveWithArrowKeys.js
diff --git a/src/components/modeler/setUpSelectionBox.js b/src/components/modeler/setUpSelectionBox.js
index b8a08f5a..2807b47f 100644
--- a/src/components/modeler/setUpSelectionBox.js
+++ b/src/components/modeler/setUpSelectionBox.js
@@ -100,7 +100,7 @@ export default function setUpSelectionBox(setCursor, resetCursor, paperManager,
       .map(shape => shape.model.component.node);
 
     store.commit('addToHighlightedNodes', selectedNodes);
-
+    
     graph.removeCells(selectionBox);
     selectionBox = null;
   }
diff --git a/src/components/nodes/boundaryEvent/boundaryEvent.vue b/src/components/nodes/boundaryEvent/boundaryEvent.vue
index b37748d6..9cb74615 100644
--- a/src/components/nodes/boundaryEvent/boundaryEvent.vue
+++ b/src/components/nodes/boundaryEvent/boundaryEvent.vue
@@ -143,7 +143,6 @@ export default {
     resetToInitialPosition() {
       this.shape.position(this.validPosition.x, this.validPosition.y);
       store.commit('allowSavingElementPosition');
-      this.$emit('shape-resize');
     },
     moveBoundaryEventIfOverTask() {
       const task = this.getTaskUnderShape();
@@ -155,13 +154,11 @@ export default {
 
       this.attachBoundaryEventToTask(task);
       this.updateShapePosition(task);
-      this.$emit('shape-resize');
     },
     resetInvalidTarget() {
       if (this.invalidTargetElement) {
         resetShapeColor(this.invalidTargetElement);
         this.invalidTargetElement = null;
-        this.$emit('shape-resize');
       }
     },
     attachToValidTarget(cellView) {
diff --git a/src/components/paperManager.js b/src/components/paperManager.js
index 7b54a2f9..1983e0cd 100644
--- a/src/components/paperManager.js
+++ b/src/components/paperManager.js
@@ -2,6 +2,7 @@ import { dia, util } from 'jointjs';
 import { defaultNodeColor, invalidNodeColor } from '@/components/nodeColors';
 import { gridSize } from '@/graph';
 
+
 export default class PaperManager {
   #paper;
   preventTranslate = false;
@@ -21,8 +22,6 @@ export default class PaperManager {
       sorting: 'sorting-approximate',
       gridSize: PaperManager.gridSize,
       drawGrid: true,
-      snapLinks: false, // disable snapping of links
-      snapElements: false, // disable snapping of elements
       clickThreshold: 10,
       perpendicularLinks: true,
       interactive: interactiveFunc,
diff --git a/src/components/toolbar/ToolBar.vue b/src/components/toolbar/ToolBar.vue
index acbbdc82..9fcee1f6 100644
--- a/src/components/toolbar/ToolBar.vue
+++ b/src/components/toolbar/ToolBar.vue
@@ -34,7 +34,7 @@
         <div class="btn-group btn-group-sm mr-2" role="group" aria-label="Zoom controls">
           <b-button
             class="btn btn-sm btn-secondary"
-            @click="paperManager.scale = paperManager.scale.sx + scaleStep"
+            @click="scale += scaleStep"
             data-test="zoom-in"
             v-b-tooltip.hover
             :title="$t('Zoom In')"
@@ -43,7 +43,7 @@
           </b-button>
           <b-button
             class="btn btn-sm btn-secondary"
-            @click="paperManager.scale = Math.max(minimumScale, paperManager.scale.sx -= scaleStep)"
+            @click="scale = Math.max(minimumScale, scale -= scaleStep)"
             data-test="zoom-out"
             v-b-tooltip.hover
             :title="$t('Zoom Out')"
@@ -51,17 +51,16 @@
             <font-awesome-icon :icon="minusIcon" />
           </b-button>
           <b-button
-            v-if="paperManager"
             class="btn btn-sm btn-secondary"
-            @click="paperManager.scale = initialScale"
-            :disabled="paperManager.scale.sx === initialScale"
+            @click="scale = initialScale"
+            :disabled="scale === initialScale"
             data-test="zoom-reset"
             v-b-tooltip.hover
             :title="$t('Reset to initial scale')"
           >
             {{ $t('Reset') }}
           </b-button>
-          <span v-if="paperManager" class="btn btn-sm btn-secondary scale-value">{{ Math.round(paperManager.scale.sx*100) }}%</span>
+          <span class="btn btn-sm btn-secondary scale-value">{{ Math.round(scale*100) }}%</span>
         </div>
 
         <div class="btn-group btn-group-sm mr-2" role="group" aria-label="Additional controls">
@@ -122,6 +121,12 @@ export default {
     panelsCompressed: Boolean,
   },
   watch: {
+    scale(scale) {
+      this.paperManager.scale = scale;
+      if (scale === this.initialScale) {
+        this.$root.$emit('bv::hide::tooltip');
+      }
+    },
     miniMapOpen(isOpen) {
       this.$emit('toggle-mini-map-open', isOpen);
     },
diff --git a/src/mixins/highlightConfig.js b/src/mixins/highlightConfig.js
index 9c09cdf3..fcf41f62 100644
--- a/src/mixins/highlightConfig.js
+++ b/src/mixins/highlightConfig.js
@@ -97,7 +97,6 @@ export default {
           this.setShapeHighlight();
           this.shape.on('change:size', () => {
             this.paperManager.awaitScheduledUpdates().then(this.setShapeHighlight);
-            this.$emit('shape-resize', this.shape);
           });
         });
     });
diff --git a/src/mixins/linkConfig.js b/src/mixins/linkConfig.js
index 41b18439..07842c5f 100644
--- a/src/mixins/linkConfig.js
+++ b/src/mixins/linkConfig.js
@@ -302,9 +302,6 @@ export default {
     }
 
     this.updateRouter();
-    this.shape.on('change:vertices', function() {
-      this.component.$emit('shape-resize');
-    });
   },
   beforeDestroy() {
     document.removeEventListener('mouseup', this.emitSave);
diff --git a/src/store.js b/src/store.js
index d9f37017..9c8fc2ef 100644
--- a/src/store.js
+++ b/src/store.js
@@ -100,12 +100,7 @@ export default new Vuex.Store({
         .map(node => node.id);
       state.highlightedNodes = highlightedNodes
         // remove from selection the selected child nodes in the pool
-        .filter(node => {
-          if (node.pool && node.pool.component.node.id) {
-            return !selectedPoolsIds.includes(node.pool.component.node.id);
-          }
-          return true;
-        });
+        .filter(node => node.pool?.component?.node?.id && !selectedPoolsIds.includes(node.pool.component.node.id));
     },
     addNode(state, node) {
       /* Add an unchanging ID that Vue can use to track the component


Test patch:
diff --git a/tests/e2e/specs/canvasUsability/canvasSelection/DeselectWhenCanvasIsClicked.spec.js b/tests/e2e/specs/canvasUsability/canvasSelection/DeselectWhenCanvasIsClicked.spec.js
deleted file mode 100644
index fcaa6c67..00000000
--- a/tests/e2e/specs/canvasUsability/canvasSelection/DeselectWhenCanvasIsClicked.spec.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import {
-  dragFromSourceToDest,
-  connectNodesWithFlow,
-  waitToRenderAllShapes,
-} from '../../../support/utils';
-import { nodeTypes } from '../../../support/constants';
-
-describe('Canvas Selection', () => {
-  it('Verify that controls are deselected when the user click in canvas', () => {
-    const startEventPosition = { x: 150, y: 150 };
-    const taskFormPosition = {
-      x: startEventPosition.x + 200,
-      y: startEventPosition.y,
-    };
-    const endEventPosition = {
-      x: taskFormPosition.x + 200,
-      y: taskFormPosition.y,
-    };
-
-    // Drag a Task Form
-    dragFromSourceToDest(nodeTypes.task, taskFormPosition);
-
-    // Connect the Start Event with Task Form
-    connectNodesWithFlow('generic-flow-button', startEventPosition, taskFormPosition);
-
-    // Drag an End Event
-    dragFromSourceToDest(nodeTypes.endEvent, endEventPosition);
-
-    // Connect the Task Form with End Event
-    connectNodesWithFlow('generic-flow-button', taskFormPosition, endEventPosition);
-
-    // Select all elements
-    cy.get('.paper-container').as('paperContainer').click();
-    cy.get('.paper-container').trigger('mousedown', 'topLeft');
-    cy.get('.paper-container').trigger('mousemove', 'bottomRight');
-    waitToRenderAllShapes();
-    cy.get('.paper-container').trigger('mouseup', 'bottomRight');
-
-    
-    // Validation 1: Verify that controls are selected inside a selection box
-    cy.get('[data-cy="selection-box"]').should('exist');
-    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"] [data-cy="selected"]').should('exist');
-    cy.get('[data-type="processmaker.components.nodes.task.Shape"] [data-cy="selected"]').should('exist');
-    cy.get('[data-type="processmaker.components.nodes.endEvent.Shape"] [data-cy="selected"]').should('exist');
-    // Check the selection is large enough to contain all elements
-    cy.get('[data-cy="selection-box"]').then($selectionBox => {
-      const selectionBoxWidth = $selectionBox.width();
-      expect(selectionBoxWidth).to.be.greaterThan(400);
-    });
-
-    // Validation 2: Verify that the previous selection was lost after click in the canvas
-    cy.get('.paper-container').trigger('mousedown', 'topLeft');
-    cy.get('.paper-container').trigger('mouseup', 'topLeft');
-    cy.get('[data-cy="selection-box"]').should('not.exist');
-  });
-});
diff --git a/tests/e2e/specs/canvasUsability/canvasSelection/SelectingAnElementByClickingOnIt.spec.js b/tests/e2e/specs/canvasUsability/canvasSelection/SelectingAnElementByClickingOnIt.spec.js
deleted file mode 100644
index 3a7e93d2..00000000
--- a/tests/e2e/specs/canvasUsability/canvasSelection/SelectingAnElementByClickingOnIt.spec.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import {
-  dragFromSourceToDest,
-  connectNodesWithFlow,
-  waitToRenderAllShapes,
-  getElementAtPosition,
-} from '../../../support/utils';
-import { nodeTypes } from '../../../support/constants';
-
-describe('Canvas Selection', () => {
-  it('Verify that controls are selected when the user click on it', () => {
-    const startEventPosition = { x: 150, y: 150 };
-    const taskFormPosition = {
-      x: startEventPosition.x + 200,
-      y: startEventPosition.y,
-    };
-    const endEventPosition = {
-      x: taskFormPosition.x + 200,
-      y: taskFormPosition.y,
-    };
-
-    // Drag a Task Form
-    dragFromSourceToDest(nodeTypes.task, taskFormPosition);
-
-    // Connect the Start Event with Task Form
-    connectNodesWithFlow('generic-flow-button', startEventPosition, taskFormPosition);
-
-    // Drag an End Event
-    dragFromSourceToDest(nodeTypes.endEvent, endEventPosition);
-
-    // Connect the Task Form with End Event
-    connectNodesWithFlow('generic-flow-button', taskFormPosition, endEventPosition);
-
-    waitToRenderAllShapes();
-    
-    // Validation 1: Click in the task the task must be selected
-    getElementAtPosition(taskFormPosition).click();
-
-    cy.get('[data-cy="selection-box"]').then($selectionBox => {
-      const { top: newTop, left: newLeft } = $selectionBox.position();
-      expect(newTop).to.be.greaterThan(100);
-      expect(newTop).to.be.lessThan(200);
-      expect(newLeft).to.be.greaterThan(480);
-      expect(newLeft).to.be.lessThan(530);
-    });
-  });
-});
diff --git a/tests/e2e/specs/canvasUsability/canvasSelection/SelectingAnElementIntoTheSelectedBox.spec.js b/tests/e2e/specs/canvasUsability/canvasSelection/SelectingAnElementIntoTheSelectedBox.spec.js
deleted file mode 100644
index 46d2547a..00000000
--- a/tests/e2e/specs/canvasUsability/canvasSelection/SelectingAnElementIntoTheSelectedBox.spec.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import {
-  dragFromSourceToDest,
-  connectNodesWithFlow,
-  waitToRenderAllShapes,
-  getElementAtPosition,
-} from '../../../support/utils';
-import { nodeTypes } from '../../../support/constants';
-
-describe('Canvas Selection', () => {
-  it('Verify that controls are selected when the user click on it', () => {
-    const startEventPosition = { x: 150, y: 150 };
-    const taskFormPosition = {
-      x: startEventPosition.x + 200,
-      y: startEventPosition.y,
-    };
-    const endEventPosition = {
-      x: taskFormPosition.x + 200,
-      y: taskFormPosition.y,
-    };
-
-    // Drag a Task Form
-    dragFromSourceToDest(nodeTypes.task, taskFormPosition);
-
-    // Connect the Start Event with Task Form
-    connectNodesWithFlow('generic-flow-button', startEventPosition, taskFormPosition);
-
-    // Drag an End Event
-    dragFromSourceToDest(nodeTypes.endEvent, endEventPosition);
-
-    // Connect the Task Form with End Event
-    connectNodesWithFlow('generic-flow-button', taskFormPosition, endEventPosition);
-
-    // Select all elements
-    cy.get('.paper-container').as('paperContainer').click();
-    cy.get('.paper-container').trigger('mousedown', 'topLeft');
-    cy.get('.paper-container').trigger('mousemove', 'bottomRight');
-    waitToRenderAllShapes();
-    cy.get('.paper-container').trigger('mouseup', 'bottomRight');
-
-    // Validation 1: Verify that controls are selected inside a selection box
-    cy.get('[data-cy="selection-box"]').should('exist');
-    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"] [data-cy="selected"]').should('exist');
-    cy.get('[data-type="processmaker.components.nodes.task.Shape"] [data-cy="selected"]').should('exist');
-    cy.get('[data-type="processmaker.components.nodes.endEvent.Shape"] [data-cy="selected"]').should('exist');
-    // Check the selection is large enough to contain all elements
-    cy.get('[data-cy="selection-box"]').then($selectionBox => {
-      const selectionBoxWidth = $selectionBox.width();
-      expect(selectionBoxWidth).to.be.greaterThan(400);
-    });
-
-    //Validation 2: Click in the task the task must be selected
-    getElementAtPosition(taskFormPosition).click();
-    cy.get('[data-cy="selection-box"]').then($selectionBox => {
-      const { top: newTop, left: newLeft } = $selectionBox.position();
-      expect(newTop).to.be.greaterThan(100);
-      expect(newTop).to.be.lessThan(200);
-      expect(newLeft).to.be.greaterThan(480);
-      expect(newLeft).to.be.lessThan(530);
-    });
-  });
-});
diff --git a/tests/e2e/specs/canvasUsability/canvasSelection/SelectionOfPoolsWithShiftClick.spec.js b/tests/e2e/specs/canvasUsability/canvasSelection/SelectionOfPoolsWithShiftClick.spec.js
index 24bfc6a9..dc481a9c 100644
--- a/tests/e2e/specs/canvasUsability/canvasSelection/SelectionOfPoolsWithShiftClick.spec.js
+++ b/tests/e2e/specs/canvasUsability/canvasSelection/SelectionOfPoolsWithShiftClick.spec.js
@@ -38,14 +38,12 @@ describe('Selection of pool with shift click', () => {
     cy.get('[data-cy="selection-box"]').should('have.attr', 'data-length', '2');
 
     // get current position of pool 1
-    // eslint-disable-next-line no-unused-vars
     let pool1;
     getElementAtPosition(pool1Position, nodeTypes.pool, 12, 100).then(($pool1) => {
       pool1 = $pool1[0].getBoundingClientRect();
     });
 
     // get current position of pool 1
-    // eslint-disable-next-line no-unused-vars
     let pool2;
     getElementAtPosition(pool2Position, nodeTypes.pool, 12, 100).then(($pool2) => {
       pool2 = $pool2[0].getBoundingClientRect();
@@ -55,10 +53,9 @@ describe('Selection of pool with shift click', () => {
     const fromPosition = { x: 200, y: 200 };
     const translateAmount = { x: 0, y: 100 };
     // click and drag fromPosition to fromPosition + translateAmount
-    cy.get('.paper-container .joint-paper').trigger('mousedown', { which: 1, pageX: fromPosition.x, pageY: fromPosition.y, force: true});
-    cy.get('.paper-container').trigger('mousemove', { which: 1, pageX: fromPosition.x + translateAmount.x, pageY: fromPosition.y + translateAmount.y, force: true});
-    waitToRenderAllShapes();
-    cy.get('.paper-container .joint-paper').trigger('mouseup',{force: true});
+    cy.get('[data-cy="selection-box"]').trigger('mousedown', { which: 1, pageX: fromPosition.x, pageY: fromPosition.y });
+    cy.get('[data-cy="selection-box"]').trigger('mousemove', { which: 1, pageX: fromPosition.x + translateAmount.x, pageY: fromPosition.y + translateAmount.y });
+    cy.get('[data-cy="selection-box"]').trigger('mouseup', { force: true });
 
     waitToRenderAllShapes();
 
@@ -74,12 +71,12 @@ describe('Selection of pool with shift click', () => {
 
     getElementAtPosition(newPool1Position, nodeTypes.pool, 12, 100).then(($pool1) => {
       const { y } = $pool1[0].getBoundingClientRect();
-      expect(pool1.y).to.be.lessThan(y);
+      expect(y).to.be.lessThan(pool1.y);
     });
 
     getElementAtPosition(newPool2Position, nodeTypes.pool, 12, 100).then(($pool2) => {
       const { y } = $pool2[0].getBoundingClientRect();
-      expect(pool1.y).to.be.lessThan(y);
+      expect(y).to.be.lessThan(pool2.y);
     });
   });
 });
diff --git a/tests/e2e/specs/canvasUsability/canvasSelection/VerifyTheIndividualSelectionOfEachElement.js b/tests/e2e/specs/canvasUsability/canvasSelection/VerifyTheIndividualSelectionOfEachElement.js
new file mode 100644
index 00000000..fd44a7cb
--- /dev/null
+++ b/tests/e2e/specs/canvasUsability/canvasSelection/VerifyTheIndividualSelectionOfEachElement.js
@@ -0,0 +1,173 @@
+import {
+  dragFromSourceToDest,
+  waitToRenderAllShapes, getGraphElements,
+} from '../../../support/utils';
+import { nodeTypes } from '../../../support/constants';
+
+describe('Canvas Selection', () => {
+  const elementPosition = { x: 350, y: 150 };
+
+  it('TCP4-2662: Verify the individual selection of Start Event', () => {
+    const initialNumberOfElements = 1;
+
+    //Step 1: Drag Start Event
+    waitToRenderAllShapes();
+    getGraphElements().should('have.length', initialNumberOfElements);
+
+    //Step 2: Set a name in Start Event
+    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"]').first().click({force: true});
+    cy.get('[name="name"]').clear().type('Start event Test 1');
+
+    //Validation 1: Verify that the element is selected ,including its name. and a rectangle highlights the element
+    cy.get('[data-cy="selection-box"]').should('exist');
+    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"] [data-cy="selected"]').should('exist');
+  });
+
+  it('TCP4-2662: Verify the individual selection of Intermediate Event', () => {
+
+    //Step 1: Add Start Event
+    waitToRenderAllShapes();
+    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"]').first().click({force: true});
+
+    //Step 2: Drag Intermediate Event
+    dragFromSourceToDest(nodeTypes.intermediateCatchEvent, elementPosition);
+
+    //Step 3: Set a name in Intermediate Event
+    cy.get('[name="name"]').clear().type('Timer Event Test 1');
+
+    //Step 4: Select the element
+    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"]').first().click();
+    cy.get('[data-type="processmaker.components.nodes.intermediateEvent.Shape"]').first().click();
+
+    //Validation 2: Verify that the element is selected ,including its name. and a rectangle highlights the element
+    cy.get('[data-cy="selection-box"]').should('exist');
+    cy.get('[data-type="processmaker.components.nodes.intermediateEvent.Shape"] [data-cy="selected"]').should('exist');
+  });
+
+  it('TCP4-2662: Verify the individual selection of End Event', () => {
+
+    //Step 1: Add Start Event
+    waitToRenderAllShapes();
+    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"]').first().click({force: true});
+
+    //Step 2: Drag End Event
+    dragFromSourceToDest(nodeTypes.endEvent, elementPosition);
+
+    //Step 3: Set a name in End Event
+    cy.get('[name="name"]').clear().type('End Event Test 1');
+
+    //Step 4: Select the element
+    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"]').first().click();
+    cy.get('[data-type="processmaker.components.nodes.endEvent.Shape"]').first().click();
+
+    //Validation 3: Verify that the element is selected ,including its name. and a rectangle highlights the element
+    cy.get('[data-cy="selection-box"]').should('exist');
+    cy.get('[data-type="processmaker.components.nodes.endEvent.Shape"] [data-cy="selected"]').should('exist');
+  });
+
+  it('TCP4-2662: Verify the individual selection of Task Form', () => {
+
+    //Step 1: Add Start Event
+    waitToRenderAllShapes();
+    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"]').first().click({force: true});
+
+    //Step 2: Drag Task Form
+    dragFromSourceToDest(nodeTypes.task, elementPosition);
+
+    //Step 3: Set a name in Task Form
+    cy.get('[name="name"]').clear().type('Task Test 1');
+
+    //Step 4: Select the element
+    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"]').first().click();
+    cy.get('[data-type="processmaker.components.nodes.task.Shape"]').first().click();
+
+    //Validation 4: Verify that the element is selected ,including its name. and a rectangle highlights the element
+    cy.get('[data-cy="selection-box"]').should('exist');
+    cy.get('[data-type="processmaker.components.nodes.task.Shape"] [data-cy="selected"]').should('exist');
+  });
+
+  it('TCP4-2662: Verify the individual selection of Gateway', () => {
+
+    //Step 1: Add Start Event
+    waitToRenderAllShapes();
+    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"]').first().click({force: true});
+
+    //Step 2: Drag Gateway component
+    dragFromSourceToDest(nodeTypes.exclusiveGateway, elementPosition);
+
+    //Step 3: Set a name in Gateway Component
+    cy.get('[name="name"]').clear().type('Exclusive Gateway Test 1');
+
+    //Step 4: Select the element
+    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"]').first().click();
+    cy.get('[data-type="processmaker.components.nodes.gateway.Shape"]').first().click();
+
+    //Validation 5: Verify that the element is selected ,including its name. and a rectangle highlights the element
+    cy.get('[data-cy="selection-box"]').should('exist');
+    cy.get('[data-type="processmaker.components.nodes.gateway.Shape"] [data-cy="selected"]').should('exist');
+  });
+
+  it('TCP4-2662: Verify the individual selection of Text Annotation', () => {
+
+    //Step 1: Add Start Event
+    waitToRenderAllShapes();
+    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"]').first().click({force: true});
+
+    //Step 2: Drag Text Annotation
+    dragFromSourceToDest(nodeTypes.textAnnotation, elementPosition);
+
+    //Step 3: Set a name in Text Annotation
+    cy.get('[name="text"]').clear().type('Text Annotation Test 1');
+
+    //Step 4: Select the element
+    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"]').first().click();
+    cy.get('[data-type="textAnnotation"]').first().click();
+
+    //Validation 6: Verify that the element is selected ,including its name. and a rectangle highlights the element
+    cy.get('[data-cy="selection-box"]').should('exist');
+    cy.get('[data-type="textAnnotation"] [data-cy="selected"]').should('exist');
+  });
+
+  it('TCP4-2662: Verify the individual selection of Data Object', () => {
+
+    //Step 1: Add Start Event
+    waitToRenderAllShapes();
+    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"]').first().click({force: true});
+
+    //Step 2: Drag Data Object
+    dragFromSourceToDest(nodeTypes.dataObject, elementPosition);
+
+    //Step 3: Set a name in Data Object
+    cy.get('[name="name"]').clear().type('Data Object Test 1');
+
+    //Step 4: Select the element
+    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"]').first().click();
+    cy.get('[data-type="standard.Path"]').first().click();
+
+    //Validation 7: Verify that the element is selected ,including its name. and a rectangle highlights the element
+    cy.get('[data-cy="selection-box"]').should('exist');
+    cy.get('[data-type="standard.Path"] [data-cy="selected"]').should('exist');
+  });
+
+  it('TCP4-2662: Verify the individual selection of Data Store', () => {
+
+    //Step 1: Add Start Event
+    waitToRenderAllShapes();
+    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"]').first().click({force: true});
+
+    //Step 2: Drag Data Store
+    dragFromSourceToDest(nodeTypes.dataStore, elementPosition);
+
+    //Step 3: Set a name in Data Store
+    cy.get('[name="name"]').clear().type('Data Store Test 1');
+
+    //Step 4: Select the element
+    cy.get('[data-type="processmaker.components.nodes.startEvent.Shape"]').first().click();
+    cy.get('[data-type="standard.Cylinder"]').first().click();
+
+    //Validation 8: Verify that the element is selected ,including its name. and a rectangle highlights the element
+    cy.get('[data-cy="selection-box"]').should('exist');
+    cy.get('[data-type="standard.Cylinder"] [data-cy="selected"]').should('exist');
+  });
+
+});
diff --git a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/Hotkeys.spec.js b/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/Hotkeys.spec.js
deleted file mode 100644
index 10688202..00000000
--- a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/Hotkeys.spec.js
+++ /dev/null
@@ -1,43 +0,0 @@
-it('Zoom percentage increases when Ctrl + "+" is pressed', () => {
-  cy.get('[aria-label="Toolbar"]').click();
-  cy.get('.scale-value').should('have.text', '100%');
-  cy.get('body').type('{ctrl}+');
-  cy.get('.scale-value').should('have.text', '110%');
-  cy.get('body').type('{ctrl}+');
-  cy.get('.scale-value').should('have.text', '120%');
-  cy.get('body').type('{ctrl}+');
-  cy.get('.scale-value').should('have.text', '130%');
-});
-
-it('Zoom percentage increases when Ctrl + "NumpadAdd" is pressed', () => {
-  cy.get('[aria-label="Toolbar"]').click();
-  cy.get('.scale-value').should('have.text', '100%');
-  cy.get('body').trigger('keydown', { key:'NumpadAdd', keyCode: 107, which: 107, ctrlKey: true });
-  cy.get('.scale-value').should('have.text', '110%');
-  cy.get('body').trigger('keydown', { key:'NumpadAdd', keyCode: 107, which: 107, ctrlKey: true });
-  cy.get('.scale-value').should('have.text', '120%');
-  cy.get('body').trigger('keydown', { key:'NumpadAdd', keyCode: 107, which: 107, ctrlKey: true });
-  cy.get('.scale-value').should('have.text', '130%');
-});
-
-it('Zoom percentage decreases when Ctrl + "-" is pressed', () => {
-  cy.get('[aria-label="Toolbar"]').click();
-  cy.get('.scale-value').should('have.text', '100%');
-  cy.get('body').type('{ctrl}-');
-  cy.get('.scale-value').should('have.text', '90%');
-  cy.get('body').type('{ctrl}-');
-  cy.get('.scale-value').should('have.text', '80%');
-  cy.get('body').type('{ctrl}-');
-  cy.get('.scale-value').should('have.text', '70%');
-});
-
-it('Zoom percentage increases when Ctrl + "NumpadSubstract" is pressed', () => {
-  cy.get('[aria-label="Toolbar"]').click();
-  cy.get('.scale-value').should('have.text', '100%');
-  cy.get('body').trigger('keydown', { key:'NumpadSubstract', keyCode: 109, which: 109, ctrlKey: true });
-  cy.get('.scale-value').should('have.text', '90%');
-  cy.get('body').trigger('keydown', { key:'NumpadSubstract', keyCode: 109, which: 109, ctrlKey: true });
-  cy.get('.scale-value').should('have.text', '80%');
-  cy.get('body').trigger('keydown', { key:'NumpadSubstract', keyCode: 109, which: 109, ctrlKey: true });
-  cy.get('.scale-value').should('have.text', '70%');
-});
\ No newline at end of file
diff --git a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyBottomRailIsNotAffectedByControl++.spec.js b/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyBottomRailIsNotAffectedByControl++.spec.js
deleted file mode 100644
index d9a1ab8d..00000000
--- a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyBottomRailIsNotAffectedByControl++.spec.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import {
-  dragFromSourceToDest,
-  connectNodesWithFlow,
-  waitToRenderAllShapes,
-  getGraphElements,
-} from '../../../support/utils';
-import { nodeTypes } from '../../../support/constants';
-
-describe('Zoom In/Out Hot keys', () => {
-  it('TCP4-2657: Verify that "BOTTOM RAIL" is not affected by Control ++', () => {
-    const initialNumberOfElements = 1;
-
-    //Step 1: Drag Start Event
-    waitToRenderAllShapes();
-    const startEventPosition = { x: 150, y: 150 };
-    getGraphElements().should('have.length', initialNumberOfElements);
-
-    //Step 2: Drag Task component
-    const taskPosition = { x: 300, y: 130 };
-    dragFromSourceToDest(nodeTypes.task, taskPosition);
-
-    //Step 3: Drag End Event
-    const endEventPosition = { x: 500, y: 150 };
-    dragFromSourceToDest(nodeTypes.endEvent, endEventPosition);
-
-    //Step 4: Connect the Start Event with Task
-    connectNodesWithFlow('generic-flow-button', startEventPosition, taskPosition);
-
-    //Step 4: Connect the Task with End Event
-    connectNodesWithFlow('generic-flow-button', taskPosition, endEventPosition);
-
-    //Step 5: Click on Form Task
-    cy.get('[data-type="processmaker.components.nodes.task.Shape"]').first().click();
-
-    //Step 6: Get width of "BOTTOM RAIL" menu
-    cy.get('div[class*="card-footer"]').should('be.visible')
-      .invoke('width').then((val) => {
-        const width = val;
-        //Step 7: Press CONTROL +++++
-        cy.get('body').type('{ctrl}+++++');
-        cy.get('.scale-value').should('have.text', '150%');
-       
-        //Validation 1: Verify that heigth "BOTTOM RAIL" does not change
-        cy.get('div[class*="card-footer"]').should('exist')
-          .invoke('width').then((val) => {
-            cy.log('width initial of BOTTOM RAIL', width);
-            cy.log('width after Ctrl +++++', val);
-            expect(val).to.be.equal(width);
-          });
-      });
-  });
-
-});
diff --git a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyBottomRailIsNotAffectedByControl--.spec.js b/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyBottomRailIsNotAffectedByControl--.spec.js
deleted file mode 100644
index 83860473..00000000
--- a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyBottomRailIsNotAffectedByControl--.spec.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import {
-  dragFromSourceToDest,
-  connectNodesWithFlow,
-  waitToRenderAllShapes,
-  getGraphElements,
-} from '../../../support/utils';
-import { nodeTypes } from '../../../support/constants';
-
-describe('Zoom In/Out Hot keys', () => {
-  it('TCP4-2656: Verify that "BOTTOM RAIL" is not affected by Control --', () => {
-    const initialNumberOfElements = 1;
-
-    //Step 1: Drag Start Event
-    waitToRenderAllShapes();
-    const startEventPosition = { x: 150, y: 150 };
-    getGraphElements().should('have.length', initialNumberOfElements);
-
-    //Step 2: Drag Task component
-    const taskPosition = { x: 300, y: 130 };
-    dragFromSourceToDest(nodeTypes.task, taskPosition);
-
-    //Step 3: Drag End Event
-    const endEventPosition = { x: 500, y: 150 };
-    dragFromSourceToDest(nodeTypes.endEvent, endEventPosition);
-
-    //Step 4: Connect the Start Event with Task
-    connectNodesWithFlow('generic-flow-button', startEventPosition, taskPosition);
-
-    //Step 4: Connect the Task with End Event
-    connectNodesWithFlow('generic-flow-button', taskPosition, endEventPosition);
-
-    //Step 5: Click on Form Task
-    cy.get('[data-type="processmaker.components.nodes.task.Shape"]').first().click();
-
-    //Step 6: Get width of "BOTTOM RAIL" menu
-    cy.get('div[class*="card-footer"]').should('be.visible')
-      .invoke('width').then((val) => {
-        const width = val;
-        //Step 7: Press CONTROL ---
-        cy.get('body').type('{ctrl}-----');
-        cy.get('.scale-value').should('have.text', '50%');
-       
-        //Validation 1: Verify that heigth "BOTTOM RAIL" does not change
-        cy.get('div[class*="card-footer"]').should('exist')
-          .invoke('width').then((val) => {
-            cy.log('width initial of BOTTOM RAIL', width);
-            cy.log('width after Ctrl -----', val);
-            expect(val).to.be.equal(width);
-          });
-      });
-  });
-
-});
diff --git a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyControlsRailIsNotAffectedByControl++.spec.js b/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyControlsRailIsNotAffectedByControl++.spec.js
deleted file mode 100644
index ce0e036b..00000000
--- a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyControlsRailIsNotAffectedByControl++.spec.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import {
-  dragFromSourceToDest,
-  connectNodesWithFlow,
-  waitToRenderAllShapes,
-  getGraphElements,
-} from '../../../support/utils';
-import { nodeTypes } from '../../../support/constants';
-
-describe('Zoom In/Out Hot keys', () => {
-  it('TCP4-2650: Verify that "CONTROLS RAIL" is not affected by Control ++', () => {
-    const initialNumberOfElements = 1;
-
-    //Step 1: Drag Start Event
-    waitToRenderAllShapes();
-    const startEventPosition = { x: 150, y: 150 };
-    getGraphElements().should('have.length', initialNumberOfElements);
-
-    //Step 2: Drag Task component
-    const taskPosition = { x: 300, y: 130 };
-    dragFromSourceToDest(nodeTypes.task, taskPosition);
-
-    //Step 3: Drag End Event
-    const endEventPosition = { x: 500, y: 150 };
-    dragFromSourceToDest(nodeTypes.endEvent, endEventPosition);
-
-    //Step 4: Connect the Start Event with Task
-    connectNodesWithFlow('generic-flow-button', startEventPosition, taskPosition);
-
-    //Step 4: Connect the Task with End Event
-    connectNodesWithFlow('generic-flow-button', taskPosition, endEventPosition);
-
-    //Step 5: Click on Form Task
-    cy.get('[data-type="processmaker.components.nodes.task.Shape"]').first().click();
-
-    //Step 6: Get heigth of "CONTROLS RAIL" menu
-    cy.get('[data-test="controls-column"]> div').should('be.visible')
-      .invoke('height').then((val) => {
-        const heigth = val;
-        //Step 7: Press CONTROL + plus
-        cy.get('body').type('{ctrl}+');
-        cy.get('.scale-value').should('have.text', '110%');
-       
-        //Validation 1: Verify that heigth "CONTROL RAIL" does not change
-        cy.get('[data-test="controls-column"]> div').should('exist')
-          .invoke('height').then((val) => {
-            cy.log('heigth initial of CONTROLS RAIL', heigth);
-            cy.log('heigth after Ctrl +', val);
-            expect(val).to.be.equal(heigth);
-          });
-      });
-  });
-
-});
diff --git a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyControlsRailIsNotAffectedByControl--.spec.js b/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyControlsRailIsNotAffectedByControl--.spec.js
deleted file mode 100644
index 8d21b544..00000000
--- a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyControlsRailIsNotAffectedByControl--.spec.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import {
-  dragFromSourceToDest,
-  connectNodesWithFlow,
-  waitToRenderAllShapes,
-  getGraphElements,
-} from '../../../support/utils';
-import { nodeTypes } from '../../../support/constants';
-
-describe('Zoom In/Out Hot keys', () => {
-  it('TCP4-2651: Verify that "CONTROLS RAIL" is not affected by Control --', () => {
-    const initialNumberOfElements = 1;
-
-    //Step 1: Drag Start Event
-    waitToRenderAllShapes();
-    const startEventPosition = { x: 150, y: 150 };
-    getGraphElements().should('have.length', initialNumberOfElements);
-
-    //Step 2: Drag Task component
-    const taskPosition = { x: 300, y: 130 };
-    dragFromSourceToDest(nodeTypes.task, taskPosition);
-
-    //Step 3: Drag End Event
-    const endEventPosition = { x: 500, y: 150 };
-    dragFromSourceToDest(nodeTypes.endEvent, endEventPosition);
-
-    //Step 4: Connect the Start Event with Task
-    connectNodesWithFlow('generic-flow-button', startEventPosition, taskPosition);
-
-    //Step 4: Connect the Task with End Event
-    connectNodesWithFlow('generic-flow-button', taskPosition, endEventPosition);
-
-    //Step 5: Click on Form Task
-    cy.get('[data-type="processmaker.components.nodes.task.Shape"]').first().click();
-
-    //Step 6: Get heigth of "CONTROLS RAIL" menu
-    cy.get('[data-test="controls-column"]> div').should('be.visible')
-      .invoke('height').then((val) => {
-        const heigth = val;
-        //Step 7: Press CONTROL -
-        cy.get('body').type('{ctrl}-');
-        cy.get('.scale-value').should('have.text', '90%');
-       
-        //Validation 1: Verify that heigth "CONTROL RAIL" does not change
-        cy.get('[data-test="controls-column"]> div').should('exist')
-          .invoke('height').then((val) => {
-            cy.log('heigth initial of CONTROLS RAIL', heigth);
-            cy.log('heigth after Ctrl -', val);
-            expect(val).to.be.equal(heigth);
-          });
-      });
-  });
-
-});
diff --git a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyInspectorRailIsNotAffectedByControl++.spec.js b/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyInspectorRailIsNotAffectedByControl++.spec.js
deleted file mode 100644
index e44de1aa..00000000
--- a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyInspectorRailIsNotAffectedByControl++.spec.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import {
-  dragFromSourceToDest,
-  connectNodesWithFlow,
-  waitToRenderAllShapes,
-  getGraphElements,
-} from '../../../support/utils';
-import { nodeTypes } from '../../../support/constants';
-
-describe('Zoom In/Out Hot keys', () => {
-  it('TCP4-2654: Verify that "INSPECTOR RAIL" is not affected by Control ++', () => {
-    const initialNumberOfElements = 1;
-
-    //Step 1: Drag Start Event
-    waitToRenderAllShapes();
-    const startEventPosition = { x: 150, y: 150 };
-    getGraphElements().should('have.length', initialNumberOfElements);
-
-    //Step 2: Drag Task component
-    const taskPosition = { x: 300, y: 130 };
-    dragFromSourceToDest(nodeTypes.task, taskPosition);
-
-    //Step 3: Drag End Event
-    const endEventPosition = { x: 500, y: 150 };
-    dragFromSourceToDest(nodeTypes.endEvent, endEventPosition);
-
-    //Step 4: Connect the Start Event with Task
-    connectNodesWithFlow('generic-flow-button', startEventPosition, taskPosition);
-
-    //Step 4: Connect the Task with End Event
-    connectNodesWithFlow('generic-flow-button', taskPosition, endEventPosition);
-
-    //Step 5: Click on Form Task
-    cy.get('[data-type="processmaker.components.nodes.task.Shape"]').first().click();
-
-    //Step 6: Get heigth of "INSPECTOR RAIL" menu
-    cy.get('[data-test="inspector-column"]').should('be.visible')
-      .invoke('height').then((val) => {
-        const heigth = val;
-        //Step 7: Press CONTROL + plus
-        cy.get('body').type('{ctrl}++++');
-        cy.get('.scale-value').should('have.text', '140%');
-       
-        //Validation 1: Verify that heigth "INSPECTOR RAIL" does not change
-        cy.get('[data-test="inspector-column"]').should('exist')
-          .invoke('height').then((val) => {
-            cy.log('heigth initial of INSPECTOR RAIL', heigth);
-            cy.log('heigth after Ctrl +', val);
-            expect(val).to.be.equal(heigth);
-          });
-      });
-  });
-
-});
diff --git a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyInspectorRailIsNotAffectedByControl--.spec.js b/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyInspectorRailIsNotAffectedByControl--.spec.js
deleted file mode 100644
index b80cd862..00000000
--- a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyInspectorRailIsNotAffectedByControl--.spec.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import {
-  dragFromSourceToDest,
-  connectNodesWithFlow,
-  waitToRenderAllShapes,
-  getGraphElements,
-} from '../../../support/utils';
-import { nodeTypes } from '../../../support/constants';
-
-describe('Zoom In/Out Hot keys', () => {
-  it('TCP4-2655: Verify that "INSPECTOR RAIL" is not affected by Control --', () => {
-    const initialNumberOfElements = 1;
-
-    //Step 1: Drag Start Event
-    waitToRenderAllShapes();
-    const startEventPosition = { x: 150, y: 150 };
-    getGraphElements().should('have.length', initialNumberOfElements);
-
-    //Step 2: Drag Task component
-    const taskPosition = { x: 300, y: 130 };
-    dragFromSourceToDest(nodeTypes.task, taskPosition);
-
-    //Step 3: Drag End Event
-    const endEventPosition = { x: 500, y: 150 };
-    dragFromSourceToDest(nodeTypes.endEvent, endEventPosition);
-
-    //Step 4: Connect the Start Event with Task
-    connectNodesWithFlow('generic-flow-button', startEventPosition, taskPosition);
-
-    //Step 4: Connect the Task with End Event
-    connectNodesWithFlow('generic-flow-button', taskPosition, endEventPosition);
-
-    //Step 5: Click on Form Task
-    cy.get('[data-type="processmaker.components.nodes.task.Shape"]').first().click();
-
-    //Step 6: Get heigth of "INSPECTOR RAIL" menu
-    cy.get('[data-test="inspector-column"]').should('be.visible')
-      .invoke('height').then((val) => {
-        const heigth = val;
-        //Step 7: Press CONTROL ---
-        cy.get('body').type('{ctrl}----');
-        cy.get('.scale-value').should('have.text', '60%');
-       
-        //Validation 1: Verify that heigth "INSPECTOR RAIL" does not change
-        cy.get('[data-test="inspector-column"]').should('exist')
-          .invoke('height').then((val) => {
-            cy.log('heigth initial of INSPECTOR RAIL', heigth);
-            cy.log('heigth after Ctrl ----', val);
-            expect(val).to.be.equal(heigth);
-          });
-      });
-  });
-
-});
diff --git a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyTopRailIsNotAffectedByControl++.spec.js b/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyTopRailIsNotAffectedByControl++.spec.js
deleted file mode 100644
index 9f3a35e7..00000000
--- a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyTopRailIsNotAffectedByControl++.spec.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import {
-  dragFromSourceToDest,
-  connectNodesWithFlow,
-  waitToRenderAllShapes,
-  getGraphElements,
-} from '../../../support/utils';
-import { nodeTypes } from '../../../support/constants';
-
-describe('Zoom In/Out Hot keys', () => {
-  it('TCP4-2652: Verify that "TOP RAIL" is not affected by Control ++', () => {
-    const initialNumberOfElements = 1;
-
-    //Step 1: Drag Start Event
-    waitToRenderAllShapes();
-    const startEventPosition = { x: 150, y: 150 };
-    getGraphElements().should('have.length', initialNumberOfElements);
-
-    //Step 2: Drag Task component
-    const taskPosition = { x: 300, y: 130 };
-    dragFromSourceToDest(nodeTypes.task, taskPosition);
-
-    //Step 3: Drag End Event
-    const endEventPosition = { x: 500, y: 150 };
-    dragFromSourceToDest(nodeTypes.endEvent, endEventPosition);
-
-    //Step 4: Connect the Start Event with Task
-    connectNodesWithFlow('generic-flow-button', startEventPosition, taskPosition);
-
-    //Step 4: Connect the Task with End Event
-    connectNodesWithFlow('generic-flow-button', taskPosition, endEventPosition);
-
-    //Step 5: Click on Form Task
-    cy.get('[data-type="processmaker.components.nodes.task.Shape"]').first().click();
-
-    //Step 6: Get width of "TOP RAIL" menu
-    cy.get('[role="toolbar"][aria-label="Toolbar"]').should('be.visible')
-      .invoke('width').then((val) => {
-        const width = val;
-        //Step 7: Press CONTROL ++
-        cy.get('body').type('{ctrl}++');
-        cy.get('.scale-value').should('have.text', '120%');
-       
-        //Validation 1: Verify that heigth "TOP RAIL" does not change
-        cy.get('[role="toolbar"][aria-label="Toolbar"]').should('exist')
-          .invoke('width').then((val) => {
-            cy.log('width initial of TOP RAIL', width);
-            cy.log('width after Ctrl ++', val);
-            expect(val).to.be.equal(width);
-          });
-      });
-  });
-
-});
diff --git a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyTopRailIsNotAffectedByControl--.spec.js b/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyTopRailIsNotAffectedByControl--.spec.js
deleted file mode 100644
index 7304f549..00000000
--- a/tests/e2e/specs/canvasUsability/zoomInOutHotKeys/VerifyTopRailIsNotAffectedByControl--.spec.js
+++ /dev/null
@@ -1,53 +0,0 @@
-import {
-  dragFromSourceToDest,
-  connectNodesWithFlow,
-  waitToRenderAllShapes,
-  getGraphElements,
-} from '../../../support/utils';
-import { nodeTypes } from '../../../support/constants';
-
-describe('Zoom In/Out Hot keys', () => {
-  it('TCP4-2653: Verify that "TOP RAIL" is not affected by Control --', () => {
-    const initialNumberOfElements = 1;
-
-    //Step 1: Drag Start Event
-    waitToRenderAllShapes();
-    const startEventPosition = { x: 150, y: 150 };
-    getGraphElements().should('have.length', initialNumberOfElements);
-
-    //Step 2: Drag Task component
-    const taskPosition = { x: 300, y: 130 };
-    dragFromSourceToDest(nodeTypes.task, taskPosition);
-
-    //Step 3: Drag End Event
-    const endEventPosition = { x: 500, y: 150 };
-    dragFromSourceToDest(nodeTypes.endEvent, endEventPosition);
-
-    //Step 4: Connect the Start Event with Task
-    connectNodesWithFlow('generic-flow-button', startEventPosition, taskPosition);
-
-    //Step 4: Connect the Task with End Event
-    connectNodesWithFlow('generic-flow-button', taskPosition, endEventPosition);
-
-    //Step 5: Click on Form Task
-    cy.get('[data-type="processmaker.components.nodes.task.Shape"]').first().click();
-
-    //Step 6: Get width of "TOP RAIL" menu
-    cy.get('[role="toolbar"][aria-label="Toolbar"]').should('be.visible')
-      .invoke('width').then((val) => {
-        const width = val;
-        //Step 7: Press CONTROL --
-        cy.get('body').type('{ctrl}--');
-        cy.get('.scale-value').should('have.text', '80%');
-       
-        //Validation 1: Verify that heigth "TOP RAIL" does not change
-        cy.get('[role="toolbar"][aria-label="Toolbar"]').should('exist')
-          .invoke('width').then((val) => {
-            cy.log('width initial of TOP RAIL', width);
-            cy.log('width after Ctrl --', val);
-            expect(val).to.be.equal(width);
-          });
-      });
-  });
-
-});
diff --git a/tests/e2e/support/utils.js b/tests/e2e/support/utils.js
index ab1b4ead..b22c35e0 100644
--- a/tests/e2e/support/utils.js
+++ b/tests/e2e/support/utils.js
@@ -148,13 +148,11 @@ export function waitToRenderNodeUpdates() {
 }
 
 export function connectNodesWithFlow(flowType, startPosition, endPosition, clickPosition = 'center') {
-  const mouseEvent = { clientX: startPosition.x , clientY: startPosition.y };
   return getElementAtPosition(startPosition)
-    .trigger('mousedown', mouseEvent, { force: true })
-    .trigger('mouseup', mouseEvent,  { force: true })
+    .click({ force: true })
     .then($element => {
       return getCrownButtonForElement($element, flowType)
-        .click();
+        .click({ force: true });
     })
     .then(() => {
       getElementAtPosition(endPosition).then($endElement => {
diff --git a/tests/unit/moveWithArrowKeys.spec.js b/tests/unit/moveWithArrowKeys.spec.js
index af3b361f..f383d6ff 100644
--- a/tests/unit/moveWithArrowKeys.spec.js
+++ b/tests/unit/moveWithArrowKeys.spec.js
@@ -1,4 +1,4 @@
-import moveShapeByKeypress, { moveAmount } from '@/components/hotkeys/moveWithArrowKeys';
+import moveShapeByKeypress, { moveAmount } from '@/components/modeler/moveWithArrowKeys';
 
 const shapeFactory = (type = 'foo') => ({
   translate: jest.fn(),