mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
refactor(editor): Migrate part of the vuex store to pinia (#4484)
* ✨ Added pinia support. Migrated community nodes module. * ✨ Added ui pinia store, moved some data from root store to it, updated modals to work with pinia stores * ✨ Added ui pinia store and migrated a part of the root store * ✨ Migrated `settings` store to pinia * ✨ Removing vuex store refs from router * ✨ Migrated `users` module to pinia store * ⚡ Fixing errors after sync with master * ⚡ One more error after merge * ⚡ Created `workflows` pinia store. Moved large part of root store to it. Started updating references. * ✨ Finished migrating workflows store to pinia * ⚡ Renaming some getters and actions to make more sense * ✨ Finished migrating the root store to pinia * ✨ Migrated ndv store to pinia * ⚡ Renaming main panel dimensions getter so it doesn't clash with data prop name * ✔️ Fixing lint errors * ✨ Migrated `templates` store to pinia * ✨ Migrated the `nodeTypes`store * ⚡ Removed unused pieces of code and oold vuex modules * ✨ Adding vuex calls to pinia store, fi xing wrong references * 💄 Removing leftover $store refs * ⚡ Added legacy getters and mutations to store to support webhooks * ⚡ Added missing front-end hooks, updated vuex state subscriptions to pinia * ✔️ Fixing linting errors * ⚡ Removing vue composition api plugin * ⚡ Fixing main sidebar state when loading node view * 🐛 Fixing an error when activating workflows * 🐛 Fixing isses with workflow settings and executions auto-refresh * 🐛 Removing duplicate listeners which cause import error * 🐛 Fixing route authentication * ⚡ Updating freshly pulled $store refs * Adding deleted const * ⚡ Updating store references in ee features. Reseting NodeView credentials update flag when resetting workspace * ⚡ Adding return type to email submission modal * ⚡ Making NodeView only react to paste event when active * 🐛 Fixing signup view errors * 👌 Addressing PR review comments * 👌 Addressing new PR comments * 👌 Updating invite id logic in signup view
This commit is contained in:
parent
c2c7927414
commit
40e413d958
100
package-lock.json
generated
100
package-lock.json
generated
|
@ -9090,6 +9090,11 @@
|
||||||
"yallist": "^2.1.2"
|
"yallist": "^2.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@vue/devtools-api": {
|
||||||
|
"version": "6.4.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.4.5.tgz",
|
||||||
|
"integrity": "sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ=="
|
||||||
|
},
|
||||||
"node_modules/@vue/eslint-config-typescript": {
|
"node_modules/@vue/eslint-config-typescript": {
|
||||||
"version": "11.0.2",
|
"version": "11.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-11.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-11.0.2.tgz",
|
||||||
|
@ -27057,6 +27062,31 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pinia": {
|
||||||
|
"version": "2.0.23",
|
||||||
|
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.23.tgz",
|
||||||
|
"integrity": "sha512-N15hFf4o5STrxpNrib1IEb1GOArvPYf1zPvQVRGOO1G1d74Ak0J0lVyalX/SmrzdT4Q0nlEFjbURsmBmIGUR5Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/devtools-api": "^6.4.4",
|
||||||
|
"vue-demi": "*"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/posva"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vue/composition-api": "^1.4.0",
|
||||||
|
"typescript": ">=4.4.4",
|
||||||
|
"vue": "^2.6.14 || ^3.2.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vue/composition-api": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"typescript": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/pinkie": {
|
"node_modules/pinkie": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
|
||||||
|
@ -35718,6 +35748,31 @@
|
||||||
"tinycolor2": "^1.1.2"
|
"tinycolor2": "^1.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vue-demi": {
|
||||||
|
"version": "0.13.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz",
|
||||||
|
"integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"bin": {
|
||||||
|
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||||
|
"vue-demi-switch": "bin/vue-demi-switch.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vue/composition-api": "^1.0.0-rc.1",
|
||||||
|
"vue": "^3.0.0-0 || ^2.6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vue/composition-api": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vue-docgen-api": {
|
"node_modules/vue-docgen-api": {
|
||||||
"version": "4.54.2",
|
"version": "4.54.2",
|
||||||
"resolved": "https://registry.npmjs.org/vue-docgen-api/-/vue-docgen-api-4.54.2.tgz",
|
"resolved": "https://registry.npmjs.org/vue-docgen-api/-/vue-docgen-api-4.54.2.tgz",
|
||||||
|
@ -38517,6 +38572,7 @@
|
||||||
"n8n-design-system": "~0.40.0",
|
"n8n-design-system": "~0.40.0",
|
||||||
"n8n-workflow": "~0.122.1",
|
"n8n-workflow": "~0.122.1",
|
||||||
"normalize-wheel": "^1.0.1",
|
"normalize-wheel": "^1.0.1",
|
||||||
|
"pinia": "^2.0.22",
|
||||||
"prismjs": "^1.17.1",
|
"prismjs": "^1.17.1",
|
||||||
"quill": "2.0.0-dev.4",
|
"quill": "2.0.0-dev.4",
|
||||||
"quill-autoformat": "^0.1.1",
|
"quill-autoformat": "^0.1.1",
|
||||||
|
@ -42784,7 +42840,7 @@
|
||||||
"functional-red-black-tree": "^1.0.1",
|
"functional-red-black-tree": "^1.0.1",
|
||||||
"glob-parent": "^6.0.1",
|
"glob-parent": "^6.0.1",
|
||||||
"globals": "^13.15.0",
|
"globals": "^13.15.0",
|
||||||
"globby": "^11.0.2",
|
"globby": "^11.1.0",
|
||||||
"grapheme-splitter": "^1.0.4",
|
"grapheme-splitter": "^1.0.4",
|
||||||
"ignore": "^5.2.0",
|
"ignore": "^5.2.0",
|
||||||
"import-fresh": "^3.0.0",
|
"import-fresh": "^3.0.0",
|
||||||
|
@ -43016,7 +43072,7 @@
|
||||||
"@oclif/errors": "^1.3.6",
|
"@oclif/errors": "^1.3.6",
|
||||||
"@oclif/parser": "^3.8.8",
|
"@oclif/parser": "^3.8.8",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"globby": "^11.0.2",
|
"globby": "^11.1.0",
|
||||||
"is-wsl": "^2.1.1",
|
"is-wsl": "^2.1.1",
|
||||||
"tslib": "^2.3.1"
|
"tslib": "^2.3.1"
|
||||||
},
|
},
|
||||||
|
@ -43042,10 +43098,10 @@
|
||||||
"clean-stack": "^3.0.1",
|
"clean-stack": "^3.0.1",
|
||||||
"cli-progress": "^3.10.0",
|
"cli-progress": "^3.10.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"ejs": "^3.1.8",
|
"ejs": "^3.1.6",
|
||||||
"fs-extra": "^9.1.0",
|
"fs-extra": "^9.1.0",
|
||||||
"get-package-type": "^0.1.0",
|
"get-package-type": "^0.1.0",
|
||||||
"globby": "^11.0.2",
|
"globby": "^11.1.0",
|
||||||
"hyperlinker": "^1.0.0",
|
"hyperlinker": "^1.0.0",
|
||||||
"indent-string": "^4.0.0",
|
"indent-string": "^4.0.0",
|
||||||
"is-wsl": "^2.2.0",
|
"is-wsl": "^2.2.0",
|
||||||
|
@ -43262,7 +43318,7 @@
|
||||||
"@oclif/errors": "^1.3.3",
|
"@oclif/errors": "^1.3.3",
|
||||||
"@oclif/parser": "^3.8.0",
|
"@oclif/parser": "^3.8.0",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"globby": "^11.0.2",
|
"globby": "^11.0.1",
|
||||||
"is-wsl": "^2.1.1",
|
"is-wsl": "^2.1.1",
|
||||||
"tslib": "^2.0.0"
|
"tslib": "^2.0.0"
|
||||||
}
|
}
|
||||||
|
@ -43855,7 +43911,7 @@
|
||||||
"css-loader": "^3.6.0",
|
"css-loader": "^3.6.0",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"find-up": "^5.0.0",
|
"find-up": "^5.0.0",
|
||||||
"fork-ts-checker-webpack-plugin": "^6.0.4",
|
"fork-ts-checker-webpack-plugin": "^4.1.6",
|
||||||
"glob": "^7.1.6",
|
"glob": "^7.1.6",
|
||||||
"glob-promise": "^3.4.0",
|
"glob-promise": "^3.4.0",
|
||||||
"global": "^4.4.0",
|
"global": "^4.4.0",
|
||||||
|
@ -45971,7 +46027,7 @@
|
||||||
"@typescript-eslint/types": "5.42.0",
|
"@typescript-eslint/types": "5.42.0",
|
||||||
"@typescript-eslint/visitor-keys": "5.42.0",
|
"@typescript-eslint/visitor-keys": "5.42.0",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"globby": "^11.0.2",
|
"globby": "^11.1.0",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
"semver": "^7.3.7",
|
"semver": "^7.3.7",
|
||||||
"tsutils": "^3.21.0"
|
"tsutils": "^3.21.0"
|
||||||
|
@ -46249,6 +46305,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@vue/devtools-api": {
|
||||||
|
"version": "6.4.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.4.5.tgz",
|
||||||
|
"integrity": "sha512-JD5fcdIuFxU4fQyXUu3w2KpAJHzTVdN+p4iOX2lMWSHMOoQdMAcpFLZzm9Z/2nmsoZ1a96QEhZ26e50xLBsgOQ=="
|
||||||
|
},
|
||||||
"@vue/eslint-config-typescript": {
|
"@vue/eslint-config-typescript": {
|
||||||
"version": "11.0.2",
|
"version": "11.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-11.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-11.0.2.tgz",
|
||||||
|
@ -47273,7 +47334,7 @@
|
||||||
"integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==",
|
"integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"browserslist": "^4.21.3",
|
"browserslist": "^4.12.0",
|
||||||
"caniuse-lite": "^1.0.30001109",
|
"caniuse-lite": "^1.0.30001109",
|
||||||
"normalize-range": "^0.1.2",
|
"normalize-range": "^0.1.2",
|
||||||
"num2fraction": "^1.2.2",
|
"num2fraction": "^1.2.2",
|
||||||
|
@ -49868,7 +49929,7 @@
|
||||||
"integrity": "sha512-piOX9Go+Z4f9ZiBFLnZ5VrOpBl0h7IGCkiFUN11QTe6LjAvOT3ifL/5TdoizMh99hcGy5SoLyWbapIY/PIb/3A==",
|
"integrity": "sha512-piOX9Go+Z4f9ZiBFLnZ5VrOpBl0h7IGCkiFUN11QTe6LjAvOT3ifL/5TdoizMh99hcGy5SoLyWbapIY/PIb/3A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"browserslist": "^4.21.3"
|
"browserslist": "^4.21.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"core-js-pure": {
|
"core-js-pure": {
|
||||||
|
@ -49936,7 +49997,7 @@
|
||||||
"requires": {
|
"requires": {
|
||||||
"arrify": "^2.0.1",
|
"arrify": "^2.0.1",
|
||||||
"cp-file": "^7.0.0",
|
"cp-file": "^7.0.0",
|
||||||
"globby": "^11.0.2",
|
"globby": "^9.2.0",
|
||||||
"has-glob": "^1.0.0",
|
"has-glob": "^1.0.0",
|
||||||
"junk": "^3.1.0",
|
"junk": "^3.1.0",
|
||||||
"nested-error-stacks": "^2.1.0",
|
"nested-error-stacks": "^2.1.0",
|
||||||
|
@ -58963,6 +59024,7 @@
|
||||||
"n8n-design-system": "~0.40.0",
|
"n8n-design-system": "~0.40.0",
|
||||||
"n8n-workflow": "~0.122.1",
|
"n8n-workflow": "~0.122.1",
|
||||||
"normalize-wheel": "^1.0.1",
|
"normalize-wheel": "^1.0.1",
|
||||||
|
"pinia": "^2.0.22",
|
||||||
"prismjs": "^1.17.1",
|
"prismjs": "^1.17.1",
|
||||||
"quill": "2.0.0-dev.4",
|
"quill": "2.0.0-dev.4",
|
||||||
"quill-autoformat": "^0.1.1",
|
"quill-autoformat": "^0.1.1",
|
||||||
|
@ -61151,6 +61213,15 @@
|
||||||
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
|
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"pinia": {
|
||||||
|
"version": "2.0.23",
|
||||||
|
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.23.tgz",
|
||||||
|
"integrity": "sha512-N15hFf4o5STrxpNrib1IEb1GOArvPYf1zPvQVRGOO1G1d74Ak0J0lVyalX/SmrzdT4Q0nlEFjbURsmBmIGUR5Q==",
|
||||||
|
"requires": {
|
||||||
|
"@vue/devtools-api": "^6.4.4",
|
||||||
|
"vue-demi": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"pinkie": {
|
"pinkie": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
|
||||||
|
@ -61952,7 +62023,7 @@
|
||||||
"fs-extra": "^6.0.1",
|
"fs-extra": "^6.0.1",
|
||||||
"get-stream": "^5.1.0",
|
"get-stream": "^5.1.0",
|
||||||
"glob": "^7.1.2",
|
"glob": "^7.1.2",
|
||||||
"globby": "^11.0.2",
|
"globby": "^10.0.1",
|
||||||
"http-call": "^5.1.2",
|
"http-call": "^5.1.2",
|
||||||
"load-json-file": "^6.2.0",
|
"load-json-file": "^6.2.0",
|
||||||
"pkg-dir": "^4.2.0",
|
"pkg-dir": "^4.2.0",
|
||||||
|
@ -67643,7 +67714,7 @@
|
||||||
"consola": "^2.15.3",
|
"consola": "^2.15.3",
|
||||||
"dotenv": "^16.0.0",
|
"dotenv": "^16.0.0",
|
||||||
"dotenv-expand": "^8.0.2",
|
"dotenv-expand": "^8.0.2",
|
||||||
"ejs": "^3.1.8",
|
"ejs": "^3.1.6",
|
||||||
"fast-glob": "^3.2.11",
|
"fast-glob": "^3.2.11",
|
||||||
"fs-extra": "^10.0.1",
|
"fs-extra": "^10.0.1",
|
||||||
"html-minifier-terser": "^6.1.0",
|
"html-minifier-terser": "^6.1.0",
|
||||||
|
@ -67820,6 +67891,11 @@
|
||||||
"tinycolor2": "^1.1.2"
|
"tinycolor2": "^1.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"vue-demi": {
|
||||||
|
"version": "0.13.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz",
|
||||||
|
"integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A=="
|
||||||
|
},
|
||||||
"vue-docgen-api": {
|
"vue-docgen-api": {
|
||||||
"version": "4.54.2",
|
"version": "4.54.2",
|
||||||
"resolved": "https://registry.npmjs.org/vue-docgen-api/-/vue-docgen-api-4.54.2.tgz",
|
"resolved": "https://registry.npmjs.org/vue-docgen-api/-/vue-docgen-api-4.54.2.tgz",
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
"n8n-design-system": "~0.41.0",
|
"n8n-design-system": "~0.41.0",
|
||||||
"n8n-workflow": "~0.123.0",
|
"n8n-workflow": "~0.123.0",
|
||||||
"normalize-wheel": "^1.0.1",
|
"normalize-wheel": "^1.0.1",
|
||||||
|
"pinia": "^2.0.22",
|
||||||
"prismjs": "^1.17.1",
|
"prismjs": "^1.17.1",
|
||||||
"quill": "2.0.0-dev.4",
|
"quill": "2.0.0-dev.4",
|
||||||
"quill-autoformat": "^0.1.1",
|
"quill-autoformat": "^0.1.1",
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
id="app"
|
id="app"
|
||||||
:class="{
|
:class="{
|
||||||
[$style.container]: true,
|
[$style.container]: true,
|
||||||
[$style.sidebarCollapsed]: sidebarMenuCollapsed
|
[$style.sidebarCollapsed]: uiStore.sidebarMenuCollapsed
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div id="header" :class="$style.header">
|
<div id="header" :class="$style.header">
|
||||||
|
@ -35,11 +35,17 @@ import { HIRING_BANNER, LOCAL_STORAGE_THEME, VIEWS } from './constants';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import { showMessage } from './components/mixins/showMessage';
|
import { showMessage } from './components/mixins/showMessage';
|
||||||
import { IUser } from './Interface';
|
import { IUser } from './Interface';
|
||||||
import { mapGetters } from 'vuex';
|
|
||||||
import { userHelpers } from './components/mixins/userHelpers';
|
import { userHelpers } from './components/mixins/userHelpers';
|
||||||
import { loadLanguage } from './plugins/i18n';
|
import { loadLanguage } from './plugins/i18n';
|
||||||
import { restApi } from '@/components/mixins/restApi';
|
import { restApi } from '@/components/mixins/restApi';
|
||||||
import { globalLinkActions } from '@/components/mixins/globalLinkActions';
|
import { globalLinkActions } from '@/components/mixins/globalLinkActions';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from './stores/ui';
|
||||||
|
import { useSettingsStore } from './stores/settings';
|
||||||
|
import { useUsersStore } from './stores/users';
|
||||||
|
import { useRootStore } from './stores/n8nRootStore';
|
||||||
|
import { useTemplatesStore } from './stores/templates';
|
||||||
|
import { useNodeTypesStore } from './stores/nodeTypes';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
showMessage,
|
showMessage,
|
||||||
|
@ -54,11 +60,16 @@ export default mixins(
|
||||||
Modals,
|
Modals,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters('settings', ['isHiringBannerEnabled', 'isTemplatesEnabled', 'isTemplatesEndpointReachable', 'isUserManagementEnabled', 'showSetupPage']),
|
...mapStores(
|
||||||
...mapGetters('users', ['currentUser']),
|
useNodeTypesStore,
|
||||||
...mapGetters('ui', ['sidebarMenuCollapsed']),
|
useRootStore,
|
||||||
|
useSettingsStore,
|
||||||
|
useTemplatesStore,
|
||||||
|
useUIStore,
|
||||||
|
useUsersStore,
|
||||||
|
),
|
||||||
defaultLocale (): string {
|
defaultLocale (): string {
|
||||||
return this.$store.getters.defaultLocale;
|
return this.rootStore.defaultLocale;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@ -69,7 +80,7 @@ export default mixins(
|
||||||
methods: {
|
methods: {
|
||||||
async initSettings(): Promise<void> {
|
async initSettings(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch('settings/getSettings');
|
await this.settingsStore.getSettings();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.$showToast({
|
this.$showToast({
|
||||||
title: this.$locale.baseText('startupError'),
|
title: this.$locale.baseText('startupError'),
|
||||||
|
@ -81,23 +92,22 @@ export default mixins(
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async loginWithCookie(): Promise<void> {
|
loginWithCookie(): void {
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch('users/loginWithCookie');
|
this.usersStore.loginWithCookie();
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
},
|
},
|
||||||
async initTemplates(): Promise<void> {
|
async initTemplates(): Promise<void> {
|
||||||
if (!this.isTemplatesEnabled) {
|
if (!this.settingsStore.isTemplatesEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch('settings/testTemplatesEndpoint');
|
await this.settingsStore.testTemplatesEndpoint();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
logHiringBanner() {
|
logHiringBanner() {
|
||||||
if (this.isHiringBannerEnabled && this.$route.name !== VIEWS.DEMO) {
|
if (this.settingsStore.isHiringBannerEnabled && this.$route.name !== VIEWS.DEMO) {
|
||||||
console.log(HIRING_BANNER); // eslint-disable-line no-console
|
console.log(HIRING_BANNER); // eslint-disable-line no-console
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -105,20 +115,20 @@ export default mixins(
|
||||||
await this.initSettings();
|
await this.initSettings();
|
||||||
await Promise.all([this.loginWithCookie(), this.initTemplates()]);
|
await Promise.all([this.loginWithCookie(), this.initTemplates()]);
|
||||||
},
|
},
|
||||||
trackPage() {
|
trackPage(): void {
|
||||||
this.$store.commit('ui/setCurrentView', this.$route.name);
|
this.uiStore.currentView = this.$route.name || '';
|
||||||
if (this.$route && this.$route.meta && this.$route.meta.templatesEnabled) {
|
if (this.$route && this.$route.meta && this.$route.meta.templatesEnabled) {
|
||||||
this.$store.commit('templates/setSessionId');
|
this.templatesStore.setSessionId();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.$store.commit('templates/resetSessionId'); // reset telemetry session id when user leaves template pages
|
this.templatesStore.resetSessionId(); // reset telemetry session id when user leaves template pages
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$telemetry.page(this.$route);
|
this.$telemetry.page(this.$route);
|
||||||
},
|
},
|
||||||
authenticate() {
|
authenticate() {
|
||||||
// redirect to setup page. user should be redirected to this only once
|
// redirect to setup page. user should be redirected to this only once
|
||||||
if (this.isUserManagementEnabled && this.showSetupPage) {
|
if (this.settingsStore.isUserManagementEnabled && this.settingsStore.showSetupPage) {
|
||||||
if (this.$route.name === VIEWS.SETUP) {
|
if (this.$route.name === VIEWS.SETUP) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -132,7 +142,7 @@ export default mixins(
|
||||||
}
|
}
|
||||||
|
|
||||||
// if cannot access page and not logged in, ask to sign in
|
// if cannot access page and not logged in, ask to sign in
|
||||||
const user = this.currentUser as IUser | null;
|
const user = this.usersStore.currentUser;
|
||||||
if (!user) {
|
if (!user) {
|
||||||
const redirect =
|
const redirect =
|
||||||
this.$route.query.redirect ||
|
this.$route.query.redirect ||
|
||||||
|
@ -154,7 +164,7 @@ export default mixins(
|
||||||
this.$router.replace({ name: VIEWS.HOMEPAGE });
|
this.$router.replace({ name: VIEWS.HOMEPAGE });
|
||||||
},
|
},
|
||||||
redirectIfNecessary() {
|
redirectIfNecessary() {
|
||||||
const redirect = this.$route.meta && typeof this.$route.meta.getRedirect === 'function' && this.$route.meta.getRedirect(this.$store);
|
const redirect = this.$route.meta && typeof this.$route.meta.getRedirect === 'function' && this.$route.meta.getRedirect();
|
||||||
if (redirect) {
|
if (redirect) {
|
||||||
this.$router.replace(redirect);
|
this.$router.replace(redirect);
|
||||||
}
|
}
|
||||||
|
@ -176,10 +186,11 @@ export default mixins(
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
|
||||||
this.trackPage();
|
this.trackPage();
|
||||||
|
// TODO: Un-comment once front-end hooks are updated to work with pinia store
|
||||||
this.$externalHooks().run('app.mount');
|
this.$externalHooks().run('app.mount');
|
||||||
|
|
||||||
if (this.defaultLocale !== 'en') {
|
if (this.defaultLocale !== 'en') {
|
||||||
void this.$store.dispatch('nodeTypes/getNodeTranslationHeaders');
|
await this.nodeTypesStore.getNodeTranslationHeaders();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { IMenuItem } from 'n8n-design-system';
|
||||||
import {
|
import {
|
||||||
jsPlumbInstance,
|
jsPlumbInstance,
|
||||||
DragOptions,
|
DragOptions,
|
||||||
|
@ -33,6 +34,7 @@ import {
|
||||||
ILoadOptions,
|
ILoadOptions,
|
||||||
INodeCredentials,
|
INodeCredentials,
|
||||||
INodeListSearchItems,
|
INodeListSearchItems,
|
||||||
|
NodeParameterValueType,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { FAKE_DOOR_FEATURES } from './constants';
|
import { FAKE_DOOR_FEATURES } from './constants';
|
||||||
|
|
||||||
|
@ -152,8 +154,8 @@ export type IJsPlumbInstance = Omit<jsPlumbInstance, 'addEndpoint' | 'draggable'
|
||||||
|
|
||||||
export interface IUpdateInformation {
|
export interface IUpdateInformation {
|
||||||
name: string;
|
name: string;
|
||||||
key: string;
|
key?: string;
|
||||||
value: string | number | { [key: string]: string | number | boolean }; // with null makes problems in NodeSettings.vue
|
value: string | number | { [key: string]: string | number | boolean } | NodeParameterValueType | INodeParameters; // with null makes problems in NodeSettings.vue
|
||||||
node?: string;
|
node?: string;
|
||||||
oldValue?: string | number;
|
oldValue?: string | number;
|
||||||
}
|
}
|
||||||
|
@ -887,6 +889,47 @@ export interface INodeMetadata {
|
||||||
parametersLastUpdatedAt?: number;
|
parametersLastUpdatedAt?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface WorkflowsState {
|
||||||
|
activeExecutions: IExecutionsCurrentSummaryExtended[];
|
||||||
|
activeWorkflows: string[];
|
||||||
|
activeWorkflowExecution: IExecutionsSummary | null;
|
||||||
|
currentWorkflowExecutions: IExecutionsSummary[];
|
||||||
|
activeExecutionId: string | null;
|
||||||
|
executingNode: string | null;
|
||||||
|
executionWaitingForWebhook: boolean;
|
||||||
|
finishedExecutionsCount: number;
|
||||||
|
nodeMetadata: NodeMetadataMap;
|
||||||
|
subWorkflowExecutionError: Error | null;
|
||||||
|
workflow: IWorkflowDb;
|
||||||
|
workflowExecutionData: IExecutionResponse | null;
|
||||||
|
workflowExecutionPairedItemMappings: {[itemId: string]: Set<string>};
|
||||||
|
workflowsById: IWorkflowsMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RootState {
|
||||||
|
baseUrl: string;
|
||||||
|
defaultLocale: string;
|
||||||
|
endpointWebhook: string;
|
||||||
|
endpointWebhookTest: string;
|
||||||
|
pushConnectionActive: boolean;
|
||||||
|
timezone: string;
|
||||||
|
executionTimeout: number;
|
||||||
|
maxExecutionTimeout: number;
|
||||||
|
versionCli: string;
|
||||||
|
oauthCallbackUrls: object;
|
||||||
|
n8nMetadata: {
|
||||||
|
[key: string]: string | number | undefined;
|
||||||
|
};
|
||||||
|
sessionId: string;
|
||||||
|
urlBaseWebhook: string;
|
||||||
|
urlBaseEditor: string;
|
||||||
|
instanceId: string;
|
||||||
|
isNpmAvailable: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NodeMetadataMap {
|
||||||
|
[nodeName: string]: INodeMetadata;
|
||||||
|
}
|
||||||
export interface IRootState {
|
export interface IRootState {
|
||||||
activeExecutions: IExecutionsCurrentSummaryExtended[];
|
activeExecutions: IExecutionsCurrentSummaryExtended[];
|
||||||
activeWorkflows: string[];
|
activeWorkflows: string[];
|
||||||
|
@ -924,12 +967,12 @@ export interface IRootState {
|
||||||
workflowsById: IWorkflowsMap;
|
workflowsById: IWorkflowsMap;
|
||||||
sidebarMenuItems: IMenuItem[];
|
sidebarMenuItems: IMenuItem[];
|
||||||
instanceId: string;
|
instanceId: string;
|
||||||
nodeMetadata: {[nodeName: string]: INodeMetadata};
|
nodeMetadata: NodeMetadataMap;
|
||||||
isNpmAvailable: boolean;
|
isNpmAvailable: boolean;
|
||||||
subworkflowExecutionError: Error | null;
|
subworkflowExecutionError: Error | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICommunityPackageMap {
|
export interface CommunityPackageMap {
|
||||||
[name: string]: PublicInstalledPackage;
|
[name: string]: PublicInstalledPackage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -964,6 +1007,7 @@ export interface IModalState {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IRunDataDisplayMode = 'table' | 'json' | 'binary';
|
export type IRunDataDisplayMode = 'table' | 'json' | 'binary';
|
||||||
|
export type nodePanelType = 'input' | 'output';
|
||||||
|
|
||||||
export interface TargetItem {
|
export interface TargetItem {
|
||||||
nodeName: string;
|
nodeName: string;
|
||||||
|
@ -1023,6 +1067,37 @@ export interface IUiState {
|
||||||
executionSidebarAutoRefresh: boolean;
|
executionSidebarAutoRefresh: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UIState {
|
||||||
|
activeActions: string[];
|
||||||
|
activeCredentialType: string | null;
|
||||||
|
sidebarMenuCollapsed: boolean;
|
||||||
|
modalStack: string[];
|
||||||
|
modals: {
|
||||||
|
[key: string]: IModalState;
|
||||||
|
};
|
||||||
|
isPageLoading: boolean;
|
||||||
|
currentView: string;
|
||||||
|
mainPanelPosition: number;
|
||||||
|
fakeDoorFeatures: IFakeDoor[];
|
||||||
|
draggable: {
|
||||||
|
isDragging: boolean;
|
||||||
|
type: string;
|
||||||
|
data: string;
|
||||||
|
canDrop: boolean;
|
||||||
|
stickyPosition: null | XYPosition;
|
||||||
|
};
|
||||||
|
stateIsDirty: boolean;
|
||||||
|
lastSelectedNode: string | null;
|
||||||
|
lastSelectedNodeOutputIndex: number | null;
|
||||||
|
nodeViewOffsetPosition: XYPosition;
|
||||||
|
nodeViewMoveInProgress: boolean;
|
||||||
|
selectedNodes: INodeUi[];
|
||||||
|
sidebarMenuItems: IMenuItem[];
|
||||||
|
nodeViewInitialized: boolean;
|
||||||
|
addFirstStepOnLoad: boolean;
|
||||||
|
executionSidebarAutoRefresh: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export type ILogLevel = 'info' | 'debug' | 'warn' | 'error' | 'verbose';
|
export type ILogLevel = 'info' | 'debug' | 'warn' | 'error' | 'verbose';
|
||||||
|
|
||||||
export type IFakeDoor = {
|
export type IFakeDoor = {
|
||||||
|
@ -1059,6 +1134,9 @@ export interface ISettingsState {
|
||||||
path: string;
|
path: string;
|
||||||
};
|
};
|
||||||
onboardingCallPromptEnabled: boolean;
|
onboardingCallPromptEnabled: boolean;
|
||||||
|
saveDataErrorExecution: string;
|
||||||
|
saveDataSuccessExecution: string;
|
||||||
|
saveManualExecutions: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface INodeTypesState {
|
export interface INodeTypesState {
|
||||||
|
@ -1109,11 +1187,9 @@ export interface IWorkflowsState {
|
||||||
[name: string]: IWorkflowDb;
|
[name: string]: IWorkflowDb;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IWorkflowsState {}
|
export interface CommunityNodesState {
|
||||||
|
|
||||||
export interface ICommunityNodesState {
|
|
||||||
availablePackageCount: number;
|
availablePackageCount: number;
|
||||||
installedPackages: ICommunityPackageMap;
|
installedPackages: CommunityPackageMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IRestApiContext {
|
export interface IRestApiContext {
|
||||||
|
@ -1149,8 +1225,8 @@ export interface IOnboardingCallPromptResponse {
|
||||||
|
|
||||||
export interface IOnboardingCallPrompt {
|
export interface IOnboardingCallPrompt {
|
||||||
title: string;
|
title: string;
|
||||||
body: string;
|
description: string;
|
||||||
index: number;
|
toast_sequence_number: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITab {
|
export interface ITab {
|
||||||
|
@ -1182,3 +1258,14 @@ export interface IResourceLocatorReqParams {
|
||||||
export interface IResourceLocatorResultExpanded extends INodeListSearchItems {
|
export interface IResourceLocatorResultExpanded extends INodeListSearchItems {
|
||||||
linkAlt?: string;
|
linkAlt?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface CurlToJSONResponse {
|
||||||
|
"parameters.url": string;
|
||||||
|
"parameters.authentication": string;
|
||||||
|
"parameters.method": string;
|
||||||
|
"parameters.sendHeaders": boolean;
|
||||||
|
"parameters.headerParameters.parameters.0.name": string;
|
||||||
|
"parameters.headerParameters.parameters.0.value": string;
|
||||||
|
"parameters.sendQuery": boolean;
|
||||||
|
"parameters.sendBody": boolean;
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,6 @@ export async function uninstallPackage(context: IRestApiContext, name: string):
|
||||||
return await makeRestApiRequest(context, 'DELETE', '/nodes', { name });
|
return await makeRestApiRequest(context, 'DELETE', '/nodes', { name });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updatePackage(context: IRestApiContext, name: string): Promise<void> {
|
export async function updatePackage(context: IRestApiContext, name: string): Promise<PublicInstalledPackage> {
|
||||||
return await makeRestApiRequest(context, 'PATCH', '/nodes', { name });
|
return await makeRestApiRequest(context, 'PATCH', '/nodes', { name });
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {IRestApiContext} from "@/Interface";
|
import {CurlToJSONResponse, IRestApiContext} from "@/Interface";
|
||||||
import {makeRestApiRequest} from "@/api/helpers";
|
import {makeRestApiRequest} from "@/api/helpers";
|
||||||
|
|
||||||
export function getCurlToJson(context: IRestApiContext, curlCommand: string): Promise<{ curlCommand: string | null }> {
|
export function getCurlToJson(context: IRestApiContext, curlCommand: string): Promise<CurlToJSONResponse> {
|
||||||
return makeRestApiRequest(context, 'POST', '/curl-to-json', { curlCommand });
|
return makeRestApiRequest(context, 'POST', '/curl-to-json', { curlCommand });
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { IRestApiContext, IN8nPrompts, IN8nValueSurveyData, IN8nUISettings } from '../Interface';
|
import { IRestApiContext, IN8nPrompts, IN8nValueSurveyData, IN8nUISettings, IN8nPromptResponse } from '../Interface';
|
||||||
import { makeRestApiRequest, get, post } from './helpers';
|
import { makeRestApiRequest, get, post } from './helpers';
|
||||||
import { N8N_IO_BASE_URL, NPM_COMMUNITY_NODE_SEARCH_API_URL } from '@/constants';
|
import { N8N_IO_BASE_URL, NPM_COMMUNITY_NODE_SEARCH_API_URL } from '@/constants';
|
||||||
|
|
||||||
|
@ -10,11 +10,11 @@ export async function getPromptsData(instanceId: string, userId: string): Promis
|
||||||
return await get(N8N_IO_BASE_URL, '/prompts', {}, {'n8n-instance-id': instanceId, 'n8n-user-id': userId});
|
return await get(N8N_IO_BASE_URL, '/prompts', {}, {'n8n-instance-id': instanceId, 'n8n-user-id': userId});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function submitContactInfo(instanceId: string, userId: string, email: string): Promise<void> {
|
export async function submitContactInfo(instanceId: string, userId: string, email: string): Promise<IN8nPromptResponse> {
|
||||||
return await post(N8N_IO_BASE_URL, '/prompt', { email }, {'n8n-instance-id': instanceId, 'n8n-user-id': userId});
|
return await post(N8N_IO_BASE_URL, '/prompt', { email }, {'n8n-instance-id': instanceId, 'n8n-user-id': userId});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function submitValueSurvey(instanceId: string, userId: string, params: IN8nValueSurveyData): Promise<IN8nPrompts> {
|
export async function submitValueSurvey(instanceId: string, userId: string, params: IN8nValueSurveyData): Promise<IN8nPromptResponse> {
|
||||||
return await post(N8N_IO_BASE_URL, '/value-survey', params, {'n8n-instance-id': instanceId, 'n8n-user-id': userId});
|
return await post(N8N_IO_BASE_URL, '/value-survey', params, {'n8n-instance-id': instanceId, 'n8n-user-id': userId});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { IOnboardingCallPromptResponse, IUser } from "@/Interface";
|
import { IOnboardingCallPrompt, IOnboardingCallPromptResponse, IUser } from "@/Interface";
|
||||||
import { get, post } from "./helpers";
|
import { get, post } from "./helpers";
|
||||||
|
|
||||||
const N8N_API_BASE_URL = 'https://api.n8n.io/api';
|
const N8N_API_BASE_URL = 'https://api.n8n.io/api';
|
||||||
const ONBOARDING_PROMPTS_ENDPOINT = '/prompts/onboarding';
|
const ONBOARDING_PROMPTS_ENDPOINT = '/prompts/onboarding';
|
||||||
const CONTACT_EMAIL_SUBMISSION_ENDPOINT = '/accounts/onboarding';
|
const CONTACT_EMAIL_SUBMISSION_ENDPOINT = '/accounts/onboarding';
|
||||||
|
|
||||||
export async function fetchNextOnboardingPrompt(instanceId: string, currentUer: IUser): Promise<IOnboardingCallPromptResponse> {
|
export async function fetchNextOnboardingPrompt(instanceId: string, currentUer: IUser): Promise<IOnboardingCallPrompt> {
|
||||||
return await get(
|
return await get(
|
||||||
N8N_API_BASE_URL,
|
N8N_API_BASE_URL,
|
||||||
ONBOARDING_PROMPTS_ENDPOINT,
|
ONBOARDING_PROMPTS_ENDPOINT,
|
||||||
|
@ -35,7 +35,7 @@ export async function applyForOnboardingCall(instanceId: string, currentUer: IUs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function submitEmailOnSignup(instanceId: string, currentUer: IUser, email: string, agree: boolean): Promise<string> {
|
export async function submitEmailOnSignup(instanceId: string, currentUer: IUser, email: string | undefined, agree: boolean): Promise<string> {
|
||||||
return await post(
|
return await post(
|
||||||
N8N_API_BASE_URL,
|
N8N_API_BASE_URL,
|
||||||
CONTACT_EMAIL_SUBMISSION_ENDPOINT,
|
CONTACT_EMAIL_SUBMISSION_ENDPOINT,
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<n8n-text>{{ $locale.baseText('about.n8nVersion') }}</n8n-text>
|
<n8n-text>{{ $locale.baseText('about.n8nVersion') }}</n8n-text>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="16">
|
<el-col :span="16">
|
||||||
<n8n-text>{{ versionCli }}</n8n-text>
|
<n8n-text>{{ rootStore.versionCli }}</n8n-text>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
<n8n-text>{{ $locale.baseText('about.instanceID') }}</n8n-text>
|
<n8n-text>{{ $locale.baseText('about.instanceID') }}</n8n-text>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="16">
|
<el-col :span="16">
|
||||||
<n8n-text>{{ instanceId }}</n8n-text>
|
<n8n-text>{{ rootStore.instanceId }}</n8n-text>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
|
@ -55,9 +55,11 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { mapGetters } from 'vuex';
|
|
||||||
import Modal from './Modal.vue';
|
import Modal from './Modal.vue';
|
||||||
import { ABOUT_MODAL_KEY } from '../constants';
|
import { ABOUT_MODAL_KEY } from '../constants';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'About',
|
name: 'About',
|
||||||
|
@ -71,8 +73,10 @@ export default Vue.extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters('settings', ['versionCli']),
|
...mapStores(
|
||||||
...mapGetters(['instanceId']),
|
useRootStore,
|
||||||
|
useSettingsStore,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
closeDialog() {
|
closeDialog() {
|
||||||
|
|
|
@ -37,9 +37,13 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
import Modal from '@/components/Modal.vue';
|
import Modal from '@/components/Modal.vue';
|
||||||
import { WORKFLOW_ACTIVE_MODAL_KEY, EXECUTIONS_MODAL_KEY, WORKFLOW_SETTINGS_MODAL_KEY, LOCAL_STORAGE_ACTIVATION_FLAG, VIEWS } from '../constants';
|
import { WORKFLOW_ACTIVE_MODAL_KEY, WORKFLOW_SETTINGS_MODAL_KEY, LOCAL_STORAGE_ACTIVATION_FLAG, VIEWS } from '../constants';
|
||||||
import { getActivatableTriggerNodes, getTriggerNodeServiceName } from './helpers';
|
import { getActivatableTriggerNodes, getTriggerNodeServiceName } from './helpers';
|
||||||
import { INodeTypeDescription } from 'n8n-workflow';
|
import { INodeTypeDescription } from 'n8n-workflow';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'ActivationModal',
|
name: 'ActivationModal',
|
||||||
|
@ -58,8 +62,8 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async showExecutionsList () {
|
async showExecutionsList () {
|
||||||
const activeExecution = this.$store.getters['workflows/getActiveWorkflowExecution'];
|
const activeExecution = this.workflowsStore.activeWorkflowExecution;
|
||||||
const currentWorkflow = this.$store.getters.workflowId;
|
const currentWorkflow = this.workflowsStore.workflowId;
|
||||||
|
|
||||||
if (activeExecution) {
|
if (activeExecution) {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
|
@ -69,10 +73,10 @@ export default Vue.extend({
|
||||||
} else {
|
} else {
|
||||||
this.$router.push({ name: VIEWS.EXECUTION_HOME, params: { name: currentWorkflow } }).catch(() => {});
|
this.$router.push({ name: VIEWS.EXECUTION_HOME, params: { name: currentWorkflow } }).catch(() => {});
|
||||||
}
|
}
|
||||||
this.$store.commit('ui/closeModal', WORKFLOW_ACTIVE_MODAL_KEY);
|
this.uiStore.closeModal(WORKFLOW_ACTIVE_MODAL_KEY);
|
||||||
},
|
},
|
||||||
async showSettings() {
|
async showSettings() {
|
||||||
this.$store.dispatch('ui/openModal', WORKFLOW_SETTINGS_MODAL_KEY);
|
this.uiStore.openModal(WORKFLOW_SETTINGS_MODAL_KEY);
|
||||||
},
|
},
|
||||||
handleCheckboxChange (checkboxValue: boolean) {
|
handleCheckboxChange (checkboxValue: boolean) {
|
||||||
this.checked = checkboxValue;
|
this.checked = checkboxValue;
|
||||||
|
@ -80,8 +84,13 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNodeTypesStore,
|
||||||
|
useUIStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
triggerContent (): string {
|
triggerContent (): string {
|
||||||
const foundTriggers = getActivatableTriggerNodes(this.$store.getters.workflowTriggerNodes);
|
const foundTriggers = getActivatableTriggerNodes(this.workflowsStore.workflowTriggerNodes);
|
||||||
if (!foundTriggers.length) {
|
if (!foundTriggers.length) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
@ -92,27 +101,28 @@ export default Vue.extend({
|
||||||
|
|
||||||
const trigger = foundTriggers[0];
|
const trigger = foundTriggers[0];
|
||||||
|
|
||||||
const triggerNodeType = this.$store.getters['nodeTypes/getNodeType'](trigger.type, trigger.typeVersion) as INodeTypeDescription;
|
const triggerNodeType = this.nodeTypesStore.getNodeType(trigger.type, trigger.typeVersion);
|
||||||
if (triggerNodeType.activationMessage) {
|
if (triggerNodeType) {
|
||||||
return triggerNodeType.activationMessage;
|
if (triggerNodeType.activationMessage) {
|
||||||
}
|
return triggerNodeType.activationMessage;
|
||||||
|
}
|
||||||
|
|
||||||
const serviceName = getTriggerNodeServiceName(triggerNodeType);
|
const serviceName = getTriggerNodeServiceName(triggerNodeType);
|
||||||
if (trigger.webhookId) {
|
if (trigger.webhookId) {
|
||||||
return this.$locale.baseText('activationModal.yourWorkflowWillNowListenForEvents', {
|
return this.$locale.baseText('activationModal.yourWorkflowWillNowListenForEvents', {
|
||||||
interpolate: {
|
interpolate: {
|
||||||
serviceName,
|
serviceName,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else if (triggerNodeType.polling) {
|
} else if (triggerNodeType.polling) {
|
||||||
return this.$locale.baseText('activationModal.yourWorkflowWillNowRegularlyCheck', {
|
return this.$locale.baseText('activationModal.yourWorkflowWillNowRegularlyCheck', {
|
||||||
interpolate: {
|
interpolate: {
|
||||||
serviceName,
|
serviceName,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
}
|
||||||
return this.$locale.baseText('activationModal.yourTriggerWillNowFire');
|
|
||||||
}
|
}
|
||||||
|
return this.$locale.baseText('activationModal.yourTriggerWillNowFire');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -32,6 +32,8 @@ import { nodeHelpers } from '@/components/mixins/nodeHelpers';
|
||||||
|
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import { restApi } from '@/components/mixins/restApi';
|
import { restApi } from '@/components/mixins/restApi';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
nodeHelpers,
|
nodeHelpers,
|
||||||
|
@ -47,6 +49,9 @@ export default mixins(
|
||||||
'windowVisible', // boolean
|
'windowVisible', // boolean
|
||||||
],
|
],
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
binaryData (): IBinaryData | null {
|
binaryData (): IBinaryData | null {
|
||||||
const binaryData = this.getBinaryData(this.workflowRunData, this.displayData.node, this.displayData.runIndex, this.displayData.outputIndex);
|
const binaryData = this.getBinaryData(this.workflowRunData, this.displayData.node, this.displayData.runIndex, this.displayData.outputIndex);
|
||||||
|
|
||||||
|
@ -72,12 +77,12 @@ export default mixins(
|
||||||
},
|
},
|
||||||
|
|
||||||
workflowRunData (): IRunData | null {
|
workflowRunData (): IRunData | null {
|
||||||
const workflowExecution = this.$store.getters.getWorkflowExecution;
|
const workflowExecution = this.workflowsStore.getWorkflowExecution;
|
||||||
if (workflowExecution === null) {
|
if (workflowExecution === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const executionData: IRunExecutionData = workflowExecution.data;
|
const executionData = workflowExecution.data;
|
||||||
return executionData.resultData.runData;
|
return executionData? executionData.resultData.runData : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
|
@ -31,6 +31,8 @@ import Modal from "./Modal.vue";
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import { IFormInputs } from "@/Interface";
|
import { IFormInputs } from "@/Interface";
|
||||||
import { CHANGE_PASSWORD_MODAL_KEY } from '../constants';
|
import { CHANGE_PASSWORD_MODAL_KEY } from '../constants';
|
||||||
|
import { mapStores } from "pinia";
|
||||||
|
import { useUsersStore } from "@/stores/users";
|
||||||
|
|
||||||
export default mixins(showMessage).extend({
|
export default mixins(showMessage).extend({
|
||||||
components: { Modal },
|
components: { Modal },
|
||||||
|
@ -50,6 +52,9 @@ export default mixins(showMessage).extend({
|
||||||
CHANGE_PASSWORD_MODAL_KEY,
|
CHANGE_PASSWORD_MODAL_KEY,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapStores(useUsersStore),
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.config = [
|
this.config = [
|
||||||
{
|
{
|
||||||
|
@ -115,7 +120,7 @@ export default mixins(showMessage).extend({
|
||||||
async onSubmit(values: {[key: string]: string}) {
|
async onSubmit(values: {[key: string]: string}) {
|
||||||
try {
|
try {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
await this.$store.dispatch('users/updateCurrentUserPassword', values);
|
await this.usersStore.updateCurrentUserPassword(values);
|
||||||
|
|
||||||
this.$showMessage({
|
this.$showMessage({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
|
|
|
@ -32,6 +32,10 @@ import {
|
||||||
PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
||||||
} from '@/constants';
|
} from '@/constants';
|
||||||
import { CodeEditor } from './forms';
|
import { CodeEditor } from './forms';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
genericHelpers,
|
genericHelpers,
|
||||||
|
@ -42,6 +46,13 @@ export default mixins(
|
||||||
CodeEditor,
|
CodeEditor,
|
||||||
},
|
},
|
||||||
props: ['codeAutocomplete', 'parameter', 'path', 'type', 'value', 'readonly'],
|
props: ['codeAutocomplete', 'parameter', 'path', 'type', 'value', 'readonly'],
|
||||||
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNDVStore,
|
||||||
|
useRootStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
loadAutocompleteData(): string[] {
|
loadAutocompleteData(): string[] {
|
||||||
if (['function', 'functionItem'].includes(this.codeAutocomplete)) {
|
if (['function', 'functionItem'].includes(this.codeAutocomplete)) {
|
||||||
|
@ -50,16 +61,16 @@ export default mixins(
|
||||||
const mode = 'manual';
|
const mode = 'manual';
|
||||||
let runIndex = 0;
|
let runIndex = 0;
|
||||||
|
|
||||||
const executedWorkflow: IExecutionResponse | null = this.$store.getters.getWorkflowExecution;
|
const executedWorkflow = this.workflowsStore.getWorkflowExecution;
|
||||||
const workflow = this.getCurrentWorkflow();
|
const workflow = this.getCurrentWorkflow();
|
||||||
const activeNode: INodeUi | null = this.$store.getters['ndv/activeNode'];
|
const activeNode: INodeUi | null = this.ndvStore.activeNode;
|
||||||
const parentNode = workflow.getParentNodes(activeNode!.name, inputName, 1);
|
const parentNode = workflow.getParentNodes(activeNode!.name, inputName, 1);
|
||||||
const nodeConnection = workflow.getNodeConnectionIndexes(activeNode!.name, parentNode[0]) || {
|
const nodeConnection = workflow.getNodeConnectionIndexes(activeNode!.name, parentNode[0]) || {
|
||||||
sourceIndex: 0,
|
sourceIndex: 0,
|
||||||
destinationIndex: 0,
|
destinationIndex: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const executionData = this.$store.getters.getWorkflowExecution as IExecutionResponse | null;
|
const executionData = this.workflowsStore.getWorkflowExecution;
|
||||||
|
|
||||||
let runExecutionData: IRunExecutionData;
|
let runExecutionData: IRunExecutionData;
|
||||||
if (!executionData || !executionData.data) {
|
if (!executionData || !executionData.data) {
|
||||||
|
@ -89,7 +100,7 @@ export default mixins(
|
||||||
$resumeWebhookUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
$resumeWebhookUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
||||||
};
|
};
|
||||||
|
|
||||||
const dataProxy = new WorkflowDataProxy(workflow, runExecutionData, runIndex, itemIndex, activeNode!.name, connectionInputData || [], {}, mode, this.$store.getters.timezone, additionalProxyKeys);
|
const dataProxy = new WorkflowDataProxy(workflow, runExecutionData, runIndex, itemIndex, activeNode!.name, connectionInputData || [], {}, mode, this.rootStore.timezone, additionalProxyKeys);
|
||||||
const proxy = dataProxy.getDataProxy();
|
const proxy = dataProxy.getDataProxy();
|
||||||
|
|
||||||
const autoCompleteItems = [
|
const autoCompleteItems = [
|
||||||
|
|
|
@ -17,6 +17,8 @@ import { workflowHelpers } from '../mixins/workflowHelpers'; // for json field c
|
||||||
import { codeNodeEditorEventBus } from '@/event-bus/code-node-editor-event-bus';
|
import { codeNodeEditorEventBus } from '@/event-bus/code-node-editor-event-bus';
|
||||||
import { CODE_NODE_TYPE } from '@/constants';
|
import { CODE_NODE_TYPE } from '@/constants';
|
||||||
import { ALL_ITEMS_PLACEHOLDER, EACH_ITEM_PLACEHOLDER } from './constants';
|
import { ALL_ITEMS_PLACEHOLDER, EACH_ITEM_PLACEHOLDER } from './constants';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
|
||||||
export default mixins(linterExtension, completerExtension, workflowHelpers).extend({
|
export default mixins(linterExtension, completerExtension, workflowHelpers).extend({
|
||||||
name: 'code-node-editor',
|
name: 'code-node-editor',
|
||||||
|
@ -47,6 +49,9 @@ export default mixins(linterExtension, completerExtension, workflowHelpers).exte
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useRootStore,
|
||||||
|
),
|
||||||
content(): string {
|
content(): string {
|
||||||
if (!this.editor) return '';
|
if (!this.editor) return '';
|
||||||
|
|
||||||
|
@ -119,7 +124,7 @@ export default mixins(linterExtension, completerExtension, workflowHelpers).exte
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$telemetry.track('User autocompleted code', {
|
this.$telemetry.track('User autocompleted code', {
|
||||||
instance_id: this.$store.getters.instanceId,
|
instance_id: this.rootStore.instanceId,
|
||||||
node_type: CODE_NODE_TYPE,
|
node_type: CODE_NODE_TYPE,
|
||||||
field_name: this.mode === 'runOnceForAllItems' ? 'jsCodeAllItems' : 'jsCodeEachItem',
|
field_name: this.mode === 'runOnceForAllItems' ? 'jsCodeAllItems' : 'jsCodeEachItem',
|
||||||
field_type: 'code',
|
field_type: 'code',
|
||||||
|
|
|
@ -4,6 +4,8 @@ import { addVarType } from '../utils';
|
||||||
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
|
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
|
||||||
import type { INodeUi } from '@/Interface';
|
import type { INodeUi } from '@/Interface';
|
||||||
import type { CodeNodeEditorMixin } from '../types';
|
import type { CodeNodeEditorMixin } from '../types';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
|
||||||
function getAutocompletableNodeNames(nodes: INodeUi[]) {
|
function getAutocompletableNodeNames(nodes: INodeUi[]) {
|
||||||
return nodes
|
return nodes
|
||||||
|
@ -12,6 +14,11 @@ function getAutocompletableNodeNames(nodes: INodeUi[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const baseCompletions = (Vue as CodeNodeEditorMixin).extend({
|
export const baseCompletions = (Vue as CodeNodeEditorMixin).extend({
|
||||||
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/**
|
/**
|
||||||
* - Complete `$` to `$execution $input $prevNode $runIndex $workflow $now $today
|
* - Complete `$` to `$execution $input $prevNode $runIndex $workflow $now $today
|
||||||
|
@ -58,7 +65,7 @@ export const baseCompletions = (Vue as CodeNodeEditorMixin).extend({
|
||||||
const options: Completion[] = TOP_LEVEL_COMPLETIONS_IN_BOTH_MODES.map(addVarType);
|
const options: Completion[] = TOP_LEVEL_COMPLETIONS_IN_BOTH_MODES.map(addVarType);
|
||||||
|
|
||||||
options.push(
|
options.push(
|
||||||
...getAutocompletableNodeNames(this.$store.getters.allNodes).map((nodeName) => {
|
...getAutocompletableNodeNames(this.workflowsStore.allNodes).map((nodeName) => {
|
||||||
return {
|
return {
|
||||||
label: `$('${nodeName}')`,
|
label: `$('${nodeName}')`,
|
||||||
type: 'variable',
|
type: 'variable',
|
||||||
|
@ -96,7 +103,7 @@ export const baseCompletions = (Vue as CodeNodeEditorMixin).extend({
|
||||||
|
|
||||||
if (!preCursor || (preCursor.from === preCursor.to && !context.explicit)) return null;
|
if (!preCursor || (preCursor.from === preCursor.to && !context.explicit)) return null;
|
||||||
|
|
||||||
const options: Completion[] = getAutocompletableNodeNames(this.$store.getters.allNodes).map(
|
const options: Completion[] = getAutocompletableNodeNames(this.workflowsStore.allNodes).map(
|
||||||
(nodeName) => {
|
(nodeName) => {
|
||||||
return {
|
return {
|
||||||
label: `$('${nodeName}')`,
|
label: `$('${nodeName}')`,
|
||||||
|
|
|
@ -3,8 +3,17 @@ import { isAllowedInDotNotation, escape, toVariableOption } from '../utils';
|
||||||
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
|
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
|
||||||
import type { IDataObject, IPinData, IRunData } from 'n8n-workflow';
|
import type { IDataObject, IPinData, IRunData } from 'n8n-workflow';
|
||||||
import type { CodeNodeEditorMixin } from '../types';
|
import type { CodeNodeEditorMixin } from '../types';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
|
||||||
export const jsonFieldCompletions = (Vue as CodeNodeEditorMixin).extend({
|
export const jsonFieldCompletions = (Vue as CodeNodeEditorMixin).extend({
|
||||||
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNDVStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/**
|
/**
|
||||||
* - Complete `x.first().json.` to `.field`.
|
* - Complete `x.first().json.` to `.field`.
|
||||||
|
@ -206,11 +215,13 @@ export const jsonFieldCompletions = (Vue as CodeNodeEditorMixin).extend({
|
||||||
|
|
||||||
getInputNodeName() {
|
getInputNodeName() {
|
||||||
try {
|
try {
|
||||||
const activeNode = this.$store.getters['ndv/activeNode'];
|
const activeNode = this.ndvStore.activeNode;
|
||||||
const workflow = this.getCurrentWorkflow();
|
if (activeNode) {
|
||||||
const input = workflow.connectionsByDestinationNode[activeNode.name];
|
const workflow = this.getCurrentWorkflow();
|
||||||
|
const input = workflow.connectionsByDestinationNode[activeNode.name];
|
||||||
|
|
||||||
return input.main[0][0].node;
|
return input.main[0][0].node;
|
||||||
|
}
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -263,7 +274,7 @@ export const jsonFieldCompletions = (Vue as CodeNodeEditorMixin).extend({
|
||||||
getJsonOutput(quotedNodeName: string, options?: { accessor?: string; index?: number }) {
|
getJsonOutput(quotedNodeName: string, options?: { accessor?: string; index?: number }) {
|
||||||
const nodeName = quotedNodeName.replace(/['"]/g, '');
|
const nodeName = quotedNodeName.replace(/['"]/g, '');
|
||||||
|
|
||||||
const pinData: IPinData | undefined = this.$store.getters.pinData;
|
const pinData: IPinData | undefined = this.workflowsStore.getPinData;
|
||||||
|
|
||||||
const nodePinData = pinData && pinData[nodeName];
|
const nodePinData = pinData && pinData[nodeName];
|
||||||
|
|
||||||
|
@ -279,7 +290,7 @@ export const jsonFieldCompletions = (Vue as CodeNodeEditorMixin).extend({
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
const runData: IRunData | null = this.$store.getters.getWorkflowRunData;
|
const runData: IRunData | null = this.workflowsStore.getWorkflowRunData;
|
||||||
|
|
||||||
const nodeRunData = runData && runData[nodeName];
|
const nodeRunData = runData && runData[nodeName];
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import Vue from 'vue';
|
||||||
import { AUTOCOMPLETABLE_BUILT_IN_MODULES } from '../constants';
|
import { AUTOCOMPLETABLE_BUILT_IN_MODULES } from '../constants';
|
||||||
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
|
import type { Completion, CompletionContext, CompletionResult } from '@codemirror/autocomplete';
|
||||||
import type { CodeNodeEditorMixin } from '../types';
|
import type { CodeNodeEditorMixin } from '../types';
|
||||||
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
|
||||||
export const requireCompletions = (Vue as CodeNodeEditorMixin).extend({
|
export const requireCompletions = (Vue as CodeNodeEditorMixin).extend({
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -14,22 +15,26 @@ export const requireCompletions = (Vue as CodeNodeEditorMixin).extend({
|
||||||
if (!preCursor || (preCursor.from === preCursor.to && !context.explicit)) return null;
|
if (!preCursor || (preCursor.from === preCursor.to && !context.explicit)) return null;
|
||||||
|
|
||||||
const options: Completion[] = [];
|
const options: Completion[] = [];
|
||||||
|
const settingsStore = useSettingsStore();
|
||||||
const allowedModules = this.$store.getters['settings/allowedModules'];
|
const allowedModules = settingsStore.allowedModules;
|
||||||
|
|
||||||
const toOption = (moduleName: string) => ({
|
const toOption = (moduleName: string) => ({
|
||||||
label: `require('${moduleName}');`,
|
label: `require('${moduleName}');`,
|
||||||
type: 'variable',
|
type: 'variable',
|
||||||
});
|
});
|
||||||
|
|
||||||
if (allowedModules?.builtIn?.includes('*')) {
|
if (allowedModules.builtIn) {
|
||||||
options.push(...AUTOCOMPLETABLE_BUILT_IN_MODULES.map(toOption));
|
if (allowedModules.builtIn.includes('*')) {
|
||||||
} else if (allowedModules?.builtIn?.length > 0) {
|
options.push(...AUTOCOMPLETABLE_BUILT_IN_MODULES.map(toOption));
|
||||||
options.push(...allowedModules.builtIn.map(toOption));
|
} else if (allowedModules?.builtIn?.length > 0) {
|
||||||
|
options.push(...allowedModules.builtIn.map(toOption));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (allowedModules?.external?.length > 0) {
|
if (allowedModules.external) {
|
||||||
options.push(...allowedModules.external.map(toOption));
|
if (allowedModules?.external?.length > 0) {
|
||||||
|
options.push(...allowedModules.external.map(toOption));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -49,6 +49,8 @@ import { get } from 'lodash';
|
||||||
|
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import {Component} from "vue";
|
import {Component} from "vue";
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
nodeHelpers,
|
nodeHelpers,
|
||||||
|
@ -72,6 +74,9 @@ export default mixins(
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNDVStore,
|
||||||
|
),
|
||||||
getPlaceholderText (): string {
|
getPlaceholderText (): string {
|
||||||
const placeholder = this.$locale.nodeText().placeholder(this.parameter, this.path);
|
const placeholder = this.$locale.nodeText().placeholder(this.parameter, this.path);
|
||||||
return placeholder ? placeholder : this.$locale.baseText('collectionParameter.choose');
|
return placeholder ? placeholder : this.$locale.baseText('collectionParameter.choose');
|
||||||
|
@ -93,8 +98,8 @@ export default mixins(
|
||||||
return this.displayNodeParameter(option as INodeProperties);
|
return this.displayNodeParameter(option as INodeProperties);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
node (): INodeUi {
|
node (): INodeUi | null {
|
||||||
return this.$store.getters['ndv/activeNode'];
|
return this.ndvStore.activeNode;
|
||||||
},
|
},
|
||||||
// Returns all the options which did not get added already
|
// Returns all the options which did not get added already
|
||||||
parameterOptions (): Array<INodePropertyOptions | INodeProperties> {
|
parameterOptions (): Array<INodePropertyOptions | INodeProperties> {
|
||||||
|
|
|
@ -55,7 +55,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
import { PublicInstalledPackage } from 'n8n-workflow';
|
import { PublicInstalledPackage } from 'n8n-workflow';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import {
|
import {
|
||||||
NPM_PACKAGE_DOCS_BASE_URL,
|
NPM_PACKAGE_DOCS_BASE_URL,
|
||||||
|
@ -91,6 +93,9 @@ export default mixins(
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapStores(useUIStore),
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async onAction(value: string) {
|
async onAction(value: string) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
|
@ -102,14 +107,14 @@ export default mixins(
|
||||||
window.open(`${NPM_PACKAGE_DOCS_BASE_URL}${this.communityPackage.packageName}`, '_blank');
|
window.open(`${NPM_PACKAGE_DOCS_BASE_URL}${this.communityPackage.packageName}`, '_blank');
|
||||||
break;
|
break;
|
||||||
case COMMUNITY_PACKAGE_MANAGE_ACTIONS.UNINSTALL:
|
case COMMUNITY_PACKAGE_MANAGE_ACTIONS.UNINSTALL:
|
||||||
this.$store.dispatch('ui/openCommunityPackageUninstallConfirmModal', this.communityPackage.packageName);
|
this.uiStore.openCommunityPackageUninstallConfirmModal(this.communityPackage.packageName);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onUpdateClick() {
|
onUpdateClick() {
|
||||||
this.$store.dispatch('ui/openCommunityPackageUpdateConfirmModal', this.communityPackage.packageName);
|
this.uiStore.openCommunityPackageUpdateConfirmModal(this.communityPackage.packageName);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -92,6 +92,8 @@ import {
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import { showMessage } from './mixins/showMessage';
|
import { showMessage } from './mixins/showMessage';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useCommunityNodesStore } from '@/stores/communityNodes';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
showMessage,
|
showMessage,
|
||||||
|
@ -114,6 +116,9 @@ export default mixins(
|
||||||
COMMUNITY_NODES_RISKS_DOCS_URL,
|
COMMUNITY_NODES_RISKS_DOCS_URL,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapStores(useCommunityNodesStore),
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openNPMPage() {
|
openNPMPage() {
|
||||||
this.$telemetry.track('user clicked cnr browse button', { source: 'cnr install modal' });
|
this.$telemetry.track('user clicked cnr browse button', { source: 'cnr install modal' });
|
||||||
|
@ -127,9 +132,9 @@ export default mixins(
|
||||||
this.$telemetry.track('user started cnr package install', { input_string: this.packageName, source: 'cnr settings page' });
|
this.$telemetry.track('user started cnr package install', { input_string: this.packageName, source: 'cnr settings page' });
|
||||||
this.infoTextErrorMessage = '';
|
this.infoTextErrorMessage = '';
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
await this.$store.dispatch('communityNodes/installPackage', this.packageName);
|
await this.communityNodesStore.installPackage(this.packageName);
|
||||||
// TODO: We need to fetch a fresh list of installed packages until proper response is implemented on the back-end
|
// TODO: We need to fetch a fresh list of installed packages until proper response is implemented on the back-end
|
||||||
await this.$store.dispatch('communityNodes/fetchInstalledPackages');
|
await this.communityNodesStore.fetchInstalledPackages();
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.modalBus.$emit('close');
|
this.modalBus.$emit('close');
|
||||||
this.$showMessage({
|
this.$showMessage({
|
||||||
|
|
|
@ -37,6 +37,8 @@ import mixins from 'vue-typed-mixins';
|
||||||
import Modal from './Modal.vue';
|
import Modal from './Modal.vue';
|
||||||
import { COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY, COMMUNITY_PACKAGE_MANAGE_ACTIONS } from '../constants';
|
import { COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY, COMMUNITY_PACKAGE_MANAGE_ACTIONS } from '../constants';
|
||||||
import { showMessage } from './mixins/showMessage';
|
import { showMessage } from './mixins/showMessage';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useCommunityNodesStore } from '@/stores/communityNodes';
|
||||||
|
|
||||||
export default mixins(showMessage).extend({
|
export default mixins(showMessage).extend({
|
||||||
name: 'CommunityPackageManageConfirmModal',
|
name: 'CommunityPackageManageConfirmModal',
|
||||||
|
@ -65,8 +67,9 @@ export default mixins(showMessage).extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(useCommunityNodesStore),
|
||||||
activePackage() {
|
activePackage() {
|
||||||
return this.$store.getters['communityNodes/getInstalledPackageByName'](this.activePackageName);
|
return this.communityNodesStore.getInstalledPackageByName(this.activePackageName);
|
||||||
},
|
},
|
||||||
getModalContent() {
|
getModalContent() {
|
||||||
if (this.mode === COMMUNITY_PACKAGE_MANAGE_ACTIONS.UNINSTALL) {
|
if (this.mode === COMMUNITY_PACKAGE_MANAGE_ACTIONS.UNINSTALL) {
|
||||||
|
@ -120,7 +123,7 @@ export default mixins(showMessage).extend({
|
||||||
package_author_email: this.activePackage.authorEmail,
|
package_author_email: this.activePackage.authorEmail,
|
||||||
});
|
});
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
await this.$store.dispatch('communityNodes/uninstallPackage', this.activePackageName);
|
await this.communityNodesStore.uninstallPackage(this.activePackageName);
|
||||||
this.$showMessage({
|
this.$showMessage({
|
||||||
title: this.$locale.baseText('settings.communityNodes.messages.uninstall.success.title'),
|
title: this.$locale.baseText('settings.communityNodes.messages.uninstall.success.title'),
|
||||||
type: 'success',
|
type: 'success',
|
||||||
|
@ -144,7 +147,7 @@ export default mixins(showMessage).extend({
|
||||||
});
|
});
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
const updatedVersion = this.activePackage.updateAvailable;
|
const updatedVersion = this.activePackage.updateAvailable;
|
||||||
await this.$store.dispatch('communityNodes/updatePackage', this.activePackageName);
|
await this.communityNodesStore.updatePackage(this.activePackageName);
|
||||||
this.$showMessage({
|
this.$showMessage({
|
||||||
title: this.$locale.baseText('settings.communityNodes.messages.update.success.title'),
|
title: this.$locale.baseText('settings.communityNodes.messages.update.success.title'),
|
||||||
message: this.$locale.baseText('settings.communityNodes.messages.update.success.message', {
|
message: this.$locale.baseText('settings.communityNodes.messages.update.success.message', {
|
||||||
|
|
|
@ -35,12 +35,14 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import { mapGetters } from 'vuex';
|
|
||||||
|
|
||||||
import { IN8nPromptResponse } from '@/Interface';
|
import { IN8nPromptResponse } from '@/Interface';
|
||||||
import { VALID_EMAIL_REGEX } from '@/constants';
|
import { VALID_EMAIL_REGEX } from '@/constants';
|
||||||
import { workflowHelpers } from '@/components/mixins/workflowHelpers';
|
import { workflowHelpers } from '@/components/mixins/workflowHelpers';
|
||||||
import Modal from './Modal.vue';
|
import Modal from './Modal.vue';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
|
||||||
export default mixins(workflowHelpers).extend({
|
export default mixins(workflowHelpers).extend({
|
||||||
components: { Modal },
|
components: { Modal },
|
||||||
|
@ -53,19 +55,20 @@ export default mixins(workflowHelpers).extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapStores(
|
||||||
promptsData: 'settings/getPromptsData',
|
useRootStore,
|
||||||
}),
|
useSettingsStore,
|
||||||
|
),
|
||||||
title(): string {
|
title(): string {
|
||||||
if (this.promptsData && this.promptsData.title) {
|
if (this.settingsStore.promptsData && this.settingsStore.promptsData.title) {
|
||||||
return this.promptsData.title;
|
return this.settingsStore.promptsData.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'You’re a power user 💪';
|
return 'You’re a power user 💪';
|
||||||
},
|
},
|
||||||
description(): string {
|
description(): string {
|
||||||
if (this.promptsData && this.promptsData.message) {
|
if (this.settingsStore.promptsData && this.settingsStore.promptsData.message) {
|
||||||
return this.promptsData.message;
|
return this.settingsStore.promptsData.message;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'Your experience with n8n can help us improve — for you and our entire community.';
|
return 'Your experience with n8n can help us improve — for you and our entire community.';
|
||||||
|
@ -78,21 +81,18 @@ export default mixins(workflowHelpers).extend({
|
||||||
closeDialog(): void {
|
closeDialog(): void {
|
||||||
if (!this.isEmailValid) {
|
if (!this.isEmailValid) {
|
||||||
this.$telemetry.track('User closed email modal', {
|
this.$telemetry.track('User closed email modal', {
|
||||||
instance_id: this.$store.getters.instanceId,
|
instance_id: this.rootStore.instanceId,
|
||||||
email: null,
|
email: null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async send() {
|
async send() {
|
||||||
if (this.isEmailValid) {
|
if (this.isEmailValid) {
|
||||||
const response: IN8nPromptResponse = await this.$store.dispatch(
|
const response = await this.settingsStore.submitContactInfo(this.email) as IN8nPromptResponse;
|
||||||
'settings/submitContactInfo',
|
|
||||||
this.email,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.updated) {
|
if (response.updated) {
|
||||||
this.$telemetry.track('User closed email modal', {
|
this.$telemetry.track('User closed email modal', {
|
||||||
instance_id: this.$store.getters.instanceId,
|
instance_id: this.rootStore.instanceId,
|
||||||
email: this.email,
|
email: this.email,
|
||||||
});
|
});
|
||||||
this.$showMessage({
|
this.$showMessage({
|
||||||
|
|
|
@ -46,8 +46,10 @@ import {EnterpriseEditionFeature} from '@/constants';
|
||||||
import {showMessage} from "@/components/mixins/showMessage";
|
import {showMessage} from "@/components/mixins/showMessage";
|
||||||
import CredentialIcon from '@/components/CredentialIcon.vue';
|
import CredentialIcon from '@/components/CredentialIcon.vue';
|
||||||
import {getCredentialPermissions, IPermissions} from "@/permissions";
|
import {getCredentialPermissions, IPermissions} from "@/permissions";
|
||||||
import {mapGetters} from "vuex";
|
|
||||||
import dateformat from "dateformat";
|
import dateformat from "dateformat";
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useUsersStore } from '@/stores/users';
|
||||||
|
|
||||||
export const CREDENTIAL_LIST_ITEM_ACTIONS = {
|
export const CREDENTIAL_LIST_ITEM_ACTIONS = {
|
||||||
OPEN: 'open',
|
OPEN: 'open',
|
||||||
|
@ -86,8 +88,12 @@ export default mixins(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useUIStore,
|
||||||
|
useUsersStore,
|
||||||
|
),
|
||||||
currentUser (): IUser {
|
currentUser (): IUser {
|
||||||
return this.$store.getters['users/currentUser'];
|
return this.usersStore.currentUser || {} as IUser;
|
||||||
},
|
},
|
||||||
credentialType(): ICredentialType {
|
credentialType(): ICredentialType {
|
||||||
return this.$store.getters['credentials/getCredentialTypeByName'](this.data.type);
|
return this.$store.getters['credentials/getCredentialTypeByName'](this.data.type);
|
||||||
|
@ -114,7 +120,7 @@ export default mixins(
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async onClick() {
|
async onClick() {
|
||||||
this.$store.dispatch('ui/openExistingCredential', { id: this.data.id});
|
this.uiStore.openExistingCredential(this.data.id);
|
||||||
},
|
},
|
||||||
async onAction(action: string) {
|
async onAction(action: string) {
|
||||||
if (action === CREDENTIAL_LIST_ITEM_ACTIONS.OPEN) {
|
if (action === CREDENTIAL_LIST_ITEM_ACTIONS.OPEN) {
|
||||||
|
|
|
@ -102,6 +102,11 @@ import { addCredentialTranslation } from '@/plugins/i18n';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import { BUILTIN_CREDENTIALS_DOCS_URL, EnterpriseEditionFeature } from '@/constants';
|
import { BUILTIN_CREDENTIALS_DOCS_URL, EnterpriseEditionFeature } from '@/constants';
|
||||||
import { IPermissions } from "@/permissions";
|
import { IPermissions } from "@/permissions";
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
|
||||||
export default mixins(restApi).extend({
|
export default mixins(restApi).extend({
|
||||||
name: 'CredentialConfig',
|
name: 'CredentialConfig',
|
||||||
|
@ -160,9 +165,9 @@ export default mixins(restApi).extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async beforeMount() {
|
async beforeMount() {
|
||||||
if (this.$store.getters.defaultLocale === 'en') return;
|
if (this.rootStore.defaultLocale === 'en') return;
|
||||||
|
|
||||||
this.$store.commit('setActiveCredentialType', this.credentialType.name);
|
this.uiStore.activeCredentialType = this.credentialType.name;
|
||||||
|
|
||||||
const key = `n8n-nodes-base.credentials.${this.credentialType.name}`;
|
const key = `n8n-nodes-base.credentials.${this.credentialType.name}`;
|
||||||
|
|
||||||
|
@ -172,10 +177,16 @@ export default mixins(restApi).extend({
|
||||||
|
|
||||||
addCredentialTranslation(
|
addCredentialTranslation(
|
||||||
{ [this.credentialType.name]: credTranslation },
|
{ [this.credentialType.name]: credTranslation },
|
||||||
this.$store.getters.defaultLocale,
|
this.rootStore.defaultLocale,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNDVStore,
|
||||||
|
useRootStore,
|
||||||
|
useUIStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
appName(): string {
|
appName(): string {
|
||||||
if (!this.credentialType) {
|
if (!this.credentialType) {
|
||||||
return '';
|
return '';
|
||||||
|
@ -195,7 +206,7 @@ export default mixins(restApi).extend({
|
||||||
},
|
},
|
||||||
documentationUrl(): string {
|
documentationUrl(): string {
|
||||||
const type = this.credentialType as ICredentialType;
|
const type = this.credentialType as ICredentialType;
|
||||||
const activeNode = this.$store.getters['ndv/activeNode'];
|
const activeNode = this.ndvStore.activeNode;
|
||||||
const isCommunityNode = activeNode ? isCommunityPackageName(activeNode.type) : false;
|
const isCommunityNode = activeNode ? isCommunityPackageName(activeNode.type) : false;
|
||||||
|
|
||||||
if (!type || !type.documentationUrl) {
|
if (!type || !type.documentationUrl) {
|
||||||
|
@ -219,7 +230,7 @@ export default mixins(restApi).extend({
|
||||||
this.parentTypes.includes('oAuth2Api')
|
this.parentTypes.includes('oAuth2Api')
|
||||||
? 'oauth2'
|
? 'oauth2'
|
||||||
: 'oauth1';
|
: 'oauth1';
|
||||||
return this.$store.getters.oauthCallbackUrls[oauthType];
|
return this.rootStore.oauthCallbackUrls[oauthType as keyof {}];
|
||||||
},
|
},
|
||||||
showOAuthSuccessBanner(): boolean {
|
showOAuthSuccessBanner(): boolean {
|
||||||
return this.isOAuthType && this.requiredPropertiesFilled && this.isOAuthConnected && !this.authError;
|
return this.isOAuthType && this.requiredPropertiesFilled && this.isOAuthConnected && !this.authError;
|
||||||
|
@ -234,7 +245,7 @@ export default mixins(restApi).extend({
|
||||||
docs_link: this.documentationUrl,
|
docs_link: this.documentationUrl,
|
||||||
credential_type: this.credentialTypeName,
|
credential_type: this.credentialTypeName,
|
||||||
source: 'modal',
|
source: 'modal',
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -109,6 +109,7 @@ import {
|
||||||
ICredentialsDecryptedResponse,
|
ICredentialsDecryptedResponse,
|
||||||
ICredentialsResponse,
|
ICredentialsResponse,
|
||||||
IFakeDoor,
|
IFakeDoor,
|
||||||
|
IUser,
|
||||||
} from '@/Interface';
|
} from '@/Interface';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -123,7 +124,6 @@ import {
|
||||||
INodeProperties,
|
INodeProperties,
|
||||||
INodeTypeDescription,
|
INodeTypeDescription,
|
||||||
ITelemetryTrackProperties,
|
ITelemetryTrackProperties,
|
||||||
IUser,
|
|
||||||
NodeHelpers,
|
NodeHelpers,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import CredentialIcon from '../CredentialIcon.vue';
|
import CredentialIcon from '../CredentialIcon.vue';
|
||||||
|
@ -141,10 +141,15 @@ import InlineNameEdit from '../InlineNameEdit.vue';
|
||||||
import {EnterpriseEditionFeature} from "@/constants";
|
import {EnterpriseEditionFeature} from "@/constants";
|
||||||
import {IDataObject} from "n8n-workflow";
|
import {IDataObject} from "n8n-workflow";
|
||||||
import FeatureComingSoon from '../FeatureComingSoon.vue';
|
import FeatureComingSoon from '../FeatureComingSoon.vue';
|
||||||
import {mapGetters} from "vuex";
|
|
||||||
import {getCredentialPermissions, IPermissions} from "@/permissions";
|
import {getCredentialPermissions, IPermissions} from "@/permissions";
|
||||||
import { IMenuItem } from 'n8n-design-system';
|
import { IMenuItem } from 'n8n-design-system';
|
||||||
import { BaseTextKey } from '@/plugins/i18n';
|
import { BaseTextKey } from '@/plugins/i18n';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
import { useUsersStore } from '@/stores/users';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
|
||||||
interface NodeAccessMap {
|
interface NodeAccessMap {
|
||||||
[nodeType: string]: ICredentialNodeAccess | null;
|
[nodeType: string]: ICredentialNodeAccess | null;
|
||||||
|
@ -236,7 +241,7 @@ export default mixins(showMessage, nodeHelpers).extend({
|
||||||
this.$externalHooks().run('credentialsEdit.credentialModalOpened', {
|
this.$externalHooks().run('credentialsEdit.credentialModalOpened', {
|
||||||
credentialType: this.credentialTypeName,
|
credentialType: this.credentialTypeName,
|
||||||
isEditingCredential: this.mode === 'edit',
|
isEditingCredential: this.mode === 'edit',
|
||||||
activeNode: this.$store.getters['ndv/activeNode'],
|
activeNode: this.ndvStore.activeNode,
|
||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -253,7 +258,16 @@ export default mixins(showMessage, nodeHelpers).extend({
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters('users', ['currentUser']),
|
...mapStores(
|
||||||
|
useNDVStore,
|
||||||
|
useSettingsStore,
|
||||||
|
useUIStore,
|
||||||
|
useUsersStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
|
currentUser(): IUser {
|
||||||
|
return this.usersStore.currentUser || {} as IUser;
|
||||||
|
},
|
||||||
currentCredential(): ICredentialsResponse | null {
|
currentCredential(): ICredentialsResponse | null {
|
||||||
if (!this.credentialId) {
|
if (!this.credentialId) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -387,7 +401,7 @@ export default mixins(showMessage, nodeHelpers).extend({
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
credentialsFakeDoorFeatures(): IFakeDoor[] {
|
credentialsFakeDoorFeatures(): IFakeDoor[] {
|
||||||
return this.$store.getters['ui/getFakeDoorByLocation']('credentialsModal');
|
return this.uiStore.getFakeDoorByLocation('credentialsModal');
|
||||||
},
|
},
|
||||||
credentialPermissions(): IPermissions {
|
credentialPermissions(): IPermissions {
|
||||||
if (this.loading) {
|
if (this.loading) {
|
||||||
|
@ -431,7 +445,7 @@ export default mixins(showMessage, nodeHelpers).extend({
|
||||||
return items;
|
return items;
|
||||||
},
|
},
|
||||||
isSharingAvailable(): boolean {
|
isSharingAvailable(): boolean {
|
||||||
return this.$store.getters['settings/isEnterpriseFeatureEnabled'](EnterpriseEditionFeature.Sharing) === true;
|
return this.settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.Sharing);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -561,13 +575,13 @@ export default mixins(showMessage, nodeHelpers).extend({
|
||||||
this.activeTab = tab;
|
this.activeTab = tab;
|
||||||
const tabName: string = tab.replaceAll('coming-soon/', '');
|
const tabName: string = tab.replaceAll('coming-soon/', '');
|
||||||
const credType: string = this.credentialType ? this.credentialType.name : '';
|
const credType: string = this.credentialType ? this.credentialType.name : '';
|
||||||
const activeNode: INode | null = this.$store.getters['ndv/activeNode'];
|
const activeNode: INode | null = this.ndvStore.activeNode;
|
||||||
|
|
||||||
this.$telemetry.track('User viewed credential tab', {
|
this.$telemetry.track('User viewed credential tab', {
|
||||||
credential_type: credType,
|
credential_type: credType,
|
||||||
node_type: activeNode ? activeNode.type : null,
|
node_type: activeNode ? activeNode.type : null,
|
||||||
tab: tabName,
|
tab: tabName,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
credential_id: this.credentialId,
|
credential_id: this.credentialId,
|
||||||
sharing_enabled: EnterpriseEditionFeature.Sharing,
|
sharing_enabled: EnterpriseEditionFeature.Sharing,
|
||||||
});
|
});
|
||||||
|
@ -715,7 +729,7 @@ export default mixins(showMessage, nodeHelpers).extend({
|
||||||
|
|
||||||
let sharedWith: IUser[] | undefined;
|
let sharedWith: IUser[] | undefined;
|
||||||
let ownedBy: IUser | undefined;
|
let ownedBy: IUser | undefined;
|
||||||
if (this.$store.getters['settings/isEnterpriseFeatureEnabled'](EnterpriseEditionFeature.Sharing)) {
|
if (this.settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.Sharing)) {
|
||||||
sharedWith = this.credentialData.sharedWith as unknown as IUser[];
|
sharedWith = this.credentialData.sharedWith as unknown as IUser[];
|
||||||
ownedBy = this.credentialData.ownedBy as unknown as IUser;
|
ownedBy = this.credentialData.ownedBy as unknown as IUser;
|
||||||
}
|
}
|
||||||
|
@ -765,7 +779,7 @@ export default mixins(showMessage, nodeHelpers).extend({
|
||||||
|
|
||||||
const trackProperties: ITelemetryTrackProperties = {
|
const trackProperties: ITelemetryTrackProperties = {
|
||||||
credential_type: credentialDetails.type,
|
credential_type: credentialDetails.type,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
credential_id: credential.id,
|
credential_id: credential.id,
|
||||||
is_complete: !!this.requiredPropertiesFilled,
|
is_complete: !!this.requiredPropertiesFilled,
|
||||||
is_new: isNewCredential,
|
is_new: isNewCredential,
|
||||||
|
@ -777,8 +791,8 @@ export default mixins(showMessage, nodeHelpers).extend({
|
||||||
trackProperties.is_valid = !!this.testedSuccessfully;
|
trackProperties.is_valid = !!this.testedSuccessfully;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.$store.getters['ndv/activeNode']) {
|
if (this.ndvStore.activeNode) {
|
||||||
trackProperties.node_type = this.$store.getters['ndv/activeNode'].type;
|
trackProperties.node_type = this.ndvStore.activeNode.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.authError && this.authError !== '') {
|
if (this.authError && this.authError !== '') {
|
||||||
|
@ -821,7 +835,7 @@ export default mixins(showMessage, nodeHelpers).extend({
|
||||||
this.$telemetry.track('User created credentials', {
|
this.$telemetry.track('User created credentials', {
|
||||||
credential_type: credentialDetails.type,
|
credential_type: credentialDetails.type,
|
||||||
credential_id: credential.id,
|
credential_id: credential.id,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
});
|
});
|
||||||
|
|
||||||
return credential;
|
return credential;
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
v-if="credentialPermissions.updateSharing"
|
v-if="credentialPermissions.updateSharing"
|
||||||
size="large"
|
size="large"
|
||||||
:users="usersList"
|
:users="usersList"
|
||||||
:currentUserId="currentUser.id"
|
:currentUserId="usersStore.currentUser.id"
|
||||||
:placeholder="$locale.baseText('credentialEdit.credentialSharing.select.placeholder')"
|
:placeholder="$locale.baseText('credentialEdit.credentialSharing.select.placeholder')"
|
||||||
@input="onAddSharee"
|
@input="onAddSharee"
|
||||||
>
|
>
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
</n8n-user-select>
|
</n8n-user-select>
|
||||||
<n8n-users-list
|
<n8n-users-list
|
||||||
:users="sharedWithList"
|
:users="sharedWithList"
|
||||||
:currentUserId="currentUser.id"
|
:currentUserId="usersStore.currentUser.id"
|
||||||
:delete-label="$locale.baseText('credentialEdit.credentialSharing.list.delete')"
|
:delete-label="$locale.baseText('credentialEdit.credentialSharing.list.delete')"
|
||||||
:readonly="!credentialPermissions.updateSharing"
|
:readonly="!credentialPermissions.updateSharing"
|
||||||
@delete="onRemoveSharee"
|
@delete="onRemoveSharee"
|
||||||
|
@ -34,11 +34,11 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
|
||||||
import { mapGetters } from 'vuex';
|
|
||||||
import {IUser} from "@/Interface";
|
import {IUser} from "@/Interface";
|
||||||
import mixins from "vue-typed-mixins";
|
import mixins from "vue-typed-mixins";
|
||||||
import {showMessage} from "@/components/mixins/showMessage";
|
import {showMessage} from "@/components/mixins/showMessage";
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUsersStore } from '@/stores/users';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
showMessage,
|
showMessage,
|
||||||
|
@ -46,10 +46,10 @@ export default mixins(
|
||||||
name: 'CredentialSharing',
|
name: 'CredentialSharing',
|
||||||
props: ['credential', 'credentialId', 'credentialData', 'sharedWith', 'credentialPermissions'],
|
props: ['credential', 'credentialId', 'credentialData', 'sharedWith', 'credentialPermissions'],
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters('users', ['allUsers', 'currentUser']),
|
...mapStores(useUsersStore),
|
||||||
usersList(): IUser[] {
|
usersList(): IUser[] {
|
||||||
return this.allUsers.filter((user: IUser) => {
|
return this.usersStore.allUsers.filter((user: IUser) => {
|
||||||
const isCurrentUser = user.id === this.currentUser.id;
|
const isCurrentUser = user.id === this.usersStore.currentUser?.id;
|
||||||
const isAlreadySharedWithUser = (this.credentialData.sharedWith || []).find((sharee: IUser) => sharee.id === user.id);
|
const isAlreadySharedWithUser = (this.credentialData.sharedWith || []).find((sharee: IUser) => sharee.id === user.id);
|
||||||
|
|
||||||
return !isCurrentUser && !isAlreadySharedWithUser;
|
return !isCurrentUser && !isAlreadySharedWithUser;
|
||||||
|
@ -58,7 +58,7 @@ export default mixins(
|
||||||
sharedWithList(): IUser[] {
|
sharedWithList(): IUser[] {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
...(this.credential ? this.credential.ownedBy : this.currentUser),
|
...(this.credential ? this.credential.ownedBy : this.usersStore.currentUser),
|
||||||
isOwner: true,
|
isOwner: true,
|
||||||
},
|
},
|
||||||
].concat(this.credentialData.sharedWith || []);
|
].concat(this.credentialData.sharedWith || []);
|
||||||
|
@ -69,30 +69,30 @@ export default mixins(
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async onAddSharee(userId: string) {
|
async onAddSharee(userId: string) {
|
||||||
const { id, firstName, lastName, email } = this.$store.getters['users/getUserById'](userId);
|
const sharee = this.usersStore.getUserById(userId);
|
||||||
const sharee = { id, firstName, lastName, email };
|
|
||||||
|
|
||||||
this.$emit('change', (this.credentialData.sharedWith || []).concat(sharee));
|
this.$emit('change', (this.credentialData.sharedWith || []).concat(sharee));
|
||||||
},
|
},
|
||||||
async onRemoveSharee(userId: string) {
|
async onRemoveSharee(userId: string) {
|
||||||
const user = this.$store.getters['users/getUserById'](userId);
|
const user = this.usersStore.getUserById(userId);
|
||||||
|
|
||||||
const confirm = await this.confirmMessage(
|
if (user) {
|
||||||
this.$locale.baseText('credentialEdit.credentialSharing.list.delete.confirm.message', { interpolate: { name: user.fullName } }),
|
const confirm = await this.confirmMessage(
|
||||||
this.$locale.baseText('credentialEdit.credentialSharing.list.delete.confirm.title'),
|
this.$locale.baseText('credentialEdit.credentialSharing.list.delete.confirm.message', { interpolate: { name: user.fullName || '' } }),
|
||||||
null,
|
this.$locale.baseText('credentialEdit.credentialSharing.list.delete.confirm.title'),
|
||||||
this.$locale.baseText('credentialEdit.credentialSharing.list.delete.confirm.confirmButtonText'),
|
null,
|
||||||
this.$locale.baseText('credentialEdit.credentialSharing.list.delete.confirm.cancelButtonText'),
|
this.$locale.baseText('credentialEdit.credentialSharing.list.delete.confirm.confirmButtonText'),
|
||||||
);
|
this.$locale.baseText('credentialEdit.credentialSharing.list.delete.confirm.cancelButtonText'),
|
||||||
|
);
|
||||||
|
|
||||||
if (confirm) {
|
if (confirm) {
|
||||||
this.$emit('change', this.credentialData.sharedWith.filter((sharee: IUser) => {
|
this.$emit('change', this.credentialData.sharedWith.filter((sharee: IUser) => {
|
||||||
return sharee.id !== user.id;
|
return sharee.id !== user.id;
|
||||||
}));
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async loadUsers() {
|
async loadUsers() {
|
||||||
await this.$store.dispatch('users/fetchUsers');
|
await this.usersStore.fetchUsers();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
|
|
||||||
|
@ -27,8 +29,11 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useRootStore,
|
||||||
|
),
|
||||||
basePath(): string {
|
basePath(): string {
|
||||||
return this.$store.getters.getBaseUrl;
|
return this.rootStore.baseUrl;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,7 +7,10 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
import { ICredentialType, INodeTypeDescription } from 'n8n-workflow';
|
import { ICredentialType, INodeTypeDescription } from 'n8n-workflow';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
|
@ -17,6 +20,10 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNodeTypesStore,
|
||||||
|
useRootStore,
|
||||||
|
),
|
||||||
credentialWithIcon(): ICredentialType | null {
|
credentialWithIcon(): ICredentialType | null {
|
||||||
return this.credentialTypeName ? this.getCredentialWithIcon(this.credentialTypeName) : null;
|
return this.credentialTypeName ? this.getCredentialWithIcon(this.credentialTypeName) : null;
|
||||||
},
|
},
|
||||||
|
@ -26,15 +33,14 @@ export default Vue.extend({
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const restUrl = this.$store.getters.getRestUrl;
|
const restUrl = this.rootStore.getRestUrl;
|
||||||
|
|
||||||
return `${restUrl}/credential-icon/${this.credentialWithIcon.name}`;
|
return `${restUrl}/credential-icon/${this.credentialWithIcon.name}`;
|
||||||
},
|
},
|
||||||
relevantNode(): INodeTypeDescription | null {
|
relevantNode(): INodeTypeDescription | null {
|
||||||
if (this.credentialWithIcon && this.credentialWithIcon.icon && this.credentialWithIcon.icon.startsWith('node:')) {
|
if (this.credentialWithIcon && this.credentialWithIcon.icon && this.credentialWithIcon.icon.startsWith('node:')) {
|
||||||
const nodeType = this.credentialWithIcon.icon.replace('node:', '');
|
const nodeType = this.credentialWithIcon.icon.replace('node:', '');
|
||||||
|
return this.nodeTypesStore.getNodeType(nodeType);
|
||||||
return this.$store.getters['nodeTypes/getNodeType'](nodeType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const nodesWithAccess = this.$store.getters['credentials/getNodesWithAccess'](this.credentialTypeName);
|
const nodesWithAccess = this.$store.getters['credentials/getNodesWithAccess'](this.credentialTypeName);
|
||||||
|
|
|
@ -56,6 +56,9 @@ import mixins from 'vue-typed-mixins';
|
||||||
import Modal from './Modal.vue';
|
import Modal from './Modal.vue';
|
||||||
import { CREDENTIAL_SELECT_MODAL_KEY } from '../constants';
|
import { CREDENTIAL_SELECT_MODAL_KEY } from '../constants';
|
||||||
import { externalHooks } from '@/components/mixins/externalHooks';
|
import { externalHooks } from '@/components/mixins/externalHooks';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
|
||||||
export default mixins(externalHooks).extend({
|
export default mixins(externalHooks).extend({
|
||||||
name: 'CredentialsSelectModal',
|
name: 'CredentialsSelectModal',
|
||||||
|
@ -85,6 +88,10 @@ export default mixins(externalHooks).extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useUIStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
...mapGetters('credentials', ['allCredentialTypes']),
|
...mapGetters('credentials', ['allCredentialTypes']),
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -93,13 +100,13 @@ export default mixins(externalHooks).extend({
|
||||||
},
|
},
|
||||||
openCredentialType () {
|
openCredentialType () {
|
||||||
this.modalBus.$emit('close');
|
this.modalBus.$emit('close');
|
||||||
this.$store.dispatch('ui/openNewCredential', { type: this.selected });
|
this.uiStore.openNewCredential(this.selected);
|
||||||
|
|
||||||
const telemetryPayload = {
|
const telemetryPayload = {
|
||||||
credential_type: this.selected,
|
credential_type: this.selected,
|
||||||
source: 'primary_menu',
|
source: 'primary_menu',
|
||||||
new_credential: true,
|
new_credential: true,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$telemetry.track('User opened Credential modal', telemetryPayload);
|
this.$telemetry.track('User opened Credential modal', telemetryPayload);
|
||||||
|
|
|
@ -20,10 +20,10 @@
|
||||||
<div :class="$style.optionInput" v-if="operation === 'transfer'">
|
<div :class="$style.optionInput" v-if="operation === 'transfer'">
|
||||||
<n8n-input-label :label="$locale.baseText('settings.users.userToTransferTo')">
|
<n8n-input-label :label="$locale.baseText('settings.users.userToTransferTo')">
|
||||||
<n8n-user-select
|
<n8n-user-select
|
||||||
:users="allUsers"
|
:users="usersStore.allUsers"
|
||||||
:value="transferId"
|
:value="transferId"
|
||||||
:ignoreIds="ignoreIds"
|
:ignoreIds="ignoreIds"
|
||||||
:currentUserId="currentUserId"
|
:currentUserId="usersStore.currentUserId"
|
||||||
@input="setTransferId"
|
@input="setTransferId"
|
||||||
/>
|
/>
|
||||||
</n8n-input-label>
|
</n8n-input-label>
|
||||||
|
@ -53,7 +53,8 @@ import { showMessage } from "@/components/mixins/showMessage";
|
||||||
import Modal from "./Modal.vue";
|
import Modal from "./Modal.vue";
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import { IUser } from "../Interface";
|
import { IUser } from "../Interface";
|
||||||
import { mapGetters } from "vuex";
|
import { mapStores } from "pinia";
|
||||||
|
import { useUsersStore } from '@/stores/users';
|
||||||
|
|
||||||
export default mixins(showMessage).extend({
|
export default mixins(showMessage).extend({
|
||||||
components: {
|
components: {
|
||||||
|
@ -79,13 +80,12 @@ export default mixins(showMessage).extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters('users', ['allUsers', 'currentUserId']),
|
...mapStores(useUsersStore),
|
||||||
userToDelete(): IUser {
|
userToDelete(): IUser | null {
|
||||||
const getUserById = this.$store.getters['users/getUserById'];
|
return this.usersStore.getUserById(this.activeId);
|
||||||
return getUserById(this.activeId);
|
|
||||||
},
|
},
|
||||||
isPending(): boolean {
|
isPending(): boolean {
|
||||||
return this.userToDelete && !this.userToDelete.firstName;
|
return this.userToDelete ? this.userToDelete && !this.userToDelete.firstName : false;
|
||||||
},
|
},
|
||||||
title(): string {
|
title(): string {
|
||||||
const user = this.userToDelete && (this.userToDelete.fullName || this.userToDelete.email) || '';
|
const user = this.userToDelete && (this.userToDelete.fullName || this.userToDelete.email) || '';
|
||||||
|
@ -133,16 +133,17 @@ export default mixins(showMessage).extend({
|
||||||
params.transferId = this.transferId;
|
params.transferId = this.transferId;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.$store.dispatch('users/deleteUser', params);
|
await this.usersStore.deleteUser(params);
|
||||||
|
|
||||||
let message = '';
|
let message = '';
|
||||||
if (this.transferId) {
|
if (this.transferId) {
|
||||||
const getUserById = this.$store.getters['users/getUserById'];
|
const transferUser: IUser | null = this.usersStore.getUserById(this.transferId);
|
||||||
const transferUser: IUser = getUserById(this.transferId);
|
if (transferUser) {
|
||||||
message = this.$locale.baseText(
|
message = this.$locale.baseText(
|
||||||
'settings.users.transferredToUser',
|
'settings.users.transferredToUser',
|
||||||
{ interpolate: { user: transferUser.fullName || '' }},
|
{ interpolate: { user: transferUser.fullName || '' }},
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$showMessage({
|
this.$showMessage({
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { XYPosition } from '@/Interface';
|
import { XYPosition } from '@/Interface';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -66,11 +68,14 @@ export default Vue.extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNDVStore,
|
||||||
|
),
|
||||||
canDrop(): boolean {
|
canDrop(): boolean {
|
||||||
return this.$store.getters['ndv/canDraggableDrop'];
|
return this.ndvStore.canDraggableDrop;
|
||||||
},
|
},
|
||||||
stickyPosition(): XYPosition | null {
|
stickyPosition(): XYPosition | null {
|
||||||
return this.$store.getters['ndv/draggableStickyPos'];
|
return this.ndvStore.draggableStickyPos;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -111,7 +116,7 @@ export default Vue.extend({
|
||||||
this.isDragging = true;
|
this.isDragging = true;
|
||||||
|
|
||||||
const data = this.targetDataKey && this.draggingEl ? this.draggingEl.dataset.value : (this.data || '');
|
const data = this.targetDataKey && this.draggingEl ? this.draggingEl.dataset.value : (this.data || '');
|
||||||
this.$store.commit('ndv/draggableStartDragging', {type: this.type, data });
|
this.ndvStore.draggableStartDragging({type: this.type, data: data || '' });
|
||||||
|
|
||||||
this.$emit('dragstart', this.draggingEl);
|
this.$emit('dragstart', this.draggingEl);
|
||||||
document.body.style.cursor = 'grabbing';
|
document.body.style.cursor = 'grabbing';
|
||||||
|
@ -141,7 +146,7 @@ export default Vue.extend({
|
||||||
this.$emit('dragend', this.draggingEl);
|
this.$emit('dragend', this.draggingEl);
|
||||||
this.isDragging = false;
|
this.isDragging = false;
|
||||||
this.draggingEl = null;
|
this.draggingEl = null;
|
||||||
this.$store.commit('ndv/draggableStopDragging');
|
this.ndvStore.draggableStopDragging();
|
||||||
}, 0);
|
}, 0);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
|
@ -37,11 +39,14 @@ export default Vue.extend({
|
||||||
window.removeEventListener('mouseup', this.onMouseUp);
|
window.removeEventListener('mouseup', this.onMouseUp);
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNDVStore,
|
||||||
|
),
|
||||||
isDragging(): boolean {
|
isDragging(): boolean {
|
||||||
return this.$store.getters['ndv/isDraggableDragging'];
|
return this.ndvStore.isDraggableDragging;
|
||||||
},
|
},
|
||||||
draggableType(): string {
|
draggableType(): string {
|
||||||
return this.$store.getters['ndv/draggableType'];
|
return this.ndvStore.draggableType;
|
||||||
},
|
},
|
||||||
droppable(): boolean {
|
droppable(): boolean {
|
||||||
return !this.disabled && this.isDragging && this.draggableType === this.type;
|
return !this.disabled && this.isDragging && this.draggableType === this.type;
|
||||||
|
@ -60,20 +65,20 @@ export default Vue.extend({
|
||||||
this.hovering = e.clientX >= dim.left && e.clientX <= dim.right && e.clientY >= dim.top && e.clientY <= dim.bottom;
|
this.hovering = e.clientX >= dim.left && e.clientX <= dim.right && e.clientY >= dim.top && e.clientY <= dim.bottom;
|
||||||
|
|
||||||
if (!this.disabled && this.sticky && this.hovering) {
|
if (!this.disabled && this.sticky && this.hovering) {
|
||||||
this.$store.commit('ndv/setDraggableStickyPos', [dim.left + this.stickyOffset, dim.top + this.stickyOffset]);
|
this.ndvStore.setDraggableStickyPos([dim.left + this.stickyOffset, dim.top + this.stickyOffset]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onMouseUp(e: MouseEvent) {
|
onMouseUp(e: MouseEvent) {
|
||||||
if (this.activeDrop) {
|
if (this.activeDrop) {
|
||||||
const data = this.$store.getters['ndv/draggableData'];
|
const data = this.ndvStore.draggableData;
|
||||||
this.$emit('drop', data);
|
this.$emit('drop', data);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
activeDrop(active) {
|
activeDrop(active) {
|
||||||
this.$store.commit('ndv/setDraggableCanDrop', active);
|
this.ndvStore.setDraggableCanDrop(active);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
:maxlength="MAX_WORKFLOW_NAME_LENGTH"
|
:maxlength="MAX_WORKFLOW_NAME_LENGTH"
|
||||||
/>
|
/>
|
||||||
<TagsDropdown
|
<TagsDropdown
|
||||||
v-if="areTagsEnabled"
|
v-if="settingsStore.areTagsEnabled"
|
||||||
:createEnabled="true"
|
:createEnabled="true"
|
||||||
:currentTagIds="currentTagIds"
|
:currentTagIds="currentTagIds"
|
||||||
:eventBus="dropdownBus"
|
:eventBus="dropdownBus"
|
||||||
|
@ -46,9 +46,10 @@ import { workflowHelpers } from "@/components/mixins/workflowHelpers";
|
||||||
import { showMessage } from "@/components/mixins/showMessage";
|
import { showMessage } from "@/components/mixins/showMessage";
|
||||||
import TagsDropdown from "@/components/TagsDropdown.vue";
|
import TagsDropdown from "@/components/TagsDropdown.vue";
|
||||||
import Modal from "./Modal.vue";
|
import Modal from "./Modal.vue";
|
||||||
import { mapGetters } from "vuex";
|
|
||||||
import {restApi} from "@/components/mixins/restApi";
|
import {restApi} from "@/components/mixins/restApi";
|
||||||
import {IWorkflowDb} from "@/Interface";
|
import { mapStores } from "pinia";
|
||||||
|
import { useSettingsStore } from "@/stores/settings";
|
||||||
|
import { useWorkflowsStore } from "@/stores/workflows";
|
||||||
|
|
||||||
export default mixins(showMessage, workflowHelpers, restApi).extend({
|
export default mixins(showMessage, workflowHelpers, restApi).extend({
|
||||||
components: { TagsDropdown, Modal },
|
components: { TagsDropdown, Modal },
|
||||||
|
@ -68,11 +69,14 @@ export default mixins(showMessage, workflowHelpers, restApi).extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
this.name = await this.$store.dispatch('workflows/getDuplicateCurrentWorkflowName', this.data.name);
|
this.name = await this.workflowsStore.getDuplicateCurrentWorkflowName(this.data.name);
|
||||||
this.$nextTick(() => this.focusOnNameInput());
|
this.$nextTick(() => this.focusOnNameInput());
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters('settings', ['areTagsEnabled']),
|
...mapStores(
|
||||||
|
useSettingsStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
isActive(active) {
|
isActive(active) {
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import {EnterpriseEditionFeature} from "@/constants";
|
import {EnterpriseEditionFeature} from "@/constants";
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'EnterpriseEdition',
|
name: 'EnterpriseEdition',
|
||||||
|
@ -18,9 +20,10 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(useSettingsStore),
|
||||||
canAccess(): boolean {
|
canAccess(): boolean {
|
||||||
return this.features.reduce((acc: boolean, feature) => {
|
return this.features.reduce((acc: boolean, feature) => {
|
||||||
return acc && !!this.$store.getters['settings/isEnterpriseFeatureEnabled'](feature);
|
return acc && !!this.settingsStore.isEnterpriseFeatureEnabled(feature as EnterpriseEditionFeature);
|
||||||
}, true);
|
}, true);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -109,6 +109,9 @@ import {
|
||||||
INodeTypeDescription,
|
INodeTypeDescription,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { sanitizeHtml } from '@/utils';
|
import { sanitizeHtml } from '@/utils';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
copyPaste,
|
copyPaste,
|
||||||
|
@ -122,15 +125,19 @@ export default mixins(
|
||||||
VueJsonPretty,
|
VueJsonPretty,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNodeTypesStore,
|
||||||
|
useNDVStore,
|
||||||
|
),
|
||||||
displayCause(): boolean {
|
displayCause(): boolean {
|
||||||
return JSON.stringify(this.error.cause).length < MAX_DISPLAY_DATA_SIZE;
|
return JSON.stringify(this.error.cause).length < MAX_DISPLAY_DATA_SIZE;
|
||||||
},
|
},
|
||||||
parameters (): INodeProperties[] {
|
parameters (): INodeProperties[] {
|
||||||
const node = this.$store.getters['ndv/activeNode'];
|
const node = this.ndvStore.activeNode;
|
||||||
if (!node) {
|
if (!node) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const nodeType = this.$store.getters['nodeTypes/getNodeType'](node.type, node.typeVersion);
|
const nodeType = this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
|
||||||
|
|
||||||
if (nodeType === null) {
|
if (nodeType === null) {
|
||||||
return [];
|
return [];
|
||||||
|
|
|
@ -203,6 +203,9 @@ import {
|
||||||
} from 'lodash';
|
} from 'lodash';
|
||||||
|
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
externalHooks,
|
externalHooks,
|
||||||
|
@ -249,7 +252,7 @@ export default mixins(
|
||||||
this.handleAutoRefreshToggle();
|
this.handleAutoRefreshToggle();
|
||||||
|
|
||||||
this.$externalHooks().run('executionsList.openDialog');
|
this.$externalHooks().run('executionsList.openDialog');
|
||||||
this.$telemetry.track('User opened Executions log', { workflow_id: this.$store.getters.workflowId });
|
this.$telemetry.track('User opened Executions log', { workflow_id: this.workflowsStore.workflowId });
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
if (this.autoRefreshInterval) {
|
if (this.autoRefreshInterval) {
|
||||||
|
@ -258,6 +261,10 @@ export default mixins(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useUIStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
statuses () {
|
statuses () {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
@ -283,7 +290,7 @@ export default mixins(
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
activeExecutions (): IExecutionsCurrentSummaryExtended[] {
|
activeExecutions (): IExecutionsCurrentSummaryExtended[] {
|
||||||
return this.$store.getters.getActiveExecutions;
|
return this.workflowsStore.activeExecutions;
|
||||||
},
|
},
|
||||||
combinedExecutions (): IExecutionsSummary[] {
|
combinedExecutions (): IExecutionsSummary[] {
|
||||||
const returnData: IExecutionsSummary[] = [];
|
const returnData: IExecutionsSummary[] = [];
|
||||||
|
@ -408,27 +415,28 @@ export default mixins(
|
||||||
await this.restApi().deleteExecutions(sendData);
|
await this.restApi().deleteExecutions(sendData);
|
||||||
let removedCurrentlyLoadedExecution = false;
|
let removedCurrentlyLoadedExecution = false;
|
||||||
let removedActiveExecution = false;
|
let removedActiveExecution = false;
|
||||||
const currentWorkflow: string = this.$store.getters.workflowId;
|
const currentWorkflow: string = this.workflowsStore.workflowId;
|
||||||
const activeExecution: IExecutionsSummary = this.$store.getters['workflows/getActiveWorkflowExecution'];
|
const activeExecution: IExecutionsSummary | null = this.workflowsStore.activeWorkflowExecution;
|
||||||
// Also update current workflow executions view if needed
|
// Also update current workflow executions view if needed
|
||||||
for (const selectedId of Object.keys(this.selectedItems)) {
|
for (const selectedId of Object.keys(this.selectedItems)) {
|
||||||
const execution: IExecutionsSummary = this.$store.getters['workflows/getExecutionDataById'](selectedId);
|
const execution: IExecutionsSummary | undefined = this.workflowsStore.getExecutionDataById(selectedId);
|
||||||
if (execution && execution.workflowId === currentWorkflow) {
|
if (execution && execution.workflowId === currentWorkflow) {
|
||||||
this.$store.commit('workflows/deleteExecution', execution);
|
this.workflowsStore.deleteExecution(execution);
|
||||||
removedCurrentlyLoadedExecution = true;
|
removedCurrentlyLoadedExecution = true;
|
||||||
}
|
}
|
||||||
if (execution.id === activeExecution.id) {
|
if ((execution !== undefined && activeExecution !== null) && execution.id === activeExecution.id) {
|
||||||
removedActiveExecution = true;
|
removedActiveExecution = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Also update route if needed
|
// Also update route if needed
|
||||||
if (removedCurrentlyLoadedExecution) {
|
if (removedCurrentlyLoadedExecution) {
|
||||||
const currentWorkflowExecutions: IExecutionsSummary[] = this.$store.getters['workflows/currentWorkflowExecutions'];
|
const currentWorkflowExecutions: IExecutionsSummary[] = this.workflowsStore.currentWorkflowExecutions;
|
||||||
if (currentWorkflowExecutions.length === 0) {
|
if (currentWorkflowExecutions.length === 0) {
|
||||||
this.$store.commit('workflows/setActiveWorkflowExecution', null);
|
this.workflowsStore.activeWorkflowExecution = null;
|
||||||
|
|
||||||
this.$router.push({ name: VIEWS.EXECUTION_HOME, params: { name: currentWorkflow } });
|
this.$router.push({ name: VIEWS.EXECUTION_HOME, params: { name: currentWorkflow } });
|
||||||
} else if (removedActiveExecution) {
|
} else if (removedActiveExecution) {
|
||||||
this.$store.commit('workflows/setActiveWorkflowExecution', currentWorkflowExecutions[0]);
|
this.workflowsStore.activeWorkflowExecution = currentWorkflowExecutions[0];
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: VIEWS.EXECUTION_PREVIEW,
|
name: VIEWS.EXECUTION_PREVIEW,
|
||||||
params: { name: currentWorkflow, executionId: currentWorkflowExecutions[0].id },
|
params: { name: currentWorkflow, executionId: currentWorkflowExecutions[0].id },
|
||||||
|
@ -468,7 +476,7 @@ export default mixins(
|
||||||
this.retryExecution(commandData.row, loadWorkflow);
|
this.retryExecution(commandData.row, loadWorkflow);
|
||||||
|
|
||||||
this.$telemetry.track('User clicked retry execution button', {
|
this.$telemetry.track('User clicked retry execution button', {
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
execution_id: commandData.row.id,
|
execution_id: commandData.row.id,
|
||||||
retry_type: loadWorkflow ? 'current' : 'original',
|
retry_type: loadWorkflow ? 'current' : 'original',
|
||||||
});
|
});
|
||||||
|
@ -497,7 +505,7 @@ export default mixins(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$store.commit('setActiveExecutions', activeExecutions);
|
this.workflowsStore.activeExecutions = activeExecutions;
|
||||||
},
|
},
|
||||||
async loadAutoRefresh () : Promise<void> {
|
async loadAutoRefresh () : Promise<void> {
|
||||||
const filter = this.workflowFilterPast;
|
const filter = this.workflowFilterPast;
|
||||||
|
@ -517,7 +525,7 @@ export default mixins(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$store.commit('setActiveExecutions', results[1]);
|
this.workflowsStore.activeExecutions = results[1];
|
||||||
|
|
||||||
// execution IDs are typed as string, int conversion is necessary so we can order.
|
// execution IDs are typed as string, int conversion is necessary so we can order.
|
||||||
const alreadyPresentExecutionIds = this.finishedExecutions.map(exec => parseInt(exec.id, 10));
|
const alreadyPresentExecutionIds = this.finishedExecutions.map(exec => parseInt(exec.id, 10));
|
||||||
|
|
|
@ -65,6 +65,8 @@ import { showMessage } from '../mixins/showMessage';
|
||||||
import WorkflowPreview from '@/components/WorkflowPreview.vue';
|
import WorkflowPreview from '@/components/WorkflowPreview.vue';
|
||||||
import { executionHelpers, IExecutionUIData } from '../mixins/executionsHelpers';
|
import { executionHelpers, IExecutionUIData } from '../mixins/executionsHelpers';
|
||||||
import { VIEWS } from '../../constants';
|
import { VIEWS } from '../../constants';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
|
||||||
export default mixins(restApi, showMessage, executionHelpers).extend({
|
export default mixins(restApi, showMessage, executionHelpers).extend({
|
||||||
name: 'execution-preview',
|
name: 'execution-preview',
|
||||||
|
@ -77,11 +79,14 @@ export default mixins(restApi, showMessage, executionHelpers).extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useUIStore,
|
||||||
|
),
|
||||||
executionUIDetails(): IExecutionUIData | null {
|
executionUIDetails(): IExecutionUIData | null {
|
||||||
return this.activeExecution ? this.getExecutionUIDetails(this.activeExecution) : null;
|
return this.activeExecution ? this.getExecutionUIDetails(this.activeExecution) : null;
|
||||||
},
|
},
|
||||||
sidebarCollapsed(): boolean {
|
sidebarCollapsed(): boolean {
|
||||||
return this.$store.getters['ui/sidebarMenuCollapsed'];
|
return this.uiStore.sidebarMenuCollapsed;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -26,6 +26,11 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
import { PLACEHOLDER_EMPTY_WORKFLOW_ID, WORKFLOW_SETTINGS_MODAL_KEY } from '@/constants';
|
import { PLACEHOLDER_EMPTY_WORKFLOW_ID, WORKFLOW_SETTINGS_MODAL_KEY } from '@/constants';
|
||||||
import { deepCopy, IWorkflowSettings } from 'n8n-workflow';
|
import { deepCopy, IWorkflowSettings } from 'n8n-workflow';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
|
@ -60,9 +65,9 @@ export default mixins(workflowHelpers).extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.defaultValues.saveFailedExecutions = this.$store.getters.saveDataErrorExecution;
|
this.defaultValues.saveFailedExecutions = this.settingsStore.saveDataErrorExecution;
|
||||||
this.defaultValues.saveSuccessfulExecutions = this.$store.getters.saveDataSuccessExecution;
|
this.defaultValues.saveSuccessfulExecutions = this.settingsStore.saveDataSuccessExecution;
|
||||||
this.defaultValues.saveManualExecutions = this.$store.getters.saveManualExecutions;
|
this.defaultValues.saveManualExecutions = this.settingsStore.saveManualExecutions;
|
||||||
this.updateSettings(this.workflowSettings);
|
this.updateSettings(this.workflowSettings);
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -71,7 +76,13 @@ export default mixins(workflowHelpers).extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
accordionItems(): Object[] {
|
...mapStores(
|
||||||
|
useRootStore,
|
||||||
|
useSettingsStore,
|
||||||
|
useUIStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
|
accordionItems(): Object[] {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
id: 'productionExecutions',
|
id: 'productionExecutions',
|
||||||
|
@ -115,7 +126,7 @@ export default mixins(workflowHelpers).extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
workflowSettings(): IWorkflowSettings {
|
workflowSettings(): IWorkflowSettings {
|
||||||
const workflowSettings = deepCopy(this.$store.getters.workflowSettings);
|
const workflowSettings = deepCopy(this.workflowsStore.workflowSettings);
|
||||||
return workflowSettings;
|
return workflowSettings;
|
||||||
},
|
},
|
||||||
accordionIcon(): { icon: string, color: string }|null {
|
accordionIcon(): { icon: string, color: string }|null {
|
||||||
|
@ -125,16 +136,16 @@ export default mixins(workflowHelpers).extend({
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
currentWorkflowId(): string {
|
currentWorkflowId(): string {
|
||||||
return this.$store.getters.workflowId;
|
return this.workflowsStore.workflowId;
|
||||||
},
|
},
|
||||||
isNewWorkflow(): boolean {
|
isNewWorkflow(): boolean {
|
||||||
return !this.currentWorkflowId || (this.currentWorkflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID || this.currentWorkflowId === 'new');
|
return !this.currentWorkflowId || (this.currentWorkflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID || this.currentWorkflowId === 'new');
|
||||||
},
|
},
|
||||||
workflowName(): string {
|
workflowName(): string {
|
||||||
return this.$store.getters.workflowName;
|
return this.workflowsStore.workflowName;
|
||||||
},
|
},
|
||||||
currentWorkflowTagIds(): string[] {
|
currentWorkflowTagIds(): string[] {
|
||||||
return this.$store.getters.workflowTags;
|
return this.workflowsStore.workflowTags;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -146,17 +157,17 @@ export default mixins(workflowHelpers).extend({
|
||||||
onAccordionClick(event: MouseEvent): void {
|
onAccordionClick(event: MouseEvent): void {
|
||||||
if (event.target instanceof HTMLAnchorElement) {
|
if (event.target instanceof HTMLAnchorElement) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.$store.dispatch('ui/openModal', WORKFLOW_SETTINGS_MODAL_KEY);
|
this.uiStore.openModal(WORKFLOW_SETTINGS_MODAL_KEY);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onItemTooltipClick(item: string, event: MouseEvent): void {
|
onItemTooltipClick(item: string, event: MouseEvent): void {
|
||||||
if (item === 'productionExecutions' && event.target instanceof HTMLAnchorElement) {
|
if (item === 'productionExecutions' && event.target instanceof HTMLAnchorElement) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.$store.dispatch('ui/openModal', WORKFLOW_SETTINGS_MODAL_KEY);
|
this.uiStore.openModal(WORKFLOW_SETTINGS_MODAL_KEY);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openWorkflowSettings(event: MouseEvent): void {
|
openWorkflowSettings(event: MouseEvent): void {
|
||||||
this.$store.dispatch('ui/openModal', WORKFLOW_SETTINGS_MODAL_KEY);
|
this.uiStore.openModal(WORKFLOW_SETTINGS_MODAL_KEY);
|
||||||
},
|
},
|
||||||
async onSaveWorkflowClick(event: MouseEvent): void {
|
async onSaveWorkflowClick(event: MouseEvent): void {
|
||||||
let currentId = undefined;
|
let currentId = undefined;
|
||||||
|
@ -166,7 +177,7 @@ export default mixins(workflowHelpers).extend({
|
||||||
currentId = this.$route.params.name;
|
currentId = this.$route.params.name;
|
||||||
}
|
}
|
||||||
const saved = await this.saveCurrentWorkflow({ id: currentId, name: this.workflowName, tags: this.currentWorkflowTagIds });
|
const saved = await this.saveCurrentWorkflow({ id: currentId, name: this.workflowName, tags: this.currentWorkflowTagIds });
|
||||||
if (saved) this.$store.dispatch('settings/fetchPromptsData');
|
if (saved) this.settingsStore.fetchPromptsData();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -27,7 +27,9 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { PLACEHOLDER_EMPTY_WORKFLOW_ID, VIEWS } from '@/constants';
|
import { PLACEHOLDER_EMPTY_WORKFLOW_ID, VIEWS } from '@/constants';
|
||||||
import { IExecutionsSummary } from '@/Interface';
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import ExecutionsInfoAccordion from './ExecutionsInfoAccordion.vue';
|
import ExecutionsInfoAccordion from './ExecutionsInfoAccordion.vue';
|
||||||
|
|
||||||
|
@ -37,24 +39,25 @@ export default Vue.extend({
|
||||||
ExecutionsInfoAccordion,
|
ExecutionsInfoAccordion,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useUIStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
executionCount(): number {
|
executionCount(): number {
|
||||||
return (this.$store.getters['workflows/currentWorkflowExecutions'] as IExecutionsSummary[]).length;
|
return this.workflowsStore.currentWorkflowExecutions.length;
|
||||||
},
|
},
|
||||||
containsTrigger(): boolean {
|
containsTrigger(): boolean {
|
||||||
return this.$store.getters.workflowTriggerNodes.length > 0;
|
return this.workflowsStore.workflowTriggerNodes.length > 0;
|
||||||
},
|
|
||||||
currentWorkflowId(): string {
|
|
||||||
return this.$store.getters.workflowId;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onSetupFirstStep(event: MouseEvent): void {
|
onSetupFirstStep(event: MouseEvent): void {
|
||||||
this.$store.commit('ui/setAddFirstStepOnLoad', true);
|
this.uiStore.addFirstStepOnLoad = true;
|
||||||
const workflowRoute = this.getWorkflowRoute();
|
const workflowRoute = this.getWorkflowRoute();
|
||||||
this.$router.push(workflowRoute);
|
this.$router.push(workflowRoute);
|
||||||
},
|
},
|
||||||
getWorkflowRoute(): { name: string, params: {}} {
|
getWorkflowRoute(): { name: string, params: {}} {
|
||||||
const workflowId = this.currentWorkflowId || this.$route.params.name;
|
const workflowId = this.workflowsStore.workflowId || this.$route.params.name;
|
||||||
if (workflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID) {
|
if (workflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID) {
|
||||||
return { name: VIEWS.NEW_WORKFLOW, params: {} };
|
return { name: VIEWS.NEW_WORKFLOW, params: {} };
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -90,6 +90,8 @@ import { IExecutionsSummary } from "@/Interface";
|
||||||
import { Route } from 'vue-router';
|
import { Route } from 'vue-router';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { PropType } from 'vue';
|
import { PropType } from 'vue';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'executions-sidebar',
|
name: 'executions-sidebar',
|
||||||
|
@ -122,6 +124,9 @@ export default Vue.extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useUIStore,
|
||||||
|
),
|
||||||
statusFilterApplied(): boolean {
|
statusFilterApplied(): boolean {
|
||||||
return this.filter.status !== '';
|
return this.filter.status !== '';
|
||||||
},
|
},
|
||||||
|
@ -143,7 +148,7 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.autoRefresh = this.$store.getters['ui/isExecutionSidebarAutoRefreshOn'];
|
this.autoRefresh = this.uiStore.executionSidebarAutoRefresh === true;
|
||||||
if (this.autoRefresh) {
|
if (this.autoRefresh) {
|
||||||
this.autoRefreshInterval = setInterval(() => this.onRefresh(), 4000);
|
this.autoRefreshInterval = setInterval(() => this.onRefresh(), 4000);
|
||||||
}
|
}
|
||||||
|
@ -179,7 +184,7 @@ export default Vue.extend({
|
||||||
this.$emit('reloadExecutions');
|
this.$emit('reloadExecutions');
|
||||||
},
|
},
|
||||||
onAutoRefreshToggle(): void {
|
onAutoRefreshToggle(): void {
|
||||||
this.$store.commit('ui/setExecutionsSidebarAutoRefresh', this.autoRefresh);
|
this.uiStore.executionSidebarAutoRefresh = this.autoRefresh;
|
||||||
if (this.autoRefreshInterval) {
|
if (this.autoRefreshInterval) {
|
||||||
// Clear any previously existing intervals (if any - there shouldn't)
|
// Clear any previously existing intervals (if any - there shouldn't)
|
||||||
clearInterval(this.autoRefreshInterval);
|
clearInterval(this.autoRefreshInterval);
|
||||||
|
|
|
@ -37,6 +37,11 @@ import { range as _range } from 'lodash';
|
||||||
import { debounceHelper } from '../mixins/debounce';
|
import { debounceHelper } from '../mixins/debounce';
|
||||||
import { getNodeViewTab } from '../helpers';
|
import { getNodeViewTab } from '../helpers';
|
||||||
import { workflowHelpers } from '../mixins/workflowHelpers';
|
import { workflowHelpers } from '../mixins/workflowHelpers';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
export default mixins(restApi, showMessage, executionHelpers, debounceHelper, workflowHelpers).extend({
|
export default mixins(restApi, showMessage, executionHelpers, debounceHelper, workflowHelpers).extend({
|
||||||
name: 'executions-page',
|
name: 'executions-page',
|
||||||
|
@ -51,6 +56,12 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNodeTypesStore,
|
||||||
|
useSettingsStore,
|
||||||
|
useUIStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
hidePreview(): boolean {
|
hidePreview(): boolean {
|
||||||
const nothingToShow = this.executions.length === 0 && this.filterApplied;
|
const nothingToShow = this.executions.length === 0 && this.filterApplied;
|
||||||
const activeNotPresent = this.filterApplied && (this.executions as IExecutionsSummary[]).find(ex => ex.id === this.activeExecution.id) === undefined;
|
const activeNotPresent = this.filterApplied && (this.executions as IExecutionsSummary[]).find(ex => ex.id === this.activeExecution.id) === undefined;
|
||||||
|
@ -66,13 +77,13 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
return this.filter.status !== '';
|
return this.filter.status !== '';
|
||||||
},
|
},
|
||||||
workflowDataNotLoaded(): boolean {
|
workflowDataNotLoaded(): boolean {
|
||||||
return this.$store.getters.workflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID && this.$store.getters.workflowName === '';
|
return this.workflowsStore.workflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID && this.workflowsStore.workflowName === '';
|
||||||
},
|
},
|
||||||
loadedFinishedExecutionsCount(): number {
|
loadedFinishedExecutionsCount(): number {
|
||||||
return (this.$store.getters['workflows/getAllLoadedFinishedExecutions'] as IExecutionsSummary[]).length;
|
return this.workflowsStore.getAllLoadedFinishedExecutions.length;
|
||||||
},
|
},
|
||||||
totalFinishedExecutionsCount(): number {
|
totalFinishedExecutionsCount(): number {
|
||||||
return this.$store.getters['workflows/getTotalFinishedExecutionsCount'];
|
return this.workflowsStore.getTotalFinishedExecutionsCount;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch:{
|
watch:{
|
||||||
|
@ -81,9 +92,9 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
this.initView(workflowChanged);
|
this.initView(workflowChanged);
|
||||||
|
|
||||||
if (to.params.executionId) {
|
if (to.params.executionId) {
|
||||||
const execution = this.$store.getters['workflows/getExecutionDataById'](to.params.executionId);
|
const execution = this.workflowsStore.getExecutionDataById(to.params.executionId);
|
||||||
if (execution) {
|
if (execution) {
|
||||||
this.$store.commit('workflows/setActiveWorkflowExecution', execution);
|
this.workflowsStore.activeWorkflowExecution = execution;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -92,7 +103,7 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
const nextTab = getNodeViewTab(to);
|
const nextTab = getNodeViewTab(to);
|
||||||
// When leaving for a page that's not a workflow view tab, ask to save changes
|
// When leaving for a page that's not a workflow view tab, ask to save changes
|
||||||
if (!nextTab) {
|
if (!nextTab) {
|
||||||
const result = this.$store.getters.getStateIsDirty;
|
const result = this.uiStore.stateIsDirty;
|
||||||
if (result) {
|
if (result) {
|
||||||
const confirmModal = await this.confirmModal(
|
const confirmModal = await this.confirmModal(
|
||||||
this.$locale.baseText('generic.unsavedWork.confirmMessage.message'),
|
this.$locale.baseText('generic.unsavedWork.confirmMessage.message'),
|
||||||
|
@ -105,11 +116,11 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
|
|
||||||
if (confirmModal === MODAL_CONFIRMED) {
|
if (confirmModal === MODAL_CONFIRMED) {
|
||||||
const saved = await this.saveCurrentWorkflow({}, false);
|
const saved = await this.saveCurrentWorkflow({}, false);
|
||||||
if (saved) this.$store.dispatch('settings/fetchPromptsData');
|
if (saved) this.settingsStore.fetchPromptsData();
|
||||||
this.$store.commit('setStateDirty', false);
|
this.uiStore.stateIsDirty = false;
|
||||||
next();
|
next();
|
||||||
} else if (confirmModal === MODAL_CANCEL) {
|
} else if (confirmModal === MODAL_CANCEL) {
|
||||||
this.$store.commit('setStateDirty', false);
|
this.uiStore.stateIsDirty = false;
|
||||||
next();
|
next();
|
||||||
} else if (confirmModal === MODAL_CLOSE) {
|
} else if (confirmModal === MODAL_CLOSE) {
|
||||||
next(false);
|
next(false);
|
||||||
|
@ -122,8 +133,8 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
const workflowUpdated = this.$route.params.name !== this.$store.getters.workflowId;
|
const workflowUpdated = this.$route.params.name !== this.workflowsStore.workflowId;
|
||||||
const onNewWorkflow = this.$route.params.name === 'new' && this.$store.getters.workflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID;
|
const onNewWorkflow = this.$route.params.name === 'new' && this.workflowsStore.workflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID;
|
||||||
const shouldUpdate = workflowUpdated && !onNewWorkflow;
|
const shouldUpdate = workflowUpdated && !onNewWorkflow;
|
||||||
await this.initView(shouldUpdate);
|
await this.initView(shouldUpdate);
|
||||||
if (!shouldUpdate) {
|
if (!shouldUpdate) {
|
||||||
|
@ -134,11 +145,11 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
methods: {
|
methods: {
|
||||||
async initView(loadWorkflow: boolean) : Promise<void> {
|
async initView(loadWorkflow: boolean) : Promise<void> {
|
||||||
if (loadWorkflow) {
|
if (loadWorkflow) {
|
||||||
if (this.$store.getters['nodeTypes/allNodeTypes'].length === 0) {
|
if (this.nodeTypesStore.allNodeTypes.length === 0) {
|
||||||
await this.$store.dispatch('nodeTypes/getNodeTypes');
|
await this.nodeTypesStore.getNodeTypes();
|
||||||
}
|
}
|
||||||
await this.openWorkflow(this.$route.params.name);
|
await this.openWorkflow(this.$route.params.name);
|
||||||
this.$store.commit('ui/setNodeViewInitialized', false);
|
this.uiStore.nodeViewInitialized = false;
|
||||||
this.setExecutions();
|
this.setExecutions();
|
||||||
if (this.activeExecution) {
|
if (this.activeExecution) {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
|
@ -193,7 +204,7 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
currentExecutions.push(newExecution);
|
currentExecutions.push(newExecution);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.$store.commit('workflows/setCurrentWorkflowExecutions', currentExecutions);
|
this.workflowsStore.currentWorkflowExecutions = currentExecutions;
|
||||||
this.loadingMore = false;
|
this.loadingMore = false;
|
||||||
},
|
},
|
||||||
async onDeleteCurrentExecution(): Promise<void> {
|
async onDeleteCurrentExecution(): Promise<void> {
|
||||||
|
@ -203,13 +214,13 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
await this.setExecutions();
|
await this.setExecutions();
|
||||||
// Select first execution in the list after deleting the current one
|
// Select first execution in the list after deleting the current one
|
||||||
if (this.executions.length > 0) {
|
if (this.executions.length > 0) {
|
||||||
this.$store.commit('workflows/setActiveWorkflowExecution', this.executions[0]);
|
this.workflowsStore.activeWorkflowExecution = this.executions[0];
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: VIEWS.EXECUTION_PREVIEW,
|
name: VIEWS.EXECUTION_PREVIEW,
|
||||||
params: { name: this.currentWorkflow, executionId: this.executions[0].id },
|
params: { name: this.currentWorkflow, executionId: this.executions[0].id },
|
||||||
}).catch(()=>{});;
|
}).catch(()=>{});;
|
||||||
} else { // If there are no executions left, show empty state and clear active execution from the store
|
} else { // If there are no executions left, show empty state and clear active execution from the store
|
||||||
this.$store.commit('workflows/setActiveWorkflowExecution', null);
|
this.workflowsStore.activeWorkflowExecution = null;
|
||||||
this.$router.push({ name: VIEWS.EXECUTION_HOME, params: { name: this.currentWorkflow } });
|
this.$router.push({ name: VIEWS.EXECUTION_HOME, params: { name: this.currentWorkflow } });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -233,7 +244,7 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
},
|
},
|
||||||
async setExecutions(): Promise<void> {
|
async setExecutions(): Promise<void> {
|
||||||
const workflowExecutions = await this.loadExecutions();
|
const workflowExecutions = await this.loadExecutions();
|
||||||
this.$store.commit('workflows/setCurrentWorkflowExecutions', workflowExecutions);
|
this.workflowsStore.currentWorkflowExecutions = workflowExecutions;
|
||||||
this.setActiveExecution();
|
this.setActiveExecution();
|
||||||
},
|
},
|
||||||
async loadAutoRefresh(): Promise<void> {
|
async loadAutoRefresh(): Promise<void> {
|
||||||
|
@ -284,12 +295,12 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
}
|
}
|
||||||
|
|
||||||
existingExecutions = existingExecutions.filter(execution => !gaps.includes(parseInt(execution.id, 10)) && lastId >= parseInt(execution.id, 10));
|
existingExecutions = existingExecutions.filter(execution => !gaps.includes(parseInt(execution.id, 10)) && lastId >= parseInt(execution.id, 10));
|
||||||
this.$store.commit('workflows/setCurrentWorkflowExecutions', existingExecutions);
|
this.workflowsStore.currentWorkflowExecutions = existingExecutions;
|
||||||
if (updatedActiveExecution !== null) {
|
if (updatedActiveExecution !== null) {
|
||||||
this.$store.commit('workflows/setActiveWorkflowExecution', updatedActiveExecution);
|
this.workflowsStore.activeWorkflowExecution = updatedActiveExecution;
|
||||||
} else {
|
} else {
|
||||||
const activeNotInTheList = existingExecutions.find(ex => ex.id === this.activeExecution.id) === undefined;
|
const activeNotInTheList = existingExecutions.find(ex => ex.id === this.activeExecution.id) === undefined;
|
||||||
if (activeNotInTheList) {
|
if (activeNotInTheList && this.executions.length > 0) {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: VIEWS.EXECUTION_PREVIEW,
|
name: VIEWS.EXECUTION_PREVIEW,
|
||||||
params: { name: this.currentWorkflow, executionId: this.executions[0].id },
|
params: { name: this.currentWorkflow, executionId: this.executions[0].id },
|
||||||
|
@ -303,7 +314,7 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const executions: IExecutionsSummary[] =
|
const executions: IExecutionsSummary[] =
|
||||||
await this.$store.dispatch('workflows/loadCurrentWorkflowExecutions', this.filter);
|
await this.workflowsStore.loadCurrentWorkflowExecutions(this.filter);
|
||||||
return executions;
|
return executions;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$showError(
|
this.$showError(
|
||||||
|
@ -316,14 +327,14 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
setActiveExecution(): void {
|
setActiveExecution(): void {
|
||||||
const activeExecutionId = this.$route.params.executionId;
|
const activeExecutionId = this.$route.params.executionId;
|
||||||
if (activeExecutionId) {
|
if (activeExecutionId) {
|
||||||
const execution = this.$store.getters['workflows/getExecutionDataById'](activeExecutionId);
|
const execution = this.workflowsStore.getExecutionDataById(activeExecutionId);
|
||||||
if (execution) {
|
if (execution) {
|
||||||
this.$store.commit('workflows/setActiveWorkflowExecution', execution);
|
this.workflowsStore.activeWorkflowExecution = execution;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If there is no execution in the route, select the first one
|
// If there is no execution in the route, select the first one
|
||||||
if (this.$store.getters['workflows/getActiveWorkflowExecution'] === null && this.executions.length > 0) {
|
if (this.workflowsStore.activeWorkflowExecution === null && this.executions.length > 0) {
|
||||||
this.$store.commit('workflows/setActiveWorkflowExecution', this.executions[0]);
|
this.workflowsStore.activeWorkflowExecution = this.executions[0];
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: VIEWS.EXECUTION_PREVIEW,
|
name: VIEWS.EXECUTION_PREVIEW,
|
||||||
params: { name: this.currentWorkflow, executionId: this.executions[0].id },
|
params: { name: this.currentWorkflow, executionId: this.executions[0].id },
|
||||||
|
@ -353,19 +364,20 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
}
|
}
|
||||||
await this.addNodes(data.nodes, data.connections);
|
await this.addNodes(data.nodes, data.connections);
|
||||||
|
|
||||||
this.$store.commit('setActive', data.active || false);
|
this.workflowsStore.setActive(data.active || false);
|
||||||
this.$store.commit('setWorkflowId', workflowId);
|
this.workflowsStore.setWorkflowId(workflowId);
|
||||||
this.$store.commit('setWorkflowName', { newName: data.name, setStateDirty: false });
|
this.workflowsStore.setWorkflowName({ newName: data.name, setStateDirty: false });
|
||||||
this.$store.commit('setWorkflowSettings', data.settings || {});
|
this.workflowsStore.setWorkflowSettings(data.settings || {});
|
||||||
this.$store.commit('setWorkflowPinData', data.pinData || {});
|
this.workflowsStore.setWorkflowPinData(data.pinData || {});
|
||||||
const tags = (data.tags || []) as ITag[];
|
const tags = (data.tags || []) as ITag[];
|
||||||
this.$store.commit('tags/upsertTags', tags);
|
|
||||||
const tagIds = tags.map((tag) => tag.id);
|
const tagIds = tags.map((tag) => tag.id);
|
||||||
this.$store.commit('setWorkflowTagIds', tagIds || []);
|
this.workflowsStore.setWorkflowTagIds(tagIds || []);
|
||||||
this.$store.commit('setWorkflowHash', data.hash);
|
this.workflowsStore.setWorkflowHash(data.hash);
|
||||||
|
|
||||||
|
this.$store.commit('tags/upsertTags', tags);
|
||||||
|
|
||||||
this.$externalHooks().run('workflow.open', { workflowId, workflowName: data.name });
|
this.$externalHooks().run('workflow.open', { workflowId, workflowName: data.name });
|
||||||
this.$store.commit('setStateDirty', false);
|
this.uiStore.stateIsDirty = false;
|
||||||
},
|
},
|
||||||
async addNodes(nodes: INodeUi[], connections?: IConnections) {
|
async addNodes(nodes: INodeUi[], connections?: IConnections) {
|
||||||
if (!nodes || !nodes.length) {
|
if (!nodes || !nodes.length) {
|
||||||
|
@ -380,7 +392,7 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
node.id = uuid();
|
node.id = uuid();
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeType = this.$store.getters['nodeTypes/getNodeType'](node.type, node.typeVersion) as INodeTypeDescription | null;
|
nodeType = this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
|
||||||
|
|
||||||
// Make sure that some properties always exist
|
// Make sure that some properties always exist
|
||||||
if (!node.hasOwnProperty('disabled')) {
|
if (!node.hasOwnProperty('disabled')) {
|
||||||
|
@ -409,7 +421,7 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$store.commit('addNode', node);
|
this.workflowsStore.addNode(node);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Load the connections
|
// Load the connections
|
||||||
|
@ -438,7 +450,7 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
},
|
},
|
||||||
] as [IConnection, IConnection];
|
] as [IConnection, IConnection];
|
||||||
|
|
||||||
this.$store.commit('addConnection', { connection: connectionData, setStateDirty: false });
|
this.workflowsStore.addConnection({ connection: connectionData, setStateDirty: false });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -446,7 +458,7 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async loadNodesProperties(nodeInfos: INodeTypeNameVersion[]): Promise<void> {
|
async loadNodesProperties(nodeInfos: INodeTypeNameVersion[]): Promise<void> {
|
||||||
const allNodes: INodeTypeDescription[] = this.$store.getters['nodeTypes/allNodeTypes'];
|
const allNodes: INodeTypeDescription[] = this.nodeTypesStore.allNodeTypes;
|
||||||
|
|
||||||
const nodesToBeFetched: INodeTypeNameVersion[] = [];
|
const nodesToBeFetched: INodeTypeNameVersion[] = [];
|
||||||
allNodes.forEach(node => {
|
allNodes.forEach(node => {
|
||||||
|
@ -463,12 +475,12 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
|
|
||||||
if (nodesToBeFetched.length > 0) {
|
if (nodesToBeFetched.length > 0) {
|
||||||
// Only call API if node information is actually missing
|
// Only call API if node information is actually missing
|
||||||
await this.$store.dispatch('nodeTypes/getNodesInformation', nodesToBeFetched);
|
await this.nodeTypesStore.getNodesInformation(nodesToBeFetched);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async loadActiveWorkflows(): Promise<void> {
|
async loadActiveWorkflows(): Promise<void> {
|
||||||
const activeWorkflows = await this.restApi().getActiveWorkflows();
|
const activeWorkflows = await this.restApi().getActiveWorkflows();
|
||||||
this.$store.commit('setActiveWorkflows', activeWorkflows);
|
this.workflowsStore.activeWorkflows = activeWorkflows;
|
||||||
},
|
},
|
||||||
async onRetryExecution(payload: { execution: IExecutionsSummary, command: string }) {
|
async onRetryExecution(payload: { execution: IExecutionsSummary, command: string }) {
|
||||||
const loadWorkflow = payload.command === 'current-workflow';
|
const loadWorkflow = payload.command === 'current-workflow';
|
||||||
|
@ -482,7 +494,7 @@ export default mixins(restApi, showMessage, executionHelpers, debounceHelper, wo
|
||||||
this.loadAutoRefresh();
|
this.loadAutoRefresh();
|
||||||
|
|
||||||
this.$telemetry.track('User clicked retry execution button', {
|
this.$telemetry.track('User clicked retry execution button', {
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
execution_id: payload.execution.id,
|
execution_id: payload.execution.id,
|
||||||
retry_type: loadWorkflow ? 'current' : 'original',
|
retry_type: loadWorkflow ? 'current' : 'original',
|
||||||
});
|
});
|
||||||
|
|
|
@ -54,6 +54,9 @@ import { genericHelpers } from '@/components/mixins/genericHelpers';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import { hasExpressionMapping } from './helpers';
|
import { hasExpressionMapping } from './helpers';
|
||||||
import { debounceHelper } from './mixins/debounce';
|
import { debounceHelper } from './mixins/debounce';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
externalHooks,
|
externalHooks,
|
||||||
|
@ -78,6 +81,12 @@ export default mixins(
|
||||||
latestValue: '',
|
latestValue: '',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNDVStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
valueChanged (value: string, forceUpdate = false) {
|
valueChanged (value: string, forceUpdate = false) {
|
||||||
this.latestValue = value;
|
this.latestValue = value;
|
||||||
|
@ -120,11 +129,11 @@ export default mixins(
|
||||||
node_name: string;
|
node_name: string;
|
||||||
} = {
|
} = {
|
||||||
event_version: '2',
|
event_version: '2',
|
||||||
node_type_dest: this.$store.getters['ndv/activeNode'].type,
|
node_type_dest: this.ndvStore.activeNode? this.ndvStore.activeNode.type : '',
|
||||||
parameter_name_dest: this.parameter.displayName,
|
parameter_name_dest: this.parameter.displayName,
|
||||||
is_immediate_input: false,
|
is_immediate_input: false,
|
||||||
variable_expression: eventData.variable,
|
variable_expression: eventData.variable,
|
||||||
node_name: this.$store.getters['ndv/activeNode'].name,
|
node_name: this.ndvStore.activeNode? this.ndvStore.activeNode.name : '',
|
||||||
};
|
};
|
||||||
|
|
||||||
if (eventData.variable) {
|
if (eventData.variable) {
|
||||||
|
@ -142,9 +151,9 @@ export default mixins(
|
||||||
|
|
||||||
if (splitVar[0].startsWith('$node')) {
|
if (splitVar[0].startsWith('$node')) {
|
||||||
const sourceNodeName = splitVar[0].split('"')[1];
|
const sourceNodeName = splitVar[0].split('"')[1];
|
||||||
trackProperties.node_type_source = this.$store.getters.getNodeByName(sourceNodeName).type;
|
trackProperties.node_type_source = this.workflowsStore.getNodeByName(sourceNodeName)?.type;
|
||||||
const nodeConnections: Array<Array<{ node: string }>> = this.$store.getters.outgoingConnectionsByNodeName(sourceNodeName).main;
|
const nodeConnections: Array<Array<{ node: string }>> = this.workflowsStore.outgoingConnectionsByNodeName(sourceNodeName).main;
|
||||||
trackProperties.is_immediate_input = (nodeConnections && nodeConnections[0] && !!nodeConnections[0].find(({ node }) => node === this.$store.getters['ndv/activeNode'].name)) ? true : false;
|
trackProperties.is_immediate_input = (nodeConnections && nodeConnections[0] && !!nodeConnections[0].find(({ node }) => node === this.ndvStore.activeNode?.name || '')) ? true : false;
|
||||||
|
|
||||||
if (splitVar[1].startsWith('parameter')) {
|
if (splitVar[1].startsWith('parameter')) {
|
||||||
trackProperties.parameter_name_source = splitVar[1].split('"')[1];
|
trackProperties.parameter_name_source = splitVar[1].split('"')[1];
|
||||||
|
@ -173,9 +182,9 @@ export default mixins(
|
||||||
if (!newValue) {
|
if (!newValue) {
|
||||||
const telemetryPayload = {
|
const telemetryPayload = {
|
||||||
empty_expression: (this.value === '=') || (this.value === '={{}}') || !this.value,
|
empty_expression: (this.value === '=') || (this.value === '={{}}') || !this.value,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
source: this.eventSource,
|
source: this.eventSource,
|
||||||
session_id: this.$store.getters['ndv/ndvSessionId'],
|
session_id: this.ndvStore.sessionId,
|
||||||
has_parameter: this.value.includes('$parameter'),
|
has_parameter: this.value.includes('$parameter'),
|
||||||
has_mapping: hasExpressionMapping(this.value),
|
has_mapping: hasExpressionMapping(this.value),
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,6 +28,11 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {IFakeDoor} from '@/Interface';
|
import {IFakeDoor} from '@/Interface';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useUsersStore } from '@/stores/users';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
|
@ -43,23 +48,28 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useRootStore,
|
||||||
|
useSettingsStore,
|
||||||
|
useUIStore,
|
||||||
|
useUsersStore,
|
||||||
|
),
|
||||||
userId(): string {
|
userId(): string {
|
||||||
return this.$store.getters['users/currentUserId'];
|
return this.usersStore.currentUserId || '';
|
||||||
},
|
|
||||||
versionCli(): string {
|
|
||||||
return this.$store.getters['settings/versionCli'];
|
|
||||||
},
|
},
|
||||||
instanceId(): string {
|
instanceId(): string {
|
||||||
return this.$store.getters.instanceId;
|
return this.rootStore.instanceId;
|
||||||
},
|
},
|
||||||
featureInfo(): IFakeDoor {
|
featureInfo(): IFakeDoor | undefined {
|
||||||
return this.$store.getters['ui/getFakeDoorById'](this.featureId);
|
return this.uiStore.getFakeDoorById(this.featureId);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openLinkPage() {
|
openLinkPage() {
|
||||||
window.open(`${this.featureInfo.linkURL}&u=${this.instanceId}#${this.userId}&v=${this.versionCli}`, '_blank');
|
if (this.featureInfo) {
|
||||||
this.$telemetry.track('user clicked feature waiting list button', {feature: this.featureId});
|
window.open(`${this.featureInfo.linkURL}&u=${this.instanceId}#${this.userId}&v=${this.rootStore.versionCli}`, '_blank');
|
||||||
|
this.$telemetry.track('user clicked feature waiting list button', {feature: this.featureId});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { VIEWS } from '@/constants';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'TemplateList',
|
name: 'GoBackButton',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
routeHasHistory: false,
|
routeHasHistory: false,
|
||||||
|
|
|
@ -42,6 +42,8 @@ import Vue from 'vue';
|
||||||
|
|
||||||
import { ITemplatesNode } from '@/Interface';
|
import { ITemplatesNode } from '@/Interface';
|
||||||
import { INodeTypeDescription } from 'n8n-workflow';
|
import { INodeTypeDescription } from 'n8n-workflow';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
|
||||||
interface NodeIconData {
|
interface NodeIconData {
|
||||||
type: string;
|
type: string;
|
||||||
|
@ -72,6 +74,9 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useRootStore,
|
||||||
|
),
|
||||||
fontStyleData(): object {
|
fontStyleData(): object {
|
||||||
return {
|
return {
|
||||||
'max-width': this.size + 'px',
|
'max-width': this.size + 'px',
|
||||||
|
@ -115,7 +120,7 @@ export default Vue.extend({
|
||||||
return (nodeType as ITemplatesNode).iconData;
|
return (nodeType as ITemplatesNode).iconData;
|
||||||
}
|
}
|
||||||
|
|
||||||
const restUrl = this.$store.getters.getRestUrl;
|
const restUrl = this.rootStore.getRestUrl;
|
||||||
|
|
||||||
if (nodeType.icon) {
|
if (nodeType.icon) {
|
||||||
const [type, path] = nodeType.icon.split(':');
|
const [type, path] = nodeType.icon.split(':');
|
||||||
|
|
|
@ -50,6 +50,9 @@ import {
|
||||||
import { showMessage } from './mixins/showMessage';
|
import { showMessage } from './mixins/showMessage';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import { INodeUi } from '@/Interface';
|
import { INodeUi } from '@/Interface';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
|
||||||
export default mixins(showMessage).extend({
|
export default mixins(showMessage).extend({
|
||||||
name: 'ImportCurlModal',
|
name: 'ImportCurlModal',
|
||||||
|
@ -64,8 +67,12 @@ export default mixins(showMessage).extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
node(): INodeUi {
|
...mapStores(
|
||||||
return this.$store.getters['ndv/activeNode'];
|
useNDVStore,
|
||||||
|
useUIStore,
|
||||||
|
),
|
||||||
|
node(): INodeUi | null {
|
||||||
|
return this.ndvStore.activeNode;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -80,8 +87,7 @@ export default mixins(showMessage).extend({
|
||||||
if (curlCommand === '') return;
|
if (curlCommand === '') return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const parameters = await this.$store.dispatch('ui/getCurlToJson', curlCommand);
|
const parameters = await this.uiStore.getCurlToJson(curlCommand);
|
||||||
|
|
||||||
const url = parameters['parameters.url'];
|
const url = parameters['parameters.url'];
|
||||||
|
|
||||||
const invalidProtocol = CURL_IMPORT_NOT_SUPPORTED_PROTOCOLS.find((p) =>
|
const invalidProtocol = CURL_IMPORT_NOT_SUPPORTED_PROTOCOLS.find((p) =>
|
||||||
|
@ -89,7 +95,8 @@ export default mixins(showMessage).extend({
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!invalidProtocol) {
|
if (!invalidProtocol) {
|
||||||
this.$store.dispatch('ui/setHttpNodeParameters', {
|
this.uiStore.setHttpNodeParameters({
|
||||||
|
name: IMPORT_CURL_MODAL_KEY,
|
||||||
parameters: JSON.stringify(parameters),
|
parameters: JSON.stringify(parameters),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -114,7 +121,7 @@ export default mixins(showMessage).extend({
|
||||||
|
|
||||||
this.sendTelemetry({ success: false, invalidProtocol: false });
|
this.sendTelemetry({ success: false, invalidProtocol: false });
|
||||||
} finally {
|
} finally {
|
||||||
this.$store.dispatch('ui/setCurlCommand', { command: this.curlCommand });
|
this.uiStore.setCurlCommand({ name: IMPORT_CURL_MODAL_KEY, command: this.curlCommand });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
showProtocolErrorWithSupportedNode(protocol: string, node: string): void {
|
showProtocolErrorWithSupportedNode(protocol: string, node: string): void {
|
||||||
|
@ -168,7 +175,7 @@ export default mixins(showMessage).extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.curlCommand = this.$store.getters['ui/getCurlCommand'];
|
this.curlCommand = this.uiStore.getCurlCommand || '';
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
(this.$refs.input as HTMLTextAreaElement).focus();
|
(this.$refs.input as HTMLTextAreaElement).focus();
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { IMPORT_CURL_MODAL_KEY } from '@/constants';
|
import { IMPORT_CURL_MODAL_KEY } from '@/constants';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import { showMessage } from './mixins/showMessage';
|
import { showMessage } from './mixins/showMessage';
|
||||||
|
|
||||||
|
@ -23,9 +25,12 @@ export default mixins(showMessage).extend({
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapStores(useUIStore),
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onImportCurlClicked() {
|
onImportCurlClicked() {
|
||||||
this.$store.dispatch('ui/openModal', IMPORT_CURL_MODAL_KEY);
|
this.uiStore.openModal(IMPORT_CURL_MODAL_KEY);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -76,6 +76,10 @@ import mixins from 'vue-typed-mixins';
|
||||||
import NodeExecuteButton from './NodeExecuteButton.vue';
|
import NodeExecuteButton from './NodeExecuteButton.vue';
|
||||||
import WireMeUp from './WireMeUp.vue';
|
import WireMeUp from './WireMeUp.vue';
|
||||||
import { CRON_NODE_TYPE, INTERVAL_NODE_TYPE, LOCAL_STORAGE_MAPPING_FLAG, MANUAL_TRIGGER_NODE_TYPE, SCHEDULE_TRIGGER_NODE_TYPE, START_NODE_TYPE } from '@/constants';
|
import { CRON_NODE_TYPE, INTERVAL_NODE_TYPE, LOCAL_STORAGE_MAPPING_FLAG, MANUAL_TRIGGER_NODE_TYPE, SCHEDULE_TRIGGER_NODE_TYPE, START_NODE_TYPE } from '@/constants';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
workflowHelpers,
|
workflowHelpers,
|
||||||
|
@ -111,8 +115,13 @@ export default mixins(
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNodeTypesStore,
|
||||||
|
useNDVStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
focusedMappableInput(): string {
|
focusedMappableInput(): string {
|
||||||
return this.$store.getters['ndv/focusedMappableInput'];
|
return this.ndvStore.focusedMappableInput;
|
||||||
},
|
},
|
||||||
isUserOnboarded(): boolean {
|
isUserOnboarded(): boolean {
|
||||||
return window.localStorage.getItem(LOCAL_STORAGE_MAPPING_FLAG) === 'true';
|
return window.localStorage.getItem(LOCAL_STORAGE_MAPPING_FLAG) === 'true';
|
||||||
|
@ -129,8 +138,8 @@ export default mixins(
|
||||||
if (!this.workflowRunning) {
|
if (!this.workflowRunning) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const triggeredNode = this.$store.getters.executedNode;
|
const triggeredNode = this.workflowsStore.executedNode;
|
||||||
const executingNode = this.$store.getters.executingNode;
|
const executingNode = this.workflowsStore.executingNode;
|
||||||
if (this.activeNode && triggeredNode === this.activeNode.name && this.activeNode.name !== executingNode) {
|
if (this.activeNode && triggeredNode === this.activeNode.name && this.activeNode.name !== executingNode) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -141,16 +150,16 @@ export default mixins(
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
workflowRunning (): boolean {
|
workflowRunning (): boolean {
|
||||||
return this.$store.getters.isActionActive('workflowRunning');
|
return this.uiStore.isActionActive('workflowRunning');
|
||||||
},
|
},
|
||||||
currentWorkflow(): Workflow {
|
currentWorkflow(): Workflow {
|
||||||
return this.workflow as Workflow;
|
return this.workflow as Workflow;
|
||||||
},
|
},
|
||||||
activeNode (): INodeUi | null {
|
activeNode (): INodeUi | null {
|
||||||
return this.$store.getters['ndv/activeNode'];
|
return this.ndvStore.activeNode;
|
||||||
},
|
},
|
||||||
currentNode (): INodeUi | null {
|
currentNode (): INodeUi | null {
|
||||||
return this.$store.getters.getNodeByName(this.currentNodeName);
|
return this.workflowsStore.getNodeByName(this.currentNodeName);
|
||||||
},
|
},
|
||||||
connectedCurrentNodeOutputs(): number[] | undefined {
|
connectedCurrentNodeOutputs(): number[] | undefined {
|
||||||
const search = this.parentNodes.find(({name}) => name === this.currentNodeName);
|
const search = this.parentNodes.find(({name}) => name === this.currentNodeName);
|
||||||
|
@ -174,7 +183,7 @@ export default mixins(
|
||||||
activeNodeType () : INodeTypeDescription | null {
|
activeNodeType () : INodeTypeDescription | null {
|
||||||
if (!this.activeNode) return null;
|
if (!this.activeNode) return null;
|
||||||
|
|
||||||
return this.$store.getters['nodeTypes/getNodeType'](this.activeNode.type, this.activeNode.typeVersion);
|
return this.nodeTypesStore.getNodeType(this.activeNode.type, this.activeNode.typeVersion);
|
||||||
},
|
},
|
||||||
isMultiInputNode (): boolean {
|
isMultiInputNode (): boolean {
|
||||||
return this.activeNodeType !== null && this.activeNodeType.inputs.length > 1;
|
return this.activeNodeType !== null && this.activeNodeType.inputs.length > 1;
|
||||||
|
@ -214,7 +223,7 @@ export default mixins(
|
||||||
if (this.activeNode) {
|
if (this.activeNode) {
|
||||||
this.$telemetry.track('User clicked ndv button', {
|
this.$telemetry.track('User clicked ndv button', {
|
||||||
node_type: this.activeNode.type,
|
node_type: this.activeNode.type,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
pane: 'input',
|
pane: 'input',
|
||||||
type: 'executePrevious',
|
type: 'executePrevious',
|
||||||
|
@ -238,7 +247,7 @@ export default mixins(
|
||||||
if (this.activeNode) {
|
if (this.activeNode) {
|
||||||
this.$telemetry.track('User clicked ndv link', {
|
this.$telemetry.track('User clicked ndv link', {
|
||||||
node_type: this.activeNode.type,
|
node_type: this.activeNode.type,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
pane: 'input',
|
pane: 'input',
|
||||||
type: 'not-connected-help',
|
type: 'not-connected-help',
|
||||||
|
|
|
@ -32,6 +32,8 @@ import Vue from "vue";
|
||||||
import { IFormInputs, IInviteResponse } from "@/Interface";
|
import { IFormInputs, IInviteResponse } from "@/Interface";
|
||||||
import { VALID_EMAIL_REGEX, INVITE_USER_MODAL_KEY } from "@/constants";
|
import { VALID_EMAIL_REGEX, INVITE_USER_MODAL_KEY } from "@/constants";
|
||||||
import { ROLE } from "@/modules/userHelpers";
|
import { ROLE } from "@/modules/userHelpers";
|
||||||
|
import { mapStores } from "pinia";
|
||||||
|
import { useUsersStore } from "@/stores/users";
|
||||||
|
|
||||||
const NAME_EMAIL_FORMAT_REGEX = /^.* <(.*)>$/;
|
const NAME_EMAIL_FORMAT_REGEX = /^.* <(.*)>$/;
|
||||||
|
|
||||||
|
@ -101,6 +103,7 @@ export default mixins(showMessage).extend({
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(useUsersStore),
|
||||||
emailsCount(): number {
|
emailsCount(): number {
|
||||||
return this.emails.split(',').filter((email: string) => !!email.trim()).length;
|
return this.emails.split(',').filter((email: string) => !!email.trim()).length;
|
||||||
},
|
},
|
||||||
|
@ -156,7 +159,7 @@ export default mixins(showMessage).extend({
|
||||||
throw new Error(this.$locale.baseText('settings.users.noUsersToInvite'));
|
throw new Error(this.$locale.baseText('settings.users.noUsersToInvite'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const invited: IInviteResponse[] = await this.$store.dispatch('users/inviteUsers', emails);
|
const invited: IInviteResponse[] = await this.usersStore.inviteUsers(emails);
|
||||||
const invitedEmails = invited.reduce((accu, {user, error}) => {
|
const invitedEmails = invited.reduce((accu, {user, error}) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
accu.error.push(user.email);
|
accu.error.push(user.email);
|
||||||
|
|
|
@ -7,12 +7,17 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useRootStore,
|
||||||
|
),
|
||||||
basePath(): string {
|
basePath(): string {
|
||||||
return this.$store.getters.getBaseUrl;
|
return this.rootStore.baseUrl;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -43,12 +43,14 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import mixins from "vue-typed-mixins";
|
import mixins from "vue-typed-mixins";
|
||||||
|
|
||||||
import { IExecutionResponse } from "../../../Interface";
|
import { IExecutionResponse, IExecutionsSummary } from "../../../Interface";
|
||||||
|
|
||||||
import { titleChange } from "@/components/mixins/titleChange";
|
import { titleChange } from "@/components/mixins/titleChange";
|
||||||
|
|
||||||
import ShortenName from "@/components/ShortenName.vue";
|
import ShortenName from "@/components/ShortenName.vue";
|
||||||
import ReadOnly from "@/components/MainHeader/ExecutionDetails/ReadOnly.vue";
|
import ReadOnly from "@/components/MainHeader/ExecutionDetails/ReadOnly.vue";
|
||||||
|
import { mapStores } from "pinia";
|
||||||
|
import { useWorkflowsStore } from "@/stores/workflows";
|
||||||
|
|
||||||
export default mixins(titleChange).extend({
|
export default mixins(titleChange).extend({
|
||||||
name: "ExecutionDetails",
|
name: "ExecutionDetails",
|
||||||
|
@ -57,24 +59,27 @@ export default mixins(titleChange).extend({
|
||||||
ReadOnly,
|
ReadOnly,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
executionId(): string | undefined {
|
executionId(): string | undefined {
|
||||||
return this.$route.params.id;
|
return this.$route.params.id;
|
||||||
},
|
},
|
||||||
executionFinished(): boolean {
|
executionFinished(): boolean {
|
||||||
const fullExecution = this.$store.getters.getWorkflowExecution;
|
const fullExecution = this.workflowsStore.getWorkflowExecution;
|
||||||
|
|
||||||
return !!fullExecution && fullExecution.finished;
|
return !!fullExecution && fullExecution.finished;
|
||||||
},
|
},
|
||||||
executionWaiting(): boolean {
|
executionWaiting(): boolean {
|
||||||
const fullExecution = this.$store.getters.getWorkflowExecution;
|
const fullExecution = this.workflowsStore.getWorkflowExecution as IExecutionsSummary;
|
||||||
|
|
||||||
return !!fullExecution && !!fullExecution.waitTill;
|
return !!fullExecution && !!fullExecution.waitTill;
|
||||||
},
|
},
|
||||||
workflowExecution(): IExecutionResponse | null {
|
workflowExecution(): IExecutionResponse | null {
|
||||||
return this.$store.getters.getWorkflowExecution;
|
return this.workflowsStore.getWorkflowExecution;
|
||||||
},
|
},
|
||||||
workflowName(): string {
|
workflowName(): string {
|
||||||
return this.$store.getters.workflowName;
|
return this.workflowsStore.workflowName;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div :class="{'main-header': true, expanded: !sidebarMenuCollapsed}">
|
<div :class="{'main-header': true, expanded: !this.uiStore.sidebarMenuCollapsed}">
|
||||||
<div v-show="!hideMenuBar" class="top-menu">
|
<div v-show="!hideMenuBar" class="top-menu">
|
||||||
<ExecutionDetails v-if="isExecutionPage" />
|
<ExecutionDetails v-if="isExecutionPage" />
|
||||||
<WorkflowDetails v-else />
|
<WorkflowDetails v-else />
|
||||||
|
@ -12,7 +12,6 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import { mapGetters } from 'vuex';
|
|
||||||
import { pushConnection } from '@/components/mixins/pushConnection';
|
import { pushConnection } from '@/components/mixins/pushConnection';
|
||||||
import WorkflowDetails from '@/components/MainHeader/WorkflowDetails.vue';
|
import WorkflowDetails from '@/components/MainHeader/WorkflowDetails.vue';
|
||||||
import ExecutionDetails from '@/components/MainHeader/ExecutionDetails/ExecutionDetails.vue';
|
import ExecutionDetails from '@/components/MainHeader/ExecutionDetails/ExecutionDetails.vue';
|
||||||
|
@ -21,6 +20,9 @@ import { MAIN_HEADER_TABS, PLACEHOLDER_EMPTY_WORKFLOW_ID, STICKY_NODE_TYPE, VIEW
|
||||||
import { IExecutionsSummary, INodeUi, ITabBarItem } from '@/Interface';
|
import { IExecutionsSummary, INodeUi, ITabBarItem } from '@/Interface';
|
||||||
import { workflowHelpers } from '../mixins/workflowHelpers';
|
import { workflowHelpers } from '../mixins/workflowHelpers';
|
||||||
import { Route } from 'vue-router';
|
import { Route } from 'vue-router';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
pushConnection,
|
pushConnection,
|
||||||
|
@ -36,13 +38,14 @@ export default mixins(
|
||||||
return {
|
return {
|
||||||
activeHeaderTab: MAIN_HEADER_TABS.WORKFLOW,
|
activeHeaderTab: MAIN_HEADER_TABS.WORKFLOW,
|
||||||
workflowToReturnTo: '',
|
workflowToReturnTo: '',
|
||||||
dirtyState: this.$store.getters.getStateIsDirty,
|
dirtyState: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters('ui', [
|
...mapStores(
|
||||||
'sidebarMenuCollapsed',
|
useNDVStore,
|
||||||
]),
|
useUIStore,
|
||||||
|
),
|
||||||
tabBarItems(): ITabBarItem[] {
|
tabBarItems(): ITabBarItem[] {
|
||||||
return [
|
return [
|
||||||
{ value: MAIN_HEADER_TABS.WORKFLOW, label: this.$locale.baseText('generic.workflow') },
|
{ value: MAIN_HEADER_TABS.WORKFLOW, label: this.$locale.baseText('generic.workflow') },
|
||||||
|
@ -53,25 +56,26 @@ export default mixins(
|
||||||
return this.$route.name === VIEWS.EXECUTION;
|
return this.$route.name === VIEWS.EXECUTION;
|
||||||
},
|
},
|
||||||
activeNode (): INodeUi | null {
|
activeNode (): INodeUi | null {
|
||||||
return this.$store.getters['ndv/activeNode'];
|
return this.ndvStore.activeNode;
|
||||||
},
|
},
|
||||||
hideMenuBar(): boolean {
|
hideMenuBar(): boolean {
|
||||||
return Boolean(this.activeNode && this.activeNode.type !== STICKY_NODE_TYPE);
|
return Boolean(this.activeNode && this.activeNode.type !== STICKY_NODE_TYPE);
|
||||||
},
|
},
|
||||||
workflowName (): string {
|
workflowName (): string {
|
||||||
return this.$store.getters.workflowName;
|
return this.workflowsStore.workflowName;
|
||||||
},
|
},
|
||||||
currentWorkflow (): string {
|
currentWorkflow (): string {
|
||||||
return this.$route.params.name || this.$store.getters.workflowId;
|
return this.$route.params.name || this.workflowsStore.workflowId;
|
||||||
},
|
},
|
||||||
onWorkflowPage(): boolean {
|
onWorkflowPage(): boolean {
|
||||||
return this.$route.meta && (this.$route.meta.nodeView || this.$route.meta.keepWorkflowAlive === true);
|
return this.$route.meta && (this.$route.meta.nodeView || this.$route.meta.keepWorkflowAlive === true);
|
||||||
},
|
},
|
||||||
activeExecution(): IExecutionsSummary {
|
activeExecution(): IExecutionsSummary {
|
||||||
return this.$store.getters['workflows/getActiveWorkflowExecution'];
|
return this.workflowsStore.activeWorkflowExecution as IExecutionsSummary;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
this.dirtyState = this.uiStore.stateIsDirty;
|
||||||
this.syncTabsWithRoute(this.$route);
|
this.syncTabsWithRoute(this.$route);
|
||||||
// Initialize the push connection
|
// Initialize the push connection
|
||||||
this.pushConnect();
|
this.pushConnect();
|
||||||
|
@ -109,13 +113,13 @@ export default mixins(
|
||||||
} else {
|
} else {
|
||||||
if (this.$route.name !== VIEWS.NEW_WORKFLOW) {
|
if (this.$route.name !== VIEWS.NEW_WORKFLOW) {
|
||||||
this.$router.push({ name: VIEWS.NEW_WORKFLOW });
|
this.$router.push({ name: VIEWS.NEW_WORKFLOW });
|
||||||
this.$store.commit('setStateDirty', this.dirtyState);
|
this.uiStore.stateIsDirty = this.dirtyState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.activeHeaderTab = MAIN_HEADER_TABS.WORKFLOW;
|
this.activeHeaderTab = MAIN_HEADER_TABS.WORKFLOW;
|
||||||
break;
|
break;
|
||||||
case MAIN_HEADER_TABS.EXECUTIONS:
|
case MAIN_HEADER_TABS.EXECUTIONS:
|
||||||
this.dirtyState = this.$store.getters.getStateIsDirty;
|
this.dirtyState = this.uiStore.stateIsDirty;
|
||||||
this.workflowToReturnTo = this.currentWorkflow;
|
this.workflowToReturnTo = this.currentWorkflow;
|
||||||
const routeWorkflowId = this.currentWorkflow === PLACEHOLDER_EMPTY_WORKFLOW_ID ? 'new' : this.currentWorkflow;
|
const routeWorkflowId = this.currentWorkflow === PLACEHOLDER_EMPTY_WORKFLOW_ID ? 'new' : this.currentWorkflow;
|
||||||
if (this.activeExecution) {
|
if (this.activeExecution) {
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
import Vue, { PropType } from 'vue';
|
import Vue, { PropType } from 'vue';
|
||||||
import { ITabBarItem } from '@/Interface';
|
import { ITabBarItem } from '@/Interface';
|
||||||
import { MAIN_HEADER_TABS } from '@/constants';
|
import { MAIN_HEADER_TABS } from '@/constants';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'tab-bar',
|
name: 'tab-bar',
|
||||||
|
@ -31,8 +33,11 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useUIStore,
|
||||||
|
),
|
||||||
mainSidebarCollapsed(): boolean {
|
mainSidebarCollapsed(): boolean {
|
||||||
return this.$store.getters['ui/sidebarMenuCollapsed'];
|
return this.uiStore.sidebarMenuCollapsed;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
</template>
|
</template>
|
||||||
</BreakpointsObserver>
|
</BreakpointsObserver>
|
||||||
|
|
||||||
<span v-if="areTagsEnabled" class="tags">
|
<span v-if="settingsStore.areTagsEnabled" class="tags">
|
||||||
<div
|
<div
|
||||||
v-if="isTagsEditEnabled">
|
v-if="isTagsEditEnabled">
|
||||||
<TagsDropdown
|
<TagsDropdown
|
||||||
|
@ -105,6 +105,11 @@ import { IWorkflowDataUpdate, IWorkflowToShare } from "@/Interface";
|
||||||
import { saveAs } from 'file-saver';
|
import { saveAs } from 'file-saver';
|
||||||
import { titleChange } from "../mixins/titleChange";
|
import { titleChange } from "../mixins/titleChange";
|
||||||
import type { MessageBoxInputData } from 'element-ui/types/message-box';
|
import type { MessageBoxInputData } from 'element-ui/types/message-box';
|
||||||
|
import { mapStores } from "pinia";
|
||||||
|
import { useUIStore } from "@/stores/ui";
|
||||||
|
import { useSettingsStore } from "@/stores/settings";
|
||||||
|
import { useWorkflowsStore } from "@/stores/workflows";
|
||||||
|
import { useRootStore } from "@/stores/n8nRootStore";
|
||||||
|
|
||||||
const hasChanged = (prev: string[], curr: string[]) => {
|
const hasChanged = (prev: string[], curr: string[]) => {
|
||||||
if (prev.length !== curr.length) {
|
if (prev.length !== curr.length) {
|
||||||
|
@ -138,24 +143,32 @@ export default mixins(workflowHelpers, titleChange).extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapStores(
|
||||||
isWorkflowActive: "isActive",
|
useRootStore,
|
||||||
workflowName: "workflowName",
|
useSettingsStore,
|
||||||
isDirty: "getStateIsDirty",
|
useUIStore,
|
||||||
currentWorkflowTagIds: "workflowTags",
|
useWorkflowsStore,
|
||||||
}),
|
),
|
||||||
...mapGetters('settings', ['areTagsEnabled']),
|
isWorkflowActive(): boolean {
|
||||||
|
return this.workflowsStore.isWorkflowActive;
|
||||||
|
},
|
||||||
|
workflowName(): string {
|
||||||
|
return this.workflowsStore.workflowName;
|
||||||
|
},
|
||||||
|
isDirty(): boolean {
|
||||||
|
return this.uiStore.stateIsDirty;
|
||||||
|
},
|
||||||
|
currentWorkflowTagIds(): string[] {
|
||||||
|
return this.workflowsStore.workflowTags;
|
||||||
|
},
|
||||||
isNewWorkflow(): boolean {
|
isNewWorkflow(): boolean {
|
||||||
return !this.currentWorkflowId || (this.currentWorkflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID || this.currentWorkflowId === 'new');
|
return !this.currentWorkflowId || (this.currentWorkflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID || this.currentWorkflowId === 'new');
|
||||||
},
|
},
|
||||||
isWorkflowSaving(): boolean {
|
isWorkflowSaving(): boolean {
|
||||||
return this.$store.getters.isActionActive("workflowSaving");
|
return this.uiStore.isActionActive('workflowSaving');
|
||||||
},
|
},
|
||||||
currentWorkflowId(): string {
|
currentWorkflowId(): string {
|
||||||
return this.$store.getters.workflowId;
|
return this.workflowsStore.workflowId;
|
||||||
},
|
|
||||||
workflowName (): string {
|
|
||||||
return this.$store.getters.workflowName;
|
|
||||||
},
|
},
|
||||||
onWorkflowPage(): boolean {
|
onWorkflowPage(): boolean {
|
||||||
return this.$route.meta && (this.$route.meta.nodeView || this.$route.meta.keepWorkflowAlive === true);
|
return this.$route.meta && (this.$route.meta.nodeView || this.$route.meta.keepWorkflowAlive === true);
|
||||||
|
@ -209,7 +222,7 @@ export default mixins(workflowHelpers, titleChange).extend({
|
||||||
currentId = this.$route.params.name;
|
currentId = this.$route.params.name;
|
||||||
}
|
}
|
||||||
const saved = await this.saveCurrentWorkflow({ id: currentId, name: this.workflowName, tags: this.currentWorkflowTagIds });
|
const saved = await this.saveCurrentWorkflow({ id: currentId, name: this.workflowName, tags: this.currentWorkflowTagIds });
|
||||||
if (saved) this.$store.dispatch('settings/fetchPromptsData');
|
if (saved) await this.settingsStore.fetchPromptsData();
|
||||||
},
|
},
|
||||||
onTagsEditEnable() {
|
onTagsEditEnable() {
|
||||||
this.$data.appliedTagIds = this.currentWorkflowTagIds;
|
this.$data.appliedTagIds = this.currentWorkflowTagIds;
|
||||||
|
@ -314,12 +327,12 @@ export default mixins(workflowHelpers, titleChange).extend({
|
||||||
async onWorkflowMenuSelect(action: string): Promise<void> {
|
async onWorkflowMenuSelect(action: string): Promise<void> {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case WORKFLOW_MENU_ACTIONS.DUPLICATE: {
|
case WORKFLOW_MENU_ACTIONS.DUPLICATE: {
|
||||||
await this.$store.dispatch('ui/openModalWithData', {
|
this.uiStore.openModalWithData({
|
||||||
name: DUPLICATE_MODAL_KEY,
|
name: DUPLICATE_MODAL_KEY,
|
||||||
data: {
|
data: {
|
||||||
id: this.$store.getters.workflowId,
|
id: this.workflowsStore.workflowId,
|
||||||
name: this.$store.getters.workflowName,
|
name: this.workflowsStore.workflowName,
|
||||||
tags: this.$store.getters.workflowTags,
|
tags: this.workflowsStore.workflowTags,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
@ -334,7 +347,7 @@ export default mixins(workflowHelpers, titleChange).extend({
|
||||||
const exportData: IWorkflowToShare = {
|
const exportData: IWorkflowToShare = {
|
||||||
...data,
|
...data,
|
||||||
meta: {
|
meta: {
|
||||||
instanceId: this.$store.getters.instanceId,
|
instanceId: this.rootStore.instanceId,
|
||||||
},
|
},
|
||||||
tags: (tags || []).map(tagId => {
|
tags: (tags || []).map(tagId => {
|
||||||
const {usageCount, ...tag} = this.$store.getters["tags/getTagById"](tagId);
|
const {usageCount, ...tag} = this.$store.getters["tags/getTagById"](tagId);
|
||||||
|
@ -347,7 +360,7 @@ export default mixins(workflowHelpers, titleChange).extend({
|
||||||
type: 'application/json;charset=utf-8',
|
type: 'application/json;charset=utf-8',
|
||||||
});
|
});
|
||||||
|
|
||||||
let workflowName = this.$store.getters.workflowName || 'unsaved_workflow';
|
let workflowName = this.workflowName || 'unsaved_workflow';
|
||||||
workflowName = workflowName.replace(/[^a-z0-9]/gi, '_');
|
workflowName = workflowName.replace(/[^a-z0-9]/gi, '_');
|
||||||
|
|
||||||
this.$telemetry.track('User exported workflow', { workflow_id: workflowData.id });
|
this.$telemetry.track('User exported workflow', { workflow_id: workflowData.id });
|
||||||
|
@ -376,7 +389,7 @@ export default mixins(workflowHelpers, titleChange).extend({
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WORKFLOW_MENU_ACTIONS.SETTINGS: {
|
case WORKFLOW_MENU_ACTIONS.SETTINGS: {
|
||||||
this.$store.dispatch('ui/openModal', WORKFLOW_SETTINGS_MODAL_KEY);
|
this.uiStore.openModal(WORKFLOW_SETTINGS_MODAL_KEY);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WORKFLOW_MENU_ACTIONS.DELETE: {
|
case WORKFLOW_MENU_ACTIONS.DELETE: {
|
||||||
|
@ -404,7 +417,7 @@ export default mixins(workflowHelpers, titleChange).extend({
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.$store.commit('setStateDirty', false);
|
this.uiStore.stateIsDirty = false;
|
||||||
// Reset tab title since workflow is deleted.
|
// Reset tab title since workflow is deleted.
|
||||||
this.$titleReset();
|
this.$titleReset();
|
||||||
this.$showMessage({
|
this.$showMessage({
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
<!-- This dropdown is only enabled when sidebar is collapsed -->
|
<!-- This dropdown is only enabled when sidebar is collapsed -->
|
||||||
<el-dropdown :disabled="!isCollapsed" placement="right-end" trigger="click" @command="onUserActionToggle">
|
<el-dropdown :disabled="!isCollapsed" placement="right-end" trigger="click" @command="onUserActionToggle">
|
||||||
<div :class="{[$style.avatar]: true, ['clickable']: isCollapsed }">
|
<div :class="{[$style.avatar]: true, ['clickable']: isCollapsed }">
|
||||||
<n8n-avatar :firstName="currentUser.firstName" :lastName="currentUser.lastName" size="small" />
|
<n8n-avatar :firstName="usersStore.currentUser.firstName" :lastName="usersStore.currentUser.lastName" size="small" />
|
||||||
<el-dropdown-menu slot="dropdown">
|
<el-dropdown-menu slot="dropdown">
|
||||||
<el-dropdown-item command="settings">{{ $locale.baseText('settings') }}</el-dropdown-item>
|
<el-dropdown-item command="settings">{{ $locale.baseText('settings') }}</el-dropdown-item>
|
||||||
<el-dropdown-item command="logout">{{ $locale.baseText('auth.signout') }}</el-dropdown-item>
|
<el-dropdown-item command="logout">{{ $locale.baseText('auth.signout') }}</el-dropdown-item>
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
</div>
|
</div>
|
||||||
<div :class="{ ['ml-2xs']: true, [$style.userName]: true, [$style.expanded]: fullyExpanded }">
|
<div :class="{ ['ml-2xs']: true, [$style.userName]: true, [$style.expanded]: fullyExpanded }">
|
||||||
<n8n-text size="small" :bold="true" color="text-dark">{{currentUser.fullName}}</n8n-text>
|
<n8n-text size="small" :bold="true" color="text-dark">{{usersStore.currentUser.fullName}}</n8n-text>
|
||||||
</div>
|
</div>
|
||||||
<div :class="{ [$style.userActions]: true, [$style.expanded]: fullyExpanded }">
|
<div :class="{ [$style.userActions]: true, [$style.expanded]: fullyExpanded }">
|
||||||
<n8n-action-dropdown :items="userMenuItems" placement="top-start" @select="onUserActionToggle" />
|
<n8n-action-dropdown :items="userMenuItems" placement="top-start" @select="onUserActionToggle" />
|
||||||
|
@ -78,12 +78,17 @@ import {
|
||||||
VERSIONS_MODAL_KEY,
|
VERSIONS_MODAL_KEY,
|
||||||
EXECUTIONS_MODAL_KEY,
|
EXECUTIONS_MODAL_KEY,
|
||||||
VIEWS,
|
VIEWS,
|
||||||
WORKFLOW_OPEN_MODAL_KEY,
|
|
||||||
PLACEHOLDER_EMPTY_WORKFLOW_ID,
|
PLACEHOLDER_EMPTY_WORKFLOW_ID,
|
||||||
} from '@/constants';
|
} from '@/constants';
|
||||||
import { userHelpers } from './mixins/userHelpers';
|
import { userHelpers } from './mixins/userHelpers';
|
||||||
import { debounceHelper } from './mixins/debounce';
|
import { debounceHelper } from './mixins/debounce';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
import { useUsersStore } from '@/stores/users';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
genericHelpers,
|
genericHelpers,
|
||||||
|
@ -105,36 +110,34 @@ export default mixins(
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
basePath: this.$store.getters.getBaseUrl,
|
basePath: '',
|
||||||
fullyExpanded: false,
|
fullyExpanded: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters('ui', {
|
...mapStores(
|
||||||
isCollapsed: 'sidebarMenuCollapsed',
|
useRootStore,
|
||||||
isNodeView: 'isNodeView',
|
useSettingsStore,
|
||||||
}),
|
useUIStore,
|
||||||
|
useUsersStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
...mapGetters('versions', [
|
...mapGetters('versions', [
|
||||||
'hasVersionUpdates',
|
'hasVersionUpdates',
|
||||||
'nextVersions',
|
'nextVersions',
|
||||||
]),
|
]),
|
||||||
...mapGetters('users', [
|
isCollapsed(): boolean {
|
||||||
'canUserAccessSidebarUserInfo',
|
return this.uiStore.sidebarMenuCollapsed;
|
||||||
'currentUser',
|
},
|
||||||
]),
|
|
||||||
...mapGetters('settings', [
|
|
||||||
'isTemplatesEnabled',
|
|
||||||
'isUserManagementEnabled',
|
|
||||||
]),
|
|
||||||
canUserAccessSettings(): boolean {
|
canUserAccessSettings(): boolean {
|
||||||
const accessibleRoute = this.findFirstAccessibleSettingsRoute();
|
const accessibleRoute = this.findFirstAccessibleSettingsRoute();
|
||||||
return accessibleRoute !== null;
|
return accessibleRoute !== null;
|
||||||
},
|
},
|
||||||
showUserArea(): boolean {
|
showUserArea(): boolean {
|
||||||
return this.isUserManagementEnabled && this.canUserAccessSidebarUserInfo && this.currentUser;
|
return this.settingsStore.isUserManagementEnabled && this.usersStore.canUserAccessSidebarUserInfo && this.usersStore.currentUser !== null;
|
||||||
},
|
},
|
||||||
workflowExecution (): IExecutionResponse | null {
|
workflowExecution (): IExecutionResponse | null {
|
||||||
return this.$store.getters.getWorkflowExecution;
|
return this.workflowsStore.getWorkflowExecution;
|
||||||
},
|
},
|
||||||
userMenuItems (): object[] {
|
userMenuItems (): object[] {
|
||||||
return [
|
return [
|
||||||
|
@ -150,7 +153,7 @@ export default mixins(
|
||||||
},
|
},
|
||||||
mainMenuItems (): IMenuItem[] {
|
mainMenuItems (): IMenuItem[] {
|
||||||
const items: IMenuItem[] = [];
|
const items: IMenuItem[] = [];
|
||||||
const injectedItems = this.$store.getters.sidebarMenuItems as IMenuItem[];
|
const injectedItems = this.uiStore.sidebarMenuItems;
|
||||||
|
|
||||||
if (injectedItems && injectedItems.length > 0) {
|
if (injectedItems && injectedItems.length > 0) {
|
||||||
for(const item of injectedItems) {
|
for(const item of injectedItems) {
|
||||||
|
@ -182,7 +185,7 @@ export default mixins(
|
||||||
icon: 'box-open',
|
icon: 'box-open',
|
||||||
label: this.$locale.baseText('mainSidebar.templates'),
|
label: this.$locale.baseText('mainSidebar.templates'),
|
||||||
position: 'top',
|
position: 'top',
|
||||||
available: this.isTemplatesEnabled,
|
available: this.settingsStore.isTemplatesEnabled,
|
||||||
activateOnRouteNames: [ VIEWS.TEMPLATES ],
|
activateOnRouteNames: [ VIEWS.TEMPLATES ],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -204,7 +207,7 @@ export default mixins(
|
||||||
icon: 'cog',
|
icon: 'cog',
|
||||||
label: this.$locale.baseText('settings'),
|
label: this.$locale.baseText('settings'),
|
||||||
position: 'bottom',
|
position: 'bottom',
|
||||||
available: this.canUserAccessSettings && this.currentUser,
|
available: this.canUserAccessSettings && this.usersStore.currentUser !== null,
|
||||||
activateOnRouteNames: [ VIEWS.USERS_SETTINGS, VIEWS.API_SETTINGS, VIEWS.PERSONAL_SETTINGS ],
|
activateOnRouteNames: [ VIEWS.USERS_SETTINGS, VIEWS.API_SETTINGS, VIEWS.PERSONAL_SETTINGS ],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -266,13 +269,14 @@ export default mixins(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
|
this.basePath = this.rootStore.baseUrl;
|
||||||
if (this.$refs.user) {
|
if (this.$refs.user) {
|
||||||
this.$externalHooks().run('mainSidebar.mounted', { userRef: this.$refs.user });
|
this.$externalHooks().run('mainSidebar.mounted', { userRef: this.$refs.user });
|
||||||
}
|
}
|
||||||
if (window.innerWidth < 900 || this.isNodeView) {
|
if (window.innerWidth < 900 || this.uiStore.isNodeView) {
|
||||||
this.$store.commit('ui/collapseSidebarMenu');
|
this.uiStore.sidebarMenuCollapsed = true;
|
||||||
} else {
|
} else {
|
||||||
this.$store.commit('ui/expandSidebarMenu');
|
this.uiStore.sidebarMenuCollapsed = false;
|
||||||
}
|
}
|
||||||
await Vue.nextTick();
|
await Vue.nextTick();
|
||||||
this.fullyExpanded = !this.isCollapsed;
|
this.fullyExpanded = !this.isCollapsed;
|
||||||
|
@ -285,7 +289,7 @@ export default mixins(
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
trackHelpItemClick (itemType: string) {
|
trackHelpItemClick (itemType: string) {
|
||||||
this.$telemetry.track('User clicked help resource', { type: itemType, workflow_id: this.$store.getters.workflowId });
|
this.$telemetry.track('User clicked help resource', { type: itemType, workflow_id: this.workflowsStore.workflowId });
|
||||||
},
|
},
|
||||||
async onUserActionToggle(action: string) {
|
async onUserActionToggle(action: string) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
|
@ -301,8 +305,7 @@ export default mixins(
|
||||||
},
|
},
|
||||||
async onLogout() {
|
async onLogout() {
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch('users/logout');
|
await this.usersStore.logout();
|
||||||
|
|
||||||
const route = this.$router.resolve({ name: VIEWS.SIGNIN });
|
const route = this.$router.resolve({ name: VIEWS.SIGNIN });
|
||||||
window.open(route.href, '_self');
|
window.open(route.href, '_self');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -310,7 +313,7 @@ export default mixins(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
toggleCollapse () {
|
toggleCollapse () {
|
||||||
this.$store.commit('ui/toggleSidebarMenuCollapse');
|
this.uiStore.toggleSidebarMenuCollapse();
|
||||||
// When expanding, delay showing some element to ensure smooth animation
|
// When expanding, delay showing some element to ensure smooth animation
|
||||||
if (!this.isCollapsed) {
|
if (!this.isCollapsed) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -321,7 +324,7 @@ export default mixins(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openUpdatesPanel() {
|
openUpdatesPanel() {
|
||||||
this.$store.dispatch('ui/openModal', VERSIONS_MODAL_KEY);
|
this.uiStore.openModal(VERSIONS_MODAL_KEY);
|
||||||
},
|
},
|
||||||
async handleSelect (key: string) {
|
async handleSelect (key: string) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
@ -344,7 +347,7 @@ export default mixins(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'executions': {
|
case 'executions': {
|
||||||
this.$store.dispatch('ui/openModal', EXECUTIONS_MODAL_KEY);
|
this.uiStore.openModal(EXECUTIONS_MODAL_KEY);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'settings': {
|
case 'settings': {
|
||||||
|
@ -359,7 +362,7 @@ export default mixins(
|
||||||
}
|
}
|
||||||
case 'about': {
|
case 'about': {
|
||||||
this.trackHelpItemClick('about');
|
this.trackHelpItemClick('about');
|
||||||
this.$store.dispatch('ui/openModal', ABOUT_MODAL_KEY);
|
this.uiStore.openModal(ABOUT_MODAL_KEY);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'quickstart':
|
case 'quickstart':
|
||||||
|
@ -373,7 +376,7 @@ export default mixins(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async createNewWorkflow (): Promise<void> {
|
async createNewWorkflow (): Promise<void> {
|
||||||
const result = this.$store.getters.getStateIsDirty;
|
const result = this.uiStore.stateIsDirty;
|
||||||
if(result) {
|
if(result) {
|
||||||
const confirmModal = await this.confirmModal(
|
const confirmModal = await this.confirmModal(
|
||||||
this.$locale.baseText('generic.unsavedWork.confirmMessage.message'),
|
this.$locale.baseText('generic.unsavedWork.confirmMessage.message'),
|
||||||
|
@ -385,7 +388,7 @@ export default mixins(
|
||||||
);
|
);
|
||||||
if (confirmModal === MODAL_CONFIRMED) {
|
if (confirmModal === MODAL_CONFIRMED) {
|
||||||
const saved = await this.saveCurrentWorkflow({}, false);
|
const saved = await this.saveCurrentWorkflow({}, false);
|
||||||
if (saved) this.$store.dispatch('settings/fetchPromptsData');
|
if (saved) await this.settingsStore.fetchPromptsData();
|
||||||
if (this.$router.currentRoute.name === VIEWS.NEW_WORKFLOW) {
|
if (this.$router.currentRoute.name === VIEWS.NEW_WORKFLOW) {
|
||||||
this.$root.$emit('newWorkflow');
|
this.$root.$emit('newWorkflow');
|
||||||
} else {
|
} else {
|
||||||
|
@ -396,11 +399,11 @@ export default mixins(
|
||||||
type: 'success',
|
type: 'success',
|
||||||
});
|
});
|
||||||
} else if (confirmModal === MODAL_CANCEL) {
|
} else if (confirmModal === MODAL_CANCEL) {
|
||||||
this.$store.commit('setStateDirty', false);
|
this.uiStore.stateIsDirty = false;
|
||||||
if (this.$router.currentRoute.name === VIEWS.NEW_WORKFLOW) {
|
if (this.$router.currentRoute.name === VIEWS.NEW_WORKFLOW) {
|
||||||
this.$root.$emit('newWorkflow');
|
this.$root.$emit('newWorkflow');
|
||||||
} else {
|
} else {
|
||||||
this.$store.commit('setWorkflowId', PLACEHOLDER_EMPTY_WORKFLOW_ID);
|
this.workflowsStore.setWorkflowId(PLACEHOLDER_EMPTY_WORKFLOW_ID);
|
||||||
this.$router.push({ name: VIEWS.NEW_WORKFLOW });
|
this.$router.push({ name: VIEWS.NEW_WORKFLOW });
|
||||||
}
|
}
|
||||||
this.$showMessage({
|
this.$showMessage({
|
||||||
|
@ -412,7 +415,7 @@ export default mixins(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.$router.currentRoute.name !== VIEWS.NEW_WORKFLOW) {
|
if (this.$router.currentRoute.name !== VIEWS.NEW_WORKFLOW) {
|
||||||
this.$store.commit('setWorkflowId', PLACEHOLDER_EMPTY_WORKFLOW_ID);
|
this.workflowsStore.setWorkflowId(PLACEHOLDER_EMPTY_WORKFLOW_ID);
|
||||||
this.$router.push({ name: VIEWS.NEW_WORKFLOW });
|
this.$router.push({ name: VIEWS.NEW_WORKFLOW });
|
||||||
}
|
}
|
||||||
this.$showMessage({
|
this.$showMessage({
|
||||||
|
@ -447,7 +450,7 @@ export default mixins(
|
||||||
},
|
},
|
||||||
checkWidthAndAdjustSidebar (width: number) {
|
checkWidthAndAdjustSidebar (width: number) {
|
||||||
if (width < 900) {
|
if (width < 900) {
|
||||||
this.$store.commit('ui/collapseSidebarMenu');
|
this.uiStore.sidebarMenuCollapsed = true;
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
this.fullyExpanded = !this.isCollapsed;
|
this.fullyExpanded = !this.isCollapsed;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<el-dialog
|
<el-dialog
|
||||||
:visible="visible"
|
:visible="uiStore.isModalOpen(this.$props.name)"
|
||||||
:before-close="closeDialog"
|
:before-close="closeDialog"
|
||||||
:class="{'dialog-wrapper': true, [$style.center]: center, scrollable: scrollable}"
|
:class="{'dialog-wrapper': true, [$style.center]: center, scrollable: scrollable}"
|
||||||
:width="width"
|
:width="width"
|
||||||
|
@ -38,6 +38,8 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { mapStores } from "pinia";
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: "Modal",
|
name: "Modal",
|
||||||
|
@ -118,7 +120,7 @@ export default Vue.extend({
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$props.eventBus.$on('closeAll', () => {
|
this.$props.eventBus.$on('closeAll', () => {
|
||||||
this.closeAllDialogs();
|
this.uiStore.closeAllModals();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,51 +132,8 @@ export default Vue.extend({
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
window.removeEventListener('keydown', this.onWindowKeydown);
|
window.removeEventListener('keydown', this.onWindowKeydown);
|
||||||
},
|
},
|
||||||
methods: {
|
|
||||||
onWindowKeydown(event: KeyboardEvent) {
|
|
||||||
if (!this.isActive) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event && event.keyCode === 13) {
|
|
||||||
this.handleEnter();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleEnter() {
|
|
||||||
if (this.isActive) {
|
|
||||||
this.$emit('enter');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
closeAllDialogs() {
|
|
||||||
this.$store.commit('ui/closeAllModals');
|
|
||||||
},
|
|
||||||
async closeDialog() {
|
|
||||||
if (this.beforeClose) {
|
|
||||||
const shouldClose = await this.beforeClose();
|
|
||||||
if (shouldClose === false) { // must be strictly false to stop modal from closing
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$store.commit('ui/closeModal', this.$props.name);
|
|
||||||
},
|
|
||||||
getCustomClass() {
|
|
||||||
let classes = this.$props.customClass || '';
|
|
||||||
|
|
||||||
if (this.$props.classic) {
|
|
||||||
classes = `${classes} classic`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return classes;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
isActive(): boolean {
|
...mapStores(useUIStore),
|
||||||
return this.$store.getters['ui/isModalActive'](this.$props.name);
|
|
||||||
},
|
|
||||||
visible(): boolean {
|
|
||||||
return this.$store.getters['ui/isModalOpen'](this.$props.name);
|
|
||||||
},
|
|
||||||
styles() {
|
styles() {
|
||||||
const styles: {[prop: string]: string} = {};
|
const styles: {[prop: string]: string} = {};
|
||||||
if (this.height) {
|
if (this.height) {
|
||||||
|
@ -195,6 +154,40 @@ export default Vue.extend({
|
||||||
return styles;
|
return styles;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
methods: {
|
||||||
|
onWindowKeydown(event: KeyboardEvent) {
|
||||||
|
if (!this.uiStore.isModalActive(this.$props.name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event && event.keyCode === 13) {
|
||||||
|
this.handleEnter();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleEnter() {
|
||||||
|
if (this.uiStore.isModalActive(this.$props.name)) {
|
||||||
|
this.$emit('enter');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async closeDialog() {
|
||||||
|
if (this.beforeClose) {
|
||||||
|
const shouldClose = await this.beforeClose();
|
||||||
|
if (shouldClose === false) { // must be strictly false to stop modal from closing
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.uiStore.closeModal(this.$props.name);
|
||||||
|
},
|
||||||
|
getCustomClass() {
|
||||||
|
let classes = this.$props.customClass || '';
|
||||||
|
|
||||||
|
if (this.$props.classic) {
|
||||||
|
classes = `${classes} classic`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return classes;
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<el-drawer
|
<el-drawer
|
||||||
:direction="direction"
|
:direction="direction"
|
||||||
:visible="visible"
|
:visible="uiStore.isModalOpen(this.$props.name)"
|
||||||
:size="width"
|
:size="width"
|
||||||
:before-close="close"
|
:before-close="close"
|
||||||
:modal="modal"
|
:modal="modal"
|
||||||
|
@ -19,6 +19,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { useUIStore } from "@/stores/ui";
|
||||||
|
import { mapStores } from "pinia";
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
|
@ -65,9 +67,12 @@ export default Vue.extend({
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
window.removeEventListener('keydown', this.onWindowKeydown);
|
window.removeEventListener('keydown', this.onWindowKeydown);
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapStores(useUIStore),
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onWindowKeydown(event: KeyboardEvent) {
|
onWindowKeydown(event: KeyboardEvent) {
|
||||||
if (!this.isActive) {
|
if (!this.uiStore.isModalActive(this.$props.name)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +81,7 @@ export default Vue.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleEnter() {
|
handleEnter() {
|
||||||
if (this.isActive) {
|
if (this.uiStore.isModalActive(this.$props.name)) {
|
||||||
this.$emit('enter');
|
this.$emit('enter');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -87,16 +92,7 @@ export default Vue.extend({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.uiStore.closeModal(this.$props.name);
|
||||||
this.$store.commit('ui/closeModal', this.$props.name);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
isActive(): boolean {
|
|
||||||
return this.$store.getters['ui/isModalActive'](this.$props.name);
|
|
||||||
},
|
|
||||||
visible(): boolean {
|
|
||||||
return this.$store.getters['ui/isModalOpen'](this.$props.name);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,40 +1,36 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-if="isOpen(name) || keepAlive"
|
v-if="uiStore.isModalOpen(name) || keepAlive"
|
||||||
>
|
>
|
||||||
<slot
|
<slot
|
||||||
:modalName="name"
|
:modalName="name"
|
||||||
:active="isActive(name)"
|
:active="uiStore.isModalActive(name)"
|
||||||
:open="isOpen(name)"
|
:open="uiStore.isModalOpen(name)"
|
||||||
:activeId="getActiveId(name)"
|
:activeId="uiStore.getModalActiveId(name)"
|
||||||
:mode="getMode(name)"
|
:mode="uiStore.getModalMode(name)"
|
||||||
:data="getData(name)"
|
:data="uiStore.getModalData(name)"
|
||||||
></slot>
|
></slot>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { mapStores } from "pinia";
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: "ModalRoot",
|
name: "ModalRoot",
|
||||||
props: ["name", "keepAlive"],
|
props: {
|
||||||
methods: {
|
name: {
|
||||||
isActive(name: string) {
|
type: String,
|
||||||
return this.$store.getters['ui/isModalActive'](name);
|
required: true,
|
||||||
},
|
},
|
||||||
isOpen(name: string) {
|
keepAlive: {
|
||||||
return this.$store.getters['ui/isModalOpen'](name);
|
type: Boolean,
|
||||||
},
|
|
||||||
getData(name: string) {
|
|
||||||
return this.$store.getters['ui/getModalData'](name);
|
|
||||||
},
|
|
||||||
getMode(name: string) {
|
|
||||||
return this.$store.getters['ui/getModalMode'](name);
|
|
||||||
},
|
|
||||||
getActiveId(name: string) {
|
|
||||||
return this.$store.getters['ui/getModalActiveId'](name);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapStores(useUIStore),
|
||||||
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -49,6 +49,9 @@ import {
|
||||||
} from '@/constants';
|
} from '@/constants';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import { debounceHelper } from './mixins/debounce';
|
import { debounceHelper } from './mixins/debounce';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
import { nodePanelType } from '@/Interface';
|
||||||
|
|
||||||
|
|
||||||
const SIDE_MARGIN = 24;
|
const SIDE_MARGIN = 24;
|
||||||
|
@ -116,32 +119,35 @@ export default mixins(debounceHelper).extend({
|
||||||
window.removeEventListener('resize', this.setTotalWidth);
|
window.removeEventListener('resize', this.setTotalWidth);
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNDVStore,
|
||||||
|
),
|
||||||
mainPanelDimensions(): {
|
mainPanelDimensions(): {
|
||||||
relativeWidth: number,
|
relativeWidth: number,
|
||||||
relativeLeft: number,
|
relativeLeft: number,
|
||||||
relativeRight: number
|
relativeRight: number
|
||||||
} {
|
} {
|
||||||
return this.$store.getters['ndv/mainPanelDimensions'](this.currentNodePaneType);
|
return this.ndvStore.getMainPanelDimensions(this.currentNodePaneType as nodePanelType);
|
||||||
},
|
},
|
||||||
supportedResizeDirections() {
|
supportedResizeDirections(): string[] {
|
||||||
const supportedDirections = ['right'];
|
const supportedDirections = ['right'];
|
||||||
|
|
||||||
if(this.isDraggable) supportedDirections.push('left');
|
if(this.isDraggable) supportedDirections.push('left');
|
||||||
return supportedDirections;
|
return supportedDirections;
|
||||||
},
|
},
|
||||||
currentNodePaneType() {
|
currentNodePaneType(): string {
|
||||||
if(!this.hasInputSlot) return 'inputless';
|
if(!this.hasInputSlot) return 'inputless';
|
||||||
if(!this.isDraggable) return 'dragless';
|
if(!this.isDraggable) return 'dragless';
|
||||||
if(this.nodeType === null) return 'unknown';
|
if(this.nodeType === null) return 'unknown';
|
||||||
return get(this, 'nodeType.parameterPane') || 'regular';
|
return get(this, 'nodeType.parameterPane') || 'regular';
|
||||||
},
|
},
|
||||||
hasInputSlot() {
|
hasInputSlot(): boolean {
|
||||||
return this.$slots.input !== undefined;
|
return this.$slots.input !== undefined;
|
||||||
},
|
},
|
||||||
inputPanelMargin(): number {
|
inputPanelMargin(): number {
|
||||||
return this.pxToRelativeWidth(SIDE_PANELS_MARGIN);
|
return this.pxToRelativeWidth(SIDE_PANELS_MARGIN);
|
||||||
},
|
},
|
||||||
minWindowWidth() {
|
minWindowWidth(): number {
|
||||||
return 2 * (SIDE_MARGIN + SIDE_PANELS_MARGIN) + MIN_PANEL_WIDTH;
|
return 2 * (SIDE_MARGIN + SIDE_PANELS_MARGIN) + MIN_PANEL_WIDTH;
|
||||||
},
|
},
|
||||||
minimumLeftPosition(): number {
|
minimumLeftPosition(): number {
|
||||||
|
@ -196,7 +202,7 @@ export default mixins(debounceHelper).extend({
|
||||||
const currentRelativeLeftDelta = this.calculatedPositions.outputPanelRelativeLeft - panelMinLeft;
|
const currentRelativeLeftDelta = this.calculatedPositions.outputPanelRelativeLeft - panelMinLeft;
|
||||||
return currentRelativeLeftDelta > 0 ? currentRelativeLeftDelta : 0;
|
return currentRelativeLeftDelta > 0 ? currentRelativeLeftDelta : 0;
|
||||||
},
|
},
|
||||||
hasDoubleWidth() {
|
hasDoubleWidth(): boolean {
|
||||||
return get(this, 'nodeType.parameterPane') === 'wide';
|
return get(this, 'nodeType.parameterPane') === 'wide';
|
||||||
},
|
},
|
||||||
fixedPanelWidth(): number {
|
fixedPanelWidth(): number {
|
||||||
|
@ -244,7 +250,7 @@ export default mixins(debounceHelper).extend({
|
||||||
setMainPanelWidth(relativeWidth?: number) {
|
setMainPanelWidth(relativeWidth?: number) {
|
||||||
const mainPanelRelativeWidth = relativeWidth || this.pxToRelativeWidth(initialMainPanelWidth[this.currentNodePaneType]);
|
const mainPanelRelativeWidth = relativeWidth || this.pxToRelativeWidth(initialMainPanelWidth[this.currentNodePaneType]);
|
||||||
|
|
||||||
this.$store.commit('ndv/setMainPanelDimensions', {
|
this.ndvStore.setMainPanelDimensions({
|
||||||
panelType: this.currentNodePaneType,
|
panelType: this.currentNodePaneType,
|
||||||
dimensions: {
|
dimensions: {
|
||||||
relativeWidth: mainPanelRelativeWidth,
|
relativeWidth: mainPanelRelativeWidth,
|
||||||
|
@ -260,7 +266,7 @@ export default mixins(debounceHelper).extend({
|
||||||
const isInputless = this.currentNodePaneType === 'inputless';
|
const isInputless = this.currentNodePaneType === 'inputless';
|
||||||
|
|
||||||
if(isMinLeft) {
|
if(isMinLeft) {
|
||||||
this.$store.commit('ndv/setMainPanelDimensions', {
|
this.ndvStore.setMainPanelDimensions({
|
||||||
panelType: this.currentNodePaneType,
|
panelType: this.currentNodePaneType,
|
||||||
dimensions: {
|
dimensions: {
|
||||||
relativeLeft: this.minimumLeftPosition,
|
relativeLeft: this.minimumLeftPosition,
|
||||||
|
@ -271,18 +277,18 @@ export default mixins(debounceHelper).extend({
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isMaxRight) {
|
if(isMaxRight) {
|
||||||
this.$store.commit('ndv/setMainPanelDimensions', {
|
this.ndvStore.setMainPanelDimensions({
|
||||||
panelType: this.currentNodePaneType,
|
panelType: this.currentNodePaneType as nodePanelType,
|
||||||
dimensions: {
|
dimensions: {
|
||||||
relativeLeft: 1 - this.mainPanelDimensions.relativeWidth - this.maximumRightPosition,
|
relativeLeft: 1 - this.mainPanelDimensions.relativeWidth - this.maximumRightPosition,
|
||||||
relativeRight: this.maximumRightPosition,
|
relativeRight: this.maximumRightPosition as number,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$store.commit('ndv/setMainPanelDimensions', {
|
this.ndvStore.setMainPanelDimensions({
|
||||||
panelType: this.currentNodePaneType,
|
panelType: this.currentNodePaneType as nodePanelType,
|
||||||
dimensions: {
|
dimensions: {
|
||||||
relativeLeft: isInputless ? this.minimumLeftPosition : mainPanelRelativeLeft,
|
relativeLeft: isInputless ? this.minimumLeftPosition : mainPanelRelativeLeft,
|
||||||
relativeRight: mainPanelRelativeRight,
|
relativeRight: mainPanelRelativeRight,
|
||||||
|
|
|
@ -111,8 +111,13 @@ import mixins from 'vue-typed-mixins';
|
||||||
|
|
||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
import { getStyleTokenValue, getTriggerNodeServiceName } from './helpers';
|
import { getStyleTokenValue, getTriggerNodeServiceName } from './helpers';
|
||||||
import { INodeUi, XYPosition } from '@/Interface';
|
import { IExecutionsSummary, INodeUi, XYPosition } from '@/Interface';
|
||||||
import { debounceHelper } from './mixins/debounce';
|
import { debounceHelper } from './mixins/debounce';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
externalHooks,
|
externalHooks,
|
||||||
|
@ -128,6 +133,12 @@ export default mixins(
|
||||||
NodeIcon,
|
NodeIcon,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNodeTypesStore,
|
||||||
|
useNDVStore,
|
||||||
|
useUIStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
isDuplicatable(): boolean {
|
isDuplicatable(): boolean {
|
||||||
if(!this.nodeType) return true;
|
if(!this.nodeType) return true;
|
||||||
return this.nodeType.maxNodes === undefined || this.sameTypeNodes.length < this.nodeType.maxNodes;
|
return this.nodeType.maxNodes === undefined || this.sameTypeNodes.length < this.nodeType.maxNodes;
|
||||||
|
@ -136,7 +147,7 @@ export default mixins(
|
||||||
return this.nodeType?.group.includes('schedule') === true;
|
return this.nodeType?.group.includes('schedule') === true;
|
||||||
},
|
},
|
||||||
nodeRunData(): ITaskData[] {
|
nodeRunData(): ITaskData[] {
|
||||||
return this.$store.getters.getWorkflowResultDataByNodeName(this.data.name);
|
return this.workflowsStore.getWorkflowResultDataByNodeName(this.data?.name || '') || [];
|
||||||
},
|
},
|
||||||
hasIssues (): boolean {
|
hasIssues (): boolean {
|
||||||
if (this.hasPinData) return false;
|
if (this.hasPinData) return false;
|
||||||
|
@ -154,7 +165,7 @@ export default mixins(
|
||||||
return workflowResultDataNode.length;
|
return workflowResultDataNode.length;
|
||||||
},
|
},
|
||||||
canvasOffsetPosition() {
|
canvasOffsetPosition() {
|
||||||
return this.$store.getters.getNodeViewOffsetPosition;
|
return this.uiStore.nodeViewOffsetPosition;
|
||||||
},
|
},
|
||||||
getTriggerNodeTooltip (): string | undefined {
|
getTriggerNodeTooltip (): string | undefined {
|
||||||
if (this.nodeType !== null && this.nodeType.hasOwnProperty('eventTriggerDescription')) {
|
if (this.nodeType !== null && this.nodeType.hasOwnProperty('eventTriggerDescription')) {
|
||||||
|
@ -179,11 +190,11 @@ export default mixins(
|
||||||
return !!(this.nodeType && this.nodeType.polling);
|
return !!(this.nodeType && this.nodeType.polling);
|
||||||
},
|
},
|
||||||
isExecuting (): boolean {
|
isExecuting (): boolean {
|
||||||
return this.$store.getters.executingNode === this.data.name;
|
return this.workflowsStore.executingNode === this.data.name;
|
||||||
},
|
},
|
||||||
isSingleActiveTriggerNode (): boolean {
|
isSingleActiveTriggerNode (): boolean {
|
||||||
const nodes = this.$store.getters.workflowTriggerNodes.filter((node: INodeUi) => {
|
const nodes = this.workflowsStore.workflowTriggerNodes.filter((node: INodeUi) => {
|
||||||
const nodeType = this.$store.getters['nodeTypes/getNodeType'](node.type, node.typeVersion) as INodeTypeDescription | null;
|
const nodeType = this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
|
||||||
return nodeType && nodeType.eventTriggerDescription !== '' && !node.disabled;
|
return nodeType && nodeType.eventTriggerDescription !== '' && !node.disabled;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -193,7 +204,7 @@ export default mixins(
|
||||||
return this.data.type === MANUAL_TRIGGER_NODE_TYPE;
|
return this.data.type === MANUAL_TRIGGER_NODE_TYPE;
|
||||||
},
|
},
|
||||||
isTriggerNode (): boolean {
|
isTriggerNode (): boolean {
|
||||||
return this.$store.getters['nodeTypes/isTriggerNode'](this.data.type);
|
return this.nodeTypesStore.isTriggerNode(this.data?.type || '');
|
||||||
},
|
},
|
||||||
isTriggerNodeTooltipEmpty () : boolean {
|
isTriggerNodeTooltipEmpty () : boolean {
|
||||||
return this.nodeType !== null ? this.nodeType.eventTriggerDescription === '' : false;
|
return this.nodeType !== null ? this.nodeType.eventTriggerDescription === '' : false;
|
||||||
|
@ -202,13 +213,13 @@ export default mixins(
|
||||||
return this.node && this.node.disabled;
|
return this.node && this.node.disabled;
|
||||||
},
|
},
|
||||||
nodeType (): INodeTypeDescription | null {
|
nodeType (): INodeTypeDescription | null {
|
||||||
return this.data && this.$store.getters['nodeTypes/getNodeType'](this.data.type, this.data.typeVersion);
|
return this.data && this.nodeTypesStore.getNodeType(this.data.type, this.data.typeVersion);
|
||||||
},
|
},
|
||||||
node (): INodeUi | undefined { // same as this.data but reactive..
|
node (): INodeUi | undefined { // same as this.data but reactive..
|
||||||
return this.$store.getters.nodesByName[this.name] as INodeUi | undefined;
|
return this.workflowsStore.nodesByName[this.name] as INodeUi | undefined;
|
||||||
},
|
},
|
||||||
sameTypeNodes (): INodeUi[] {
|
sameTypeNodes (): INodeUi[] {
|
||||||
return this.$store.getters.allNodes.filter((node: INodeUi) => node.type === this.data.type);
|
return this.workflowsStore.allNodes.filter((node: INodeUi) => node.type === this.data.type);
|
||||||
},
|
},
|
||||||
nodeClass (): object {
|
nodeClass (): object {
|
||||||
return {
|
return {
|
||||||
|
@ -261,7 +272,7 @@ export default mixins(
|
||||||
return this.data.name;
|
return this.data.name;
|
||||||
},
|
},
|
||||||
waiting (): string | undefined {
|
waiting (): string | undefined {
|
||||||
const workflowExecution = this.$store.getters.getWorkflowExecution;
|
const workflowExecution = this.workflowsStore.getWorkflowExecution as IExecutionsSummary;
|
||||||
|
|
||||||
if (workflowExecution && workflowExecution.waitTill) {
|
if (workflowExecution && workflowExecution.waitTill) {
|
||||||
const lastNodeExecuted = get(workflowExecution, 'data.resultData.lastNodeExecuted');
|
const lastNodeExecuted = get(workflowExecution, 'data.resultData.lastNodeExecuted');
|
||||||
|
@ -285,7 +296,7 @@ export default mixins(
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
workflowRunning (): boolean {
|
workflowRunning (): boolean {
|
||||||
return this.$store.getters.isActionActive('workflowRunning');
|
return this.uiStore.isActionActive('workflowRunning');
|
||||||
},
|
},
|
||||||
nodeStyle (): object {
|
nodeStyle (): object {
|
||||||
let borderColor = getStyleTokenValue('--color-foreground-xdark');
|
let borderColor = getStyleTokenValue('--color-foreground-xdark');
|
||||||
|
@ -312,7 +323,7 @@ export default mixins(
|
||||||
return returnStyles;
|
return returnStyles;
|
||||||
},
|
},
|
||||||
isSelected (): boolean {
|
isSelected (): boolean {
|
||||||
return this.$store.getters.getSelectedNodes.find((node: INodeUi) => node.name === this.data.name);
|
return this.uiStore.getSelectedNodes.find((node: INodeUi) => node.name === this.data.name) !== undefined;
|
||||||
},
|
},
|
||||||
shiftOutputCount (): boolean {
|
shiftOutputCount (): boolean {
|
||||||
return !!(this.nodeType && this.nodeType.outputs.length > 2);
|
return !!(this.nodeType && this.nodeType.outputs.length > 2);
|
||||||
|
@ -408,14 +419,14 @@ export default mixins(
|
||||||
},
|
},
|
||||||
disableNode () {
|
disableNode () {
|
||||||
this.disableNodes([this.data]);
|
this.disableNodes([this.data]);
|
||||||
this.$telemetry.track('User clicked node hover button', { node_type: this.data.type, button_name: 'disable', workflow_id: this.$store.getters.workflowId });
|
this.$telemetry.track('User clicked node hover button', { node_type: this.data.type, button_name: 'disable', workflow_id: this.workflowsStore.workflowId });
|
||||||
},
|
},
|
||||||
executeNode () {
|
executeNode () {
|
||||||
this.$emit('runWorkflow', this.data.name, 'Node.executeNode');
|
this.$emit('runWorkflow', this.data.name, 'Node.executeNode');
|
||||||
this.$telemetry.track('User clicked node hover button', { node_type: this.data.type, button_name: 'execute', workflow_id: this.$store.getters.workflowId });
|
this.$telemetry.track('User clicked node hover button', { node_type: this.data.type, button_name: 'execute', workflow_id: this.workflowsStore.workflowId });
|
||||||
},
|
},
|
||||||
deleteNode () {
|
deleteNode () {
|
||||||
this.$telemetry.track('User clicked node hover button', { node_type: this.data.type, button_name: 'delete', workflow_id: this.$store.getters.workflowId });
|
this.$telemetry.track('User clicked node hover button', { node_type: this.data.type, button_name: 'delete', workflow_id: this.workflowsStore.workflowId });
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
// Wait a tick else vue causes problems because the data is gone
|
// Wait a tick else vue causes problems because the data is gone
|
||||||
|
@ -423,7 +434,7 @@ export default mixins(
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
duplicateNode () {
|
duplicateNode () {
|
||||||
this.$telemetry.track('User clicked node hover button', { node_type: this.data.type, button_name: 'duplicate', workflow_id: this.$store.getters.workflowId });
|
this.$telemetry.track('User clicked node hover button', { node_type: this.data.type, button_name: 'duplicate', workflow_id: this.workflowsStore.workflowId });
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
// Wait a tick else vue causes problems because the data is gone
|
// Wait a tick else vue causes problems because the data is gone
|
||||||
this.$emit('duplicateNode', this.data.name);
|
this.$emit('duplicateNode', this.data.name);
|
||||||
|
@ -444,7 +455,7 @@ export default mixins(
|
||||||
},
|
},
|
||||||
|
|
||||||
setNodeActive () {
|
setNodeActive () {
|
||||||
this.$store.commit('ndv/setActiveNodeName', this.data.name);
|
this.ndvStore.activeNodeName = this.data ? this.data.name : '';
|
||||||
this.pinDataDiscoveryTooltipVisible = false;
|
this.pinDataDiscoveryTooltipVisible = false;
|
||||||
},
|
},
|
||||||
touchStart () {
|
touchStart () {
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import * as CanvasHelpers from "@/views/canvasHelpers";
|
import * as CanvasHelpers from "@/views/canvasHelpers";
|
||||||
import {DEFAULT_STICKY_HEIGHT, DEFAULT_STICKY_WIDTH, STICKY_NODE_TYPE} from "@/constants";
|
import {DEFAULT_STICKY_HEIGHT, DEFAULT_STICKY_WIDTH, STICKY_NODE_TYPE} from "@/constants";
|
||||||
|
import { mapStores } from "pinia";
|
||||||
|
import { useUIStore } from "@/stores/ui";
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'node-creation',
|
name: 'node-creation',
|
||||||
|
@ -41,6 +43,9 @@ export default Vue.extend({
|
||||||
showStickyButton: false,
|
showStickyButton: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapStores(useUIStore),
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onCreateMenuHoverIn(mouseinEvent: MouseEvent) {
|
onCreateMenuHoverIn(mouseinEvent: MouseEvent) {
|
||||||
const buttonsWrapper = mouseinEvent.target as Element;
|
const buttonsWrapper = mouseinEvent.target as Element;
|
||||||
|
@ -73,7 +78,7 @@ export default Vue.extend({
|
||||||
(document.activeElement as HTMLElement).blur();
|
(document.activeElement as HTMLElement).blur();
|
||||||
}
|
}
|
||||||
|
|
||||||
const offset: [number, number] = [...(this.$store.getters.getNodeViewOffsetPosition as [number, number])];
|
const offset: [number, number] = [...(this.uiStore.nodeViewOffsetPosition)];
|
||||||
|
|
||||||
const position = CanvasHelpers.getMidCanvasPosition(this.nodeViewScale, offset);
|
const position = CanvasHelpers.getMidCanvasPosition(this.nodeViewScale, offset);
|
||||||
position[0] -= DEFAULT_STICKY_WIDTH / 2;
|
position[0] -= DEFAULT_STICKY_WIDTH / 2;
|
||||||
|
|
|
@ -92,6 +92,10 @@ import { matchesNodeType, matchesSelectType } from './helpers';
|
||||||
import { BaseTextKey } from '@/plugins/i18n';
|
import { BaseTextKey } from '@/plugins/i18n';
|
||||||
import { intersection } from '@/utils';
|
import { intersection } from '@/utils';
|
||||||
import { sublimeSearch } from './sortUtils';
|
import { sublimeSearch } from './sortUtils';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
export default mixins(externalHooks, globalLinkActions).extend({
|
export default mixins(externalHooks, globalLinkActions).extend({
|
||||||
name: 'CategorizedItems',
|
name: 'CategorizedItems',
|
||||||
|
@ -146,6 +150,11 @@ export default mixins(externalHooks, globalLinkActions).extend({
|
||||||
this.unregisterCustomAction('showAllNodeCreatorNodes');
|
this.unregisterCustomAction('showAllNodeCreatorNodes');
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNodeTypesStore,
|
||||||
|
useRootStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
activeSubcategory(): INodeCreateElement | null {
|
activeSubcategory(): INodeCreateElement | null {
|
||||||
return this.activeSubcategoryHistory[this.activeSubcategoryHistory.length - 1] || null;
|
return this.activeSubcategoryHistory[this.activeSubcategoryHistory.length - 1] || null;
|
||||||
},
|
},
|
||||||
|
@ -156,10 +165,10 @@ export default mixins(externalHooks, globalLinkActions).extend({
|
||||||
return this.$store.getters['nodeCreator/selectedType'];
|
return this.$store.getters['nodeCreator/selectedType'];
|
||||||
},
|
},
|
||||||
categoriesWithNodes(): ICategoriesWithNodes {
|
categoriesWithNodes(): ICategoriesWithNodes {
|
||||||
return this.$store.getters['nodeTypes/categoriesWithNodes'];
|
return this.nodeTypesStore.categoriesWithNodes;
|
||||||
},
|
},
|
||||||
categorizedItems(): INodeCreateElement[] {
|
categorizedItems(): INodeCreateElement[] {
|
||||||
return this.$store.getters['nodeTypes/categorizedItems'];
|
return this.nodeTypesStore.categorizedItems;
|
||||||
},
|
},
|
||||||
activeSubcategoryTitle(): string {
|
activeSubcategoryTitle(): string {
|
||||||
if(!this.activeSubcategory || !this.activeSubcategory.properties) return '';
|
if(!this.activeSubcategory || !this.activeSubcategory.properties) return '';
|
||||||
|
@ -178,7 +187,7 @@ export default mixins(externalHooks, globalLinkActions).extend({
|
||||||
return this.nodeFilter.toLowerCase().trim();
|
return this.nodeFilter.toLowerCase().trim();
|
||||||
},
|
},
|
||||||
defaultLocale (): string {
|
defaultLocale (): string {
|
||||||
return this.$store.getters.defaultLocale;
|
return this.rootStore.defaultLocale;
|
||||||
},
|
},
|
||||||
filteredNodeTypes(): INodeCreateElement[] {
|
filteredNodeTypes(): INodeCreateElement[] {
|
||||||
const filter = this.searchFilter;
|
const filter = this.searchFilter;
|
||||||
|
@ -337,7 +346,7 @@ export default mixins(externalHooks, globalLinkActions).extend({
|
||||||
newValue,
|
newValue,
|
||||||
selectedType: this.selectedType,
|
selectedType: this.selectedType,
|
||||||
filteredNodes: this.filteredNodeTypes,
|
filteredNodes: this.filteredNodeTypes,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -444,7 +453,7 @@ export default mixins(externalHooks, globalLinkActions).extend({
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.activeCategory = [...this.activeCategory, category];
|
this.activeCategory = [...this.activeCategory, category];
|
||||||
this.$telemetry.trackNodesPanel('nodeCreateList.onCategoryExpanded', { category_name: category, workflow_id: this.$store.getters.workflowId });
|
this.$telemetry.trackNodesPanel('nodeCreateList.onCategoryExpanded', { category_name: category, workflow_id: this.workflowsStore.workflowId });
|
||||||
}
|
}
|
||||||
|
|
||||||
this.activeIndex = this.categorized.findIndex(
|
this.activeIndex = this.categorized.findIndex(
|
||||||
|
@ -456,7 +465,7 @@ export default mixins(externalHooks, globalLinkActions).extend({
|
||||||
this.$store.commit('nodeCreator/setShowTabs', false);
|
this.$store.commit('nodeCreator/setShowTabs', false);
|
||||||
this.activeSubcategoryIndex = 0;
|
this.activeSubcategoryIndex = 0;
|
||||||
this.activeSubcategoryHistory.push(selected);
|
this.activeSubcategoryHistory.push(selected);
|
||||||
this.$telemetry.trackNodesPanel('nodeCreateList.onSubcategorySelected', { selected, workflow_id: this.$store.getters.workflowId });
|
this.$telemetry.trackNodesPanel('nodeCreateList.onSubcategorySelected', { selected, workflow_id: this.workflowsStore.workflowId });
|
||||||
},
|
},
|
||||||
|
|
||||||
onSubcategoryClose() {
|
onSubcategoryClose() {
|
||||||
|
|
|
@ -18,6 +18,8 @@ import camelcase from 'lodash.camelcase';
|
||||||
import { CategoryName } from '@/plugins/i18n';
|
import { CategoryName } from '@/plugins/i18n';
|
||||||
import { INodeCreateElement, ICategoriesWithNodes } from '@/Interface';
|
import { INodeCreateElement, ICategoriesWithNodes } from '@/Interface';
|
||||||
import { NODE_TYPE_COUNT_MAPPER } from '@/constants';
|
import { NODE_TYPE_COUNT_MAPPER } from '@/constants';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
|
@ -27,20 +29,23 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNodeTypesStore,
|
||||||
|
),
|
||||||
selectedType(): "Regular" | "Trigger" | "All" {
|
selectedType(): "Regular" | "Trigger" | "All" {
|
||||||
return this.$store.getters['nodeCreator/selectedType'];
|
return this.$store.getters['nodeCreator/selectedType'];
|
||||||
},
|
},
|
||||||
categoriesWithNodes(): ICategoriesWithNodes {
|
categoriesWithNodes(): ICategoriesWithNodes {
|
||||||
return this.$store.getters['nodeTypes/categoriesWithNodes'];
|
return this.nodeTypesStore.categoriesWithNodes;
|
||||||
},
|
},
|
||||||
categorizedItems(): INodeCreateElement[] {
|
categorizedItems(): INodeCreateElement[] {
|
||||||
return this.$store.getters['nodeTypes/categorizedItems'];
|
return this.nodeTypesStore.categorizedItems;
|
||||||
},
|
},
|
||||||
categoryName() {
|
categoryName() {
|
||||||
return camelcase(this.item.category);
|
return camelcase(this.item.category);
|
||||||
},
|
},
|
||||||
nodesCount(): number {
|
nodesCount(): number {
|
||||||
const currentCategory = this.categoriesWithNodes[this.item.category];
|
const currentCategory= (this.categoriesWithNodes as ICategoriesWithNodes)[this.item.category];
|
||||||
const subcategories = Object.keys(currentCategory);
|
const subcategories = Object.keys(currentCategory);
|
||||||
|
|
||||||
// We need to sum subcategories count for the curent nodeType view
|
// We need to sum subcategories count for the curent nodeType view
|
||||||
|
|
|
@ -33,6 +33,8 @@ import { ALL_NODE_FILTER, TRIGGER_NODE_FILTER, OTHER_TRIGGER_NODES_SUBCATEGORY,
|
||||||
import CategorizedItems from './CategorizedItems.vue';
|
import CategorizedItems from './CategorizedItems.vue';
|
||||||
import TypeSelector from './TypeSelector.vue';
|
import TypeSelector from './TypeSelector.vue';
|
||||||
import { INodeCreateElement } from '@/Interface';
|
import { INodeCreateElement } from '@/Interface';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
|
||||||
export default mixins(externalHooks).extend({
|
export default mixins(externalHooks).extend({
|
||||||
name: 'NodeCreateList',
|
name: 'NodeCreateList',
|
||||||
|
@ -55,6 +57,9 @@ export default mixins(externalHooks).extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
selectedType(): string {
|
selectedType(): string {
|
||||||
return this.$store.getters['nodeCreator/selectedType'];
|
return this.$store.getters['nodeCreator/selectedType'];
|
||||||
},
|
},
|
||||||
|
@ -68,7 +73,7 @@ export default mixins(externalHooks).extend({
|
||||||
this.$telemetry.trackNodesPanel('nodeCreateList.selectedTypeChanged', {
|
this.$telemetry.trackNodesPanel('nodeCreateList.selectedTypeChanged', {
|
||||||
old_filter: oldValue,
|
old_filter: oldValue,
|
||||||
new_filter: newValue,
|
new_filter: newValue,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -80,7 +85,7 @@ export default mixins(externalHooks).extend({
|
||||||
destroyed() {
|
destroyed() {
|
||||||
this.$store.commit('nodeCreator/setSelectedType', ALL_NODE_FILTER);
|
this.$store.commit('nodeCreator/setSelectedType', ALL_NODE_FILTER);
|
||||||
this.$externalHooks().run('nodeCreateList.destroyed');
|
this.$externalHooks().run('nodeCreateList.destroyed');
|
||||||
this.$telemetry.trackNodesPanel('nodeCreateList.destroyed', { workflow_id: this.$store.getters.workflowId });
|
this.$telemetry.trackNodesPanel('nodeCreateList.destroyed', { workflow_id: this.workflowsStore.workflowId });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<aside :class="{'node-creator-scrim': true, expanded: !sidebarMenuCollapsed, active: showScrim}" />
|
<aside :class="{'node-creator-scrim': true, expanded: !uiStore.sidebarMenuCollapsed, active: showScrim}" />
|
||||||
|
|
||||||
<slide-transition>
|
<slide-transition>
|
||||||
<div
|
<div
|
||||||
|
@ -29,6 +29,9 @@ import { INodeTypeDescription } from 'n8n-workflow';
|
||||||
import SlideTransition from '../../transitions/SlideTransition.vue';
|
import SlideTransition from '../../transitions/SlideTransition.vue';
|
||||||
|
|
||||||
import MainPanel from './MainPanel.vue';
|
import MainPanel from './MainPanel.vue';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'NodeCreator',
|
name: 'NodeCreator',
|
||||||
|
@ -42,14 +45,15 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNodeTypesStore,
|
||||||
|
useUIStore,
|
||||||
|
),
|
||||||
showScrim(): boolean {
|
showScrim(): boolean {
|
||||||
return this.$store.getters['nodeCreator/showScrim'];
|
return this.$store.getters['nodeCreator/showScrim'];
|
||||||
},
|
},
|
||||||
sidebarMenuCollapsed(): boolean {
|
|
||||||
return this.$store.getters['ui/sidebarMenuCollapsed'];
|
|
||||||
},
|
|
||||||
visibleNodeTypes(): INodeTypeDescription[] {
|
visibleNodeTypes(): INodeTypeDescription[] {
|
||||||
return this.$store.getters['nodeTypes/visibleNodeTypes'];
|
return this.nodeTypesStore.visibleNodeTypes;
|
||||||
},
|
},
|
||||||
searchItems(): INodeCreateElement[] {
|
searchItems(): INodeCreateElement[] {
|
||||||
const sorted = [...this.visibleNodeTypes];
|
const sorted = [...this.visibleNodeTypes];
|
||||||
|
|
|
@ -63,6 +63,7 @@ import {
|
||||||
ICredentialsResponse,
|
ICredentialsResponse,
|
||||||
INodeUi,
|
INodeUi,
|
||||||
INodeUpdatePropertiesInformation,
|
INodeUpdatePropertiesInformation,
|
||||||
|
IUser,
|
||||||
} from '@/Interface';
|
} from '@/Interface';
|
||||||
import {
|
import {
|
||||||
ICredentialType,
|
ICredentialType,
|
||||||
|
@ -81,6 +82,11 @@ import { mapGetters } from "vuex";
|
||||||
|
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import {getCredentialPermissions} from "@/permissions";
|
import {getCredentialPermissions} from "@/permissions";
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useUsersStore } from '@/stores/users';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
genericHelpers,
|
genericHelpers,
|
||||||
|
@ -103,11 +109,19 @@ export default mixins(
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters('users', ['currentUser']),
|
...mapStores(
|
||||||
|
useNodeTypesStore,
|
||||||
|
useUIStore,
|
||||||
|
useUsersStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
...mapGetters('credentials', {
|
...mapGetters('credentials', {
|
||||||
allCredentialsByType: 'allCredentialsByType',
|
allCredentialsByType: 'allCredentialsByType',
|
||||||
getCredentialTypeByName: 'getCredentialTypeByName',
|
getCredentialTypeByName: 'getCredentialTypeByName',
|
||||||
}),
|
}),
|
||||||
|
currentUser (): IUser {
|
||||||
|
return this.usersStore.currentUser || {} as IUser;
|
||||||
|
},
|
||||||
credentialTypesNode (): string[] {
|
credentialTypesNode (): string[] {
|
||||||
return this.credentialTypesNodeDescription
|
return this.credentialTypesNodeDescription
|
||||||
.map((credentialTypeDescription) => credentialTypeDescription.name);
|
.map((credentialTypeDescription) => credentialTypeDescription.name);
|
||||||
|
@ -125,7 +139,7 @@ export default mixins(
|
||||||
|
|
||||||
if (credType) return [credType];
|
if (credType) return [credType];
|
||||||
|
|
||||||
const activeNodeType = this.$store.getters['nodeTypes/getNodeType'](node.type, node.typeVersion) as INodeTypeDescription | null;
|
const activeNodeType = this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
|
||||||
if (activeNodeType && activeNodeType.credentials) {
|
if (activeNodeType && activeNodeType.credentials) {
|
||||||
return activeNodeType.credentials;
|
return activeNodeType.credentials;
|
||||||
}
|
}
|
||||||
|
@ -220,8 +234,8 @@ export default mixins(
|
||||||
onCredentialSelected (credentialType: string, credentialId: string | null | undefined) {
|
onCredentialSelected (credentialType: string, credentialId: string | null | undefined) {
|
||||||
if (credentialId === this.NEW_CREDENTIALS_TEXT) {
|
if (credentialId === this.NEW_CREDENTIALS_TEXT) {
|
||||||
this.listenForNewCredentials(credentialType);
|
this.listenForNewCredentials(credentialType);
|
||||||
this.$store.dispatch('ui/openNewCredential', { type: credentialType });
|
this.uiStore.openNewCredential(credentialType);
|
||||||
this.$telemetry.track('User opened Credential modal', { credential_type: credentialType, source: 'node', new_credential: true, workflow_id: this.$store.getters.workflowId });
|
this.$telemetry.track('User opened Credential modal', { credential_type: credentialType, source: 'node', new_credential: true, workflow_id: this.workflowsStore.workflowId });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +245,7 @@ export default mixins(
|
||||||
credential_type: credentialType,
|
credential_type: credentialType,
|
||||||
node_type: this.node.type,
|
node_type: this.node.type,
|
||||||
...(this.hasProxyAuth(this.node) ? { is_service_specific: true } : {}),
|
...(this.hasProxyAuth(this.node) ? { is_service_specific: true } : {}),
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
credential_id: credentialId,
|
credential_id: credentialId,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -244,7 +258,7 @@ export default mixins(
|
||||||
// if credentials has been string or neither id matched nor name matched uniquely
|
// if credentials has been string or neither id matched nor name matched uniquely
|
||||||
if (oldCredentials.id === null || (oldCredentials.id && !this.$store.getters['credentials/getCredentialByIdAndType'](oldCredentials.id, credentialType))) {
|
if (oldCredentials.id === null || (oldCredentials.id && !this.$store.getters['credentials/getCredentialByIdAndType'](oldCredentials.id, credentialType))) {
|
||||||
// update all nodes in the workflow with the same old/invalid credentials
|
// update all nodes in the workflow with the same old/invalid credentials
|
||||||
this.$store.commit('replaceInvalidWorkflowCredentials', {
|
this.workflowsStore.replaceInvalidWorkflowCredentials({
|
||||||
credentials: selected,
|
credentials: selected,
|
||||||
invalid: oldCredentials,
|
invalid: oldCredentials,
|
||||||
type: credentialType,
|
type: credentialType,
|
||||||
|
@ -316,9 +330,9 @@ export default mixins(
|
||||||
|
|
||||||
editCredential(credentialType: string): void {
|
editCredential(credentialType: string): void {
|
||||||
const { id } = this.node.credentials[credentialType];
|
const { id } = this.node.credentials[credentialType];
|
||||||
this.$store.dispatch('ui/openExistingCredential', { id });
|
this.uiStore.openExistingCredential(id);
|
||||||
|
|
||||||
this.$telemetry.track('User opened Credential modal', { credential_type: credentialType, source: 'node', new_credential: false, workflow_id: this.$store.getters.workflowId });
|
this.$telemetry.track('User opened Credential modal', { credential_type: credentialType, source: 'node', new_credential: false, workflow_id: this.workflowsStore.workflowId });
|
||||||
|
|
||||||
this.listenForNewCredentials(credentialType);
|
this.listenForNewCredentials(credentialType);
|
||||||
},
|
},
|
||||||
|
|
|
@ -141,6 +141,11 @@ import {
|
||||||
import { workflowActivate } from './mixins/workflowActivate';
|
import { workflowActivate } from './mixins/workflowActivate';
|
||||||
import { pinData } from "@/components/mixins/pinData";
|
import { pinData } from "@/components/mixins/pinData";
|
||||||
import { dataPinningEventBus } from '@/event-bus/data-pinning-event-bus';
|
import { dataPinningEventBus } from '@/event-bus/data-pinning-event-bus';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
externalHooks,
|
externalHooks,
|
||||||
|
@ -182,8 +187,7 @@ export default mixins(
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$store.commit('ndv/setNDVSessionId');
|
this.ndvStore.setNDVSessionId;
|
||||||
|
|
||||||
dataPinningEventBus.$on('data-pinning-discovery', ({ isTooltipVisible }: { isTooltipVisible: boolean }) => {
|
dataPinningEventBus.$on('data-pinning-discovery', ({ isTooltipVisible }: { isTooltipVisible: boolean }) => {
|
||||||
this.pinDataDiscoveryTooltipVisible = isTooltipVisible;
|
this.pinDataDiscoveryTooltipVisible = isTooltipVisible;
|
||||||
});
|
});
|
||||||
|
@ -192,12 +196,17 @@ export default mixins(
|
||||||
dataPinningEventBus.$off('data-pinning-discovery');
|
dataPinningEventBus.$off('data-pinning-discovery');
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['executionWaitingForWebhook']),
|
...mapStores(
|
||||||
|
useNodeTypesStore,
|
||||||
|
useNDVStore,
|
||||||
|
useUIStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
sessionId(): string {
|
sessionId(): string {
|
||||||
return this.$store.getters['ndv/ndvSessionId'];
|
return this.ndvStore.sessionId;
|
||||||
},
|
},
|
||||||
workflowRunning(): boolean {
|
workflowRunning(): boolean {
|
||||||
return this.$store.getters.isActionActive('workflowRunning');
|
return this.uiStore.isActionActive('workflowRunning');
|
||||||
},
|
},
|
||||||
showTriggerWaitingWarning(): boolean {
|
showTriggerWaitingWarning(): boolean {
|
||||||
return (
|
return (
|
||||||
|
@ -205,25 +214,25 @@ export default mixins(
|
||||||
!!this.activeNodeType &&
|
!!this.activeNodeType &&
|
||||||
!this.activeNodeType.group.includes('trigger') &&
|
!this.activeNodeType.group.includes('trigger') &&
|
||||||
this.workflowRunning &&
|
this.workflowRunning &&
|
||||||
this.executionWaitingForWebhook
|
this.workflowsStore.executionWaitingForWebhook
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
activeNode(): INodeUi | null {
|
activeNode(): INodeUi | null {
|
||||||
return this.$store.getters['ndv/activeNode'];
|
return this.ndvStore.activeNode;
|
||||||
},
|
},
|
||||||
inputNodeName(): string | undefined {
|
inputNodeName(): string | undefined {
|
||||||
return this.selectedInput || this.parentNode;
|
return this.selectedInput || this.parentNode;
|
||||||
},
|
},
|
||||||
inputNode(): INodeUi | null {
|
inputNode(): INodeUi | null {
|
||||||
if (this.inputNodeName) {
|
if (this.inputNodeName) {
|
||||||
return this.$store.getters.getNodeByName(this.inputNodeName);
|
return this.workflowsStore.getNodeByName(this.inputNodeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
activeNodeType(): INodeTypeDescription | null {
|
activeNodeType(): INodeTypeDescription | null {
|
||||||
if (this.activeNode) {
|
if (this.activeNode) {
|
||||||
return this.$store.getters['nodeTypes/getNodeType'](this.activeNode.type, this.activeNode.typeVersion);
|
return this.nodeTypesStore.getNodeType(this.activeNode.type, this.activeNode.typeVersion);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
@ -257,11 +266,11 @@ export default mixins(
|
||||||
},
|
},
|
||||||
isActiveStickyNode(): boolean {
|
isActiveStickyNode(): boolean {
|
||||||
return (
|
return (
|
||||||
!!this.$store.getters['ndv/activeNode'] && this.$store.getters['ndv/activeNode'].type === STICKY_NODE_TYPE
|
!!this.ndvStore.activeNode && this.ndvStore.activeNode .type === STICKY_NODE_TYPE
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
workflowExecution(): IExecutionResponse | null {
|
workflowExecution(): IExecutionResponse | null {
|
||||||
return this.$store.getters.getWorkflowExecution;
|
return this.workflowsStore.getWorkflowExecution;
|
||||||
},
|
},
|
||||||
workflowRunData(): IRunData | null {
|
workflowRunData(): IRunData | null {
|
||||||
if (this.workflowExecution === null) {
|
if (this.workflowExecution === null) {
|
||||||
|
@ -340,13 +349,13 @@ export default mixins(
|
||||||
return `${BASE_NODE_SURVEY_URL}${this.activeNodeType.name}`;
|
return `${BASE_NODE_SURVEY_URL}${this.activeNodeType.name}`;
|
||||||
},
|
},
|
||||||
outputPanelEditMode(): { enabled: boolean; value: string; } {
|
outputPanelEditMode(): { enabled: boolean; value: string; } {
|
||||||
return this.$store.getters['ndv/outputPanelEditMode'];
|
return this.ndvStore.outputPanelEditMode;
|
||||||
},
|
},
|
||||||
isWorkflowRunning(): boolean {
|
isWorkflowRunning(): boolean {
|
||||||
return this.$store.getters.isActionActive('workflowRunning');
|
return this.uiStore.isActionActive('workflowRunning');
|
||||||
},
|
},
|
||||||
isExecutionWaitingForWebhook(): boolean {
|
isExecutionWaitingForWebhook(): boolean {
|
||||||
return this.$store.getters.executionWaitingForWebhook;
|
return this.workflowsStore.executionWaitingForWebhook;
|
||||||
},
|
},
|
||||||
blockUi(): boolean {
|
blockUi(): boolean {
|
||||||
return this.isWorkflowRunning || this.isExecutionWaitingForWebhook;
|
return this.isWorkflowRunning || this.isExecutionWaitingForWebhook;
|
||||||
|
@ -364,7 +373,7 @@ export default mixins(
|
||||||
this.avgInputRowHeight = 0;
|
this.avgInputRowHeight = 0;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.$store.commit('ndv/setNDVSessionId');
|
this.ndvStore.setNDVSessionId;
|
||||||
}, 0);
|
}, 0);
|
||||||
this.$externalHooks().run('dataDisplay.nodeTypeChanged', {
|
this.$externalHooks().run('dataDisplay.nodeTypeChanged', {
|
||||||
nodeSubtitle: this.getNodeSubtitle(node, this.activeNodeType, this.getCurrentWorkflow()),
|
nodeSubtitle: this.getNodeSubtitle(node, this.activeNodeType, this.getCurrentWorkflow()),
|
||||||
|
@ -374,24 +383,24 @@ export default mixins(
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (this.activeNode) {
|
if (this.activeNode) {
|
||||||
const outogingConnections = this.$store.getters.outgoingConnectionsByNodeName(
|
const outgoingConnections = this.workflowsStore.outgoingConnectionsByNodeName(
|
||||||
this.activeNode.name,
|
this.activeNode.name,
|
||||||
) as INodeConnections;
|
) as INodeConnections;
|
||||||
|
|
||||||
this.$telemetry.track('User opened node modal', {
|
this.$telemetry.track('User opened node modal', {
|
||||||
node_type: this.activeNodeType ? this.activeNodeType.name : '',
|
node_type: this.activeNodeType ? this.activeNodeType.name : '',
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
parameters_pane_position: this.mainPanelPosition,
|
parameters_pane_position: this.mainPanelPosition,
|
||||||
input_first_connector_runs: this.maxInputRun,
|
input_first_connector_runs: this.maxInputRun,
|
||||||
output_first_connector_runs: this.maxOutputRun,
|
output_first_connector_runs: this.maxOutputRun,
|
||||||
selected_view_inputs: this.isTriggerNode
|
selected_view_inputs: this.isTriggerNode
|
||||||
? 'trigger'
|
? 'trigger'
|
||||||
: this.$store.getters['ndv/inputPanelDisplayMode'],
|
: this.ndvStore.inputPanelDisplayMode,
|
||||||
selected_view_outputs: this.$store.getters['ndv/outputPanelDisplayMode'],
|
selected_view_outputs: this.ndvStore.outputPanelDisplayMode,
|
||||||
input_connectors: this.parentNodes.length,
|
input_connectors: this.parentNodes.length,
|
||||||
output_connectors:
|
output_connectors:
|
||||||
outogingConnections && outogingConnections.main && outogingConnections.main.length,
|
outgoingConnections && outgoingConnections.main && outgoingConnections.main.length,
|
||||||
input_displayed_run_index: this.inputRun,
|
input_displayed_run_index: this.inputRun,
|
||||||
output_displayed_run_index: this.outputRun,
|
output_displayed_run_index: this.outputRun,
|
||||||
data_pinning_tooltip_presented: this.pinDataDiscoveryTooltipVisible,
|
data_pinning_tooltip_presented: this.pinDataDiscoveryTooltipVisible,
|
||||||
|
@ -413,12 +422,12 @@ export default mixins(
|
||||||
},
|
},
|
||||||
inputNodeName(nodeName: string | undefined) {
|
inputNodeName(nodeName: string | undefined) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.$store.commit('ndv/setInputNodeName', nodeName);
|
this.ndvStore.setInputNodeName(nodeName);
|
||||||
}, 0);
|
}, 0);
|
||||||
},
|
},
|
||||||
inputRun() {
|
inputRun() {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.$store.commit('ndv/setInputRunIndex', this.inputRun);
|
this.ndvStore.setInputRunIndex(this.inputRun);
|
||||||
}, 0);
|
}, 0);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -428,7 +437,7 @@ export default mixins(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (e === null) {
|
if (e === null) {
|
||||||
this.$store.commit('ndv/setHoveringItem', null);
|
this.ndvStore.setHoveringItem(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,11 +447,11 @@ export default mixins(
|
||||||
outputIndex: e.outputIndex,
|
outputIndex: e.outputIndex,
|
||||||
itemIndex: e.itemIndex,
|
itemIndex: e.itemIndex,
|
||||||
};
|
};
|
||||||
this.$store.commit('ndv/setHoveringItem', item);
|
this.ndvStore.setHoveringItem(item);
|
||||||
},
|
},
|
||||||
onOutputItemHover(e: {itemIndex: number, outputIndex: number} | null) {
|
onOutputItemHover(e: {itemIndex: number, outputIndex: number} | null) {
|
||||||
if (e === null || !this.activeNode) {
|
if (e === null || !this.activeNode) {
|
||||||
this.$store.commit('ndv/setHoveringItem', null);
|
this.ndvStore.setHoveringItem(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,7 +461,7 @@ export default mixins(
|
||||||
outputIndex: e.outputIndex,
|
outputIndex: e.outputIndex,
|
||||||
itemIndex: e.itemIndex,
|
itemIndex: e.itemIndex,
|
||||||
};
|
};
|
||||||
this.$store.commit('ndv/setHoveringItem', item);
|
this.ndvStore.setHoveringItem(item);
|
||||||
},
|
},
|
||||||
onInputTableMounted(e: { avgRowHeight: number }) {
|
onInputTableMounted(e: { avgRowHeight: number }) {
|
||||||
this.avgInputRowHeight = e.avgRowHeight;
|
this.avgInputRowHeight = e.avgRowHeight;
|
||||||
|
@ -461,7 +470,7 @@ export default mixins(
|
||||||
this.avgOutputRowHeight = e.avgRowHeight;
|
this.avgOutputRowHeight = e.avgRowHeight;
|
||||||
},
|
},
|
||||||
onWorkflowActivate() {
|
onWorkflowActivate() {
|
||||||
this.$store.commit('ndv/setActiveNodeName', null);
|
this.ndvStore.activeNodeName = null;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.activateCurrentWorkflow('ndv');
|
this.activateCurrentWorkflow('ndv');
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
@ -471,7 +480,7 @@ export default mixins(
|
||||||
if (this.activeNode) {
|
if (this.activeNode) {
|
||||||
this.$telemetry.track('User clicked ndv link', {
|
this.$telemetry.track('User clicked ndv link', {
|
||||||
node_type: this.activeNode.type,
|
node_type: this.activeNode.type,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
pane: 'main',
|
pane: 'main',
|
||||||
type: 'i-wish-this-node-would',
|
type: 'i-wish-this-node-would',
|
||||||
|
@ -493,7 +502,7 @@ export default mixins(
|
||||||
end_position: e.position,
|
end_position: e.position,
|
||||||
node_type: this.activeNodeType ? this.activeNodeType.name : '',
|
node_type: this.activeNodeType ? this.activeNodeType.name : '',
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
});
|
});
|
||||||
this.mainPanelPosition = e.position;
|
this.mainPanelPosition = e.position;
|
||||||
},
|
},
|
||||||
|
@ -567,21 +576,23 @@ export default mixins(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$store.commit('pinData', { node: this.activeNode, data: jsonParse(value) });
|
if (this.activeNode) {
|
||||||
|
this.workflowsStore.pinData({ node: this.activeNode, data: jsonParse(value) });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$store.commit('ndv/setOutputPanelEditModeEnabled', false);
|
this.ndvStore.setOutputPanelEditModeEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$externalHooks().run('dataDisplay.nodeEditingFinished');
|
this.$externalHooks().run('dataDisplay.nodeEditingFinished');
|
||||||
this.$telemetry.track('User closed node modal', {
|
this.$telemetry.track('User closed node modal', {
|
||||||
node_type: this.activeNodeType ? this.activeNodeType.name : '',
|
node_type: this.activeNodeType ? this.activeNodeType.name : '',
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
});
|
});
|
||||||
this.triggerWaitingWarningEnabled = false;
|
this.triggerWaitingWarningEnabled = false;
|
||||||
this.$store.commit('ndv/setActiveNodeName', null);
|
this.ndvStore.activeNodeName = null;
|
||||||
this.$store.commit('ndv/resetNDVSessionId');
|
this.ndvStore.resetNDVSessionId();
|
||||||
},
|
},
|
||||||
onRunOutputIndexChange(run: number) {
|
onRunOutputIndexChange(run: number) {
|
||||||
this.runOutputIndex = run;
|
this.runOutputIndex = run;
|
||||||
|
@ -610,7 +621,7 @@ export default mixins(
|
||||||
this.$telemetry.track('User changed ndv input dropdown', {
|
this.$telemetry.track('User changed ndv input dropdown', {
|
||||||
node_type: this.activeNode ? this.activeNode.type : '',
|
node_type: this.activeNode ? this.activeNode.type : '',
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
selection_value: index,
|
selection_value: index,
|
||||||
input_node_type: this.inputNode ? this.inputNode.type : '',
|
input_node_type: this.inputNode ? this.inputNode.type : '',
|
||||||
});
|
});
|
||||||
|
|
|
@ -23,6 +23,10 @@ import mixins from 'vue-typed-mixins';
|
||||||
import { workflowRun } from './mixins/workflowRun';
|
import { workflowRun } from './mixins/workflowRun';
|
||||||
import { pinData } from './mixins/pinData';
|
import { pinData } from './mixins/pinData';
|
||||||
import { dataPinningEventBus } from '@/event-bus/data-pinning-event-bus';
|
import { dataPinningEventBus } from '@/event-bus/data-pinning-event-bus';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
workflowRun,
|
workflowRun,
|
||||||
|
@ -54,25 +58,30 @@ export default mixins(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
node (): INodeUi {
|
...mapStores(
|
||||||
return this.$store.getters.getNodeByName(this.nodeName);
|
useNodeTypesStore,
|
||||||
|
useNDVStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
|
node (): INodeUi | null {
|
||||||
|
return this.workflowsStore.getNodeByName(this.nodeName);
|
||||||
},
|
},
|
||||||
nodeType (): INodeTypeDescription | null {
|
nodeType (): INodeTypeDescription | null {
|
||||||
if (this.node) {
|
if (this.node) {
|
||||||
return this.$store.getters['nodeTypes/getNodeType'](this.node.type, this.node.typeVersion);
|
return this.nodeTypesStore.getNodeType(this.node.type, this.node.typeVersion);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
nodeRunning (): boolean {
|
nodeRunning (): boolean {
|
||||||
const triggeredNode = this.$store.getters.executedNode;
|
const triggeredNode = this.workflowsStore.executedNode;
|
||||||
const executingNode = this.$store.getters.executingNode;
|
const executingNode = this.workflowsStore.executingNode;
|
||||||
return this.workflowRunning && (executingNode === this.node.name || triggeredNode === this.node.name);
|
return this.workflowRunning && (executingNode === this.node.name || triggeredNode === this.node.name);
|
||||||
},
|
},
|
||||||
workflowRunning (): boolean {
|
workflowRunning (): boolean {
|
||||||
return this.$store.getters.isActionActive('workflowRunning');
|
return this.uiStore.isActionActive('workflowRunning');
|
||||||
},
|
},
|
||||||
isTriggerNode (): boolean {
|
isTriggerNode (): boolean {
|
||||||
return this.$store.getters['nodeTypes/isTriggerNode'](this.node.type);
|
return this.nodeTypesStore.isTriggerNode(this.node.type);
|
||||||
},
|
},
|
||||||
isManualTriggerNode (): boolean {
|
isManualTriggerNode (): boolean {
|
||||||
return Boolean(this.nodeType && this.nodeType.name === MANUAL_TRIGGER_NODE_TYPE);
|
return Boolean(this.nodeType && this.nodeType.name === MANUAL_TRIGGER_NODE_TYPE);
|
||||||
|
@ -87,8 +96,8 @@ export default mixins(
|
||||||
return Boolean(this.nodeType && this.nodeType.name === WEBHOOK_NODE_TYPE);
|
return Boolean(this.nodeType && this.nodeType.name === WEBHOOK_NODE_TYPE);
|
||||||
},
|
},
|
||||||
isListeningForEvents(): boolean {
|
isListeningForEvents(): boolean {
|
||||||
const waitingOnWebhook = this.$store.getters.executionWaitingForWebhook as boolean;
|
const waitingOnWebhook = this.workflowsStore.executionWaitingForWebhook;
|
||||||
const executedNode = this.$store.getters.executedNode as string | undefined;
|
const executedNode = this.workflowsStore.executedNode;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
this.node &&
|
this.node &&
|
||||||
|
@ -114,7 +123,8 @@ export default mixins(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isTriggerNode && this.hasIssues) {
|
if (this.isTriggerNode && this.hasIssues) {
|
||||||
if (this.$store.getters['ndv/activeNode'] && this.$store.getters['ndv/activeNode'].name !== this.nodeName) {
|
const activeNode = this.ndvStore.activeNode;
|
||||||
|
if (activeNode && activeNode.name !== this.nodeName) {
|
||||||
return this.$locale.baseText('ndv.execute.fixPrevious');
|
return this.$locale.baseText('ndv.execute.fixPrevious');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +164,7 @@ export default mixins(
|
||||||
methods: {
|
methods: {
|
||||||
async stopWaitingForWebhook () {
|
async stopWaitingForWebhook () {
|
||||||
try {
|
try {
|
||||||
await this.restApi().removeTestWebhook(this.$store.getters.workflowId);
|
await this.restApi().removeTestWebhook(this.workflowsStore.workflowId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$showError(
|
this.$showError(
|
||||||
error,
|
error,
|
||||||
|
@ -182,14 +192,14 @@ export default mixins(
|
||||||
|
|
||||||
if (shouldUnpinAndExecute) {
|
if (shouldUnpinAndExecute) {
|
||||||
dataPinningEventBus.$emit('data-unpinning', { source: 'unpin-and-execute-modal' });
|
dataPinningEventBus.$emit('data-unpinning', { source: 'unpin-and-execute-modal' });
|
||||||
this.$store.commit('unpinData', { node: this.node });
|
this.workflowsStore.unpinData({ node: this.node });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.hasPinData || shouldUnpinAndExecute) {
|
if (!this.hasPinData || shouldUnpinAndExecute) {
|
||||||
const telemetryPayload = {
|
const telemetryPayload = {
|
||||||
node_type: this.nodeType ? this.nodeType.name : null,
|
node_type: this.nodeType ? this.nodeType.name : null,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
source: this.telemetrySource,
|
source: this.telemetrySource,
|
||||||
};
|
};
|
||||||
this.$telemetry.track('User clicked execute node button', telemetryPayload);
|
this.$telemetry.track('User clicked execute node button', telemetryPayload);
|
||||||
|
|
|
@ -15,7 +15,9 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { IVersionNode } from '@/Interface';
|
import { IVersionNode } from '@/Interface';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
import { INodeTypeDescription } from 'n8n-workflow';
|
import { INodeTypeDescription } from 'n8n-workflow';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
interface NodeIconSource {
|
interface NodeIconSource {
|
||||||
|
@ -47,6 +49,9 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useRootStore,
|
||||||
|
),
|
||||||
type (): string {
|
type (): string {
|
||||||
const nodeType = this.nodeType as INodeTypeDescription | IVersionNode | null;
|
const nodeType = this.nodeType as INodeTypeDescription | IVersionNode | null;
|
||||||
let iconType = 'unknown';
|
let iconType = 'unknown';
|
||||||
|
@ -68,7 +73,7 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
iconSource () : NodeIconSource {
|
iconSource () : NodeIconSource {
|
||||||
const nodeType = this.nodeType as INodeTypeDescription | IVersionNode | null;
|
const nodeType = this.nodeType as INodeTypeDescription | IVersionNode | null;
|
||||||
const restUrl = this.$store.getters.getRestUrl;
|
const restUrl = this.rootStore.getRestUrl;
|
||||||
const iconSource = {} as NodeIconSource;
|
const iconSource = {} as NodeIconSource;
|
||||||
|
|
||||||
if (nodeType) {
|
if (nodeType) {
|
||||||
|
|
|
@ -152,6 +152,11 @@ import { nodeHelpers } from '@/components/mixins/nodeHelpers';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import NodeExecuteButton from './NodeExecuteButton.vue';
|
import NodeExecuteButton from './NodeExecuteButton.vue';
|
||||||
import { isCommunityPackageName } from './helpers';
|
import { isCommunityPackageName } from './helpers';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
export default mixins(externalHooks, nodeHelpers).extend({
|
export default mixins(externalHooks, nodeHelpers).extend({
|
||||||
name: 'NodeSettings',
|
name: 'NodeSettings',
|
||||||
|
@ -165,8 +170,14 @@ export default mixins(externalHooks, nodeHelpers).extend({
|
||||||
NodeExecuteButton,
|
NodeExecuteButton,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isCurlImportModalOpen() {
|
...mapStores(
|
||||||
return this.$store.getters['ui/isModalOpen'](IMPORT_CURL_MODAL_KEY);
|
useNodeTypesStore,
|
||||||
|
useNDVStore,
|
||||||
|
useUIStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
|
isCurlImportModalOpen(): boolean {
|
||||||
|
return this.uiStore.isModalOpen(IMPORT_CURL_MODAL_KEY);
|
||||||
},
|
},
|
||||||
nodeTypeName(): string {
|
nodeTypeName(): string {
|
||||||
if (this.nodeType) {
|
if (this.nodeType) {
|
||||||
|
@ -201,8 +212,8 @@ export default mixins(externalHooks, nodeHelpers).extend({
|
||||||
'background-color': this.node.color,
|
'background-color': this.node.color,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
node(): INodeUi {
|
node(): INodeUi | null {
|
||||||
return this.$store.getters['ndv/activeNode'];
|
return this.ndvStore.activeNode;
|
||||||
},
|
},
|
||||||
parametersSetting(): INodeProperties[] {
|
parametersSetting(): INodeProperties[] {
|
||||||
return this.parameters.filter((item) => {
|
return this.parameters.filter((item) => {
|
||||||
|
@ -222,13 +233,13 @@ export default mixins(externalHooks, nodeHelpers).extend({
|
||||||
return this.nodeType.properties;
|
return this.nodeType.properties;
|
||||||
},
|
},
|
||||||
outputPanelEditMode(): { enabled: boolean; value: string } {
|
outputPanelEditMode(): { enabled: boolean; value: string } {
|
||||||
return this.$store.getters['ndv/outputPanelEditMode'];
|
return this.ndvStore.outputPanelEditMode;
|
||||||
},
|
},
|
||||||
isCommunityNode(): boolean {
|
isCommunityNode(): boolean {
|
||||||
return isCommunityPackageName(this.node.type);
|
return isCommunityPackageName(this.node.type);
|
||||||
},
|
},
|
||||||
isTriggerNode(): boolean {
|
isTriggerNode(): boolean {
|
||||||
return this.$store.getters['nodeTypes/isTriggerNode'](this.node.type);
|
return this.nodeTypesStore.isTriggerNode(this.node.type);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -366,7 +377,7 @@ export default mixins(externalHooks, nodeHelpers).extend({
|
||||||
},
|
},
|
||||||
isCurlImportModalOpen(newValue, oldValue) {
|
isCurlImportModalOpen(newValue, oldValue) {
|
||||||
if (newValue === false) {
|
if (newValue === false) {
|
||||||
let parameters = this.$store.getters['ui/getHttpNodeParameters'];
|
let parameters = this.uiStore.getHttpNodeParameters || '';
|
||||||
|
|
||||||
if (!parameters) return;
|
if (!parameters) return;
|
||||||
|
|
||||||
|
@ -382,7 +393,7 @@ export default mixins(externalHooks, nodeHelpers).extend({
|
||||||
value: parameters,
|
value: parameters,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$store.dispatch('ui/setHttpNodeParameters', { parameters: '' });
|
this.uiStore.setHttpNodeParameters({ name: IMPORT_CURL_MODAL_KEY, parameters: '' });
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -452,12 +463,14 @@ export default mixins(externalHooks, nodeHelpers).extend({
|
||||||
},
|
},
|
||||||
credentialSelected(updateInformation: INodeUpdatePropertiesInformation) {
|
credentialSelected(updateInformation: INodeUpdatePropertiesInformation) {
|
||||||
// Update the values on the node
|
// Update the values on the node
|
||||||
this.$store.commit('updateNodeProperties', updateInformation);
|
this.workflowsStore.updateNodeProperties(updateInformation);
|
||||||
|
|
||||||
const node = this.$store.getters.getNodeByName(updateInformation.name);
|
const node = this.workflowsStore.getNodeByName(updateInformation.name);
|
||||||
|
|
||||||
// Update the issues
|
if (node) {
|
||||||
this.updateNodeCredentialIssues(node);
|
// Update the issues
|
||||||
|
this.updateNodeCredentialIssues(node);
|
||||||
|
}
|
||||||
|
|
||||||
this.$externalHooks().run('nodeSettings.credentialSelected', { updateInformation });
|
this.$externalHooks().run('nodeSettings.credentialSelected', { updateInformation });
|
||||||
},
|
},
|
||||||
|
@ -481,7 +494,12 @@ export default mixins(externalHooks, nodeHelpers).extend({
|
||||||
// Save the node name before we commit the change because
|
// Save the node name before we commit the change because
|
||||||
// we need the old name to rename the node properly
|
// we need the old name to rename the node properly
|
||||||
const nodeNameBefore = parameterData.node || this.node.name;
|
const nodeNameBefore = parameterData.node || this.node.name;
|
||||||
const node = this.$store.getters.getNodeByName(nodeNameBefore);
|
const node = this.workflowsStore.getNodeByName(nodeNameBefore);
|
||||||
|
|
||||||
|
if (node === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (parameterData.name === 'name') {
|
if (parameterData.name === 'name') {
|
||||||
// Name of node changed so we have to set also the new node name as active
|
// Name of node changed so we have to set also the new node name as active
|
||||||
|
|
||||||
|
@ -494,10 +512,7 @@ export default mixins(externalHooks, nodeHelpers).extend({
|
||||||
this.$emit('valueChanged', sendData);
|
this.$emit('valueChanged', sendData);
|
||||||
} else if (parameterData.name === 'parameters') {
|
} else if (parameterData.name === 'parameters') {
|
||||||
|
|
||||||
const nodeType = this.$store.getters['nodeTypes/getNodeType'](
|
const nodeType = this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
|
||||||
node.type,
|
|
||||||
node.typeVersion,
|
|
||||||
) as INodeTypeDescription | null;
|
|
||||||
if (!nodeType) {
|
if (!nodeType) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -573,23 +588,21 @@ export default mixins(externalHooks, nodeHelpers).extend({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the data in vuex
|
if (nodeParameters) {
|
||||||
const updateInformation = {
|
const updateInformation: IUpdateInformation = {
|
||||||
name: node.name,
|
name: node.name,
|
||||||
value: nodeParameters,
|
value: nodeParameters,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$store.commit('setNodeParameters', updateInformation);
|
this.workflowsStore.setNodeParameters(updateInformation);
|
||||||
|
|
||||||
this.updateNodeParameterIssues(node, nodeType);
|
this.updateNodeParameterIssues(node, nodeType);
|
||||||
this.updateNodeCredentialIssues(node);
|
this.updateNodeCredentialIssues(node);
|
||||||
|
}
|
||||||
} else if (parameterData.name.startsWith('parameters.')) {
|
} else if (parameterData.name.startsWith('parameters.')) {
|
||||||
// A node parameter changed
|
// A node parameter changed
|
||||||
|
|
||||||
const nodeType = this.$store.getters['nodeTypes/getNodeType'](
|
const nodeType = this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
|
||||||
node.type,
|
|
||||||
node.typeVersion,
|
|
||||||
) as INodeTypeDescription | null;
|
|
||||||
if (!nodeType) {
|
if (!nodeType) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -657,7 +670,7 @@ export default mixins(externalHooks, nodeHelpers).extend({
|
||||||
value: nodeParameters,
|
value: nodeParameters,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$store.commit('setNodeParameters', updateInformation);
|
this.workflowsStore.setNodeParameters(updateInformation);
|
||||||
|
|
||||||
this.$externalHooks().run('nodeSettings.valueChanged', {
|
this.$externalHooks().run('nodeSettings.valueChanged', {
|
||||||
parameterPath,
|
parameterPath,
|
||||||
|
@ -680,7 +693,8 @@ export default mixins(externalHooks, nodeHelpers).extend({
|
||||||
key: parameterData.name,
|
key: parameterData.name,
|
||||||
value: newValue,
|
value: newValue,
|
||||||
};
|
};
|
||||||
this.$store.commit('setNodeValue', updateInformation);
|
|
||||||
|
this.workflowsStore.setNodeValue(updateInformation);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,7 +6,10 @@
|
||||||
import { externalHooks } from '@/components/mixins/externalHooks';
|
import { externalHooks } from '@/components/mixins/externalHooks';
|
||||||
import { BUILTIN_NODES_DOCS_URL, COMMUNITY_NODES_INSTALLATION_DOCS_URL, NPM_PACKAGE_DOCS_BASE_URL } from '@/constants';
|
import { BUILTIN_NODES_DOCS_URL, COMMUNITY_NODES_INSTALLATION_DOCS_URL, NPM_PACKAGE_DOCS_BASE_URL } from '@/constants';
|
||||||
import { INodeUi, ITab } from '@/Interface';
|
import { INodeUi, ITab } from '@/Interface';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
import { INodeTypeDescription } from 'n8n-workflow';
|
import { INodeTypeDescription } from 'n8n-workflow';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import { isCommunityPackageName } from './helpers';
|
import { isCommunityPackageName } from './helpers';
|
||||||
|
@ -26,8 +29,12 @@ export default mixins(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
activeNode(): INodeUi {
|
...mapStores(
|
||||||
return this.$store.getters['ndv/activeNode'];
|
useNDVStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
|
activeNode(): INodeUi | null {
|
||||||
|
return this.ndvStore.activeNode;
|
||||||
},
|
},
|
||||||
documentationUrl (): string {
|
documentationUrl (): string {
|
||||||
const nodeType = this.nodeType as INodeTypeDescription | null;
|
const nodeType = this.nodeType as INodeTypeDescription | null;
|
||||||
|
@ -113,7 +120,7 @@ export default mixins(
|
||||||
this.$externalHooks().run('dataDisplay.onDocumentationUrlClick', { nodeType: this.nodeType as INodeTypeDescription, documentationUrl: this.documentationUrl });
|
this.$externalHooks().run('dataDisplay.onDocumentationUrlClick', { nodeType: this.nodeType as INodeTypeDescription, documentationUrl: this.documentationUrl });
|
||||||
this.$telemetry.track('User clicked ndv link', {
|
this.$telemetry.track('User clicked ndv link', {
|
||||||
node_type: this.activeNode.type,
|
node_type: this.activeNode.type,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
pane: 'main',
|
pane: 'main',
|
||||||
type: 'docs',
|
type: 'docs',
|
||||||
|
@ -121,7 +128,7 @@ export default mixins(
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tab === 'settings' && this.nodeType) {
|
if(tab === 'settings' && this.nodeType) {
|
||||||
this.$telemetry.track('User viewed node settings', { node_type: (this.nodeType as INodeTypeDescription).name, workflow_id: this.$store.getters.workflowId });
|
this.$telemetry.track('User viewed node settings', { node_type: (this.nodeType as INodeTypeDescription).name, workflow_id: this.workflowsStore.workflowId });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tab === 'settings' || tab === 'params') {
|
if (tab === 'settings' || tab === 'params') {
|
||||||
|
|
|
@ -55,6 +55,8 @@ import Modal from './Modal.vue';
|
||||||
|
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import { showMessage } from './mixins/showMessage';
|
import { showMessage } from './mixins/showMessage';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
showMessage,
|
showMessage,
|
||||||
|
@ -75,6 +77,7 @@ export default mixins(
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(useUIStore),
|
||||||
isEmailValid(): boolean {
|
isEmailValid(): boolean {
|
||||||
return VALID_EMAIL_REGEX.test(String(this.email).toLowerCase());
|
return VALID_EMAIL_REGEX.test(String(this.email).toLowerCase());
|
||||||
},
|
},
|
||||||
|
@ -90,7 +93,7 @@ export default mixins(
|
||||||
this.okToClose = false;
|
this.okToClose = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch('ui/applyForOnboardingCall', { email: this.email });
|
await this.uiStore.applyForOnboardingCall(this.email);
|
||||||
this.$showMessage({
|
this.$showMessage({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
title: this.$locale.baseText('onboardingCallSignupSucess.title'),
|
title: this.$locale.baseText('onboardingCallSignupSucess.title'),
|
||||||
|
|
|
@ -86,6 +86,11 @@ import RunData, { EnterEditModeArgs } from './RunData.vue';
|
||||||
import RunInfo from './RunInfo.vue';
|
import RunInfo from './RunInfo.vue';
|
||||||
import { pinData } from "@/components/mixins/pinData";
|
import { pinData } from "@/components/mixins/pinData";
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
type RunDataRef = Vue & { enterEditMode: (args: EnterEditModeArgs) => void };
|
type RunDataRef = Vue & { enterEditMode: (args: EnterEditModeArgs) => void };
|
||||||
|
|
||||||
|
@ -116,17 +121,23 @@ export default mixins(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
node(): INodeUi {
|
...mapStores(
|
||||||
return this.$store.getters['ndv/activeNode'];
|
useNodeTypesStore,
|
||||||
|
useNDVStore,
|
||||||
|
useUIStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
|
node(): INodeUi | null {
|
||||||
|
return this.ndvStore.activeNode;
|
||||||
},
|
},
|
||||||
nodeType (): INodeTypeDescription | null {
|
nodeType (): INodeTypeDescription | null {
|
||||||
if (this.node) {
|
if (this.node) {
|
||||||
return this.$store.getters['nodeTypes/getNodeType'](this.node.type, this.node.typeVersion);
|
return this.nodeTypesStore.getNodeType(this.node.type, this.node.typeVersion);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
isTriggerNode (): boolean {
|
isTriggerNode (): boolean {
|
||||||
return this.$store.getters['nodeTypes/isTriggerNode'](this.node.type);
|
return this.nodeTypesStore.isTriggerNode(this.node.type);
|
||||||
},
|
},
|
||||||
isPollingTypeNode (): boolean {
|
isPollingTypeNode (): boolean {
|
||||||
return !!(this.nodeType && this.nodeType.polling);
|
return !!(this.nodeType && this.nodeType.polling);
|
||||||
|
@ -135,14 +146,14 @@ export default mixins(
|
||||||
return !!(this.nodeType && this.nodeType.group.includes('schedule'));
|
return !!(this.nodeType && this.nodeType.group.includes('schedule'));
|
||||||
},
|
},
|
||||||
isNodeRunning(): boolean {
|
isNodeRunning(): boolean {
|
||||||
const executingNode = this.$store.getters.executingNode;
|
const executingNode = this.workflowsStore.executingNode;
|
||||||
return this.node && executingNode === this.node.name;
|
return this.node && executingNode === this.node.name;
|
||||||
},
|
},
|
||||||
workflowRunning (): boolean {
|
workflowRunning (): boolean {
|
||||||
return this.$store.getters.isActionActive('workflowRunning');
|
return this.uiStore.isActionActive('workflowRunning');
|
||||||
},
|
},
|
||||||
workflowExecution(): IExecutionResponse | null {
|
workflowExecution(): IExecutionResponse | null {
|
||||||
return this.$store.getters.getWorkflowExecution;
|
return this.workflowsStore.getWorkflowExecution;
|
||||||
},
|
},
|
||||||
workflowRunData(): IRunData | null {
|
workflowRunData(): IRunData | null {
|
||||||
if (this.workflowExecution === null) {
|
if (this.workflowExecution === null) {
|
||||||
|
@ -155,7 +166,7 @@ export default mixins(
|
||||||
return executionData.resultData.runData;
|
return executionData.resultData.runData;
|
||||||
},
|
},
|
||||||
hasNodeRun(): boolean {
|
hasNodeRun(): boolean {
|
||||||
if (this.$store.getters.subworkflowExecutionError) return true;
|
if (this.workflowsStore.subWorkflowExecutionError) return true;
|
||||||
|
|
||||||
return Boolean(
|
return Boolean(
|
||||||
this.node && this.workflowRunData && this.workflowRunData.hasOwnProperty(this.node.name),
|
this.node && this.workflowRunData && this.workflowRunData.hasOwnProperty(this.node.name),
|
||||||
|
@ -199,7 +210,7 @@ export default mixins(
|
||||||
if (!this.node) {
|
if (!this.node) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const updatedAt = this.$store.getters.getParametersLastUpdated(this.node.name);
|
const updatedAt = this.workflowsStore.getParametersLastUpdate(this.node.name);
|
||||||
if (!updatedAt || !this.runTaskData) {
|
if (!updatedAt || !this.runTaskData) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -207,7 +218,7 @@ export default mixins(
|
||||||
return updatedAt > runAt;
|
return updatedAt > runAt;
|
||||||
},
|
},
|
||||||
outputPanelEditMode(): { enabled: boolean; value: string; } {
|
outputPanelEditMode(): { enabled: boolean; value: string; } {
|
||||||
return this.$store.getters['ndv/outputPanelEditMode'];
|
return this.ndvStore.outputPanelEditMode;
|
||||||
},
|
},
|
||||||
canPinData(): boolean {
|
canPinData(): boolean {
|
||||||
return this.isPinDataNodeType && !this.isReadOnly;
|
return this.isPinDataNodeType && !this.isReadOnly;
|
||||||
|
@ -221,7 +232,7 @@ export default mixins(
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$telemetry.track('User clicked ndv link', {
|
this.$telemetry.track('User clicked ndv link', {
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
node_type: this.node.type,
|
node_type: this.node.type,
|
||||||
pane: 'output',
|
pane: 'output',
|
||||||
|
@ -239,7 +250,7 @@ export default mixins(
|
||||||
this.$emit('openSettings');
|
this.$emit('openSettings');
|
||||||
this.$telemetry.track('User clicked ndv link', {
|
this.$telemetry.track('User clicked ndv link', {
|
||||||
node_type: this.node.type,
|
node_type: this.node.type,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
pane: 'output',
|
pane: 'output',
|
||||||
type: 'settings',
|
type: 'settings',
|
||||||
|
|
|
@ -339,6 +339,10 @@ import { mapGetters } from 'vuex';
|
||||||
import { CODE_NODE_TYPE } from '@/constants';
|
import { CODE_NODE_TYPE } from '@/constants';
|
||||||
import { PropType } from 'vue';
|
import { PropType } from 'vue';
|
||||||
import { debounceHelper } from './mixins/debounce';
|
import { debounceHelper } from './mixins/debounce';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
externalHooks,
|
externalHooks,
|
||||||
|
@ -472,6 +476,11 @@ export default mixins(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNodeTypesStore,
|
||||||
|
useNDVStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
...mapGetters('credentials', ['allCredentialTypes']),
|
...mapGetters('credentials', ['allCredentialTypes']),
|
||||||
expressionDisplayValue(): string {
|
expressionDisplayValue(): string {
|
||||||
if (this.activeDrop || this.forceShowExpression) {
|
if (this.activeDrop || this.forceShowExpression) {
|
||||||
|
@ -499,7 +508,7 @@ export default mixins(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the resolved parameter values of the current node
|
// Get the resolved parameter values of the current node
|
||||||
const currentNodeParameters = this.$store.getters['ndv/activeNode'].parameters;
|
const currentNodeParameters = this.ndvStore.activeNode?.parameters;
|
||||||
try {
|
try {
|
||||||
const resolvedNodeParameters = this.resolveParameter(currentNodeParameters);
|
const resolvedNodeParameters = this.resolveParameter(currentNodeParameters);
|
||||||
|
|
||||||
|
@ -514,7 +523,7 @@ export default mixins(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
node (): INodeUi | null {
|
node (): INodeUi | null {
|
||||||
return this.$store.getters['ndv/activeNode'];
|
return this.ndvStore.activeNode;
|
||||||
},
|
},
|
||||||
displayTitle (): string {
|
displayTitle (): string {
|
||||||
const interpolation = { interpolate: { shortPath: this.shortPath } };
|
const interpolation = { interpolate: { shortPath: this.shortPath } };
|
||||||
|
@ -742,12 +751,14 @@ export default mixins(
|
||||||
},
|
},
|
||||||
credentialSelected (updateInformation: INodeUpdatePropertiesInformation) {
|
credentialSelected (updateInformation: INodeUpdatePropertiesInformation) {
|
||||||
// Update the values on the node
|
// Update the values on the node
|
||||||
this.$store.commit('updateNodeProperties', updateInformation);
|
this.workflowsStore.updateNodeProperties(updateInformation);
|
||||||
|
|
||||||
const node = this.$store.getters.getNodeByName(updateInformation.name);
|
const node = this.workflowsStore.getNodeByName(updateInformation.name);
|
||||||
|
|
||||||
// Update the issues
|
if (node) {
|
||||||
this.updateNodeCredentialIssues(node);
|
// Update the issues
|
||||||
|
this.updateNodeCredentialIssues(node);
|
||||||
|
}
|
||||||
|
|
||||||
this.$externalHooks().run('nodeSettings.credentialSelected', { updateInformation });
|
this.$externalHooks().run('nodeSettings.credentialSelected', { updateInformation });
|
||||||
},
|
},
|
||||||
|
@ -784,12 +795,12 @@ export default mixins(
|
||||||
// Get the resolved parameter values of the current node
|
// Get the resolved parameter values of the current node
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const currentNodeParameters = (this.$store.getters['ndv/activeNode'] as INodeUi).parameters;
|
const currentNodeParameters = (this.ndvStore.activeNode as INodeUi).parameters;
|
||||||
const resolvedNodeParameters = this.resolveParameter(currentNodeParameters) as INodeParameters;
|
const resolvedNodeParameters = this.resolveParameter(currentNodeParameters) as INodeParameters;
|
||||||
const loadOptionsMethod = this.getArgument('loadOptionsMethod') as string | undefined;
|
const loadOptionsMethod = this.getArgument('loadOptionsMethod') as string | undefined;
|
||||||
const loadOptions = this.getArgument('loadOptions') as ILoadOptions | undefined;
|
const loadOptions = this.getArgument('loadOptions') as ILoadOptions | undefined;
|
||||||
|
|
||||||
const options = await this.$store.dispatch('nodeTypes/getNodeParameterOptions',
|
const options = await this.nodeTypesStore.getNodeParameterOptions(
|
||||||
{
|
{
|
||||||
nodeTypeAndVersion: {
|
nodeTypeAndVersion: {
|
||||||
name: this.node.type,
|
name: this.node.type,
|
||||||
|
@ -827,8 +838,8 @@ export default mixins(
|
||||||
parameter_name: this.parameter.displayName,
|
parameter_name: this.parameter.displayName,
|
||||||
parameter_field_type: this.parameter.type,
|
parameter_field_type: this.parameter.type,
|
||||||
new_expression: !this.isValueExpression,
|
new_expression: !this.isValueExpression,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
session_id: this.$store.getters['ndv/ndvSessionId'],
|
session_id: this.ndvStore.sessionId,
|
||||||
source: this.eventSource || 'ndv',
|
source: this.eventSource || 'ndv',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -956,11 +967,11 @@ export default mixins(
|
||||||
|
|
||||||
if (this.parameter.name === 'operation' || this.parameter.name === 'mode') {
|
if (this.parameter.name === 'operation' || this.parameter.name === 'mode') {
|
||||||
this.$telemetry.track('User set node operation or mode', {
|
this.$telemetry.track('User set node operation or mode', {
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
node_type: this.node && this.node.type,
|
node_type: this.node && this.node.type,
|
||||||
resource: this.node && this.node.parameters.resource,
|
resource: this.node && this.node.parameters.resource,
|
||||||
is_custom: value === CUSTOM_API_CALL_KEY,
|
is_custom: value === CUSTOM_API_CALL_KEY,
|
||||||
session_id: this.$store.getters['ndv/ndvSessionId'],
|
session_id: this.ndvStore.sessionId,
|
||||||
parameter: this.parameter.name,
|
parameter: this.parameter.name,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,8 @@ import Vue, { PropType } from 'vue';
|
||||||
import ParameterInputWrapper from './ParameterInputWrapper.vue';
|
import ParameterInputWrapper from './ParameterInputWrapper.vue';
|
||||||
import { isValueExpression } from './helpers';
|
import { isValueExpression } from './helpers';
|
||||||
import { INodeParameterResourceLocator, INodeProperties } from 'n8n-workflow';
|
import { INodeParameterResourceLocator, INodeProperties } from 'n8n-workflow';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'parameter-input-expanded',
|
name: 'parameter-input-expanded',
|
||||||
|
@ -85,6 +87,9 @@ export default Vue.extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
showRequiredErrors(): boolean {
|
showRequiredErrors(): boolean {
|
||||||
if (!this.$props.parameter.required) {
|
if (!this.$props.parameter.required) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -136,7 +141,7 @@ export default Vue.extend({
|
||||||
this.$telemetry.track('User clicked credential modal docs link', {
|
this.$telemetry.track('User clicked credential modal docs link', {
|
||||||
docs_link: this.documentationUrl,
|
docs_link: this.documentationUrl,
|
||||||
source: 'field',
|
source: 'field',
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -79,6 +79,8 @@ import { hasOnlyListMode } from '@/components/ResourceLocator/helpers';
|
||||||
import { INodeParameters, INodeProperties, INodePropertyMode } from 'n8n-workflow';
|
import { INodeParameters, INodeProperties, INodePropertyMode } from 'n8n-workflow';
|
||||||
import { isResourceLocatorValue } from '@/typeGuards';
|
import { isResourceLocatorValue } from '@/typeGuards';
|
||||||
import { BaseTextKey } from "@/plugins/i18n";
|
import { BaseTextKey } from "@/plugins/i18n";
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
showMessage,
|
showMessage,
|
||||||
|
@ -135,8 +137,11 @@ export default mixins(
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNDVStore,
|
||||||
|
),
|
||||||
node (): INodeUi | null {
|
node (): INodeUi | null {
|
||||||
return this.$store.getters['ndv/activeNode'];
|
return this.ndvStore.activeNode;
|
||||||
},
|
},
|
||||||
hint (): string | null {
|
hint (): string | null {
|
||||||
return this.$locale.nodeText().hint(this.parameter, this.path);
|
return this.$locale.nodeText().hint(this.parameter, this.path);
|
||||||
|
@ -154,10 +159,10 @@ export default mixins(
|
||||||
return this.isResourceLocator ? !hasOnlyListMode(this.parameter): true;
|
return this.isResourceLocator ? !hasOnlyListMode(this.parameter): true;
|
||||||
},
|
},
|
||||||
isInputDataEmpty (): boolean {
|
isInputDataEmpty (): boolean {
|
||||||
return this.$store.getters['ndv/getNDVDataIsEmpty']('input');
|
return this.ndvStore.isDNVDataEmpty('input');
|
||||||
},
|
},
|
||||||
displayMode(): IRunDataDisplayMode {
|
displayMode(): IRunDataDisplayMode {
|
||||||
return this.$store.getters['ndv/inputPanelDisplayMode'];
|
return this.ndvStore.inputPanelDisplayMode;
|
||||||
},
|
},
|
||||||
showMappingTooltip (): boolean {
|
showMappingTooltip (): boolean {
|
||||||
return this.focused && this.isInputTypeString && !this.isInputDataEmpty && window.localStorage.getItem(LOCAL_STORAGE_MAPPING_FLAG) !== 'true';
|
return this.focused && this.isInputTypeString && !this.isInputDataEmpty && window.localStorage.getItem(LOCAL_STORAGE_MAPPING_FLAG) !== 'true';
|
||||||
|
@ -167,13 +172,13 @@ export default mixins(
|
||||||
onFocus() {
|
onFocus() {
|
||||||
this.focused = true;
|
this.focused = true;
|
||||||
if (!this.parameter.noDataExpression) {
|
if (!this.parameter.noDataExpression) {
|
||||||
this.$store.commit('ndv/setMappableNDVInputFocus', this.parameter.displayName);
|
this.ndvStore.setMappableNDVInputFocus(this.parameter.displayName);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onBlur() {
|
onBlur() {
|
||||||
this.focused = false;
|
this.focused = false;
|
||||||
if (!this.parameter.noDataExpression) {
|
if (!this.parameter.noDataExpression) {
|
||||||
this.$store.commit('ndv/setMappableNDVInputFocus', '');
|
this.ndvStore.setMappableNDVInputFocus('');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onMenuExpanded(expanded: boolean) {
|
onMenuExpanded(expanded: boolean) {
|
||||||
|
@ -250,7 +255,7 @@ export default mixins(
|
||||||
window.localStorage.setItem(LOCAL_STORAGE_MAPPING_FLAG, 'true');
|
window.localStorage.setItem(LOCAL_STORAGE_MAPPING_FLAG, 'true');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$store.commit('ndv/setMappingTelemetry', {
|
this.ndvStore.setMappingTelemetry({
|
||||||
dest_node_type: this.node.type,
|
dest_node_type: this.node.type,
|
||||||
dest_parameter: this.path,
|
dest_parameter: this.path,
|
||||||
dest_parameter_mode: typeof prevValue === 'string' && prevValue.startsWith('=')? 'expression': 'fixed',
|
dest_parameter_mode: typeof prevValue === 'string' && prevValue.startsWith('=')? 'expression': 'fixed',
|
||||||
|
|
|
@ -119,6 +119,9 @@ import { get, set } from 'lodash';
|
||||||
|
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import {Component} from "vue";
|
import {Component} from "vue";
|
||||||
|
import { mapState, mapStores } from 'pinia';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
workflowHelpers,
|
workflowHelpers,
|
||||||
|
@ -141,6 +144,10 @@ export default mixins(
|
||||||
'isReadOnly',
|
'isReadOnly',
|
||||||
],
|
],
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNodeTypesStore,
|
||||||
|
useNDVStore,
|
||||||
|
),
|
||||||
nodeTypeVersion(): number | null {
|
nodeTypeVersion(): number | null {
|
||||||
if (this.node) {
|
if (this.node) {
|
||||||
return this.node.typeVersion;
|
return this.node.typeVersion;
|
||||||
|
@ -159,8 +166,8 @@ export default mixins(
|
||||||
filteredParameterNames (): string[] {
|
filteredParameterNames (): string[] {
|
||||||
return this.filteredParameters.map(parameter => parameter.name);
|
return this.filteredParameters.map(parameter => parameter.name);
|
||||||
},
|
},
|
||||||
node (): INodeUi {
|
node (): INodeUi | null {
|
||||||
return this.$store.getters['ndv/activeNode'];
|
return this.ndvStore.activeNode;
|
||||||
},
|
},
|
||||||
indexToShowSlotAt (): number {
|
indexToShowSlotAt (): number {
|
||||||
let index = 0;
|
let index = 0;
|
||||||
|
@ -179,7 +186,7 @@ export default mixins(
|
||||||
methods: {
|
methods: {
|
||||||
getCredentialsDependencies() {
|
getCredentialsDependencies() {
|
||||||
const dependencies = new Set();
|
const dependencies = new Set();
|
||||||
const nodeType = this.$store.getters['nodeTypes/getNodeType'](this.node.type, this.node.typeVersion) as INodeTypeDescription | undefined;
|
const nodeType = this.nodeTypesStore.getNodeType(this.node?.type || '', this.node?.typeVersion);
|
||||||
|
|
||||||
// Get names of all fields that credentials rendering depends on (using displayOptions > show)
|
// Get names of all fields that credentials rendering depends on (using displayOptions > show)
|
||||||
if(nodeType && nodeType.credentials) {
|
if(nodeType && nodeType.credentials) {
|
||||||
|
@ -323,7 +330,7 @@ export default mixins(
|
||||||
if (!newValue.includes(parameter)) {
|
if (!newValue.includes(parameter)) {
|
||||||
const parameterData = {
|
const parameterData = {
|
||||||
name: `${this.path}.${parameter}`,
|
name: `${this.path}.${parameter}`,
|
||||||
node: this.$store.getters['ndv/activeNode'].name,
|
node: this.ndvStore.activeNode?.name || '',
|
||||||
value: undefined,
|
value: undefined,
|
||||||
};
|
};
|
||||||
this.$emit('valueChanged', parameterData);
|
this.$emit('valueChanged', parameterData);
|
||||||
|
|
|
@ -37,6 +37,8 @@ import { INodeProperties, INodePropertyMode, IRunData, isResourceLocatorValue, N
|
||||||
import { INodeUi, IUiState, IUpdateInformation, TargetItem } from '@/Interface';
|
import { INodeUi, IUiState, IUpdateInformation, TargetItem } from '@/Interface';
|
||||||
import { workflowHelpers } from './mixins/workflowHelpers';
|
import { workflowHelpers } from './mixins/workflowHelpers';
|
||||||
import { isValueExpression } from './helpers';
|
import { isValueExpression } from './helpers';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
showMessage,
|
showMessage,
|
||||||
|
@ -97,11 +99,14 @@ export default mixins(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNDVStore,
|
||||||
|
),
|
||||||
isValueExpression () {
|
isValueExpression () {
|
||||||
return isValueExpression(this.parameter, this.value);
|
return isValueExpression(this.parameter, this.value);
|
||||||
},
|
},
|
||||||
activeNode(): INodeUi | null {
|
activeNode(): INodeUi | null {
|
||||||
return this.$store.getters['ndv/activeNode'];
|
return this.ndvStore.activeNode;
|
||||||
},
|
},
|
||||||
selectedRLMode(): INodePropertyMode | undefined {
|
selectedRLMode(): INodePropertyMode | undefined {
|
||||||
if (typeof this.value !== 'object' ||this.parameter.type !== 'resourceLocator' || !isResourceLocatorValue(this.value)) {
|
if (typeof this.value !== 'object' ||this.parameter.type !== 'resourceLocator' || !isResourceLocatorValue(this.value)) {
|
||||||
|
@ -126,17 +131,17 @@ export default mixins(
|
||||||
return this.hint;
|
return this.hint;
|
||||||
},
|
},
|
||||||
targetItem(): TargetItem | null {
|
targetItem(): TargetItem | null {
|
||||||
return this.$store.getters['ndv/hoveringItem'];
|
return this.ndvStore.hoveringItem;
|
||||||
},
|
},
|
||||||
expressionValueComputed (): string | null {
|
expressionValueComputed (): string | null {
|
||||||
const inputNodeName: string | undefined = this.$store.getters['ndv/ndvInputNodeName'];
|
const inputNodeName: string | undefined = this.ndvStore.ndvInputNodeName;
|
||||||
const value = isResourceLocatorValue(this.value)? this.value.value: this.value;
|
const value = isResourceLocatorValue(this.value)? this.value.value: this.value;
|
||||||
if (this.activeNode === null || !this.isValueExpression || typeof value !== 'string') {
|
if (this.activeNode === null || !this.isValueExpression || typeof value !== 'string') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputRunIndex: number | undefined = this.$store.getters['ndv/ndvInputRunIndex'];
|
const inputRunIndex: number | undefined = this.ndvStore.ndvInputRunIndex;
|
||||||
const inputBranchIndex: number | undefined = this.$store.getters['ndv/ndvInputBranchIndex'];
|
const inputBranchIndex: number | undefined = this.ndvStore.ndvInputBranchIndex;
|
||||||
|
|
||||||
let computedValue: NodeParameterValue;
|
let computedValue: NodeParameterValue;
|
||||||
try {
|
try {
|
||||||
|
@ -157,7 +162,7 @@ export default mixins(
|
||||||
},
|
},
|
||||||
expressionOutput(): string | null {
|
expressionOutput(): string | null {
|
||||||
if (this.isValueExpression && this.expressionValueComputed) {
|
if (this.isValueExpression && this.expressionValueComputed) {
|
||||||
const inputData = this.$store.getters['ndv/ndvInputData'];
|
const inputData = this.ndvStore.ndvInputData;
|
||||||
if (!inputData || (inputData && inputData.length <= 1)) {
|
if (!inputData || (inputData && inputData.length <= 1)) {
|
||||||
return this.expressionValueComputed;
|
return this.expressionValueComputed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
>
|
>
|
||||||
<template v-slot:content>
|
<template v-slot:content>
|
||||||
<div v-if="submitted" :class="$style.submittedContainer">
|
<div v-if="submitted" :class="$style.submittedContainer">
|
||||||
<img :class="$style.demoImage" :src="baseUrl + 'suggestednodes.png'" />
|
<img :class="$style.demoImage" :src="rootStore.baseUrl + 'suggestednodes.png'" />
|
||||||
<n8n-text>{{ $locale.baseText('personalizationModal.lookOutForThingsMarked') }}</n8n-text>
|
<n8n-text>{{ $locale.baseText('personalizationModal.lookOutForThingsMarked') }}</n8n-text>
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style.container" v-else>
|
<div :class="$style.container" v-else>
|
||||||
|
@ -50,7 +50,6 @@ import mixins from 'vue-typed-mixins';
|
||||||
const SURVEY_VERSION = 'v3';
|
const SURVEY_VERSION = 'v3';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CODING_SKILL_KEY,
|
|
||||||
COMPANY_SIZE_100_499,
|
COMPANY_SIZE_100_499,
|
||||||
COMPANY_SIZE_1000_OR_MORE,
|
COMPANY_SIZE_1000_OR_MORE,
|
||||||
COMPANY_SIZE_20_OR_LESS,
|
COMPANY_SIZE_20_OR_LESS,
|
||||||
|
@ -116,11 +115,15 @@ import {
|
||||||
import { workflowHelpers } from '@/components/mixins/workflowHelpers';
|
import { workflowHelpers } from '@/components/mixins/workflowHelpers';
|
||||||
import { showMessage } from '@/components/mixins/showMessage';
|
import { showMessage } from '@/components/mixins/showMessage';
|
||||||
import Modal from './Modal.vue';
|
import Modal from './Modal.vue';
|
||||||
import { IFormInputs, IPersonalizationLatestVersion } from '@/Interface';
|
import { IFormInputs, IPersonalizationLatestVersion, IPersonalizationSurveyAnswersV3, IUser } from '@/Interface';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { mapGetters } from 'vuex';
|
|
||||||
import { getAccountAge } from '@/modules/userHelpers';
|
import { getAccountAge } from '@/modules/userHelpers';
|
||||||
import { GenericValue } from 'n8n-workflow';
|
import { GenericValue } from 'n8n-workflow';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
import { useUsersStore } from '@/stores/users';
|
||||||
|
|
||||||
export default mixins(showMessage, workflowHelpers).extend({
|
export default mixins(showMessage, workflowHelpers).extend({
|
||||||
components: { Modal },
|
components: { Modal },
|
||||||
|
@ -138,15 +141,12 @@ export default mixins(showMessage, workflowHelpers).extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapStores(
|
||||||
baseUrl: 'getBaseUrl',
|
useRootStore,
|
||||||
}),
|
useSettingsStore,
|
||||||
...mapGetters('users', [
|
useUIStore,
|
||||||
'currentUser',
|
useUsersStore,
|
||||||
]),
|
),
|
||||||
...mapGetters('settings', [
|
|
||||||
'isOnboardingCallPromptFeatureEnabled',
|
|
||||||
]),
|
|
||||||
survey() {
|
survey() {
|
||||||
const survey: IFormInputs = [
|
const survey: IFormInputs = [
|
||||||
{
|
{
|
||||||
|
@ -470,12 +470,12 @@ export default mixins(showMessage, workflowHelpers).extend({
|
||||||
...values,
|
...values,
|
||||||
version: SURVEY_VERSION,
|
version: SURVEY_VERSION,
|
||||||
personalization_survey_submitted_at: new Date().toISOString(),
|
personalization_survey_submitted_at: new Date().toISOString(),
|
||||||
personalization_survey_n8n_version: this.$store.getters.versionCli,
|
personalization_survey_n8n_version: this.rootStore.versionCli,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$externalHooks().run('personalizationModal.onSubmit', survey);
|
this.$externalHooks().run('personalizationModal.onSubmit', survey);
|
||||||
|
|
||||||
await this.$store.dispatch('users/submitPersonalizationSurvey', survey);
|
await this.usersStore.submitPersonalizationSurvey(survey as IPersonalizationSurveyAnswersV3);
|
||||||
|
|
||||||
if (Object.keys(values).length === 0) {
|
if (Object.keys(values).length === 0) {
|
||||||
this.closeDialog();
|
this.closeDialog();
|
||||||
|
@ -490,8 +490,8 @@ export default mixins(showMessage, workflowHelpers).extend({
|
||||||
this.$data.isSaving = false;
|
this.$data.isSaving = false;
|
||||||
},
|
},
|
||||||
async fetchOnboardingPrompt() {
|
async fetchOnboardingPrompt() {
|
||||||
if (this.isOnboardingCallPromptFeatureEnabled && getAccountAge(this.currentUser) <= ONBOARDING_PROMPT_TIMEBOX) {
|
if (this.settingsStore.onboardingCallPromptEnabled && getAccountAge(this.usersStore.currentUser || {} as IUser) <= ONBOARDING_PROMPT_TIMEBOX) {
|
||||||
const onboardingResponse = await this.$store.dispatch('ui/getNextOnboardingPrompt');
|
const onboardingResponse = await this.uiStore.getNextOnboardingPrompt();
|
||||||
const promptTimeout = onboardingResponse.toast_sequence_number === 1 ? FIRST_ONBOARDING_PROMPT_TIMEOUT : 1000;
|
const promptTimeout = onboardingResponse.toast_sequence_number === 1 ? FIRST_ONBOARDING_PROMPT_TIMEOUT : 1000;
|
||||||
|
|
||||||
if (onboardingResponse.title && onboardingResponse.description) {
|
if (onboardingResponse.title && onboardingResponse.description) {
|
||||||
|
@ -509,7 +509,7 @@ export default mixins(showMessage, workflowHelpers).extend({
|
||||||
title: onboardingResponse.title,
|
title: onboardingResponse.title,
|
||||||
description: onboardingResponse.description,
|
description: onboardingResponse.description,
|
||||||
});
|
});
|
||||||
this.$store.commit('ui/openModal', ONBOARDING_CALL_SIGNUP_MODAL_KEY, {root: true});
|
this.uiStore.openModal(ONBOARDING_CALL_SIGNUP_MODAL_KEY);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}, promptTimeout);
|
}, promptTimeout);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<span>
|
<span>
|
||||||
<div class="push-connection-lost primary-color" v-if="!pushConnectionActive">
|
<div class="push-connection-lost primary-color" v-if="!rootStore.pushConnectionActive">
|
||||||
<n8n-tooltip placement="bottom-end" >
|
<n8n-tooltip placement="bottom-end" >
|
||||||
<div slot="content" v-html="$locale.baseText('pushConnectionTracker.cannotConnectToServer')"></div>
|
<div slot="content" v-html="$locale.baseText('pushConnectionTracker.cannotConnectToServer')"></div>
|
||||||
<span>
|
<span>
|
||||||
|
@ -13,13 +13,16 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { useRootStore } from "@/stores/n8nRootStore";
|
||||||
|
import { mapStores } from "pinia";
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import { mapGetters } from "vuex";
|
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: "PushConnectionTracker",
|
name: "PushConnectionTracker",
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(["pushConnectionActive"]),
|
...mapStores(
|
||||||
|
useRootStore,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -172,6 +172,12 @@ import { workflowHelpers } from '../mixins/workflowHelpers';
|
||||||
import { nodeHelpers } from '../mixins/nodeHelpers';
|
import { nodeHelpers } from '../mixins/nodeHelpers';
|
||||||
import { getAppNameFromNodeName } from '../helpers';
|
import { getAppNameFromNodeName } from '../helpers';
|
||||||
import { isResourceLocatorValue } from '@/typeGuards';
|
import { isResourceLocatorValue } from '@/typeGuards';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
interface IResourceLocatorQuery {
|
interface IResourceLocatorQuery {
|
||||||
results: INodeListSearchItems[];
|
results: INodeListSearchItems[];
|
||||||
|
@ -248,7 +254,6 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
mainPanelMutationSubscription: () => {},
|
|
||||||
showResourceDropdown: false,
|
showResourceDropdown: false,
|
||||||
searchFilter: '',
|
searchFilter: '',
|
||||||
cachedResponses: {} as { [key: string]: IResourceLocatorQuery },
|
cachedResponses: {} as { [key: string]: IResourceLocatorQuery },
|
||||||
|
@ -257,13 +262,20 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNodeTypesStore,
|
||||||
|
useNDVStore,
|
||||||
|
useRootStore,
|
||||||
|
useUIStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
appName(): string {
|
appName(): string {
|
||||||
if (!this.node) {
|
if (!this.node) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const nodeType = this.$store.getters['nodeTypes/getNodeType'](this.node.type);
|
const nodeType = this.nodeTypesStore.getNodeType(this.node.type);
|
||||||
return getAppNameFromNodeName(nodeType.displayName);
|
return getAppNameFromNodeName(nodeType?.displayName || '');
|
||||||
},
|
},
|
||||||
selectedMode(): string {
|
selectedMode(): string {
|
||||||
if (typeof this.value !== 'object') { // legacy mode
|
if (typeof this.value !== 'object') { // legacy mode
|
||||||
|
@ -280,7 +292,7 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
|
||||||
return this.selectedMode === 'list';
|
return this.selectedMode === 'list';
|
||||||
},
|
},
|
||||||
hasCredential(): boolean {
|
hasCredential(): boolean {
|
||||||
const node = this.$store.getters['ndv/activeNode'] as INodeUi | null;
|
const node = this.ndvStore.activeNode;
|
||||||
if (!node) {
|
if (!node) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -425,24 +437,21 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$on('refreshList', this.refreshList);
|
this.$on('refreshList', this.refreshList);
|
||||||
window.addEventListener('resize', this.setWidth);
|
window.addEventListener('resize', this.setWidth);
|
||||||
this.mainPanelMutationSubscription = this.$store.subscribe(this.setWidthOnMainPanelResize);
|
useNDVStore().$subscribe((mutation, state) => {
|
||||||
|
// Update the width when main panel dimension change
|
||||||
|
this.setWidth();
|
||||||
|
});
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.setWidth();
|
this.setWidth();
|
||||||
}, 0);
|
}, 0);
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
// Unsubscribe
|
|
||||||
this.mainPanelMutationSubscription();
|
|
||||||
window.removeEventListener('resize', this.setWidth);
|
window.removeEventListener('resize', this.setWidth);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setWidth() {
|
setWidth() {
|
||||||
this.width = (this.$refs.container as HTMLElement).offsetWidth;
|
this.width = (this.$refs.container as HTMLElement).offsetWidth;
|
||||||
},
|
},
|
||||||
setWidthOnMainPanelResize(mutation: { type: string }) {
|
|
||||||
// Update the width when main panel dimension change
|
|
||||||
if(mutation.type === 'ndv/setMainPanelDimensions') this.setWidth();
|
|
||||||
},
|
|
||||||
getLinkAlt(entity: string) {
|
getLinkAlt(entity: string) {
|
||||||
if (this.selectedMode === 'list' && entity) {
|
if (this.selectedMode === 'list' && entity) {
|
||||||
return this.$locale.baseText('resourceLocator.openSpecificResource', { interpolate: { entity, appName: this.appName } });
|
return this.$locale.baseText('resourceLocator.openSpecificResource', { interpolate: { entity, appName: this.appName } });
|
||||||
|
@ -480,7 +489,7 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
|
||||||
return parameter.typeOptions[argumentName];
|
return parameter.typeOptions[argumentName];
|
||||||
},
|
},
|
||||||
openCredential(): void {
|
openCredential(): void {
|
||||||
const node = this.$store.getters['ndv/activeNode'] as INodeUi | null;
|
const node = this.ndvStore.activeNode;
|
||||||
if (!node || !node.credentials) {
|
if (!node || !node.credentials) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -489,7 +498,7 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const id = node.credentials[credentialKey].id;
|
const id = node.credentials[credentialKey].id;
|
||||||
this.$store.dispatch('ui/openExistingCredential', { id });
|
this.uiStore.openExistingCredential(id);
|
||||||
},
|
},
|
||||||
findModeByName(name: string): INodePropertyMode | null {
|
findModeByName(name: string): INodePropertyMode | null {
|
||||||
if (this.parameter.modes) {
|
if (this.parameter.modes) {
|
||||||
|
@ -533,8 +542,8 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
|
||||||
},
|
},
|
||||||
trackEvent(event: string, params?: {[key: string]: string}): void {
|
trackEvent(event: string, params?: {[key: string]: string}): void {
|
||||||
this.$telemetry.track(event, {
|
this.$telemetry.track(event, {
|
||||||
instance_id: this.$store.getters.instanceId,
|
instance_id: this.rootStore.instanceId,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
node_type: this.node && this.node.type,
|
node_type: this.node && this.node.type,
|
||||||
resource: this.node && this.node.parameters && this.node.parameters.resource,
|
resource: this.node && this.node.parameters && this.node.parameters.resource,
|
||||||
operation: this.node && this.node.parameters && this.node.parameters.operation,
|
operation: this.node && this.node.parameters && this.node.parameters.operation,
|
||||||
|
@ -618,10 +627,7 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
|
||||||
...(paginationToken ? { paginationToken } : {}),
|
...(paginationToken ? { paginationToken } : {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
const response: INodeListSearchResult = await this.$store.dispatch(
|
const response = await this.nodeTypesStore.getResourceLocatorResults(requestParams);
|
||||||
'nodeTypes/getResourceLocatorResults',
|
|
||||||
requestParams,
|
|
||||||
);
|
|
||||||
|
|
||||||
this.setResponse(paramsKey, {
|
this.setResponse(paramsKey, {
|
||||||
results: (cachedResponse ? cachedResponse.results : []).concat(response.results),
|
results: (cachedResponse ? cachedResponse.results : []).concat(response.results),
|
||||||
|
|
|
@ -145,7 +145,7 @@
|
||||||
:value="editMode.value"
|
:value="editMode.value"
|
||||||
:options="{ scrollBeyondLastLine: false }"
|
:options="{ scrollBeyondLastLine: false }"
|
||||||
type="json"
|
type="json"
|
||||||
@input="$store.commit('ndv/setOutputPanelEditModeValue', $event)"
|
@input="ndvStore.setOutputPanelEditModeValue($event)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div :class="$style['edit-mode-footer']">
|
<div :class="$style['edit-mode-footer']">
|
||||||
|
@ -344,6 +344,7 @@ import {
|
||||||
IBinaryDisplayData,
|
IBinaryDisplayData,
|
||||||
IExecutionResponse,
|
IExecutionResponse,
|
||||||
INodeUi,
|
INodeUi,
|
||||||
|
INodeUpdatePropertiesInformation,
|
||||||
IRunDataDisplayMode,
|
IRunDataDisplayMode,
|
||||||
ITab,
|
ITab,
|
||||||
} from '@/Interface';
|
} from '@/Interface';
|
||||||
|
@ -373,6 +374,10 @@ import { clearJsonKey, executionDataToJson, stringSizeInBytes } from './helpers'
|
||||||
import RunDataTable from './RunDataTable.vue';
|
import RunDataTable from './RunDataTable.vue';
|
||||||
import RunDataJson from '@/components/RunDataJson.vue';
|
import RunDataJson from '@/components/RunDataJson.vue';
|
||||||
import { isEmpty } from '@/utils';
|
import { isEmpty } from '@/utils';
|
||||||
|
import { useWorkflowsStore } from "@/stores/workflows";
|
||||||
|
import { mapStores } from "pinia";
|
||||||
|
import { useNDVStore } from "@/stores/ndv";
|
||||||
|
import { useNodeTypesStore } from "@/stores/nodeTypes";
|
||||||
|
|
||||||
export type EnterEditModeArgs = {
|
export type EnterEditModeArgs = {
|
||||||
origin: 'editIconButton' | 'insertTestDataLink',
|
origin: 'editIconButton' | 'insertTestDataLink',
|
||||||
|
@ -475,8 +480,8 @@ export default mixins(
|
||||||
this.showPinDataDiscoveryTooltip(this.jsonData);
|
this.showPinDataDiscoveryTooltip(this.jsonData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.$store.commit('ndv/setNDVBranchIndex', {
|
this.ndvStore.setNDVBranchIndex({
|
||||||
pane: this.paneType,
|
pane: this.paneType as "input" | "output",
|
||||||
branchIndex: this.currentOutputIndex,
|
branchIndex: this.currentOutputIndex,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -486,8 +491,13 @@ export default mixins(
|
||||||
this.eventBus.$off('data-unpinning', this.onDataUnpinning);
|
this.eventBus.$off('data-unpinning', this.onDataUnpinning);
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
activeNode(): INodeUi {
|
...mapStores(
|
||||||
return this.$store.getters['ndv/activeNode'];
|
useNodeTypesStore,
|
||||||
|
useNDVStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
|
activeNode(): INodeUi | null {
|
||||||
|
return this.ndvStore.activeNode;
|
||||||
},
|
},
|
||||||
dataPinningDocsUrl(): string {
|
dataPinningDocsUrl(): string {
|
||||||
return DATA_PINNING_DOCS_URL;
|
return DATA_PINNING_DOCS_URL;
|
||||||
|
@ -496,19 +506,19 @@ export default mixins(
|
||||||
return DATA_EDITING_DOCS_URL;
|
return DATA_EDITING_DOCS_URL;
|
||||||
},
|
},
|
||||||
displayMode(): IRunDataDisplayMode {
|
displayMode(): IRunDataDisplayMode {
|
||||||
return this.$store.getters['ndv/getPanelDisplayMode'](this.paneType);
|
return this.ndvStore.getPanelDisplayMode(this.paneType as "input" | "output");
|
||||||
},
|
},
|
||||||
node(): INodeUi | null {
|
node(): INodeUi | null {
|
||||||
return (this.nodeUi as INodeUi | null) || null;
|
return (this.nodeUi as INodeUi | null) || null;
|
||||||
},
|
},
|
||||||
nodeType (): INodeTypeDescription | null {
|
nodeType (): INodeTypeDescription | null {
|
||||||
if (this.node) {
|
if (this.node) {
|
||||||
return this.$store.getters['nodeTypes/getNodeType'](this.node.type, this.node.typeVersion);
|
return this.nodeTypesStore.getNodeType(this.node.type, this.node.typeVersion);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
isTriggerNode (): boolean {
|
isTriggerNode (): boolean {
|
||||||
return this.$store.getters['nodeTypes/isTriggerNode'](this.node.type);
|
return this.nodeTypesStore.isTriggerNode(this.node.type);
|
||||||
},
|
},
|
||||||
canPinData (): boolean {
|
canPinData (): boolean {
|
||||||
return !this.isPaneTypeInput &&
|
return !this.isPaneTypeInput &&
|
||||||
|
@ -532,7 +542,7 @@ export default mixins(
|
||||||
return Boolean(!this.isExecuting && this.node && (this.workflowRunData && this.workflowRunData.hasOwnProperty(this.node.name) || this.hasPinData));
|
return Boolean(!this.isExecuting && this.node && (this.workflowRunData && this.workflowRunData.hasOwnProperty(this.node.name) || this.hasPinData));
|
||||||
},
|
},
|
||||||
subworkflowExecutionError(): Error | null {
|
subworkflowExecutionError(): Error | null {
|
||||||
return this.$store.getters.subworkflowExecutionError;
|
return this.workflowsStore.subWorkflowExecutionError;
|
||||||
},
|
},
|
||||||
hasSubworkflowExecutionError(): boolean {
|
hasSubworkflowExecutionError(): boolean {
|
||||||
return Boolean(this.subworkflowExecutionError);
|
return Boolean(this.subworkflowExecutionError);
|
||||||
|
@ -541,7 +551,7 @@ export default mixins(
|
||||||
return Boolean(this.node && this.workflowRunData && this.workflowRunData[this.node.name] && this.workflowRunData[this.node.name][this.runIndex] && this.workflowRunData[this.node.name][this.runIndex].error);
|
return Boolean(this.node && this.workflowRunData && this.workflowRunData[this.node.name] && this.workflowRunData[this.node.name][this.runIndex] && this.workflowRunData[this.node.name][this.runIndex].error);
|
||||||
},
|
},
|
||||||
workflowExecution (): IExecutionResponse | null {
|
workflowExecution (): IExecutionResponse | null {
|
||||||
return this.$store.getters.getWorkflowExecution;
|
return this.workflowsStore.getWorkflowExecution;
|
||||||
},
|
},
|
||||||
workflowRunData (): IRunData | null {
|
workflowRunData (): IRunData | null {
|
||||||
if (this.workflowExecution === null) {
|
if (this.workflowExecution === null) {
|
||||||
|
@ -680,7 +690,7 @@ export default mixins(
|
||||||
editMode(): { enabled: boolean; value: string; } {
|
editMode(): { enabled: boolean; value: string; } {
|
||||||
return this.isPaneTypeInput
|
return this.isPaneTypeInput
|
||||||
? { enabled: false, value: '' }
|
? { enabled: false, value: '' }
|
||||||
: this.$store.getters['ndv/outputPanelEditMode'];
|
: this.ndvStore.outputPanelEditMode;
|
||||||
},
|
},
|
||||||
isPaneTypeInput(): boolean {
|
isPaneTypeInput(): boolean {
|
||||||
return this.paneType === 'input';
|
return this.paneType === 'input';
|
||||||
|
@ -700,9 +710,9 @@ export default mixins(
|
||||||
},
|
},
|
||||||
onClickDataPinningDocsLink() {
|
onClickDataPinningDocsLink() {
|
||||||
this.$telemetry.track('User clicked ndv link', {
|
this.$telemetry.track('User clicked ndv link', {
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
node_type: this.activeNode.type,
|
node_type: this.activeNode?.type,
|
||||||
pane: 'output',
|
pane: 'output',
|
||||||
type: 'data-pinning-docs',
|
type: 'data-pinning-docs',
|
||||||
});
|
});
|
||||||
|
@ -742,11 +752,11 @@ export default mixins(
|
||||||
? inputData
|
? inputData
|
||||||
: TEST_PIN_DATA;
|
: TEST_PIN_DATA;
|
||||||
|
|
||||||
this.$store.commit('ndv/setOutputPanelEditModeEnabled', true);
|
this.ndvStore.setOutputPanelEditModeEnabled(true);
|
||||||
this.$store.commit('ndv/setOutputPanelEditModeValue', JSON.stringify(data, null, 2));
|
this.ndvStore.setOutputPanelEditModeValue(JSON.stringify(data, null, 2));
|
||||||
|
|
||||||
this.$telemetry.track('User opened ndv edit state', {
|
this.$telemetry.track('User opened ndv edit state', {
|
||||||
node_type: this.activeNode.type,
|
node_type: this.activeNode?.type,
|
||||||
click_type: origin === 'editIconButton' ? 'button' : 'link',
|
click_type: origin === 'editIconButton' ? 'button' : 'link',
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
run_index: this.runIndex,
|
run_index: this.runIndex,
|
||||||
|
@ -756,8 +766,8 @@ export default mixins(
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onClickCancelEdit() {
|
onClickCancelEdit() {
|
||||||
this.$store.commit('ndv/setOutputPanelEditModeEnabled', false);
|
this.ndvStore.setOutputPanelEditModeEnabled(false);
|
||||||
this.$store.commit('ndv/setOutputPanelEditModeValue', '');
|
this.ndvStore.setOutputPanelEditModeValue('');
|
||||||
this.onExitEditMode({ type: 'cancel' });
|
this.onExitEditMode({ type: 'cancel' });
|
||||||
},
|
},
|
||||||
onClickSaveEdit() {
|
onClickSaveEdit() {
|
||||||
|
@ -775,8 +785,8 @@ export default mixins(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$store.commit('ndv/setOutputPanelEditModeEnabled', false);
|
this.ndvStore.setOutputPanelEditModeEnabled(false);
|
||||||
this.$store.commit('pinData', { node: this.node, data: clearJsonKey(value) });
|
this.workflowsStore.pinData({ node: this.node, data: clearJsonKey(value) as INodeExecutionData[] });
|
||||||
|
|
||||||
this.onDataPinningSuccess({ source: 'save-edit' });
|
this.onDataPinningSuccess({ source: 'save-edit' });
|
||||||
|
|
||||||
|
@ -784,7 +794,7 @@ export default mixins(
|
||||||
},
|
},
|
||||||
onExitEditMode({ type }: { type: 'save' | 'cancel' }) {
|
onExitEditMode({ type }: { type: 'save' | 'cancel' }) {
|
||||||
this.$telemetry.track('User closed ndv edit state', {
|
this.$telemetry.track('User closed ndv edit state', {
|
||||||
node_type: this.activeNode.type,
|
node_type: this.activeNode?.type,
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
run_index: this.runIndex,
|
run_index: this.runIndex,
|
||||||
view: this.displayMode,
|
view: this.displayMode,
|
||||||
|
@ -795,7 +805,7 @@ export default mixins(
|
||||||
{ source }: { source: 'banner-link' | 'pin-icon-click' | 'unpin-and-execute-modal' },
|
{ source }: { source: 'banner-link' | 'pin-icon-click' | 'unpin-and-execute-modal' },
|
||||||
) {
|
) {
|
||||||
this.$telemetry.track('User unpinned ndv data', {
|
this.$telemetry.track('User unpinned ndv data', {
|
||||||
node_type: this.activeNode.type,
|
node_type: this.activeNode?.type,
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
run_index: this.runIndex,
|
run_index: this.runIndex,
|
||||||
source,
|
source,
|
||||||
|
@ -849,11 +859,11 @@ export default mixins(
|
||||||
|
|
||||||
if (this.hasPinData) {
|
if (this.hasPinData) {
|
||||||
this.onDataUnpinning({ source });
|
this.onDataUnpinning({ source });
|
||||||
this.$store.commit('unpinData', { node: this.node });
|
this.workflowsStore.unpinData({ node: this.node });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = executionDataToJson(this.rawInputData);
|
const data = executionDataToJson(this.rawInputData) as INodeExecutionData[];
|
||||||
|
|
||||||
if (!this.isValidPinDataSize(data)) {
|
if (!this.isValidPinDataSize(data)) {
|
||||||
this.onDataPinningError({ errorType: 'data-too-large', source: 'pin-icon-click' });
|
this.onDataPinningError({ errorType: 'data-too-large', source: 'pin-icon-click' });
|
||||||
|
@ -862,7 +872,7 @@ export default mixins(
|
||||||
|
|
||||||
this.onDataPinningSuccess({ source: 'pin-icon-click' });
|
this.onDataPinningSuccess({ source: 'pin-icon-click' });
|
||||||
|
|
||||||
this.$store.commit('pinData', { node: this.node, data });
|
this.workflowsStore.pinData({ node: this.node, data });
|
||||||
|
|
||||||
if (this.maxRunIndex > 0) {
|
if (this.maxRunIndex > 0) {
|
||||||
this.$showToast({
|
this.$showToast({
|
||||||
|
@ -898,7 +908,7 @@ export default mixins(
|
||||||
this.showData = true;
|
this.showData = true;
|
||||||
this.$telemetry.track('User clicked ndv button', {
|
this.$telemetry.track('User clicked ndv button', {
|
||||||
node_type: this.activeNode.type,
|
node_type: this.activeNode.type,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
pane: this.paneType,
|
pane: this.paneType,
|
||||||
type: 'showTooMuchData',
|
type: 'showTooMuchData',
|
||||||
|
@ -912,8 +922,8 @@ export default mixins(
|
||||||
},
|
},
|
||||||
onCurrentPageChange() {
|
onCurrentPageChange() {
|
||||||
this.$telemetry.track('User changed ndv page', {
|
this.$telemetry.track('User changed ndv page', {
|
||||||
node_type: this.activeNode.type,
|
node_type: this.activeNode?.type,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
pane: this.paneType,
|
pane: this.paneType,
|
||||||
page_selected: this.currentPage,
|
page_selected: this.currentPage,
|
||||||
|
@ -929,8 +939,8 @@ export default mixins(
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$telemetry.track('User changed ndv page size', {
|
this.$telemetry.track('User changed ndv page size', {
|
||||||
node_type: this.activeNode.type,
|
node_type: this.activeNode?.type,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
pane: this.paneType,
|
pane: this.paneType,
|
||||||
page_selected: this.currentPage,
|
page_selected: this.currentPage,
|
||||||
|
@ -940,7 +950,7 @@ export default mixins(
|
||||||
},
|
},
|
||||||
onDisplayModeChange(displayMode: IRunDataDisplayMode) {
|
onDisplayModeChange(displayMode: IRunDataDisplayMode) {
|
||||||
const previous = this.displayMode;
|
const previous = this.displayMode;
|
||||||
this.$store.commit('ndv/setPanelDisplayMode', {pane: this.paneType, mode: displayMode});
|
this.ndvStore.setPanelDisplayMode({pane: this.paneType as "input" | "output", mode: displayMode});
|
||||||
|
|
||||||
const dataContainer = this.$refs.dataContainer;
|
const dataContainer = this.$refs.dataContainer;
|
||||||
if (dataContainer) {
|
if (dataContainer) {
|
||||||
|
@ -958,7 +968,7 @@ export default mixins(
|
||||||
previous_view: previous,
|
previous_view: previous,
|
||||||
new_view: displayMode,
|
new_view: displayMode,
|
||||||
node_type: this.activeNode.type,
|
node_type: this.activeNode.type,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
pane: this.paneType,
|
pane: this.paneType,
|
||||||
});
|
});
|
||||||
|
@ -1012,10 +1022,10 @@ export default mixins(
|
||||||
this.refreshDataSize();
|
this.refreshDataSize();
|
||||||
this.closeBinaryDataDisplay();
|
this.closeBinaryDataDisplay();
|
||||||
if (this.binaryData.length > 0) {
|
if (this.binaryData.length > 0) {
|
||||||
this.$store.commit('ndv/setPanelDisplayMode', {pane: this.paneType, mode: 'binary'});
|
this.ndvStore.setPanelDisplayMode({pane: this.paneType as "input" | "output", mode: 'binary'});
|
||||||
}
|
}
|
||||||
else if (this.displayMode === 'binary') {
|
else if (this.displayMode === 'binary') {
|
||||||
this.$store.commit('ndv/setPanelDisplayMode', {pane: this.paneType, mode: 'table'});
|
this.ndvStore.setPanelDisplayMode({pane: this.paneType as "input" | "output", mode: 'table'});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
closeBinaryDataDisplay () {
|
closeBinaryDataDisplay () {
|
||||||
|
@ -1023,7 +1033,7 @@ export default mixins(
|
||||||
this.binaryDataDisplayData = null;
|
this.binaryDataDisplayData = null;
|
||||||
},
|
},
|
||||||
clearExecutionData () {
|
clearExecutionData () {
|
||||||
this.$store.commit('setWorkflowExecutionData', null);
|
this.workflowsStore.setWorkflowExecutionData(null);
|
||||||
this.updateNodesExecutionIssues();
|
this.updateNodesExecutionIssues();
|
||||||
},
|
},
|
||||||
isDownloadable (index: number, key: string): boolean {
|
isDownloadable (index: number, key: string): boolean {
|
||||||
|
@ -1093,15 +1103,15 @@ export default mixins(
|
||||||
name: this.node.name,
|
name: this.node.name,
|
||||||
properties: {
|
properties: {
|
||||||
disabled: !this.node.disabled,
|
disabled: !this.node.disabled,
|
||||||
},
|
} as IDataObject,
|
||||||
};
|
} as INodeUpdatePropertiesInformation;
|
||||||
|
|
||||||
this.$store.commit('updateNodeProperties', updateInformation);
|
this.workflowsStore.updateNodeProperties(updateInformation);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
goToErroredNode() {
|
goToErroredNode() {
|
||||||
if (this.node) {
|
if (this.node) {
|
||||||
this.$store.commit('ndv/setActiveNodeName', this.node.name);
|
this.ndvStore.activeNodeName = this.node.name;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1112,7 +1122,7 @@ export default mixins(
|
||||||
inputData:{
|
inputData:{
|
||||||
handler(data: INodeExecutionData[]) {
|
handler(data: INodeExecutionData[]) {
|
||||||
if(this.paneType && data){
|
if(this.paneType && data){
|
||||||
this.$store.commit('ndv/setNDVPanelDataIsEmpty', { panel: this.paneType, isEmpty: data.every(item => isEmpty(item.json)) });
|
this.ndvStore.setNDVPanelDataIsEmpty({ panel: this.paneType as "input" | "output", isEmpty: data.every(item => isEmpty(item.json)) });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
immediate: true,
|
immediate: true,
|
||||||
|
@ -1135,8 +1145,8 @@ export default mixins(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
currentOutputIndex(branchIndex: number) {
|
currentOutputIndex(branchIndex: number) {
|
||||||
this.$store.commit('ndv/setNDVBranchIndex', {
|
this.ndvStore.setNDVBranchIndex({
|
||||||
pane: this.paneType,
|
pane: this.paneType as "input" | "output",
|
||||||
branchIndex,
|
branchIndex,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -66,6 +66,8 @@ import { convertPath, executionDataToJson, isString, isStringNumber } from "@/co
|
||||||
import { INodeUi } from "@/Interface";
|
import { INodeUi } from "@/Interface";
|
||||||
import { shorten } from './helpers';
|
import { shorten } from './helpers';
|
||||||
import { externalHooks } from "@/components/mixins/externalHooks";
|
import { externalHooks } from "@/components/mixins/externalHooks";
|
||||||
|
import { mapStores } from "pinia";
|
||||||
|
import { useNDVStore } from "@/stores/ndv";
|
||||||
|
|
||||||
const runDataJsonActions = () => import('@/components/RunDataJsonActions.vue');
|
const runDataJsonActions = () => import('@/components/RunDataJsonActions.vue');
|
||||||
|
|
||||||
|
@ -137,6 +139,9 @@ export default mixins(externalHooks).extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNDVStore,
|
||||||
|
),
|
||||||
jsonData(): IDataObject[] {
|
jsonData(): IDataObject[] {
|
||||||
return executionDataToJson(this.inputData as INodeExecutionData[]);
|
return executionDataToJson(this.inputData as INodeExecutionData[]);
|
||||||
},
|
},
|
||||||
|
@ -165,13 +170,13 @@ export default mixins(externalHooks).extend({
|
||||||
this.draggingPath = el.dataset.path;
|
this.draggingPath = el.dataset.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$store.commit('ndv/resetMappingTelemetry');
|
this.ndvStore.resetMappingTelemetry();
|
||||||
},
|
},
|
||||||
onDragEnd(el: HTMLElement) {
|
onDragEnd(el: HTMLElement) {
|
||||||
this.draggingPath = null;
|
this.draggingPath = null;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const mappingTelemetry = this.$store.getters['ndv/mappingTelemetry'];
|
const mappingTelemetry = this.ndvStore.mappingTelemetry;
|
||||||
const telemetryPayload = {
|
const telemetryPayload = {
|
||||||
src_node_type: this.node.type,
|
src_node_type: this.node.type,
|
||||||
src_field_name: el.dataset.name || '',
|
src_field_name: el.dataset.name || '',
|
||||||
|
|
|
@ -35,6 +35,9 @@ import { pinData } from "@/components/mixins/pinData";
|
||||||
import { nodeHelpers } from "@/components/mixins/nodeHelpers";
|
import { nodeHelpers } from "@/components/mixins/nodeHelpers";
|
||||||
import { genericHelpers } from "@/components/mixins/genericHelpers";
|
import { genericHelpers } from "@/components/mixins/genericHelpers";
|
||||||
import { clearJsonKey, convertPath, executionDataToJson } from "@/components/helpers";
|
import { clearJsonKey, convertPath, executionDataToJson } from "@/components/helpers";
|
||||||
|
import { mapStores } from "pinia";
|
||||||
|
import { useWorkflowsStore } from "@/stores/workflows";
|
||||||
|
import { useNDVStore } from "@/stores/ndv";
|
||||||
|
|
||||||
type JsonPathData = {
|
type JsonPathData = {
|
||||||
path: string;
|
path: string;
|
||||||
|
@ -83,8 +86,12 @@ export default mixins(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
activeNode(): INodeUi {
|
...mapStores(
|
||||||
return this.$store.getters['ndv/activeNode'];
|
useNDVStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
|
activeNode(): INodeUi | null {
|
||||||
|
return this.ndvStore.activeNode;
|
||||||
},
|
},
|
||||||
normalisedJsonPath(): string {
|
normalisedJsonPath(): string {
|
||||||
const isNotSelected = this.selectedJsonPath === nonExistingJsonPath;
|
const isNotSelected = this.selectedJsonPath === nonExistingJsonPath;
|
||||||
|
@ -189,7 +196,7 @@ export default mixins(
|
||||||
run_index: this.runIndex,
|
run_index: this.runIndex,
|
||||||
view: 'json',
|
view: 'json',
|
||||||
copy_type: copyType,
|
copy_type: copyType,
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
pane: this.paneType,
|
pane: this.paneType,
|
||||||
in_execution_log: this.isReadOnly,
|
in_execution_log: this.isReadOnly,
|
||||||
});
|
});
|
||||||
|
|
|
@ -152,14 +152,18 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { INodeUi, IRootState, ITableData, NDVState } from '@/Interface';
|
/* eslint-disable prefer-spread */
|
||||||
|
import { INodeUi, ITableData, NDVState } from '@/Interface';
|
||||||
import { getPairedItemId } from '@/pairedItemUtils';
|
import { getPairedItemId } from '@/pairedItemUtils';
|
||||||
import Vue, { PropType } from 'vue';
|
import Vue, { PropType } from 'vue';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import { GenericValue, IDataObject, INodeExecutionData } from 'n8n-workflow';
|
import { GenericValue, IDataObject, INodeExecutionData } from 'n8n-workflow';
|
||||||
import Draggable from '@/components/Draggable.vue';
|
import Draggable from './Draggable.vue';
|
||||||
import { shorten } from '@/components/helpers';
|
import { shorten } from './helpers';
|
||||||
import { externalHooks } from '@/components/mixins/externalHooks';
|
import { externalHooks } from './mixins/externalHooks';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
|
||||||
const MAX_COLUMNS_LIMIT = 40;
|
const MAX_COLUMNS_LIMIT = 40;
|
||||||
|
|
||||||
|
@ -217,11 +221,15 @@ export default mixins(externalHooks).extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNDVStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
hoveringItem(): NDVState['hoveringItem'] {
|
hoveringItem(): NDVState['hoveringItem'] {
|
||||||
return this.$store.getters['ndv/hoveringItem'];
|
return this.ndvStore.hoveringItem;
|
||||||
},
|
},
|
||||||
pairedItemMappings(): IRootState['workflowExecutionPairedItemMappings'] {
|
pairedItemMappings(): {[itemId: string]: Set<string>} {
|
||||||
return this.$store.getters['workflowExecutionPairedItemMappings'];
|
return this.workflowsStore.workflowExecutionPairedItemMappings;
|
||||||
},
|
},
|
||||||
tableData(): ITableData {
|
tableData(): ITableData {
|
||||||
return this.convertToTable(this.inputData);
|
return this.convertToTable(this.inputData);
|
||||||
|
@ -360,8 +368,7 @@ export default mixins(externalHooks).extend({
|
||||||
},
|
},
|
||||||
onDragStart() {
|
onDragStart() {
|
||||||
this.draggedColumn = true;
|
this.draggedColumn = true;
|
||||||
|
this.ndvStore.resetMappingTelemetry();
|
||||||
this.$store.commit('ndv/resetMappingTelemetry');
|
|
||||||
},
|
},
|
||||||
onCellDragStart(el: HTMLElement) {
|
onCellDragStart(el: HTMLElement) {
|
||||||
if (el && el.dataset.value) {
|
if (el && el.dataset.value) {
|
||||||
|
@ -384,7 +391,7 @@ export default mixins(externalHooks).extend({
|
||||||
},
|
},
|
||||||
onDragEnd(column: string, src: string, depth = '0') {
|
onDragEnd(column: string, src: string, depth = '0') {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const mappingTelemetry = this.$store.getters['ndv/mappingTelemetry'];
|
const mappingTelemetry = this.ndvStore.mappingTelemetry;
|
||||||
const telemetryPayload = {
|
const telemetryPayload = {
|
||||||
src_node_type: this.node.type,
|
src_node_type: this.node.type,
|
||||||
src_field_name: column,
|
src_field_name: column,
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<template #menuSuffix>
|
<template #menuSuffix>
|
||||||
<div :class="$style.versionContainer">
|
<div :class="$style.versionContainer">
|
||||||
<n8n-link @click="onVersionClick" size="small">
|
<n8n-link @click="onVersionClick" size="small">
|
||||||
{{ $locale.baseText('settings.version') }} {{ versionCli }}
|
{{ $locale.baseText('settings.version') }} {{ rootStore.versionCli }}
|
||||||
</n8n-link>
|
</n8n-link>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -29,6 +29,10 @@ import { pushConnection } from "@/components/mixins/pushConnection";
|
||||||
import { IFakeDoor } from '@/Interface';
|
import { IFakeDoor } from '@/Interface';
|
||||||
import { IMenuItem } from 'n8n-design-system';
|
import { IMenuItem } from 'n8n-design-system';
|
||||||
import { BaseTextKey } from '@/plugins/i18n';
|
import { BaseTextKey } from '@/plugins/i18n';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
userHelpers,
|
userHelpers,
|
||||||
|
@ -36,9 +40,13 @@ export default mixins(
|
||||||
).extend({
|
).extend({
|
||||||
name: 'SettingsSidebar',
|
name: 'SettingsSidebar',
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters('settings', ['versionCli']),
|
...mapStores(
|
||||||
|
useRootStore,
|
||||||
|
useSettingsStore,
|
||||||
|
useUIStore,
|
||||||
|
),
|
||||||
settingsFakeDoorFeatures(): IFakeDoor[] {
|
settingsFakeDoorFeatures(): IFakeDoor[] {
|
||||||
return this.$store.getters['ui/getFakeDoorByLocation']('settings');
|
return this.uiStore.getFakeDoorByLocation('settings');
|
||||||
},
|
},
|
||||||
sidebarMenuItems(): IMenuItem[] {
|
sidebarMenuItems(): IMenuItem[] {
|
||||||
|
|
||||||
|
@ -113,13 +121,13 @@ export default mixins(
|
||||||
return this.canUserAccessRouteByName(VIEWS.API_SETTINGS);
|
return this.canUserAccessRouteByName(VIEWS.API_SETTINGS);
|
||||||
},
|
},
|
||||||
onVersionClick() {
|
onVersionClick() {
|
||||||
this.$store.dispatch('ui/openModal', ABOUT_MODAL_KEY);
|
this.uiStore.openModal(ABOUT_MODAL_KEY);
|
||||||
},
|
},
|
||||||
onReturn() {
|
onReturn() {
|
||||||
this.$router.push({name: VIEWS.HOMEPAGE});
|
this.$router.push({name: VIEWS.HOMEPAGE});
|
||||||
},
|
},
|
||||||
openUpdatesPanel() {
|
openUpdatesPanel() {
|
||||||
this.$store.dispatch('ui/openModal', VERSIONS_MODAL_KEY);
|
this.uiStore.openModal(VERSIONS_MODAL_KEY);
|
||||||
},
|
},
|
||||||
async handleSelect (key: string) {
|
async handleSelect (key: string) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
|
|
@ -50,12 +50,18 @@ import { nodeBase } from '@/components/mixins/nodeBase';
|
||||||
import { nodeHelpers } from '@/components/mixins/nodeHelpers';
|
import { nodeHelpers } from '@/components/mixins/nodeHelpers';
|
||||||
import { workflowHelpers } from '@/components/mixins/workflowHelpers';
|
import { workflowHelpers } from '@/components/mixins/workflowHelpers';
|
||||||
import { getStyleTokenValue, isNumber, isString } from './helpers';
|
import { getStyleTokenValue, isNumber, isString } from './helpers';
|
||||||
import { INodeUi, XYPosition } from '@/Interface';
|
import { INodeUi, INodeUpdatePropertiesInformation, IUpdateInformation, XYPosition } from '@/Interface';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
IDataObject,
|
||||||
INodeTypeDescription,
|
INodeTypeDescription,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { QUICKSTART_NOTE_NAME } from '@/constants';
|
import { QUICKSTART_NOTE_NAME } from '@/constants';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
export default mixins(externalHooks, nodeBase, nodeHelpers, workflowHelpers).extend({
|
export default mixins(externalHooks, nodeBase, nodeHelpers, workflowHelpers).extend({
|
||||||
name: 'Sticky',
|
name: 'Sticky',
|
||||||
|
@ -68,6 +74,12 @@ export default mixins(externalHooks, nodeBase, nodeHelpers, workflowHelpers).ext
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNodeTypesStore,
|
||||||
|
useNDVStore,
|
||||||
|
useUIStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
defaultText (): string {
|
defaultText (): string {
|
||||||
if (!this.nodeType) {
|
if (!this.nodeType) {
|
||||||
return '';
|
return '';
|
||||||
|
@ -78,13 +90,13 @@ export default mixins(externalHooks, nodeBase, nodeHelpers, workflowHelpers).ext
|
||||||
return content && isString(content.default) ? content.default : '';
|
return content && isString(content.default) ? content.default : '';
|
||||||
},
|
},
|
||||||
isSelected (): boolean {
|
isSelected (): boolean {
|
||||||
return this.$store.getters.getSelectedNodes.find((node: INodeUi) => node.name === this.data.name);
|
return this.uiStore.getSelectedNodes.find((node: INodeUi) => node.name === this.data.name) !== undefined;
|
||||||
},
|
},
|
||||||
nodeType (): INodeTypeDescription | null {
|
nodeType (): INodeTypeDescription | null {
|
||||||
return this.data && this.$store.getters['nodeTypes/getNodeType'](this.data.type, this.data.typeVersion);
|
return this.data && this.nodeTypesStore.getNodeType(this.data.type, this.data.typeVersion);
|
||||||
},
|
},
|
||||||
node (): INodeUi | undefined { // same as this.data but reactive..
|
node (): INodeUi | null { // same as this.data but reactive..
|
||||||
return this.$store.getters.nodesByName[this.name] as INodeUi | undefined;
|
return this.workflowsStore.getNodeByName(this.name);
|
||||||
},
|
},
|
||||||
position (): XYPosition {
|
position (): XYPosition {
|
||||||
if (this.node) {
|
if (this.node) {
|
||||||
|
@ -124,7 +136,7 @@ export default mixins(externalHooks, nodeBase, nodeHelpers, workflowHelpers).ext
|
||||||
return !(this.hideActions || this.isReadOnly || this.workflowRunning || this.isResizing);
|
return !(this.hideActions || this.isReadOnly || this.workflowRunning || this.isResizing);
|
||||||
},
|
},
|
||||||
workflowRunning (): boolean {
|
workflowRunning (): boolean {
|
||||||
return this.$store.getters.isActionActive('workflowRunning');
|
return this.uiStore.isActionActive('workflowRunning');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
|
@ -142,10 +154,10 @@ export default mixins(externalHooks, nodeBase, nodeHelpers, workflowHelpers).ext
|
||||||
},
|
},
|
||||||
onEdit(edit: boolean) {
|
onEdit(edit: boolean) {
|
||||||
if (edit && !this.isActive && this.node) {
|
if (edit && !this.isActive && this.node) {
|
||||||
this.$store.commit('ndv/setActiveNodeName', this.node.name);
|
this.ndvStore.activeNodeName = this.node.name;
|
||||||
}
|
}
|
||||||
else if (this.isActive && !edit) {
|
else if (this.isActive && !edit) {
|
||||||
this.$store.commit('ndv/setActiveNodeName', null);
|
this.ndvStore.activeNodeName = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onMarkdownClick ( link:HTMLAnchorElement, event: Event ) {
|
onMarkdownClick ( link:HTMLAnchorElement, event: Event ) {
|
||||||
|
@ -191,12 +203,13 @@ export default mixins(externalHooks, nodeBase, nodeHelpers, workflowHelpers).ext
|
||||||
width: isNumber(params.width) ? params.width : this.node.parameters.width,
|
width: isNumber(params.width) ? params.width : this.node.parameters.width,
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateInformation = {
|
const updateInformation: IUpdateInformation = {
|
||||||
|
key: this.node.id,
|
||||||
name: this.node.name,
|
name: this.node.name,
|
||||||
value: nodeParameters,
|
value: nodeParameters,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$store.commit('setNodeParameters', updateInformation);
|
this.workflowsStore.setNodeParameters(updateInformation);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setPosition(position: XYPosition) {
|
setPosition(position: XYPosition) {
|
||||||
|
@ -204,14 +217,14 @@ export default mixins(externalHooks, nodeBase, nodeHelpers, workflowHelpers).ext
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateInformation = {
|
const updateInformation: INodeUpdatePropertiesInformation = {
|
||||||
name: this.node.name,
|
name: this.node.name,
|
||||||
properties: {
|
properties: {
|
||||||
position,
|
position: { position },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$store.commit('updateNodeProperties', updateInformation);
|
this.workflowsStore.updateNodeProperties(updateInformation);
|
||||||
},
|
},
|
||||||
touchStart () {
|
touchStart () {
|
||||||
if (this.isTouchDevice === true && this.isMacOs === false && this.isTouchActive === false) {
|
if (this.isTouchDevice === true && this.isMacOs === false && this.isTouchActive === false) {
|
||||||
|
|
|
@ -60,6 +60,8 @@ import { ITag } from "@/Interface";
|
||||||
import { MAX_TAG_NAME_LENGTH, TAGS_MANAGER_MODAL_KEY } from "@/constants";
|
import { MAX_TAG_NAME_LENGTH, TAGS_MANAGER_MODAL_KEY } from "@/constants";
|
||||||
|
|
||||||
import { showMessage } from "@/components/mixins/showMessage";
|
import { showMessage } from "@/components/mixins/showMessage";
|
||||||
|
import { mapStores } from "pinia";
|
||||||
|
import { useUIStore } from "@/stores/ui";
|
||||||
|
|
||||||
const MANAGE_KEY = "__manage";
|
const MANAGE_KEY = "__manage";
|
||||||
const CREATE_KEY = "__create";
|
const CREATE_KEY = "__create";
|
||||||
|
@ -113,6 +115,7 @@ export default mixins(showMessage).extend({
|
||||||
this.$store.dispatch("tags/fetchAll");
|
this.$store.dispatch("tags/fetchAll");
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(useUIStore),
|
||||||
...mapGetters("tags", ["allTags", "isLoading", "hasTags"]),
|
...mapGetters("tags", ["allTags", "isLoading", "hasTags"]),
|
||||||
options(): ITag[] {
|
options(): ITag[] {
|
||||||
return this.allTags
|
return this.allTags
|
||||||
|
@ -156,7 +159,7 @@ export default mixins(showMessage).extend({
|
||||||
);
|
);
|
||||||
if (ops === MANAGE_KEY) {
|
if (ops === MANAGE_KEY) {
|
||||||
this.$data.filter = "";
|
this.$data.filter = "";
|
||||||
this.$store.dispatch("ui/openModal", TAGS_MANAGER_MODAL_KEY);
|
this.uiStore.openModal(TAGS_MANAGER_MODAL_KEY);
|
||||||
} else if (ops === CREATE_KEY) {
|
} else if (ops === CREATE_KEY) {
|
||||||
this.onCreate();
|
this.onCreate();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -32,6 +32,8 @@ import { ITag, ITagRow } from "@/Interface";
|
||||||
import TagsTableHeader from "@/components/TagsManager/TagsView/TagsTableHeader.vue";
|
import TagsTableHeader from "@/components/TagsManager/TagsView/TagsTableHeader.vue";
|
||||||
import TagsTable from "@/components/TagsManager/TagsView/TagsTable.vue";
|
import TagsTable from "@/components/TagsManager/TagsView/TagsTable.vue";
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
import { mapStores } from "pinia";
|
||||||
|
import { useUsersStore } from "@/stores/users";
|
||||||
|
|
||||||
const matches = (name: string, filter: string) => name.toLowerCase().trim().includes(filter.toLowerCase().trim());
|
const matches = (name: string, filter: string) => name.toLowerCase().trim().includes(filter.toLowerCase().trim());
|
||||||
|
|
||||||
|
@ -51,7 +53,7 @@ export default Vue.extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters('users', ['canUserDeleteTags']),
|
...mapStores(useUsersStore),
|
||||||
isCreateEnabled(): boolean {
|
isCreateEnabled(): boolean {
|
||||||
return (this.$props.tags || []).length === 0 || this.$data.createEnabled;
|
return (this.$props.tags || []).length === 0 || this.$data.createEnabled;
|
||||||
},
|
},
|
||||||
|
@ -69,7 +71,7 @@ export default Vue.extend({
|
||||||
disable: disabled && tag.id !== this.deleteId && tag.id !== this.$data.updateId,
|
disable: disabled && tag.id !== this.deleteId && tag.id !== this.$data.updateId,
|
||||||
update: disabled && tag.id === this.$data.updateId,
|
update: disabled && tag.id === this.$data.updateId,
|
||||||
delete: disabled && tag.id === this.$data.deleteId,
|
delete: disabled && tag.id === this.$data.deleteId,
|
||||||
canDelete: this.canUserDeleteTags,
|
canDelete: this.usersStore.canUserDeleteTags,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return this.isCreateEnabled
|
return this.isCreateEnabled
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
import { useUsersStore } from '@/stores/users';
|
||||||
|
import { ITelemetrySettings } from 'n8n-workflow';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
|
|
||||||
import { mapGetters } from 'vuex';
|
|
||||||
import { externalHooks } from './mixins/externalHooks';
|
import { externalHooks } from './mixins/externalHooks';
|
||||||
|
|
||||||
export default mixins(externalHooks).extend({
|
export default mixins(externalHooks).extend({
|
||||||
|
@ -17,12 +19,20 @@ export default mixins(externalHooks).extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters('settings', ['telemetry']),
|
...mapStores(
|
||||||
...mapGetters('users', ['currentUserId']),
|
useRootStore,
|
||||||
...mapGetters(['instanceId']),
|
useSettingsStore,
|
||||||
|
useUsersStore,
|
||||||
|
),
|
||||||
|
currentUserId(): string {
|
||||||
|
return this.usersStore.currentUserId || '';
|
||||||
|
},
|
||||||
isTelemetryEnabledOnRoute(): boolean {
|
isTelemetryEnabledOnRoute(): boolean {
|
||||||
return this.$route.meta && this.$route.meta.telemetry ? !this.$route.meta.telemetry.disabled: true;
|
return this.$route.meta && this.$route.meta.telemetry ? !this.$route.meta.telemetry.disabled: true;
|
||||||
},
|
},
|
||||||
|
telemetry(): ITelemetrySettings {
|
||||||
|
return this.settingsStore.telemetry;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.init();
|
this.init();
|
||||||
|
@ -40,15 +50,15 @@ export default mixins(externalHooks).extend({
|
||||||
this.$telemetry.init(
|
this.$telemetry.init(
|
||||||
telemetrySettings,
|
telemetrySettings,
|
||||||
{
|
{
|
||||||
instanceId: this.instanceId,
|
instanceId: this.rootStore.instanceId,
|
||||||
userId: this.currentUserId,
|
userId: this.currentUserId,
|
||||||
store: this.$store,
|
store: this.$store,
|
||||||
versionCli: this.$store.getters['settings/versionCli'],
|
versionCli: this.rootStore.versionCli,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
this.$externalHooks().run('telemetry.currentUserIdChanged', {
|
this.$externalHooks().run('telemetry.currentUserIdChanged', {
|
||||||
instanceId: this.instanceId,
|
instanceId: this.rootStore.instanceId,
|
||||||
userId: this.currentUserId,
|
userId: this.currentUserId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -60,9 +70,9 @@ export default mixins(externalHooks).extend({
|
||||||
this.init();
|
this.init();
|
||||||
},
|
},
|
||||||
currentUserId(userId) {
|
currentUserId(userId) {
|
||||||
this.$telemetry.identify(this.instanceId, userId);
|
this.$telemetry.identify(this.rootStore.instanceId, userId);
|
||||||
this.$externalHooks().run('telemetry.currentUserIdChanged', {
|
this.$externalHooks().run('telemetry.currentUserIdChanged', {
|
||||||
instanceId: this.instanceId,
|
instanceId: this.rootStore.instanceId,
|
||||||
userId,
|
userId,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
</template-details-block>
|
</template-details-block>
|
||||||
|
|
||||||
<template-details-block
|
<template-details-block
|
||||||
v-if="!loading && template.categories.length > 0"
|
v-if="!loading && template?.categories.length > 0"
|
||||||
:title="$locale.baseText('template.details.categories')"
|
:title="$locale.baseText('template.details.categories')"
|
||||||
>
|
>
|
||||||
<n8n-tags :tags="template.categories" @click="redirectToCategory" />
|
<n8n-tags :tags="template.categories" @click="redirectToCategory" />
|
||||||
|
@ -52,6 +52,8 @@ import TemplateDetailsBlock from '@/components/TemplateDetailsBlock.vue';
|
||||||
import NodeIcon from '@/components/NodeIcon.vue';
|
import NodeIcon from '@/components/NodeIcon.vue';
|
||||||
import { abbreviateNumber, filterTemplateNodes } from '@/components/helpers';
|
import { abbreviateNumber, filterTemplateNodes } from '@/components/helpers';
|
||||||
import { ITemplatesNode, ITemplatesWorkflow, ITemplatesWorkflowFull } from '@/Interface';
|
import { ITemplatesNode, ITemplatesWorkflow, ITemplatesWorkflowFull } from '@/Interface';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useTemplatesStore } from '@/stores/templates';
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'TemplateDetails',
|
name: 'TemplateDetails',
|
||||||
props: {
|
props: {
|
||||||
|
@ -69,15 +71,20 @@ export default Vue.extend({
|
||||||
NodeIcon,
|
NodeIcon,
|
||||||
TemplateDetailsBlock,
|
TemplateDetailsBlock,
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useTemplatesStore,
|
||||||
|
),
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
abbreviateNumber,
|
abbreviateNumber,
|
||||||
filterTemplateNodes,
|
filterTemplateNodes,
|
||||||
redirectToCategory(id: string) {
|
redirectToCategory(id: string) {
|
||||||
this.$store.commit('templates/resetSessionId');
|
this.templatesStore.resetSessionId();
|
||||||
this.$router.push(`/templates?categories=${id}`);
|
this.$router.push(`/templates?categories=${id}`);
|
||||||
},
|
},
|
||||||
redirectToSearchPage(node: ITemplatesNode) {
|
redirectToSearchPage(node: ITemplatesNode) {
|
||||||
this.$store.commit('templates/resetSessionId');
|
this.templatesStore.resetSessionId();
|
||||||
this.$router.push(`/templates?search=${node.displayName}`);
|
this.$router.push(`/templates?search=${node.displayName}`);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,6 +9,8 @@ import { format, LocaleFunc, register } from 'timeago.js';
|
||||||
import { convertToHumanReadableDate } from './helpers';
|
import { convertToHumanReadableDate } from './helpers';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { mapGetters } from 'vuex';
|
import { mapGetters } from 'vuex';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
name: 'TimeAgo',
|
name: 'TimeAgo',
|
||||||
|
@ -48,7 +50,12 @@ export default Vue.extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['defaultLocale']),
|
...mapStores(
|
||||||
|
useRootStore,
|
||||||
|
),
|
||||||
|
defaultLocale(): string {
|
||||||
|
return this.rootStore.defaultLocale;
|
||||||
|
},
|
||||||
format(): string {
|
format(): string {
|
||||||
const text = format(this.date, this.defaultLocale);
|
const text = format(this.date, this.defaultLocale);
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,11 @@ import NodeIcon from './NodeIcon.vue';
|
||||||
import { copyPaste } from './mixins/copyPaste';
|
import { copyPaste } from './mixins/copyPaste';
|
||||||
import { showMessage } from '@/components/mixins/showMessage';
|
import { showMessage } from '@/components/mixins/showMessage';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
|
||||||
export default mixins(workflowHelpers, copyPaste, showMessage).extend({
|
export default mixins(workflowHelpers, copyPaste, showMessage).extend({
|
||||||
name: 'TriggerPanel',
|
name: 'TriggerPanel',
|
||||||
|
@ -125,12 +130,18 @@ export default mixins(workflowHelpers, copyPaste, showMessage).extend({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNodeTypesStore,
|
||||||
|
useNDVStore,
|
||||||
|
useUIStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
node(): INodeUi | null {
|
node(): INodeUi | null {
|
||||||
return this.$store.getters.getNodeByName(this.nodeName);
|
return this.workflowsStore.getNodeByName(this.nodeName);
|
||||||
},
|
},
|
||||||
nodeType(): INodeTypeDescription | null {
|
nodeType(): INodeTypeDescription | null {
|
||||||
if (this.node) {
|
if (this.node) {
|
||||||
return this.$store.getters['nodeTypes/getNodeType'](this.node.type, this.node.typeVersion);
|
return this.nodeTypesStore.getNodeType(this.node.type, this.node.typeVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -195,8 +206,8 @@ export default mixins(workflowHelpers, copyPaste, showMessage).extend({
|
||||||
return Boolean(this.nodeType && this.nodeType.polling);
|
return Boolean(this.nodeType && this.nodeType.polling);
|
||||||
},
|
},
|
||||||
isListeningForEvents(): boolean {
|
isListeningForEvents(): boolean {
|
||||||
const waitingOnWebhook = this.$store.getters.executionWaitingForWebhook as boolean;
|
const waitingOnWebhook = this.workflowsStore.executionWaitingForWebhook as boolean;
|
||||||
const executedNode = this.$store.getters.executedNode as string | undefined;
|
const executedNode = this.workflowsStore.executedNode as string | undefined;
|
||||||
return (
|
return (
|
||||||
!!this.node &&
|
!!this.node &&
|
||||||
!this.node.disabled &&
|
!this.node.disabled &&
|
||||||
|
@ -206,15 +217,15 @@ export default mixins(workflowHelpers, copyPaste, showMessage).extend({
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
workflowRunning(): boolean {
|
workflowRunning(): boolean {
|
||||||
return this.$store.getters.isActionActive('workflowRunning');
|
return this.uiStore.isActionActive('workflowRunning');
|
||||||
},
|
},
|
||||||
isActivelyPolling(): boolean {
|
isActivelyPolling(): boolean {
|
||||||
const triggeredNode = this.$store.getters.executedNode;
|
const triggeredNode = this.workflowsStore.executedNode;
|
||||||
|
|
||||||
return this.workflowRunning && this.isPollingNode && this.nodeName === triggeredNode;
|
return this.workflowRunning && this.isPollingNode && this.nodeName === triggeredNode;
|
||||||
},
|
},
|
||||||
isWorkflowActive(): boolean {
|
isWorkflowActive(): boolean {
|
||||||
return this.$store.getters.isActive;
|
return this.workflowsStore.isWorkflowActive;
|
||||||
},
|
},
|
||||||
header(): string {
|
header(): string {
|
||||||
const serviceName = this.nodeType ? getTriggerNodeServiceName(this.nodeType) : '';
|
const serviceName = this.nodeType ? getTriggerNodeServiceName(this.nodeType) : '';
|
||||||
|
@ -369,15 +380,15 @@ export default mixins(workflowHelpers, copyPaste, showMessage).extend({
|
||||||
this.$emit('activate');
|
this.$emit('activate');
|
||||||
} else if (target.dataset.key === 'executions') {
|
} else if (target.dataset.key === 'executions') {
|
||||||
this.$telemetry.track('User clicked ndv link', {
|
this.$telemetry.track('User clicked ndv link', {
|
||||||
workflow_id: this.$store.getters.workflowId,
|
workflow_id: this.workflowsStore.workflowId,
|
||||||
session_id: this.sessionId,
|
session_id: this.sessionId,
|
||||||
pane: 'input',
|
pane: 'input',
|
||||||
type: 'open-executions-log',
|
type: 'open-executions-log',
|
||||||
});
|
});
|
||||||
this.$store.commit('ndv/setActiveNodeName', null);
|
this.ndvStore.activeNodeName = null;
|
||||||
this.$store.dispatch('ui/openModal', EXECUTIONS_MODAL_KEY);
|
this.uiStore.openModal(EXECUTIONS_MODAL_KEY);
|
||||||
} else if (target.dataset.key === 'settings') {
|
} else if (target.dataset.key === 'settings') {
|
||||||
this.$store.dispatch('ui/openModal', WORKFLOW_SETTINGS_MODAL_KEY);
|
this.uiStore.openModal(WORKFLOW_SETTINGS_MODAL_KEY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -64,6 +64,9 @@ import ModalDrawer from './ModalDrawer.vue';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import { workflowHelpers } from '@/components/mixins/workflowHelpers';
|
import { workflowHelpers } from '@/components/mixins/workflowHelpers';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
|
||||||
const DEFAULT_TITLE = `How likely are you to recommend n8n to a friend or colleague?`;
|
const DEFAULT_TITLE = `How likely are you to recommend n8n to a friend or colleague?`;
|
||||||
const GREAT_FEEDBACK_TITLE = `Great to hear! Can we reach out to see how we can make n8n even better for you?`;
|
const GREAT_FEEDBACK_TITLE = `Great to hear! Can we reach out to see how we can make n8n even better for you?`;
|
||||||
|
@ -79,12 +82,16 @@ export default mixins(workflowHelpers).extend({
|
||||||
isActive(isActive) {
|
isActive(isActive) {
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
this.$telemetry.track('User shown value survey', {
|
this.$telemetry.track('User shown value survey', {
|
||||||
instance_id: this.$store.getters.instanceId,
|
instance_id: this.rootStore.instanceId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useRootStore,
|
||||||
|
useSettingsStore,
|
||||||
|
),
|
||||||
getTitle(): string {
|
getTitle(): string {
|
||||||
if (this.form.value !== '') {
|
if (this.form.value !== '') {
|
||||||
if (Number(this.form.value) > 7) {
|
if (Number(this.form.value) > 7) {
|
||||||
|
@ -115,13 +122,13 @@ export default mixins(workflowHelpers).extend({
|
||||||
closeDialog(): void {
|
closeDialog(): void {
|
||||||
if (this.form.value === '') {
|
if (this.form.value === '') {
|
||||||
this.$telemetry.track('User responded value survey score', {
|
this.$telemetry.track('User responded value survey score', {
|
||||||
instance_id: this.$store.getters.instanceId,
|
instance_id: this.rootStore.instanceId,
|
||||||
nps: '',
|
nps: '',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (this.form.value !== '' && this.form.email === '') {
|
if (this.form.value !== '' && this.form.email === '') {
|
||||||
this.$telemetry.track('User responded value survey email', {
|
this.$telemetry.track('User responded value survey email', {
|
||||||
instance_id: this.$store.getters.instanceId,
|
instance_id: this.rootStore.instanceId,
|
||||||
email: '',
|
email: '',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -133,31 +140,25 @@ export default mixins(workflowHelpers).extend({
|
||||||
this.form.value = value;
|
this.form.value = value;
|
||||||
this.showButtons = false;
|
this.showButtons = false;
|
||||||
|
|
||||||
const response: IN8nPromptResponse = await this.$store.dispatch(
|
const response: IN8nPromptResponse | undefined = await this.settingsStore.submitValueSurvey({ value: this.form.value });
|
||||||
'settings/submitValueSurvey',
|
|
||||||
{ value: this.form.value },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.updated) {
|
if (response && response.updated) {
|
||||||
this.$telemetry.track('User responded value survey score', {
|
this.$telemetry.track('User responded value survey score', {
|
||||||
instance_id: this.$store.getters.instanceId,
|
instance_id: this.rootStore.instanceId,
|
||||||
nps: this.form.value,
|
nps: this.form.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async send() {
|
async send() {
|
||||||
if (this.isEmailValid) {
|
if (this.isEmailValid) {
|
||||||
const response: IN8nPromptResponse = await this.$store.dispatch(
|
const response: IN8nPromptResponse | undefined = await this.settingsStore.submitValueSurvey({
|
||||||
'settings/submitValueSurvey',
|
email: this.form.email,
|
||||||
{
|
value: this.form.value,
|
||||||
email: this.form.email,
|
});
|
||||||
value: this.form.value,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.updated) {
|
if (response && response.updated) {
|
||||||
this.$telemetry.track('User responded value survey email', {
|
this.$telemetry.track('User responded value survey email', {
|
||||||
instance_id: this.$store.getters.instanceId,
|
instance_id: this.rootStore.instanceId,
|
||||||
email: this.form.email,
|
email: this.form.email,
|
||||||
});
|
});
|
||||||
this.$showMessage({
|
this.$showMessage({
|
||||||
|
|
|
@ -40,6 +40,10 @@ import {
|
||||||
import { workflowHelpers } from '@/components/mixins/workflowHelpers';
|
import { workflowHelpers } from '@/components/mixins/workflowHelpers';
|
||||||
|
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
|
|
||||||
// Node types that should not be displayed in variable selector
|
// Node types that should not be displayed in variable selector
|
||||||
const SKIPPED_NODE_TYPES = [
|
const SKIPPED_NODE_TYPES = [
|
||||||
|
@ -64,6 +68,11 @@ export default mixins(
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useNDVStore,
|
||||||
|
useRootStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
extendAll (): boolean {
|
extendAll (): boolean {
|
||||||
if (this.variableFilter) {
|
if (this.variableFilter) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -406,7 +415,7 @@ export default mixins(
|
||||||
const runIndex = 0;
|
const runIndex = 0;
|
||||||
const returnData: IVariableSelectorOption[] = [];
|
const returnData: IVariableSelectorOption[] = [];
|
||||||
|
|
||||||
const activeNode: INodeUi | null = this.$store.getters['ndv/activeNode'];
|
const activeNode: INodeUi | null = this.ndvStore.activeNode;
|
||||||
|
|
||||||
if (activeNode === null) {
|
if (activeNode === null) {
|
||||||
return returnData;
|
return returnData;
|
||||||
|
@ -431,7 +440,7 @@ export default mixins(
|
||||||
$resumeWebhookUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
$resumeWebhookUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
|
||||||
};
|
};
|
||||||
|
|
||||||
const dataProxy = new WorkflowDataProxy(workflow, runExecutionData, runIndex, itemIndex, nodeName, connectionInputData, {}, 'manual', this.$store.getters.timezone, additionalKeys);
|
const dataProxy = new WorkflowDataProxy(workflow, runExecutionData, runIndex, itemIndex, nodeName, connectionInputData, {}, 'manual', this.rootStore.timezone, additionalKeys);
|
||||||
const proxy = dataProxy.getDataProxy();
|
const proxy = dataProxy.getDataProxy();
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -486,15 +495,15 @@ export default mixins(
|
||||||
getFilterResults (filterText: string, itemIndex: number): IVariableSelectorOption[] {
|
getFilterResults (filterText: string, itemIndex: number): IVariableSelectorOption[] {
|
||||||
const inputName = 'main';
|
const inputName = 'main';
|
||||||
|
|
||||||
const activeNode: INodeUi | null = this.$store.getters['ndv/activeNode'];
|
const activeNode: INodeUi | null = this.ndvStore.activeNode;
|
||||||
|
|
||||||
if (activeNode === null) {
|
if (activeNode === null) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const executionData = this.$store.getters.getWorkflowExecution as IExecutionResponse | null;
|
const executionData = this.workflowsStore.getWorkflowExecution;
|
||||||
let parentNode = this.workflow.getParentNodes(activeNode.name, inputName, 1);
|
let parentNode = this.workflow.getParentNodes(activeNode.name, inputName, 1);
|
||||||
let runData = this.$store.getters.getWorkflowRunData as IRunData | null;
|
let runData = this.workflowsStore.getWorkflowRunData;
|
||||||
|
|
||||||
if (runData === null) {
|
if (runData === null) {
|
||||||
runData = {};
|
runData = {};
|
||||||
|
@ -543,7 +552,7 @@ export default mixins(
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
parentNode.forEach((parentNodeName) => {
|
parentNode.forEach((parentNodeName) => {
|
||||||
const pinData = this.$store.getters['pinDataByNodeName'](parentNodeName);
|
const pinData = this.workflowsStore.pinDataByNodeName(parentNodeName);
|
||||||
|
|
||||||
if (pinData) {
|
if (pinData) {
|
||||||
const output = this.getNodePinDataOutput(parentNodeName, pinData, filterText, true);
|
const output = this.getNodePinDataOutput(parentNodeName, pinData, filterText, true);
|
||||||
|
@ -677,7 +686,7 @@ export default mixins(
|
||||||
|
|
||||||
if (upstreamNodes.includes(nodeName)) {
|
if (upstreamNodes.includes(nodeName)) {
|
||||||
// If the node is an upstream node add also the output data which can be referenced
|
// If the node is an upstream node add also the output data which can be referenced
|
||||||
const pinData = this.$store.getters['pinDataByNodeName'](nodeName);
|
const pinData = this.workflowsStore.pinDataByNodeName(nodeName);
|
||||||
tempOutputData = pinData
|
tempOutputData = pinData
|
||||||
? this.getNodePinDataOutput(nodeName, pinData, filterText)
|
? this.getNodePinDataOutput(nodeName, pinData, filterText)
|
||||||
: this.getNodeRunDataOutput(nodeName, runData, filterText, itemIndex);
|
: this.getNodeRunDataOutput(nodeName, runData, filterText, itemIndex);
|
||||||
|
|
|
@ -35,10 +35,10 @@
|
||||||
|
|
||||||
import { showMessage } from '@/components/mixins/showMessage';
|
import { showMessage } from '@/components/mixins/showMessage';
|
||||||
import { workflowActivate } from '@/components/mixins/workflowActivate';
|
import { workflowActivate } from '@/components/mixins/workflowActivate';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import { mapGetters } from "vuex";
|
|
||||||
|
|
||||||
import { getActivatableTriggerNodes } from './helpers';
|
import { getActivatableTriggerNodes } from './helpers';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
|
@ -53,14 +53,18 @@ export default mixins(
|
||||||
'workflowId',
|
'workflowId',
|
||||||
],
|
],
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapStores(
|
||||||
dirtyState: "getStateIsDirty",
|
useUIStore,
|
||||||
}),
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
|
getStateIsDirty (): boolean {
|
||||||
|
return this.uiStore.stateIsDirty;
|
||||||
|
},
|
||||||
nodesIssuesExist (): boolean {
|
nodesIssuesExist (): boolean {
|
||||||
return this.$store.getters.nodesIssuesExist;
|
return this.workflowsStore.nodesIssuesExist;
|
||||||
},
|
},
|
||||||
isWorkflowActive (): boolean {
|
isWorkflowActive (): boolean {
|
||||||
const activeWorkflows = this.$store.getters.getActiveWorkflows;
|
const activeWorkflows = this.workflowsStore.activeWorkflows;
|
||||||
return activeWorkflows.includes(this.workflowId);
|
return activeWorkflows.includes(this.workflowId);
|
||||||
},
|
},
|
||||||
couldNotBeStarted (): boolean {
|
couldNotBeStarted (): boolean {
|
||||||
|
@ -73,7 +77,7 @@ export default mixins(
|
||||||
return '#13ce66';
|
return '#13ce66';
|
||||||
},
|
},
|
||||||
isCurrentWorkflow(): boolean {
|
isCurrentWorkflow(): boolean {
|
||||||
return this.$store.getters['workflowId'] === this.workflowId;
|
return this.workflowsStore.workflowId === this.workflowId;
|
||||||
},
|
},
|
||||||
disabled(): boolean {
|
disabled(): boolean {
|
||||||
const isNewWorkflow = !this.workflowId;
|
const isNewWorkflow = !this.workflowId;
|
||||||
|
@ -84,7 +88,7 @@ export default mixins(
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
containsTrigger(): boolean {
|
containsTrigger(): boolean {
|
||||||
const foundTriggers = getActivatableTriggerNodes(this.$store.getters.workflowTriggerNodes);
|
const foundTriggers = getActivatableTriggerNodes(this.workflowsStore.workflowTriggerNodes);
|
||||||
return foundTriggers.length > 0;
|
return foundTriggers.length > 0;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<n8n-text color="text-light" size="small">
|
<n8n-text color="text-light" size="small">
|
||||||
<span v-show="data">{{$locale.baseText('workflows.item.updated')}} <time-ago :date="data.updatedAt" /> | </span>
|
<span v-show="data">{{$locale.baseText('workflows.item.updated')}} <time-ago :date="data.updatedAt" /> | </span>
|
||||||
<span v-show="data" class="mr-2xs">{{$locale.baseText('workflows.item.created')}} {{ formattedCreatedAtDate }} </span>
|
<span v-show="data" class="mr-2xs">{{$locale.baseText('workflows.item.created')}} {{ formattedCreatedAtDate }} </span>
|
||||||
<span v-if="areTagsEnabled && data.tags && data.tags.length > 0" v-show="data">
|
<span v-if="settingsStore.areTagsEnabled && data.tags && data.tags.length > 0" v-show="data">
|
||||||
<n8n-tags
|
<n8n-tags
|
||||||
:tags="data.tags"
|
:tags="data.tags"
|
||||||
:truncateAt="3"
|
:truncateAt="3"
|
||||||
|
@ -62,6 +62,11 @@ import dateformat from "dateformat";
|
||||||
import { restApi } from '@/components/mixins/restApi';
|
import { restApi } from '@/components/mixins/restApi';
|
||||||
import WorkflowActivator from '@/components/WorkflowActivator.vue';
|
import WorkflowActivator from '@/components/WorkflowActivator.vue';
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
import { useUsersStore } from '@/stores/users';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
|
||||||
export const WORKFLOW_LIST_ITEM_ACTIONS = {
|
export const WORKFLOW_LIST_ITEM_ACTIONS = {
|
||||||
OPEN: 'open',
|
OPEN: 'open',
|
||||||
|
@ -103,11 +108,14 @@ export default mixins(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapStores(
|
||||||
|
useSettingsStore,
|
||||||
|
useUIStore,
|
||||||
|
useUsersStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
currentUser (): IUser {
|
currentUser (): IUser {
|
||||||
return this.$store.getters['users/currentUser'];
|
return this.usersStore.currentUser || {} as IUser;
|
||||||
},
|
|
||||||
areTagsEnabled(): boolean {
|
|
||||||
return this.$store.getters['settings/areTagsEnabled'];
|
|
||||||
},
|
},
|
||||||
credentialPermissions(): IPermissions {
|
credentialPermissions(): IPermissions {
|
||||||
return getWorkflowPermissions(this.currentUser, this.data, this.$store);
|
return getWorkflowPermissions(this.currentUser, this.data, this.$store);
|
||||||
|
@ -162,7 +170,7 @@ export default mixins(
|
||||||
if (action === WORKFLOW_LIST_ITEM_ACTIONS.OPEN) {
|
if (action === WORKFLOW_LIST_ITEM_ACTIONS.OPEN) {
|
||||||
await this.onClick();
|
await this.onClick();
|
||||||
} else if (action === WORKFLOW_LIST_ITEM_ACTIONS.DUPLICATE) {
|
} else if (action === WORKFLOW_LIST_ITEM_ACTIONS.DUPLICATE) {
|
||||||
await this.$store.dispatch('ui/openModalWithData', {
|
this.uiStore.openModalWithData({
|
||||||
name: DUPLICATE_MODAL_KEY,
|
name: DUPLICATE_MODAL_KEY,
|
||||||
data: {
|
data: {
|
||||||
id: this.data.id,
|
id: this.data.id,
|
||||||
|
@ -188,7 +196,7 @@ export default mixins(
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.restApi().deleteWorkflow(this.data.id);
|
await this.restApi().deleteWorkflow(this.data.id);
|
||||||
this.$store.commit('deleteWorkflow', this.data.id);
|
this.workflowsStore.deleteWorkflow(this.data.id);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$showError(
|
this.$showError(
|
||||||
error,
|
error,
|
||||||
|
|
|
@ -220,10 +220,12 @@ import { restApi } from '@/components/mixins/restApi';
|
||||||
import { genericHelpers } from '@/components/mixins/genericHelpers';
|
import { genericHelpers } from '@/components/mixins/genericHelpers';
|
||||||
import { showMessage } from '@/components/mixins/showMessage';
|
import { showMessage } from '@/components/mixins/showMessage';
|
||||||
import {
|
import {
|
||||||
|
IN8nUISettings,
|
||||||
ITimeoutHMS,
|
ITimeoutHMS,
|
||||||
IWorkflowDataUpdate,
|
IWorkflowDataUpdate,
|
||||||
IWorkflowSettings,
|
IWorkflowSettings,
|
||||||
IWorkflowShortResponse,
|
IWorkflowShortResponse,
|
||||||
|
WorkflowCallerPolicyDefaultOption,
|
||||||
} from '@/Interface';
|
} from '@/Interface';
|
||||||
import Modal from './Modal.vue';
|
import Modal from './Modal.vue';
|
||||||
import { PLACEHOLDER_EMPTY_WORKFLOW_ID, WORKFLOW_SETTINGS_MODAL_KEY } from '../constants';
|
import { PLACEHOLDER_EMPTY_WORKFLOW_ID, WORKFLOW_SETTINGS_MODAL_KEY } from '../constants';
|
||||||
|
@ -232,6 +234,10 @@ import mixins from 'vue-typed-mixins';
|
||||||
|
|
||||||
import { mapGetters } from "vuex";
|
import { mapGetters } from "vuex";
|
||||||
import { deepCopy } from "n8n-workflow";
|
import { deepCopy } from "n8n-workflow";
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
import { useRootStore } from '@/stores/n8nRootStore';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(
|
||||||
externalHooks,
|
externalHooks,
|
||||||
|
@ -274,8 +280,8 @@ export default mixins(
|
||||||
timezones: [] as Array<{ key: string, value: string }>,
|
timezones: [] as Array<{ key: string, value: string }>,
|
||||||
workflowSettings: {} as IWorkflowSettings,
|
workflowSettings: {} as IWorkflowSettings,
|
||||||
workflows: [] as IWorkflowShortResponse[],
|
workflows: [] as IWorkflowShortResponse[],
|
||||||
executionTimeout: this.$store.getters.executionTimeout,
|
executionTimeout: 0,
|
||||||
maxExecutionTimeout: this.$store.getters.maxExecutionTimeout,
|
maxExecutionTimeout: 0,
|
||||||
timeoutHMS: { hours: 0, minutes: 0, seconds: 0 } as ITimeoutHMS,
|
timeoutHMS: { hours: 0, minutes: 0, seconds: 0 } as ITimeoutHMS,
|
||||||
modalBus: new Vue(),
|
modalBus: new Vue(),
|
||||||
WORKFLOW_SETTINGS_MODAL_KEY,
|
WORKFLOW_SETTINGS_MODAL_KEY,
|
||||||
|
@ -283,13 +289,25 @@ export default mixins(
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['workflowName', 'workflowId']),
|
...mapStores(
|
||||||
|
useRootStore,
|
||||||
|
useSettingsStore,
|
||||||
|
useWorkflowsStore,
|
||||||
|
),
|
||||||
|
workflowName(): string {
|
||||||
|
return this.workflowsStore.workflowName;
|
||||||
|
},
|
||||||
|
workflowId(): string {
|
||||||
|
return this.workflowsStore.workflowId;
|
||||||
|
},
|
||||||
isWorkflowSharingEnabled(): boolean {
|
isWorkflowSharingEnabled(): boolean {
|
||||||
return this.$store.getters['settings/isWorkflowSharingEnabled'];
|
return this.settingsStore.isWorkflowSharingEnabled;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
async mounted () {
|
async mounted () {
|
||||||
|
this.executionTimeout = this.rootStore.executionTimeout;
|
||||||
|
this.maxExecutionTimeout = this.rootStore.maxExecutionTimeout;
|
||||||
|
|
||||||
if (!this.workflowId || this.workflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID) {
|
if (!this.workflowId || this.workflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID) {
|
||||||
this.$showMessage({
|
this.$showMessage({
|
||||||
title: 'No workflow active',
|
title: 'No workflow active',
|
||||||
|
@ -301,11 +319,11 @@ export default mixins(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.defaultValues.saveDataErrorExecution = this.$store.getters.saveDataErrorExecution;
|
this.defaultValues.saveDataErrorExecution = this.settingsStore.saveDataErrorExecution;
|
||||||
this.defaultValues.saveDataSuccessExecution = this.$store.getters.saveDataSuccessExecution;
|
this.defaultValues.saveDataSuccessExecution = this.settingsStore.saveDataSuccessExecution;
|
||||||
this.defaultValues.saveManualExecutions = this.$store.getters.saveManualExecutions;
|
this.defaultValues.saveManualExecutions = this.settingsStore.saveManualExecutions;
|
||||||
this.defaultValues.timezone = this.$store.getters.timezone;
|
this.defaultValues.timezone = this.rootStore.timezone;
|
||||||
this.defaultValues.workflowCallerPolicy = this.$store.getters['settings/workflowCallerPolicyDefaultOption'];
|
this.defaultValues.workflowCallerPolicy = this.settingsStore.workflowCallerPolicyDefaultOption;
|
||||||
|
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
@ -323,7 +341,7 @@ export default mixins(
|
||||||
this.$showError(error, 'Problem loading settings', 'The following error occurred loading the data:');
|
this.$showError(error, 'Problem loading settings', 'The following error occurred loading the data:');
|
||||||
}
|
}
|
||||||
|
|
||||||
const workflowSettings = deepCopy(this.$store.getters.workflowSettings);
|
const workflowSettings = deepCopy(this.workflowsStore.workflowSettings) as IWorkflowSettings;
|
||||||
|
|
||||||
if (workflowSettings.timezone === undefined) {
|
if (workflowSettings.timezone === undefined) {
|
||||||
workflowSettings.timezone = 'DEFAULT';
|
workflowSettings.timezone = 'DEFAULT';
|
||||||
|
@ -338,16 +356,16 @@ export default mixins(
|
||||||
workflowSettings.saveExecutionProgress = 'DEFAULT';
|
workflowSettings.saveExecutionProgress = 'DEFAULT';
|
||||||
}
|
}
|
||||||
if (workflowSettings.saveManualExecutions === undefined) {
|
if (workflowSettings.saveManualExecutions === undefined) {
|
||||||
workflowSettings.saveManualExecutions = 'DEFAULT';
|
workflowSettings.saveManualExecutions = this.defaultValues.saveManualExecutions;
|
||||||
}
|
}
|
||||||
if (workflowSettings.callerPolicy === undefined) {
|
if (workflowSettings.callerPolicy === undefined) {
|
||||||
workflowSettings.callerPolicy = this.defaultValues.workflowCallerPolicy;
|
workflowSettings.callerPolicy = this.defaultValues.workflowCallerPolicy as WorkflowCallerPolicyDefaultOption;
|
||||||
}
|
}
|
||||||
if (workflowSettings.executionTimeout === undefined) {
|
if (workflowSettings.executionTimeout === undefined) {
|
||||||
workflowSettings.executionTimeout = this.$store.getters.executionTimeout;
|
workflowSettings.executionTimeout = this.rootStore.executionTimeout;
|
||||||
}
|
}
|
||||||
if (workflowSettings.maxExecutionTimeout === undefined) {
|
if (workflowSettings.maxExecutionTimeout === undefined) {
|
||||||
workflowSettings.maxExecutionTimeout = this.$store.getters.maxExecutionTimeout;
|
workflowSettings.maxExecutionTimeout = this.rootStore.maxExecutionTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.set(this, 'workflowSettings', workflowSettings);
|
Vue.set(this, 'workflowSettings', workflowSettings);
|
||||||
|
@ -355,7 +373,7 @@ export default mixins(
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
|
|
||||||
this.$externalHooks().run('workflowSettings.dialogVisibleChanged', { dialogVisible: true });
|
this.$externalHooks().run('workflowSettings.dialogVisibleChanged', { dialogVisible: true });
|
||||||
this.$telemetry.track('User opened workflow settings', { workflow_id: this.$store.getters.workflowId });
|
this.$telemetry.track('User opened workflow settings', { workflow_id: this.workflowsStore.workflowId });
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onCallerIdsInput(str: string) {
|
onCallerIdsInput(str: string) {
|
||||||
|
@ -589,11 +607,11 @@ export default mixins(
|
||||||
delete data.settings!.maxExecutionTimeout;
|
delete data.settings!.maxExecutionTimeout;
|
||||||
|
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
data.hash = this.$store.getters.workflowHash;
|
data.hash = this.workflowsStore.workflowHash;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const workflow = await this.restApi().updateWorkflow(this.$route.params.name, data);
|
const workflow = await this.restApi().updateWorkflow(this.$route.params.name, data);
|
||||||
this.$store.commit('setWorkflowHash', workflow.hash);
|
this.workflowsStore.setWorkflowHash(workflow.hash || '');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$showError(
|
this.$showError(
|
||||||
error,
|
error,
|
||||||
|
@ -611,9 +629,9 @@ export default mixins(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldSettings = deepCopy(this.$store.getters.workflowSettings);
|
const oldSettings = deepCopy(this.workflowsStore.workflowSettings);
|
||||||
|
|
||||||
this.$store.commit('setWorkflowSettings', localWorkflowSettings);
|
this.workflowsStore.setWorkflowSettings(localWorkflowSettings);
|
||||||
|
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
|
|
||||||
|
@ -625,7 +643,7 @@ export default mixins(
|
||||||
this.closeDialog();
|
this.closeDialog();
|
||||||
|
|
||||||
this.$externalHooks().run('workflowSettings.saveSettings', { oldSettings });
|
this.$externalHooks().run('workflowSettings.saveSettings', { oldSettings });
|
||||||
this.$telemetry.track('User updated workflow settings', { workflow_id: this.$store.getters.workflowId });
|
this.$telemetry.track('User updated workflow settings', { workflow_id: this.workflowsStore.workflowId });
|
||||||
},
|
},
|
||||||
toggleTimeout() {
|
toggleTimeout() {
|
||||||
this.workflowSettings.executionTimeout = this.workflowSettings.executionTimeout === -1 ? 0 : -1;
|
this.workflowSettings.executionTimeout = this.workflowSettings.executionTimeout === -1 ? 0 : -1;
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
/>
|
/>
|
||||||
<n8n-user-select
|
<n8n-user-select
|
||||||
:users="ownedByUsers"
|
:users="ownedByUsers"
|
||||||
:currentUserId="currentUser.id"
|
:currentUserId="usersStore.currentUser.id"
|
||||||
:value="value.ownedBy"
|
:value="value.ownedBy"
|
||||||
size="small"
|
size="small"
|
||||||
@input="setKeyValue('ownedBy', $event)"
|
@input="setKeyValue('ownedBy', $event)"
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
/>
|
/>
|
||||||
<n8n-user-select
|
<n8n-user-select
|
||||||
:users="sharedWithUsers"
|
:users="sharedWithUsers"
|
||||||
:currentUserId="currentUser.id"
|
:currentUserId="usersStore.currentUser.id"
|
||||||
:value="value.sharedWith"
|
:value="value.sharedWith"
|
||||||
size="small"
|
size="small"
|
||||||
@input="setKeyValue('sharedWith', $event)"
|
@input="setKeyValue('sharedWith', $event)"
|
||||||
|
@ -66,8 +66,9 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue, { PropType } from 'vue';
|
import Vue, { PropType } from 'vue';
|
||||||
import {EnterpriseEditionFeature} from "@/constants";
|
import {EnterpriseEditionFeature} from "@/constants";
|
||||||
import {IResource} from "@/components/layouts/ResourcesListLayout.vue";
|
|
||||||
import {IUser} from "@/Interface";
|
import {IUser} from "@/Interface";
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
|
import { useUsersStore } from '@/stores/users';
|
||||||
|
|
||||||
export type IResourceFiltersType = Record<string, boolean | string | string[]>;
|
export type IResourceFiltersType = Record<string, boolean | string | string[]>;
|
||||||
|
|
||||||
|
@ -95,17 +96,12 @@ export default Vue.extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
currentUser(): IUser {
|
...mapStores(useUsersStore),
|
||||||
return this.$store.getters['users/currentUser'];
|
|
||||||
},
|
|
||||||
allUsers(): IUser[] {
|
|
||||||
return this.$store.getters['users/allUsers'];
|
|
||||||
},
|
|
||||||
ownedByUsers(): IUser[] {
|
ownedByUsers(): IUser[] {
|
||||||
return this.allUsers.map((user) => user.id === this.value.sharedWith ? { ...user, disabled: true } : user);
|
return this.usersStore.allUsers.map((user) => user.id === this.value.sharedWith ? { ...user, disabled: true } : user);
|
||||||
},
|
},
|
||||||
sharedWithUsers(): IUser[] {
|
sharedWithUsers(): IUser[] {
|
||||||
return this.allUsers.map((user) => user.id === this.value.ownedBy ? { ...user, disabled: true } : user);
|
return this.usersStore.allUsers.map((user) => user.id === this.value.ownedBy ? { ...user, disabled: true } : user);
|
||||||
},
|
},
|
||||||
filtersLength(): number {
|
filtersLength(): number {
|
||||||
let length = 0;
|
let length = 0;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="[$style.wrapper, !sidebarMenuCollapsed && $style.expandedSidebar]">
|
<div :class="[$style.wrapper, !this.uiStore.sidebarMenuCollapsed && $style.expandedSidebar]">
|
||||||
<div :class="$style.container">
|
<div :class="$style.container">
|
||||||
<aside :class="$style.aside" v-if="$slots.aside">
|
<aside :class="$style.aside" v-if="$slots.aside">
|
||||||
<slot name="aside" />
|
<slot name="aside" />
|
||||||
|
@ -12,6 +12,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { useUIStore } from '@/stores/ui';
|
||||||
|
import { mapStores } from 'pinia';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
|
@ -22,9 +24,7 @@ export default Vue.extend({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
sidebarMenuCollapsed(): boolean {
|
...mapStores(useUIStore),
|
||||||
return this.$store.getters['ui/sidebarMenuCollapsed'];
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue