mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 01:56:46 +00:00
fix(editor): Ensure NDV in focus panel reflect changes made in NDV modal (no-changelog) (#19095)
This commit is contained in:
@@ -0,0 +1,80 @@
|
|||||||
|
import { createTestNode } from '@/__tests__/mocks';
|
||||||
|
import { createComponentRenderer } from '@/__tests__/render';
|
||||||
|
import { cleanupAppModals, createAppModals } from '@/__tests__/utils';
|
||||||
|
import { SET_NODE_TYPE } from '@/constants';
|
||||||
|
import { useNDVStore } from '@/stores/ndv.store';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
|
import { createTestingPinia } from '@pinia/testing';
|
||||||
|
import ExperimentalNodeDetailsDrawer from './ExperimentalNodeDetailsDrawer.vue';
|
||||||
|
import { nextTick } from 'vue';
|
||||||
|
|
||||||
|
const renderComponent = createComponentRenderer(ExperimentalNodeDetailsDrawer);
|
||||||
|
|
||||||
|
describe('ExperimentalNodeDetailsDrawer', () => {
|
||||||
|
let pinia: ReturnType<typeof createTestingPinia>;
|
||||||
|
let workflowsStore: ReturnType<typeof useWorkflowsStore>;
|
||||||
|
let nodeTypesStore: ReturnType<typeof useNodeTypesStore>;
|
||||||
|
let ndvStore: ReturnType<typeof useNDVStore>;
|
||||||
|
|
||||||
|
const mockNodes = [
|
||||||
|
createTestNode({
|
||||||
|
id: 'node1',
|
||||||
|
name: 'Node 1',
|
||||||
|
type: SET_NODE_TYPE,
|
||||||
|
parameters: { p0: 'before update' },
|
||||||
|
}),
|
||||||
|
createTestNode({ id: 'node2', name: 'Node 2', type: SET_NODE_TYPE }),
|
||||||
|
createTestNode({ id: 'node3', name: 'Node 3', type: SET_NODE_TYPE }),
|
||||||
|
];
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
pinia = createTestingPinia({
|
||||||
|
stubActions: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
workflowsStore = useWorkflowsStore(pinia);
|
||||||
|
workflowsStore.setNodes(mockNodes);
|
||||||
|
nodeTypesStore = useNodeTypesStore(pinia);
|
||||||
|
nodeTypesStore.setNodeTypes([
|
||||||
|
{
|
||||||
|
name: SET_NODE_TYPE,
|
||||||
|
properties: [{ name: 'p0', displayName: 'P0', type: 'string', default: '' }],
|
||||||
|
version: 1,
|
||||||
|
defaults: {},
|
||||||
|
inputs: ['main'],
|
||||||
|
outputs: ['main'],
|
||||||
|
displayName: 'T0',
|
||||||
|
group: [],
|
||||||
|
description: '',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
ndvStore = useNDVStore();
|
||||||
|
createAppModals();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
cleanupAppModals();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show updated parameter after closing NDV', async () => {
|
||||||
|
const rendered = renderComponent({
|
||||||
|
pinia,
|
||||||
|
props: {
|
||||||
|
node: mockNodes[0],
|
||||||
|
nodes: [mockNodes[0]],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await rendered.findByDisplayValue('before update');
|
||||||
|
|
||||||
|
// Simulate parameter update in NDV
|
||||||
|
ndvStore.setActiveNodeName('Node 1', 'other');
|
||||||
|
await nextTick();
|
||||||
|
workflowsStore.setNodeParameters({ name: 'Node 1', value: { p0: 'after update' } });
|
||||||
|
ndvStore.unsetActiveNodeName();
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
await rendered.findByDisplayValue('after update');
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -4,14 +4,31 @@ import { ExpressionLocalResolveContextSymbol } from '@/constants';
|
|||||||
import { type INodeUi } from '@/Interface';
|
import { type INodeUi } from '@/Interface';
|
||||||
import { N8nText } from '@n8n/design-system';
|
import { N8nText } from '@n8n/design-system';
|
||||||
import { type GraphNode } from '@vue-flow/core';
|
import { type GraphNode } from '@vue-flow/core';
|
||||||
import { computed, provide } from 'vue';
|
import { computed, provide, ref, watch } from 'vue';
|
||||||
import ExperimentalCanvasNodeSettings from './ExperimentalCanvasNodeSettings.vue';
|
import ExperimentalCanvasNodeSettings from './ExperimentalCanvasNodeSettings.vue';
|
||||||
|
import { useNDVStore } from '@/stores/ndv.store';
|
||||||
|
|
||||||
const { node, nodes } = defineProps<{ node: INodeUi; nodes: GraphNode[] }>();
|
const { node, nodes } = defineProps<{ node: INodeUi; nodes: GraphNode[] }>();
|
||||||
|
|
||||||
const emit = defineEmits<{ openNdv: [] }>();
|
const emit = defineEmits<{ openNdv: [] }>();
|
||||||
|
|
||||||
const expressionResolveCtx = useExpressionResolveCtx(computed(() => node));
|
const expressionResolveCtx = useExpressionResolveCtx(computed(() => node));
|
||||||
|
const ndvStore = useNDVStore();
|
||||||
|
|
||||||
|
const ndvCloseTimes = ref(0);
|
||||||
|
|
||||||
|
// To ensure showing latest parameters, force re-render when NDV is closed
|
||||||
|
const nodeSettingsViewKey = computed(() => [node.id, ndvCloseTimes.value].join('|'));
|
||||||
|
|
||||||
|
// Track closing NDV
|
||||||
|
watch(
|
||||||
|
() => ndvStore.activeNodeName,
|
||||||
|
(name, oldName) => {
|
||||||
|
if (name === null && oldName !== null) {
|
||||||
|
ndvCloseTimes.value += 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
provide(ExpressionLocalResolveContextSymbol, expressionResolveCtx);
|
provide(ExpressionLocalResolveContextSymbol, expressionResolveCtx);
|
||||||
</script>
|
</script>
|
||||||
@@ -19,7 +36,7 @@ provide(ExpressionLocalResolveContextSymbol, expressionResolveCtx);
|
|||||||
<template>
|
<template>
|
||||||
<div :class="$style.component">
|
<div :class="$style.component">
|
||||||
<N8nText v-if="nodes.length > 1" color="text-base"> {{ nodes.length }} nodes selected </N8nText>
|
<N8nText v-if="nodes.length > 1" color="text-base"> {{ nodes.length }} nodes selected </N8nText>
|
||||||
<ExperimentalCanvasNodeSettings v-else-if="node" :key="node.id" :node-id="node.id">
|
<ExperimentalCanvasNodeSettings v-else-if="node" :key="nodeSettingsViewKey" :node-id="node.id">
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<N8nIconButton
|
<N8nIconButton
|
||||||
icon="maximize-2"
|
icon="maximize-2"
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export const useSettingsStore = defineStore(STORES.SETTINGS, () => {
|
|||||||
secureCookie: settings.value.authCookie.secure,
|
secureCookie: settings.value.authCookie.secure,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const isEnterpriseFeatureEnabled = computed(() => settings.value.enterprise);
|
const isEnterpriseFeatureEnabled = computed(() => settings.value.enterprise ?? {});
|
||||||
|
|
||||||
const nodeJsVersion = computed(() => settings.value.nodeJsVersion);
|
const nodeJsVersion = computed(() => settings.value.nodeJsVersion);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user