mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-20 19:32:15 +00:00
feat(editor): Add context menu to canvas v2 (no-changelog) (#10088)
This commit is contained in:
@@ -24,6 +24,7 @@ import type {
|
||||
IWorkflowDataUpdate,
|
||||
IWorkflowDb,
|
||||
IWorkflowTemplate,
|
||||
NodeCreatorOpenSource,
|
||||
ToggleNodeCreatorOptions,
|
||||
XYPosition,
|
||||
} from '@/Interface';
|
||||
@@ -40,6 +41,7 @@ import {
|
||||
NODE_CREATOR_OPEN_SOURCES,
|
||||
PLACEHOLDER_EMPTY_WORKFLOW_ID,
|
||||
START_NODE_TYPE,
|
||||
STICKY_NODE_TYPE,
|
||||
VIEWS,
|
||||
} from '@/constants';
|
||||
import { useSourceControlStore } from '@/stores/sourceControl.store';
|
||||
@@ -80,6 +82,7 @@ import * as NodeViewUtils from '@/utils/nodeViewUtils';
|
||||
import { tryToParseNumber } from '@/utils/typesUtils';
|
||||
import { useTemplatesStore } from '@/stores/templates.store';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import type { PinDataSource } from '@/composables/usePinnedData';
|
||||
|
||||
const NodeCreation = defineAsyncComponent(
|
||||
async () => await import('@/components/Node/NodeCreation.vue'),
|
||||
@@ -133,9 +136,11 @@ const {
|
||||
revertRenameNode,
|
||||
setNodeActive,
|
||||
setNodeSelected,
|
||||
toggleNodeDisabled,
|
||||
toggleNodesDisabled,
|
||||
toggleNodesPinned,
|
||||
setNodeParameters,
|
||||
deleteNode,
|
||||
deleteNodes,
|
||||
revertDeleteNode,
|
||||
addNodes,
|
||||
createConnection,
|
||||
@@ -438,6 +443,10 @@ function onDeleteNode(id: string) {
|
||||
deleteNode(id, { trackHistory: true });
|
||||
}
|
||||
|
||||
function onDeleteNodes(ids: string[]) {
|
||||
deleteNodes(ids);
|
||||
}
|
||||
|
||||
function onRevertDeleteNode({ node }: { node: INodeUi }) {
|
||||
revertDeleteNode(node);
|
||||
}
|
||||
@@ -447,7 +456,15 @@ function onToggleNodeDisabled(id: string) {
|
||||
return;
|
||||
}
|
||||
|
||||
toggleNodeDisabled(id);
|
||||
toggleNodesDisabled([id]);
|
||||
}
|
||||
|
||||
function onToggleNodesDisabled(ids: string[]) {
|
||||
if (!checkIfEditingIsAllowed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
toggleNodesDisabled(ids);
|
||||
}
|
||||
|
||||
function onSetNodeActive(id: string) {
|
||||
@@ -458,12 +475,77 @@ function onSetNodeSelected(id?: string) {
|
||||
setNodeSelected(id);
|
||||
}
|
||||
|
||||
function onCopyNodes(_ids: string[]) {
|
||||
// @TODO: implement this
|
||||
}
|
||||
|
||||
function onCutNodes(_ids: string[]) {
|
||||
// @TODO: implement this
|
||||
}
|
||||
|
||||
function onDuplicateNodes(_ids: string[]) {
|
||||
// @TODO: implement this
|
||||
}
|
||||
|
||||
function onPinNodes(ids: string[], source: PinDataSource) {
|
||||
if (!checkIfEditingIsAllowed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
toggleNodesPinned(ids, source);
|
||||
}
|
||||
|
||||
async function onSaveWorkflow() {
|
||||
await workflowHelpers.saveCurrentWorkflow();
|
||||
}
|
||||
|
||||
async function onCreateWorkflow() {
|
||||
await router.push({ name: VIEWS.NEW_WORKFLOW });
|
||||
}
|
||||
|
||||
function onRenameNode(parameterData: IUpdateInformation) {
|
||||
if (parameterData.name === 'name' && parameterData.oldValue) {
|
||||
void renameNode(parameterData.oldValue as string, parameterData.value as string);
|
||||
}
|
||||
}
|
||||
|
||||
async function onOpenRenameNodeModal(id: string) {
|
||||
const currentName = workflowsStore.getNodeById(id)?.name ?? '';
|
||||
try {
|
||||
const promptResponsePromise = message.prompt(
|
||||
i18n.baseText('nodeView.prompt.newName') + ':',
|
||||
i18n.baseText('nodeView.prompt.renameNode') + `: ${currentName}`,
|
||||
{
|
||||
customClass: 'rename-prompt',
|
||||
confirmButtonText: i18n.baseText('nodeView.prompt.rename'),
|
||||
cancelButtonText: i18n.baseText('nodeView.prompt.cancel'),
|
||||
inputErrorMessage: i18n.baseText('nodeView.prompt.invalidName'),
|
||||
inputValue: currentName,
|
||||
inputValidator: (value: string) => {
|
||||
if (!value.trim()) {
|
||||
return i18n.baseText('nodeView.prompt.invalidName');
|
||||
}
|
||||
return true;
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
// Wait till input is displayed
|
||||
await nextTick();
|
||||
|
||||
// Focus and select input content
|
||||
const nameInput = document.querySelector<HTMLInputElement>('.rename-prompt .el-input__inner');
|
||||
nameInput?.focus();
|
||||
nameInput?.select();
|
||||
|
||||
const promptResponse = await promptResponsePromise;
|
||||
|
||||
if (promptResponse.action === MODAL_CONFIRM) {
|
||||
await renameNode(currentName, promptResponse.value, { trackHistory: true });
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
async function onRevertRenameNode({
|
||||
currentName,
|
||||
newName,
|
||||
@@ -626,10 +708,18 @@ async function onOpenSelectiveNodeCreator(node: string, connectionType: NodeConn
|
||||
nodeCreatorStore.openSelectiveNodeCreator({ node, connectionType });
|
||||
}
|
||||
|
||||
function onOpenNodeCreatorFromCanvas(source: NodeCreatorOpenSource) {
|
||||
onOpenNodeCreator({ createNodeActive: true, source });
|
||||
}
|
||||
|
||||
function onOpenNodeCreator(options: ToggleNodeCreatorOptions) {
|
||||
nodeCreatorStore.openNodeCreator(options);
|
||||
}
|
||||
|
||||
function onCreateSticky() {
|
||||
void onAddNodesAndConnections({ nodes: [{ type: STICKY_NODE_TYPE }], connections: [] });
|
||||
}
|
||||
|
||||
function onClickConnectionAdd(connection: Connection) {
|
||||
nodeCreatorStore.openNodeCreatorForConnectingNode({
|
||||
connection,
|
||||
@@ -1156,6 +1246,7 @@ onBeforeUnmount(() => {
|
||||
@update:node:active="onSetNodeActive"
|
||||
@update:node:selected="onSetNodeSelected"
|
||||
@update:node:enabled="onToggleNodeDisabled"
|
||||
@update:node:name="onOpenRenameNodeModal"
|
||||
@update:node:parameters="onUpdateNodeParameters"
|
||||
@run:node="onRunWorkflowToNode"
|
||||
@delete:node="onDeleteNode"
|
||||
@@ -1164,6 +1255,17 @@ onBeforeUnmount(() => {
|
||||
@delete:connection="onDeleteConnection"
|
||||
@click:connection:add="onClickConnectionAdd"
|
||||
@click:pane="onClickPane"
|
||||
@create:node="onOpenNodeCreatorFromCanvas"
|
||||
@create:sticky="onCreateSticky"
|
||||
@delete:nodes="onDeleteNodes"
|
||||
@update:nodes:enabled="onToggleNodesDisabled"
|
||||
@update:nodes:pin="onPinNodes"
|
||||
@duplicate:nodes="onDuplicateNodes"
|
||||
@copy:nodes="onCopyNodes"
|
||||
@cut:nodes="onCutNodes"
|
||||
@run:workflow="onRunWorkflow"
|
||||
@save:workflow="onSaveWorkflow"
|
||||
@create:workflow="onCreateWorkflow"
|
||||
>
|
||||
<div :class="$style.executionButtons">
|
||||
<CanvasRunWorkflowButton
|
||||
|
||||
Reference in New Issue
Block a user