Repository: ProcessMaker/modeler
Pull request #1545 (2023-05-11 21:38:34)

FOUR-8401 Added the new explorer rail (UI refresh)
## Issue & Reproduction Steps

Expected behavior: 
Explorer rail should show the new design

## Solution
- Added a new component
- Added a new store to manage the `nodeTypes` and set/unset the pinned objects (functionality to be done in another ticket)
- Added a unit test to cover the javascript logic
- Old component was removed

## How to Test
Test the steps above
* run `npm run serve` in modeler
* Serve

### Note
There's no way at the moment to hide the explorer rail until https://github.com/ProcessMaker/modeler/pull/1543 gets merged

## Related Tickets & Packages
- https://processmaker.atlassian.net/browse/FOUR-8401

## 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.

ci:deploy


Patch:
diff --git a/package-lock.json b/package-lock.json
index 93d794e6..c0c5cef3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,20 +1,20 @@
 {
   "name": "@processmaker/modeler",
-  "version": "1.30.1",
+  "version": "1.29.0",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "@processmaker/modeler",
-      "version": "1.30.1",
+      "version": "1.29.0",
       "dependencies": {
         "@babel/plugin-proposal-private-methods": "^7.12.1",
         "@fortawesome/fontawesome-free": "^5.11.2",
         "@fortawesome/fontawesome-svg-core": "^1.2.25",
         "@fortawesome/free-solid-svg-icons": "^5.11.2",
         "@fortawesome/vue-fontawesome": "^0.1.8",
-        "@processmaker/screen-builder": "2.70.0",
-        "@processmaker/vue-form-elements": "0.45.0",
+        "@processmaker/screen-builder": "2.29.0",
+        "@processmaker/vue-form-elements": "0.29.1",
         "@processmaker/vue-multiselect": "^2.2.0",
         "acorn": "^6.4.2",
         "bootstrap": "^4.3.1",
@@ -2827,13 +2827,12 @@
       }
     },
     "node_modules/@processmaker/screen-builder": {
-      "version": "2.70.0",
-      "resolved": "https://registry.npmjs.org/@processmaker/screen-builder/-/screen-builder-2.70.0.tgz",
-      "integrity": "sha512-9GzTuRO/EIE6sYSZGKNR72u8MjLmNc9oBhTNuQe2le56Ch1XAXzNewly+B/PR7MVYtuIJY2pRXnNOXOdU1XMIg==",
+      "version": "2.29.0",
+      "resolved": "https://registry.npmjs.org/@processmaker/screen-builder/-/screen-builder-2.29.0.tgz",
+      "integrity": "sha512-Vag4ppV/CoJKFwd7iN+dRoNZiqdVvruXGbd3jrdrgTV9tHktfsjbjDyl4vt/cI7rXPObhrEQfwtXIL6NYMRjkA==",
       "dependencies": {
-        "axios-extensions": "^2.0.3",
-        "lodash": "^4.17.21",
-        "lru-cache": "^7.14.0",
+        "is-proxy": "^1.0.6",
+        "lodash": "^4.17.20",
         "moment": "^2.29.1",
         "moment-timezone": "^0.5.27",
         "scrollparent": "^2.0.1",
@@ -2848,7 +2847,7 @@
       },
       "peerDependencies": {
         "@panter/vue-i18next": "^0.15.0",
-        "@processmaker/vue-form-elements": "0.45.0",
+        "@processmaker/vue-form-elements": "0.29.1",
         "i18next": "^15.0.8",
         "vue": "^2.6.12",
         "vuex": "^3.1.1"
@@ -3121,11 +3120,15 @@
       }
     },
     "node_modules/@processmaker/screen-builder/node_modules/lru-cache": {
-      "version": "7.18.3",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
-      "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+      "peer": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
       "engines": {
-        "node": ">=12"
+        "node": ">=10"
       }
     },
     "node_modules/@processmaker/screen-builder/node_modules/postcss-modules-extract-imports": {
@@ -3233,18 +3236,6 @@
         "node": ">=10"
       }
     },
-    "node_modules/@processmaker/screen-builder/node_modules/semver/node_modules/lru-cache": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-      "peer": true,
-      "dependencies": {
-        "yallist": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
     "node_modules/@processmaker/screen-builder/node_modules/serialize-javascript": {
       "version": "6.0.1",
       "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
@@ -3430,13 +3421,14 @@
       "peer": true
     },
     "node_modules/@processmaker/vue-form-elements": {
-      "version": "0.45.0",
-      "resolved": "https://registry.npmjs.org/@processmaker/vue-form-elements/-/vue-form-elements-0.45.0.tgz",
-      "integrity": "sha512-VXrNOY9jlKgh1KWoyn5QB8N8OH0wVD4ccQVqU4ZPhigIWr6158KR11RrSs1yBFFpXu6MMBuL1hyT2t1n6GbRqA==",
+      "version": "0.29.1",
+      "resolved": "https://registry.npmjs.org/@processmaker/vue-form-elements/-/vue-form-elements-0.29.1.tgz",
+      "integrity": "sha512-qla4tWiYYZ6NBviJQfD+TP5zOxSWcXEuTl/8rdFuhVXUT/YDfcmCbgPlqcvIoHyrmFb6XfuzBMuYcl3YqVYgag==",
       "dependencies": {
         "@tinymce/tinymce-vue": "2.0.0",
         "bootstrap": "^4.5.3",
         "jquery": "^3.5.1",
+        "luxon": "^1.11.3",
         "moment": "^2.29.1",
         "moment-timezone": "^0.5.26",
         "popper.js": "^1.14.4",
@@ -3445,8 +3437,7 @@
         "v-calendar": "^0.9.7",
         "validatorjs": "^3.22.1",
         "vue": "^2.6.12",
-        "vue-date-pick": "^1.5.1",
-        "vue-uniq-ids": "^1.0.0",
+        "vue-bootstrap-datetimepicker": "^5.0.1",
         "weekstart": "^1.0.0"
       },
       "engines": {
@@ -3804,11 +3795,6 @@
       "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
       "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ=="
     },
-    "node_modules/@types/lru-cache": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-4.1.3.tgz",
-      "integrity": "sha512-QjCOmf5kYwekcsfEKhcEHMK8/SvgnneuSDXFERBuC/DPca2KJIO/gpChTsVb35BoWLBpEAJWz1GFVEArSdtKtw=="
-    },
     "node_modules/@types/mime": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
@@ -6481,35 +6467,11 @@
       "version": "0.21.4",
       "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
       "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
+      "dev": true,
       "dependencies": {
         "follow-redirects": "^1.14.0"
       }
     },
-    "node_modules/axios-extensions": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/axios-extensions/-/axios-extensions-2.0.3.tgz",
-      "integrity": "sha512-KMWSNMth4eVUe1hDER1pfwMgVxeIrt9rstONy1nGHIxYPOiZ7NiwO252RRjUwTANOtUPEWaVbIP/6v3fREY9Eg==",
-      "dependencies": {
-        "@types/lru-cache": "^4.1.0",
-        "axios": "*",
-        "babel-runtime": "^6.26.0",
-        "lru-cache": "^4.1.1"
-      }
-    },
-    "node_modules/axios-extensions/node_modules/lru-cache": {
-      "version": "4.1.5",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
-      "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
-      "dependencies": {
-        "pseudomap": "^1.0.2",
-        "yallist": "^2.1.2"
-      }
-    },
-    "node_modules/axios-extensions/node_modules/yallist": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
-      "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="
-    },
     "node_modules/axios-mock-adapter": {
       "version": "1.21.2",
       "resolved": "https://registry.npmjs.org/axios-mock-adapter/-/axios-mock-adapter-1.21.2.tgz",
@@ -6907,6 +6869,7 @@
       "version": "6.26.0",
       "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
       "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
+      "dev": true,
       "dependencies": {
         "core-js": "^2.4.0",
         "regenerator-runtime": "^0.11.0"
@@ -6917,12 +6880,14 @@
       "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
       "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
       "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
+      "dev": true,
       "hasInstallScript": true
     },
     "node_modules/babel-runtime/node_modules/regenerator-runtime": {
       "version": "0.11.1",
       "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
-      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
+      "dev": true
     },
     "node_modules/babel-template": {
       "version": "6.26.0",
@@ -12697,6 +12662,7 @@
       "version": "1.15.2",
       "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
       "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
+      "dev": true,
       "funding": [
         {
           "type": "individual",
@@ -15043,6 +15009,11 @@
       "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==",
       "dev": true
     },
+    "node_modules/is-proxy": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/is-proxy/-/is-proxy-1.0.6.tgz",
+      "integrity": "sha512-RzUROKx085vc7tpo9zCinKAmsD7ihAnXJ7HvKdcsc3m0XW/vpJDFSvZgutqMam0aBxpYBmDVYv48+T/+AMYl1g=="
+    },
     "node_modules/is-regex": {
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
@@ -18581,9 +18552,9 @@
       }
     },
     "node_modules/moment-timezone": {
-      "version": "0.5.43",
-      "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz",
-      "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==",
+      "version": "0.5.41",
+      "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.41.tgz",
+      "integrity": "sha512-e0jGNZDOHfBXJGz8vR/sIMXvBIGJJcqFjmlg9lmE+5KX1U7/RZNMswfD8nKnNCnQdKTIj50IaRKwl1fvMLyyRg==",
       "dependencies": {
         "moment": "^2.29.4"
       },
@@ -20014,6 +19985,34 @@
         "node": ">=0.12"
       }
     },
