mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
fix(editor): Inline expression previews are not displayed in NDV (#14475)
This commit is contained in:
@@ -126,6 +126,10 @@ export function getNodeOutputErrorMessage() {
|
|||||||
return getOutputPanel().findChildByTestId('node-error-message');
|
return getOutputPanel().findChildByTestId('node-error-message');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getParameterExpressionPreviewValue() {
|
||||||
|
return cy.getByTestId('parameter-expression-preview-value');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actions
|
* Actions
|
||||||
*/
|
*/
|
||||||
@@ -264,3 +268,7 @@ export function populateFixedCollection<T extends readonly string[]>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function assertInlineExpressionValid() {
|
||||||
|
cy.getByTestId('inline-expression-editor-input').find('.cm-valid-resolvable').should('exist');
|
||||||
|
}
|
||||||
|
|||||||
24
cypress/e2e/9999-SUG-38-inline-expression-preview.cy.ts
Normal file
24
cypress/e2e/9999-SUG-38-inline-expression-preview.cy.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import {
|
||||||
|
assertInlineExpressionValid,
|
||||||
|
getParameterExpressionPreviewValue,
|
||||||
|
} from '../composables/ndv';
|
||||||
|
import {
|
||||||
|
clickZoomToFit,
|
||||||
|
executeWorkflowAndWait,
|
||||||
|
navigateToNewWorkflowPage,
|
||||||
|
openNode,
|
||||||
|
pasteWorkflow,
|
||||||
|
} from '../composables/workflow';
|
||||||
|
import Workflow from '../fixtures/Test_9999-SUG-38.json';
|
||||||
|
|
||||||
|
describe('SUG-38 Inline expression previews are not displayed in NDV', () => {
|
||||||
|
it("should show resolved inline expression preview in NDV if the node's input data is populated", () => {
|
||||||
|
navigateToNewWorkflowPage();
|
||||||
|
pasteWorkflow(Workflow);
|
||||||
|
clickZoomToFit();
|
||||||
|
executeWorkflowAndWait();
|
||||||
|
openNode('Repro1');
|
||||||
|
assertInlineExpressionValid();
|
||||||
|
getParameterExpressionPreviewValue().should('have.text', 'hello there');
|
||||||
|
});
|
||||||
|
});
|
||||||
80
cypress/fixtures/Test_9999-SUG-38.json
Normal file
80
cypress/fixtures/Test_9999-SUG-38.json
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"parameters": {},
|
||||||
|
"type": "n8n-nodes-base.manualTrigger",
|
||||||
|
"typeVersion": 1,
|
||||||
|
"position": [-240, 180],
|
||||||
|
"id": "cd9b8124-567e-43d9-b4d1-638b111cd049",
|
||||||
|
"name": "When clicking ‘Test workflow’"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"assignments": {
|
||||||
|
"assignments": [
|
||||||
|
{
|
||||||
|
"id": "3a40d9f2-0eed-4a92-9287-9d6ec9ce90e8",
|
||||||
|
"name": "message",
|
||||||
|
"value": "hello there",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.set",
|
||||||
|
"typeVersion": 3.4,
|
||||||
|
"position": [-20, 180],
|
||||||
|
"id": "6e58ae14-4851-4e9d-9465-4155b6e2f278",
|
||||||
|
"name": "Edit Fields1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"parameters": {
|
||||||
|
"assignments": {
|
||||||
|
"assignments": [
|
||||||
|
{
|
||||||
|
"id": "9e957377-c5f2-4254-89d8-334d32a8cfb6",
|
||||||
|
"name": "test",
|
||||||
|
"value": "={{ $json.message }}",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"options": {}
|
||||||
|
},
|
||||||
|
"type": "n8n-nodes-base.set",
|
||||||
|
"typeVersion": 3.4,
|
||||||
|
"position": [200, 180],
|
||||||
|
"id": "c4e9d792-51e9-4296-ba66-afac3cf378dd",
|
||||||
|
"name": "Repro1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": {
|
||||||
|
"When clicking ‘Test workflow’": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Edit Fields1",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Edit Fields1": {
|
||||||
|
"main": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"node": "Repro1",
|
||||||
|
"type": "main",
|
||||||
|
"index": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pinData": {},
|
||||||
|
"meta": {
|
||||||
|
"instanceId": "cdc3bfdf3e6244f221ab6e71b2115a631406ae45a034bfca5e9731cf64f4eb64"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1547,7 +1547,7 @@ export interface IN8nPromptResponse {
|
|||||||
|
|
||||||
export type InputPanel = {
|
export type InputPanel = {
|
||||||
nodeName?: string;
|
nodeName?: string;
|
||||||
run: number;
|
run?: number;
|
||||||
branch?: number;
|
branch?: number;
|
||||||
data: {
|
data: {
|
||||||
isEmpty: boolean;
|
isEmpty: boolean;
|
||||||
@@ -1555,7 +1555,6 @@ export type InputPanel = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type OutputPanel = {
|
export type OutputPanel = {
|
||||||
run: number;
|
|
||||||
branch?: number;
|
branch?: number;
|
||||||
data: {
|
data: {
|
||||||
isEmpty: boolean;
|
isEmpty: boolean;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useI18n } from '@/composables/useI18n';
|
|||||||
import { useNodeHelpers } from '@/composables/useNodeHelpers';
|
import { useNodeHelpers } from '@/composables/useNodeHelpers';
|
||||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
import { N8nButton, N8nRadioButtons, N8nText, N8nTooltip } from '@n8n/design-system';
|
import { N8nButton, N8nRadioButtons, N8nText, N8nTooltip } from '@n8n/design-system';
|
||||||
import { computed, nextTick } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { ElTree, type TreeNode as ElTreeNode } from 'element-plus';
|
import { ElTree, type TreeNode as ElTreeNode } from 'element-plus';
|
||||||
import {
|
import {
|
||||||
createAiData,
|
createAiData,
|
||||||
@@ -115,9 +115,6 @@ function handleToggleExpanded(treeNode: ElTreeNode) {
|
|||||||
|
|
||||||
async function handleOpenNdv(treeNode: TreeNode) {
|
async function handleOpenNdv(treeNode: TreeNode) {
|
||||||
ndvStore.setActiveNodeName(treeNode.node);
|
ndvStore.setActiveNodeName(treeNode.node);
|
||||||
|
|
||||||
// HACK: defer setting the output run index to not be overridden by other effects
|
|
||||||
await nextTick(() => ndvStore.setOutputRunIndex(treeNode.runIndex));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleTriggerPartialExecution(treeNode: TreeNode) {
|
async function handleTriggerPartialExecution(treeNode: TreeNode) {
|
||||||
|
|||||||
@@ -78,6 +78,9 @@ const { APP_Z_INDEXES } = useStyles();
|
|||||||
|
|
||||||
const settingsEventBus = createEventBus();
|
const settingsEventBus = createEventBus();
|
||||||
const redrawRequired = ref(false);
|
const redrawRequired = ref(false);
|
||||||
|
const runInputIndex = ref(-1);
|
||||||
|
const runOutputIndex = ref(-1);
|
||||||
|
const isLinkingEnabled = ref(true);
|
||||||
const selectedInput = ref<string | undefined>();
|
const selectedInput = ref<string | undefined>();
|
||||||
const triggerWaitingWarningEnabled = ref(false);
|
const triggerWaitingWarningEnabled = ref(false);
|
||||||
const isDragging = ref(false);
|
const isDragging = ref(false);
|
||||||
@@ -245,6 +248,12 @@ const maxOutputRun = computed(() => {
|
|||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const outputRun = computed(() =>
|
||||||
|
runOutputIndex.value === -1
|
||||||
|
? maxOutputRun.value
|
||||||
|
: Math.min(runOutputIndex.value, maxOutputRun.value),
|
||||||
|
);
|
||||||
|
|
||||||
const maxInputRun = computed(() => {
|
const maxInputRun = computed(() => {
|
||||||
if (inputNode.value === null || activeNode.value === null) {
|
if (inputNode.value === null || activeNode.value === null) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -281,23 +290,15 @@ const maxInputRun = computed(() => {
|
|||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
const isLinkingEnabled = computed(() => ndvStore.isRunIndexLinkingEnabled);
|
|
||||||
|
|
||||||
const outputRun = computed(() =>
|
|
||||||
ndvStore.output.run === -1
|
|
||||||
? maxOutputRun.value
|
|
||||||
: Math.min(ndvStore.output.run, maxOutputRun.value),
|
|
||||||
);
|
|
||||||
|
|
||||||
const inputRun = computed(() => {
|
const inputRun = computed(() => {
|
||||||
if (isLinkingEnabled.value && maxOutputRun.value === maxInputRun.value) {
|
if (isLinkingEnabled.value && maxOutputRun.value === maxInputRun.value) {
|
||||||
return outputRun.value;
|
return outputRun.value;
|
||||||
}
|
}
|
||||||
if (ndvStore.input.run === -1) {
|
if (runInputIndex.value === -1) {
|
||||||
return maxInputRun.value;
|
return maxInputRun.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.min(ndvStore.input.run, maxInputRun.value);
|
return Math.min(runInputIndex.value, maxInputRun.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
const canLinkRuns = computed(
|
const canLinkRuns = computed(
|
||||||
@@ -442,13 +443,13 @@ const onPanelsInit = (e: { position: number }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onLinkRunToOutput = () => {
|
const onLinkRunToOutput = () => {
|
||||||
ndvStore.setRunIndexLinkingEnabled(true);
|
isLinkingEnabled.value = true;
|
||||||
trackLinking('output');
|
trackLinking('output');
|
||||||
};
|
};
|
||||||
|
|
||||||
const onUnlinkRun = (pane: string) => {
|
const onUnlinkRun = (pane: string) => {
|
||||||
ndvStore.setInputRunIndex(outputRun.value);
|
runInputIndex.value = runOutputIndex.value;
|
||||||
ndvStore.setRunIndexLinkingEnabled(false);
|
isLinkingEnabled.value = false;
|
||||||
trackLinking(pane);
|
trackLinking(pane);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -475,8 +476,8 @@ const trackLinking = (pane: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onLinkRunToInput = () => {
|
const onLinkRunToInput = () => {
|
||||||
ndvStore.setOutputRunIndex(inputRun.value);
|
runOutputIndex.value = runInputIndex.value;
|
||||||
ndvStore.setRunIndexLinkingEnabled(true);
|
isLinkingEnabled.value = true;
|
||||||
trackLinking('input');
|
trackLinking('input');
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -552,12 +553,15 @@ const trackRunChange = (run: number, pane: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onRunOutputIndexChange = (run: number) => {
|
const onRunOutputIndexChange = (run: number) => {
|
||||||
ndvStore.setOutputRunIndex(run);
|
runOutputIndex.value = run;
|
||||||
trackRunChange(run, 'output');
|
trackRunChange(run, 'output');
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRunInputIndexChange = (run: number) => {
|
const onRunInputIndexChange = (run: number) => {
|
||||||
ndvStore.setInputRunIndex(run);
|
runInputIndex.value = run;
|
||||||
|
if (linked.value) {
|
||||||
|
runOutputIndex.value = run;
|
||||||
|
}
|
||||||
trackRunChange(run, 'input');
|
trackRunChange(run, 'input');
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -566,8 +570,8 @@ const onOutputTableMounted = (e: { avgRowHeight: number }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onInputNodeChange = (value: string, index: number) => {
|
const onInputNodeChange = (value: string, index: number) => {
|
||||||
ndvStore.setInputRunIndex(-1);
|
runInputIndex.value = -1;
|
||||||
ndvStore.setRunIndexLinkingEnabled(true);
|
isLinkingEnabled.value = true;
|
||||||
selectedInput.value = value;
|
selectedInput.value = value;
|
||||||
|
|
||||||
telemetry.track('User changed ndv input dropdown', {
|
telemetry.track('User changed ndv input dropdown', {
|
||||||
@@ -617,6 +621,9 @@ watch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (node && node.name !== oldNode?.name && !isActiveStickyNode.value) {
|
if (node && node.name !== oldNode?.name && !isActiveStickyNode.value) {
|
||||||
|
runInputIndex.value = -1;
|
||||||
|
runOutputIndex.value = -1;
|
||||||
|
isLinkingEnabled.value = true;
|
||||||
selectedInput.value = undefined;
|
selectedInput.value = undefined;
|
||||||
triggerWaitingWarningEnabled.value = false;
|
triggerWaitingWarningEnabled.value = false;
|
||||||
avgOutputRowHeight.value = 0;
|
avgOutputRowHeight.value = 0;
|
||||||
@@ -667,12 +674,26 @@ watch(
|
|||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
watch(maxOutputRun, () => {
|
||||||
|
runOutputIndex.value = -1;
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(maxInputRun, () => {
|
||||||
|
runInputIndex.value = -1;
|
||||||
|
});
|
||||||
|
|
||||||
watch(inputNodeName, (nodeName) => {
|
watch(inputNodeName, (nodeName) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
ndvStore.setInputNodeName(nodeName);
|
ndvStore.setInputNodeName(nodeName);
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(inputRun, (inputRun) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
ndvStore.setInputRunIndex(inputRun);
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
dataPinningEventBus.on('data-pinning-discovery', setIsTooltipVisible);
|
dataPinningEventBus.on('data-pinning-discovery', setIsTooltipVisible);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ export const useNDVStore = defineStore(STORES.NDV, () => {
|
|||||||
const localStorageAutoCompleteIsOnboarded = useStorage(LOCAL_STORAGE_AUTOCOMPLETE_IS_ONBOARDED);
|
const localStorageAutoCompleteIsOnboarded = useStorage(LOCAL_STORAGE_AUTOCOMPLETE_IS_ONBOARDED);
|
||||||
|
|
||||||
const activeNodeName = ref<string | null>(null);
|
const activeNodeName = ref<string | null>(null);
|
||||||
const isRunIndexLinkingEnabled = ref(true);
|
|
||||||
const mainPanelDimensions = ref<MainPanelDimensions>({
|
const mainPanelDimensions = ref<MainPanelDimensions>({
|
||||||
unknown: { ...DEFAULT_MAIN_PANEL_DIMENSIONS },
|
unknown: { ...DEFAULT_MAIN_PANEL_DIMENSIONS },
|
||||||
regular: { ...DEFAULT_MAIN_PANEL_DIMENSIONS },
|
regular: { ...DEFAULT_MAIN_PANEL_DIMENSIONS },
|
||||||
@@ -49,7 +48,7 @@ export const useNDVStore = defineStore(STORES.NDV, () => {
|
|||||||
const pushRef = ref('');
|
const pushRef = ref('');
|
||||||
const input = ref<InputPanel>({
|
const input = ref<InputPanel>({
|
||||||
nodeName: undefined,
|
nodeName: undefined,
|
||||||
run: -1,
|
run: undefined,
|
||||||
branch: undefined,
|
branch: undefined,
|
||||||
data: {
|
data: {
|
||||||
isEmpty: true,
|
isEmpty: true,
|
||||||
@@ -60,7 +59,6 @@ export const useNDVStore = defineStore(STORES.NDV, () => {
|
|||||||
'schema',
|
'schema',
|
||||||
);
|
);
|
||||||
const output = ref<OutputPanel>({
|
const output = ref<OutputPanel>({
|
||||||
run: -1,
|
|
||||||
branch: undefined,
|
branch: undefined,
|
||||||
data: {
|
data: {
|
||||||
isEmpty: true,
|
isEmpty: true,
|
||||||
@@ -215,36 +213,15 @@ export const useNDVStore = defineStore(STORES.NDV, () => {
|
|||||||
const isNDVOpen = computed(() => activeNodeName.value !== null);
|
const isNDVOpen = computed(() => activeNodeName.value !== null);
|
||||||
|
|
||||||
const setActiveNodeName = (nodeName: string | null): void => {
|
const setActiveNodeName = (nodeName: string | null): void => {
|
||||||
if (nodeName === activeNodeName.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
activeNodeName.value = nodeName;
|
activeNodeName.value = nodeName;
|
||||||
|
|
||||||
// Reset run index
|
|
||||||
input.value.run = -1;
|
|
||||||
output.value.run = -1;
|
|
||||||
isRunIndexLinkingEnabled.value = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const setInputNodeName = (nodeName: string | undefined): void => {
|
const setInputNodeName = (nodeName: string | undefined): void => {
|
||||||
input.value.nodeName = nodeName;
|
input.value.nodeName = nodeName;
|
||||||
};
|
};
|
||||||
|
|
||||||
const setInputRunIndex = (run: number = -1): void => {
|
const setInputRunIndex = (run?: number): void => {
|
||||||
input.value.run = run;
|
input.value.run = run;
|
||||||
|
|
||||||
if (isRunIndexLinkingEnabled.value) {
|
|
||||||
setOutputRunIndex(run);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const setOutputRunIndex = (run: number = -1): void => {
|
|
||||||
output.value.run = run;
|
|
||||||
};
|
|
||||||
|
|
||||||
const setRunIndexLinkingEnabled = (value: boolean): void => {
|
|
||||||
isRunIndexLinkingEnabled.value = value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const setMainPanelDimensions = (params: {
|
const setMainPanelDimensions = (params: {
|
||||||
@@ -427,12 +404,9 @@ export const useNDVStore = defineStore(STORES.NDV, () => {
|
|||||||
expressionOutputItemIndex,
|
expressionOutputItemIndex,
|
||||||
isTableHoverOnboarded,
|
isTableHoverOnboarded,
|
||||||
mainPanelDimensions,
|
mainPanelDimensions,
|
||||||
isRunIndexLinkingEnabled,
|
|
||||||
setActiveNodeName,
|
setActiveNodeName,
|
||||||
setInputNodeName,
|
setInputNodeName,
|
||||||
setInputRunIndex,
|
setInputRunIndex,
|
||||||
setOutputRunIndex,
|
|
||||||
setRunIndexLinkingEnabled,
|
|
||||||
setMainPanelDimensions,
|
setMainPanelDimensions,
|
||||||
setNDVPushRef,
|
setNDVPushRef,
|
||||||
resetNDVPushRef,
|
resetNDVPushRef,
|
||||||
|
|||||||
Reference in New Issue
Block a user