mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
fix(editor): Fix pin data showing up in production executions on new canvas (#11951)
This commit is contained in:
parent
40a7445f08
commit
5f6f8a1bdd
|
@ -5,12 +5,13 @@ import type {
|
||||||
IWebhookDescription,
|
IWebhookDescription,
|
||||||
Workflow,
|
Workflow,
|
||||||
INodeConnections,
|
INodeConnections,
|
||||||
|
WorkflowExecuteMode,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
import { NodeConnectionType, NodeHelpers } from 'n8n-workflow';
|
import { NodeConnectionType, NodeHelpers } from 'n8n-workflow';
|
||||||
import { useCanvasOperations } from '@/composables/useCanvasOperations';
|
import { useCanvasOperations } from '@/composables/useCanvasOperations';
|
||||||
import type { CanvasConnection, CanvasNode } from '@/types';
|
import type { CanvasConnection, CanvasNode } from '@/types';
|
||||||
import { CanvasConnectionMode } from '@/types';
|
import { CanvasConnectionMode } from '@/types';
|
||||||
import type { ICredentialsResponse, INodeUi, IWorkflowDb } from '@/Interface';
|
import type { ICredentialsResponse, IExecutionResponse, INodeUi, IWorkflowDb } from '@/Interface';
|
||||||
import { RemoveNodeCommand } from '@/models/history';
|
import { RemoveNodeCommand } from '@/models/history';
|
||||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
import { useUIStore } from '@/stores/ui.store';
|
import { useUIStore } from '@/stores/ui.store';
|
||||||
|
@ -2174,6 +2175,67 @@ describe('useCanvasOperations', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('openExecution', () => {
|
||||||
|
it('should initialize workspace and set execution data when execution is found', async () => {
|
||||||
|
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||||
|
const uiStore = mockedStore(useUIStore);
|
||||||
|
const { openExecution } = useCanvasOperations({ router });
|
||||||
|
|
||||||
|
const executionId = '123';
|
||||||
|
const executionData: IExecutionResponse = {
|
||||||
|
id: executionId,
|
||||||
|
finished: true,
|
||||||
|
status: 'success',
|
||||||
|
startedAt: new Date(),
|
||||||
|
createdAt: new Date(),
|
||||||
|
workflowData: createTestWorkflow(),
|
||||||
|
mode: 'manual' as WorkflowExecuteMode,
|
||||||
|
};
|
||||||
|
|
||||||
|
workflowsStore.getExecution.mockResolvedValue(executionData);
|
||||||
|
|
||||||
|
const result = await openExecution(executionId);
|
||||||
|
|
||||||
|
expect(workflowsStore.setWorkflowExecutionData).toHaveBeenCalledWith(executionData);
|
||||||
|
expect(uiStore.stateIsDirty).toBe(false);
|
||||||
|
expect(result).toEqual(executionData);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error when execution data is undefined', async () => {
|
||||||
|
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||||
|
const executionId = '123';
|
||||||
|
const { openExecution } = useCanvasOperations({ router });
|
||||||
|
|
||||||
|
workflowsStore.getExecution.mockResolvedValue(undefined);
|
||||||
|
|
||||||
|
await expect(openExecution(executionId)).rejects.toThrow(
|
||||||
|
`Execution with id "${executionId}" could not be found!`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should clear workflow pin data if execution mode is not manual', async () => {
|
||||||
|
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||||
|
const { openExecution } = useCanvasOperations({ router });
|
||||||
|
|
||||||
|
const executionId = '123';
|
||||||
|
const executionData: IExecutionResponse = {
|
||||||
|
id: executionId,
|
||||||
|
finished: true,
|
||||||
|
status: 'success',
|
||||||
|
startedAt: new Date(),
|
||||||
|
createdAt: new Date(),
|
||||||
|
workflowData: createTestWorkflow(),
|
||||||
|
mode: 'trigger' as WorkflowExecuteMode,
|
||||||
|
};
|
||||||
|
|
||||||
|
workflowsStore.getExecution.mockResolvedValue(executionData);
|
||||||
|
|
||||||
|
await openExecution(executionId);
|
||||||
|
|
||||||
|
expect(workflowsStore.setWorkflowPinData).toHaveBeenCalledWith({});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function buildImportNodes() {
|
function buildImportNodes() {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
AddedNodesAndConnections,
|
AddedNodesAndConnections,
|
||||||
|
IExecutionResponse,
|
||||||
INodeUi,
|
INodeUi,
|
||||||
ITag,
|
ITag,
|
||||||
IUsedCredential,
|
IUsedCredential,
|
||||||
|
@ -1849,6 +1850,32 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
||||||
deleteNodes(ids);
|
deleteNodes(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function openExecution(executionId: string) {
|
||||||
|
let data: IExecutionResponse | undefined;
|
||||||
|
try {
|
||||||
|
data = await workflowsStore.getExecution(executionId);
|
||||||
|
} catch (error) {
|
||||||
|
toast.showError(error, i18n.baseText('nodeView.showError.openExecution.title'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data === undefined) {
|
||||||
|
throw new Error(`Execution with id "${executionId}" could not be found!`);
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeWorkspace(data.workflowData);
|
||||||
|
|
||||||
|
workflowsStore.setWorkflowExecutionData(data);
|
||||||
|
|
||||||
|
if (data.mode !== 'manual') {
|
||||||
|
workflowsStore.setWorkflowPinData({});
|
||||||
|
}
|
||||||
|
|
||||||
|
uiStore.stateIsDirty = false;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
lastClickPosition,
|
lastClickPosition,
|
||||||
editableWorkflow,
|
editableWorkflow,
|
||||||
|
@ -1891,5 +1918,6 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
|
||||||
resetWorkspace,
|
resetWorkspace,
|
||||||
initializeWorkspace,
|
initializeWorkspace,
|
||||||
resolveNodeWebhook,
|
resolveNodeWebhook,
|
||||||
|
openExecution,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,6 +185,7 @@ const {
|
||||||
fetchWorkflowDataFromUrl,
|
fetchWorkflowDataFromUrl,
|
||||||
resetWorkspace,
|
resetWorkspace,
|
||||||
initializeWorkspace,
|
initializeWorkspace,
|
||||||
|
openExecution,
|
||||||
editableWorkflow,
|
editableWorkflow,
|
||||||
editableWorkflowObject,
|
editableWorkflowObject,
|
||||||
lastClickPosition,
|
lastClickPosition,
|
||||||
|
@ -1051,30 +1052,18 @@ function trackRunWorkflowToNode(node: INodeUi) {
|
||||||
void externalHooks.run('nodeView.onRunNode', telemetryPayload);
|
void externalHooks.run('nodeView.onRunNode', telemetryPayload);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function openExecution(executionId: string) {
|
async function onOpenExecution(executionId: string) {
|
||||||
canvasStore.startLoading();
|
canvasStore.startLoading();
|
||||||
|
|
||||||
resetWorkspace();
|
resetWorkspace();
|
||||||
|
|
||||||
let data: IExecutionResponse | undefined;
|
|
||||||
try {
|
|
||||||
data = await workflowsStore.getExecution(executionId);
|
|
||||||
} catch (error) {
|
|
||||||
toast.showError(error, i18n.baseText('nodeView.showError.openExecution.title'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (data === undefined) {
|
|
||||||
throw new Error(`Execution with id "${executionId}" could not be found!`);
|
|
||||||
}
|
|
||||||
|
|
||||||
await initializeData();
|
await initializeData();
|
||||||
|
|
||||||
initializeWorkspace(data.workflowData);
|
const data = await openExecution(executionId);
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
workflowsStore.setWorkflowExecutionData(data);
|
|
||||||
|
|
||||||
uiStore.stateIsDirty = false;
|
|
||||||
canvasStore.stopLoading();
|
canvasStore.stopLoading();
|
||||||
|
|
||||||
fitView();
|
fitView();
|
||||||
|
|
||||||
canvasEventBus.emit('open:execution', data);
|
canvasEventBus.emit('open:execution', data);
|
||||||
|
@ -1320,7 +1309,7 @@ async function onPostMessageReceived(messageEvent: MessageEvent) {
|
||||||
// so everything it needs has to be sent using post messages and passed down to child components
|
// so everything it needs has to be sent using post messages and passed down to child components
|
||||||
isProductionExecutionPreview.value = json.executionMode !== 'manual';
|
isProductionExecutionPreview.value = json.executionMode !== 'manual';
|
||||||
|
|
||||||
await openExecution(json.executionId);
|
await onOpenExecution(json.executionId);
|
||||||
canOpenNDV.value = json.canOpenNDV ?? true;
|
canOpenNDV.value = json.canOpenNDV ?? true;
|
||||||
hideNodeIssues.value = json.hideNodeIssues ?? false;
|
hideNodeIssues.value = json.hideNodeIssues ?? false;
|
||||||
isExecutionPreview.value = true;
|
isExecutionPreview.value = true;
|
||||||
|
|
Loading…
Reference in a new issue