mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-09 22:24:05 -08:00
fix: Stop listening button not working in NDV (#9023)
This commit is contained in:
parent
e2bde6b751
commit
02219dde2f
|
@ -658,4 +658,18 @@ describe('NDV', () => {
|
|||
cy.realPress('Escape');
|
||||
});
|
||||
});
|
||||
|
||||
it('Stop listening for trigger event from NDV', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('Local File Trigger', {
|
||||
keepNdvOpen: true,
|
||||
action: 'On Changes To A Specific File',
|
||||
isTrigger: true,
|
||||
});
|
||||
ndv.getters.triggerPanelExecuteButton().should('exist');
|
||||
ndv.getters.triggerPanelExecuteButton().click();
|
||||
ndv.getters.triggerPanelExecuteButton().should('contain', 'Stop Listening');
|
||||
ndv.getters.triggerPanelExecuteButton().click();
|
||||
ndv.getters.triggerPanelExecuteButton().should('contain', 'Test step');
|
||||
workflowPage.getters.successToast().should('exist');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -145,19 +145,20 @@ export class WorkflowPage extends BasePage {
|
|||
},
|
||||
addInitialNodeToCanvas: (
|
||||
nodeDisplayName: string,
|
||||
opts?: { keepNdvOpen?: boolean; action?: string },
|
||||
opts?: { keepNdvOpen?: boolean; action?: string, isTrigger?: boolean},
|
||||
) => {
|
||||
this.getters.canvasPlusButton().click();
|
||||
this.getters.nodeCreatorSearchBar().type(nodeDisplayName);
|
||||
this.getters.nodeCreatorSearchBar().type('{enter}');
|
||||
if (opts?.action) {
|
||||
const itemId = opts.isTrigger ? 'Triggers' : 'Actions';
|
||||
// Expand actions category if it's collapsed
|
||||
nodeCreator.getters
|
||||
.getCategoryItem('Actions')
|
||||
.getCategoryItem(itemId)
|
||||
.parent()
|
||||
.then(($el) => {
|
||||
if ($el.attr('data-category-collapsed') === 'true') {
|
||||
nodeCreator.getters.getCategoryItem('Actions').click();
|
||||
nodeCreator.getters.getCategoryItem(itemId).click();
|
||||
}
|
||||
});
|
||||
nodeCreator.getters.getCreatorItem(opts.action).click();
|
||||
|
|
|
@ -77,18 +77,20 @@ export default defineComponent({
|
|||
type: Boolean,
|
||||
},
|
||||
},
|
||||
emits: ['stopExecution', 'execute'],
|
||||
setup(props) {
|
||||
const router = useRouter();
|
||||
const workflowsStore = useWorkflowsStore();
|
||||
const node = workflowsStore.getNodeByName(props.nodeName);
|
||||
const pinnedData = usePinnedData(node);
|
||||
const externalHooks = useExternalHooks();
|
||||
const { runWorkflow } = useRunWorkflow({ router });
|
||||
const { runWorkflow, stopCurrentExecution } = useRunWorkflow({ router });
|
||||
|
||||
return {
|
||||
externalHooks,
|
||||
pinnedData,
|
||||
runWorkflow,
|
||||
stopCurrentExecution,
|
||||
...useToast(),
|
||||
...useMessage(),
|
||||
};
|
||||
|
@ -236,6 +238,7 @@ export default defineComponent({
|
|||
} else if (this.isListeningForEvents) {
|
||||
await this.stopWaitingForWebhook();
|
||||
} else if (this.isListeningForWorkflowEvents) {
|
||||
await this.stopCurrentExecution();
|
||||
this.$emit('stopExecution');
|
||||
} else {
|
||||
let shouldUnpinAndExecute = false;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import type {
|
||||
IExecutionPushResponse,
|
||||
IExecutionResponse,
|
||||
IPushDataExecutionFinished,
|
||||
IStartRunData,
|
||||
IWorkflowDb,
|
||||
} from '@/Interface';
|
||||
|
@ -13,6 +14,7 @@ import type {
|
|||
IWorkflowBase,
|
||||
Workflow,
|
||||
StartNodeData,
|
||||
IRun,
|
||||
} from 'n8n-workflow';
|
||||
import {
|
||||
NodeHelpers,
|
||||
|
@ -449,9 +451,67 @@ export function useRunWorkflow(options: { router: ReturnType<typeof useRouter> }
|
|||
return { runData: newRunData, startNodeNames };
|
||||
}
|
||||
|
||||
async function stopCurrentExecution() {
|
||||
const executionId = workflowsStore.activeExecutionId;
|
||||
if (executionId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await workflowsStore.stopCurrentExecution(executionId);
|
||||
} catch (error) {
|
||||
// Execution stop might fail when the execution has already finished. Let's treat this here.
|
||||
const execution = await this.workflowsStore.getExecution(executionId);
|
||||
|
||||
if (execution === undefined) {
|
||||
// execution finished but was not saved (e.g. due to low connectivity)
|
||||
workflowsStore.finishActiveExecution({
|
||||
executionId,
|
||||
data: { finished: true, stoppedAt: new Date() },
|
||||
});
|
||||
workflowsStore.executingNode.length = 0;
|
||||
uiStore.removeActiveAction('workflowRunning');
|
||||
|
||||
titleSet(workflowsStore.workflowName, 'IDLE');
|
||||
toast.showMessage({
|
||||
title: i18n.baseText('nodeView.showMessage.stopExecutionCatch.unsaved.title'),
|
||||
message: i18n.baseText('nodeView.showMessage.stopExecutionCatch.unsaved.message'),
|
||||
type: 'success',
|
||||
});
|
||||
} else if (execution?.finished) {
|
||||
// execution finished before it could be stopped
|
||||
const executedData = {
|
||||
data: execution.data,
|
||||
finished: execution.finished,
|
||||
mode: execution.mode,
|
||||
startedAt: execution.startedAt,
|
||||
stoppedAt: execution.stoppedAt,
|
||||
} as IRun;
|
||||
const pushData = {
|
||||
data: executedData,
|
||||
executionId,
|
||||
retryOf: execution.retryOf,
|
||||
} as IPushDataExecutionFinished;
|
||||
workflowsStore.finishActiveExecution(pushData);
|
||||
titleSet(execution.workflowData.name, 'IDLE');
|
||||
workflowsStore.executingNode.length = 0;
|
||||
workflowsStore.setWorkflowExecutionData(executedData as IExecutionResponse);
|
||||
uiStore.removeActiveAction('workflowRunning');
|
||||
toast.showMessage({
|
||||
title: i18n.baseText('nodeView.showMessage.stopExecutionCatch.title'),
|
||||
message: i18n.baseText('nodeView.showMessage.stopExecutionCatch.message'),
|
||||
type: 'success',
|
||||
});
|
||||
} else {
|
||||
toast.showError(error, i18n.baseText('nodeView.showError.stopExecution.title'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
consolidateRunDataAndStartNodes,
|
||||
runWorkflow,
|
||||
runWorkflowApi,
|
||||
stopCurrentExecution,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -279,7 +279,6 @@ import type {
|
|||
INodeTypeDescription,
|
||||
INodeTypeNameVersion,
|
||||
IPinData,
|
||||
IRun,
|
||||
ITaskData,
|
||||
ITelemetryTrackProperties,
|
||||
IWorkflowBase,
|
||||
|
@ -303,7 +302,6 @@ import type {
|
|||
IUpdateInformation,
|
||||
IWorkflowDataUpdate,
|
||||
XYPosition,
|
||||
IPushDataExecutionFinished,
|
||||
ITag,
|
||||
INewWorkflowData,
|
||||
IWorkflowTemplate,
|
||||
|
@ -492,7 +490,7 @@ export default defineComponent({
|
|||
const { callDebounced } = useDebounce();
|
||||
const canvasPanning = useCanvasPanning(nodeViewRootRef, { onMouseMoveEnd });
|
||||
const workflowHelpers = useWorkflowHelpers({ router });
|
||||
const { runWorkflow } = useRunWorkflow({ router });
|
||||
const { runWorkflow, stopCurrentExecution } = useRunWorkflow({ router });
|
||||
|
||||
return {
|
||||
locale,
|
||||
|
@ -509,6 +507,7 @@ export default defineComponent({
|
|||
onMouseMoveEnd,
|
||||
workflowHelpers,
|
||||
runWorkflow,
|
||||
stopCurrentExecution,
|
||||
callDebounced,
|
||||
...useCanvasMouseSelect(),
|
||||
...useGlobalLinkActions(),
|
||||
|
@ -1930,67 +1929,8 @@ export default defineComponent({
|
|||
});
|
||||
},
|
||||
async stopExecution() {
|
||||
const executionId = this.workflowsStore.activeExecutionId;
|
||||
if (executionId === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.stopExecutionInProgress = true;
|
||||
await this.workflowsStore.stopCurrentExecution(executionId);
|
||||
} catch (error) {
|
||||
// Execution stop might fail when the execution has already finished. Let's treat this here.
|
||||
const execution = await this.workflowsStore.getExecution(executionId);
|
||||
|
||||
if (execution === undefined) {
|
||||
// execution finished but was not saved (e.g. due to low connectivity)
|
||||
|
||||
this.workflowsStore.finishActiveExecution({
|
||||
executionId,
|
||||
data: { finished: true, stoppedAt: new Date() },
|
||||
});
|
||||
this.workflowsStore.executingNode.length = 0;
|
||||
this.uiStore.removeActiveAction('workflowRunning');
|
||||
|
||||
this.titleSet(this.workflowsStore.workflowName, 'IDLE');
|
||||
this.showMessage({
|
||||
title: this.$locale.baseText('nodeView.showMessage.stopExecutionCatch.unsaved.title'),
|
||||
message: this.$locale.baseText(
|
||||
'nodeView.showMessage.stopExecutionCatch.unsaved.message',
|
||||
),
|
||||
type: 'success',
|
||||
});
|
||||
} else if (execution?.finished) {
|
||||
// execution finished before it could be stopped
|
||||
|
||||
const executedData = {
|
||||
data: execution.data,
|
||||
finished: execution.finished,
|
||||
mode: execution.mode,
|
||||
startedAt: execution.startedAt,
|
||||
stoppedAt: execution.stoppedAt,
|
||||
} as IRun;
|
||||
const pushData = {
|
||||
data: executedData,
|
||||
executionId,
|
||||
retryOf: execution.retryOf,
|
||||
} as IPushDataExecutionFinished;
|
||||
this.workflowsStore.finishActiveExecution(pushData);
|
||||
this.titleSet(execution.workflowData.name, 'IDLE');
|
||||
this.workflowsStore.executingNode.length = 0;
|
||||
this.workflowsStore.setWorkflowExecutionData(executedData as IExecutionResponse);
|
||||
this.uiStore.removeActiveAction('workflowRunning');
|
||||
this.showMessage({
|
||||
title: this.$locale.baseText('nodeView.showMessage.stopExecutionCatch.title'),
|
||||
message: this.$locale.baseText('nodeView.showMessage.stopExecutionCatch.message'),
|
||||
type: 'success',
|
||||
});
|
||||
} else {
|
||||
this.showError(error, this.$locale.baseText('nodeView.showError.stopExecution.title'));
|
||||
}
|
||||
}
|
||||
await this.stopCurrentExecution();
|
||||
this.stopExecutionInProgress = false;
|
||||
|
||||
void this.workflowHelpers.getWorkflowDataToSave().then((workflowData) => {
|
||||
const trackProps = {
|
||||
workflow_id: this.workflowsStore.workflowId,
|
||||
|
|
Loading…
Reference in a new issue