Implement dynamic outcomes

This commit is contained in:
Sipke Schoorstra 2022-02-01 20:29:35 +01:00
parent 50fd5f85ed
commit 0397c58e17
23 changed files with 586 additions and 372 deletions

View file

@ -5,7 +5,7 @@ namespace Elsa.ActivityNodeResolvers;
public class SwitchActivityNodeResolver : IActivityNodeResolver
{
public int Priority => -1;
public int Priority => 0;
public bool GetSupportsActivity(IActivity activity) => activity is Switch;
public IEnumerable<IActivity> GetPorts(IActivity activity)

View file

@ -9,16 +9,15 @@
"version": "3.0.0",
"license": "MIT",
"dependencies": {
"@antv/x6": "^1.29.1",
"@stencil/core": "^2.12.0",
"@antv/x6": "^1.30.0",
"@stencil/core": "^2.13.0",
"@stencil/state-tunnel": "^1.0.1",
"@stencil/store": "^1.5.0",
"axios": "^0.24.0",
"axios": "^0.25.0",
"axios-middleware": "^0.3.1",
"el-transition": "^0.0.7",
"lodash": "^4.17.21",
"moment": "^2.29.1",
"monaco-editor": "^0.31.1",
"reflect-metadata": "^0.1.13",
"typedi": "^0.10.0",
"uuid": "^8.3.2"
@ -28,18 +27,21 @@
"@stencil/postcss": "^2.1.0",
"@stencil/sass": "^1.5.2",
"@tailwindcss/forms": "^0.4.0",
"@tailwindcss/typography": "^0.5.0",
"@types/jquery": "^3.5.11",
"@tailwindcss/typography": "^0.5.1",
"@types/jquery": "^3.5.13",
"@types/jquery-mousewheel": "^3.1.9",
"autoprefixer": "^10.4.0",
"postcss": "^8.4.5",
"tailwindcss": "^3.0.7"
"autoprefixer": "^10.4.2",
"postcss": "^8.4.6",
"tailwindcss": "^3.0.18"
},
"peerDependencies": {
"monaco-editor": ""
}
},
"node_modules/@antv/x6": {
"version": "1.29.1",
"resolved": "https://registry.npmjs.org/@antv/x6/-/x6-1.29.1.tgz",
"integrity": "sha512-XSCtW1T/CIC0QUUUYW04EUQ5VnBMsShiNz9NP64oN8fAW14Jw99NKUhzToKpHGqQtVDg6qBX1UjFsfi0SUL4lg==",
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/@antv/x6/-/x6-1.30.0.tgz",
"integrity": "sha512-YYUSY1YdreTw4LxElQClXQqZ2msSefHZ2JFM9dM3NOMPn/VWNc6+GIvfxJ51HHWCNF23Hn126xxVBxYRu1zAuw==",
"dependencies": {
"csstype": "^3.0.3",
"jquery": "^3.5.1",
@ -194,9 +196,9 @@
}
},
"node_modules/@stencil/core": {
"version": "2.12.0",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.12.0.tgz",
"integrity": "sha512-hQlQKh5CUJe8g3L5avLLsfgVu95HMS2LToTtS7gpvvP0eKes1VvAC56uhI+vH4u44GZl9ck/g1rJBVRmMWu0LA==",
"version": "2.13.0",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.13.0.tgz",
"integrity": "sha512-EEKHOHgYpg3/iFUKMXTZJjUayRul7sXDwNw0OGgkEOe4t7JWiibDkzUHuruvpbqEydX+z1+ez5K2bMMY76c2wA==",
"bin": {
"stencil": "bin/stencil"
},
@ -280,24 +282,23 @@
}
},
"node_modules/@tailwindcss/typography": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.0.tgz",
"integrity": "sha512-1p/3C6C+JJziS/ghtG8ACYalbA2SyLJY27Pm33cVTlAoY6VQ7zfm2H64cPxUMBkVIlWXTtWHhZcZJPobMRmQAA==",
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.1.tgz",
"integrity": "sha512-AmSzZSgLhHKlILKduU+PKBTHL6c+al82syZlRid1xgmlWwXagLigO+O++B4C0scpMfzW//f/3YCRcwwEHWoU3w==",
"dev": true,
"dependencies": {
"lodash.castarray": "^4.4.0",
"lodash.isplainobject": "^4.0.6",
"lodash.merge": "^4.6.2",
"lodash.uniq": "^4.5.0"
"lodash.merge": "^4.6.2"
},
"peerDependencies": {
"tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || insiders"
}
},
"node_modules/@types/jquery": {
"version": "3.5.11",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.11.tgz",
"integrity": "sha512-lYZGdfOtUa0XFjIATQgiogqeTY5PNNMOmp3Jq48ghmJALL8t/IqABRqlEwdHfuUdA8iIE1uGD1HoI4a7Tiy6OA==",
"version": "3.5.13",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.13.tgz",
"integrity": "sha512-ZxJrup8nz/ZxcU0vantG+TPdboMhB24jad2uSap50zE7Q9rUeYlCF25kFMSmHR33qoeOgqcdHEp3roaookC0Sg==",
"dev": true,
"dependencies": {
"@types/sizzle": "*"
@ -391,17 +392,17 @@
"dev": true
},
"node_modules/autoprefixer": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.0.tgz",
"integrity": "sha512-7FdJ1ONtwzV1G43GDD0kpVMn/qbiNqyOPMFTX5nRffI+7vgWoFEc6DcXOxHJxrWNDXrZh18eDsZjvZGUljSRGA==",
"version": "10.4.2",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz",
"integrity": "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==",
"dev": true,
"dependencies": {
"browserslist": "^4.17.5",
"caniuse-lite": "^1.0.30001272",
"fraction.js": "^4.1.1",
"browserslist": "^4.19.1",
"caniuse-lite": "^1.0.30001297",
"fraction.js": "^4.1.2",
"normalize-range": "^0.1.2",
"picocolors": "^1.0.0",
"postcss-value-parser": "^4.1.0"
"postcss-value-parser": "^4.2.0"
},
"bin": {
"autoprefixer": "bin/autoprefixer"
@ -418,11 +419,11 @@
}
},
"node_modules/axios": {
"version": "0.24.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
"integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
"version": "0.25.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz",
"integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==",
"dependencies": {
"follow-redirects": "^1.14.4"
"follow-redirects": "^1.14.7"
}
},
"node_modules/axios-middleware": {
@ -471,13 +472,13 @@
}
},
"node_modules/browserslist": {
"version": "4.17.5",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.5.tgz",
"integrity": "sha512-I3ekeB92mmpctWBoLXe0d5wPS2cBuRvvW0JyyJHMrk9/HmP2ZjrTboNAZ8iuGqaEIlKguljbQY32OkOJIRrgoA==",
"version": "4.19.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz",
"integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==",
"dev": true,
"dependencies": {
"caniuse-lite": "^1.0.30001271",
"electron-to-chromium": "^1.3.878",
"caniuse-lite": "^1.0.30001286",
"electron-to-chromium": "^1.4.17",
"escalade": "^3.1.1",
"node-releases": "^2.0.1",
"picocolors": "^1.0.0"
@ -512,9 +513,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001272",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001272.tgz",
"integrity": "sha512-DV1j9Oot5dydyH1v28g25KoVm7l8MTxazwuiH3utWiAS6iL/9Nh//TGwqFEeqqN8nnWYQ8HHhUq+o4QPt9kvYw==",
"version": "1.0.30001304",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001304.tgz",
"integrity": "sha512-bdsfZd6K6ap87AGqSHJP/s1V+U6Z5lyrcbBu3ovbCCf8cSYpwTtGrCBObMpJqwxfTbLW6YTIdbb1jEeTelcpYQ==",
"dev": true,
"funding": {
"type": "opencollective",
@ -538,10 +539,16 @@
}
},
"node_modules/chokidar": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
"integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
],
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
@ -677,9 +684,9 @@
"integrity": "sha512-a23pEa7ahqLmBIEqtxi8CdL6CRLF52ZoAwawDFTD1IDkegrL4iValQAj6IMEgIEXPSrXZtx/Nr/ej6ebov4uoA=="
},
"node_modules/electron-to-chromium": {
"version": "1.3.883",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.883.tgz",
"integrity": "sha512-goyjNx4wB9j911PBteb+AXNbErug7rJVkmDXWdw5SCVn2JlARBwsqucPkvp1h5mXWxHUbBRK3bwXTrqSxSiAIQ==",
"version": "1.4.59",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.59.tgz",
"integrity": "sha512-AOJ3cAE0TWxz4fQ9zkND5hWrQg16nsZKVz9INOot1oV//u4wWu5xrj9CQMmPTYskkZRunSRc9sAnr4EkexXokg==",
"dev": true
},
"node_modules/error-ex": {
@ -710,9 +717,9 @@
}
},
"node_modules/fast-glob": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz",
"integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==",
"version": "3.2.11",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
"integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
"dev": true,
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
@ -722,7 +729,7 @@
"micromatch": "^4.0.4"
},
"engines": {
"node": ">=8"
"node": ">=8.6.0"
}
},
"node_modules/fast-glob/node_modules/glob-parent": {
@ -759,9 +766,9 @@
}
},
"node_modules/follow-redirects": {
"version": "1.14.5",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz",
"integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==",
"version": "1.14.7",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==",
"funding": [
{
"type": "individual",
@ -778,9 +785,9 @@
}
},
"node_modules/fraction.js": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.1.tgz",
"integrity": "sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg==",
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz",
"integrity": "sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==",
"dev": true,
"engines": {
"node": "*"
@ -953,9 +960,9 @@
}
},
"node_modules/is-core-module": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz",
"integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==",
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz",
"integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==",
"dev": true,
"dependencies": {
"has": "^1.0.3"
@ -1059,12 +1066,6 @@
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true
},
"node_modules/lodash.uniq": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
"integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=",
"dev": true
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@ -1125,7 +1126,8 @@
"node_modules/monaco-editor": {
"version": "0.31.1",
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.31.1.tgz",
"integrity": "sha512-FYPwxGZAeP6mRRyrr5XTGHD9gRXVjy7GUzF4IPChnyt3fS5WrNxIkS8DNujWf6EQy0Zlzpxw8oTVE+mWI2/D1Q=="
"integrity": "sha512-FYPwxGZAeP6mRRyrr5XTGHD9gRXVjy7GUzF4IPChnyt3fS5WrNxIkS8DNujWf6EQy0Zlzpxw8oTVE+mWI2/D1Q==",
"peer": true
},
"node_modules/mousetrap": {
"version": "1.6.5",
@ -1133,9 +1135,9 @@
"integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA=="
},
"node_modules/nanoid": {
"version": "3.1.30",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.30.tgz",
"integrity": "sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==",
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz",
"integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==",
"dev": true,
"bin": {
"nanoid": "bin/nanoid.cjs"
@ -1247,9 +1249,9 @@
"dev": true
},
"node_modules/picomatch": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
"integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"engines": {
"node": ">=8.6"
@ -1259,14 +1261,14 @@
}
},
"node_modules/postcss": {
"version": "8.4.5",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz",
"integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==",
"version": "8.4.6",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz",
"integrity": "sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==",
"dev": true,
"dependencies": {
"nanoid": "^3.1.30",
"nanoid": "^3.2.0",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.1"
"source-map-js": "^1.0.2"
},
"engines": {
"node": "^10 || ^12 || >=14"
@ -1277,20 +1279,22 @@
}
},
"node_modules/postcss-js": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-3.0.3.tgz",
"integrity": "sha512-gWnoWQXKFw65Hk/mi2+WTQTHdPD5UJdDXZmX073EY/B3BWnYjO4F4t0VneTCnCGQ5E5GsCdMkzPaTXwl3r5dJw==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz",
"integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==",
"dev": true,
"dependencies": {
"camelcase-css": "^2.0.1",
"postcss": "^8.1.6"
"camelcase-css": "^2.0.1"
},
"engines": {
"node": ">=10.0"
"node": "^12 || ^14 || >= 16"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
"peerDependencies": {
"postcss": "^8.3.3"
}
},
"node_modules/postcss-load-config": {
@ -1339,9 +1343,9 @@
}
},
"node_modules/postcss-selector-parser": {
"version": "6.0.8",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.8.tgz",
"integrity": "sha512-D5PG53d209Z1Uhcc0qAZ5U3t5HagH3cxu+WLZ22jt3gLUpXM4eXXfiO14jiDWST3NNooX/E8wISfOhZ9eIjGTQ==",
"version": "6.0.9",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz",
"integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==",
"dev": true,
"dependencies": {
"cssesc": "^3.0.0",
@ -1352,9 +1356,9 @@
}
},
"node_modules/postcss-value-parser": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
"integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==",
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true
},
"node_modules/purgecss": {
@ -1422,13 +1426,17 @@
"integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
},
"node_modules/resolve": {
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
"version": "1.22.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
"integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
"dev": true,
"dependencies": {
"is-core-module": "^2.2.0",
"path-parse": "^1.0.6"
"is-core-module": "^2.8.1",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
"bin": {
"resolve": "bin/resolve"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@ -1453,21 +1461,6 @@
"node": ">=0.10.0"
}
},
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@ -1492,9 +1485,9 @@
}
},
"node_modules/source-map-js": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.1.tgz",
"integrity": "sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
"dev": true,
"engines": {
"node": ">=0.10.0"
@ -1512,33 +1505,44 @@
"node": ">=8"
}
},
"node_modules/supports-preserve-symlinks-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/tailwindcss": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.7.tgz",
"integrity": "sha512-rZdKNHtC64jcQncLoWOuCzj4lQDTAgLtgK3WmQS88tTdpHh9OwLqULTQxI3tw9AMJsqSpCKlmcjW/8CSnni6zQ==",
"version": "3.0.18",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.18.tgz",
"integrity": "sha512-ihPTpEyA5ANgZbwKlgrbfnzOp9R5vDHFWmqxB1PT8NwOGCOFVVMl+Ps1cQQ369acaqqf1BEF77roCwK0lvNmTw==",
"dev": true,
"dependencies": {
"arg": "^5.0.1",
"chalk": "^4.1.2",
"chokidar": "^3.5.2",
"chokidar": "^3.5.3",
"color-name": "^1.1.4",
"cosmiconfig": "^7.0.1",
"detective": "^5.2.0",
"didyoumean": "^1.2.2",
"dlv": "^1.1.3",
"fast-glob": "^3.2.7",
"fast-glob": "^3.2.11",
"glob-parent": "^6.0.2",
"is-glob": "^4.0.3",
"normalize-path": "^3.0.0",
"object-hash": "^2.2.0",
"postcss-js": "^3.0.3",
"postcss-js": "^4.0.0",
"postcss-load-config": "^3.1.0",
"postcss-nested": "5.0.6",
"postcss-selector-parser": "^6.0.7",
"postcss-selector-parser": "^6.0.9",
"postcss-value-parser": "^4.2.0",
"quick-lru": "^5.1.1",
"resolve": "^1.20.0",
"tmp": "^0.2.1"
"resolve": "^1.21.0"
},
"bin": {
"tailwind": "lib/cli.js",
@ -1552,24 +1556,6 @@
"postcss": "^8.0.9"
}
},
"node_modules/tailwindcss/node_modules/postcss-value-parser": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true
},
"node_modules/tmp": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
"integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
"dev": true,
"dependencies": {
"rimraf": "^3.0.0"
},
"engines": {
"node": ">=8.17.0"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@ -1636,9 +1622,9 @@
},
"dependencies": {
"@antv/x6": {
"version": "1.29.1",
"resolved": "https://registry.npmjs.org/@antv/x6/-/x6-1.29.1.tgz",
"integrity": "sha512-XSCtW1T/CIC0QUUUYW04EUQ5VnBMsShiNz9NP64oN8fAW14Jw99NKUhzToKpHGqQtVDg6qBX1UjFsfi0SUL4lg==",
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/@antv/x6/-/x6-1.30.0.tgz",
"integrity": "sha512-YYUSY1YdreTw4LxElQClXQqZ2msSefHZ2JFM9dM3NOMPn/VWNc6+GIvfxJ51HHWCNF23Hn126xxVBxYRu1zAuw==",
"requires": {
"csstype": "^3.0.3",
"jquery": "^3.5.1",
@ -1762,9 +1748,9 @@
}
},
"@stencil/core": {
"version": "2.12.0",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.12.0.tgz",
"integrity": "sha512-hQlQKh5CUJe8g3L5avLLsfgVu95HMS2LToTtS7gpvvP0eKes1VvAC56uhI+vH4u44GZl9ck/g1rJBVRmMWu0LA=="
"version": "2.13.0",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.13.0.tgz",
"integrity": "sha512-EEKHOHgYpg3/iFUKMXTZJjUayRul7sXDwNw0OGgkEOe4t7JWiibDkzUHuruvpbqEydX+z1+ez5K2bMMY76c2wA=="
},
"@stencil/postcss": {
"version": "2.1.0",
@ -1823,21 +1809,20 @@
}
},
"@tailwindcss/typography": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.0.tgz",
"integrity": "sha512-1p/3C6C+JJziS/ghtG8ACYalbA2SyLJY27Pm33cVTlAoY6VQ7zfm2H64cPxUMBkVIlWXTtWHhZcZJPobMRmQAA==",
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.1.tgz",
"integrity": "sha512-AmSzZSgLhHKlILKduU+PKBTHL6c+al82syZlRid1xgmlWwXagLigO+O++B4C0scpMfzW//f/3YCRcwwEHWoU3w==",
"dev": true,
"requires": {
"lodash.castarray": "^4.4.0",
"lodash.isplainobject": "^4.0.6",
"lodash.merge": "^4.6.2",
"lodash.uniq": "^4.5.0"
"lodash.merge": "^4.6.2"
}
},
"@types/jquery": {
"version": "3.5.11",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.11.tgz",
"integrity": "sha512-lYZGdfOtUa0XFjIATQgiogqeTY5PNNMOmp3Jq48ghmJALL8t/IqABRqlEwdHfuUdA8iIE1uGD1HoI4a7Tiy6OA==",
"version": "3.5.13",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.13.tgz",
"integrity": "sha512-ZxJrup8nz/ZxcU0vantG+TPdboMhB24jad2uSap50zE7Q9rUeYlCF25kFMSmHR33qoeOgqcdHEp3roaookC0Sg==",
"dev": true,
"requires": {
"@types/sizzle": "*"
@ -1913,25 +1898,25 @@
"dev": true
},
"autoprefixer": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.0.tgz",
"integrity": "sha512-7FdJ1ONtwzV1G43GDD0kpVMn/qbiNqyOPMFTX5nRffI+7vgWoFEc6DcXOxHJxrWNDXrZh18eDsZjvZGUljSRGA==",
"version": "10.4.2",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz",
"integrity": "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==",
"dev": true,
"requires": {
"browserslist": "^4.17.5",
"caniuse-lite": "^1.0.30001272",
"fraction.js": "^4.1.1",
"browserslist": "^4.19.1",
"caniuse-lite": "^1.0.30001297",
"fraction.js": "^4.1.2",
"normalize-range": "^0.1.2",
"picocolors": "^1.0.0",
"postcss-value-parser": "^4.1.0"
"postcss-value-parser": "^4.2.0"
}
},
"axios": {
"version": "0.24.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
"integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
"version": "0.25.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz",
"integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==",
"requires": {
"follow-redirects": "^1.14.4"
"follow-redirects": "^1.14.7"
}
},
"axios-middleware": {
@ -1972,13 +1957,13 @@
}
},
"browserslist": {
"version": "4.17.5",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.5.tgz",
"integrity": "sha512-I3ekeB92mmpctWBoLXe0d5wPS2cBuRvvW0JyyJHMrk9/HmP2ZjrTboNAZ8iuGqaEIlKguljbQY32OkOJIRrgoA==",
"version": "4.19.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz",
"integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30001271",
"electron-to-chromium": "^1.3.878",
"caniuse-lite": "^1.0.30001286",
"electron-to-chromium": "^1.4.17",
"escalade": "^3.1.1",
"node-releases": "^2.0.1",
"picocolors": "^1.0.0"
@ -1997,9 +1982,9 @@
"dev": true
},
"caniuse-lite": {
"version": "1.0.30001272",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001272.tgz",
"integrity": "sha512-DV1j9Oot5dydyH1v28g25KoVm7l8MTxazwuiH3utWiAS6iL/9Nh//TGwqFEeqqN8nnWYQ8HHhUq+o4QPt9kvYw==",
"version": "1.0.30001304",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001304.tgz",
"integrity": "sha512-bdsfZd6K6ap87AGqSHJP/s1V+U6Z5lyrcbBu3ovbCCf8cSYpwTtGrCBObMpJqwxfTbLW6YTIdbb1jEeTelcpYQ==",
"dev": true
},
"chalk": {
@ -2013,9 +1998,9 @@
}
},
"chokidar": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
"integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
"dev": true,
"requires": {
"anymatch": "~3.1.2",
@ -2125,9 +2110,9 @@
"integrity": "sha512-a23pEa7ahqLmBIEqtxi8CdL6CRLF52ZoAwawDFTD1IDkegrL4iValQAj6IMEgIEXPSrXZtx/Nr/ej6ebov4uoA=="
},
"electron-to-chromium": {
"version": "1.3.883",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.883.tgz",
"integrity": "sha512-goyjNx4wB9j911PBteb+AXNbErug7rJVkmDXWdw5SCVn2JlARBwsqucPkvp1h5mXWxHUbBRK3bwXTrqSxSiAIQ==",
"version": "1.4.59",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.59.tgz",
"integrity": "sha512-AOJ3cAE0TWxz4fQ9zkND5hWrQg16nsZKVz9INOot1oV//u4wWu5xrj9CQMmPTYskkZRunSRc9sAnr4EkexXokg==",
"dev": true
},
"error-ex": {
@ -2152,9 +2137,9 @@
"dev": true
},
"fast-glob": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz",
"integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==",
"version": "3.2.11",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
"integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
"dev": true,
"requires": {
"@nodelib/fs.stat": "^2.0.2",
@ -2194,14 +2179,14 @@
}
},
"follow-redirects": {
"version": "1.14.5",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz",
"integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA=="
"version": "1.14.7",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ=="
},
"fraction.js": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.1.tgz",
"integrity": "sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg==",
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz",
"integrity": "sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==",
"dev": true
},
"fs.realpath": {
@ -2329,9 +2314,9 @@
}
},
"is-core-module": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz",
"integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==",
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz",
"integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==",
"dev": true,
"requires": {
"has": "^1.0.3"
@ -2420,12 +2405,6 @@
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true
},
"lodash.uniq": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
"integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=",
"dev": true
},
"merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@ -2471,7 +2450,8 @@
"monaco-editor": {
"version": "0.31.1",
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.31.1.tgz",
"integrity": "sha512-FYPwxGZAeP6mRRyrr5XTGHD9gRXVjy7GUzF4IPChnyt3fS5WrNxIkS8DNujWf6EQy0Zlzpxw8oTVE+mWI2/D1Q=="
"integrity": "sha512-FYPwxGZAeP6mRRyrr5XTGHD9gRXVjy7GUzF4IPChnyt3fS5WrNxIkS8DNujWf6EQy0Zlzpxw8oTVE+mWI2/D1Q==",
"peer": true
},
"mousetrap": {
"version": "1.6.5",
@ -2479,9 +2459,9 @@
"integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA=="
},
"nanoid": {
"version": "3.1.30",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.30.tgz",
"integrity": "sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==",
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz",
"integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==",
"dev": true
},
"node-releases": {
@ -2563,30 +2543,29 @@
"dev": true
},
"picomatch": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
"integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true
},
"postcss": {
"version": "8.4.5",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz",
"integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==",
"version": "8.4.6",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz",
"integrity": "sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==",
"dev": true,
"requires": {
"nanoid": "^3.1.30",
"nanoid": "^3.2.0",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.1"
"source-map-js": "^1.0.2"
}
},
"postcss-js": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-3.0.3.tgz",
"integrity": "sha512-gWnoWQXKFw65Hk/mi2+WTQTHdPD5UJdDXZmX073EY/B3BWnYjO4F4t0VneTCnCGQ5E5GsCdMkzPaTXwl3r5dJw==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz",
"integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==",
"dev": true,
"requires": {
"camelcase-css": "^2.0.1",
"postcss": "^8.1.6"
"camelcase-css": "^2.0.1"
}
},
"postcss-load-config": {
@ -2610,9 +2589,9 @@
}
},
"postcss-selector-parser": {
"version": "6.0.8",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.8.tgz",
"integrity": "sha512-D5PG53d209Z1Uhcc0qAZ5U3t5HagH3cxu+WLZ22jt3gLUpXM4eXXfiO14jiDWST3NNooX/E8wISfOhZ9eIjGTQ==",
"version": "6.0.9",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz",
"integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==",
"dev": true,
"requires": {
"cssesc": "^3.0.0",
@ -2620,9 +2599,9 @@
}
},
"postcss-value-parser": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
"integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==",
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true
},
"purgecss": {
@ -2664,13 +2643,14 @@
"integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
},
"resolve": {
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
"version": "1.22.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
"integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
"dev": true,
"requires": {
"is-core-module": "^2.2.0",
"path-parse": "^1.0.6"
"is-core-module": "^2.8.1",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
}
},
"resolve-from": {
@ -2685,15 +2665,6 @@
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
"dev": true
},
"rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"requires": {
"glob": "^7.1.3"
}
},
"run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@ -2704,9 +2675,9 @@
}
},
"source-map-js": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.1.tgz",
"integrity": "sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
"dev": true
},
"supports-color": {
@ -2718,50 +2689,38 @@
"has-flag": "^4.0.0"
}
},
"supports-preserve-symlinks-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"dev": true
},
"tailwindcss": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.7.tgz",
"integrity": "sha512-rZdKNHtC64jcQncLoWOuCzj4lQDTAgLtgK3WmQS88tTdpHh9OwLqULTQxI3tw9AMJsqSpCKlmcjW/8CSnni6zQ==",
"version": "3.0.18",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.18.tgz",
"integrity": "sha512-ihPTpEyA5ANgZbwKlgrbfnzOp9R5vDHFWmqxB1PT8NwOGCOFVVMl+Ps1cQQ369acaqqf1BEF77roCwK0lvNmTw==",
"dev": true,
"requires": {
"arg": "^5.0.1",
"chalk": "^4.1.2",
"chokidar": "^3.5.2",
"chokidar": "^3.5.3",
"color-name": "^1.1.4",
"cosmiconfig": "^7.0.1",
"detective": "^5.2.0",
"didyoumean": "^1.2.2",
"dlv": "^1.1.3",
"fast-glob": "^3.2.7",
"fast-glob": "^3.2.11",
"glob-parent": "^6.0.2",
"is-glob": "^4.0.3",
"normalize-path": "^3.0.0",
"object-hash": "^2.2.0",
"postcss-js": "^3.0.3",
"postcss-js": "^4.0.0",
"postcss-load-config": "^3.1.0",
"postcss-nested": "5.0.6",
"postcss-selector-parser": "^6.0.7",
"postcss-selector-parser": "^6.0.9",
"postcss-value-parser": "^4.2.0",
"quick-lru": "^5.1.1",
"resolve": "^1.20.0",
"tmp": "^0.2.1"
},
"dependencies": {
"postcss-value-parser": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true
}
}
},
"tmp": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
"integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
"dev": true,
"requires": {
"rimraf": "^3.0.0"
"resolve": "^1.21.0"
}
},
"to-regex-range": {

View file

@ -23,11 +23,11 @@
"generate": "stencil generate"
},
"dependencies": {
"@antv/x6": "^1.29.1",
"@stencil/core": "^2.12.0",
"@antv/x6": "^1.30.0",
"@stencil/core": "^2.13.0",
"@stencil/state-tunnel": "^1.0.1",
"@stencil/store": "^1.5.0",
"axios": "^0.24.0",
"axios": "^0.25.0",
"axios-middleware": "^0.3.1",
"reflect-metadata": "^0.1.13",
"typedi": "^0.10.0",
@ -44,12 +44,12 @@
"@stencil/postcss": "^2.1.0",
"@stencil/sass": "^1.5.2",
"@tailwindcss/forms": "^0.4.0",
"@tailwindcss/typography": "^0.5.0",
"@types/jquery": "^3.5.11",
"@tailwindcss/typography": "^0.5.1",
"@types/jquery": "^3.5.13",
"@types/jquery-mousewheel": "^3.1.9",
"autoprefixer": "^10.4.0",
"postcss": "^8.4.5",
"tailwindcss": "^3.0.7"
"autoprefixer": "^10.4.2",
"postcss": "^8.4.6",
"tailwindcss": "^3.0.18"
},
"license": "MIT"
}