+    "node_modules/pc-bootstrap4-datetimepicker": {
+      "version": "4.17.51",
+      "resolved": "https://registry.npmjs.org/pc-bootstrap4-datetimepicker/-/pc-bootstrap4-datetimepicker-4.17.51.tgz",
+      "integrity": "sha512-UQDSKS5d1c43btk2vQ4siiv9YIkscZYQfTE513abeTqh5PIOJiyAeNdoCSTsDTZcpWJtWZHWk15yDXypYSFzcQ==",
+      "dependencies": {
+        "bootstrap": "^4.0.0-beta.2",
+        "jquery": "^1.8.3 || ^2.0 || ^3.0",
+        "moment": "^2.10",
+        "moment-timezone": "^0.4.0"
+      },
+      "peerDependencies": {
+        "bootstrap": "^4.0.0-beta.2",
+        "jquery": "^1.8.3 || ^2.0 || ^3.0",
+        "moment": "^2.10",
+        "moment-timezone": "^0.4.0 || ^0.5.0"
+      }
+    },
+    "node_modules/pc-bootstrap4-datetimepicker/node_modules/moment-timezone": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.4.1.tgz",
+      "integrity": "sha512-5cNPVUwaVJDCe9JM8m/qz17f9SkaI8rpnRUyDJi2K5HAd6EwhuQ3n5nLclZkNC/qJnomKgQH2TIu70Gy2dxFKA==",
+      "dependencies": {
+        "moment": ">= 2.6.0"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/pend": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
@@ -21729,11 +21728,6 @@
         "teleport": ">=0.2.0"
       }
     },
-    "node_modules/qinu": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/qinu/-/qinu-1.2.0.tgz",
-      "integrity": "sha512-tcTCpRzghKo6jfjkQ8tEWwD8qtyOR4cqoVo0/6waSfYT3NM/lTytRCcYNbISFrK1tu7ttowyhY8XpEjleZWybA=="
-    },
     "node_modules/qs": {
       "version": "6.10.4",
       "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz",
@@ -26498,6 +26492,21 @@
         "csstype": "^3.1.0"
       }
     },
+    "node_modules/vue-bootstrap-datetimepicker": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/vue-bootstrap-datetimepicker/-/vue-bootstrap-datetimepicker-5.0.1.tgz",
+      "integrity": "sha512-jao7sWXHgKzjbOio97u7kEfB/FJMWJ5rhsc4q8iNTOLCULfSJ5m3AZ2qZh62dNcMA4/uuTW6m6tONYIith/2XQ==",
+      "dependencies": {
+        "pc-bootstrap4-datetimepicker": "^4.17.50"
+      },
+      "engines": {
+        "node": ">= 6.9.0",
+        "npm": ">= 3.10.0"
+      },
+      "peerDependencies": {
+        "vue": "^2.0.0"
+      }
+    },
     "node_modules/vue-color": {
       "version": "2.8.1",
       "resolved": "https://registry.npmjs.org/vue-color/-/vue-color-2.8.1.tgz",
@@ -26510,18 +26519,6 @@
         "tinycolor2": "^1.1.2"
       }
     },
-    "node_modules/vue-date-pick": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/vue-date-pick/-/vue-date-pick-1.5.1.tgz",
-      "integrity": "sha512-7IZDRBgrBUWiF7xMgVAEETq49E//djP7mCbMofLtG91D0IZNbLocT0Z+eueVrJ496lf5WSUE1dF3/ZaOGZW++w==",
-      "dependencies": {
-        "vue": "^2.6.0"
-      },
-      "engines": {
-        "node": ">= 6.0.0",
-        "npm": ">= 3.0.0"
-      }
-    },
     "node_modules/vue-deepset": {
       "version": "0.6.3",
       "resolved": "https://registry.npmjs.org/vue-deepset/-/vue-deepset-0.6.3.tgz",
@@ -26875,14 +26872,6 @@
       "resolved": "https://registry.npmjs.org/vue-the-mask/-/vue-the-mask-0.11.1.tgz",
       "integrity": "sha512-UquSfnSWejD0zAfcD+3jJ1chUAkOAyoxya9Lxh9acCRtrlmGcAIvd0cQYraWqKenbuZJUdum+S174atv2AuEHQ=="
     },
-    "node_modules/vue-uniq-ids": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/vue-uniq-ids/-/vue-uniq-ids-1.1.2.tgz",
-      "integrity": "sha512-Jt4BSopBVJskX0iWiN9+lclWW5zXzrf5rkod80RVrp0fmpRC+KUMtQDAh2dyZP5QimWReioY4qqKuIqDMO/6UA==",
-      "dependencies": {
-        "qinu": "^1.1.2"
-      }
-    },
     "node_modules/vue-upload-component": {
       "version": "2.8.23",
       "resolved": "https://registry.npmjs.org/vue-upload-component/-/vue-upload-component-2.8.23.tgz",
@@ -30260,13 +30249,12 @@
       }
     },
     "@processmaker/screen-builder": {
-      "version": "2.70.0",
-      "resolved": "https://registry.npmjs.org/@processmaker/screen-builder/-/screen-builder-2.70.0.tgz",
-      "integrity": "sha512-9GzTuRO/EIE6sYSZGKNR72u8MjLmNc9oBhTNuQe2le56Ch1XAXzNewly+B/PR7MVYtuIJY2pRXnNOXOdU1XMIg==",
+      "version": "2.29.0",
+      "resolved": "https://registry.npmjs.org/@processmaker/screen-builder/-/screen-builder-2.29.0.tgz",
+      "integrity": "sha512-Vag4ppV/CoJKFwd7iN+dRoNZiqdVvruXGbd3jrdrgTV9tHktfsjbjDyl4vt/cI7rXPObhrEQfwtXIL6NYMRjkA==",
       "requires": {
-        "axios-extensions": "^2.0.3",
-        "lodash": "^4.17.21",
-        "lru-cache": "^7.14.0",
+        "is-proxy": "^1.0.6",
+        "lodash": "^4.17.20",
         "moment": "^2.29.1",
         "moment-timezone": "^0.5.27",
         "scrollparent": "^2.0.1",
@@ -30502,9 +30490,13 @@
           "peer": true
         },
         "lru-cache": {
-          "version": "7.18.3",
-          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
-          "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="
+          "version": "6.0.0",
+          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+          "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+          "peer": true,
+          "requires": {
+            "yallist": "^4.0.0"
+          }
         },
         "postcss-modules-extract-imports": {
           "version": "3.0.0",
@@ -30570,17 +30562,6 @@
           "peer": true,
           "requires": {
             "lru-cache": "^6.0.0"
-          },
-          "dependencies": {
-            "lru-cache": {
-              "version": "6.0.0",
-              "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-              "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-              "peer": true,
-              "requires": {
-                "yallist": "^4.0.0"
-              }
-            }
           }
         },
         "serialize-javascript": {
@@ -30701,13 +30682,14 @@
       }
     },
     "@processmaker/vue-form-elements": {
-      "version": "0.45.0",
-      "resolved": "https://registry.npmjs.org/@processmaker/vue-form-elements/-/vue-form-elements-0.45.0.tgz",
-      "integrity": "sha512-VXrNOY9jlKgh1KWoyn5QB8N8OH0wVD4ccQVqU4ZPhigIWr6158KR11RrSs1yBFFpXu6MMBuL1hyT2t1n6GbRqA==",
+      "version": "0.29.1",
+      "resolved": "https://registry.npmjs.org/@processmaker/vue-form-elements/-/vue-form-elements-0.29.1.tgz",
+      "integrity": "sha512-qla4tWiYYZ6NBviJQfD+TP5zOxSWcXEuTl/8rdFuhVXUT/YDfcmCbgPlqcvIoHyrmFb6XfuzBMuYcl3YqVYgag==",
       "requires": {
         "@tinymce/tinymce-vue": "2.0.0",
         "bootstrap": "^4.5.3",
         "jquery": "^3.5.1",
+        "luxon": "^1.11.3",
         "moment": "^2.29.1",
         "moment-timezone": "^0.5.26",
         "popper.js": "^1.14.4",
@@ -30716,8 +30698,7 @@
         "v-calendar": "^0.9.7",
         "validatorjs": "^3.22.1",
         "vue": "^2.6.12",
-        "vue-date-pick": "^1.5.1",
-        "vue-uniq-ids": "^1.0.0",
+        "vue-bootstrap-datetimepicker": "^5.0.1",
         "weekstart": "^1.0.0"
       }
     },
