credentialTypeDescription.name);
@@ -125,7 +139,7 @@ export default mixins(
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) {
return activeNodeType.credentials;
}
@@ -220,8 +234,8 @@ export default mixins(
onCredentialSelected (credentialType: string, credentialId: string | null | undefined) {
if (credentialId === this.NEW_CREDENTIALS_TEXT) {
this.listenForNewCredentials(credentialType);
- this.$store.dispatch('ui/openNewCredential', { type: credentialType });
- this.$telemetry.track('User opened Credential modal', { credential_type: credentialType, source: 'node', new_credential: true, workflow_id: this.$store.getters.workflowId });
+ this.uiStore.openNewCredential(credentialType);
+ this.$telemetry.track('User opened Credential modal', { credential_type: credentialType, source: 'node', new_credential: true, workflow_id: this.workflowsStore.workflowId });
return;
}
@@ -231,7 +245,7 @@ export default mixins(
credential_type: credentialType,
node_type: this.node.type,
...(this.hasProxyAuth(this.node) ? { is_service_specific: true } : {}),
- workflow_id: this.$store.getters.workflowId,
+ workflow_id: this.workflowsStore.workflowId,
credential_id: credentialId,
},
);
@@ -244,7 +258,7 @@ export default mixins(
// 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))) {
// update all nodes in the workflow with the same old/invalid credentials
- this.$store.commit('replaceInvalidWorkflowCredentials', {
+ this.workflowsStore.replaceInvalidWorkflowCredentials({
credentials: selected,
invalid: oldCredentials,
type: credentialType,
@@ -316,9 +330,9 @@ export default mixins(
editCredential(credentialType: string): void {
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);
},
diff --git a/packages/editor-ui/src/components/NodeDetailsView.vue b/packages/editor-ui/src/components/NodeDetailsView.vue
index 2d22d5978c2eb..340fa06cd5d0c 100644
--- a/packages/editor-ui/src/components/NodeDetailsView.vue
+++ b/packages/editor-ui/src/components/NodeDetailsView.vue
@@ -141,6 +141,11 @@ import {
import { workflowActivate } from './mixins/workflowActivate';
import { pinData } from "@/components/mixins/pinData";
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(
externalHooks,
@@ -182,8 +187,7 @@ export default mixins(
};
},
mounted() {
- this.$store.commit('ndv/setNDVSessionId');
-
+ this.ndvStore.setNDVSessionId;
dataPinningEventBus.$on('data-pinning-discovery', ({ isTooltipVisible }: { isTooltipVisible: boolean }) => {
this.pinDataDiscoveryTooltipVisible = isTooltipVisible;
});
@@ -192,12 +196,17 @@ export default mixins(
dataPinningEventBus.$off('data-pinning-discovery');
},
computed: {
- ...mapGetters(['executionWaitingForWebhook']),
+ ...mapStores(
+ useNodeTypesStore,
+ useNDVStore,
+ useUIStore,
+ useWorkflowsStore,
+ ),
sessionId(): string {
- return this.$store.getters['ndv/ndvSessionId'];
+ return this.ndvStore.sessionId;
},
workflowRunning(): boolean {
- return this.$store.getters.isActionActive('workflowRunning');
+ return this.uiStore.isActionActive('workflowRunning');
},
showTriggerWaitingWarning(): boolean {
return (
@@ -205,25 +214,25 @@ export default mixins(
!!this.activeNodeType &&
!this.activeNodeType.group.includes('trigger') &&
this.workflowRunning &&
- this.executionWaitingForWebhook
+ this.workflowsStore.executionWaitingForWebhook
);
},
activeNode(): INodeUi | null {
- return this.$store.getters['ndv/activeNode'];
+ return this.ndvStore.activeNode;
},
inputNodeName(): string | undefined {
return this.selectedInput || this.parentNode;
},
inputNode(): INodeUi | null {
if (this.inputNodeName) {
- return this.$store.getters.getNodeByName(this.inputNodeName);
+ return this.workflowsStore.getNodeByName(this.inputNodeName);
}
return null;
},
activeNodeType(): INodeTypeDescription | null {
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;
},
@@ -257,11 +266,11 @@ export default mixins(
},
isActiveStickyNode(): boolean {
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 {
- return this.$store.getters.getWorkflowExecution;
+ return this.workflowsStore.getWorkflowExecution;
},
workflowRunData(): IRunData | null {
if (this.workflowExecution === null) {
@@ -340,13 +349,13 @@ export default mixins(
return `${BASE_NODE_SURVEY_URL}${this.activeNodeType.name}`;
},
outputPanelEditMode(): { enabled: boolean; value: string; } {
- return this.$store.getters['ndv/outputPanelEditMode'];
+ return this.ndvStore.outputPanelEditMode;
},
isWorkflowRunning(): boolean {
- return this.$store.getters.isActionActive('workflowRunning');
+ return this.uiStore.isActionActive('workflowRunning');
},
isExecutionWaitingForWebhook(): boolean {
- return this.$store.getters.executionWaitingForWebhook;
+ return this.workflowsStore.executionWaitingForWebhook;
},
blockUi(): boolean {
return this.isWorkflowRunning || this.isExecutionWaitingForWebhook;
@@ -364,7 +373,7 @@ export default mixins(
this.avgInputRowHeight = 0;
setTimeout(() => {
- this.$store.commit('ndv/setNDVSessionId');
+ this.ndvStore.setNDVSessionId;
}, 0);
this.$externalHooks().run('dataDisplay.nodeTypeChanged', {
nodeSubtitle: this.getNodeSubtitle(node, this.activeNodeType, this.getCurrentWorkflow()),
@@ -374,24 +383,24 @@ export default mixins(
setTimeout(() => {
if (this.activeNode) {
- const outogingConnections = this.$store.getters.outgoingConnectionsByNodeName(
+ const outgoingConnections = this.workflowsStore.outgoingConnectionsByNodeName(
this.activeNode.name,
) as INodeConnections;
this.$telemetry.track('User opened node modal', {
node_type: this.activeNodeType ? this.activeNodeType.name : '',
- workflow_id: this.$store.getters.workflowId,
+ workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId,
parameters_pane_position: this.mainPanelPosition,
input_first_connector_runs: this.maxInputRun,
output_first_connector_runs: this.maxOutputRun,
selected_view_inputs: this.isTriggerNode
? 'trigger'
- : this.$store.getters['ndv/inputPanelDisplayMode'],
- selected_view_outputs: this.$store.getters['ndv/outputPanelDisplayMode'],
+ : this.ndvStore.inputPanelDisplayMode,
+ selected_view_outputs: this.ndvStore.outputPanelDisplayMode,
input_connectors: this.parentNodes.length,
output_connectors:
- outogingConnections && outogingConnections.main && outogingConnections.main.length,
+ outgoingConnections && outgoingConnections.main && outgoingConnections.main.length,
input_displayed_run_index: this.inputRun,
output_displayed_run_index: this.outputRun,
data_pinning_tooltip_presented: this.pinDataDiscoveryTooltipVisible,
@@ -413,12 +422,12 @@ export default mixins(
},
inputNodeName(nodeName: string | undefined) {
setTimeout(() => {
- this.$store.commit('ndv/setInputNodeName', nodeName);
+ this.ndvStore.setInputNodeName(nodeName);
}, 0);
},
inputRun() {
setTimeout(() => {
- this.$store.commit('ndv/setInputRunIndex', this.inputRun);
+ this.ndvStore.setInputRunIndex(this.inputRun);
}, 0);
},
},
@@ -428,7 +437,7 @@ export default mixins(
return;
}
if (e === null) {
- this.$store.commit('ndv/setHoveringItem', null);
+ this.ndvStore.setHoveringItem(null);
return;
}
@@ -438,11 +447,11 @@ export default mixins(
outputIndex: e.outputIndex,
itemIndex: e.itemIndex,
};
- this.$store.commit('ndv/setHoveringItem', item);
+ this.ndvStore.setHoveringItem(item);
},
onOutputItemHover(e: {itemIndex: number, outputIndex: number} | null) {
if (e === null || !this.activeNode) {
- this.$store.commit('ndv/setHoveringItem', null);
+ this.ndvStore.setHoveringItem(null);
return;
}
@@ -452,7 +461,7 @@ export default mixins(
outputIndex: e.outputIndex,
itemIndex: e.itemIndex,
};
- this.$store.commit('ndv/setHoveringItem', item);
+ this.ndvStore.setHoveringItem(item);
},
onInputTableMounted(e: { avgRowHeight: number }) {
this.avgInputRowHeight = e.avgRowHeight;
@@ -461,7 +470,7 @@ export default mixins(
this.avgOutputRowHeight = e.avgRowHeight;
},
onWorkflowActivate() {
- this.$store.commit('ndv/setActiveNodeName', null);
+ this.ndvStore.activeNodeName = null;
setTimeout(() => {
this.activateCurrentWorkflow('ndv');
}, 1000);
@@ -471,7 +480,7 @@ export default mixins(
if (this.activeNode) {
this.$telemetry.track('User clicked ndv link', {
node_type: this.activeNode.type,
- workflow_id: this.$store.getters.workflowId,
+ workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId,
pane: 'main',
type: 'i-wish-this-node-would',
@@ -493,7 +502,7 @@ export default mixins(
end_position: e.position,
node_type: this.activeNodeType ? this.activeNodeType.name : '',
session_id: this.sessionId,
- workflow_id: this.$store.getters.workflowId,
+ workflow_id: this.workflowsStore.workflowId,
});
this.mainPanelPosition = e.position;
},
@@ -567,21 +576,23 @@ export default mixins(
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.$telemetry.track('User closed node modal', {
node_type: this.activeNodeType ? this.activeNodeType.name : '',
session_id: this.sessionId,
- workflow_id: this.$store.getters.workflowId,
+ workflow_id: this.workflowsStore.workflowId,
});
this.triggerWaitingWarningEnabled = false;
- this.$store.commit('ndv/setActiveNodeName', null);
- this.$store.commit('ndv/resetNDVSessionId');
+ this.ndvStore.activeNodeName = null;
+ this.ndvStore.resetNDVSessionId();
},
onRunOutputIndexChange(run: number) {
this.runOutputIndex = run;
@@ -610,7 +621,7 @@ export default mixins(
this.$telemetry.track('User changed ndv input dropdown', {
node_type: this.activeNode ? this.activeNode.type : '',
session_id: this.sessionId,
- workflow_id: this.$store.getters.workflowId,
+ workflow_id: this.workflowsStore.workflowId,
selection_value: index,
input_node_type: this.inputNode ? this.inputNode.type : '',
});
diff --git a/packages/editor-ui/src/components/NodeExecuteButton.vue b/packages/editor-ui/src/components/NodeExecuteButton.vue
index ec07a63bb9520..962a7d6b57ce1 100644
--- a/packages/editor-ui/src/components/NodeExecuteButton.vue
+++ b/packages/editor-ui/src/components/NodeExecuteButton.vue
@@ -23,6 +23,10 @@ import mixins from 'vue-typed-mixins';
import { workflowRun } from './mixins/workflowRun';
import { pinData } from './mixins/pinData';
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(
workflowRun,
@@ -54,25 +58,30 @@ export default mixins(
},
},
computed: {
- node (): INodeUi {
- return this.$store.getters.getNodeByName(this.nodeName);
+ ...mapStores(
+ useNodeTypesStore,
+ useNDVStore,
+ useWorkflowsStore,
+ ),
+ node (): INodeUi | null {
+ return this.workflowsStore.getNodeByName(this.nodeName);
},
nodeType (): INodeTypeDescription | null {
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;
},
nodeRunning (): boolean {
- const triggeredNode = this.$store.getters.executedNode;
- const executingNode = this.$store.getters.executingNode;
+ const triggeredNode = this.workflowsStore.executedNode;
+ const executingNode = this.workflowsStore.executingNode;
return this.workflowRunning && (executingNode === this.node.name || triggeredNode === this.node.name);
},
workflowRunning (): boolean {
- return this.$store.getters.isActionActive('workflowRunning');
+ return this.uiStore.isActionActive('workflowRunning');
},
isTriggerNode (): boolean {
- return this.$store.getters['nodeTypes/isTriggerNode'](this.node.type);
+ return this.nodeTypesStore.isTriggerNode(this.node.type);
},
isManualTriggerNode (): boolean {
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);
},
isListeningForEvents(): boolean {
- const waitingOnWebhook = this.$store.getters.executionWaitingForWebhook as boolean;
- const executedNode = this.$store.getters.executedNode as string | undefined;
+ const waitingOnWebhook = this.workflowsStore.executionWaitingForWebhook;
+ const executedNode = this.workflowsStore.executedNode;
return (
this.node &&
@@ -114,7 +123,8 @@ export default mixins(
}
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');
}
@@ -154,7 +164,7 @@ export default mixins(
methods: {
async stopWaitingForWebhook () {
try {
- await this.restApi().removeTestWebhook(this.$store.getters.workflowId);
+ await this.restApi().removeTestWebhook(this.workflowsStore.workflowId);
} catch (error) {
this.$showError(
error,
@@ -182,14 +192,14 @@ export default mixins(
if (shouldUnpinAndExecute) {
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) {
const telemetryPayload = {
node_type: this.nodeType ? this.nodeType.name : null,
- workflow_id: this.$store.getters.workflowId,
+ workflow_id: this.workflowsStore.workflowId,
source: this.telemetrySource,
};
this.$telemetry.track('User clicked execute node button', telemetryPayload);
diff --git a/packages/editor-ui/src/components/NodeIcon.vue b/packages/editor-ui/src/components/NodeIcon.vue
index 6e9c4dfcbd95f..b162c06162c27 100644
--- a/packages/editor-ui/src/components/NodeIcon.vue
+++ b/packages/editor-ui/src/components/NodeIcon.vue
@@ -15,7 +15,9 @@
diff --git a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue
index d0535690e9d88..d9c3b5cbbb347 100644
--- a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue
+++ b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue
@@ -172,6 +172,12 @@ import { workflowHelpers } from '../mixins/workflowHelpers';
import { nodeHelpers } from '../mixins/nodeHelpers';
import { getAppNameFromNodeName } from '../helpers';
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 {
results: INodeListSearchItems[];
@@ -248,7 +254,6 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
},
data() {
return {
- mainPanelMutationSubscription: () => {},
showResourceDropdown: false,
searchFilter: '',
cachedResponses: {} as { [key: string]: IResourceLocatorQuery },
@@ -257,13 +262,20 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
};
},
computed: {
+ ...mapStores(
+ useNodeTypesStore,
+ useNDVStore,
+ useRootStore,
+ useUIStore,
+ useWorkflowsStore,
+ ),
appName(): string {
if (!this.node) {
return '';
}
- const nodeType = this.$store.getters['nodeTypes/getNodeType'](this.node.type);
- return getAppNameFromNodeName(nodeType.displayName);
+ const nodeType = this.nodeTypesStore.getNodeType(this.node.type);
+ return getAppNameFromNodeName(nodeType?.displayName || '');
},
selectedMode(): string {
if (typeof this.value !== 'object') { // legacy mode
@@ -280,7 +292,7 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
return this.selectedMode === 'list';
},
hasCredential(): boolean {
- const node = this.$store.getters['ndv/activeNode'] as INodeUi | null;
+ const node = this.ndvStore.activeNode;
if (!node) {
return false;
}
@@ -425,24 +437,21 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
mounted() {
this.$on('refreshList', this.refreshList);
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(() => {
this.setWidth();
}, 0);
},
beforeDestroy() {
- // Unsubscribe
- this.mainPanelMutationSubscription();
window.removeEventListener('resize', this.setWidth);
},
methods: {
setWidth() {
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) {
if (this.selectedMode === 'list' && entity) {
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];
},
openCredential(): void {
- const node = this.$store.getters['ndv/activeNode'] as INodeUi | null;
+ const node = this.ndvStore.activeNode;
if (!node || !node.credentials) {
return;
}
@@ -489,7 +498,7 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
return;
}
const id = node.credentials[credentialKey].id;
- this.$store.dispatch('ui/openExistingCredential', { id });
+ this.uiStore.openExistingCredential(id);
},
findModeByName(name: string): INodePropertyMode | null {
if (this.parameter.modes) {
@@ -533,8 +542,8 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
},
trackEvent(event: string, params?: {[key: string]: string}): void {
this.$telemetry.track(event, {
- instance_id: this.$store.getters.instanceId,
- workflow_id: this.$store.getters.workflowId,
+ instance_id: this.rootStore.instanceId,
+ workflow_id: this.workflowsStore.workflowId,
node_type: this.node && this.node.type,
resource: this.node && this.node.parameters && this.node.parameters.resource,
operation: this.node && this.node.parameters && this.node.parameters.operation,
@@ -618,10 +627,7 @@ export default mixins(debounceHelper, workflowHelpers, nodeHelpers).extend({
...(paginationToken ? { paginationToken } : {}),
};
- const response: INodeListSearchResult = await this.$store.dispatch(
- 'nodeTypes/getResourceLocatorResults',
- requestParams,
- );
+ const response = await this.nodeTypesStore.getResourceLocatorResults(requestParams);
this.setResponse(paramsKey, {
results: (cachedResponse ? cachedResponse.results : []).concat(response.results),
diff --git a/packages/editor-ui/src/components/RunData.vue b/packages/editor-ui/src/components/RunData.vue
index 6c21b8e0bce45..0fce00bc88a97 100644
--- a/packages/editor-ui/src/components/RunData.vue
+++ b/packages/editor-ui/src/components/RunData.vue
@@ -145,7 +145,7 @@
:value="editMode.value"
:options="{ scrollBeyondLastLine: false }"
type="json"
- @input="$store.commit('ndv/setOutputPanelEditModeValue', $event)"
+ @input="ndvStore.setOutputPanelEditModeValue($event)"
/>
@@ -344,6 +344,7 @@ import {
IBinaryDisplayData,
IExecutionResponse,
INodeUi,
+ INodeUpdatePropertiesInformation,
IRunDataDisplayMode,
ITab,
} from '@/Interface';
@@ -373,6 +374,10 @@ import { clearJsonKey, executionDataToJson, stringSizeInBytes } from './helpers'
import RunDataTable from './RunDataTable.vue';
import RunDataJson from '@/components/RunDataJson.vue';
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 = {
origin: 'editIconButton' | 'insertTestDataLink',
@@ -475,8 +480,8 @@ export default mixins(
this.showPinDataDiscoveryTooltip(this.jsonData);
}
}
- this.$store.commit('ndv/setNDVBranchIndex', {
- pane: this.paneType,
+ this.ndvStore.setNDVBranchIndex({
+ pane: this.paneType as "input" | "output",
branchIndex: this.currentOutputIndex,
});
},
@@ -486,8 +491,13 @@ export default mixins(
this.eventBus.$off('data-unpinning', this.onDataUnpinning);
},
computed: {
- activeNode(): INodeUi {
- return this.$store.getters['ndv/activeNode'];
+ ...mapStores(
+ useNodeTypesStore,
+ useNDVStore,
+ useWorkflowsStore,
+ ),
+ activeNode(): INodeUi | null {
+ return this.ndvStore.activeNode;
},
dataPinningDocsUrl(): string {
return DATA_PINNING_DOCS_URL;
@@ -496,19 +506,19 @@ export default mixins(
return DATA_EDITING_DOCS_URL;
},
displayMode(): IRunDataDisplayMode {
- return this.$store.getters['ndv/getPanelDisplayMode'](this.paneType);
+ return this.ndvStore.getPanelDisplayMode(this.paneType as "input" | "output");
},
node(): INodeUi | null {
return (this.nodeUi as INodeUi | null) || null;
},
nodeType (): INodeTypeDescription | null {
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;
},
isTriggerNode (): boolean {
- return this.$store.getters['nodeTypes/isTriggerNode'](this.node.type);
+ return this.nodeTypesStore.isTriggerNode(this.node.type);
},
canPinData (): boolean {
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));
},
subworkflowExecutionError(): Error | null {
- return this.$store.getters.subworkflowExecutionError;
+ return this.workflowsStore.subWorkflowExecutionError;
},
hasSubworkflowExecutionError(): boolean {
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);
},
workflowExecution (): IExecutionResponse | null {
- return this.$store.getters.getWorkflowExecution;
+ return this.workflowsStore.getWorkflowExecution;
},
workflowRunData (): IRunData | null {
if (this.workflowExecution === null) {
@@ -680,7 +690,7 @@ export default mixins(
editMode(): { enabled: boolean; value: string; } {
return this.isPaneTypeInput
? { enabled: false, value: '' }
- : this.$store.getters['ndv/outputPanelEditMode'];
+ : this.ndvStore.outputPanelEditMode;
},
isPaneTypeInput(): boolean {
return this.paneType === 'input';
@@ -700,9 +710,9 @@ export default mixins(
},
onClickDataPinningDocsLink() {
this.$telemetry.track('User clicked ndv link', {
- workflow_id: this.$store.getters.workflowId,
+ workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId,
- node_type: this.activeNode.type,
+ node_type: this.activeNode?.type,
pane: 'output',
type: 'data-pinning-docs',
});
@@ -742,11 +752,11 @@ export default mixins(
? inputData
: TEST_PIN_DATA;
- this.$store.commit('ndv/setOutputPanelEditModeEnabled', true);
- this.$store.commit('ndv/setOutputPanelEditModeValue', JSON.stringify(data, null, 2));
+ this.ndvStore.setOutputPanelEditModeEnabled(true);
+ this.ndvStore.setOutputPanelEditModeValue(JSON.stringify(data, null, 2));
this.$telemetry.track('User opened ndv edit state', {
- node_type: this.activeNode.type,
+ node_type: this.activeNode?.type,
click_type: origin === 'editIconButton' ? 'button' : 'link',
session_id: this.sessionId,
run_index: this.runIndex,
@@ -756,8 +766,8 @@ export default mixins(
});
},
onClickCancelEdit() {
- this.$store.commit('ndv/setOutputPanelEditModeEnabled', false);
- this.$store.commit('ndv/setOutputPanelEditModeValue', '');
+ this.ndvStore.setOutputPanelEditModeEnabled(false);
+ this.ndvStore.setOutputPanelEditModeValue('');
this.onExitEditMode({ type: 'cancel' });
},
onClickSaveEdit() {
@@ -775,8 +785,8 @@ export default mixins(
return;
}
- this.$store.commit('ndv/setOutputPanelEditModeEnabled', false);
- this.$store.commit('pinData', { node: this.node, data: clearJsonKey(value) });
+ this.ndvStore.setOutputPanelEditModeEnabled(false);
+ this.workflowsStore.pinData({ node: this.node, data: clearJsonKey(value) as INodeExecutionData[] });
this.onDataPinningSuccess({ source: 'save-edit' });
@@ -784,7 +794,7 @@ export default mixins(
},
onExitEditMode({ type }: { type: 'save' | 'cancel' }) {
this.$telemetry.track('User closed ndv edit state', {
- node_type: this.activeNode.type,
+ node_type: this.activeNode?.type,
session_id: this.sessionId,
run_index: this.runIndex,
view: this.displayMode,
@@ -795,7 +805,7 @@ export default mixins(
{ source }: { source: 'banner-link' | 'pin-icon-click' | 'unpin-and-execute-modal' },
) {
this.$telemetry.track('User unpinned ndv data', {
- node_type: this.activeNode.type,
+ node_type: this.activeNode?.type,
session_id: this.sessionId,
run_index: this.runIndex,
source,
@@ -849,11 +859,11 @@ export default mixins(
if (this.hasPinData) {
this.onDataUnpinning({ source });
- this.$store.commit('unpinData', { node: this.node });
+ this.workflowsStore.unpinData({ node: this.node });
return;
}
- const data = executionDataToJson(this.rawInputData);
+ const data = executionDataToJson(this.rawInputData) as INodeExecutionData[];
if (!this.isValidPinDataSize(data)) {
this.onDataPinningError({ errorType: 'data-too-large', source: 'pin-icon-click' });
@@ -862,7 +872,7 @@ export default mixins(
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) {
this.$showToast({
@@ -898,7 +908,7 @@ export default mixins(
this.showData = true;
this.$telemetry.track('User clicked ndv button', {
node_type: this.activeNode.type,
- workflow_id: this.$store.getters.workflowId,
+ workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId,
pane: this.paneType,
type: 'showTooMuchData',
@@ -912,8 +922,8 @@ export default mixins(
},
onCurrentPageChange() {
this.$telemetry.track('User changed ndv page', {
- node_type: this.activeNode.type,
- workflow_id: this.$store.getters.workflowId,
+ node_type: this.activeNode?.type,
+ workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId,
pane: this.paneType,
page_selected: this.currentPage,
@@ -929,8 +939,8 @@ export default mixins(
}
this.$telemetry.track('User changed ndv page size', {
- node_type: this.activeNode.type,
- workflow_id: this.$store.getters.workflowId,
+ node_type: this.activeNode?.type,
+ workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId,
pane: this.paneType,
page_selected: this.currentPage,
@@ -940,7 +950,7 @@ export default mixins(
},
onDisplayModeChange(displayMode: IRunDataDisplayMode) {
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;
if (dataContainer) {
@@ -958,7 +968,7 @@ export default mixins(
previous_view: previous,
new_view: displayMode,
node_type: this.activeNode.type,
- workflow_id: this.$store.getters.workflowId,
+ workflow_id: this.workflowsStore.workflowId,
session_id: this.sessionId,
pane: this.paneType,
});
@@ -1012,10 +1022,10 @@ export default mixins(
this.refreshDataSize();
this.closeBinaryDataDisplay();
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') {
- this.$store.commit('ndv/setPanelDisplayMode', {pane: this.paneType, mode: 'table'});
+ this.ndvStore.setPanelDisplayMode({pane: this.paneType as "input" | "output", mode: 'table'});
}
},
closeBinaryDataDisplay () {
@@ -1023,7 +1033,7 @@ export default mixins(
this.binaryDataDisplayData = null;
},
clearExecutionData () {
- this.$store.commit('setWorkflowExecutionData', null);
+ this.workflowsStore.setWorkflowExecutionData(null);
this.updateNodesExecutionIssues();
},
isDownloadable (index: number, key: string): boolean {
@@ -1093,15 +1103,15 @@ export default mixins(
name: this.node.name,
properties: {
disabled: !this.node.disabled,
- },
- };
+ } as IDataObject,
+ } as INodeUpdatePropertiesInformation;
- this.$store.commit('updateNodeProperties', updateInformation);
+ this.workflowsStore.updateNodeProperties(updateInformation);
}
},
goToErroredNode() {
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:{
handler(data: INodeExecutionData[]) {
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,
@@ -1135,8 +1145,8 @@ export default mixins(
}
},
currentOutputIndex(branchIndex: number) {
- this.$store.commit('ndv/setNDVBranchIndex', {
- pane: this.paneType,
+ this.ndvStore.setNDVBranchIndex({
+ pane: this.paneType as "input" | "output",
branchIndex,
});
},
diff --git a/packages/editor-ui/src/components/RunDataJson.vue b/packages/editor-ui/src/components/RunDataJson.vue
index 3472f9206cb0b..bc9b8b41bc806 100644
--- a/packages/editor-ui/src/components/RunDataJson.vue
+++ b/packages/editor-ui/src/components/RunDataJson.vue
@@ -66,6 +66,8 @@ import { convertPath, executionDataToJson, isString, isStringNumber } from "@/co
import { INodeUi } from "@/Interface";
import { shorten } from './helpers';
import { externalHooks } from "@/components/mixins/externalHooks";
+import { mapStores } from "pinia";
+import { useNDVStore } from "@/stores/ndv";
const runDataJsonActions = () => import('@/components/RunDataJsonActions.vue');
@@ -137,6 +139,9 @@ export default mixins(externalHooks).extend({
}
},
computed: {
+ ...mapStores(
+ useNDVStore,
+ ),
jsonData(): IDataObject[] {
return executionDataToJson(this.inputData as INodeExecutionData[]);
},
@@ -165,13 +170,13 @@ export default mixins(externalHooks).extend({
this.draggingPath = el.dataset.path;
}
- this.$store.commit('ndv/resetMappingTelemetry');
+ this.ndvStore.resetMappingTelemetry();
},
onDragEnd(el: HTMLElement) {
this.draggingPath = null;
setTimeout(() => {
- const mappingTelemetry = this.$store.getters['ndv/mappingTelemetry'];
+ const mappingTelemetry = this.ndvStore.mappingTelemetry;
const telemetryPayload = {
src_node_type: this.node.type,
src_field_name: el.dataset.name || '',
diff --git a/packages/editor-ui/src/components/RunDataJsonActions.vue b/packages/editor-ui/src/components/RunDataJsonActions.vue
index 1cd7ca27d9c98..883ed23217b49 100644
--- a/packages/editor-ui/src/components/RunDataJsonActions.vue
+++ b/packages/editor-ui/src/components/RunDataJsonActions.vue
@@ -35,6 +35,9 @@ import { pinData } from "@/components/mixins/pinData";
import { nodeHelpers } from "@/components/mixins/nodeHelpers";
import { genericHelpers } from "@/components/mixins/genericHelpers";
import { clearJsonKey, convertPath, executionDataToJson } from "@/components/helpers";
+import { mapStores } from "pinia";
+import { useWorkflowsStore } from "@/stores/workflows";
+import { useNDVStore } from "@/stores/ndv";
type JsonPathData = {
path: string;
@@ -83,8 +86,12 @@ export default mixins(
},
},
computed: {
- activeNode(): INodeUi {
- return this.$store.getters['ndv/activeNode'];
+ ...mapStores(
+ useNDVStore,
+ useWorkflowsStore,
+ ),
+ activeNode(): INodeUi | null {
+ return this.ndvStore.activeNode;
},
normalisedJsonPath(): string {
const isNotSelected = this.selectedJsonPath === nonExistingJsonPath;
@@ -189,7 +196,7 @@ export default mixins(
run_index: this.runIndex,
view: 'json',
copy_type: copyType,
- workflow_id: this.$store.getters.workflowId,
+ workflow_id: this.workflowsStore.workflowId,
pane: this.paneType,
in_execution_log: this.isReadOnly,
});
diff --git a/packages/editor-ui/src/components/RunDataTable.vue b/packages/editor-ui/src/components/RunDataTable.vue
index fa9546f08f51f..e7be285f8c5f1 100644
--- a/packages/editor-ui/src/components/RunDataTable.vue
+++ b/packages/editor-ui/src/components/RunDataTable.vue
@@ -152,14 +152,18 @@
diff --git a/packages/editor-ui/src/components/layouts/ResourcesListLayout.vue b/packages/editor-ui/src/components/layouts/ResourcesListLayout.vue
index 4742e00996250..5f34048c2b720 100644
--- a/packages/editor-ui/src/components/layouts/ResourcesListLayout.vue
+++ b/packages/editor-ui/src/components/layouts/ResourcesListLayout.vue
@@ -32,8 +32,8 @@
{
- if (this.isOwnerSubview && this.$store.getters['settings/isEnterpriseFeatureEnabled'](EnterpriseEditionFeature.Sharing)) {
- return !!(resource.ownedBy && resource.ownedBy.id === this.currentUser.id);
+ if (this.isOwnerSubview && this.settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.Sharing)) {
+ return !!(resource.ownedBy && resource.ownedBy.id === this.usersStore.currentUser?.id);
}
return true;
@@ -268,7 +269,7 @@ export default mixins(
},
resourcesNotOwned(): IResource[] {
return (this.resources as IResource[]).filter((resource) => {
- return resource.ownedBy && resource.ownedBy.id !== this.currentUser.id;
+ return resource.ownedBy && resource.ownedBy.id !== this.usersStore.currentUser?.id;
});
},
},
diff --git a/packages/editor-ui/src/components/mixins/executionsHelpers.ts b/packages/editor-ui/src/components/mixins/executionsHelpers.ts
index 7591fda98bc4c..70aaa5e5a05a4 100644
--- a/packages/editor-ui/src/components/mixins/executionsHelpers.ts
+++ b/packages/editor-ui/src/components/mixins/executionsHelpers.ts
@@ -1,5 +1,7 @@
import { IExecutionsSummary } from "@/Interface";
+import { useWorkflowsStore } from "@/stores/workflows";
import dateFormat from "dateformat";
+import { mapStores } from "pinia";
import mixins from "vue-typed-mixins";
import { genericHelpers } from "./genericHelpers";
@@ -12,20 +14,23 @@ export interface IExecutionUIData {
export const executionHelpers = mixins(genericHelpers).extend({
computed: {
+ ...mapStores(
+ useWorkflowsStore,
+ ),
executionId(): string {
return this.$route.params.executionId;
},
workflowName (): string {
- return this.$store.getters.workflowName;
+ return this.workflowsStore.workflowName;
},
currentWorkflow (): string {
- return this.$route.params.name || this.$store.getters.workflowId;
+ return this.$route.params.name || this.workflowsStore.workflowId;
},
executions(): IExecutionsSummary[] {
- return this.$store.getters['workflows/currentWorkflowExecutions'];
+ return this.workflowsStore.currentWorkflowExecutions;
},
- activeExecution(): IExecutionsSummary {
- return this.$store.getters['workflows/getActiveWorkflowExecution'];
+ activeExecution(): IExecutionsSummary | null {
+ return this.workflowsStore.activeWorkflowExecution;
},
},
methods: {
diff --git a/packages/editor-ui/src/components/mixins/mouseSelect.ts b/packages/editor-ui/src/components/mixins/mouseSelect.ts
index 0ee605b9c2eee..fdea3ff59f4db 100644
--- a/packages/editor-ui/src/components/mixins/mouseSelect.ts
+++ b/packages/editor-ui/src/components/mixins/mouseSelect.ts
@@ -5,6 +5,9 @@ import mixins from 'vue-typed-mixins';
import { deviceSupportHelpers } from '@/components/mixins/deviceSupportHelpers';
import { getMousePosition, getRelativePosition, HEADER_HEIGHT, INNER_SIDEBAR_WIDTH, SIDEBAR_WIDTH, SIDEBAR_WIDTH_EXPANDED } from '@/views/canvasHelpers';
import { VIEWS } from '@/constants';
+import { mapStores } from 'pinia';
+import { useUIStore } from '@/stores/ui';
+import { useWorkflowsStore } from '@/stores/workflows';
export const mouseSelect = mixins(
deviceSupportHelpers,
@@ -19,6 +22,10 @@ export const mouseSelect = mixins(
this.createSelectBox();
},
computed: {
+ ...mapStores(
+ useUIStore,
+ useWorkflowsStore,
+ ),
isDemo (): boolean {
return this.$route.name === VIEWS.DEMO;
},
@@ -49,10 +56,10 @@ export const mouseSelect = mixins(
},
getMousePositionWithinNodeView (event: MouseEvent | TouchEvent): XYPosition {
const [x, y] = getMousePosition(event);
+ const sidebarOffset = this.isDemo ? 0 : this.uiStore.sidebarMenuCollapsed ? SIDEBAR_WIDTH : SIDEBAR_WIDTH_EXPANDED;
const headerOffset = this.isDemo ? 0 : HEADER_HEIGHT;
- const sidebarOffset = this.isDemo ? 0 : this.$store.getters['ui/sidebarMenuCollapsed'] ? SIDEBAR_WIDTH : SIDEBAR_WIDTH_EXPANDED;
// @ts-ignore
- return getRelativePosition(x - sidebarOffset, y - headerOffset, this.nodeViewScale, this.$store.getters.getNodeViewOffsetPosition);
+ return getRelativePosition(x - sidebarOffset, y - headerOffset, this.nodeViewScale, this.uiStore.nodeViewOffsetPosition);
},
showSelectBox (event: MouseEvent) {
const [x, y] = this.getMousePositionWithinNodeView(event);
@@ -105,7 +112,7 @@ export const mouseSelect = mixins(
const selectionBox = this.getSelectionBox(event);
// Go through all nodes and check if they are selected
- this.$store.getters.allNodes.forEach((node: INodeUi) => {
+ this.workflowsStore.allNodes.forEach((node: INodeUi) => {
// TODO: Currently always uses the top left corner for checking. Should probably use the center instead
if (node.position[0] < selectionBox.x || node.position[0] > (selectionBox.x + selectionBox.width)) {
return;
@@ -125,7 +132,7 @@ export const mouseSelect = mixins(
return;
}
- if (this.$store.getters.isActionActive('dragActive')) {
+ if (this.uiStore.isActionActive('dragActive')) {
// If a node does currently get dragged we do not activate the selection
return;
}
@@ -161,7 +168,7 @@ export const mouseSelect = mixins(
});
if (selectedNodes.length === 1) {
- this.$store.commit('setLastSelectedNode', selectedNodes[0].name);
+ this.uiStore.lastSelectedNode = selectedNodes[0].name;
}
this.hideSelectBox();
@@ -178,21 +185,21 @@ export const mouseSelect = mixins(
this.updateSelectBox(e);
},
nodeDeselected (node: INodeUi) {
- this.$store.commit('removeNodeFromSelection', node);
+ this.uiStore.removeNodeFromSelection(node);
// @ts-ignore
this.instance.removeFromDragSelection(node.id);
},
nodeSelected (node: INodeUi) {
- this.$store.commit('addSelectedNode', node);
+ this.uiStore.addSelectedNode(node);
// @ts-ignore
this.instance.addToDragSelection(node.id);
},
deselectAllNodes () {
// @ts-ignore
this.instance.clearDragSelection();
- this.$store.commit('resetSelectedNodes');
- this.$store.commit('setLastSelectedNode', null);
- this.$store.commit('setLastSelectedNodeOutputIndex', null);
+ this.uiStore.resetSelectedNodes();
+ this.uiStore.lastSelectedNode = null;
+ this.uiStore.lastSelectedNodeOutputIndex = null;
// @ts-ignore
this.lastSelectedConnection = null;
// @ts-ignore
diff --git a/packages/editor-ui/src/components/mixins/moveNodeWorkflow.ts b/packages/editor-ui/src/components/mixins/moveNodeWorkflow.ts
index dacf5884fdf84..0884215d94049 100644
--- a/packages/editor-ui/src/components/mixins/moveNodeWorkflow.ts
+++ b/packages/editor-ui/src/components/mixins/moveNodeWorkflow.ts
@@ -3,6 +3,8 @@ import mixins from 'vue-typed-mixins';
import normalizeWheel from 'normalize-wheel';
import { deviceSupportHelpers } from '@/components/mixins/deviceSupportHelpers';
import { getMousePosition } from '@/views/canvasHelpers';
+import { mapStores } from 'pinia';
+import { useUIStore } from '@/stores/ui';
export const moveNodeWorkflow = mixins(
deviceSupportHelpers,
@@ -12,16 +14,18 @@ export const moveNodeWorkflow = mixins(
moveLastPosition: [0, 0],
};
},
-
+ computed: {
+ ...mapStores(useUIStore),
+ },
methods: {
moveWorkflow (e: MouseEvent) {
- const offsetPosition = this.$store.getters.getNodeViewOffsetPosition;
+ const offsetPosition = this.uiStore.nodeViewOffsetPosition;
const [x, y] = getMousePosition(e);
const nodeViewOffsetPositionX = offsetPosition[0] + (x - this.moveLastPosition[0]);
const nodeViewOffsetPositionY = offsetPosition[1] + (y - this.moveLastPosition[1]);
- this.$store.commit('setNodeViewOffsetPosition', {newOffset: [nodeViewOffsetPositionX, nodeViewOffsetPositionY]});
+ this.uiStore.nodeViewOffsetPosition = [nodeViewOffsetPositionX, nodeViewOffsetPositionY];
// Update the last position
this.moveLastPosition[0] = x;
@@ -34,12 +38,12 @@ export const moveNodeWorkflow = mixins(
return;
}
- if (this.$store.getters.isActionActive('dragActive')) {
+ if (this.uiStore.isActionActive('dragActive')) {
// If a node does currently get dragged we do not activate the selection
return;
}
- this.$store.commit('setNodeViewMoveInProgress', true);
+ this.uiStore.nodeViewMoveInProgress = true;
const [x, y] = getMousePosition(e);
@@ -50,7 +54,7 @@ export const moveNodeWorkflow = mixins(
this.$el.addEventListener('mousemove', this.mouseMoveNodeWorkflow);
},
mouseUpMoveWorkflow (e: MouseEvent) {
- if (this.$store.getters.isNodeViewMoveInProgress === false) {
+ if (this.uiStore.nodeViewMoveInProgress === false) {
// If it is not active return directly.
// Else normal node dragging will not work.
return;
@@ -59,7 +63,7 @@ export const moveNodeWorkflow = mixins(
// @ts-ignore
this.$el.removeEventListener('mousemove', this.mouseMoveNodeWorkflow);
- this.$store.commit('setNodeViewMoveInProgress', false);
+ this.uiStore.nodeViewMoveInProgress = false;
// Nothing else to do. Simply leave the node view at the current offset
},
@@ -69,7 +73,7 @@ export const moveNodeWorkflow = mixins(
return;
}
- if (this.$store.getters.isActionActive('dragActive')) {
+ if (this.uiStore.isActionActive('dragActive')) {
return;
}
@@ -86,10 +90,10 @@ export const moveNodeWorkflow = mixins(
},
wheelMoveWorkflow (e: WheelEvent) {
const normalized = normalizeWheel(e);
- const offsetPosition = this.$store.getters.getNodeViewOffsetPosition;
+ const offsetPosition = this.uiStore.nodeViewOffsetPosition;
const nodeViewOffsetPositionX = offsetPosition[0] - (e.shiftKey ? normalized.pixelY : normalized.pixelX);
const nodeViewOffsetPositionY = offsetPosition[1] - (e.shiftKey ? normalized.pixelX : normalized.pixelY);
- this.$store.commit('setNodeViewOffsetPosition', {newOffset: [nodeViewOffsetPositionX, nodeViewOffsetPositionY]});
+ this.uiStore.nodeViewOffsetPosition = [nodeViewOffsetPositionX, nodeViewOffsetPositionY];
},
},
});
diff --git a/packages/editor-ui/src/components/mixins/newVersions.ts b/packages/editor-ui/src/components/mixins/newVersions.ts
index dbb721a6320e5..5df15a668a184 100644
--- a/packages/editor-ui/src/components/mixins/newVersions.ts
+++ b/packages/editor-ui/src/components/mixins/newVersions.ts
@@ -4,10 +4,15 @@ import {
IVersion,
} from '../../Interface';
import { VERSIONS_MODAL_KEY } from '@/constants';
+import { mapStores } from 'pinia';
+import { useUIStore } from '@/stores/ui';
export const newVersions = mixins(
showMessage,
).extend({
+ computed: {
+ ...mapStores(useUIStore),
+ },
methods: {
async checkForNewVersions() {
const enabled = this.$store.getters['versions/areNotificationsEnabled'];
@@ -31,7 +36,7 @@ export const newVersions = mixins(
title: 'Critical update available',
message,
onClick: () => {
- this.$store.dispatch('ui/openModal', VERSIONS_MODAL_KEY);
+ this.uiStore.openModal(VERSIONS_MODAL_KEY);
},
closeOnClick: true,
customClass: 'clickable',
diff --git a/packages/editor-ui/src/components/mixins/nodeBase.ts b/packages/editor-ui/src/components/mixins/nodeBase.ts
index df114d3a2e31d..3d3a6d0eeef50 100644
--- a/packages/editor-ui/src/components/mixins/nodeBase.ts
+++ b/packages/editor-ui/src/components/mixins/nodeBase.ts
@@ -9,7 +9,10 @@ import {
INodeTypeDescription,
} from 'n8n-workflow';
import { getStyleTokenValue } from '../helpers';
-import { readonly } from 'vue';
+import { mapStores } from 'pinia';
+import { useUIStore } from '@/stores/ui';
+import { useWorkflowsStore } from "@/stores/workflows";
+import { useNodeTypesStore } from "@/stores/nodeTypes";
export const nodeBase = mixins(
deviceSupportHelpers,
@@ -26,11 +29,16 @@ export const nodeBase = mixins(
}
},
computed: {
- data (): INodeUi {
- return this.$store.getters.getNodeByName(this.name);
+ ...mapStores(
+ useNodeTypesStore,
+ useUIStore,
+ useWorkflowsStore,
+ ),
+ data (): INodeUi | null {
+ return this.workflowsStore.getNodeByName(this.name);
},
nodeId (): string {
- return this.data.id;
+ return this.data?.id || '';
},
},
props: {
@@ -242,7 +250,7 @@ export const nodeBase = mixins(
// @ts-ignore
this.dragging = true;
- const isSelected = this.$store.getters.isNodeSelected(this.data.name);
+ const isSelected = this.uiStore.isNodeSelected(this.data.name);
const nodeName = this.data.name;
if (this.data.type === STICKY_NODE_TYPE && !isSelected) {
setTimeout(() => {
@@ -255,17 +263,17 @@ export const nodeBase = mixins(
// undefined. So check if the currently dragged node is selected and if not clear
// the drag-selection.
this.instance.clearDragSelection();
- this.$store.commit('resetSelectedNodes');
+ this.uiStore.resetSelectedNodes();
}
- this.$store.commit('addActiveAction', 'dragActive');
+ this.uiStore.addActiveAction('dragActive');
return true;
},
stop: (params: { e: MouseEvent }) => {
// @ts-ignore
this.dragging = false;
- if (this.$store.getters.isActionActive('dragActive')) {
- const moveNodes = this.$store.getters.getSelectedNodes.slice();
+ if (this.uiStore.isActionActive('dragActive')) {
+ const moveNodes = this.uiStore.getSelectedNodes.slice();
const selectedNodeNames = moveNodes.map((node: INodeUi) => node.name);
if (!selectedNodeNames.includes(this.data.name)) {
// If the current node is not in selected add it to the nodes which
@@ -297,7 +305,7 @@ export const nodeBase = mixins(
},
};
- this.$store.commit('updateNodeProperties', updateInformation);
+ this.workflowsStore.updateNodeProperties(updateInformation);
});
this.$emit('moved', node);
@@ -307,10 +315,10 @@ export const nodeBase = mixins(
});
},
__addNode (node: INodeUi) {
- let nodeTypeData = this.$store.getters['nodeTypes/getNodeType'](node.type, node.typeVersion) as INodeTypeDescription | null;
+ let nodeTypeData = this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
if (!nodeTypeData) {
// If node type is not know use by default the base.noOp data to display it
- nodeTypeData = this.$store.getters['nodeTypes/getNodeType'](NO_OP_NODE_TYPE) as INodeTypeDescription;
+ nodeTypeData = this.nodeTypesStore.getNodeType(NO_OP_NODE_TYPE);
}
this.__addInputEndpoints(node, nodeTypeData);
@@ -319,8 +327,8 @@ export const nodeBase = mixins(
},
touchEnd(e: MouseEvent) {
if (this.isTouchDevice) {
- if (this.$store.getters.isActionActive('dragActive')) {
- this.$store.commit('removeActiveAction', 'dragActive');
+ if (this.uiStore.isActionActive('dragActive')) {
+ this.uiStore.removeActiveAction('dragActive');
}
}
},
@@ -334,14 +342,14 @@ export const nodeBase = mixins(
}
if (!this.isTouchDevice) {
- if (this.$store.getters.isActionActive('dragActive')) {
- this.$store.commit('removeActiveAction', 'dragActive');
+ if (this.uiStore.isActionActive('dragActive')) {
+ this.uiStore.removeActiveAction('dragActive');
} else {
if (!this.isCtrlKeyPressed(e)) {
this.$emit('deselectAllNodes');
}
- if (this.$store.getters.isNodeSelected(this.data.name)) {
+ if (this.uiStore.isNodeSelected(this.data.name)) {
this.$emit('deselectNode', this.name);
} else {
this.$emit('nodeSelected', this.name);
diff --git a/packages/editor-ui/src/components/mixins/nodeHelpers.ts b/packages/editor-ui/src/components/mixins/nodeHelpers.ts
index 110691c99418d..2b38f25076acd 100644
--- a/packages/editor-ui/src/components/mixins/nodeHelpers.ts
+++ b/packages/editor-ui/src/components/mixins/nodeHelpers.ts
@@ -22,11 +22,14 @@ import {
ITaskDataConnections,
INode,
INodePropertyOptions,
+ IDataObject,
} from 'n8n-workflow';
import {
ICredentialsResponse,
INodeUi,
+ INodeUpdatePropertiesInformation,
+ IUser,
} from '@/Interface';
import { restApi } from '@/components/mixins/restApi';
@@ -37,12 +40,22 @@ import mixins from 'vue-typed-mixins';
import { mapGetters } from 'vuex';
import { isObjectLiteral } from '@/utils';
import {getCredentialPermissions} from "@/permissions";
+import { mapStores } from 'pinia';
+import { useSettingsStore } from '@/stores/settings';
+import { useUsersStore } from '@/stores/users';
+import { useWorkflowsStore } from '@/stores/workflows';
+import { useNodeTypesStore } from '@/stores/nodeTypes';
export const nodeHelpers = mixins(
restApi,
)
.extend({
computed: {
+ ...mapStores(
+ useNodeTypesStore,
+ useSettingsStore,
+ useWorkflowsStore,
+ ),
...mapGetters('credentials', [ 'getCredentialTypeByName', 'getCredentialsByType' ]),
},
methods: {
@@ -76,7 +89,7 @@ export const nodeHelpers = mixins(
// Returns all the issues of the node
getNodeIssues (nodeType: INodeTypeDescription | null, node: INodeUi, ignoreIssues?: string[]): INodeIssues | null {
- const pinDataNodeNames = Object.keys(this.$store.getters.pinData || {});
+ const pinDataNodeNames = Object.keys(this.workflowsStore.getPinData || {});
let nodeIssues: INodeIssues | null = null;
ignoreIssues = ignoreIssues || [];
@@ -125,7 +138,7 @@ export const nodeHelpers = mixins(
// Set the status on all the nodes which produced an error so that it can be
// displayed in the node-view
hasNodeExecutionIssues (node: INodeUi): boolean {
- const workflowResultData: IRunData = this.$store.getters.getWorkflowRunData;
+ const workflowResultData: IRunData = this.workflowsStore.getWorkflowRunData;
if (workflowResultData === null || !workflowResultData.hasOwnProperty(node.name)) {
return false;
@@ -159,10 +172,10 @@ export const nodeHelpers = mixins(
// Updates the execution issues.
updateNodesExecutionIssues () {
- const nodes = this.$store.getters.allNodes;
+ const nodes = this.workflowsStore.allNodes;
for (const node of nodes) {
- this.$store.commit('setNodeIssue', {
+ this.workflowsStore.setNodeIssue({
node: node.name,
type: 'execution',
value: this.hasNodeExecutionIssues(node) ? true : null,
@@ -179,17 +192,17 @@ export const nodeHelpers = mixins(
newIssues = fullNodeIssues.credentials!;
}
- this.$store.commit('setNodeIssue', {
+ this.workflowsStore.setNodeIssue({
node: node.name,
type: 'credentials',
value: newIssues,
- } as INodeIssueData);
+ });
},
// Updates the parameter-issues of the node
updateNodeParameterIssues(node: INodeUi, nodeType?: INodeTypeDescription): void {
if (nodeType === undefined) {
- nodeType = this.$store.getters['nodeTypes/getNodeType'](node.type, node.typeVersion);
+ nodeType = this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
}
if (nodeType === null) {
@@ -205,11 +218,11 @@ export const nodeHelpers = mixins(
newIssues = fullNodeIssues.parameters!;
}
- this.$store.commit('setNodeIssue', {
+ this.workflowsStore.setNodeIssue({
node: node.name,
type: 'parameters',
value: newIssues,
- } as INodeIssueData);
+ });
},
// Returns all the credential-issues of the node
@@ -220,7 +233,7 @@ export const nodeHelpers = mixins(
}
if (!nodeType) {
- nodeType = this.$store.getters['nodeTypes/getNodeType'](node.type, node.typeVersion);
+ nodeType = this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
}
if (!nodeType?.credentials) {
@@ -313,9 +326,11 @@ export const nodeHelpers = mixins(
};
}
+ const usersStore = useUsersStore();
+ const currentUser = usersStore.currentUser || {} as IUser;
userCredentials = this.$store.getters['credentials/getCredentialsByType'](credentialTypeDescription.name)
.filter((credential: ICredentialsResponse) => {
- const permissions = getCredentialPermissions(this.$store.getters['users/currentUser'], credential, this.$store);
+ const permissions = getCredentialPermissions(currentUser, credential, this.$store);
return permissions.use;
});
@@ -337,7 +352,7 @@ export const nodeHelpers = mixins(
}
if (nameMatches.length === 0) {
- if (this.$store.getters['settings/isEnterpriseFeatureEnabled'](EnterpriseEditionFeature.Sharing)) {
+ if (this.settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.Sharing)) {
foundIssues[credentialTypeDescription.name] = [this.$locale.baseText('nodeIssues.credentials.notAvailable')];
} else {
foundIssues[credentialTypeDescription.name] = [this.$locale.baseText('nodeIssues.credentials.doNotExist', { interpolate: { name: selectedCredentials.name, type: credentialDisplayName } }), this.$locale.baseText('nodeIssues.credentials.doNotExist.hint')];
@@ -358,13 +373,13 @@ export const nodeHelpers = mixins(
// Updates the node credential issues
updateNodesCredentialsIssues () {
- const nodes = this.$store.getters.allNodes;
+ const nodes = this.workflowsStore.allNodes;
let issues: INodeIssues | null;
for (const node of nodes) {
issues = this.getNodeCredentialIssues(node);
- this.$store.commit('setNodeIssue', {
+ this.workflowsStore.setNodeIssue({
node: node.name,
type: 'credentials',
value: issues === null ? null : issues.credentials,
@@ -377,10 +392,10 @@ export const nodeHelpers = mixins(
return [];
}
- if (this.$store.getters.getWorkflowExecution === null) {
+ if (this.workflowsStore.getWorkflowExecution === null) {
return [];
}
- const executionData: IRunExecutionData = this.$store.getters.getWorkflowExecution.data;
+ const executionData = this.workflowsStore.getWorkflowExecution.data;
if (!executionData || !executionData.resultData) { // unknown status
return [];
}
@@ -437,13 +452,13 @@ export const nodeHelpers = mixins(
name: node.name,
properties: {
disabled: !node.disabled,
- },
- };
+ } as IDataObject,
+ } as INodeUpdatePropertiesInformation;
- this.$telemetry.track('User set node enabled status', { node_type: node.type, is_enabled: node.disabled, workflow_id: this.$store.getters.workflowId });
+ this.$telemetry.track('User set node enabled status', { node_type: node.type, is_enabled: node.disabled, workflow_id: this.workflowsStore.workflowId });
- this.$store.commit('updateNodeProperties', updateInformation);
- this.$store.commit('clearNodeExecutionData', node.name);
+ this.workflowsStore.updateNodeProperties(updateInformation);
+ this.workflowsStore.clearNodeExecutionData(node.name);
this.updateNodeParameterIssues(node);
this.updateNodeCredentialIssues(node);
}
diff --git a/packages/editor-ui/src/components/mixins/pinData.ts b/packages/editor-ui/src/components/mixins/pinData.ts
index 1bfe9cc1e140e..0fa14e6cf6182 100644
--- a/packages/editor-ui/src/components/mixins/pinData.ts
+++ b/packages/editor-ui/src/components/mixins/pinData.ts
@@ -3,6 +3,8 @@ import { INodeUi } from '@/Interface';
import { IPinData } from 'n8n-workflow';
import { stringSizeInBytes } from '@/components/helpers';
import { MAX_WORKFLOW_PINNED_DATA_SIZE, PIN_DATA_NODE_TYPES_DENYLIST } from '@/constants';
+import { mapStores } from 'pinia';
+import { useWorkflowsStore } from '@/stores/workflows';
export interface IPinDataContext {
node: INodeUi;
@@ -11,8 +13,9 @@ export interface IPinDataContext {
export const pinData = (Vue as Vue.VueConstructor).extend({
computed: {
+ ...mapStores(useWorkflowsStore),
pinData (): IPinData[string] | undefined {
- return this.node ? this.$store.getters['pinDataByNodeName'](this.node!.name) : undefined;
+ return this.node ? this.workflowsStore.pinDataByNodeName(this.node!.name) : undefined;
},
hasPinData (): boolean {
return !!this.node && typeof this.pinData !== 'undefined';
@@ -70,7 +73,7 @@ export const pinData = (Vue as Vue.VueConstructor).extend
isValidPinDataSize(data: string | object): boolean {
if (typeof data === 'object') data = JSON.stringify(data);
- if (this.$store.getters['pinDataSize'] + stringSizeInBytes(data) > MAX_WORKFLOW_PINNED_DATA_SIZE) {
+ if (this.workflowsStore.pinDataSize + stringSizeInBytes(data) > MAX_WORKFLOW_PINNED_DATA_SIZE) {
this.$showError(
new Error(this.$locale.baseText('ndv.pinData.error.tooLarge.description')),
this.$locale.baseText('ndv.pinData.error.tooLarge.title'),
diff --git a/packages/editor-ui/src/components/mixins/pushConnection.ts b/packages/editor-ui/src/components/mixins/pushConnection.ts
index dcc3599911346..15b1a2aa9285a 100644
--- a/packages/editor-ui/src/components/mixins/pushConnection.ts
+++ b/packages/editor-ui/src/components/mixins/pushConnection.ts
@@ -1,4 +1,5 @@
import {
+ IExecutionResponse,
IExecutionsCurrentSummaryExtended,
IPushData,
} from '../../Interface';
@@ -22,6 +23,10 @@ import mixins from 'vue-typed-mixins';
import { WORKFLOW_SETTINGS_MODAL_KEY } from '@/constants';
import { getTriggerNodeServiceName } from '../helpers';
import { codeNodeEditorEventBus } from '@/event-bus/code-node-editor-event-bus';
+import { mapStores } from 'pinia';
+import { useUIStore } from '@/stores/ui';
+import { useWorkflowsStore } from '@/stores/workflows';
+import { useNodeTypesStore } from '@/stores/nodeTypes';
export const pushConnection = mixins(
externalHooks,
@@ -40,8 +45,13 @@ export const pushConnection = mixins(
};
},
computed: {
+ ...mapStores(
+ useNodeTypesStore,
+ useUIStore,
+ useWorkflowsStore,
+ ),
sessionId (): string {
- return this.$store.getters.sessionId;
+ return this.rootStore.sessionId;
},
},
methods: {
@@ -63,13 +73,13 @@ export const pushConnection = mixins(
// always removed that we do not end up with multiple ones
this.pushDisconnect();
- const connectionUrl = `${this.$store.getters.getRestUrl}/push?sessionId=${this.sessionId}`;
+ const connectionUrl = `${this.rootStore.getRestUrl}/push?sessionId=${this.sessionId}`;
this.eventSource = new EventSource(connectionUrl, { withCredentials: true });
this.eventSource.addEventListener('message', this.pushMessageReceived, false);
this.eventSource.addEventListener('open', () => {
- this.$store.commit('setPushConnectionActive', true);
+ this.rootStore.pushConnectionActive = true;
if (this.reconnectTimeout !== null) {
clearTimeout(this.reconnectTimeout);
this.reconnectTimeout = null;
@@ -84,7 +94,7 @@ export const pushConnection = mixins(
this.reconnectTimeout = null;
}
- this.$store.commit('setPushConnectionActive', false);
+ this.rootStore.pushConnectionActive = false;
this.pushAutomaticReconnect();
}, false);
},
@@ -97,7 +107,7 @@ export const pushConnection = mixins(
this.eventSource.close();
this.eventSource = null;
- this.$store.commit('setPushConnectionActive', false);
+ this.rootStore.pushConnectionActive = false;
}
},
@@ -178,12 +188,12 @@ export const pushConnection = mixins(
}
if (receivedData.type === 'nodeExecuteAfter' || receivedData.type === 'nodeExecuteBefore') {
- if (this.$store.getters.isActionActive('workflowRunning') === false) {
+ if (!this.uiStore.isActionActive('workflowRunning')) {
// No workflow is running so ignore the messages
return false;
}
const pushData = receivedData.data;
- if (this.$store.getters.activeExecutionId !== pushData.executionId) {
+ if (this.workflowsStore.activeExecutionId !== pushData.executionId) {
// The data is not for the currently active execution or
// we do not have the execution id yet.
if (isRetry !== true) {
@@ -197,14 +207,14 @@ export const pushConnection = mixins(
// The workflow finished executing
const pushData = receivedData.data;
- this.$store.commit('finishActiveExecution', pushData);
+ this.workflowsStore.finishActiveExecution(pushData);
- if (this.$store.getters.isActionActive('workflowRunning') === false) {
+ if (!this.uiStore.isActionActive('workflowRunning')) {
// No workflow is running so ignore the messages
return false;
}
- if (this.$store.getters.activeExecutionId !== pushData.executionId) {
+ if (this.workflowsStore.activeExecutionId !== pushData.executionId) {
// The workflow which did finish execution did either not get started
// by this session or we do not have the execution id yet.
if (isRetry !== true) {
@@ -227,19 +237,17 @@ export const pushConnection = mixins(
const workflow = this.getCurrentWorkflow();
if (runDataExecuted.waitTill !== undefined) {
- const {
- activeExecutionId,
- workflowSettings,
- saveManualExecutions,
- } = this.$store.getters;
+ const activeExecutionId = this.workflowsStore.activeExecutionId;
+ const workflowSettings = this.workflowsStore.workflowSettings;
+ const saveManualExecutions = this.rootStore.saveManualExecutions;
const isSavingExecutions= workflowSettings.saveManualExecutions === undefined ? saveManualExecutions : workflowSettings.saveManualExecutions;
let action;
if (!isSavingExecutions) {
this.$root.$emit('registerGlobalLinkAction', 'open-settings', async () => {
- if (this.$store.getters.isNewWorkflow) await this.saveAsNewWorkflow();
- this.$store.dispatch('ui/openModal', WORKFLOW_SETTINGS_MODAL_KEY);
+ if (this.workflowsStore.isNewWorkflow) await this.saveAsNewWorkflow();
+ this.uiStore.openModal(WORKFLOW_SETTINGS_MODAL_KEY);
});
action = 'Turn on saving manual executions and run again to see what happened after this node.';
@@ -272,7 +280,7 @@ export const pushConnection = mixins(
error_title: error.message,
error_type: error.context.type,
node_graph_string: JSON.stringify(TelemetryHelpers.generateNodesGraph(workflowData as IWorkflowBase, this.getNodeTypes()).nodeGraph),
- workflow_id: this.$store.getters.workflowId,
+ workflow_id: this.workflowsStore.workflowId,
};
if (error.context.nodeCause && ['no pairing info', 'invalid pairing info'].includes(error.context.type as string)) {
@@ -295,7 +303,7 @@ export const pushConnection = mixins(
if (runDataExecuted.data.resultData.error?.name === 'SubworkflowOperationError') {
const error = runDataExecuted.data.resultData.error as SubworkflowOperationError;
- this.$store.commit('setSubworkflowExecutionError', error);
+ this.workflowsStore.subWorkflowExecutionError = error;
this.$showMessage({
title: error.message,
@@ -324,10 +332,10 @@ export const pushConnection = mixins(
// Workflow did execute without a problem
this.$titleSet(workflow.name as string, 'IDLE');
- const execution = this.$store.getters.getWorkflowExecution;
+ const execution = this.workflowsStore.getWorkflowExecution;
if (execution && execution.executedNode) {
- const node = this.$store.getters.getNodeByName(execution.executedNode);
- const nodeType = node && this.$store.getters['nodeTypes/getNodeType'](node.type, node.typeVersion);
+ const node = this.workflowsStore.getNodeByName(execution.executedNode);
+ const nodeType = node && this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
const nodeOutput = execution && execution.executedNode && execution.data && execution.data.resultData && execution.data.resultData.runData && execution.data.resultData.runData[execution.executedNode];
if (node && nodeType && !nodeOutput) {
this.$showMessage({
@@ -361,11 +369,13 @@ export const pushConnection = mixins(
// It does not push the runData as it got already pushed with each
// node that did finish. For that reason copy in here the data
// which we already have.
- runDataExecuted.data.resultData.runData = this.$store.getters.getWorkflowRunData;
+ if (this.workflowsStore.getWorkflowRunData) {
+ runDataExecuted.data.resultData.runData = this.workflowsStore.getWorkflowRunData;
+ }
- this.$store.commit('setExecutingNode', null);
- this.$store.commit('setWorkflowExecutionData', runDataExecuted);
- this.$store.commit('removeActiveAction', 'workflowRunning');
+ this.workflowsStore.executingNode = null;
+ this.workflowsStore.setWorkflowExecutionData(runDataExecuted as IExecutionResponse);
+ this.uiStore.removeActiveAction('workflowRunning');
// Set the node execution issues on all the nodes which produced an error so that
// it can be displayed in the node-view
@@ -397,36 +407,36 @@ export const pushConnection = mixins(
workflowName: pushData.workflowName,
};
- this.$store.commit('addActiveExecution', executionData);
+ this.workflowsStore.addActiveExecution(executionData);
} else if (receivedData.type === 'nodeExecuteAfter') {
// A node finished to execute. Add its data
const pushData = receivedData.data;
- this.$store.commit('addNodeExecutionData', pushData);
+ this.workflowsStore.addNodeExecutionData(pushData);
} else if (receivedData.type === 'nodeExecuteBefore') {
// A node started to be executed. Set it as executing.
const pushData = receivedData.data;
- this.$store.commit('setExecutingNode', pushData.nodeName);
+ this.workflowsStore.executingNode = pushData.nodeName;
} else if (receivedData.type === 'testWebhookDeleted') {
// A test-webhook was deleted
const pushData = receivedData.data;
- if (pushData.workflowId === this.$store.getters.workflowId) {
- this.$store.commit('setExecutionWaitingForWebhook', false);
- this.$store.commit('removeActiveAction', 'workflowRunning');
+ if (pushData.workflowId === this.workflowsStore.workflowId) {
+ this.workflowsStore.executionWaitingForWebhook = false;
+ this.uiStore.removeActiveAction('workflowRunning');
}
} else if (receivedData.type === 'testWebhookReceived') {
// A test-webhook did get called
const pushData = receivedData.data;
- if (pushData.workflowId === this.$store.getters.workflowId) {
- this.$store.commit('setExecutionWaitingForWebhook', false);
- this.$store.commit('setActiveExecutionId', pushData.executionId);
+ if (pushData.workflowId === this.workflowsStore.workflowId) {
+ this.workflowsStore.executionWaitingForWebhook = false;
+ this.workflowsStore.activeExecutionId = pushData.executionId;
}
this.processWaitingPushMessages();
} else if (receivedData.type === 'reloadNodeType') {
- this.$store.dispatch('nodeTypes/getNodeTypes');
- this.$store.dispatch('nodeTypes/getFullNodesProperties', [receivedData.data]);
+ this.nodeTypesStore.getNodeTypes();
+ this.nodeTypesStore.getFullNodesProperties([receivedData.data]);
} else if (receivedData.type === 'removeNodeType') {
const pushData = receivedData.data;
@@ -435,7 +445,7 @@ export const pushConnection = mixins(
// Force reload of all credential types
this.$store.dispatch('credentials/fetchCredentialTypes')
.then(() => {
- this.$store.commit('nodeTypes/removeNodeTypes', nodesToBeRemoved);
+ this.nodeTypesStore.removeNodeTypes(nodesToBeRemoved);
});
}
return true;
diff --git a/packages/editor-ui/src/components/mixins/restApi.ts b/packages/editor-ui/src/components/mixins/restApi.ts
index ecf3c48f22e3a..cf3ee357f5995 100644
--- a/packages/editor-ui/src/components/mixins/restApi.ts
+++ b/packages/editor-ui/src/components/mixins/restApi.ts
@@ -28,6 +28,8 @@ import {
INodeTypeNameVersion,
} from 'n8n-workflow';
import { makeRestApiRequest } from '@/api/helpers';
+import { mapStores } from 'pinia';
+import { useRootStore } from '@/stores/n8nRootStore';
/**
* Unflattens the Execution data.
@@ -52,12 +54,17 @@ function unflattenExecutionData (fullExecutionData: IExecutionFlattedResponse):
}
export const restApi = Vue.extend({
+ computed: {
+ ...mapStores(
+ useRootStore,
+ ),
+ },
methods: {
restApi (): IRestApi {
const self = this;
return {
async makeRestApiRequest (method: Method, endpoint: string, data?: IDataObject): Promise { // tslint:disable-line:no-any
- return makeRestApiRequest(self.$store.getters.getRestApiContext, method, endpoint, data);
+ return makeRestApiRequest(self.rootStore.getRestApiContext, method, endpoint, data);
},
getActiveWorkflows: (): Promise => {
return self.restApi().makeRestApiRequest('GET', `/active`);
diff --git a/packages/editor-ui/src/components/mixins/showMessage.ts b/packages/editor-ui/src/components/mixins/showMessage.ts
index 473fc85550f02..b76e0c88b0a4b 100644
--- a/packages/editor-ui/src/components/mixins/showMessage.ts
+++ b/packages/editor-ui/src/components/mixins/showMessage.ts
@@ -7,10 +7,17 @@ import { IRunExecutionData } from 'n8n-workflow';
import type { ElMessageBoxOptions } from 'element-ui/types/message-box';
import type { ElMessageComponent, ElMessageOptions, MessageType } from 'element-ui/types/message';
import { sanitizeHtml } from '@/utils';
+import { mapStores } from 'pinia';
+import { useWorkflowsStore } from '@/stores/workflows';
let stickyNotificationQueue: ElNotificationComponent[] = [];
export const showMessage = mixins(externalHooks).extend({
+ computed: {
+ ...mapStores(
+ useWorkflowsStore,
+ ),
+ },
methods: {
$showMessage(
messageData: Omit & { message?: string },
@@ -34,7 +41,7 @@ export const showMessage = mixins(externalHooks).extend({
error_title: messageData.title,
error_message: messageData.message,
caused_by_credential: this.causedByCredential(messageData.message),
- workflow_id: this.$store.getters.workflowId,
+ workflow_id: this.workflowsStore.workflowId,
});
}
@@ -134,7 +141,7 @@ export const showMessage = mixins(externalHooks).extend({
error_description: message,
error_message: error.message,
caused_by_credential: this.causedByCredential(error.message),
- workflow_id: this.$store.getters.workflowId,
+ workflow_id: this.workflowsStore.workflowId,
});
},
diff --git a/packages/editor-ui/src/components/mixins/userHelpers.ts b/packages/editor-ui/src/components/mixins/userHelpers.ts
index 68e3a4412f649..a7aee3a06aebc 100644
--- a/packages/editor-ui/src/components/mixins/userHelpers.ts
+++ b/packages/editor-ui/src/components/mixins/userHelpers.ts
@@ -1,5 +1,6 @@
-import { IPermissions } from '@/Interface';
+import { IPermissions, IUser } from '@/Interface';
import { isAuthorized } from '@/modules/userHelpers';
+import { useUsersStore } from '@/stores/users';
import Vue from 'vue';
import { Route } from 'vue-router';
@@ -11,13 +12,14 @@ export const userHelpers = Vue.extend({
return this.canUserAccessRoute(route);
},
- canUserAccessCurrentRoute() {
+ canUserAccessCurrentRoute(): boolean {
return this.canUserAccessRoute(this.$route);
},
canUserAccessRoute(route: Route): boolean {
const permissions: IPermissions = route.meta && route.meta.permissions;
- const currentUser = this.$store.getters['users/currentUser'];
+ const usersStore = useUsersStore();
+ const currentUser = usersStore.currentUser;
if (permissions && isAuthorized(permissions, currentUser)) {
return true;
diff --git a/packages/editor-ui/src/components/mixins/workflowActivate.ts b/packages/editor-ui/src/components/mixins/workflowActivate.ts
index 783be2a84fc3d..5133aaee5a478 100644
--- a/packages/editor-ui/src/components/mixins/workflowActivate.ts
+++ b/packages/editor-ui/src/components/mixins/workflowActivate.ts
@@ -5,6 +5,10 @@ import { showMessage } from '@/components/mixins/showMessage';
import mixins from 'vue-typed-mixins';
import { LOCAL_STORAGE_ACTIVATION_FLAG, PLACEHOLDER_EMPTY_WORKFLOW_ID, WORKFLOW_ACTIVE_MODAL_KEY } from '@/constants';
+import { mapStores } from 'pinia';
+import { useUIStore } from '@/stores/ui';
+import { useSettingsStore } from '@/stores/settings';
+import { useWorkflowsStore } from '@/stores/workflows';
export const workflowActivate = mixins(
externalHooks,
@@ -17,14 +21,21 @@ export const workflowActivate = mixins(
updatingWorkflowActivation: false,
};
},
+ computed: {
+ ...mapStores(
+ useSettingsStore,
+ useUIStore,
+ useWorkflowsStore,
+ ),
+ },
methods: {
async activateCurrentWorkflow(telemetrySource?: string) {
- const workflowId = this.$store.getters.workflowId;
+ const workflowId = this.workflowsStore.workflowId;
return this.updateWorkflowActivation(workflowId, true, telemetrySource);
},
async updateWorkflowActivation(workflowId: string | undefined, newActiveState: boolean, telemetrySource?: string) {
this.updatingWorkflowActivation = true;
- const nodesIssuesExist = this.$store.getters.nodesIssuesExist as boolean;
+ const nodesIssuesExist = this.workflowsStore.nodesIssuesExist as boolean;
let currWorkflowId: string | undefined = workflowId;
if (!currWorkflowId || currWorkflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID) {
@@ -33,11 +44,11 @@ export const workflowActivate = mixins(
this.updatingWorkflowActivation = false;
return;
}
- currWorkflowId = this.$store.getters.workflowId as string;
+ currWorkflowId = this.workflowsStore.workflowId as string;
}
- const isCurrentWorkflow = currWorkflowId === this.$store.getters['workflowId'];
+ const isCurrentWorkflow = currWorkflowId === this.workflowsStore.workflowId;
- const activeWorkflows = this.$store.getters.getActiveWorkflows;
+ const activeWorkflows = this.workflowsStore.activeWorkflows;
const isWorkflowActive = activeWorkflows.includes(currWorkflowId);
const telemetryPayload = {
@@ -93,10 +104,10 @@ export const workflowActivate = mixins(
if (isCurrentWorkflow) {
if (newActiveState && window.localStorage.getItem(LOCAL_STORAGE_ACTIVATION_FLAG) !== 'true') {
- this.$store.dispatch('ui/openModal', WORKFLOW_ACTIVE_MODAL_KEY);
+ this.uiStore.openModal(WORKFLOW_ACTIVE_MODAL_KEY);
}
else {
- this.$store.dispatch('settings/fetchPromptsData');
+ this.settingsStore.fetchPromptsData();
}
}
},
diff --git a/packages/editor-ui/src/components/mixins/workflowHelpers.ts b/packages/editor-ui/src/components/mixins/workflowHelpers.ts
index 381378e3c758c..e8136f6d27a08 100644
--- a/packages/editor-ui/src/components/mixins/workflowHelpers.ts
+++ b/packages/editor-ui/src/components/mixins/workflowHelpers.ts
@@ -57,6 +57,14 @@ import { isEqual } from 'lodash';
import mixins from 'vue-typed-mixins';
import { v4 as uuid } from 'uuid';
import { getSourceItems } from '@/pairedItemUtils';
+import { mapStores } from 'pinia';
+import { useUIStore } from '@/stores/ui';
+import { useWorkflowsStore } from '@/stores/workflows';
+import { useRootStore } from '@/stores/n8nRootStore';
+import { IWorkflowSettings } from 'n8n-workflow';
+import { useNDVStore } from '@/stores/ndv';
+import { useTemplatesStore } from '@/stores/templates';
+import { useNodeTypesStore } from '@/stores/nodeTypes';
let cachedWorkflowKey: string | null = '';
let cachedWorkflow: Workflow | null = null;
@@ -68,6 +76,16 @@ export const workflowHelpers = mixins(
showMessage,
)
.extend({
+ computed: {
+ ...mapStores(
+ useNodeTypesStore,
+ useNDVStore,
+ useRootStore,
+ useTemplatesStore,
+ useWorkflowsStore,
+ useUIStore,
+ ),
+ },
methods: {
executeData(parentNode: string[], currentNode: string, inputName: string, runIndex: number): IExecuteData {
const executeData = {
@@ -81,7 +99,7 @@ export const workflowHelpers = mixins(
// which does not use the node name
const parentNodeName = parentNode[0];
- const parentPinData = this.$store.getters.pinData[parentNodeName];
+ const parentPinData = this.workflowsStore.getPinData![parentNodeName];
// populate `executeData` from `pinData`
@@ -94,7 +112,7 @@ export const workflowHelpers = mixins(
// populate `executeData` from `runData`
- const workflowRunData = this.$store.getters.getWorkflowRunData as IRunData | null;
+ const workflowRunData = this.workflowsStore.getWorkflowRunData;
if (workflowRunData === null) {
return executeData;
}
@@ -154,7 +172,7 @@ export const workflowHelpers = mixins(
}
const parentPinData = parentNode.reduce((acc: INodeExecutionData[], parentNodeName, index) => {
- const pinData = this.$store.getters['pinDataByNodeName'](parentNodeName);
+ const pinData = this.workflowsStore.pinDataByNodeName(parentNodeName);
if (pinData) {
acc.push({
@@ -190,7 +208,7 @@ export const workflowHelpers = mixins(
// This has the advantage that it is very fast and does not cause problems with vuex
// when the workflow replaces the node-parameters.
getNodes (): INodeUi[] {
- const nodes = this.$store.getters.allNodes;
+ const nodes = this.workflowsStore.allNodes;
const returnNodes: INodeUi[] = [];
for (const node of nodes) {
@@ -204,11 +222,11 @@ export const workflowHelpers = mixins(
// For each such type does it return how high the limit is, how many
// already exist and the name of this nodes.
getNodeTypesMaxCount (): INodeTypesMaxCount {
- const nodes = this.$store.getters.allNodes;
+ const nodes = this.workflowsStore.allNodes;
const returnData: INodeTypesMaxCount = {};
- const nodeTypes = this.$store.getters['nodeTypes/allNodeTypes'];
+ const nodeTypes = this.nodeTypesStore.allNodeTypes;
for (const nodeType of nodeTypes) {
if (nodeType.maxNodes !== undefined) {
returnData[nodeType.name] = {
@@ -231,7 +249,7 @@ export const workflowHelpers = mixins(
// Returns how many nodes of the given type currently exist
getNodeTypeCount (nodeType: string): number {
- const nodes = this.$store.getters.allNodes;
+ const nodes = this.workflowsStore.allNodes;
let count = 0;
@@ -318,7 +336,7 @@ export const workflowHelpers = mixins(
return [];
},
getByNameAndVersion: (nodeType: string, version?: number): INodeType | undefined => {
- const nodeTypeDescription = this.$store.getters['nodeTypes/getNodeType'](nodeType, version) as INodeTypeDescription | null;
+ const nodeTypeDescription = this.nodeTypesStore.getNodeType(nodeType, version);
if (nodeTypeDescription === null) {
return undefined;
@@ -339,7 +357,7 @@ export const workflowHelpers = mixins(
getCurrentWorkflow(copyData?: boolean): Workflow {
const nodes = this.getNodes();
- const connections = (this.$store.getters.allConnections as IConnections);
+ const connections = this.workflowsStore.allConnections;
const cacheKey = JSON.stringify({nodes, connections});
if (!copyData && cachedWorkflow && cacheKey === cachedWorkflowKey) {
return cachedWorkflow;
@@ -352,12 +370,12 @@ export const workflowHelpers = mixins(
// Returns a workflow instance.
getWorkflow (nodes: INodeUi[], connections: IConnections, copyData?: boolean): Workflow {
const nodeTypes = this.getNodeTypes();
- let workflowId = this.$store.getters.workflowId;
- if (workflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID) {
+ let workflowId : string | undefined = this.workflowsStore.workflowId;
+ if (workflowId && workflowId === PLACEHOLDER_EMPTY_WORKFLOW_ID) {
workflowId = undefined;
}
- const workflowName = this.$store.getters.workflowName;
+ const workflowName = this.workflowsStore.workflowName;
cachedWorkflow = new Workflow({
id: workflowId,
@@ -366,8 +384,8 @@ export const workflowHelpers = mixins(
connections: copyData? deepCopy(connections): connections,
active: false,
nodeTypes,
- settings: this.$store.getters.workflowSettings,
- pinData: this.$store.getters.pinData,
+ settings: this.workflowsStore.workflowSettings,
+ pinData: this.workflowsStore.pinData,
});
return cachedWorkflow;
@@ -375,8 +393,8 @@ export const workflowHelpers = mixins(
// Returns the currently loaded workflow as JSON.
getWorkflowDataToSave (): Promise {
- const workflowNodes = this.$store.getters.allNodes;
- const workflowConnections = this.$store.getters.allConnections;
+ const workflowNodes = this.workflowsStore.allNodes;
+ const workflowConnections = this.workflowsStore.allConnections;
let nodeData;
@@ -393,17 +411,17 @@ export const workflowHelpers = mixins(
}
const data: IWorkflowData = {
- name: this.$store.getters.workflowName,
+ name: this.workflowsStore.workflowName,
nodes,
- pinData: this.$store.getters.pinData,
+ pinData: this.workflowsStore.getPinData,
connections: workflowConnections,
- active: this.$store.getters.isActive,
- settings: this.$store.getters.workflowSettings,
- tags: this.$store.getters.workflowTags,
- hash: this.$store.getters.workflowHash,
+ active: this.workflowsStore.isWorkflowActive,
+ settings: this.workflowsStore.workflow.settings,
+ tags: this.workflowsStore.workflowTags,
+ hash: this.workflowsStore.workflow.hash,
};
- const workflowId = this.$store.getters.workflowId;
+ const workflowId = this.workflowsStore.workflowId;
if (workflowId !== PLACEHOLDER_EMPTY_WORKFLOW_ID) {
data.id = workflowId;
}
@@ -438,7 +456,7 @@ export const workflowHelpers = mixins(
// Get the data of the node type that we can get the default values
// TODO: Later also has to care about the node-type-version as defaults could be different
- const nodeType = this.$store.getters['nodeTypes/getNodeType'](node.type, node.typeVersion) as INodeTypeDescription | null;
+ const nodeType = this.nodeTypesStore.getNodeType(node.type, node.typeVersion);
if (nodeType !== null) {
// Node-Type is known so we can save the parameters correctly
@@ -518,12 +536,12 @@ export const workflowHelpers = mixins(
if (webhookData.restartWebhook === true) {
return '$execution.resumeUrl';
}
- let baseUrl = this.$store.getters.getWebhookUrl;
+ let baseUrl = this.rootStore.getWebhookUrl;
if (showUrlFor === 'test') {
- baseUrl = this.$store.getters.getWebhookTestUrl;
+ baseUrl = this.rootStore.getWebhookTestUrl;
}
- const workflowId = this.$store.getters.workflowId;
+ const workflowId = this.workflowsStore.workflowId;
const path = this.getWebhookExpressionValue(webhookData, 'path');
const isFullPath = this.getWebhookExpressionValue(webhookData, 'isFullPath') as unknown as boolean || false;
@@ -535,11 +553,11 @@ export const workflowHelpers = mixins(
let itemIndex = opts?.targetItem?.itemIndex || 0;
const inputName = 'main';
- const activeNode = this.$store.getters['ndv/activeNode'];
+ const activeNode = this.ndvStore.activeNode;
const workflow = this.getCurrentWorkflow();
- const workflowRunData = this.$store.getters.getWorkflowRunData as IRunData | null;
- let parentNode = workflow.getParentNodes(activeNode.name, inputName, 1);
- const executionData = this.$store.getters.getWorkflowExecution as IExecutionResponse | null;
+ const workflowRunData = this.workflowsStore.getWorkflowRunData;
+ let parentNode = workflow.getParentNodes(activeNode?.name, inputName, 1);
+ const executionData = this.workflowsStore.getWorkflowExecution;
if (opts?.inputNodeName && !parentNode.includes(opts.inputNodeName)) {
return null;
@@ -586,7 +604,7 @@ export const workflowHelpers = mixins(
}
parentNode.forEach((parentNodeName) => {
- const pinData: IPinData[string] = this.$store.getters['pinDataByNodeName'](parentNodeName);
+ const pinData: IPinData[string] = this.workflowsStore.pinDataByNodeName(parentNodeName);
if (pinData) {
runExecutionData = {
@@ -635,7 +653,7 @@ export const workflowHelpers = mixins(
}
const executeData = this.executeData(parentNode, activeNode.name, inputName, runIndexCurrent);
- return workflow.expression.getParameterValue(parameter, runExecutionData, runIndexCurrent, itemIndex, activeNode.name, connectionInputData, 'manual', this.$store.getters.timezone, additionalKeys, executeData, false) as IDataObject;
+ return workflow.expression.getParameterValue(parameter, runExecutionData, runIndexCurrent, itemIndex, activeNode.name, connectionInputData, 'manual', this.rootStore.timezone, additionalKeys, executeData, false) as IDataObject;
},
resolveExpression(expression: string, siblingParameters: INodeParameters = {}, opts: {targetItem?: TargetItem, inputNodeName?: string, inputRunIndex?: number, inputBranchIndex?: number, c?: number} = {}) {
@@ -658,7 +676,7 @@ export const workflowHelpers = mixins(
async updateWorkflow({workflowId, active}: {workflowId: string, active?: boolean}) {
let data: IWorkflowDataUpdate = {};
- const isCurrentWorkflow = workflowId === this.$store.getters.workflowId;
+ const isCurrentWorkflow = workflowId === this.workflowsStore.workflowId;
if (isCurrentWorkflow) {
data = await this.getWorkflowDataToSave();
} else {
@@ -671,17 +689,17 @@ export const workflowHelpers = mixins(
}
const workflow = await this.restApi().updateWorkflow(workflowId, data);
- this.$store.commit('setWorkflowHash', workflow.hash);
+ this.workflowsStore.setWorkflowHash(workflow.hash || '');
if (isCurrentWorkflow) {
- this.$store.commit('setActive', !!workflow.active);
- this.$store.commit('setStateDirty', false);
+ this.workflowsStore.setActive(!!workflow.active);
+ this.uiStore.stateIsDirty = false;
}
if (workflow.active) {
- this.$store.commit('setWorkflowActive', workflowId);
+ this.workflowsStore.setWorkflowActive(workflowId);
} else {
- this.$store.commit('setWorkflowInactive', workflowId);
+ this.workflowsStore.setWorkflowInactive(workflowId);
}
},
@@ -694,7 +712,7 @@ export const workflowHelpers = mixins(
// Workflow exists already so update it
try {
- this.$store.commit('addActiveAction', 'workflowSaving');
+ this.uiStore.addActiveAction('workflowSaving');
const workflowDataRequest: IWorkflowDataUpdate = await this.getWorkflowDataToSave();
@@ -706,28 +724,28 @@ export const workflowHelpers = mixins(
workflowDataRequest.tags = tags;
}
- workflowDataRequest.hash = this.$store.getters.workflowHash;
+ workflowDataRequest.hash = this.workflowsStore.workflowHash;
const workflowData = await this.restApi().updateWorkflow(currentWorkflow, workflowDataRequest);
- this.$store.commit('setWorkflowHash', workflowData.hash);
+ this.workflowsStore.setWorkflowHash(workflowData.hash || '');
if (name) {
- this.$store.commit('setWorkflowName', {newName: workflowData.name});
+ this.workflowsStore.setWorkflowName({newName: workflowData.name, setStateDirty: false});
}
if (tags) {
const createdTags = (workflowData.tags || []) as ITag[];
const tagIds = createdTags.map((tag: ITag): string => tag.id);
- this.$store.commit('setWorkflowTagIds', tagIds);
+ this.workflowsStore.setWorkflowTagIds(tagIds);
}
- this.$store.commit('setStateDirty', false);
- this.$store.commit('removeActiveAction', 'workflowSaving');
+ this.uiStore.stateIsDirty = false;
+ this.uiStore.removeActiveAction('workflowSaving');
this.$externalHooks().run('workflow.afterUpdate', { workflowData });
return true;
} catch (error) {
- this.$store.commit('removeActiveAction', 'workflowSaving');
+ this.uiStore.removeActiveAction('workflowSaving');
this.$showMessage({
title: this.$locale.baseText('workflowHelpers.showMessage.title'),
@@ -741,7 +759,7 @@ export const workflowHelpers = mixins(
async saveAsNewWorkflow ({ name, tags, resetWebhookUrls, resetNodeIds, openInNewWindow, data }: {name?: string, tags?: string[], resetWebhookUrls?: boolean, openInNewWindow?: boolean, resetNodeIds?: boolean, data?: IWorkflowDataUpdate} = {}, redirect = true): Promise {
try {
- this.$store.commit('addActiveAction', 'workflowSaving');
+ this.uiStore.addActiveAction('workflowSaving');
const workflowDataRequest: IWorkflowDataUpdate = data || await this.getWorkflowDataToSave();
// make sure that the new ones are not active
@@ -775,40 +793,40 @@ export const workflowHelpers = mixins(
}
const workflowData = await this.restApi().createNewWorkflow(workflowDataRequest);
- this.$store.commit('addWorkflow', workflowData);
- this.$store.commit('setWorkflowHash', workflowData.hash);
+ this.workflowsStore.addWorkflow(workflowData);
+ this.workflowsStore.setWorkflowHash(workflowData.hash || '');
if (openInNewWindow) {
const routeData = this.$router.resolve({name: VIEWS.WORKFLOW, params: {name: workflowData.id}});
window.open(routeData.href, '_blank');
- this.$store.commit('removeActiveAction', 'workflowSaving');
+ this.uiStore.removeActiveAction('workflowSaving');
return true;
}
- this.$store.commit('setActive', workflowData.active || false);
- this.$store.commit('setWorkflowId', workflowData.id);
- this.$store.commit('setWorkflowName', {newName: workflowData.name, setStateDirty: false});
- this.$store.commit('setWorkflowSettings', workflowData.settings || {});
- this.$store.commit('setStateDirty', false);
+ this.workflowsStore.setActive(workflowData.active || false);
+ this.workflowsStore.setWorkflowId(workflowData.id);
+ this.workflowsStore.setWorkflowName({newName: workflowData.name, setStateDirty: false});
+ this.workflowsStore.setWorkflowSettings(workflowData.settings as IWorkflowSettings|| {});
+ this.uiStore.stateIsDirty = false;
Object.keys(changedNodes).forEach((nodeName) => {
const changes = {
key: 'webhookId',
value: changedNodes[nodeName],
name: nodeName,
- } as IUpdateInformation;
- this.$store.commit('setNodeValue', changes);
+ };
+ this.workflowsStore.setNodeValue(changes);
});
const createdTags = (workflowData.tags || []) as ITag[];
const tagIds = createdTags.map((tag: ITag): string => tag.id);
- this.$store.commit('setWorkflowTagIds', tagIds);
+ this.workflowsStore.setWorkflowTagIds(tagIds);
const templateId = this.$route.query.templateId;
if (templateId) {
this.$telemetry.track('User saved new workflow from template', {
template_id: templateId,
workflow_id: workflowData.id,
- wf_template_repo_session_id: this.$store.getters['templates/previousSessionId'],
+ wf_template_repo_session_id: this.templatesStore.previousSessionId,
});
}
@@ -819,13 +837,13 @@ export const workflowHelpers = mixins(
});
}
- this.$store.commit('removeActiveAction', 'workflowSaving');
- this.$store.commit('setStateDirty', false);
+ this.uiStore.removeActiveAction('workflowSaving');
+ this.uiStore.stateIsDirty = false;
this.$externalHooks().run('workflow.afterUpdate', { workflowData });
return true;
} catch (e) {
- this.$store.commit('removeActiveAction', 'workflowSaving');
+ this.uiStore.removeActiveAction('workflowSaving');
this.$showMessage({
title: this.$locale.baseText('workflowHelpers.showMessage.title'),
diff --git a/packages/editor-ui/src/components/mixins/workflowRun.ts b/packages/editor-ui/src/components/mixins/workflowRun.ts
index 7cde605824d84..9275898c37f06 100644
--- a/packages/editor-ui/src/components/mixins/workflowRun.ts
+++ b/packages/editor-ui/src/components/mixins/workflowRun.ts
@@ -19,6 +19,10 @@ import { showMessage } from '@/components/mixins/showMessage';
import mixins from 'vue-typed-mixins';
import { titleChange } from './titleChange';
+import { mapStores } from 'pinia';
+import { useUIStore } from '@/stores/ui';
+import { useWorkflowsStore } from '@/stores/workflows';
+import { useRootStore } from '@/stores/n8nRootStore';
export const workflowRun = mixins(
externalHooks,
@@ -27,10 +31,17 @@ export const workflowRun = mixins(
showMessage,
titleChange,
).extend({
+ computed: {
+ ...mapStores(
+ useRootStore,
+ useUIStore,
+ useWorkflowsStore,
+ ),
+ },
methods: {
// Starts to executes a workflow on server.
async runWorkflowApi (runData: IStartRunData): Promise {
- if (this.$store.getters.pushConnectionActive === false) {
+ if (this.rootStore.pushConnectionActive === false) {
// Do not start if the connection to server is not active
// because then it can not receive the data as it executes.
throw new Error(
@@ -38,25 +49,25 @@ export const workflowRun = mixins(
);
}
- this.$store.commit('setSubworkflowExecutionError', null);
+ this.workflowsStore.subWorkflowExecutionError = null;
- this.$store.commit('addActiveAction', 'workflowRunning');
+ this.uiStore.addActiveAction('workflowRunning');
let response: IExecutionPushResponse;
try {
response = await this.restApi().runWorkflow(runData);
} catch (error) {
- this.$store.commit('removeActiveAction', 'workflowRunning');
+ this.uiStore.removeActiveAction('workflowRunning');
throw error;
}
if (response.executionId !== undefined) {
- this.$store.commit('setActiveExecutionId', response.executionId);
+ this.workflowsStore.activeExecutionId = response.executionId;
}
if (response.waitingForWebhook === true) {
- this.$store.commit('setExecutionWaitingForWebhook', true);
+ this.workflowsStore.executionWaitingForWebhook = true;
}
return response;
@@ -64,7 +75,7 @@ export const workflowRun = mixins(
async runWorkflow (nodeName?: string, source?: string): Promise {
const workflow = this.getCurrentWorkflow();
- if (this.$store.getters.isActionActive('workflowRunning') === true) {
+ if (this.uiStore.isActionActive('workflowRunning')) {
return;
}
@@ -74,7 +85,7 @@ export const workflowRun = mixins(
try {
// Check first if the workflow has any issues before execute it
- const issuesExist = this.$store.getters.nodesIssuesExist;
+ const issuesExist = this.workflowsStore.nodesIssuesExist;
if (issuesExist === true) {
// If issues exist get all of the issues of all nodes
const workflowIssues = this.checkReadyForExecution(workflow, nodeName);
@@ -89,7 +100,7 @@ export const workflowRun = mixins(
for (const nodeName of Object.keys(workflowIssues)) {
nodeIssues = NodeHelpers.nodeIssuesToString(workflowIssues[nodeName]);
let issueNodeType = 'UNKNOWN';
- const issueNode = this.$store.getters.getNodeByName(nodeName);
+ const issueNode = this.workflowsStore.getNodeByName(nodeName);
if (issueNode) {
issueNodeType = issueNode.type;
@@ -138,7 +149,7 @@ export const workflowRun = mixins(
directParentNodes = workflow.getParentNodes(nodeName, 'main', 1);
}
- const runData = this.$store.getters.getWorkflowRunData;
+ const runData = this.workflowsStore.getWorkflowRunData;
let newRunData: IRunData | undefined;
@@ -181,8 +192,8 @@ export const workflowRun = mixins(
startNodes.push(nodeName);
}
- const isNewWorkflow = this.$store.getters.isNewWorkflow;
- const hasWebhookNode = this.$store.getters.currentWorkflowHasWebhookNode;
+ const isNewWorkflow = this.workflowsStore.isNewWorkflow;
+ const hasWebhookNode = this.workflowsStore.currentWorkflowHasWebhookNode;
if (isNewWorkflow && hasWebhookNode) {
await this.saveCurrentWorkflow();
}
@@ -219,7 +230,7 @@ export const workflowRun = mixins(
},
} as IRunExecutionData,
workflowData: {
- id: this.$store.getters.workflowId,
+ id: this.workflowsStore.workflowId,
name: workflowData.name!,
active: workflowData.active!,
createdAt: 0,
@@ -227,7 +238,7 @@ export const workflowRun = mixins(
...workflowData,
},
};
- this.$store.commit('setWorkflowExecutionData', executionData);
+ this.workflowsStore.setWorkflowExecutionData(executionData);
this.updateNodesExecutionIssues();
const runWorkflowApiResponse = await this.runWorkflowApi(startRunData);
diff --git a/packages/editor-ui/src/constants.ts b/packages/editor-ui/src/constants.ts
index 3fa9c5912f1fa..2c377d1aa884e 100644
--- a/packages/editor-ui/src/constants.ts
+++ b/packages/editor-ui/src/constants.ts
@@ -410,3 +410,15 @@ export const CURL_IMPORT_NODES_PROTOCOLS: { [key: string]: string } = {
'imap': 'IMAP',
'imaps': 'IMAP',
};
+
+export enum STORES {
+ COMMUNITY_NODES = 'communityNodes',
+ ROOT = 'root',
+ SETTINGS = 'settings',
+ UI = 'ui',
+ USERS = 'users',
+ WORKFLOWS = 'workflows',
+ NDV = 'ndv',
+ TEMPLATES = 'templates',
+ NODE_TYPES = 'nodeTypes',
+}
diff --git a/packages/editor-ui/src/main.ts b/packages/editor-ui/src/main.ts
index de091b8dcba8d..013b9ecd97301 100644
--- a/packages/editor-ui/src/main.ts
+++ b/packages/editor-ui/src/main.ts
@@ -22,6 +22,8 @@ import { runExternalHook } from './components/mixins/externalHooks';
import { TelemetryPlugin } from './plugins/telemetry';
import { I18nPlugin, i18nInstance } from './plugins/i18n';
+import { createPinia, PiniaVuePlugin } from 'pinia';
+
import { store } from './store';
Vue.config.productionTip = false;
@@ -31,11 +33,15 @@ router.afterEach((to, from) => {
Vue.use(TelemetryPlugin);
Vue.use((vue) => I18nPlugin(vue, store));
+Vue.use(PiniaVuePlugin);
+
+const pinia = createPinia();
new Vue({
i18n: i18nInstance,
router,
store,
+ pinia,
render: h => h(App),
}).$mount('#app');
diff --git a/packages/editor-ui/src/modules/communityNodes.ts b/packages/editor-ui/src/modules/communityNodes.ts
deleted file mode 100644
index 0794fa3e6a160..0000000000000
--- a/packages/editor-ui/src/modules/communityNodes.ts
+++ /dev/null
@@ -1,87 +0,0 @@
-import { getInstalledCommunityNodes, installNewPackage, uninstallPackage, updatePackage } from '@/api/communityNodes';
-import { getAvailableCommunityPackageCount } from '@/api/settings';
-import { ICommunityNodesState, ICommunityPackageMap, IRootState } from '@/Interface';
-import { PublicInstalledPackage } from 'n8n-workflow';
-import Vue from 'vue';
-import { ActionContext, Module } from 'vuex';
-
-const LOADER_DELAY = 300;
-
-const module: Module = {
- namespaced: true,
- state: {
- // -1 means that package count has not been fetched yet
- availablePackageCount: -1,
- installedPackages: {},
- },
- mutations: {
- setAvailablePackageCount: (state: ICommunityNodesState, count: number) => {
- state.availablePackageCount = count;
- },
- setInstalledPackages: (state: ICommunityNodesState, packages: PublicInstalledPackage[]) => {
- state.installedPackages = packages.reduce((packageMap: ICommunityPackageMap, pack: PublicInstalledPackage) => {
- packageMap[pack.packageName] = pack;
- return packageMap;
- }, {});
- },
- removePackageByName(state: ICommunityNodesState, name: string) {
- Vue.delete(state.installedPackages, name);
- },
- updatePackageObject(state: ICommunityNodesState, newPackage: PublicInstalledPackage) {
- state.installedPackages[newPackage.packageName] = newPackage;
- },
- },
- getters: {
- availablePackageCount(state: ICommunityNodesState): number {
- return state.availablePackageCount;
- },
- getInstalledPackages(state: ICommunityNodesState): PublicInstalledPackage[] {
- return Object.values(state.installedPackages).sort((a, b) => a.packageName.localeCompare(b.packageName));
- },
- getInstalledPackageByName(state: ICommunityNodesState) {
- return (name: string) => state.installedPackages[name];
- },
- },
- actions: {
- async fetchAvailableCommunityPackageCount(context: ActionContext) {
- if(context.state.availablePackageCount === -1) {
- const packageCount = await getAvailableCommunityPackageCount();
- context.commit('setAvailablePackageCount', packageCount);
- }
- },
- async fetchInstalledPackages(context: ActionContext) {
- const installedPackages = await getInstalledCommunityNodes(context.rootGetters.getRestApiContext);
- context.commit('setInstalledPackages', installedPackages);
- const timeout = installedPackages.length > 0 ? 0 : LOADER_DELAY;
- setTimeout(() => {
- }, timeout);
- },
- async installPackage(context: ActionContext, packageName: string) {
- try {
- await installNewPackage(context.rootGetters.getRestApiContext, packageName);
- await context.dispatch('communityNodes/fetchInstalledPackages');
- } catch(error) {
- throw(error);
- }
- },
- async uninstallPackage(context: ActionContext, packageName: string) {
- try {
- await uninstallPackage(context.rootGetters.getRestApiContext, packageName);
- context.commit('removePackageByName', packageName);
- } catch(error) {
- throw(error);
- }
- },
- async updatePackage(context: ActionContext, packageName: string) {
- try {
- const packageToUpdate = context.getters.getInstalledPackageByName(packageName);
- const updatedPackage = await updatePackage(context.rootGetters.getRestApiContext, packageToUpdate.packageName);
- context.commit('updatePackageObject', updatedPackage);
- } catch (error) {
- throw(error);
- }
- },
- },
-};
-
-export default module;
diff --git a/packages/editor-ui/src/modules/credentials.ee.ts b/packages/editor-ui/src/modules/credentials.ee.ts
index e99e036a67ef0..293937c3e88ec 100644
--- a/packages/editor-ui/src/modules/credentials.ee.ts
+++ b/packages/editor-ui/src/modules/credentials.ee.ts
@@ -6,6 +6,8 @@ import {
} from '../Interface';
import {setCredentialSharedWith} from "@/api/credentials.ee";
import {EnterpriseEditionFeature} from "@/constants";
+import { useSettingsStore } from '@/stores/settings';
+import { useRootStore } from '@/stores/n8nRootStore';
export const credentialsEEModule: Module = {
mutations: {
@@ -33,9 +35,9 @@ export const credentialsEEModule: Module = {
},
actions: {
setCredentialSharedWith: async (context: ActionContext, payload: { sharedWith: IUser[]; credentialId: string; }) => {
- if (context.rootGetters['settings/isEnterpriseFeatureEnabled'](EnterpriseEditionFeature.Sharing)) {
+ if(useSettingsStore().isEnterpriseFeatureEnabled(EnterpriseEditionFeature.Sharing)) {
await setCredentialSharedWith(
- context.rootGetters.getRestApiContext,
+ useRootStore().getRestApiContext,
payload.credentialId,
{
shareWithIds: payload.sharedWith.map((sharee) => sharee.id),
diff --git a/packages/editor-ui/src/modules/credentials.ts b/packages/editor-ui/src/modules/credentials.ts
index 9922ae0186990..05aad2575e9ba 100644
--- a/packages/editor-ui/src/modules/credentials.ts
+++ b/packages/editor-ui/src/modules/credentials.ts
@@ -31,6 +31,10 @@ import { getAppNameFromCredType } from '@/components/helpers';
import {i18n} from "@/plugins/i18n";
import {credentialsEEModule} from "@/modules/credentials.ee";
import {EnterpriseEditionFeature} from "@/constants";
+import { useUsersStore } from '@/stores/users';
+import { useNodeTypesStore } from '@/stores/nodeTypes';
+import { useRootStore } from '@/stores/n8nRootStore';
+import { useSettingsStore } from '@/stores/settings';
const DEFAULT_CREDENTIAL_NAME = 'Unnamed credential';
const DEFAULT_CREDENTIAL_POSTFIX = 'account';
@@ -127,7 +131,8 @@ const module: Module = {
},
getNodesWithAccess (state: ICredentialsState, getters: any, rootState: IRootState, rootGetters: any) { // tslint:disable-line:no-any
return (credentialTypeName: string) => {
- const allLatestNodeTypes: INodeTypeDescription[] = rootGetters['nodeTypes/allLatestNodeTypes'];
+ const nodeTypesStore = useNodeTypesStore();
+ const allLatestNodeTypes: INodeTypeDescription[] = nodeTypesStore.allLatestNodeTypes;
return allLatestNodeTypes.filter((nodeType: INodeTypeDescription) => {
if (!nodeType.credentials) {
@@ -187,28 +192,34 @@ const module: Module = {
if (context.getters.allCredentialTypes.length > 0 && forceFetch !== true) {
return;
}
- const credentialTypes = await getCredentialTypes(context.rootGetters.getRestApiContext);
+ const rootStore = useRootStore();
+ const credentialTypes = await getCredentialTypes(rootStore.getRestApiContext);
context.commit('setCredentialTypes', credentialTypes);
},
fetchAllCredentials: async (context: ActionContext): Promise => {
- const credentials = await getAllCredentials(context.rootGetters.getRestApiContext);
+ const rootStore = useRootStore();
+ const credentials = await getAllCredentials(rootStore.getRestApiContext);
context.commit('setCredentials', credentials);
return credentials;
},
fetchForeignCredentials: async (context: ActionContext): Promise => {
- const credentials = await getForeignCredentials(context.rootGetters.getRestApiContext);
+ const rootStore = useRootStore();
+ const credentials = await getForeignCredentials(rootStore.getRestApiContext);
context.commit('setForeignCredentials', credentials);
return credentials;
},
getCredentialData: async (context: ActionContext, { id }: {id: string}) => {
- return await getCredentialData(context.rootGetters.getRestApiContext, id);
+ const rootStore = useRootStore();
+ return await getCredentialData(rootStore.getRestApiContext, id);
},
createNewCredential: async (context: ActionContext, data: ICredentialsDecrypted) => {
- const credential = await createNewCredential(context.rootGetters.getRestApiContext, data);
+ const rootStore = useRootStore();
+ const settingsStore = useSettingsStore();
+ const credential = await createNewCredential(rootStore.getRestApiContext, data);
- if (context.rootGetters['settings/isEnterpriseFeatureEnabled'](EnterpriseEditionFeature.Sharing)) {
+ if (settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.Sharing)) {
context.commit('upsertCredential', credential);
if (data.ownedBy) {
@@ -217,7 +228,8 @@ const module: Module = {
ownedBy: data.ownedBy,
});
- if (data.sharedWith && data.ownedBy.id === context.rootGetters['users/currentUserId']) {
+ const usersStore = useUsersStore();
+ if (data.sharedWith && data.ownedBy.id === usersStore.currentUserId) {
await context.dispatch('setCredentialSharedWith', {
credentialId: credential.id,
sharedWith: data.sharedWith,
@@ -232,9 +244,11 @@ const module: Module = {
},
updateCredential: async (context: ActionContext, params: {data: ICredentialsDecrypted, id: string}) => {
const { id, data } = params;
- const credential = await updateCredential(context.rootGetters.getRestApiContext, id, data);
+ const rootStore = useRootStore();
+ const settingsStore = useSettingsStore();
+ const credential = await updateCredential(rootStore.getRestApiContext, id, data);
- if (context.rootGetters['settings/isEnterpriseFeatureEnabled'](EnterpriseEditionFeature.Sharing)) {
+ if (settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.Sharing)) {
context.commit('upsertCredential', credential);
if (data.ownedBy) {
@@ -243,7 +257,8 @@ const module: Module = {
ownedBy: data.ownedBy,
});
- if (data.sharedWith && data.ownedBy.id === context.rootGetters['users/currentUserId']) {
+ const usersStore = useUsersStore();
+ if (data.sharedWith && data.ownedBy.id === usersStore.currentUserId) {
await context.dispatch('setCredentialSharedWith', {
credentialId: credential.id,
sharedWith: data.sharedWith,
@@ -257,19 +272,23 @@ const module: Module = {
return credential;
},
deleteCredential: async (context: ActionContext, { id }: {id: string}) => {
- const deleted = await deleteCredential(context.rootGetters.getRestApiContext, id);
+ const rootStore = useRootStore();
+ const deleted = await deleteCredential(rootStore.getRestApiContext, id);
if (deleted) {
context.commit('deleteCredential', id);
}
},
oAuth2Authorize: async (context: ActionContext, data: ICredentialsResponse) => {
- return oAuth2CredentialAuthorize(context.rootGetters.getRestApiContext, data);
+ const rootStore = useRootStore();
+ return oAuth2CredentialAuthorize(rootStore.getRestApiContext, data);
},
oAuth1Authorize: async (context: ActionContext, data: ICredentialsResponse) => {
- return oAuth1CredentialAuthorize(context.rootGetters.getRestApiContext, data);
+ const rootStore = useRootStore();
+ return oAuth1CredentialAuthorize(rootStore.getRestApiContext, data);
},
testCredential: async (context: ActionContext, data: ICredentialsDecrypted): Promise => {
- return testCredential(context.rootGetters.getRestApiContext, { credentials: data });
+ const rootStore = useRootStore();
+ return testCredential(rootStore.getRestApiContext, { credentials: data });
},
getNewCredentialName: async (context: ActionContext, params: { credentialTypeName: string }) => {
try {
@@ -280,8 +299,8 @@ const module: Module = {
newName = getAppNameFromCredType(displayName);
newName = newName.length > 0 ? `${newName} ${DEFAULT_CREDENTIAL_POSTFIX}` : DEFAULT_CREDENTIAL_NAME;
}
-
- const res = await getCredentialsNewName(context.rootGetters.getRestApiContext, newName);
+ const rootStore = useRootStore();
+ const res = await getCredentialsNewName(rootStore.getRestApiContext, newName);
return res.name;
} catch (e) {
return DEFAULT_CREDENTIAL_NAME;
diff --git a/packages/editor-ui/src/modules/ndv.ts b/packages/editor-ui/src/modules/ndv.ts
deleted file mode 100644
index 707b5b78dfacc..0000000000000
--- a/packages/editor-ui/src/modules/ndv.ts
+++ /dev/null
@@ -1,170 +0,0 @@
-import Vue from 'vue';
-import { Module } from 'vuex';
-import {
- IRootState,
- IRunDataDisplayMode,
- NDVState,
- XYPosition,
- IExecutionResponse,
- INodeUi,
-} from '../Interface';
-
-const module: Module = {
- namespaced: true,
- state: {
- activeNodeName: null,
- mainPanelDimensions: {},
- sessionId: '',
- input: {
- displayMode: 'table',
- nodeName: undefined,
- run: undefined,
- branch: undefined,
- data: {
- isEmpty: true,
- },
- },
- output: {
- displayMode: 'table',
- branch: undefined,
- data: {
- isEmpty: true,
- },
- editMode: {
- enabled: false,
- value: '',
- },
- },
- focusedMappableInput: '',
- mappingTelemetry: {},
- hoveringItem: null,
- draggable: {
- isDragging: false,
- type: '',
- data: '',
- canDrop: false,
- stickyPosition: null,
- },
- },
- getters: {
- activeNodeName: (state: NDVState) => state.activeNodeName,
- activeNode: (state, getters, rootState, rootGetters): INodeUi | null => {
- return rootGetters.getNodeByName(state.activeNodeName);
- },
- ndvInputData: (state: NDVState, getters, rootState: IRootState, rootGetters) => {
- const executionData = rootGetters.getWorkflowExecution as IExecutionResponse | null;
- const inputNodeName: string | undefined = state.input.nodeName;
- const inputRunIndex: number = state.input.run ?? 0;
- const inputBranchIndex: number = state.input.branch?? 0;
-
- if (!executionData || !inputNodeName || inputRunIndex === undefined || inputBranchIndex === undefined) {
- return [];
- }
-
- return executionData.data?.resultData?.runData?.[inputNodeName]?.[inputRunIndex]?.data?.main?.[inputBranchIndex];
- },
- ndvSessionId: (state: NDVState): string => state.sessionId,
- getPanelDisplayMode: (state: NDVState) => {
- return (panel: 'input' | 'output') => state[panel].displayMode;
- },
- inputPanelDisplayMode: (state: NDVState) => state.input.displayMode,
- outputPanelDisplayMode: (state: NDVState) => state.output.displayMode,
- outputPanelEditMode: (state: NDVState): NDVState['output']['editMode'] => state.output.editMode,
- focusedMappableInput: (state: NDVState) => state.focusedMappableInput,
- isDraggableDragging: (state: NDVState) => state.draggable.isDragging,
- draggableType: (state: NDVState) => state.draggable.type,
- draggableData: (state: NDVState) => state.draggable.data,
- canDraggableDrop: (state: NDVState) => state.draggable.canDrop,
- mainPanelDimensions: (state: NDVState) => (panelType: string) => {
- const defaults = { relativeRight: 1, relativeLeft: 1, relativeWidth: 1 };
-
- return {...defaults, ...state.mainPanelDimensions[panelType]};
- },
- draggableStickyPos: (state: NDVState) => state.draggable.stickyPosition,
- mappingTelemetry: (state: NDVState) => state.mappingTelemetry,
- hoveringItem: (state: NDVState) => state.hoveringItem,
- ndvInputNodeName: (state: NDVState) => state.input.nodeName,
- ndvInputRunIndex: (state: NDVState) => state.input.run,
- ndvInputBranchIndex: (state: NDVState) => state.input.branch,
- getNDVDataIsEmpty: (state: NDVState) => (panel: 'input' | 'output'): boolean => state[panel].data.isEmpty,
- },
- mutations: {
- setActiveNodeName(state, nodeName: string) {
- state.activeNodeName = nodeName;
- },
- setInputNodeName: (state: NDVState, name: string | undefined) => {
- Vue.set(state.input, 'nodeName', name);
- },
- setInputRunIndex: (state: NDVState, run?: string) => {
- Vue.set(state.input, 'run', run);
- },
- setMainPanelDimensions: (state: NDVState, params: { panelType:string, dimensions: { relativeLeft?: number, relativeRight?: number, relativeWidth?: number }}) => {
- Vue.set(
- state.mainPanelDimensions,
- params.panelType,
- {...state.mainPanelDimensions[params.panelType], ...params.dimensions },
- );
- },
- setNDVSessionId: (state: NDVState) => {
- Vue.set(state, 'sessionId', `ndv-${Math.random().toString(36).slice(-8)}`);
- },
- resetNDVSessionId: (state: NDVState) => {
- Vue.set(state, 'sessionId', '');
- },
- setPanelDisplayMode: (state: NDVState, params: {pane: 'input' | 'output', mode: IRunDataDisplayMode}) => {
- Vue.set(state[params.pane], 'displayMode', params.mode);
- },
- setOutputPanelEditModeEnabled: (state: NDVState, payload: boolean) => {
- Vue.set(state.output.editMode, 'enabled', payload);
- },
- setOutputPanelEditModeValue: (state: NDVState, payload: string) => {
- Vue.set(state.output.editMode, 'value', payload);
- },
- setMappableNDVInputFocus(state: NDVState, paramName: string) {
- Vue.set(state, 'focusedMappableInput', paramName);
- },
- draggableStartDragging(state: NDVState, {type, data}: {type: string, data: string}) {
- state.draggable = {
- isDragging: true,
- type,
- data,
- canDrop: false,
- stickyPosition: null,
- };
- },
- draggableStopDragging(state: NDVState) {
- state.draggable = {
- isDragging: false,
- type: '',
- data: '',
- canDrop: false,
- stickyPosition: null,
- };
- },
- setDraggableStickyPos(state: NDVState, position: XYPosition | null) {
- Vue.set(state.draggable, 'stickyPosition', position);
- },
- setDraggableCanDrop(state: NDVState, canDrop: boolean) {
- Vue.set(state.draggable, 'canDrop', canDrop);
- },
- setMappingTelemetry(state: NDVState, telemetry: {[key: string]: string | number | boolean}) {
- state.mappingTelemetry = {...state.mappingTelemetry, ...telemetry};
- },
- resetMappingTelemetry(state: NDVState) {
- state.mappingTelemetry = {};
- },
- setHoveringItem(state: NDVState, item: null | NDVState['hoveringItem']) {
- Vue.set(state, 'hoveringItem', item);
- },
- setNDVBranchIndex(state: NDVState, e: {pane: 'input' | 'output', branchIndex: number}) {
- Vue.set(state[e.pane], 'branch', e.branchIndex);
- },
- setNDVPanelDataIsEmpty(state: NDVState, payload: {panel: 'input' | 'output', isEmpty: boolean}) {
- Vue.set(state[payload.panel].data, 'isEmpty', payload.isEmpty);
- },
- },
- actions: {
- },
-};
-
-export default module;
diff --git a/packages/editor-ui/src/modules/nodeTypes.ts b/packages/editor-ui/src/modules/nodeTypes.ts
deleted file mode 100644
index 6aa777a9c9d5b..0000000000000
--- a/packages/editor-ui/src/modules/nodeTypes.ts
+++ /dev/null
@@ -1,180 +0,0 @@
-import Vue from 'vue';
-import { ActionContext, Module } from 'vuex';
-import type {
- ILoadOptions,
- INodeCredentials,
- INodeListSearchResult,
- INodeParameters,
- INodeTypeDescription,
- INodeTypeNameVersion,
-} from 'n8n-workflow';
-
-import { DEFAULT_NODETYPE_VERSION } from '@/constants';
-import { addHeaders, addNodeTranslation } from '@/plugins/i18n';
-import {
- getNodeParameterOptions,
- getNodesInformation,
- getNodeTranslationHeaders,
- getNodeTypes,
- getResourceLocatorResults,
-} from '@/api/nodeTypes';
-import { omit } from '@/utils';
-import type { IRootState, INodeTypesState, ICategoriesWithNodes, INodeCreateElement, IResourceLocatorReqParams } from '../Interface';
-import { getCategoriesWithNodes, getCategorizedList } from './nodeTypesHelpers';
-
-const module: Module = {
- namespaced: true,
- state: {
- nodeTypes: {},
- },
- getters: {
- allNodeTypes: (state): INodeTypeDescription[] => {
- return Object.values(state.nodeTypes).reduce((allNodeTypes, nodeType) => {
- const versionNumbers = Object.keys(nodeType).map(Number);
- const allNodeVersions = versionNumbers.map(version => nodeType[version]);
-
- return [...allNodeTypes, ...allNodeVersions];
- }, []);
- },
- allLatestNodeTypes: (state): INodeTypeDescription[] => {
- return Object.values(state.nodeTypes).reduce((allLatestNodeTypes, nodeVersions) => {
- const versionNumbers = Object.keys(nodeVersions).map(Number);
- const latestNodeVersion = nodeVersions[Math.max(...versionNumbers)];
-
- if (!latestNodeVersion) return allLatestNodeTypes;
-
- return [...allLatestNodeTypes, latestNodeVersion];
- }, []);
- },
- getNodeType: (state) => (nodeTypeName: string, version?: number): INodeTypeDescription | null => {
- const nodeVersions = state.nodeTypes[nodeTypeName];
-
- if (!nodeVersions) return null;
-
- const versionNumbers = Object.keys(nodeVersions).map(Number);
- const nodeType = nodeVersions[version || Math.max(...versionNumbers)];
-
- return nodeType || null;
- },
- isTriggerNode: (state, getters) => (nodeTypeName: string) => {
- const nodeType = getters.getNodeType(nodeTypeName);
- return !!(nodeType && nodeType.group.includes('trigger'));
- },
- visibleNodeTypes: (state, getters): INodeTypeDescription[] => {
- return getters.allLatestNodeTypes.filter((nodeType: INodeTypeDescription) => !nodeType.hidden);
- },
- categoriesWithNodes: (state, getters, rootState, rootGetters): ICategoriesWithNodes => {
- return getCategoriesWithNodes(getters.visibleNodeTypes, rootGetters['users/personalizedNodeTypes']);
- },
- categorizedItems: (state, getters): INodeCreateElement[] => {
- return getCategorizedList(getters.categoriesWithNodes);
- },
- },
- mutations: {
- setNodeTypes(state, newNodeTypes: INodeTypeDescription[] = []) {
- const nodeTypes = newNodeTypes.reduce>>((acc, newNodeType) => {
- const newNodeVersions = getNodeVersions(newNodeType);
-
- if (newNodeVersions.length === 0) {
- const singleVersion = { [DEFAULT_NODETYPE_VERSION]: newNodeType };
-
- acc[newNodeType.name] = singleVersion;
- return acc;
- }
-
- for (const version of newNodeVersions) {
- if (acc[newNodeType.name]) {
- acc[newNodeType.name][version] = newNodeType;
- } else {
- acc[newNodeType.name] = { [version]: newNodeType };
- }
- }
-
- return acc;
- }, { ...state.nodeTypes });
-
- Vue.set(state, 'nodeTypes', nodeTypes);
- },
- removeNodeTypes(state, nodeTypesToRemove: INodeTypeDescription[]) {
- state.nodeTypes = nodeTypesToRemove.reduce(
- (oldNodes, newNodeType) => omit(newNodeType.name, oldNodes),
- state.nodeTypes,
- );
- },
- },
- actions: {
- async getFullNodesProperties(
- context: ActionContext,
- nodesToBeFetched: INodeTypeNameVersion[],
- ) {
- await context.dispatch('credentials/fetchCredentialTypes', true);
-
- const nodesInformation = await context.dispatch(
- 'getNodesInformation',
- nodesToBeFetched,
- );
-
- context.commit('setNodeTypes', nodesInformation);
- },
- async getNodeTypes(context: ActionContext) {
- const nodeTypes = await getNodeTypes(context.rootGetters.getRestApiContext);
- if (nodeTypes.length) {
- context.commit('setNodeTypes', nodeTypes);
- }
- },
- async getNodeTranslationHeaders(context: ActionContext) {
- const headers = await getNodeTranslationHeaders(context.rootGetters.getRestApiContext);
-
- if (headers) {
- addHeaders(headers, context.rootGetters.defaultLocale);
- }
- },
- async getNodesInformation(
- context: ActionContext,
- nodeInfos: INodeTypeNameVersion[],
- ) {
- const nodesInformation = await getNodesInformation(
- context.rootGetters.getRestApiContext,
- nodeInfos,
- );
-
- nodesInformation.forEach(nodeInformation => {
- if (nodeInformation.translation) {
- const nodeType = nodeInformation.name.replace('n8n-nodes-base.', '');
-
- addNodeTranslation(
- { [nodeType]: nodeInformation.translation },
- context.getters.defaultLocale,
- );
- }
- });
-
- context.commit('setNodeTypes', nodesInformation);
- },
- async getNodeParameterOptions(
- context: ActionContext,
- sendData: {
- nodeTypeAndVersion: INodeTypeNameVersion,
- path: string,
- methodName?: string,
- loadOptions?: ILoadOptions,
- currentNodeParameters: INodeParameters,
- credentials?: INodeCredentials,
- },
- ) {
- return getNodeParameterOptions(context.rootGetters.getRestApiContext, sendData);
- },
- async getResourceLocatorResults(
- context: ActionContext,
- sendData: IResourceLocatorReqParams,
- ): Promise {
- return getResourceLocatorResults(context.rootGetters.getRestApiContext, sendData);
- },
- },
-};
-
-function getNodeVersions(nodeType: INodeTypeDescription) {
- return Array.isArray(nodeType.version) ? nodeType.version : [nodeType.version];
-}
-
-export default module;
diff --git a/packages/editor-ui/src/modules/settings.ts b/packages/editor-ui/src/modules/settings.ts
deleted file mode 100644
index 68ea3b578cc7d..0000000000000
--- a/packages/editor-ui/src/modules/settings.ts
+++ /dev/null
@@ -1,243 +0,0 @@
-import { ActionContext, Module } from 'vuex';
-import {
- ILogLevel,
- IN8nPrompts,
- IN8nUISettings,
- IN8nValueSurveyData,
- IRootState,
- ISettingsState,
- WorkflowCallerPolicyDefaultOption,
-} from '../Interface';
-import { getPromptsData, submitValueSurvey, submitContactInfo, getSettings } from '../api/settings';
-import Vue from 'vue';
-import {CONTACT_PROMPT_MODAL_KEY, EnterpriseEditionFeature, VALUE_SURVEY_MODAL_KEY} from '@/constants';
-import { ITelemetrySettings } from 'n8n-workflow';
-import { testHealthEndpoint } from '@/api/templates';
-import {createApiKey, deleteApiKey, getApiKey } from "@/api/api-keys";
-
-const module: Module = {
- namespaced: true,
- state: {
- settings: {} as IN8nUISettings,
- promptsData: {} as IN8nPrompts,
- userManagement: {
- enabled: false,
- showSetupOnFirstLoad: false,
- smtpSetup: false,
- },
- templatesEndpointHealthy: false,
- api: {
- enabled: false,
- latestVersion: 0,
- path: '/',
- },
- onboardingCallPromptEnabled: false,
- },
- getters: {
- isEnterpriseFeatureEnabled: (state: ISettingsState) => (feature: EnterpriseEditionFeature): boolean => {
- return state.settings.enterprise[feature];
- },
- versionCli(state: ISettingsState) {
- return state.settings.versionCli;
- },
- isUserManagementEnabled(state: ISettingsState): boolean {
- return state.userManagement.enabled;
- },
- isPublicApiEnabled(state: ISettingsState): boolean {
- return state.api.enabled;
- },
- publicApiLatestVersion(state: ISettingsState): number {
- return state.api.latestVersion;
- },
- publicApiPath(state: ISettingsState): string {
- return state.api.path;
- },
- showSetupPage(state: ISettingsState) {
- return state.userManagement.showSetupOnFirstLoad;
- },
- getPromptsData(state: ISettingsState) {
- return state.promptsData;
- },
- isDesktopDeployment(state: ISettingsState) {
- return state.settings.deployment?.type.startsWith('desktop_');
- },
- isCloudDeployment(state: ISettingsState) {
- return state.settings.deployment && state.settings.deployment.type === 'cloud';
- },
- isSmtpSetup(state: ISettingsState) {
- return state.userManagement.smtpSetup;
- },
- isPersonalizationSurveyEnabled(state: ISettingsState) {
- return state.settings.telemetry.enabled && state.settings.personalizationSurveyEnabled;
- },
- telemetry: (state): ITelemetrySettings => {
- return state.settings.telemetry;
- },
- logLevel: (state): ILogLevel => {
- return state.settings.logLevel;
- },
- isTelemetryEnabled: (state) => {
- return state.settings.telemetry && state.settings.telemetry.enabled;
- },
- areTagsEnabled: (state) => {
- return state.settings.workflowTagsDisabled !== undefined ? !state.settings.workflowTagsDisabled : true;
- },
- isHiringBannerEnabled: (state): boolean => {
- return state.settings.hiringBannerEnabled;
- },
- isTemplatesEnabled: (state): boolean => {
- return Boolean(state.settings.templates && state.settings.templates.enabled);
- },
- isTemplatesEndpointReachable: (state): boolean => {
- return state.templatesEndpointHealthy;
- },
- templatesHost: (state): string => {
- return state.settings.templates.host;
- },
- isOnboardingCallPromptFeatureEnabled: (state): boolean => {
- return state.onboardingCallPromptEnabled;
- },
- isCommunityNodesFeatureEnabled: (state): boolean => {
- return state.settings.communityNodesEnabled;
- },
- isNpmAvailable: (state): boolean => {
- return state.settings.isNpmAvailable;
- },
- allowedModules: (state): { builtIn?: string[]; external?: string[] } => {
- return state.settings.allowedModules;
- },
- isQueueModeEnabled: (state): boolean => {
- return state.settings.executionMode === 'queue';
- },
- workflowCallerPolicyDefaultOption: (state): WorkflowCallerPolicyDefaultOption => {
- return state.settings.workflowCallerPolicyDefaultOption;
- },
- isWorkflowSharingEnabled: (state): boolean => {
- return state.settings.isWorkflowSharingEnabled;
- },
- },
- mutations: {
- setSettings(state: ISettingsState, settings: IN8nUISettings) {
- state.settings = settings;
- state.userManagement.enabled = settings.userManagement.enabled;
- state.userManagement.showSetupOnFirstLoad = !!settings.userManagement.showSetupOnFirstLoad;
- state.userManagement.smtpSetup = settings.userManagement.smtpSetup;
- state.api.enabled = settings.publicApi.enabled;
- state.api.latestVersion = settings.publicApi.latestVersion;
- state.api.path = settings.publicApi.path;
- state.onboardingCallPromptEnabled = settings.onboardingCallPromptEnabled;
- },
- stopShowingSetupPage(state: ISettingsState) {
- Vue.set(state.userManagement, 'showSetupOnFirstLoad', false);
- },
- setPromptsData(state: ISettingsState, promptsData: IN8nPrompts) {
- Vue.set(state, 'promptsData', promptsData);
- },
- setTemplatesEndpointHealthy(state: ISettingsState) {
- state.templatesEndpointHealthy = true;
- },
- setCommunityNodesFeatureEnabled(state: ISettingsState, isEnabled: boolean) {
- state.settings.communityNodesEnabled = isEnabled;
- },
- setIsWorkflowSharingEnabled(state: ISettingsState, enabled: boolean) {
- state.settings.isWorkflowSharingEnabled = enabled;
- },
- setWorkflowCallerPolicyDefaultOption(state: ISettingsState, defaultOption: WorkflowCallerPolicyDefaultOption) {
- state.settings.workflowCallerPolicyDefaultOption = defaultOption;
- },
- setAllowedModules(state, allowedModules: { builtIn?: string, external?: string }) {
- state.settings.allowedModules = {
- ...(allowedModules.builtIn && { builtIn: allowedModules.builtIn.split(',') }),
- ...(allowedModules.external && { external: allowedModules.external.split(',') }),
- };
- },
- },
- actions: {
- async getSettings(context: ActionContext) {
- const settings = await getSettings(context.rootGetters.getRestApiContext);
- context.commit('setSettings', settings);
-
- // todo refactor to this store
- context.commit('setUrlBaseWebhook', settings.urlBaseWebhook, {root: true});
- context.commit('setUrlBaseEditor', settings.urlBaseEditor, {root: true});
- context.commit('setEndpointWebhook', settings.endpointWebhook, {root: true});
- context.commit('setEndpointWebhookTest', settings.endpointWebhookTest, {root: true});
- context.commit('setSaveDataErrorExecution', settings.saveDataErrorExecution, {root: true});
- context.commit('setSaveDataSuccessExecution', settings.saveDataSuccessExecution, {root: true});
- context.commit('setSaveManualExecutions', settings.saveManualExecutions, {root: true});
- context.commit('setTimezone', settings.timezone, {root: true});
- context.commit('setExecutionTimeout', settings.executionTimeout, {root: true});
- context.commit('setMaxExecutionTimeout', settings.maxExecutionTimeout, {root: true});
- context.commit('setVersionCli', settings.versionCli, {root: true});
- context.commit('setInstanceId', settings.instanceId, {root: true});
- context.commit('setOauthCallbackUrls', settings.oauthCallbackUrls, {root: true});
- context.commit('setN8nMetadata', settings.n8nMetadata || {}, {root: true});
- context.commit('setDefaultLocale', settings.defaultLocale, {root: true});
- context.commit('setIsNpmAvailable', settings.isNpmAvailable, {root: true});
- context.commit('versions/setVersionNotificationSettings', settings.versionNotifications, {root: true});
- context.commit('setCommunityNodesFeatureEnabled', settings.communityNodesEnabled === true);
- context.commit('settings/setAllowedModules', settings.allowedModules, {root: true});
- context.commit('settings/setWorkflowCallerPolicyDefaultOption', settings.workflowCallerPolicyDefaultOption, {root: true});
- context.commit('settings/setIsWorkflowSharingEnabled', settings.enterprise.workflowSharing, {root: true});
- },
- async fetchPromptsData(context: ActionContext) {
- if (!context.getters.isTelemetryEnabled) {
- return;
- }
-
- try {
- const instanceId = context.state.settings.instanceId;
- const userId = context.rootGetters['users/currentUserId'];
- const promptsData: IN8nPrompts = await getPromptsData(instanceId, userId);
-
- if (promptsData && promptsData.showContactPrompt) {
- context.commit('ui/openModal', CONTACT_PROMPT_MODAL_KEY, {root: true});
- } else if (promptsData && promptsData.showValueSurvey) {
- context.commit('ui/openModal', VALUE_SURVEY_MODAL_KEY, {root: true});
- }
-
- context.commit('setPromptsData', promptsData);
- } catch (e) {
- return e;
- }
-
- },
- async submitContactInfo(context: ActionContext, email: string) {
- try {
- const instanceId = context.state.settings.instanceId;
- const userId = context.rootGetters['users/currentUserId'];
- return await submitContactInfo(instanceId, userId, email);
- } catch (e) {
- return e;
- }
- },
-
- async submitValueSurvey(context: ActionContext, params: IN8nValueSurveyData) {
- try {
- const instanceId = context.state.settings.instanceId;
- const userId = context.rootGetters['users/currentUserId'];
- return await submitValueSurvey(instanceId, userId, params);
- } catch (e) {
- return e;
- }
- },
- async testTemplatesEndpoint(context: ActionContext) {
- const timeout = new Promise((_, reject) => setTimeout(() => reject(), 2000));
- await Promise.race([testHealthEndpoint(context.getters.templatesHost), timeout]);
- context.commit('setTemplatesEndpointHealthy', true);
- },
- async getApiKey(context: ActionContext) {
- const { apiKey } = await getApiKey(context.rootGetters['getRestApiContext']);
- return apiKey;
- },
- async createApiKey(context: ActionContext) {
- const { apiKey } = await createApiKey(context.rootGetters['getRestApiContext']);
- return apiKey;
- },
- async deleteApiKey(context: ActionContext) {
- await deleteApiKey(context.rootGetters['getRestApiContext']);
- },
- },
-};
-
-export default module;
diff --git a/packages/editor-ui/src/modules/tags.ts b/packages/editor-ui/src/modules/tags.ts
index 52063607c6375..1430ed440d45c 100644
--- a/packages/editor-ui/src/modules/tags.ts
+++ b/packages/editor-ui/src/modules/tags.ts
@@ -6,6 +6,8 @@ import {
} from '../Interface';
import { createTag, deleteTag, getTags, updateTag } from '../api/tags';
import Vue from 'vue';
+import { useWorkflowsStore } from '@/stores/workflows';
+import { useRootStore } from '@/stores/n8nRootStore';
const module: Module = {
namespaced: true,
@@ -71,30 +73,35 @@ const module: Module = {
}
context.commit('setLoading', true);
- const tags = await getTags(context.rootGetters.getRestApiContext, Boolean(withUsageCount));
+ const rootStore = useRootStore();
+ const tags = await getTags(rootStore.getRestApiContext, Boolean(withUsageCount));
context.commit('setAllTags', tags);
context.commit('setLoading', false);
return tags;
},
create: async (context: ActionContext, name: string): Promise => {
- const tag = await createTag(context.rootGetters.getRestApiContext, { name });
+ const rootStore = useRootStore();
+ const tag = await createTag(rootStore.getRestApiContext, { name });
context.commit('upsertTags', [tag]);
return tag;
},
rename: async (context: ActionContext, { id, name }: { id: string, name: string }) => {
- const tag = await updateTag(context.rootGetters.getRestApiContext, id, { name });
+ const rootStore = useRootStore();
+ const tag = await updateTag(rootStore.getRestApiContext, id, { name });
context.commit('upsertTags', [tag]);
return tag;
},
delete: async (context: ActionContext, id: string) => {
- const deleted = await deleteTag(context.rootGetters.getRestApiContext, id);
+ const rootStore = useRootStore();
+ const deleted = await deleteTag(rootStore.getRestApiContext, id);
if (deleted) {
context.commit('deleteTag', id);
- context.commit('removeWorkflowTagId', id, {root: true});
+ const workflowsStore = useWorkflowsStore();
+ workflowsStore.removeWorkflowTagId(id);
}
return deleted;
diff --git a/packages/editor-ui/src/modules/templates.ts b/packages/editor-ui/src/modules/templates.ts
deleted file mode 100644
index 44c0c379f9621..0000000000000
--- a/packages/editor-ui/src/modules/templates.ts
+++ /dev/null
@@ -1,282 +0,0 @@
-import { getCategories, getCollectionById, getCollections, getTemplateById, getWorkflows, getWorkflowTemplate } from '@/api/templates';
-import { ActionContext, Module } from 'vuex';
-import {
- IRootState,
- ITemplatesCollection,
- ITemplatesWorkflow,
- ITemplatesCategory,
- ITemplateState,
- ITemplatesQuery,
- ITemplatesWorkflowFull,
- ITemplatesCollectionFull,
- IWorkflowTemplate,
-} from '../Interface';
-
-import Vue from 'vue';
-
-const TEMPLATES_PAGE_SIZE = 10;
-
-function getSearchKey(query: ITemplatesQuery): string {
- return JSON.stringify([query.search || '', [...query.categories].sort()]);
-}
-
-const module: Module = {
- namespaced: true,
- state: {
- categories: {},
- collections: {},
- workflows: {},
- collectionSearches: {},
- workflowSearches: {},
- currentSessionId: '',
- previousSessionId: '',
- },
- getters: {
- allCategories(state: ITemplateState) {
- return Object.values(state.categories).sort((a: ITemplatesCategory, b: ITemplatesCategory) => a.name > b.name ? 1: -1);
- },
- getTemplateById(state: ITemplateState) {
- return (id: string): null | ITemplatesWorkflow => state.workflows[id];
- },
- getCollectionById(state: ITemplateState) {
- return (id: string): null | ITemplatesCollection => state.collections[id];
- },
- getCategoryById(state: ITemplateState) {
- return (id: string): null | ITemplatesCategory => state.categories[id];
- },
- getSearchedCollections(state: ITemplateState) {
- return (query: ITemplatesQuery) => {
- const searchKey = getSearchKey(query);
- const search = state.collectionSearches[searchKey];
- if (!search) {
- return null;
- }
-
- return search.collectionIds.map((collectionId: string) => state.collections[collectionId]);
- };
- },
- getSearchedWorkflows(state: ITemplateState) {
- return (query: ITemplatesQuery) => {
- const searchKey = getSearchKey(query);
- const search = state.workflowSearches[searchKey];
- if (!search) {
- return null;
- }
-
- return search.workflowIds.map((workflowId: string) => state.workflows[workflowId]);
- };
- },
- getSearchedWorkflowsTotal(state: ITemplateState) {
- return (query: ITemplatesQuery) => {
- const searchKey = getSearchKey(query);
- const search = state.workflowSearches[searchKey];
-
- return search ? search.totalWorkflows : 0;
- };
- },
- isSearchLoadingMore(state: ITemplateState) {
- return (query: ITemplatesQuery) => {
- const searchKey = getSearchKey(query);
- const search = state.workflowSearches[searchKey];
-
- return Boolean(search && search.loadingMore);
- };
- },
- isSearchFinished(state: ITemplateState) {
- return (query: ITemplatesQuery) => {
- const searchKey = getSearchKey(query);
- const search = state.workflowSearches[searchKey];
-
- return Boolean(search && !search.loadingMore && search.totalWorkflows === search.workflowIds.length);
- };
- },
- currentSessionId(state: ITemplateState) {
- return state.currentSessionId;
- },
- previousSessionId(state: ITemplateState) {
- return state.previousSessionId;
- },
- },
- mutations: {
- addCategories(state: ITemplateState, categories: ITemplatesCategory[]) {
- categories.forEach((category: ITemplatesCategory) => {
- Vue.set(state.categories, category.id, category);
- });
- },
- addCollections(state: ITemplateState, collections: Array) {
- collections.forEach((collection) => {
- const workflows = (collection.workflows || []).map((workflow) => ({id: workflow.id}));
- const cachedCollection = state.collections[collection.id] || {};
- Vue.set(state.collections, collection.id, {
- ...cachedCollection,
- ...collection,
- workflows,
- });
- });
- },
- addWorkflows(state: ITemplateState, workflows: Array) {
- workflows.forEach((workflow: ITemplatesWorkflow) => {
- const cachedWorkflow = state.workflows[workflow.id] || {};
- Vue.set(state.workflows, workflow.id, {
- ...cachedWorkflow,
- ...workflow,
- });
- });
- },
- addCollectionSearch(state: ITemplateState, data: {collections: ITemplatesCollection[], query: ITemplatesQuery}) {
- const collectionIds = data.collections.map((collection) => collection.id);
- const searchKey = getSearchKey(data.query);
- Vue.set(state.collectionSearches, searchKey, {
- collectionIds,
- });
- },
- addWorkflowsSearch(state: ITemplateState, data: {totalWorkflows: number; workflows: ITemplatesWorkflow[], query: ITemplatesQuery}) {
- const workflowIds = data.workflows.map((workflow) => workflow.id);
- const searchKey = getSearchKey(data.query);
- const cachedResults = state.workflowSearches[searchKey];
- if (!cachedResults) {
- Vue.set(state.workflowSearches, searchKey, {
- workflowIds,
- totalWorkflows: data.totalWorkflows,
- });
-
- return;
- }
-
- Vue.set(state.workflowSearches, searchKey, {
- workflowIds: [...cachedResults.workflowIds, ...workflowIds],
- totalWorkflows: data.totalWorkflows,
- });
- },
- setWorkflowSearchLoading(state: ITemplateState, query: ITemplatesQuery) {
- const searchKey = getSearchKey(query);
- const cachedResults = state.workflowSearches[searchKey];
- if (!cachedResults) {
- return;
- }
-
- Vue.set(state.workflowSearches[searchKey], 'loadingMore', true);
- },
- setWorkflowSearchLoaded(state: ITemplateState, query: ITemplatesQuery) {
- const searchKey = getSearchKey(query);
- const cachedResults = state.workflowSearches[searchKey];
- if (!cachedResults) {
- return;
- }
-
- Vue.set(state.workflowSearches[searchKey], 'loadingMore', false);
- },
- resetSessionId(state: ITemplateState) {
- state.previousSessionId = state.currentSessionId;
- state.currentSessionId = '';
- },
- setSessionId(state: ITemplateState) {
- if (!state.currentSessionId) {
- state.currentSessionId = `templates-${Date.now()}`;
- }
- },
- },
- actions: {
- async getTemplateById(context: ActionContext, templateId: string): Promise {
- const apiEndpoint: string = context.rootGetters['settings/templatesHost'];
- const versionCli: string = context.rootGetters['versionCli'];
- const response = await getTemplateById(apiEndpoint, templateId, { 'n8n-version': versionCli });
- const template: ITemplatesWorkflowFull = {
- ...response.workflow,
- full: true,
- };
-
- context.commit('addWorkflows', [template]);
- return template;
- },
- async getCollectionById(context: ActionContext, collectionId: string): Promise {
- const apiEndpoint: string = context.rootGetters['settings/templatesHost'];
- const versionCli: string = context.rootGetters['versionCli'];
- const response = await getCollectionById(apiEndpoint, collectionId, { 'n8n-version': versionCli });
- const collection: ITemplatesCollectionFull = {
- ...response.collection,
- full: true,
- };
-
- context.commit('addCollections', [collection]);
- context.commit('addWorkflows', response.collection.workflows);
-
- return context.getters.getCollectionById(collectionId);
- },
- async getCategories(context: ActionContext): Promise {
- const cachedCategories: ITemplatesCategory[] = context.getters.allCategories;
- if (cachedCategories.length) {
- return cachedCategories;
- }
- const apiEndpoint: string = context.rootGetters['settings/templatesHost'];
- const versionCli: string = context.rootGetters['versionCli'];
- const response = await getCategories(apiEndpoint, { 'n8n-version': versionCli });
- const categories = response.categories;
-
- context.commit('addCategories', categories);
-
- return categories;
- },
- async getCollections(context: ActionContext, query: ITemplatesQuery): Promise {
- const cachedResults: ITemplatesCollection[] | null = context.getters.getSearchedCollections(query);
- if (cachedResults) {
- return cachedResults;
- }
-
- const apiEndpoint: string = context.rootGetters['settings/templatesHost'];
- const versionCli: string = context.rootGetters['versionCli'];
- const response = await getCollections(apiEndpoint, query, { 'n8n-version': versionCli });
- const collections = response.collections;
-
- context.commit('addCollections', collections);
- context.commit('addCollectionSearch', {query, collections});
- collections.forEach((collection: ITemplatesCollection) => context.commit('addWorkflows', collection.workflows));
-
- return collections;
- },
- async getWorkflows(context: ActionContext, query: ITemplatesQuery): Promise {
- const cachedResults: ITemplatesWorkflow[] = context.getters.getSearchedWorkflows(query);
- if (cachedResults) {
- return cachedResults;
- }
-
- const apiEndpoint: string = context.rootGetters['settings/templatesHost'];
- const versionCli: string = context.rootGetters['versionCli'];
-
- const payload = await getWorkflows(apiEndpoint, {...query, skip: 0, limit: TEMPLATES_PAGE_SIZE}, { 'n8n-version': versionCli });
-
- context.commit('addWorkflows', payload.workflows);
- context.commit('addWorkflowsSearch', {...payload, query});
-
- return context.getters.getSearchedWorkflows(query);
- },
- async getMoreWorkflows(context: ActionContext, query: ITemplatesQuery): Promise {
- if (context.getters.isSearchLoadingMore(query) && !context.getters.isSearchFinished(query)) {
- return [];
- }
- const cachedResults: ITemplatesWorkflow[] = context.getters.getSearchedWorkflows(query) || [];
- const apiEndpoint: string = context.rootGetters['settings/templatesHost'];
-
- context.commit('setWorkflowSearchLoading', query);
- try {
- const payload = await getWorkflows(apiEndpoint, {...query, skip: cachedResults.length, limit: TEMPLATES_PAGE_SIZE});
-
- context.commit('setWorkflowSearchLoaded', query);
- context.commit('addWorkflows', payload.workflows);
- context.commit('addWorkflowsSearch', {...payload, query});
-
- return context.getters.getSearchedWorkflows(query);
- } catch (e) {
- context.commit('setWorkflowSearchLoaded', query);
- throw e;
- }
- },
- getWorkflowTemplate: async (context: ActionContext, templateId: string): Promise => {
- const apiEndpoint: string = context.rootGetters['settings/templatesHost'];
- const versionCli: string = context.rootGetters['versionCli'];
- return await getWorkflowTemplate(apiEndpoint, templateId, { 'n8n-version': versionCli });
- },
- },
-};
-
-export default module;
diff --git a/packages/editor-ui/src/modules/ui.ts b/packages/editor-ui/src/modules/ui.ts
deleted file mode 100644
index 763051dfba171..0000000000000
--- a/packages/editor-ui/src/modules/ui.ts
+++ /dev/null
@@ -1,376 +0,0 @@
-import { getCurlToJson } from '@/api/curlHelper';
-import { applyForOnboardingCall, fetchNextOnboardingPrompt, submitEmailOnSignup } from '@/api/workflow-webhooks';
-import {
- ABOUT_MODAL_KEY,
- COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY,
- COMMUNITY_PACKAGE_INSTALL_MODAL_KEY,
- CREDENTIAL_EDIT_MODAL_KEY,
- CREDENTIAL_SELECT_MODAL_KEY,
- CHANGE_PASSWORD_MODAL_KEY,
- CONTACT_PROMPT_MODAL_KEY,
- DELETE_USER_MODAL_KEY,
- DUPLICATE_MODAL_KEY,
- EXECUTIONS_MODAL_KEY,
- PERSONALIZATION_MODAL_KEY,
- INVITE_USER_MODAL_KEY,
- TAGS_MANAGER_MODAL_KEY,
- VALUE_SURVEY_MODAL_KEY,
- VERSIONS_MODAL_KEY,
- WORKFLOW_ACTIVE_MODAL_KEY,
- WORKFLOW_SETTINGS_MODAL_KEY,
- VIEWS,
- ONBOARDING_CALL_SIGNUP_MODAL_KEY,
- FAKE_DOOR_FEATURES,
- COMMUNITY_PACKAGE_MANAGE_ACTIONS,
- IMPORT_CURL_MODAL_KEY,
-} from '@/constants';
-import Vue from 'vue';
-import { ActionContext, Module } from 'vuex';
-import {
- IFakeDoorLocation,
- IRootState,
- IUiState,
- XYPosition,
- IFakeDoor,
-} from '../Interface';
-
-const module: Module = {
- namespaced: true,
- state: {
- modals: {
- [ABOUT_MODAL_KEY]: {
- open: false,
- },
- [CHANGE_PASSWORD_MODAL_KEY]: {
- open: false,
- },
- [CONTACT_PROMPT_MODAL_KEY]: {
- open: false,
- },
- [CREDENTIAL_EDIT_MODAL_KEY]: {
- open: false,
- mode: '',
- activeId: null,
- },
- [CREDENTIAL_SELECT_MODAL_KEY]: {
- open: false,
- },
- [DELETE_USER_MODAL_KEY]: {
- open: false,
- activeId: null,
- },
- [DUPLICATE_MODAL_KEY]: {
- open: false,
- },
- [ONBOARDING_CALL_SIGNUP_MODAL_KEY]: {
- open: false,
- },
- [PERSONALIZATION_MODAL_KEY]: {
- open: false,
- },
- [INVITE_USER_MODAL_KEY]: {
- open: false,
- },
- [TAGS_MANAGER_MODAL_KEY]: {
- open: false,
- },
- [VALUE_SURVEY_MODAL_KEY]: {
- open: false,
- },
- [VERSIONS_MODAL_KEY]: {
- open: false,
- },
- [WORKFLOW_SETTINGS_MODAL_KEY]: {
- open: false,
- },
- [EXECUTIONS_MODAL_KEY]: {
- open: false,
- },
- [WORKFLOW_ACTIVE_MODAL_KEY]: {
- open: false,
- },
- [COMMUNITY_PACKAGE_INSTALL_MODAL_KEY]: {
- open: false,
- },
- [COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY]: {
- open: false,
- mode: '',
- activeId: null,
- },
- [IMPORT_CURL_MODAL_KEY]: {
- open: false,
- curlCommand: '',
- httpNodeParameters: '',
- },
- },
- modalStack: [],
- sidebarMenuCollapsed: false,
- isPageLoading: true,
- currentView: '',
- fakeDoorFeatures: [
- {
- id: FAKE_DOOR_FEATURES.ENVIRONMENTS,
- featureName: 'fakeDoor.settings.environments.name',
- icon: 'server',
- infoText: 'fakeDoor.settings.environments.infoText',
- actionBoxTitle: `fakeDoor.settings.environments.actionBox.title`,
- actionBoxDescription: 'fakeDoor.settings.environments.actionBox.description',
- linkURL: `https://n8n-community.typeform.com/to/l7QOrERN#f=environments`,
- uiLocations: ['settings'],
- },
- {
- id: FAKE_DOOR_FEATURES.LOGGING,
- featureName: 'fakeDoor.settings.logging.name',
- icon: 'sign-in-alt',
- infoText: 'fakeDoor.settings.logging.infoText',
- actionBoxTitle: `fakeDoor.settings.logging.actionBox.title`,
- actionBoxDescription: 'fakeDoor.settings.logging.actionBox.description',
- linkURL: `https://n8n-community.typeform.com/to/l7QOrERN#f=logging`,
- uiLocations: ['settings'],
- },
- {
- id: FAKE_DOOR_FEATURES.SHARING,
- featureName: 'fakeDoor.credentialEdit.sharing.name',
- actionBoxTitle: 'fakeDoor.credentialEdit.sharing.actionBox.title',
- actionBoxDescription: 'fakeDoor.credentialEdit.sharing.actionBox.description',
- linkURL: 'https://n8n-community.typeform.com/to/l7QOrERN#f=sharing',
- uiLocations: ['credentialsModal'],
- },
- ],
- nodeViewInitialized: false,
- addFirstStepOnLoad: false,
- executionSidebarAutoRefresh: true,
- },
- getters: {
- isVersionsOpen: (state: IUiState) => {
- return state.modals[VERSIONS_MODAL_KEY].open;
- },
- getCurlCommand: (state: IUiState) => {
- return state.modals[IMPORT_CURL_MODAL_KEY].curlCommand;
- },
- getHttpNodeParameters: (state: IUiState) => {
- return state.modals[IMPORT_CURL_MODAL_KEY].httpNodeParameters;
- },
- isModalOpen: (state: IUiState) => {
- return (name: string) => state.modals[name].open;
- },
- isModalActive: (state: IUiState) => {
- return (name: string) => state.modalStack.length > 0 && name === state.modalStack[0];
- },
- getModalActiveId: (state: IUiState) => {
- return (name: string) => state.modals[name].activeId;
- },
- getModalMode: (state: IUiState) => {
- return (name: string) => state.modals[name].mode;
- },
- getModalData: (state: IUiState) => {
- return (name: string) => state.modals[name].data;
- },
- sidebarMenuCollapsed: (state: IUiState): boolean => state.sidebarMenuCollapsed,
- getFakeDoorFeatures: (state: IUiState): IFakeDoor[] => {
- return state.fakeDoorFeatures;
- },
- getFakeDoorByLocation: (state: IUiState, getters) => (location: IFakeDoorLocation) => {
- return getters.getFakeDoorFeatures.filter((fakeDoor: IFakeDoor) => fakeDoor.uiLocations.includes(location));
- },
- getFakeDoorById: (state: IUiState, getters) => (id: string) => {
- return getters.getFakeDoorFeatures.find((fakeDoor: IFakeDoor) => fakeDoor.id.toString() === id);
- },
- getCurrentView: (state: IUiState) => state.currentView,
- isNodeView: (state: IUiState) => [VIEWS.NEW_WORKFLOW.toString(), VIEWS.WORKFLOW.toString(), VIEWS.EXECUTION.toString()].includes(state.currentView),
- getNDVDataIsEmpty: (state: IUiState) => (panel: 'input' | 'output'): boolean => state.ndv[panel].data.isEmpty,
- isNodeViewInitialized: (state: IUiState) => state.nodeViewInitialized,
- getAddFirstStepOnLoad: (state: IUiState) => state.addFirstStepOnLoad,
- isExecutionSidebarAutoRefreshOn: (state: IUiState) => state.executionSidebarAutoRefresh,
- },
- mutations: {
- setMode: (state: IUiState, params: {name: string, mode: string}) => {
- const { name, mode } = params;
- Vue.set(state.modals[name], 'mode', mode);
- },
- setFakeDoorFeatures: (state: IUiState, payload: IFakeDoor[]) => {
- state.fakeDoorFeatures = payload;
- },
- setActiveId: (state: IUiState, params: {name: string, id: string}) => {
- const { name, id } = params;
- Vue.set(state.modals[name], 'activeId', id);
- },
- setModalData: (state: IUiState, params: { name: string, data: Record }) => {
- const { name, data } = params;
-
- Vue.set(state.modals[name], 'data', data);
- },
- setCurlCommand: (state: IUiState, params: {name: string, command: string}) => {
- const { name, command } = params;
- Vue.set(state.modals[name], 'curlCommand', command);
- },
- setHttpNodeParameters: (state: IUiState, params: {name: string, parameters: string}) => {
- const { name, parameters } = params;
- Vue.set(state.modals[name], 'httpNodeParameters', parameters);
- },
- openModal: (state: IUiState, name: string) => {
- Vue.set(state.modals[name], 'open', true);
- state.modalStack = [name].concat(state.modalStack);
- },
- closeModal: (state: IUiState, name: string) => {
- Vue.set(state.modals[name], 'open', false);
- state.modalStack = state.modalStack.filter((openModalName: string) => {
- return name !== openModalName;
- });
- },
- closeAllModals: (state: IUiState) => {
- Object.keys(state.modals).forEach((name: string) => {
- if (state.modals[name].open) {
- Vue.set(state.modals[name], 'open', false);
- }
- });
- state.modalStack = [];
- },
- toggleSidebarMenuCollapse: (state: IUiState) => {
- state.sidebarMenuCollapsed = !state.sidebarMenuCollapsed;
- },
- collapseSidebarMenu: (state: IUiState) => {
- state.sidebarMenuCollapsed = true;
- },
- expandSidebarMenu: (state: IUiState) => {
- state.sidebarMenuCollapsed = false;
- },
- setCurrentView: (state: IUiState, currentView: string) => {
- state.currentView = currentView;
- },
- setNDVSessionId: (state: IUiState) => {
- Vue.set(state.ndv, 'sessionId', `ndv-${Math.random().toString(36).slice(-8)}`);
- },
- resetNDVSessionId: (state: IUiState) => {
- Vue.set(state.ndv, 'sessionId', '');
- },
- setPanelDisplayMode: (state: IUiState, params: {pane: 'input' | 'output', mode: IRunDataDisplayMode}) => {
- Vue.set(state.ndv[params.pane], 'displayMode', params.mode);
- },
- setOutputPanelEditModeEnabled: (state: IUiState, payload: boolean) => {
- Vue.set(state.ndv.output.editMode, 'enabled', payload);
- },
- setOutputPanelEditModeValue: (state: IUiState, payload: string) => {
- Vue.set(state.ndv.output.editMode, 'value', payload);
- },
- setMainPanelRelativePosition(state: IUiState, relativePosition: number) {
- state.mainPanelPosition = relativePosition;
- },
- setMappableNDVInputFocus(state: IUiState, paramName: string) {
- Vue.set(state.ndv, 'focusedMappableInput', paramName);
- },
- draggableStartDragging(state: IUiState, {type, data}: {type: string, data: string}) {
- state.draggable = {
- isDragging: true,
- type,
- data,
- canDrop: false,
- stickyPosition: null,
- };
- },
- draggableStopDragging(state: IUiState) {
- state.draggable = {
- isDragging: false,
- type: '',
- data: '',
- canDrop: false,
- stickyPosition: null,
- };
- },
- setDraggableStickyPos(state: IUiState, position: XYPosition | null) {
- Vue.set(state.draggable, 'stickyPosition', position);
- },
- setDraggableCanDrop(state: IUiState, canDrop: boolean) {
- Vue.set(state.draggable, 'canDrop', canDrop);
- },
- setMappingTelemetry(state: IUiState, telemetry: {[key: string]: string | number | boolean}) {
- state.ndv.mappingTelemetry = {...state.ndv.mappingTelemetry, ...telemetry};
- },
- resetMappingTelemetry(state: IUiState) {
- state.ndv.mappingTelemetry = {};
- },
- setHoveringItem(state: IUiState, item: null | IUiState['ndv']['hoveringItem']) {
- Vue.set(state.ndv, 'hoveringItem', item);
- },
- setNDVBranchIndex(state: IUiState, e: {pane: 'input' | 'output', branchIndex: number}) {
- Vue.set(state.ndv[e.pane], 'branch', e.branchIndex);
- },
- setNDVPanelDataIsEmpty(state: IUiState, payload: {panel: 'input' | 'output', isEmpty: boolean}) {
- Vue.set(state.ndv[payload.panel].data, 'isEmpty', payload.isEmpty);
- },
- setNodeViewInitialized(state: IUiState, isInitialized: boolean) {
- state.nodeViewInitialized = isInitialized;
- },
- setAddFirstStepOnLoad(state: IUiState, addStep: boolean) {
- state.addFirstStepOnLoad = addStep;
- },
- setExecutionsSidebarAutoRefresh(state: IUiState, autoRefresh: boolean) {
- state.executionSidebarAutoRefresh = autoRefresh;
- },
- },
- actions: {
- openModal: async (context: ActionContext, modalKey: string) => {
- context.commit('openModal', modalKey);
- },
- openModalWithData: async (context: ActionContext, payload: { name: string, data: Record }) => {
- context.commit('setModalData', payload);
- context.commit('openModal', payload.name);
- },
- openDeleteUserModal: async (context: ActionContext, { id }: {id: string}) => {
- context.commit('setActiveId', { name: DELETE_USER_MODAL_KEY, id });
- context.commit('openModal', DELETE_USER_MODAL_KEY);
- },
- openExistingCredential: async (context: ActionContext, { id }: {id: string}) => {
- context.commit('setActiveId', { name: CREDENTIAL_EDIT_MODAL_KEY, id });
- context.commit('setMode', { name: CREDENTIAL_EDIT_MODAL_KEY, mode: 'edit' });
- context.commit('openModal', CREDENTIAL_EDIT_MODAL_KEY);
- },
- setCurlCommand: async (context: ActionContext, { command }: {command: string}) => {
- context.commit('setCurlCommand', { name: IMPORT_CURL_MODAL_KEY, command });
- },
- setHttpNodeParameters: async (context: ActionContext, { parameters }) => {
- context.commit('setHttpNodeParameters', { name: IMPORT_CURL_MODAL_KEY, parameters });
- },
- openExisitngCredential: async (context: ActionContext, { id }: {id: string}) => {
- context.commit('setActiveId', { name: CREDENTIAL_EDIT_MODAL_KEY, id });
- context.commit('setMode', { name: CREDENTIAL_EDIT_MODAL_KEY, mode: 'edit' });
- context.commit('openModal', CREDENTIAL_EDIT_MODAL_KEY);
- },
- openNewCredential: async (context: ActionContext, { type }: {type: string}) => {
- context.commit('setActiveId', { name: CREDENTIAL_EDIT_MODAL_KEY, id: type });
- context.commit('setMode', { name: CREDENTIAL_EDIT_MODAL_KEY, mode: 'new' });
- context.commit('openModal', CREDENTIAL_EDIT_MODAL_KEY);
- },
- getNextOnboardingPrompt: async (context: ActionContext) => {
- const instanceId = context.rootGetters.instanceId;
- const currentUser = context.rootGetters['users/currentUser'];
- return await fetchNextOnboardingPrompt(instanceId, currentUser);
- },
- applyForOnboardingCall: async (context: ActionContext, { email }) => {
- const instanceId = context.rootGetters.instanceId;
- const currentUser = context.rootGetters['users/currentUser'];
- return await applyForOnboardingCall(instanceId, currentUser, email);
- },
- submitContactEmail: async (context: ActionContext, { email, agree }) => {
- const instanceId = context.rootGetters.instanceId;
- const currentUser = context.rootGetters['users/currentUser'];
-
- return await submitEmailOnSignup(instanceId, currentUser, email || currentUser.email, agree);
- },
- async openCommunityPackageUninstallConfirmModal(context: ActionContext, packageName: string) {
- context.commit('setActiveId', { name: COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY, id: packageName});
- context.commit('setMode', { name: COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY, mode: COMMUNITY_PACKAGE_MANAGE_ACTIONS.UNINSTALL });
- context.commit('openModal', COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY);
- },
- async openCommunityPackageUpdateConfirmModal(context: ActionContext, packageName: string) {
- context.commit('setActiveId', { name: COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY, id: packageName});
- context.commit('setMode', { name: COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY, mode: COMMUNITY_PACKAGE_MANAGE_ACTIONS.UPDATE });
- context.commit('openModal', COMMUNITY_PACKAGE_CONFIRM_MODAL_KEY);
- },
- async getCurlToJson(context: ActionContext, curlCommand) {
- return await getCurlToJson(context.rootGetters['getRestApiContext'], curlCommand);
- },
- },
-};
-
-export default module;
diff --git a/packages/editor-ui/src/modules/users.ts b/packages/editor-ui/src/modules/users.ts
deleted file mode 100644
index d1faa6f290458..0000000000000
--- a/packages/editor-ui/src/modules/users.ts
+++ /dev/null
@@ -1,227 +0,0 @@
-import { PERSONALIZATION_MODAL_KEY } from '@/constants';
-import {
- changePassword,
- deleteUser,
- getCurrentUser,
- getUsers,
- inviteUsers,
- login,
- loginCurrentUser,
- logout,
- reinvite,
- sendForgotPasswordEmail,
- setupOwner,
- signup,
- submitPersonalizationSurvey,
- skipOwnerSetup,
- updateCurrentUser,
- updateCurrentUserPassword,
- validatePasswordToken,
- validateSignupToken,
-} from '@/api/users';
-import Vue from 'vue';
-import { ActionContext, Module } from 'vuex';
-import {
- IInviteResponse,
- IPersonalizationLatestVersion,
- IRootState,
- IUser,
- IUserResponse,
- IUsersState,
-} from '../Interface';
-import { getPersonalizedNodeTypes, isAuthorized, PERMISSIONS, ROLE } from './userHelpers';
-
-const isDefaultUser = (user: IUserResponse | null) => Boolean(user && user.isPending && user.globalRole && user.globalRole.name === ROLE.Owner);
-
-const isPendingUser = (user: IUserResponse | null) => Boolean(user && user.isPending);
-
-
-const module: Module = {
- namespaced: true,
- state: {
- currentUserId: null,
- users: {},
- },
- mutations: {
- addUsers: (state: IUsersState, users: IUserResponse[]) => {
- users.forEach((userResponse: IUserResponse) => {
- const prevUser = state.users[userResponse.id] || {};
- const updatedUser = {
- ...prevUser,
- ...userResponse,
- };
- const user: IUser = {
- ...updatedUser,
- fullName: userResponse.firstName? `${updatedUser.firstName} ${updatedUser.lastName || ''}`: undefined,
- isDefaultUser: isDefaultUser(updatedUser),
- isPendingUser: isPendingUser(updatedUser),
- isOwner: Boolean(updatedUser.globalRole && updatedUser.globalRole.name === ROLE.Owner),
- };
- Vue.set(state.users, user.id, user);
- });
- },
- setCurrentUserId: (state: IUsersState, userId: string) => {
- state.currentUserId = userId;
- },
- clearCurrentUserId: (state: IUsersState) => {
- state.currentUserId = null;
- },
- deleteUser: (state: IUsersState, userId: string) => {
- Vue.delete(state.users, userId);
- },
- setPersonalizationAnswers(state: IUsersState, answers: IPersonalizationLatestVersion) {
- if (!state.currentUserId) {
- return;
- }
-
- const user = state.users[state.currentUserId] as IUser | null;
- if (!user) {
- return;
- }
-
- Vue.set(user, 'personalizationAnswers', answers);
- },
- },
- getters: {
- allUsers(state: IUsersState): IUser[] {
- return Object.values(state.users);
- },
- currentUserId(state: IUsersState): string | null {
- return state.currentUserId;
- },
- currentUser(state: IUsersState): IUser | null {
- return state.currentUserId ? state.users[state.currentUserId] : null;
- },
- getUserById(state: IUsersState): (userId: string) => IUser | null {
- return (userId: string): IUser | null => state.users[userId];
- },
- globalRoleName(state: IUsersState, getters: any) { // tslint:disable-line:no-any
- return getters.currentUser.globalRole.name;
- },
- canUserDeleteTags(state: IUsersState, getters: any, rootState: IRootState, rootGetters: any) { // tslint:disable-line:no-any
- const currentUser = getters.currentUser;
-
- return isAuthorized(PERMISSIONS.TAGS.CAN_DELETE_TAGS, currentUser);
- },
- canUserAccessSidebarUserInfo(state: IUsersState, getters: any, rootState: IRootState, rootGetters: any) { // tslint:disable-line:no-any
- const currentUser = getters.currentUser;
-
- return isAuthorized(PERMISSIONS.PRIMARY_MENU.CAN_ACCESS_USER_INFO, currentUser);
- },
- showUMSetupWarning(state: IUsersState, getters: any, rootState: IRootState, rootGetters: any) { // tslint:disable-line:no-any
- const currentUser = getters.currentUser;
-
- return isAuthorized(PERMISSIONS.USER_SETTINGS.VIEW_UM_SETUP_WARNING, currentUser);
- },
- personalizedNodeTypes(state: IUsersState, getters: any): string[] { // tslint:disable-line:no-any
- const user = getters.currentUser as IUser | null;
- if (!user) {
- return [];
- }
-
- const answers = user.personalizationAnswers;
- if (!answers) {
- return [];
- }
-
- return getPersonalizedNodeTypes(answers);
- },
- },
- actions: {
- async loginWithCookie(context: ActionContext) {
- const user = await loginCurrentUser(context.rootGetters.getRestApiContext);
- if (user) {
- context.commit('addUsers', [user]);
- context.commit('setCurrentUserId', user.id);
- }
- },
- async getCurrentUser(context: ActionContext) {
- const user = await getCurrentUser(context.rootGetters.getRestApiContext);
- if (user) {
- context.commit('addUsers', [user]);
- context.commit('setCurrentUserId', user.id);
- }
- },
- async loginWithCreds(context: ActionContext, params: {email: string, password: string}) {
- const user = await login(context.rootGetters.getRestApiContext, params);
- if (user) {
- context.commit('addUsers', [user]);
- context.commit('setCurrentUserId', user.id);
- }
- },
- async logout(context: ActionContext) {
- await logout(context.rootGetters.getRestApiContext);
- context.commit('clearCurrentUserId');
- },
- async createOwner(context: ActionContext, params: { firstName: string; lastName: string; email: string; password: string;}) {
- const user = await setupOwner(context.rootGetters.getRestApiContext, params);
- if (user) {
- context.commit('addUsers', [user]);
- context.commit('setCurrentUserId', user.id);
- context.commit('settings/stopShowingSetupPage', null, { root: true });
- }
- },
- async validateSignupToken(context: ActionContext, params: {inviteeId: string, inviterId: string}): Promise<{ inviter: { firstName: string, lastName: string } }> {
- return await validateSignupToken(context.rootGetters.getRestApiContext, params);
- },
- async signup(context: ActionContext, params: { inviteeId: string; inviterId: string; firstName: string; lastName: string; password: string;}) {
- const user = await signup(context.rootGetters.getRestApiContext, params);
- if (user) {
- context.commit('addUsers', [user]);
- context.commit('setCurrentUserId', user.id);
- }
- },
- async sendForgotPasswordEmail(context: ActionContext, params: {email: string}) {
- await sendForgotPasswordEmail(context.rootGetters.getRestApiContext, params);
- },
- async validatePasswordToken(context: ActionContext, params: {token: string, userId: string}) {
- await validatePasswordToken(context.rootGetters.getRestApiContext, params);
- },
- async changePassword(context: ActionContext, params: {token: string, password: string, userId: string}) {
- await changePassword(context.rootGetters.getRestApiContext, params);
- },
- async updateUser(context: ActionContext, params: {id: string, firstName: string, lastName: string, email: string}) {
- const user = await updateCurrentUser(context.rootGetters.getRestApiContext, params);
- context.commit('addUsers', [user]);
- },
- async updateCurrentUserPassword(context: ActionContext, {password, currentPassword}: {password: string, currentPassword: string}) {
- await updateCurrentUserPassword(context.rootGetters.getRestApiContext, {newPassword: password, currentPassword});
- },
- async deleteUser(context: ActionContext, params: { id: string, transferId?: string}) {
- await deleteUser(context.rootGetters.getRestApiContext, params);
- context.commit('deleteUser', params.id);
- },
- async fetchUsers(context: ActionContext) {
- const users = await getUsers(context.rootGetters.getRestApiContext);
- context.commit('addUsers', users);
- },
- async inviteUsers(context: ActionContext, params: Array<{email: string}>): Promise {
- const users = await inviteUsers(context.rootGetters.getRestApiContext, params);
- context.commit('addUsers', users.map(({user}) => ({ isPending: true, ...user })));
- return users;
- },
- async reinviteUser(context: ActionContext, params: {id: string}) {
- await reinvite(context.rootGetters.getRestApiContext, params);
- },
- async submitPersonalizationSurvey(context: ActionContext, results: IPersonalizationLatestVersion) {
- await submitPersonalizationSurvey(context.rootGetters.getRestApiContext, results);
-
- context.commit('setPersonalizationAnswers', results);
- },
- async showPersonalizationSurvey(context: ActionContext) {
- const surveyEnabled = context.rootGetters['settings/isPersonalizationSurveyEnabled'] as boolean;
- const currentUser = context.getters.currentUser as IUser | null;
- if (surveyEnabled && currentUser && !currentUser.personalizationAnswers) {
- context.dispatch('ui/openModal', PERSONALIZATION_MODAL_KEY, {root: true});
- }
- },
- async skipOwnerSetup(context: ActionContext) {
- try {
- context.commit('settings/stopShowingSetupPage', null, { root: true });
- await skipOwnerSetup(context.rootGetters.getRestApiContext);
- } catch (error) {}
- },
- },
-};
-
-export default module;
diff --git a/packages/editor-ui/src/modules/versions.ts b/packages/editor-ui/src/modules/versions.ts
index 56d28c6411591..e992644bc2727 100644
--- a/packages/editor-ui/src/modules/versions.ts
+++ b/packages/editor-ui/src/modules/versions.ts
@@ -1,4 +1,5 @@
import { getNextVersions } from '@/api/versions';
+import { useRootStore } from '@/stores/n8nRootStore';
import { ActionContext, Module } from 'vuex';
import {
IRootState,
@@ -40,7 +41,7 @@ const module: Module = {
state.currentVersion = versions.find((version) => version.name === currentVersion);
},
setVersionNotificationSettings(state: IVersionsState, settings: {enabled: true, endpoint: string, infoUrl: string}) {
- state.versionNotificationSettings = settings;
+ state.versionNotificationSettings = settings;
},
},
actions: {
@@ -48,8 +49,9 @@ const module: Module = {
try {
const { enabled, endpoint } = context.state.versionNotificationSettings;
if (enabled && endpoint) {
- const currentVersion = context.rootState.versionCli;
- const instanceId = context.rootState.instanceId;
+ const rootStore = useRootStore();
+ const currentVersion = rootStore.versionCli;
+ const instanceId = rootStore.instanceId;
const versions = await getNextVersions(endpoint, currentVersion, instanceId);
context.commit('setVersions', {versions, currentVersion});
}
@@ -59,4 +61,4 @@ const module: Module = {
},
};
-export default module;
\ No newline at end of file
+export default module;
diff --git a/packages/editor-ui/src/modules/workflows.ts b/packages/editor-ui/src/modules/workflows.ts
deleted file mode 100644
index 5fdd05ecec740..0000000000000
--- a/packages/editor-ui/src/modules/workflows.ts
+++ /dev/null
@@ -1,115 +0,0 @@
-import { getCurrentExecutions, getFinishedExecutions, getNewWorkflow } from '@/api/workflows';
-import { DUPLICATE_POSTFFIX, MAX_WORKFLOW_NAME_LENGTH, DEFAULT_NEW_WORKFLOW_NAME } from '@/constants';
-import { IDataObject } from 'n8n-workflow';
-import { ActionContext, Module } from 'vuex';
-import {
- IExecutionsSummary,
- IRootState,
- IWorkflowsState,
-} from '../Interface';
-
-const module: Module = {
- namespaced: true,
- state: {
- currentWorkflowExecutions: [],
- activeWorkflowExecution: null,
- finishedExecutionsCount: 0,
- },
- actions: {
- getNewWorkflowData: async (context: ActionContext, name?: string): Promise