mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
feat(editor): Open Focus Panel on canvas action button click (no-changelog) (#16698)
This commit is contained in:
@@ -1454,6 +1454,7 @@
|
|||||||
"nodeSettings.outputCleared.message": "Order of parameters changed, outgoing connections were cleared",
|
"nodeSettings.outputCleared.message": "Order of parameters changed, outgoing connections were cleared",
|
||||||
"nodeSettings.nodeVersion": "{node} node version {version}",
|
"nodeSettings.nodeVersion": "{node} node version {version}",
|
||||||
"nodeView.addNode": "Add node",
|
"nodeView.addNode": "Add node",
|
||||||
|
"nodeView.openFocusPanel": "Open focus panel",
|
||||||
"nodeView.openNodesPanel": "Open nodes panel",
|
"nodeView.openNodesPanel": "Open nodes panel",
|
||||||
"nodeView.addATriggerNodeFirst": "Add a <a data-action='showNodeCreator'>Trigger Node</a> first",
|
"nodeView.addATriggerNodeFirst": "Add a <a data-action='showNodeCreator'>Trigger Node</a> first",
|
||||||
"nodeView.addOrEnableTriggerNode": "<a data-action='showNodeCreator'>Add</a> or enable a Trigger node to execute the workflow",
|
"nodeView.addOrEnableTriggerNode": "<a data-action='showNodeCreator'>Add</a> or enable a Trigger node to execute the workflow",
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
/* eslint-disable vue/no-multiple-template-root */
|
/* eslint-disable vue/no-multiple-template-root */
|
||||||
import { defineAsyncComponent, onBeforeUnmount, onMounted, ref } from 'vue';
|
import { computed, defineAsyncComponent, onBeforeUnmount, onMounted, ref } from 'vue';
|
||||||
import { getMidCanvasPosition } from '@/utils/nodeViewUtils';
|
import { getMidCanvasPosition } from '@/utils/nodeViewUtils';
|
||||||
import {
|
import {
|
||||||
DEFAULT_STICKY_HEIGHT,
|
DEFAULT_STICKY_HEIGHT,
|
||||||
DEFAULT_STICKY_WIDTH,
|
DEFAULT_STICKY_WIDTH,
|
||||||
|
FOCUS_PANEL_EXPERIMENT,
|
||||||
NODE_CREATOR_OPEN_SOURCES,
|
NODE_CREATOR_OPEN_SOURCES,
|
||||||
STICKY_NODE_TYPE,
|
STICKY_NODE_TYPE,
|
||||||
} from '@/constants';
|
} from '@/constants';
|
||||||
import { useUIStore } from '@/stores/ui.store';
|
import { useUIStore } from '@/stores/ui.store';
|
||||||
|
import { useFocusPanelStore } from '@/stores/focusPanel.store';
|
||||||
|
import { usePostHog } from '@/stores/posthog.store';
|
||||||
import type {
|
import type {
|
||||||
AddedNodesAndConnections,
|
AddedNodesAndConnections,
|
||||||
NodeTypeSelectedPayload,
|
NodeTypeSelectedPayload,
|
||||||
@@ -39,6 +42,8 @@ const emit = defineEmits<{
|
|||||||
}>();
|
}>();
|
||||||
|
|
||||||
const uiStore = useUIStore();
|
const uiStore = useUIStore();
|
||||||
|
const focusPanelStore = useFocusPanelStore();
|
||||||
|
const posthogStore = usePostHog();
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
|
|
||||||
const { getAddedNodesAndConnections } = useActions();
|
const { getAddedNodesAndConnections } = useActions();
|
||||||
@@ -46,6 +51,9 @@ const { getAddedNodesAndConnections } = useActions();
|
|||||||
const wrapperRef = ref<HTMLElement | undefined>();
|
const wrapperRef = ref<HTMLElement | undefined>();
|
||||||
const wrapperBoundingRect = ref<DOMRect | undefined>();
|
const wrapperBoundingRect = ref<DOMRect | undefined>();
|
||||||
const isStickyNotesButtonVisible = ref(true);
|
const isStickyNotesButtonVisible = ref(true);
|
||||||
|
const isOpenFocusPanelButtonVisible = computed(() => {
|
||||||
|
return posthogStore.getVariant(FOCUS_PANEL_EXPERIMENT.name) === FOCUS_PANEL_EXPERIMENT.variant;
|
||||||
|
});
|
||||||
|
|
||||||
const onMouseMove = useThrottleFn((event: MouseEvent) => {
|
const onMouseMove = useThrottleFn((event: MouseEvent) => {
|
||||||
if (wrapperBoundingRect.value) {
|
if (wrapperBoundingRect.value) {
|
||||||
@@ -111,7 +119,7 @@ onBeforeUnmount(() => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="!createNodeActive" :class="$style.nodeButtonsWrapper">
|
<div v-if="!createNodeActive" :class="$style.nodeButtonsWrapper">
|
||||||
<div ref="wrapperRef" :class="$style.nodeCreatorButton" data-test-id="node-creator-plus-button">
|
<div ref="wrapperRef" :class="$style.nodeCreatorButton">
|
||||||
<KeyboardShortcutTooltip
|
<KeyboardShortcutTooltip
|
||||||
:label="i18n.baseText('nodeView.openNodesPanel')"
|
:label="i18n.baseText('nodeView.openNodesPanel')"
|
||||||
:shortcut="{ keys: ['Tab'] }"
|
:shortcut="{ keys: ['Tab'] }"
|
||||||
@@ -121,7 +129,7 @@ onBeforeUnmount(() => {
|
|||||||
size="large"
|
size="large"
|
||||||
icon="plus"
|
icon="plus"
|
||||||
type="tertiary"
|
type="tertiary"
|
||||||
:class="$style.nodeCreatorPlus"
|
data-test-id="node-creator-plus-button"
|
||||||
@click="openNodeCreator"
|
@click="openNodeCreator"
|
||||||
/>
|
/>
|
||||||
</KeyboardShortcutTooltip>
|
</KeyboardShortcutTooltip>
|
||||||
@@ -138,6 +146,19 @@ onBeforeUnmount(() => {
|
|||||||
<n8n-icon-button type="tertiary" :icon="['far', 'note-sticky']" />
|
<n8n-icon-button type="tertiary" :icon="['far', 'note-sticky']" />
|
||||||
</KeyboardShortcutTooltip>
|
</KeyboardShortcutTooltip>
|
||||||
</div>
|
</div>
|
||||||
|
<KeyboardShortcutTooltip
|
||||||
|
v-if="isOpenFocusPanelButtonVisible"
|
||||||
|
:label="i18n.baseText('nodeView.openFocusPanel')"
|
||||||
|
:shortcut="{ keys: ['f'], shiftKey: true }"
|
||||||
|
placement="left"
|
||||||
|
>
|
||||||
|
<n8n-icon-button
|
||||||
|
type="tertiary"
|
||||||
|
size="large"
|
||||||
|
icon="list"
|
||||||
|
@click="focusPanelStore.toggleFocusPanel"
|
||||||
|
/>
|
||||||
|
</KeyboardShortcutTooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Suspense>
|
<Suspense>
|
||||||
@@ -169,10 +190,6 @@ onBeforeUnmount(() => {
|
|||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
.noEvents {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nodeCreatorButton {
|
.nodeCreatorButton {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -180,8 +197,4 @@ onBeforeUnmount(() => {
|
|||||||
right: var(--spacing-s);
|
right: var(--spacing-s);
|
||||||
pointer-events: all !important;
|
pointer-events: all !important;
|
||||||
}
|
}
|
||||||
.nodeCreatorPlus {
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ const emit = defineEmits<{
|
|||||||
'create:workflow': [];
|
'create:workflow': [];
|
||||||
'drag-and-drop': [position: XYPosition, event: DragEvent];
|
'drag-and-drop': [position: XYPosition, event: DragEvent];
|
||||||
'tidy-up': [CanvasLayoutEvent];
|
'tidy-up': [CanvasLayoutEvent];
|
||||||
|
'toggle:focus-panel': [];
|
||||||
'viewport:change': [viewport: ViewportTransform, dimensions: Dimensions];
|
'viewport:change': [viewport: ViewportTransform, dimensions: Dimensions];
|
||||||
'selection:end': [position: XYPosition];
|
'selection:end': [position: XYPosition];
|
||||||
'open:sub-workflow': [nodeId: string];
|
'open:sub-workflow': [nodeId: string];
|
||||||
@@ -315,6 +316,7 @@ const keyMap = computed(() => {
|
|||||||
f2: emitWithLastSelectedNode((id) => emit('update:node:name', id)),
|
f2: emitWithLastSelectedNode((id) => emit('update:node:name', id)),
|
||||||
tab: () => emit('create:node', 'tab'),
|
tab: () => emit('create:node', 'tab'),
|
||||||
shift_s: () => emit('create:sticky'),
|
shift_s: () => emit('create:sticky'),
|
||||||
|
shift_f: () => emit('toggle:focus-panel'),
|
||||||
ctrl_alt_n: () => emit('create:workflow'),
|
ctrl_alt_n: () => emit('create:workflow'),
|
||||||
ctrl_enter: () => emit('run:workflow'),
|
ctrl_enter: () => emit('run:workflow'),
|
||||||
ctrl_s: () => emit('save:workflow'),
|
ctrl_s: () => emit('save:workflow'),
|
||||||
|
|||||||
@@ -27,10 +27,15 @@ export const useFocusPanelStore = defineStore(STORES.FOCUS_PANEL, () => {
|
|||||||
focusPanelActive.value = false;
|
focusPanelActive.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const toggleFocusPanel = () => {
|
||||||
|
focusPanelActive.value = !focusPanelActive.value;
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
focusPanelActive,
|
focusPanelActive,
|
||||||
focusedNodeParameters,
|
focusedNodeParameters,
|
||||||
setFocusedNodeParameter,
|
setFocusedNodeParameter,
|
||||||
closeFocusPanel,
|
closeFocusPanel,
|
||||||
|
toggleFocusPanel,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ import { needsAgentInput } from '@/utils/nodes/nodeTransforms';
|
|||||||
import { useLogsStore } from '@/stores/logs.store';
|
import { useLogsStore } from '@/stores/logs.store';
|
||||||
import { canvasEventBus } from '@/event-bus/canvas';
|
import { canvasEventBus } from '@/event-bus/canvas';
|
||||||
import CanvasChatButton from '@/components/canvas/elements/buttons/CanvasChatButton.vue';
|
import CanvasChatButton from '@/components/canvas/elements/buttons/CanvasChatButton.vue';
|
||||||
|
import { useFocusPanelStore } from '@/stores/focusPanel.store';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'NodeView',
|
name: 'NodeView',
|
||||||
@@ -186,6 +187,7 @@ const usersStore = useUsersStore();
|
|||||||
const tagsStore = useTagsStore();
|
const tagsStore = useTagsStore();
|
||||||
const pushConnectionStore = usePushConnectionStore();
|
const pushConnectionStore = usePushConnectionStore();
|
||||||
const ndvStore = useNDVStore();
|
const ndvStore = useNDVStore();
|
||||||
|
const focusPanelStore = useFocusPanelStore();
|
||||||
const templatesStore = useTemplatesStore();
|
const templatesStore = useTemplatesStore();
|
||||||
const builderStore = useBuilderStore();
|
const builderStore = useBuilderStore();
|
||||||
const foldersStore = useFoldersStore();
|
const foldersStore = useFoldersStore();
|
||||||
@@ -1207,6 +1209,14 @@ function onToggleNodeCreator(options: ToggleNodeCreatorOptions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onToggleFocusPanel() {
|
||||||
|
if (!isFocusPanelFeatureEnabled.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
focusPanelStore.toggleFocusPanel();
|
||||||
|
}
|
||||||
|
|
||||||
function closeNodeCreator() {
|
function closeNodeCreator() {
|
||||||
if (nodeCreatorStore.isCreateNodeActive) {
|
if (nodeCreatorStore.isCreateNodeActive) {
|
||||||
nodeCreatorStore.isCreateNodeActive = false;
|
nodeCreatorStore.isCreateNodeActive = false;
|
||||||
@@ -2039,6 +2049,7 @@ onBeforeUnmount(() => {
|
|||||||
@selection:end="onSelectionEnd"
|
@selection:end="onSelectionEnd"
|
||||||
@drag-and-drop="onDragAndDrop"
|
@drag-and-drop="onDragAndDrop"
|
||||||
@tidy-up="onTidyUp"
|
@tidy-up="onTidyUp"
|
||||||
|
@toggle:focus-panel="onToggleFocusPanel"
|
||||||
@extract-workflow="onExtractWorkflow"
|
@extract-workflow="onExtractWorkflow"
|
||||||
@start-chat="startChat()"
|
@start-chat="startChat()"
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user