@@ -31025,11 +31006,6 @@
       "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
       "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ=="
     },
-    "@types/lru-cache": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-4.1.3.tgz",
-      "integrity": "sha512-QjCOmf5kYwekcsfEKhcEHMK8/SvgnneuSDXFERBuC/DPca2KJIO/gpChTsVb35BoWLBpEAJWz1GFVEArSdtKtw=="
-    },
     "@types/mime": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
@@ -33190,37 +33166,11 @@
       "version": "0.21.4",
       "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
       "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
+      "dev": true,
       "requires": {
         "follow-redirects": "^1.14.0"
       }
     },
-    "axios-extensions": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/axios-extensions/-/axios-extensions-2.0.3.tgz",
-      "integrity": "sha512-KMWSNMth4eVUe1hDER1pfwMgVxeIrt9rstONy1nGHIxYPOiZ7NiwO252RRjUwTANOtUPEWaVbIP/6v3fREY9Eg==",
-      "requires": {
-        "@types/lru-cache": "^4.1.0",
-        "axios": "*",
-        "babel-runtime": "^6.26.0",
-        "lru-cache": "^4.1.1"
-      },
-      "dependencies": {
-        "lru-cache": {
-          "version": "4.1.5",
-          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
-          "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
-          "requires": {
-            "pseudomap": "^1.0.2",
-            "yallist": "^2.1.2"
-          }
-        },
-        "yallist": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
-          "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="
-        }
-      }
-    },
     "axios-mock-adapter": {
       "version": "1.21.2",
       "resolved": "https://registry.npmjs.org/axios-mock-adapter/-/axios-mock-adapter-1.21.2.tgz",
@@ -33530,6 +33480,7 @@
       "version": "6.26.0",
       "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
       "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
+      "dev": true,
       "requires": {
         "core-js": "^2.4.0",
         "regenerator-runtime": "^0.11.0"
@@ -33538,12 +33489,14 @@
         "core-js": {
           "version": "2.6.12",
           "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
-          "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
+          "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
+          "dev": true
         },
         "regenerator-runtime": {
           "version": "0.11.1",
           "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
-          "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+          "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
+          "dev": true
         }
       }
     },
@@ -38199,7 +38152,8 @@
     "follow-redirects": {
       "version": "1.15.2",
       "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
-      "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
+      "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
+      "dev": true
     },
     "for-each": {
       "version": "0.3.3",
@@ -39968,6 +39922,11 @@
       "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==",
       "dev": true
     },
+    "is-proxy": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/is-proxy/-/is-proxy-1.0.6.tgz",
+      "integrity": "sha512-RzUROKx085vc7tpo9zCinKAmsD7ihAnXJ7HvKdcsc3m0XW/vpJDFSvZgutqMam0aBxpYBmDVYv48+T/+AMYl1g=="
+    },
     "is-regex": {
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
@@ -42775,9 +42734,9 @@
       "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
     },
     "moment-timezone": {
-      "version": "0.5.43",
-      "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz",
-      "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==",
+      "version": "0.5.41",
+      "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.41.tgz",
+      "integrity": "sha512-e0jGNZDOHfBXJGz8vR/sIMXvBIGJJcqFjmlg9lmE+5KX1U7/RZNMswfD8nKnNCnQdKTIj50IaRKwl1fvMLyyRg==",
       "requires": {
         "moment": "^2.29.4"
       }
@@ -43920,6 +43879,27 @@
         "sha.js": "^2.4.8"
       }
     },
+    "pc-bootstrap4-datetimepicker": {
+      "version": "4.17.51",
+      "resolved": "https://registry.npmjs.org/pc-bootstrap4-datetimepicker/-/pc-bootstrap4-datetimepicker-4.17.51.tgz",
+      "integrity": "sha512-UQDSKS5d1c43btk2vQ4siiv9YIkscZYQfTE513abeTqh5PIOJiyAeNdoCSTsDTZcpWJtWZHWk15yDXypYSFzcQ==",
+      "requires": {
+        "bootstrap": "^4.0.0-beta.2",
+        "jquery": "^1.8.3 || ^2.0 || ^3.0",
+        "moment": "^2.10",
+        "moment-timezone": "^0.4.0"
+      },
+      "dependencies": {
+        "moment-timezone": {
+          "version": "0.4.1",
+          "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.4.1.tgz",
+          "integrity": "sha512-5cNPVUwaVJDCe9JM8m/qz17f9SkaI8rpnRUyDJi2K5HAd6EwhuQ3n5nLclZkNC/qJnomKgQH2TIu70Gy2dxFKA==",
+          "requires": {
+            "moment": ">= 2.6.0"
+          }
+        }
+      }
+    },
     "pend": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
@@ -45235,11 +45215,6 @@
       "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==",
       "dev": true
     },
-    "qinu": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/qinu/-/qinu-1.2.0.tgz",
-      "integrity": "sha512-tcTCpRzghKo6jfjkQ8tEWwD8qtyOR4cqoVo0/6waSfYT3NM/lTytRCcYNbISFrK1tu7ttowyhY8XpEjleZWybA=="
-    },
     "qs": {
       "version": "6.10.4",
       "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz",
@@ -48988,6 +48963,14 @@
         }
       }
     },
+    "vue-bootstrap-datetimepicker": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/vue-bootstrap-datetimepicker/-/vue-bootstrap-datetimepicker-5.0.1.tgz",
+      "integrity": "sha512-jao7sWXHgKzjbOio97u7kEfB/FJMWJ5rhsc4q8iNTOLCULfSJ5m3AZ2qZh62dNcMA4/uuTW6m6tONYIith/2XQ==",
+      "requires": {
+        "pc-bootstrap4-datetimepicker": "^4.17.50"
+      }
+    },
     "vue-color": {
       "version": "2.8.1",
       "resolved": "https://registry.npmjs.org/vue-color/-/vue-color-2.8.1.tgz",
@@ -49000,14 +48983,6 @@
         "tinycolor2": "^1.1.2"
       }
     },
-    "vue-date-pick": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/vue-date-pick/-/vue-date-pick-1.5.1.tgz",
-      "integrity": "sha512-7IZDRBgrBUWiF7xMgVAEETq49E//djP7mCbMofLtG91D0IZNbLocT0Z+eueVrJ496lf5WSUE1dF3/ZaOGZW++w==",
-      "requires": {
-        "vue": "^2.6.0"
-      }
-    },
     "vue-deepset": {
       "version": "0.6.3",
       "resolved": "https://registry.npmjs.org/vue-deepset/-/vue-deepset-0.6.3.tgz",
@@ -49284,14 +49259,6 @@
       "resolved": "https://registry.npmjs.org/vue-the-mask/-/vue-the-mask-0.11.1.tgz",
       "integrity": "sha512-UquSfnSWejD0zAfcD+3jJ1chUAkOAyoxya9Lxh9acCRtrlmGcAIvd0cQYraWqKenbuZJUdum+S174atv2AuEHQ=="
     },