View file

@ -7,16 +7,17 @@
import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
import { ActionDefinition, ActionInvokedArgs, Activity, ActivityDescriptor, ActivitySelectedArgs, ContainerSelectedArgs, GraphUpdatedArgs, IntellisenseContext, SelectListItem, TabChangedArgs, TabDefinition, Trigger, TriggerDescriptor, Workflow, WorkflowInstance, WorkflowInstanceSummary, WorkflowSummary } from "./models";
import { ActivityUpdatedArgs, DeleteActivityRequestedArgs } from "./components/designer/activity-properties-editor/activity-properties-editor";
import { ContainerActivityComponent } from "./components/activities/container-activity-component";
import { AddActivityArgs } from "./components/designer/canvas/canvas";
import { NodeInputContext } from "./services/node-input-driver";
import { MenuItem } from "./components/shared/context-menu/models";
import { DropdownButtonItem, DropdownButtonOrigin } from "./components/shared/dropdown-button/models";
import { Graph } from "@antv/x6";
import { AddActivityArgs as AddActivityArgs1 } from "./components/designer/canvas/canvas";
import { ExpressionChangedArs } from "./components/designer/input-control-switch/input-control-switch";
import { MonacoLib, MonacoValueChangedArgs } from "./components/shared/monaco-editor/monaco-editor";
import { PagerData } from "./components/shared/pager/pager";
import { PanelPosition, PanelStateChangedArgs } from "./components/designer/panel/models";
import { Graph } from "@antv/x6";
import { TriggerDeselectedArgs, TriggerSelectedArgs, TriggersUpdatedArgs } from "./components/designer/trigger-container/trigger-container";
import { DeleteTriggerRequestedArgs, TriggerUpdatedArgs } from "./components/designer/trigger-properties-editor/trigger-properties-editor";
import { WorkflowUpdatedArgs } from "./components/designer/workflow-editor/workflow-editor";
@ -33,6 +34,7 @@ export namespace Components {
interface ElsaCanvas {
"addActivity": (args: AddActivityArgs) => Promise<void>;
"exportGraph": () => Promise<Activity>;
"getRootComponent": () => Promise<ContainerActivityComponent>;
"importGraph": (root: Activity) => Promise<void>;
"interactiveMode": boolean;
"updateLayout": () => Promise<void>;
@ -59,6 +61,7 @@ export namespace Components {
"activityDescriptors": Array<ActivityDescriptor>;
"addActivity": (args: AddActivityArgs) => Promise<void>;
"exportRoot": () => Promise<Activity>;
"getGraph": () => Promise<Graph>;
"importRoot": (root: Activity) => Promise<void>;
"interactiveMode": boolean;
"root"?: Activity;
@ -177,6 +180,7 @@ export namespace Components {
}
interface ElsaWorkflowEditor {
"activityDescriptors": Array<ActivityDescriptor>;
"getCanvas": () => Promise<HTMLElsaCanvasElement>;
"getWorkflow": () => Promise<Workflow>;
"importWorkflow": (workflow: Workflow, workflowInstance?: WorkflowInstance) => Promise<void>;
"importWorkflowMetadata": (workflow: Workflow) => Promise<void>;

View file

@ -1,5 +1,9 @@
import 'reflect-metadata';
import {Container} from "typedi"
import {camelCase} from "lodash";
import {Activity, ActivityDescriptor, Container} from "../../../models";
import {Activity, ActivityDescriptor} from "../../../models";
import {PortProviderRegistry} from "./port-provider-registry";
import {TransposeHandlerRegistry} from "./transpose-handler-registry";
export interface ActivityNode {
activity: Activity;
@ -13,11 +17,11 @@ export interface ActivityPort {
port: string;
}
export function walkActivities(root: Activity, descriptors: Array<ActivityDescriptor>, untranspose: boolean): ActivityNode {
export function walkActivities(root: Activity, descriptors: Array<ActivityDescriptor>): ActivityNode {
const collectedActivities = new Set<Activity>([root]);
const graph: ActivityNode = {activity: root, parents: [], children: []};
const collectedNodes = new Set<ActivityNode>([graph]);
walkRecursive(graph, root, collectedActivities, collectedNodes, descriptors, untranspose);
walkRecursive(graph, root, collectedActivities, collectedNodes, descriptors);
return graph;
}
@ -36,7 +40,7 @@ export function flattenList(activities: Array<ActivityNode>): Array<ActivityNode
return list;
}
function walkRecursive(node: ActivityNode, activity: Activity, collectedActivities: Set<Activity>, collectedNodes: Set<ActivityNode>, descriptors: Array<ActivityDescriptor>, untranspose: boolean) {
function walkRecursive(node: ActivityNode, activity: Activity, collectedActivities: Set<Activity>, collectedNodes: Set<ActivityNode>, descriptors: Array<ActivityDescriptor>) {
const ports = getPorts(node, activity, descriptors);
for (const port of ports) {
@ -45,42 +49,22 @@ function walkRecursive(node: ActivityNode, activity: Activity, collectedActiviti
if (!childNode) {
childNode = {activity: port.activity, children: [], parents: [], port: port.port};
if (untranspose) {
const propName = camelCase(port.port);
delete activity[propName];
}
collectedNodes.add(childNode);
}
childNode.parents.push(node);
node.children.push(childNode);
collectedActivities.add(port.activity);
walkRecursive(childNode, port.activity, collectedActivities, collectedNodes, descriptors, untranspose);
walkRecursive(childNode, port.activity, collectedActivities, collectedNodes, descriptors);
}
}
function getPorts(node: ActivityNode, activity: Activity, descriptors: Array<ActivityDescriptor>): Array<ActivityPort> {
const descriptor = descriptors.find(x => x.nodeType == activity.nodeType);
if (!descriptor)
return [];
let ports: Array<ActivityPort> = [];
for (const outPort of descriptor.outPorts) {
const outPortName = camelCase(outPort.name);
const outbound: Activity | Array<Activity> = activity[outPortName];
if (!!outbound) {
if (Array.isArray(outbound)) {
for (const a of outbound)
ports.push({activity: a, port: outPort.name});
} else
ports.push({activity: outbound, port: outPort.name});
}
}
return ports;
const portProviderRegistry = Container.get(PortProviderRegistry);
const transposeHandlerRegistry = Container.get(TransposeHandlerRegistry);
const transposeHandler = transposeHandlerRegistry.get(activity.nodeType);
const portProvider = portProviderRegistry.get(activity.nodeType);
const activityDescriptor = descriptors.find(x => x.nodeType == activity.nodeType);
const untransposedConnections = transposeHandler.untranspose({activity, activityDescriptor});
return untransposedConnections.map(x => ({activity: x.target, port: x.sourcePort}));
}

View file

@ -16,10 +16,22 @@ export class DefaultNodeHandler implements ActivityNodeHandler {
createDesignerNode(context: CreateUINodeContext): Node.Metadata {
const {activityDescriptor, activity, x, y} = context;
const provider = this.portProviderRegistry.get(activityDescriptor.nodeType);
const providerContext: PortProviderContext = { activityDescriptor, activity };
const providerContext: PortProviderContext = {activityDescriptor, activity};
let inPorts = provider.getInboundPorts(providerContext);
let outPorts = provider.getOutboundPorts(providerContext);
if (inPorts.length == 0)
inPorts = [{name: 'In', displayName: 'In'}];
if (inPorts.length == 1)
inPorts[0].displayName = null;
if (outPorts.length == 0)
outPorts = [{name: 'Done', displayName: 'Done'}];
if (outPorts.length == 1)
outPorts[0].displayName = null;
const inPortModels = inPorts.map(x => ({
id: x.name,
group: 'in',

View file

@ -7,27 +7,12 @@ import {PortProvider, PortProviderContext} from "./port-provider";
export class DefaultPortProvider implements PortProvider {
getInboundPorts(context: PortProviderContext): Array<Port> {
const {activityDescriptor} = context;
let inPorts: Array<Port> = [...activityDescriptor.inPorts];
if (inPorts.length == 0)
inPorts = [{name: 'In', displayName: 'In'}];
if (inPorts.length == 1)
inPorts[0].displayName = null;
return inPorts;
return [...activityDescriptor.inPorts];
}
getOutboundPorts(context: PortProviderContext): Array<Port> {
const {activityDescriptor} = context;
let outPorts: Array<Port> = [...activityDescriptor.outPorts];
outPorts = [...outPorts, {name: 'Done', displayName: 'Done'}];
if (outPorts.length == 1)
outPorts[0].displayName = null;
return outPorts;
return [...activityDescriptor.outPorts];
}
}

View file

@ -0,0 +1,47 @@
import 'reflect-metadata';
import {camelCase} from 'lodash';
import {Service} from "typedi"
import {TransposeContext, TransposeHandler, UntransposeContext, UntransposedConnection} from "./transpose-handler";
import {Activity, Port} from "../../../models";
@Service()
export class DefaultTransposeHandler implements TransposeHandler {
transpose(context: TransposeContext): boolean {
const {connection, source, target, sourceDescriptor} = context;
const matchingTargetPort = sourceDescriptor.outPorts.find(x => x.name == connection.sourcePort);
if (!matchingTargetPort)
return false;
// Assign the target activity directly to the outbound port of the source activity.
const outPortPropName = camelCase(connection.sourcePort);
source[outPortPropName] = target;
return true;
}
untranspose(context: UntransposeContext): Array<UntransposedConnection> {
const connections: Array<UntransposedConnection> = [];
const activityDescriptor = context.activityDescriptor;
const activity = context.activity;
const outPorts: Array<Port> = [...activityDescriptor.outPorts];
for (const port of outPorts) {
const propName = camelCase(port.name);
const source = activity;
const target: Activity | Array<Activity> = activity[propName];
delete activity[propName];
if (!!target) {
if (Array.isArray(target)) {
for (const a of target)
connections.push({source, target: a, sourcePort: port.name, targetPort: 'in'});
} else
connections.push({source, target, sourcePort: port.name, targetPort: 'in'});
}
}
return connections;
}
}

View file

@ -1,8 +1,8 @@
import 'reflect-metadata';
import {Component, Element, Event, EventEmitter, h, Method, Prop, Watch} from '@stencil/core';
import {Edge, Graph, Model, Node, NodeView, Segment} from '@antv/x6';
import {Edge, Graph, Model, Node, NodeView} from '@antv/x6';
import {v4 as uuid} from 'uuid';
import {camelCase, first} from 'lodash';
import {first} from 'lodash';
import './shapes';
import './ports';
import {ContainerActivityComponent} from '../container-activity-component';
@ -12,12 +12,13 @@ import {createGraph} from './graph-factory';
import {Connection, Flowchart} from './models';
import WorkflowEditorTunnel from '../../designer/state';
import {ActivityNode, flattenList, walkActivities} from "./activity-walker";
import PositionEventArgs = NodeView.PositionEventArgs;
import FromJSONData = Model.FromJSONData;
import {NodeFactory} from "./node-factory";
import {Container} from "typedi";
import {EventBus} from "../../../services";
import {ConnectionCreatedEventArgs, FlowchartEvents} from "./events";
import {TransposeHandlerRegistry} from "./transpose-handler-registry";
import PositionEventArgs = NodeView.PositionEventArgs;
import FromJSONData = Model.FromJSONData;
@Component({
tag: 'elsa-flowchart',
@ -47,6 +48,11 @@ export class FlowchartComponent implements ContainerActivityComponent {
@Event() containerSelected: EventEmitter<ContainerSelectedArgs>;
@Event() graphUpdated: EventEmitter<GraphUpdatedArgs>;
@Method()
public async getGraph(): Promise<Graph> {
return this.graph;
}
@Method()
public async updateLayout(): Promise<void> {
const width = this.el.clientWidth;
@ -149,19 +155,17 @@ export class FlowchartComponent implements ContainerActivityComponent {
const remainingConnections: Array<Connection> = []; // The connections remaining after transposition.
let remainingActivities: Array<Activity> = [...activities]; // The activities remaining after transposition.
const activityDescriptors = this.activityDescriptors;
const transposeHandlerRegistry = Container.get(TransposeHandlerRegistry);
// Transpose connections to activity outbound port properties.
for (const connection of connections) {
const source = activities.find(x => x.id == connection.source);
const target = activities.find(x => x.id == connection.target);
const sourceDescriptor = activityDescriptors.find(x => x.nodeType == source.nodeType);
const matchingTargetPort = sourceDescriptor.outPorts.find(x => x.name == connection.sourcePort);
if (!!matchingTargetPort) {
// Assign the target activity directly to the outbound port of the source activity.
const outPortPropName = camelCase(connection.sourcePort);
source[outPortPropName] = target;
const targetDescriptor = activityDescriptors.find(x => x.nodeType == target.nodeType);
const transposeHandler = transposeHandlerRegistry.get(source.nodeType);
if (transposeHandler.transpose({source, target, connection, sourceDescriptor, targetDescriptor})) {
// Remove the target activity from the list.
remainingActivities = remainingActivities.filter(x => x != target);
} else {
@ -185,8 +189,9 @@ export class FlowchartComponent implements ContainerActivityComponent {
this.rootId = root.id;
const descriptors = this.activityDescriptors;
const flowchart = root as Flowchart;
const flowchartGraph = walkActivities(flowchart, this.activityDescriptors, true);
const flowchartGraph = walkActivities(flowchart, this.activityDescriptors);
const flowchartNodes = flattenList(flowchartGraph.children);
const transposeHandlerRegistry = Container.get(TransposeHandlerRegistry);
// Clear inbound port for start activity.
const startActivityNode = flowchartNodes.find(x => x.activity.id === flowchart.start);
@ -194,27 +199,27 @@ export class FlowchartComponent implements ContainerActivityComponent {
if (startActivityNode.port)
delete startActivityNode.port;
const nodes: Array<Node.Metadata> = [];
let edges: Array<Edge.Metadata> = [];
// Create an X6 node for each activity.
for (const activityNode of flowchartNodes) {
const nodes: Array<Node.Metadata> = flowchartNodes.map(activityNode => {
const activity = activityNode.activity;
const position = activity.metadata.designer?.position || {x: 100, y: 100};
const {x, y} = position;
const descriptor = descriptors.find(x => x.nodeType == activity.nodeType)
const node = this.nodeFactory.createNode(descriptor, activity, x, y);
return this.nodeFactory.createNode(descriptor, activity, x, y);
});
nodes.push(node);
// Create X6 edges for each child activity.
const childEdges = this.createEdges(flowchartNodes, activityNode);
// Create X6 edges for each child activity.
for (const rootNodes of flowchartNodes) {
const childEdges = this.createEdges(rootNodes);
edges = [...edges, ...childEdges];
}
// Create X6 edges for each connection in the flowchart.
for (const connection of flowchart.connections) {
const edge: Edge.Metadata = this.createEdge(flowchartNodes, connection);
const edge: Edge.Metadata = this.createEdge(connection);
edges.push(edge);
}
@ -226,11 +231,11 @@ export class FlowchartComponent implements ContainerActivityComponent {
this.graph.unfreeze();
};
private createEdges = (allNodes: Array<ActivityNode>, activityNode: ActivityNode): Array<Edge.Metadata> => {
private createEdges = (activityNode: ActivityNode): Array<Edge.Metadata> => {
let edges: Array<Edge.Metadata> = [];
for (const childNode of activityNode.children) {
const edge = this.createEdge(allNodes, {
const edge = this.createEdge({
source: activityNode.activity.id,
sourcePort: childNode.port,
target: childNode.activity.id,
@ -243,7 +248,18 @@ export class FlowchartComponent implements ContainerActivityComponent {
return edges;
}
private createEdge = (allNodes: Array<ActivityNode>, connection: Connection): Edge.Metadata => {
// private createEdges = (connections: Array<Connection>): Array<Edge.Metadata> => {
// let edges: Array<Edge.Metadata> = [];
//
// for (const connection of connections) {
// const edge = this.createEdge(connection);
// edges.push(edge);
// }
//
// return edges;
// }
private createEdge = (connection: Connection): Edge.Metadata => {
return {
shape: 'elsa-edge',
zIndex: -1,

View file

@ -10,7 +10,7 @@ export class PortProviderRegistry {
private map: Map<string, PortProviderFactory> = new Map<string, PortProviderFactory>();
private defaultProviderFactory: PortProviderFactory = () => Container.get(DefaultPortProvider);
public register(activityType: string, defaultProviderFactory: PortProviderFactory) {
public add(activityType: string, defaultProviderFactory: PortProviderFactory) {
this.map.set(activityType, defaultProviderFactory);
}

View file

@ -0,0 +1,21 @@
import 'reflect-metadata';
import {Container, Service} from "typedi";
import {TransposeHandler} from "./transpose-handler";
import {DefaultTransposeHandler} from "./default-transpose-handler";
export type TransposeHandlerFactory = () => TransposeHandler;
@Service()
export class TransposeHandlerRegistry {
private map: Map<string, TransposeHandlerFactory> = new Map<string, TransposeHandlerFactory>();
private defaultHandlerFactory: TransposeHandlerFactory = () => Container.get(DefaultTransposeHandler);
public add(activityType: string, handlerFactory: TransposeHandlerFactory) {
this.map.set(activityType, handlerFactory);
}
public get(activityType: string): TransposeHandler {
const factory = this.map.get(activityType) ?? this.defaultHandlerFactory;
return factory();
}
}

View file

@ -0,0 +1,29 @@
import {Connection} from "./models";
import {Activity, ActivityDescriptor} from "../../../models";
import {ActivityNode} from "./activity-walker";
export interface TransposeHandler {
transpose: (context: TransposeContext) => boolean;
untranspose: (context: UntransposeContext) => Array<UntransposedConnection>;
}
export interface TransposeContext {
connection: Connection;
source: Activity;
target: Activity;
sourceDescriptor: ActivityDescriptor;
targetDescriptor: ActivityDescriptor;
}
export interface UntransposeContext {
//activityNode: ActivityNode;
activity: Activity;
activityDescriptor: ActivityDescriptor;
}
export interface UntransposedConnection {
source: Activity;
sourcePort: string;
target: Activity;
targetPort: string;
}

View file

@ -17,6 +17,9 @@ import {FormEntry} from "../../shared/forms/form-entry";
export interface ActivityUpdatedArgs {
activity: Activity;
activityDescriptor: ActivityDescriptor;
propertyName: string;
inputDescriptor: InputDescriptor;
}
export interface DeleteActivityRequestedArgs {
@ -63,7 +66,7 @@ export class ActivityPropertiesEditor {
node: activity,
nodeDescriptor: activityDescriptor,
inputDescriptor,
notifyInputChanged: () => this.activityUpdated.emit({activity}),
notifyInputChanged: () => this.activityUpdated.emit({activity, activityDescriptor, propertyName: camelCase(inputDescriptor.name), inputDescriptor}),
inputChanged: (v, s) => this.onPropertyEditorChanged(inputDescriptor, v, s)
};
@ -116,12 +119,19 @@ export class ActivityPropertiesEditor {
const inputElement = e.target as HTMLInputElement;
activity.id = inputElement.value;
this.activityUpdated.emit({activity: activity});
const activityDescriptor = this.findActivityDescriptor();
const inputDescriptor: InputDescriptor = {
name: 'Id',
displayName: 'Id',
type: 'string'
};
this.activityUpdated.emit({activity, activityDescriptor, propertyName: 'id', inputDescriptor});
}
private onPropertyEditorChanged = (inputDescriptor: InputDescriptor, propertyValue: any, syntax: string) => {
const activity = this.activity;
const propertyName = inputDescriptor.name;
const activityDescriptor = this.findActivityDescriptor();
const camelCasePropertyName = camelCase(propertyName);
activity[camelCasePropertyName] = {
@ -132,7 +142,7 @@ export class ActivityPropertiesEditor {
}
};
this.activityUpdated.emit({activity: activity});
this.activityUpdated.emit({activity, activityDescriptor, propertyName: camelCasePropertyName, inputDescriptor});
}
private onDeleteActivity = () => this.deleteActivityRequested.emit({activity: this.activity});

View file

@ -18,6 +18,11 @@ export class Canvas {
@Prop() public interactiveMode: boolean = true;
@Method()
public async getRootComponent(): Promise<ContainerActivityComponent> {
return this.root;
}
@Method()
public async addActivity(args: AddActivityArgs): Promise<void> {
await this.root.addActivity(args);

View file

@ -1,12 +1,12 @@
import {Component, h, Listen, Prop, State, Event, EventEmitter, Method, Watch} from '@stencil/core';
import {Component, h, Listen, Prop, State, Event, EventEmitter, Method, Watch, Element} from '@stencil/core';
import {debounce} from 'lodash';
import {v4 as uuid} from 'uuid';
import {Container} from "typedi";
import {PanelPosition, PanelStateChangedArgs} from '../panel/models';
import {
Activity,
ActivityDescriptor,
ActivitySelectedArgs, ContainerSelectedArgs,
ActivityDescriptor, ActivityPropertyChangedEventArgs,
ActivitySelectedArgs, ContainerSelectedArgs, EventTypes,
GraphUpdatedArgs, Trigger,
TriggerDescriptor,
Workflow, WorkflowInstance
@ -16,7 +16,7 @@ import {
ActivityUpdatedArgs,
DeleteActivityRequestedArgs
} from '../activity-properties-editor/activity-properties-editor';
import {ActivityDriverRegistry} from '../../../services';
import {ActivityDriverRegistry, EventBus} from '../../../services';
import {TriggerSelectedArgs, TriggersUpdatedArgs} from '../trigger-container/trigger-container';
import {DeleteTriggerRequestedArgs, TriggerUpdatedArgs} from "../trigger-properties-editor/trigger-properties-editor";
import {WorkflowPropsUpdatedArgs} from "../workflow-properties-editor/workflow-properties-editor";
@ -33,6 +33,7 @@ export interface WorkflowUpdatedArgs {
})
export class WorkflowEditor {
private readonly pluginRegistry: PluginRegistry;
private readonly eventBus: EventBus;
private canvas: HTMLElsaCanvasElement;
private container: HTMLDivElement;
private toolbox: HTMLElsaToolboxElement;
@ -41,6 +42,7 @@ export class WorkflowEditor {
private deleteActivity: (activity: Activity) => void;
private applyTriggerChanges: (trigger: Trigger) => void;
private deleteTrigger: (trigger: Trigger) => void;
private readonly emitActivityChangedDebounced: (e: ActivityPropertyChangedEventArgs) => void;
private readonly saveChangesDebounced: () => void;
private workflow: Workflow = {
@ -54,10 +56,13 @@ export class WorkflowEditor {
private workflowInstance?: WorkflowInstance;
constructor() {
this.eventBus = Container.get(EventBus);
this.pluginRegistry = Container.get(PluginRegistry);
this.emitActivityChangedDebounced = debounce(this.emitActivityChanged, 100);
this.saveChangesDebounced = debounce(this.saveChanges, 1000);
}
@Element() el: HTMLElsaWorkflowEditorElement;
@Prop({attribute: 'monaco-lib-path'}) public monacoLibPath: string;
@Prop() public activityDescriptors: Array<ActivityDescriptor> = [];
@Prop() public triggerDescriptors: Array<TriggerDescriptor> = [];
@ -87,14 +92,14 @@ export class WorkflowEditor {
}
@Listen('containerSelected')
async handleContainerSelected(e: CustomEvent<ContainerSelectedArgs>) {
private async handleContainerSelected(e: CustomEvent<ContainerSelectedArgs>) {
this.selectedActivity = null;
this.selectedTrigger = null;
await this.triggerContainer.deselectAll();
}
@Listen('activitySelected')
async handleActivitySelected(e: CustomEvent<ActivitySelectedArgs>) {
private async handleActivitySelected(e: CustomEvent<ActivitySelectedArgs>) {
this.selectedActivity = e.detail.activity;
this.selectedTrigger = null;
await this.triggerContainer.deselectAll();
@ -103,7 +108,7 @@ export class WorkflowEditor {
}
@Listen('triggerSelected')
async handleTriggerSelected(e: CustomEvent<TriggerSelectedArgs>) {
private async handleTriggerSelected(e: CustomEvent<TriggerSelectedArgs>) {
this.selectedTrigger = e.detail.trigger;
this.selectedActivity = null;
this.applyTriggerChanges = e.detail.applyChanges;
@ -111,35 +116,41 @@ export class WorkflowEditor {
}
@Listen('triggerDeselected')
async handleTriggerDeselected(e: CustomEvent<TriggerSelectedArgs>) {
private async handleTriggerDeselected(e: CustomEvent<TriggerSelectedArgs>) {
this.selectedTrigger = null;
}
@Listen('graphUpdated')
handleGraphUpdated(e: CustomEvent<GraphUpdatedArgs>) {
private handleGraphUpdated(e: CustomEvent<GraphUpdatedArgs>) {
if (this.interactiveMode)
this.saveChangesDebounced();
}
@Method()
async registerActivityDrivers(register: (registry: ActivityDriverRegistry) => void): Promise<void> {
public async getCanvas(): Promise<HTMLElsaCanvasElement> {
return this.canvas;
}
@Method()
public async registerActivityDrivers(register: (registry: ActivityDriverRegistry) => void): Promise<void> {
const registry = Container.get(ActivityDriverRegistry);
register(registry);
}
@Method() getWorkflow(): Promise<Workflow> {
@Method()
public getWorkflow(): Promise<Workflow> {
return this.getWorkflowInternal();
}
@Method()
async importWorkflow(workflow: Workflow, workflowInstance?: WorkflowInstance): Promise<void> {
public async importWorkflow(workflow: Workflow, workflowInstance?: WorkflowInstance): Promise<void> {
this.workflowInstance = workflowInstance;
await this.importWorkflowMetadata(workflow);
await this.canvas.importGraph(workflow.root);
}
@Method()
async importWorkflowMetadata(workflow: Workflow): Promise<void> {
public async importWorkflowMetadata(workflow: Workflow): Promise<void> {
this.workflow = workflow;
this.triggers = workflow.triggers;
}
@ -218,6 +229,10 @@ export class WorkflowEditor {
return workflow;
};
private emitActivityChanged = async (activity: Activity, propertyName: string) => {
await this.eventBus.emit(EventTypes.Activity.PropertyChanged, this, activity, propertyName, this);
};
private saveChanges = async (): Promise<void> => {
const workflow = await this.getWorkflowInternal();
this.workflowUpdated.emit({workflow});
@ -261,6 +276,7 @@ export class WorkflowEditor {
private onActivityUpdated = (e: CustomEvent<ActivityUpdatedArgs>) => {
const updatedActivity = e.detail.activity;
this.applyActivityChanges(updatedActivity);
this.emitActivityChangedDebounced({...e.detail, workflowEditor: this.el});
this.saveChangesDebounced();
}

View file

@ -35,12 +35,12 @@ export interface NodePropertyDescriptor {
type: Type;
displayName?: string;
description?: string;
order: number;
order?: number;
isBrowsable?: boolean;
}
export interface InputDescriptor extends NodePropertyDescriptor {
uiHint: string;
uiHint?: string;
options?: any;
category?: string;
defaultValue?: any;

View file

@ -1,4 +1,5 @@
import {Activity} from "./core";
import {ActivityDescriptor, InputDescriptor} from "./api";
export interface ActivitySelectedArgs {
activity: Activity;
@ -12,3 +13,11 @@ export interface ContainerSelectedArgs {
export interface GraphUpdatedArgs {
exportGraph: () => Activity;
}
export interface ActivityPropertyChangedEventArgs {
activity: Activity;
activityDescriptor: ActivityDescriptor;
propertyName: string;
inputDescriptor: InputDescriptor;
workflowEditor: HTMLElsaWorkflowEditorElement;
}

View file

@ -2,5 +2,8 @@
HttpClient: {
ConfigCreated: 'http-client:config-created',
ClientCreated: 'http-client:created',
},
Activity: {
PropertyChanged: 'activity:property-changed'
}
};

View file

@ -3,8 +3,9 @@ import {Activity, ActivityInput, Expression} from "../../models";
export interface SwitchCase {
label: string;
condition: Expression;
activity?: Activity;
}
export interface SwitchActivity extends Activity {
cases: ActivityInput;
cases: Array<SwitchCase>;
}

View file

@ -4,18 +4,28 @@ import {Container, Service} from "typedi";
import {ActivityDriverRegistry, InputControlRegistry} from "../../services";
import {Plugin} from "../../models";
import {SwitchActivityDriver} from "./switch-activity-driver";
import {PortProviderRegistry} from "../../components/activities/flowchart/port-provider-registry";
import {SwitchPortProvider} from "./switch-port-provider";
import {SwitchPortUpdater} from "./switch-port-updater";
import {TransposeHandlerRegistry} from "../../components/activities/flowchart/transpose-handler-registry";
import {SwitchTransposeHandler} from "./switch-transpose-handler";
@Service()
export class SwitchPlugin implements Plugin {
private static readonly ActivityTypeName: string = 'ControlFlow.Switch';
public static readonly ActivityTypeName: string = 'ControlFlow.Switch';
constructor() {
const activityTypeName = SwitchPlugin.ActivityTypeName;
const driverRegistry = Container.get(ActivityDriverRegistry);
const inputControlRegistry = Container.get(InputControlRegistry);
const portProviderRegistry = Container.get(PortProviderRegistry);
const switchPortUpdater = Container.get(SwitchPortUpdater);
const transposeHandlerRegistry = Container.get(TransposeHandlerRegistry);
driverRegistry.add(activityTypeName, () => Container.get(SwitchActivityDriver));
inputControlRegistry.add('switch-editor', c => <elsa-switch-editor inputContext={c}/>);
portProviderRegistry.add(activityTypeName, () => Container.get(SwitchPortProvider));
transposeHandlerRegistry.add(activityTypeName, () => Container.get(SwitchTransposeHandler));
}
}

View file

@ -1,13 +1,20 @@
import 'reflect-metadata';
import {Service} from "typedi";
import {PortProvider, PortProviderContext} from "../../components/activities/flowchart/port-provider";
import {Port} from "../../models";
import {SwitchActivity} from "./models";
@Service()
export class SwitchPortProvider implements PortProvider {
getInboundPorts(context: PortProviderContext): Array<Port> {
return undefined;
public getInboundPorts(context: PortProviderContext): Array<Port> {
return [{name: 'In', displayName: 'In'}];
}
getOutboundPorts(context: PortProviderContext): Array<Port> {
return undefined;
}
public getOutboundPorts(context: PortProviderContext): Array<Port> {
const activity = context.activity as SwitchActivity;
const cases = activity.cases;
return cases.map(x => ({name: x.label, displayName: x.label}));
}
}

View file

@ -0,0 +1,58 @@
import 'reflect-metadata';
import {Container, Service} from "typedi";
import {PortProvider, PortProviderContext} from "../../components/activities/flowchart/port-provider";
import {Activity, ActivityPropertyChangedEventArgs, EventTypes, Port} from "../../models";
import {SwitchActivity} from "./models";
import {EventBus} from "../../services";
import {SwitchPlugin} from "./switch-plugin";
@Service()
export class SwitchPortUpdater {
constructor() {
const eventBus = Container.get(EventBus);
eventBus.on(EventTypes.Activity.PropertyChanged, this.onActivityPropertyChanged);
}
private onActivityPropertyChanged = async (e: ActivityPropertyChangedEventArgs) => {
const activity = e.activity;
const propertyName = e.propertyName;
if (activity.nodeType !== SwitchPlugin.ActivityTypeName || propertyName !== 'cases')
return;
const switchActivity = activity as SwitchActivity;
const cases = switchActivity.cases;
const workflowEditor = e.workflowEditor;
const canvas = await workflowEditor.getCanvas();
const flowChart = (await canvas.getRootComponent()) as HTMLElsaFlowchartElement;
const graph = await flowChart.getGraph();
const node = graph.getNodes().find(x => x.data.id === activity.id);
if (!node)
return;
// Remove ports.
const ports = [...node.getPortsByGroup('out')];
for (const port of ports) {
if (cases.find(x => x.label == port.id) == null)
node.removePort(port);
}
// Add new ports.
for (const c of cases) {
if (!node.hasPort(c.label))
node.addPort({
id: c.label, group: 'out', attrs: {
text: {
text: c.label
}
}
})
}
}
}

View file

@ -0,0 +1,38 @@
import 'reflect-metadata';
import {Service} from "typedi"
import {TransposeContext, TransposeHandler, UntransposeContext, UntransposedConnection} from "../../components/activities/flowchart/transpose-handler";
import {SwitchActivity} from "./models";
@Service()
export class SwitchTransposeHandler implements TransposeHandler {
transpose(context: TransposeContext): boolean {
const {connection, source, target, sourceDescriptor} = context;
const switchActivity = source as SwitchActivity;
const cases = switchActivity.cases;
const matchingCase = cases.find(x => x.label == connection.sourcePort);
if (!matchingCase)
return false;
// Assign the target activity directly to the switch case.
matchingCase.activity = target;
return true;
}
untranspose(context: UntransposeContext): Array<UntransposedConnection> {
const activity = context.activity as SwitchActivity;
const connections: Array<UntransposedConnection> = [];
for (const switchCase of activity.cases) {
const target = switchCase.activity;
delete switchCase.activity;
if (!!target)
connections.push({source: activity, sourcePort: switchCase.label, target: target, targetPort: 'in'});
}
return connections;
}
}