mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
refactor(editor): Refactor usePushConnection and introduce new queueing system (#14529)
This commit is contained in:
@@ -221,7 +221,7 @@ describe('LogsPanel', () => {
|
||||
expect(rendered.getByText('Running')).toBeInTheDocument();
|
||||
expect(rendered.queryByText('AI Agent')).not.toBeInTheDocument();
|
||||
|
||||
workflowsStore.setNodeExecuting({
|
||||
workflowsStore.addNodeExecutionData({
|
||||
nodeName: 'AI Agent',
|
||||
executionId: '567',
|
||||
data: { executionIndex: 0, startTime: Date.parse('2025-04-20T12:34:51.000Z'), source: [] },
|
||||
@@ -243,7 +243,6 @@ describe('LogsPanel', () => {
|
||||
executionStatus: 'success',
|
||||
},
|
||||
});
|
||||
|
||||
expect(await treeItem.findByText('AI Agent')).toBeInTheDocument();
|
||||
expect(treeItem.getByText('Success in 33ms')).toBeInTheDocument();
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
START_NODE_TYPE,
|
||||
} from '@/constants';
|
||||
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
||||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||
import { useNDVStore } from '@/stores/ndv.store';
|
||||
import { waitingNodeTooltip } from '@/utils/executionUtils';
|
||||
import { uniqBy } from 'lodash-es';
|
||||
import { N8nIcon, N8nRadioButtons, N8nText, N8nTooltip } from '@n8n/design-system';
|
||||
@@ -23,7 +23,6 @@ import {
|
||||
} from 'n8n-workflow';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { useNDVStore } from '../stores/ndv.store';
|
||||
import InputNodeSelect from './InputNodeSelect.vue';
|
||||
import NodeExecuteButton from './NodeExecuteButton.vue';
|
||||
import RunData from './RunData.vue';
|
||||
@@ -90,7 +89,6 @@ const inputModes = [
|
||||
const nodeTypesStore = useNodeTypesStore();
|
||||
const ndvStore = useNDVStore();
|
||||
const workflowsStore = useWorkflowsStore();
|
||||
const uiStore = useUIStore();
|
||||
|
||||
const {
|
||||
activeNode,
|
||||
@@ -166,7 +164,7 @@ const isMappingEnabled = computed(() => {
|
||||
return true;
|
||||
});
|
||||
const isExecutingPrevious = computed(() => {
|
||||
if (!workflowRunning.value) {
|
||||
if (!workflowsStore.isWorkflowRunning) {
|
||||
return false;
|
||||
}
|
||||
const triggeredNode = workflowsStore.executedNode;
|
||||
@@ -187,7 +185,6 @@ const isExecutingPrevious = computed(() => {
|
||||
}
|
||||
return false;
|
||||
});
|
||||
const workflowRunning = computed(() => uiStore.isActionActive.workflowRunning);
|
||||
|
||||
const rootNodesParents = computed(() => {
|
||||
if (!rootNode.value) return [];
|
||||
|
||||
@@ -31,7 +31,6 @@ import { dataPinningEventBus, ndvEventBus } from '@/event-bus';
|
||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||
import { useNDVStore } from '@/stores/ndv.store';
|
||||
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
||||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { useSettingsStore } from '@/stores/settings.store';
|
||||
import { useDeviceSupport } from '@n8n/composables/useDeviceSupport';
|
||||
import { useNodeHelpers } from '@/composables/useNodeHelpers';
|
||||
@@ -72,7 +71,6 @@ const { activeNode } = storeToRefs(ndvStore);
|
||||
const pinnedData = usePinnedData(activeNode);
|
||||
const workflowActivate = useWorkflowActivate();
|
||||
const nodeTypesStore = useNodeTypesStore();
|
||||
const uiStore = useUIStore();
|
||||
const workflowsStore = useWorkflowsStore();
|
||||
const settingsStore = useSettingsStore();
|
||||
const deviceSupport = useDeviceSupport();
|
||||
@@ -108,14 +106,12 @@ const activeNodeType = computed(() => {
|
||||
return null;
|
||||
});
|
||||
|
||||
const workflowRunning = computed(() => uiStore.isActionActive.workflowRunning);
|
||||
|
||||
const showTriggerWaitingWarning = computed(
|
||||
() =>
|
||||
triggerWaitingWarningEnabled.value &&
|
||||
!!activeNodeType.value &&
|
||||
!activeNodeType.value.group.includes('trigger') &&
|
||||
workflowRunning.value &&
|
||||
workflowsStore.isWorkflowRunning &&
|
||||
workflowsStore.executionWaitingForWebhook,
|
||||
);
|
||||
|
||||
@@ -327,11 +323,11 @@ const featureRequestUrl = computed(() => {
|
||||
|
||||
const outputPanelEditMode = computed(() => ndvStore.outputPanelEditMode);
|
||||
|
||||
const isWorkflowRunning = computed(() => uiStore.isActionActive.workflowRunning);
|
||||
|
||||
const isExecutionWaitingForWebhook = computed(() => workflowsStore.executionWaitingForWebhook);
|
||||
|
||||
const blockUi = computed(() => isWorkflowRunning.value || isExecutionWaitingForWebhook.value);
|
||||
const blockUi = computed(
|
||||
() => workflowsStore.isWorkflowRunning || isExecutionWaitingForWebhook.value,
|
||||
);
|
||||
|
||||
const foreignCredentials = computed(() => {
|
||||
const credentials = activeNode.value?.credentials;
|
||||
@@ -470,7 +466,7 @@ const onUnlinkRun = (pane: string) => {
|
||||
|
||||
const onNodeExecute = () => {
|
||||
setTimeout(() => {
|
||||
if (!activeNode.value || !workflowRunning.value) {
|
||||
if (!activeNode.value || !workflowsStore.isWorkflowRunning) {
|
||||
return;
|
||||
}
|
||||
triggerWaitingWarningEnabled.value = true;
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
} from '@/constants';
|
||||
import NodeExecuteButton from '@/components/NodeExecuteButton.vue';
|
||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
||||
import { useNDVStore } from '@/stores/ndv.store';
|
||||
import { useRunWorkflow } from '@/composables/useRunWorkflow';
|
||||
@@ -84,7 +83,6 @@ vi.mock('@/composables/useMessage', () => {
|
||||
|
||||
let renderComponent: ReturnType<typeof createComponentRenderer>;
|
||||
let workflowsStore: MockedStore<typeof useWorkflowsStore>;
|
||||
let uiStore: MockedStore<typeof useUIStore>;
|
||||
let nodeTypesStore: MockedStore<typeof useNodeTypesStore>;
|
||||
let ndvStore: MockedStore<typeof useNDVStore>;
|
||||
|
||||
@@ -109,7 +107,6 @@ describe('NodeExecuteButton', () => {
|
||||
});
|
||||
|
||||
workflowsStore = mockedStore(useWorkflowsStore);
|
||||
uiStore = mockedStore(useUIStore);
|
||||
nodeTypesStore = mockedStore(useNodeTypesStore);
|
||||
ndvStore = mockedStore(useNDVStore);
|
||||
|
||||
@@ -193,7 +190,7 @@ describe('NodeExecuteButton', () => {
|
||||
workflowsStore.getNodeByName.mockReturnValue(node);
|
||||
workflowsStore.isNodeExecuting = vi.fn(() => true);
|
||||
nodeTypesStore.isTriggerNode = () => true;
|
||||
uiStore.isActionActive.workflowRunning = true;
|
||||
workflowsStore.isWorkflowRunning = true;
|
||||
|
||||
const { getByRole } = renderComponent();
|
||||
expect(getByRole('button').textContent).toBe('Stop Listening');
|
||||
@@ -203,7 +200,7 @@ describe('NodeExecuteButton', () => {
|
||||
const node = mockNode({ name: 'test-node', type: SET_NODE_TYPE });
|
||||
workflowsStore.getNodeByName.mockReturnValue(node);
|
||||
workflowsStore.isNodeExecuting = vi.fn(() => true);
|
||||
uiStore.isActionActive.workflowRunning = true;
|
||||
workflowsStore.isWorkflowRunning = true;
|
||||
|
||||
const { getByRole } = renderComponent();
|
||||
expect(getByRole('button').querySelector('.n8n-spinner')).toBeVisible();
|
||||
@@ -227,7 +224,7 @@ describe('NodeExecuteButton', () => {
|
||||
});
|
||||
|
||||
it('should be disabled when workflow is running but node is not executing', async () => {
|
||||
uiStore.isActionActive.workflowRunning = true;
|
||||
workflowsStore.isWorkflowRunning = true;
|
||||
workflowsStore.isNodeExecuting.mockReturnValue(false);
|
||||
workflowsStore.getNodeByName.mockReturnValue(
|
||||
mockNode({ name: 'test-node', type: SET_NODE_TYPE }),
|
||||
@@ -277,7 +274,7 @@ describe('NodeExecuteButton', () => {
|
||||
});
|
||||
|
||||
it('stops execution when clicking button while workflow is running', async () => {
|
||||
uiStore.isActionActive.workflowRunning = true;
|
||||
workflowsStore.isWorkflowRunning = true;
|
||||
nodeTypesStore.isTriggerNode = () => true;
|
||||
workflowsStore.setActiveExecutionId('test-execution-id');
|
||||
workflowsStore.isNodeExecuting.mockReturnValue(true);
|
||||
|
||||
@@ -22,7 +22,6 @@ import { useExternalHooks } from '@/composables/useExternalHooks';
|
||||
import { nodeViewEventBus } from '@/event-bus';
|
||||
import { usePinnedData } from '@/composables/usePinnedData';
|
||||
import { useRunWorkflow } from '@/composables/useRunWorkflow';
|
||||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useI18n } from '@/composables/useI18n';
|
||||
import { useTelemetry } from '@/composables/useTelemetry';
|
||||
@@ -72,7 +71,6 @@ const externalHooks = useExternalHooks();
|
||||
const toast = useToast();
|
||||
const ndvStore = useNDVStore();
|
||||
const nodeTypesStore = useNodeTypesStore();
|
||||
const uiStore = useUIStore();
|
||||
const i18n = useI18n();
|
||||
const message = useMessage();
|
||||
const telemetry = useTelemetry();
|
||||
@@ -85,7 +83,7 @@ const nodeType = computed((): INodeTypeDescription | null => {
|
||||
});
|
||||
|
||||
const isNodeRunning = computed(() => {
|
||||
if (!uiStore.isActionActive.workflowRunning || codeGenerationInProgress.value) return false;
|
||||
if (!workflowsStore.isWorkflowRunning || codeGenerationInProgress.value) return false;
|
||||
const triggeredNode = workflowsStore.executedNode;
|
||||
return (
|
||||
workflowsStore.isNodeExecuting(node.value?.name ?? '') || triggeredNode === node.value?.name
|
||||
@@ -96,8 +94,6 @@ const isTriggerNode = computed(() => {
|
||||
return node.value ? nodeTypesStore.isTriggerNode(node.value.type) : false;
|
||||
});
|
||||
|
||||
const isWorkflowRunning = computed(() => uiStore.isActionActive.workflowRunning);
|
||||
|
||||
const isManualTriggerNode = computed(() =>
|
||||
nodeType.value ? nodeType.value.name === MANUAL_TRIGGER_NODE_TYPE : false,
|
||||
);
|
||||
@@ -168,7 +164,7 @@ const disabledHint = computed(() => {
|
||||
return i18n.baseText('ndv.execute.requiredFieldsMissing');
|
||||
}
|
||||
|
||||
if (isWorkflowRunning.value && !isNodeRunning.value) {
|
||||
if (workflowsStore.isWorkflowRunning && !isNodeRunning.value) {
|
||||
return i18n.baseText('ndv.execute.workflowAlreadyRunning');
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
import RunData from './RunData.vue';
|
||||
import RunInfo from './RunInfo.vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||
import { useNDVStore } from '@/stores/ndv.store';
|
||||
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
||||
@@ -77,7 +76,6 @@ const emit = defineEmits<{
|
||||
const ndvStore = useNDVStore();
|
||||
const nodeTypesStore = useNodeTypesStore();
|
||||
const workflowsStore = useWorkflowsStore();
|
||||
const uiStore = useUIStore();
|
||||
const telemetry = useTelemetry();
|
||||
const i18n = useI18n();
|
||||
const { activeNode } = storeToRefs(ndvStore);
|
||||
@@ -144,7 +142,7 @@ const isNodeRunning = computed(() => {
|
||||
return workflowRunning.value && !!node.value && workflowsStore.isNodeExecuting(node.value.name);
|
||||
});
|
||||
|
||||
const workflowRunning = computed(() => uiStore.isActionActive.workflowRunning);
|
||||
const workflowRunning = computed(() => workflowsStore.isWorkflowRunning);
|
||||
|
||||
const workflowExecution = computed(() => {
|
||||
return workflowsStore.getWorkflowExecution;
|
||||
|
||||
@@ -162,9 +162,7 @@ const isListeningForEvents = computed(() => {
|
||||
);
|
||||
});
|
||||
|
||||
const workflowRunning = computed(() => {
|
||||
return uiStore.isActionActive.workflowRunning;
|
||||
});
|
||||
const workflowRunning = computed(() => workflowsStore.isWorkflowRunning);
|
||||
|
||||
const isActivelyPolling = computed(() => {
|
||||
const triggeredNode = workflowsStore.executedNode;
|
||||
|
||||
@@ -16,7 +16,7 @@ const {
|
||||
hasIssues,
|
||||
executionStatus,
|
||||
executionWaiting,
|
||||
executionRunningThrottled,
|
||||
executionRunning,
|
||||
hasRunData,
|
||||
runDataIterations,
|
||||
isDisabled,
|
||||
@@ -55,6 +55,16 @@ const dirtiness = computed(() =>
|
||||
<FontAwesomeIcon icon="sync-alt" spin />
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="executionStatus === 'unknown'">
|
||||
<!-- Do nothing, unknown means the node never executed -->
|
||||
</div>
|
||||
<div
|
||||
v-else-if="executionRunning || executionStatus === 'running'"
|
||||
data-test-id="canvas-node-status-running"
|
||||
:class="[$style.status, $style.running]"
|
||||
>
|
||||
<FontAwesomeIcon icon="sync-alt" spin />
|
||||
</div>
|
||||
<div
|
||||
v-else-if="hasPinnedData && !nodeHelpers.isProductionExecutionPreview.value && !isDisabled"
|
||||
data-test-id="canvas-node-status-pinned"
|
||||
@@ -62,16 +72,6 @@ const dirtiness = computed(() =>
|
||||
>
|
||||
<FontAwesomeIcon icon="thumbtack" />
|
||||
</div>
|
||||
<div v-else-if="executionStatus === 'unknown'">
|
||||
<!-- Do nothing, unknown means the node never executed -->
|
||||
</div>
|
||||
<div
|
||||
v-else-if="executionRunningThrottled || executionStatus === 'running'"
|
||||
data-test-id="canvas-node-status-running"
|
||||
:class="[$style.status, $style.running]"
|
||||
>
|
||||
<FontAwesomeIcon icon="sync-alt" spin />
|
||||
</div>
|
||||
<div v-else-if="dirtiness !== undefined">
|
||||
<N8nTooltip :show-after="500" placement="bottom">
|
||||
<template #content>
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useCanvasOperations } from '@/composables/useCanvasOperations';
|
||||
import { useI18n } from '@/composables/useI18n';
|
||||
import { useRunWorkflow } from '@/composables/useRunWorkflow';
|
||||
import { CHAT_TRIGGER_NODE_TYPE } from '@/constants';
|
||||
import { useUIStore } from '@/stores/ui.store';
|
||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||
import { computed, useCssModule } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
@@ -36,12 +35,11 @@ const containerClass = computed(() => ({
|
||||
const router = useRouter();
|
||||
const i18n = useI18n();
|
||||
const workflowsStore = useWorkflowsStore();
|
||||
const uiStore = useUIStore();
|
||||
const { runEntireWorkflow } = useRunWorkflow({ router });
|
||||
const { toggleChatOpen } = useCanvasOperations({ router });
|
||||
|
||||
const isChatOpen = computed(() => workflowsStore.logsPanelState !== LOGS_PANEL_STATE.CLOSED);
|
||||
const isExecuting = computed(() => uiStore.isActionActive.workflowRunning);
|
||||
const isExecuting = computed(() => workflowsStore.isWorkflowRunning);
|
||||
const testId = computed(() => `execute-workflow-button-${name}`);
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user