-    "vue-uniq-ids": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/vue-uniq-ids/-/vue-uniq-ids-1.1.2.tgz",
-      "integrity": "sha512-Jt4BSopBVJskX0iWiN9+lclWW5zXzrf5rkod80RVrp0fmpRC+KUMtQDAh2dyZP5QimWReioY4qqKuIqDMO/6UA==",
-      "requires": {
-        "qinu": "^1.1.2"
-      }
-    },
     "vue-upload-component": {
       "version": "2.8.23",
       "resolved": "https://registry.npmjs.org/vue-upload-component/-/vue-upload-component-2.8.23.tgz",
diff --git a/package.json b/package.json
index fa535cb0..6d882104 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@processmaker/modeler",
-  "version": "1.30.1",
+  "version": "1.29.0",
   "scripts": {
     "serve": "vue-cli-service serve",
     "open-cypress": "TZ=UTC cypress open",
@@ -41,8 +41,8 @@
     "@fortawesome/fontawesome-svg-core": "^1.2.25",
     "@fortawesome/free-solid-svg-icons": "^5.11.2",
     "@fortawesome/vue-fontawesome": "^0.1.8",
-    "@processmaker/screen-builder": "2.70.0",
-    "@processmaker/vue-form-elements": "0.45.0",
+    "@processmaker/screen-builder": "2.29.0",
+    "@processmaker/vue-form-elements": "0.29.1",
     "@processmaker/vue-multiselect": "^2.2.0",
     "acorn": "^6.4.2",
     "bootstrap": "^4.3.1",
diff --git a/src/components/Icons.js b/src/components/Icons.js
index 22944a85..cf2189c3 100644
--- a/src/components/Icons.js
+++ b/src/components/Icons.js
@@ -151,7 +151,7 @@ export default class
 
 String.prototype.startsLowerCase = function() {
   let firstLetter = this.substring(0,1);
-  return firstLetter == firstLetter.toLowerCase();
+  return firstLetter === firstLetter.toLowerCase();
 };
 
 String.prototype.unSlug = function() {
diff --git a/src/components/controls/controls.scss b/src/components/controls/controls.scss
deleted file mode 100644
index e8a1b412..00000000
--- a/src/components/controls/controls.scss
+++ /dev/null
@@ -1,69 +0,0 @@
-$controls-column-max-width: 265px;
-$controls-column-compressed-max-width: 95px;
-$controls-transition: 0.3s;
-
-.controls {
-  z-index: 2;
-  padding-bottom: $toolbar-height;
-
-  &-column {
-    max-width: $controls-column-max-width;
-    transition: all $controls-transition ease-out;
-
-    .list-group {
-      &:last-child {
-        border-bottom: 1px solid $border-color;
-      }
-    }
-  }
-
-  &-column-compressed {
-    max-width: $controls-column-compressed-max-width;
-    transition: all $controls-transition ease-in;
-  }
-}
-
-.card-header {
-  background: #f7f7f7;
-}
-
-.list-group-item {
-  &:focus-visible {
-    outline: none;
-  }
-  &:first-child {
-    border-top: 0;
-  }
-}
-
-.tool {
-  cursor: grab;
-  user-select: none;
-  font-size: 0.875rem;
-}
-
-.is-dragging {
-  background: $primary-color;
-  color: $primary-white;
-  position: absolute;
-  z-index: 10;
-  box-shadow: 5px 5px 8px 0px #0000004a;
-  cursor: grabbing;
-  padding: 0.5rem;
-
-  &.no-drop {
-    opacity: 0.8;
-    cursor: no-drop;
-  }
-
-  &:hover {
-    background-color: $primary-color;
-    color: $primary-white;
-  }
-}
-
-.tool-icon {
-  width: 1.5rem;
-  height: 1.5rem;
-  pointer-events: none;
-}
diff --git a/src/components/controls/controls.vue b/src/components/controls/controls.vue
deleted file mode 100644
index c46e1cdd..00000000
--- a/src/components/controls/controls.vue
+++ /dev/null
@@ -1,113 +0,0 @@
-<template>
-  <b-col
-    class="h-100 overflow-hidden controls-column"
-    :class="[{ 'ignore-pointer': canvasDragPosition, 'controls-column-compressed' : compressed }]"
-    data-test="controls-column"
-  >
-    <b-card no-body class="controls rounded-0 border-top-0 border-bottom-0 border-left-0" :style="{ height: parentHeight }">
-      <b-list-group flush class="overflow-auto w-auto" :class="{ 'd-flex align-items-center': compressed }">
-        <b-list-group-item
-          tabindex="0"
-          v-for="(control, index) in controls"
-          :key="index"
-          class="control-item border-right-0 flex-grow-1"
-          :class="compressed ? 'p-0 pt-2 pb-2 w-100 d-flex justify-content-center' : 'p-2'"
-          :data-test="control.type"
-          @dragstart="$event.preventDefault()"
-          @mousedown="startDrag($event, control)"
-        >
-          <div
-            class="tool"
-            :class="{ 'text-truncate ml-1': !compressed }"
-            v-b-tooltip.hover.viewport.d50="{ customClass: 'no-pointer-events' }"
-            :title="$t(control.label)"
-          >
-            <img :src="control.icon" class="tool-icon" :alt="$t(control.label)">
-            <span v-if="!compressed" class="ml-1">{{ $t(control.label) }}</span>
-          </div>
-        </b-list-group-item>
-      </b-list-group>
-    </b-card>
-  </b-col>
-</template>
-
-<script>
-import { BOTTOM } from '@/components/controls/rankConstants';
-
-export default {
-  props: ['allowDrop', 'compressed', 'canvasDragPosition', 'parentHeight', 'nodeTypes'],
-  watch: {
-    allowDrop(allowDrop) {
-      if (this.draggingElement) {
-        this.draggingElement.classList.toggle('no-drop', !allowDrop);
-      }
-    },
-  },
-  data() {
-    return {
-      draggingElement: null,
-      draggingControl: null,
-      xOffset: null,
-      yOffset: null,
-    };
-  },
-  computed: {
-    controls() {
-      return this.nodeTypes
-        .filter(nodeType => nodeType.control)
-        .map(nodeType => ({
-          type: nodeType.id,
-          icon: nodeType.icon,
-          label: nodeType.label,
-          bpmnType: nodeType.bpmnType,
-          rank: nodeType.rank || BOTTOM,
-        }))
-        .sort((node1, node2) => node1.rank - node2.rank);
-    },
-  },
-  methods: {
-    startDrag(event, control) {
-      const sourceElement = event.target;
-      const duplicateElement = sourceElement.cloneNode(true);
-      duplicateElement.classList.add('is-dragging');
-      duplicateElement.classList.toggle('no-drop', !this.allowDrop);
-
-      document.body.appendChild(duplicateElement);
-      this.xOffset = event.clientX - sourceElement.getBoundingClientRect().left;
-      this.yOffset = event.clientY - sourceElement.getBoundingClientRect().top;
-      this.draggingElement = duplicateElement;
-      this.draggingControl = control;
-
-      document.addEventListener('mousemove', this.setDraggingPosition);
-      document.addEventListener('mouseup', this.dropElement);
-      document.addEventListener('keyup', this.stopDrag);
-
-      this.setDraggingPosition(event);
-    },
-    stopDrag(event) {
-      if (event && event.key !== 'Escape') {
-        return;
-      }
-
-      document.removeEventListener('mousemove', this.setDraggingPosition);
-      document.removeEventListener('mouseup', this.dropElement);
-      document.removeEventListener('keyup', this.stopDrag);
-
-      document.body.removeChild(this.draggingElement);
-      this.draggingElement = null;
-      this.draggingControl = null;
-    },
-    dropElement({ clientX, clientY }) {
-      this.$emit('handleDrop', { clientX, clientY, control: this.draggingControl });
-      this.stopDrag();
-    },
-    setDraggingPosition({ pageX, pageY, clientX, clientY }) {
-      this.draggingElement.style.left = pageX - this.xOffset + 'px';
-      this.draggingElement.style.top = pageY - this.yOffset + 'px';
-      this.$emit('drag', { clientX, clientY, control: this.draggingControl });
-    },
-  },
-};
-</script>
-
-<style lang="scss" src="./controls.scss" scoped />
diff --git a/src/components/crown/crownButtons/associationFlowButton.vue b/src/components/crown/crownButtons/associationFlowButton.vue
index e4b91019..89fc0827 100644
--- a/src/components/crown/crownButtons/associationFlowButton.vue
+++ b/src/components/crown/crownButtons/associationFlowButton.vue
@@ -20,8 +20,6 @@ import connectIcon from '@/assets/connect-artifacts.svg';
 import CrownButton from '@/components/crown/crownButtons/crownButton';
 import { direction } from '@/components/nodes/association/associationConfig';
 import Node from '@/components/nodes/node';
-import store from '@/store';
-import { V } from 'jointjs';
 
 export default {
   components: { CrownButton },
@@ -31,23 +29,12 @@ export default {
       connectIcon,
     };
   },
-  computed: {
-    paper: () => store.getters.paper,
-  },
   methods: {
     addAssociation(cellView, evt, x, y) {
       this.$emit('toggle-crown-state', false);
-      const { clientX, clientY } = cellView;
-      let point = null;
-      if (cellView){
-        point = V(this.paper.viewport).toLocalPoint(clientX, clientY);
-      }
       const associationLink = this.moddle.create('bpmn:Association', {
         sourceRef: this.shape.component.node.definition,
-        targetRef: {
-          x: x ? x : point.x,
-          y: y ? y : point.y,
-        },
+        targetRef: { x, y },
         associationDirection: direction.none,
       });
 
diff --git a/src/components/crown/crownButtons/dataAssociationFlowButton.vue b/src/components/crown/crownButtons/dataAssociationFlowButton.vue
index 889a2e1b..e0bb69f2 100644
--- a/src/components/crown/crownButtons/dataAssociationFlowButton.vue
+++ b/src/components/crown/crownButtons/dataAssociationFlowButton.vue
@@ -22,8 +22,6 @@ import Node from '@/components/nodes/node';
 import * as dataOutputConfig from '@/components/nodes/dataOutputAssociation/config';
 import * as dataInputConfig from '@/components/nodes/dataInputAssociation/config';
 import DataAssociation from '@/components/nodes/genericFlow/DataAssociation';
-import store from '@/store';
-import { V } from 'jointjs';
 
 export default {
   components: { CrownButton },
@@ -34,19 +32,14 @@ export default {
     };
   },
   computed: {
-    paper: () => store.getters.paper,
     allowOutgoingDataAssociationFlow() {
       return DataAssociation.isADataNode(this.node);
     },
   },
   methods: {
-    addDataAssociation(cellView, x, y) {
+    addDataAssociation() {
       this.$emit('toggle-crown-state', false);
-      const { clientX, clientY } = cellView;
-      let point = null;
-      if (cellView){
-        point = V(this.paper.viewport).toLocalPoint(clientX, clientY);
-      }
+
       const comingFromDataStoreOrDataObject = this.node.isBpmnType('bpmn:DataStoreReference', 'bpmn:DataObjectReference');
 
       const dataAssociationConfig = comingFromDataStoreOrDataObject
@@ -63,10 +56,7 @@ export default {
 
       node.dataAssociationProps = {
         sourceShape: this.shape,
-        targetCoords: {
-          x: x ? x : point.x,
-          y: y ? y : point.y,
-        },
+        targetCoords: { x: undefined, y: undefined },
       };
 
       this.$emit('add-node', node);
diff --git a/src/components/crown/crownButtons/genericFlowButton.vue b/src/components/crown/crownButtons/genericFlowButton.vue
index c37819ef..258fc7bf 100644
--- a/src/components/crown/crownButtons/genericFlowButton.vue
+++ b/src/components/crown/crownButtons/genericFlowButton.vue
@@ -19,8 +19,6 @@ import Flow from '@/assets/connect-elements.svg';
 import CrownButton from '@/components/crown/crownButtons/crownButton';
 import Node from '@/components/nodes/node';
 import { id as genericFlowId } from '@/components/nodes/genericFlow/config';
-import store from '@/store';
-import { V } from 'jointjs';
 
 // Don't show the magic flow button on:
 const dontShowOn = [
@@ -44,7 +42,6 @@ export default {
     };
   },
   computed: {
-    paper: () => store.getters.paper,
     sequenceFlowConfig() {
       return this.nodeRegistry[genericFlowId];
     },
@@ -61,18 +58,10 @@ export default {
   methods: {
     addSequence(cellView, evt, x, y) {
       this.$emit('toggle-crown-state', false);
-      const { clientX, clientY } = cellView;
-      let point = null;
-      if (cellView){
-        point = V(this.paper.viewport).toLocalPoint(clientX, clientY);
-      }
       const flowPlaceholderDefinition = this.moddle.create('bpmn:SequenceFlow', {
         name: '',
         sourceRef: this.node.definition,
-        targetRef: {
-          x: x ? x : point.x,
-          y: y ? y : point.y,
-        },
+        targetRef: { x, y },
       });
 
       this.$emit('add-node', new Node(
diff --git a/src/components/crown/crownConfig/crownConfig.vue b/src/components/crown/crownConfig/crownConfig.vue
index 49992a33..53da1eba 100644
--- a/src/components/crown/crownConfig/crownConfig.vue
+++ b/src/components/crown/crownConfig/crownConfig.vue
@@ -222,6 +222,8 @@ export default {
       if (!store.getters.allowSavingElementPosition) {
         return;
       }
+
+      this.$emit('save-state');
     },
     repositionCrown() {
       const shapeView = this.shape.findView(this.paper);
diff --git a/src/components/modeler/Modeler.vue b/src/components/modeler/Modeler.vue
index 4fff43b7..da93ad7d 100644
--- a/src/components/modeler/Modeler.vue
+++ b/src/components/modeler/Modeler.vue
@@ -23,16 +23,8 @@
         :target="getTooltipTarget"
         :title="tooltipTitle"
       />
-
-      <controls
-        :nodeTypes="nodeTypes"
-        :compressed="panelsCompressed"
-        :parent-height="parentHeight"
-        :allowDrop="allowDrop"
-        @drag="validateDropTarget"
-        @handleDrop="handleDrop"
-        class="controls h-100 rounded-0 border-top-0 border-bottom-0 border-left-0"
-        :canvas-drag-position="canvasDragPosition"
+      <explorer-rail
+        :node-types="nodeTypes"
       />
       <b-col
         class="paper-container h-100 pr-4"
@@ -132,7 +124,7 @@ import _ from 'lodash';
 import { dia } from 'jointjs';
 import boundaryEventConfig from '../nodes/boundaryEvent';
 import BpmnModdle from 'bpmn-moddle';
-import controls from '../controls/controls';
+import ExplorerRail from '../rails/explorer-rail/explorer';
 import pull from 'lodash/pull';
 import remove from 'lodash/remove';
 import store from '@/store';
@@ -153,12 +145,6 @@ import { id as messageFlowId } from '../nodes/messageFlow/config';
 import { id as dataOutputAssociationFlowId } from '../nodes/dataOutputAssociation/config';
 import { id as dataInputAssociationFlowId } from '../nodes/dataInputAssociation/config';
 import { id as genericFlowId } from '@/components/nodes/genericFlow/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 PaperManager from '../paperManager';
 import registerInspectorExtension from '@/components/InspectorExtensionManager';
@@ -184,7 +170,7 @@ import Selection from './Selection';
 export default {
   components: {
     ToolBar,
-    controls,
+    ExplorerRail,
     InspectorPanel,
     MiniPaper,
     ProcessmakerModelerGenericFlow,
@@ -342,15 +328,7 @@ export default {
         genericFlowId,
         processId,
       ];
-      const boundaryEvents = [
-        boundaryErrorEventId,
-        boundaryConditionalEventId,
-        boundaryEscalationEventId,
-        boundaryMessageEventId,
-        boundarySignalEventId,
-        boundaryTimerEventId,
-      ];
-      if (this.highlightedNodes.length === 1 && (flows.includes(this.highlightedNodes[0].type) || boundaryEvents.includes(this.highlightedNodes[0].type))) return;
+      if (this.highlightedNodes.length === 1 && flows.includes(this.highlightedNodes[0].type)) return;
       store.commit('setCopiedElements', this.cloneNodesSelection());
       this.$bvToast.toast(this.$t('Object(s) have been copied'), { noCloseButton:true, variant: 'success', solid: true, toaster: 'b-toaster-top-center' });
     },
@@ -1172,7 +1150,6 @@ export default {
     },
     pointerMoveHandler(event) {
       const { clientX: x, clientY: y } = event;
-      if (this.isGrabbing) return;
       if (this.dragStart && (Math.abs(x - this.dragStart.x) > 5 || Math.abs(y - this.dragStart.y) > 5)) {
         this.isDragging = true;
         this.dragStart = null;
@@ -1190,6 +1167,7 @@ export default {
       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();
@@ -1267,16 +1245,6 @@ export default {
       this.isOverShape = false;
       this.pointerDownHandler(event);
     }, this);
-
-    this.paperManager.addEventHandler('cell:mouseover element:mouseover', ({ model: shape }) => {
-      if (this.isBpmnNode(shape) && shape.attr('body/cursor') !== 'default' && !this.isGrabbing) {
-        shape.attr('body/cursor', 'move');
-      }
-      // If the user is panning the Paper while hovering an element, ignore the default move cursor
-      if (this.isGrabbing && this.isBpmnNode(shape)) {
-        shape.attr('body/cursor', 'grabbing');
-      }
-    });
     this.paperManager.addEventHandler('blank:pointerup', (event) => {
       this.canvasDragPosition = null;
       this.activeNode = null;
@@ -1313,9 +1281,6 @@ export default {
         return;
       }
 
-      // ignore click event if the user is Grabbing the paper
-      if (this.isGrabbing) return;
-
       shape.component.$emit('click', event);
     });
 
@@ -1323,30 +1288,11 @@ export default {
       if (!this.isBpmnNode(shape)) {
         return;
       }
-      // If the user is pressing Space (grabbing) and clicking on a Cell, return
-      if (this.isGrabbing) {
-        return;
-      }
       this.setShapeStacking(shape);
       this.activeNode = shape.component.node;
       this.isOverShape = true;
       this.pointerDowInShape(event, shape);
     });
-    // If the user is grabbing the paper while he clicked in a cell, move the paper and not the cell
-    this.paperManager.addEventHandler('cell:pointermove', (_, event, x, y) => {
-      if (this.isGrabbing) {
-        if (!this.canvasDragPosition) {
-          const scale = this.paperManager.scale;
-          this.canvasDragPosition = { x: x * scale.sx, y: y * scale.sy };
-        }
-        if (this.canvasDragPosition && !this.clientLeftPaper) {
-          this.paperManager.translate(
-            event.offsetX - this.canvasDragPosition.x,
-            event.offsetY - this.canvasDragPosition.y
-          );
-        }
-      }
-    });
 
     /* Register custom nodes */
     window.ProcessMaker.EventBus.$emit('modeler-start', {
diff --git a/src/components/modeler/Selection.vue b/src/components/modeler/Selection.vue
index cc20e951..620d1fa8 100644
--- a/src/components/modeler/Selection.vue
+++ b/src/components/modeler/Selection.vue
@@ -53,7 +53,6 @@ export default {
       isSelecting: false,
       isSelected: false,
       selected: [],
-      conectedLinks:[],
       dragging: false,
       style:  {
         left: '0px',
@@ -97,7 +96,6 @@ export default {
   watch: {
     // whenever selected changes
     selected(newSelected) {
-      this.prepareConectedLinks(newSelected);
       this.addToHighlightedNodes(newSelected);
     },
   },
@@ -296,24 +294,6 @@ export default {
       });
       return elements;
     },
-    /**
-     * Prepare the conectedLinks collection
-     * @param {Array} shapes 
-     */
-    prepareConectedLinks(shapes){
-      const { paper } = this.paperManager;
-      this.conectedLinks = [];
-      shapes.forEach((shape) => {
-        const conectedLinks = this.graph.getConnectedLinks(shape.model);
-        conectedLinks.forEach((link) => {
-          const linkView = paper.findViewByModel(link);
-          if (!this.conectedLinks.some(obj => obj.id === linkView.id)) {
-            this.conectedLinks.push(linkView);
-          }
-        });
- 
-      });
-    },
     /**
      * Return the bounding box of the selected elements,
      * @param {Array} selected
@@ -387,7 +367,7 @@ export default {
         // remove from selection the selected flows that belongs to a selected pools
         if (shape.model.component  && flowTypes.includes(shape.model.component.node.type)) {
           const parent = shape.model.getParentCell();
-          if (parent && parent.component && parent.component.node.pool) {
+          if (parent.component && parent.component.node.pool) {
             return !selectedPoolsIds.includes(parent.component.node.pool.component.node.id);
           }
         }
@@ -495,27 +475,13 @@ export default {
      * @param {Object} event
      */
     stopDrag() {
+      this.overPoolStopDrag();
+      this.$emit('save-state');
       this.dragging = false;
       this.stopForceMove = false;
       // Readjusts the selection box, taking into consideration elements
       // that are anchored and did not move, such as boundary events. 
       this.updateSelectionBox();
-      this.updateFlowsWaypoint();
-      this.overPoolStopDrag();
-    },
-    /**
-     * Selector will update the waypoints of the related flows
-     */
-    updateFlowsWaypoint(){
-      this.conectedLinks.forEach((link)=> {
-        if (link.model.component && link.model.get('type') === 'standard.Link'){
-          const start = link.sourceAnchor;
-          const end = link.targetAnchor;
-          link.model.component.node.diagram.waypoint = [start,
-            ...link.model.component.shape.vertices(),
-            end].map(point => link.model.component.moddle.create('dc:Point', point));
-        }
-      });
     },
     /**
      * Translate the Selected shapes adding some custom validations
@@ -666,14 +632,12 @@ export default {
      */
     overPoolStopDrag(){
       if (this.isNotPoolChilds(this.selected)) {
-        this.$emit('save-state');
         return;
       }
       if (this.isOutOfThePool) {
         this.rollbackSelection();
       } else {
         this.expandToFitElement(this.selected);
-        this.$emit('save-state');
       }
     },
     /**
@@ -695,7 +659,6 @@ export default {
           shape.model.translate(deltaX/scale.sx, deltaY/scale.sy);
         });
       this.isOutOfThePool = false;
-      this.updateFlowsWaypoint();
       await store.commit('allowSavingElementPosition');
       this.paperManager.setStateValid();
       await this.$nextTick();
@@ -771,6 +734,7 @@ export default {
             node: pool.component.node,
             bounds: pool.getBBox(),
           });
+          this.$emit('save-state');
         }
       }
     },
diff --git a/src/components/modeler/modeler.scss b/src/components/modeler/modeler.scss
index 963b1278..46258326 100644
--- a/src/components/modeler/modeler.scss
+++ b/src/components/modeler/modeler.scss
@@ -21,10 +21,6 @@
     user-select: none;
   }
 
-  .joint-element {
-    cursor: default;
-  }
-
   .joint-marker-vertex:hover {
     fill: $error-color;
     cursor: url('../../assets/delete-icon-vertex.png') 0 0, pointer;
diff --git a/src/components/modeler/setUpSelectionBox.js b/src/components/modeler/setUpSelectionBox.js
new file mode 100644
index 00000000..b8a08f5a
--- /dev/null
+++ b/src/components/modeler/setUpSelectionBox.js
@@ -0,0 +1,146 @@
+import { g, shapes } from 'jointjs';
+import store from '@/store';
+import { canMoveProgrammatically } from '@/components/nodes/utilities/shapeMovement';
+
+const shapesToNotTranslate = [
+  'processmaker.modeler.bpmn.pool',
+  'PoolLane',
+  'processmaker.components.nodes.boundaryEvent.Shape',
+];
+
+export default function setUpSelectionBox(setCursor, resetCursor, paperManager, graph) {
+  let initialPosition;
+  let shiftKeyPressed = false;
+  let selectionBox;
+  let selectionboxMousedownPosition;
+
+  document.addEventListener('keydown', shiftKeyDownListener);
+  document.addEventListener('keyup', shiftKeyUpListener);
+  document.addEventListener('mousedown', mousedownListener);
+  document.addEventListener('mouseup', mouseupListener);
+  document.addEventListener('mousemove', mousemoveListener);
+  paperManager.addEventHandler('cell:pointerdown', cellView => {
+    if (!cellView.model.component) {
+      return;
+    }
+
+    initialPosition = cellView.model.position();
+    cellView.model.on('change:position', moveAllOtherHighlightedShapes);
+  });
+  paperManager.addEventHandler('cell:pointerup link:pointerup element:pointerup blank:pointerup', cellView => {
+    if (!cellView.model) {
+      return;
+    }
+
+    cellView.model.off('change:position', moveAllOtherHighlightedShapes);
+  });
+
+  function resetMultiSelect() {
+    resetCursor();
+    shiftKeyPressed = false;
+    paperManager.preventTranslate = false;
+    paperManager.paper.setInteractivity(graph.get('interactiveFunc'));
+  }
+
+  function shiftKeyDownListener(event) {
+    if (event.shiftKey && (event.ctrlKey || event.altKey || event.metaKey)) {
+      resetMultiSelect();
+      return;
+    }
+
+    if (event.key !== 'Shift' || shiftKeyPressed) {
+      return;
+    }
+
+    setCursor();
+    shiftKeyPressed = true;
+    paperManager.preventTranslate = true;
+    paperManager.paper.setInteractivity(false);
+  }
+
+  function shiftKeyUpListener({ key }) {
+    if (key !== 'Shift' || !shiftKeyPressed) {
+      return;
+    }
+    resetMultiSelect();
+  }
+
+  function mousedownListener({ clientX, clientY }) {
+    if (!shiftKeyPressed) {
+      return;
+    }
+
+    selectionboxMousedownPosition = paperManager.clientToGridPoint(clientX, clientY);
+  }
+
+  function mousemoveListener({ clientX, clientY }) {
+    if (!selectionboxMousedownPosition) {
+      return;
+    }
+
+    if (selectionBox) {
+      graph.removeCells(selectionBox);
+    }
+
+    const { x, y } = paperManager.clientToGridPoint(clientX, clientY);
+    selectionBox = createSelectionBox(selectionboxMousedownPosition, { x, y });
+    graph.addCell(selectionBox);
+  }
+
+  function mouseupListener() {
+    selectionboxMousedownPosition = null;
+
+    if (!selectionBox) {
+      return;
+    }
+
+    const selectedNodes = paperManager.paper
+      .findViewsInArea(selectionBox.getBBox(), { strict: true })
+      .filter(shape => shape.model.component)
+      .map(shape => shape.model.component.node);
+
+    store.commit('addToHighlightedNodes', selectedNodes);
+
+    graph.removeCells(selectionBox);
+    selectionBox = null;
+  }
+
+  function moveAllOtherHighlightedShapes(element, newPosition, { movedWithArrowKeys }) {
+    if (
+      movedWithArrowKeys ||
+      !canMoveProgrammatically(element) ||
+      !store.getters.highlightedShapes.includes(element) ||
+      element.component.node.pool
+    ) {
+      return;
+    }
+
+    const { x, y } = initialPosition;
+    const dx = newPosition.x - x;
+    const dy = newPosition.y - y;
+
+    store.getters.highlightedShapes
+      .filter(shape => shape !== element && !shapesToNotTranslate.includes(shape.get('type')))
+      .forEach(shape => shape.translate(dx, dy));
+
+    initialPosition = newPosition;
+  }
+
+  function createSelectionBox(p1, p2) {
+    const { x, y, width, height } = new g.Line(p1, p2).bbox();
+
+    return new shapes.standard.Rectangle({
+      position: { x, y },
+      size: { width, height },
+      type: 'selectionBox',
+      attrs: {
+        body: {
+          fill: 'lightblue',
+          opacity: 0.3,
+          stroke: 'blue',
+          strokeWidth: 1,
+        },
+      },
+    });
+  }
+}
diff --git a/src/components/nodes/boundaryConditionalEvent/index.js b/src/components/nodes/boundaryConditionalEvent/index.js
index be123fba..878e31e8 100644
--- a/src/components/nodes/boundaryConditionalEvent/index.js
+++ b/src/components/nodes/boundaryConditionalEvent/index.js
@@ -7,10 +7,9 @@ import advancedAccordionConfig from '@/components/inspectors/advancedAccordionCo
 import documentationAccordionConfig from '@/components/inspectors/documentationAccordionConfig';
 import { default as eventDefinition, inspector } from '../conditionalEventDefinition';
 
-export const id = 'processmaker-modeler-boundary-conditional-event';
 export default merge(cloneDeep(boundaryEventConfig), {
   ...eventDefinition,
-  id,
+  id: 'processmaker-modeler-boundary-conditional-event',
   component,
   control: false,
   label: 'Boundary Conditional Event',
diff --git a/src/components/nodes/boundaryEvent/boundaryEvent.vue b/src/components/nodes/boundaryEvent/boundaryEvent.vue
index 5f7de5d3..b37748d6 100644
--- a/src/components/nodes/boundaryEvent/boundaryEvent.vue
+++ b/src/components/nodes/boundaryEvent/boundaryEvent.vue
@@ -218,6 +218,7 @@ export default {
     this.updateShapePosition(task);
 
     this.shape.on('change:position', this.turnInvalidTargetRed);
+    this.shape.listenTo(this.paper, 'element:pointerdown', this.attachToValidTarget);
   },
 };
 </script>
diff --git a/src/components/nodes/boundaryTimerEvent/index.js b/src/components/nodes/boundaryTimerEvent/index.js
index 339d776f..435f9162 100644
--- a/src/components/nodes/boundaryTimerEvent/index.js
+++ b/src/components/nodes/boundaryTimerEvent/index.js
@@ -9,10 +9,8 @@ import documentationAccordionConfig from '@/components/inspectors/documentationA
 
 export const defaultDurationValue = 'PT1H';
 
-export const id = 'processmaker-modeler-boundary-timer-event';
-
 export default merge(cloneDeep(boundaryEventConfig), {
-  id,
+  id: 'processmaker-modeler-boundary-timer-event',
   component,
   control: false,
   label: 'Boundary Timer Event',
diff --git a/src/components/rails/explorer-rail/explorer-rail.scss b/src/components/rails/explorer-rail/explorer-rail.scss
new file mode 100644
index 00000000..b56432ef
--- /dev/null
+++ b/src/components/rails/explorer-rail/explorer-rail.scss
@@ -0,0 +1,65 @@
+$controls-transition: 0.3s;
+$secondary-color-nav: #6c757d;
+
+#explorer-rail {
+	max-width: 355px;
+	background-color: white;
+	width: 100%;
+	transition: all $controls-transition ease-out;
+	z-index: 2;
+	border-radius: 4px;
+	box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1);
+	padding-left: 1rem;
+}
+
+.rail-menu {
+	display: flex;
+	align-items: center;
+	justify-content: space-between;
+	padding: 0.5rem 0;
+	.nav-link {
+		color: $secondary-color-nav;
+		&.active {
+			font-weight: bold;
+			border-bottom: 2px solid #1572C2;
+			color: #000;
+		}
+	}
+
+	.close--container {
+		width: 50px;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		height: 40px;
+		&:hover {
+			cursor: pointer;
+		}
+	}
+}
+
+.node-types {
+	&__container {
+		padding: 0.5rem 1rem;
+		p {
+			font-size: 13px;
+			line-height: 19px;
+			color: #000;
+		}
+	}
+
+	&__item {
+		display: flex;
+		margin-bottom: 1rem;
+		align-items: center;
+		img {
+			height: 1.5rem;
+			width: 1.5rem;
+		}
+		span {
+			margin-left: 0.8rem;
+			font-size: 13px;
+			line-height: 19px;
+		}
+	}
+}
diff --git a/src/components/rails/explorer-rail/explorer.vue b/src/components/rails/explorer-rail/explorer.vue
new file mode 100644
index 00000000..64c0372d
--- /dev/null
+++ b/src/components/rails/explorer-rail/explorer.vue
@@ -0,0 +1,98 @@
+<script>
+import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
+import { faTimes } from '@fortawesome/free-solid-svg-icons';
+import nodeTypesStore from '@/nodeTypesStore';
+
+export default {
+  name: 'ExplorerRail',
+  props: {
+    nodeTypes: {
+      type: Array,
+    },
+  },
+  components: {
+    FontAwesomeIcon,
+  },
+  data() {
+    return {
+      // TODO set to false when the bottom control rail is merged
+      expanded: true,
+      tabs: [{
+        idx: 0,
+        label: 'Add Object',
+      }, {
+        idx: 1,
+        label: 'PM Blocks',
+      }],
+      tabIndex: 0,
+    };
+  },
+  computed: {
+    objects() {
+      return nodeTypesStore.getters.getNodeTypes;
+    },
+    pinnedObjects() {
+      return nodeTypesStore.getters.getPinnedNodeTypes;
+    },
+  },
+  created() {
+    nodeTypesStore.commit('setNodeTypes', this.nodeTypes);
+  },
+  methods: {
+    faTimes() {
+      return faTimes;
+    },
+    setTabIndex(idx) {
+      this.tabIndex = idx;
+    },
+    toggleRail() {
+      this.expanded = !this.expanded;
+    },
+    closeRail() {
+      this.expanded = false;
+    },
+  },
+};
+</script>
+
+<template>
+  <div id="explorer-rail" data-test="explorer-rail" v-if="expanded">
+    <div class="rail-menu">
+      <b-tabs class="tabs--container" :no-nav-style="true">
+        <template v-for="tab in tabs">
+          <b-tab :title="$t(tab.label)" :active="tab.idx === tabIndex"
+            @click="setTabIndex(tab.idx)" :key="tab.idx"
+          />
+        </template>
+      </b-tabs>
+      <div class="close--container" @click="closeRail()">
+        <font-awesome-icon :icon="faTimes()"/>
+      </div>
+    </div>
+    <div class="node-types__container" v-if="tabIndex === 0">
+      <template v-if="pinnedObjects.length > 0">
+        <p>{{ $t('Pinned Objects') }}</p>
+        <template v-for="pinnedObject in pinnedObjects">
+          <div class="node-types__item" :key="pinnedObject.id">
+            <img :src="pinnedObject.icon" :alt="$t(pinnedObject.label)">
+            <span>{{ $t(pinnedObject.label) }}</span>
+          </div>
+        </template>
+      </template>
+      <template v-if="objects.length > 0">
+        <p>{{ $t('Object Category') }}</p>
+        <template v-for="object in objects">
+          <div class="node-types__item" :key="object.id">
+            <img :src="object.icon" :alt="$t(object.label)">
+            <span>{{ $t(object.label) }}</span>
+          </div>
+        </template>
+      </template>
+    </div>
+    <div class="pm-blocks__container">
+      <!--   Here goes the PM Blocks   -->
+    </div>
+  </div>
+</template>
+
+<style lang="scss" src="./explorer-rail.scss"></style>
diff --git a/src/components/controls/rankConstants.js b/src/components/rails/explorer-rail/rankConstants.js
similarity index 100%
rename from src/components/controls/rankConstants.js
rename to src/components/rails/explorer-rail/rankConstants.js
diff --git a/src/mixins/linkConfig.js b/src/mixins/linkConfig.js
index 1c3a7446..1c979c51 100644
--- a/src/mixins/linkConfig.js
+++ b/src/mixins/linkConfig.js
@@ -118,23 +118,14 @@ export default {
       const targetShape = this.shape.getTargetElement();
       resetShapeColor(targetShape);
 
-      this.shape.on('change:vertices', this.onChangeVertices);
+      this.shape.listenTo(this.sourceShape, 'change:position', this.updateWaypoints);
+      this.shape.listenTo(targetShape, 'change:position', this.updateWaypoints);
+      this.shape.on('change:vertices change:source change:target', this.updateWaypoints);
 
       const sourceShape = this.shape.getSourceElement();
       sourceShape.embed(this.shape);
       this.$emit('set-shape-stacking', sourceShape);
     },
-    /**
-     * On Change vertices handler
-     * @param {Object} link 
-     * @param {Array} vertices 
-     * @param {Object} options 
-     */
-    onChangeVertices(link, vertices, options){
-      if (options && options.ui) {
-        this.updateWaypoints();
-      }
-    },
     updateWaypoints() {
       const linkView = this.shape.findView(this.paper);
       const start = linkView.sourceAnchor;
diff --git a/src/nodeTypesStore.js b/src/nodeTypesStore.js
new file mode 100644
index 00000000..5ce86293
--- /dev/null
+++ b/src/nodeTypesStore.js
@@ -0,0 +1,39 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import { BOTTOM } from '@/components/rails/explorer-rail/rankConstants';
+
+Vue.use(Vuex);
+
+export default new Vuex.Store({
+  state: {
+    nodeTypes: [],
+    pinnedNodeTypes: [],
+  },
+  getters: {
+    getNodeTypes: state => state.nodeTypes,
+    getPinnedNodeTypes: state => state.pinnedNodeTypes,
+  },
+  mutations: {
+    setNodeTypes(state, nodeTypes) {
+      state.nodeTypes = nodeTypes
+        .filter(nodeType => nodeType.control)
+        .map(nodeType => ({
+          type: nodeType.id,
+          icon: nodeType.icon,
+          label: nodeType.label,
+          bpmnType: nodeType.bpmnType,
+          rank: nodeType.rank || BOTTOM,
+        }))
+        .sort((node1, node2) => node1.rank - node2.rank);
+    },
+    setPinnedNodes(state, payload) {
+      state.pinnedNodeTypes = payload;
+    },
+  },
+  actions: {
+    // eslint-disable-next-line no-unused-vars
+    getUserPinnedObjects(state) {
+      // here goes the axios call to get the user pinned objects
+    },
+  },
+});
diff --git a/src/store.js b/src/store.js
index 4e432c90..deb48a5d 100644
--- a/src/store.js
+++ b/src/store.js
@@ -40,7 +40,6 @@ export default new Vuex.Store({
   },
   getters: {
     nodes: state => state.nodes,
-    paper: state => state.paper,
     highlightedNodes: state => state.highlightedNodes,
     nodeShape: state => node => {
       return state.graph.getCells().find(cell => cell.component && cell.component.node === node);


Test patch:
diff --git a/tests/unit/rails/__snapshots__/explorer.spec.js.snap b/tests/unit/rails/__snapshots__/explorer.spec.js.snap
new file mode 100644
index 00000000..5045a0bc
--- /dev/null
+++ b/tests/unit/rails/__snapshots__/explorer.spec.js.snap
@@ -0,0 +1,46 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Explorer Rail should render the component 1`] = `
+<div
+  data-test="explorer-rail"
+  id="explorer-rail"
+>
+  <div
+    class="rail-menu"
+  >
+    <b-tabs-stub
+      class="tabs--container"
+      nonavstyle="true"
+      tag="div"
+    >
+      <b-tab-stub
+        active="true"
+        tag="div"
+      />
+      <b-tab-stub
+        tag="div"
+      />
+    </b-tabs-stub>
+     
+    <div
+      class="close--container"
+    >
+      <font-awesome-icon-stub
+        icon="[object Object]"
+      />
+    </div>
+  </div>
+   
+  <div
+    class="node-types__container"
+  >
+    <!---->
+     
+    <!---->
+  </div>
+   
+  <div
+    class="pm-blocks__container"
+  />
+</div>
+`;
diff --git a/tests/unit/rails/explorer.spec.js b/tests/unit/rails/explorer.spec.js
new file mode 100644
index 00000000..3cf395b9
--- /dev/null
+++ b/tests/unit/rails/explorer.spec.js
@@ -0,0 +1,58 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import explorerRail from '@/components/rails/explorer-rail/explorer';
+import BootstrapVue from 'bootstrap-vue';
+
+const nodeTypes = [
+  {
+    id: 'processmaker-modeler-process',
+    bpmnType: 'bpmn:Process',
+    label: 'Process',
+  },
+];
+
+const localVue = createLocalVue();
+
+localVue.use(BootstrapVue);
+
+describe('Explorer Rail', () => {
+  let wrapper;
+  beforeEach(() => {
+    wrapper = shallowMount(explorerRail, {
+      propsData: {
+        nodeTypes,
+      },
+      mocks: {
+        $t() {},
+      },
+      localVue,
+    });
+  });
+  it('should render the component', () => {
+    expect(wrapper.vm).toBeTruthy();
+    expect(wrapper.vm.$el).toMatchSnapshot();
+  });
+  it('should check for vdata defaults', () => {
+    // TODO uncomment the code when the bottom rail has been merged
+    // expect(wrapper.vm.expanded).toBe(false);
+    expect(wrapper.vm.tabs).toHaveLength(2);
+    expect(wrapper.vm.tabIndex).toBe(0);
+  });
+  it('should set the tab index', () => {
+    wrapper.vm.setTabIndex(1);
+    expect(wrapper.vm.tabIndex).toBe(1);
+  });
+  // TODO replace the xit with it when bottom rail has been merged
+  xit('should toggle the rail', () => {
+    expect(wrapper.vm.expanded).toBe(false);
+    wrapper.vm.toggleRail();
+    expect(wrapper.vm.expanded).toBe(true);
+  });
+  // TODO replace the xit with it when bottom rail has been merged
+  xit('should close the rail', () => {
+    // toggling the rail to be opened
+    wrapper.vm.toggleRail();
+    expect(wrapper.vm.expanded).toBe(true);
+    wrapper.vm.closeRail();
+    expect(wrapper.vm.expanded).toBe(false);
+  });
+});