();
+const { nodeId, noWheel, isReadOnly } = defineProps<{
+ nodeId: string;
+ noWheel?: boolean;
+ isReadOnly?: boolean;
+}>();
defineSlots<{ actions?: {} }>();
@@ -30,7 +34,7 @@ function handleValueChanged(parameterData: IUpdateInformation) {
:active-node="activeNode"
push-ref=""
:foreign-credentials="[]"
- :read-only="false"
+ :read-only="isReadOnly"
:block-u-i="false"
:executable="false"
:input-size="0"
diff --git a/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalEmbeddedNodeDetails.vue b/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalEmbeddedNodeDetails.vue
index d405ad7819..67df688787 100644
--- a/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalEmbeddedNodeDetails.vue
+++ b/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalEmbeddedNodeDetails.vue
@@ -9,7 +9,11 @@ import { N8nIcon, N8nIconButton } from '@n8n/design-system';
import { useVueFlow } from '@vue-flow/core';
import { watchOnce } from '@vueuse/core';
-const { nodeId } = defineProps<{ nodeId: string }>();
+const { nodeId, isReadOnly, isConfigurable } = defineProps<{
+ nodeId: string;
+ isReadOnly?: boolean;
+ isConfigurable: boolean;
+}>();
const experimentalNdvStore = useExperimentalNdvStore();
const isExpanded = computed(() => !experimentalNdvStore.collapsedNodes[nodeId]);
@@ -22,7 +26,7 @@ const nodeType = computed(() => {
}
return null;
});
-const vf = useVueFlow(workflowsStore.workflowId);
+const vf = useVueFlow();
const isMoving = ref(false);
@@ -65,7 +69,10 @@ function handleToggleExpand() {
* {
- zoom: var(--zoom);
- }
-}
-
-:root .settingsView {
height: auto;
- max-height: min(200%, 300px);
- top: -10%;
- min-height: 120%;
+ max-height: min(calc(var(--canvas-node--height) * 2), 300px);
+ min-height: var(--spacing-3xl); // should be multiple of GRID_SIZE
}
.collapsedContent {
@@ -169,5 +158,15 @@ function handleToggleExpand() {
background-color: var(--color-background-xlight);
color: var(--color-text-base);
cursor: pointer;
+
+ & > * {
+ zoom: calc(var(--zoom) * 1.25);
+ }
+}
+
+.settingsView {
+ & > * {
+ zoom: var(--zoom);
+ }
}
diff --git a/packages/frontend/editor-ui/src/components/canvas/experimental/experimentalNdv.store.ts b/packages/frontend/editor-ui/src/components/canvas/experimental/experimentalNdv.store.ts
index 3618f2ee84..d33cee2ad3 100644
--- a/packages/frontend/editor-ui/src/components/canvas/experimental/experimentalNdv.store.ts
+++ b/packages/frontend/editor-ui/src/components/canvas/experimental/experimentalNdv.store.ts
@@ -2,6 +2,8 @@ import { computed, shallowRef } from 'vue';
import { defineStore } from 'pinia';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { useSettingsStore } from '@/stores/settings.store';
+import { useVueFlow } from '@vue-flow/core';
+import { calculateNodeSize } from '@/utils/nodeViewUtils';
export const useExperimentalNdvStore = defineStore('experimentalNdv', () => {
const workflowStore = useWorkflowsStore();
@@ -20,7 +22,7 @@ export const useExperimentalNdvStore = defineStore('experimentalNdv', () => {
function setNodeExpanded(nodeId: string, isExpanded?: boolean) {
collapsedNodes.value = {
...collapsedNodes.value,
- [nodeId]: isExpanded ?? !collapsedNodes.value[nodeId],
+ [nodeId]: isExpanded === undefined ? !collapsedNodes.value[nodeId] : !isExpanded,
};
}
@@ -42,6 +44,40 @@ export const useExperimentalNdvStore = defineStore('experimentalNdv', () => {
return isEnabled.value && canvasZoom === maxCanvasZoom.value;
}
+ function focusNode(nodeId: string) {
+ const nodeToFocus = workflowStore.getNodeById(nodeId);
+
+ if (!nodeToFocus) {
+ return;
+ }
+
+ // Call useVueFlow() here because having it in setup fn scope seem to cause initialization problem
+ const vueFlow = useVueFlow(workflowStore.workflow.id);
+
+ collapsedNodes.value = workflowStore.allNodes.reduce>>(
+ (acc, node) => {
+ acc[node.id] = node.id !== nodeId;
+ return acc;
+ },
+ {},
+ );
+
+ const workflow = workflowStore.getCurrentWorkflow();
+ const nodeSize = calculateNodeSize(
+ workflow.getChildNodes(nodeToFocus.name, 'ALL_NON_MAIN').length > 0,
+ workflow.getParentNodes(nodeToFocus.name, 'ALL_NON_MAIN').length > 0,
+ workflow.getParentNodes(nodeToFocus.name, 'main').length,
+ workflow.getChildNodes(nodeToFocus.name, 'main').length,
+ workflow.getParentNodes(nodeToFocus.name, 'ALL_NON_MAIN').length,
+ );
+
+ void vueFlow.setCenter(
+ nodeToFocus.position[0] + (nodeSize.width * 1.5) / 2,
+ nodeToFocus.position[1] + 80,
+ { duration: 200, zoom: maxCanvasZoom.value },
+ );
+ }
+
return {
isEnabled,
maxCanvasZoom,
@@ -50,5 +86,6 @@ export const useExperimentalNdvStore = defineStore('experimentalNdv', () => {
setNodeExpanded,
expandAllNodes,
collapseAllNodes,
+ focusNode,
};
});
diff --git a/packages/frontend/editor-ui/src/features/logs/composables/useLogsSelection.ts b/packages/frontend/editor-ui/src/features/logs/composables/useLogsSelection.ts
index b11cc183a0..b42ca150a8 100644
--- a/packages/frontend/editor-ui/src/features/logs/composables/useLogsSelection.ts
+++ b/packages/frontend/editor-ui/src/features/logs/composables/useLogsSelection.ts
@@ -15,6 +15,7 @@ import { useUIStore } from '@/stores/ui.store';
import { shallowRef, watch } from 'vue';
import { computed, type ComputedRef } from 'vue';
import { useWorkflowsStore } from '@/stores/workflows.store';
+import { useExperimentalNdvStore } from '@/components/canvas/experimental/experimentalNdv.store';
export function useLogsSelection(
execution: ComputedRef,
@@ -33,13 +34,19 @@ export function useLogsSelection(
const uiStore = useUIStore();
const canvasStore = useCanvasStore();
const workflowsStore = useWorkflowsStore();
+ const experimentalNdvStore = useExperimentalNdvStore();
function syncSelectionToCanvasIfEnabled(value: LogEntry) {
if (!logsStore.isLogSelectionSyncedWithCanvas) {
return;
}
- canvasEventBus.emit('nodes:select', { ids: [value.node.id], panIntoView: true });
+ if (experimentalNdvStore.isEnabled) {
+ canvasEventBus.emit('nodes:select', { ids: [value.node.id], panIntoView: false });
+ experimentalNdvStore.focusNode(value.node.id);
+ } else {
+ canvasEventBus.emit('nodes:select', { ids: [value.node.id], panIntoView: true });
+ }
}
function select(value: LogEntry | undefined) {