feat(editor): Add context menu to canvas v2 (no-changelog) (#10088)

This commit is contained in:
Elias Meire
2024-07-18 13:00:54 +02:00
committed by GitHub
parent 45affe5d89
commit 5b440a7679
16 changed files with 573 additions and 168 deletions

View File

@@ -9,12 +9,14 @@ import { computed, ref, watch } from 'vue';
import { getMousePosition } from '../utils/nodeViewUtils';
import { useI18n } from './useI18n';
import { usePinnedData } from './usePinnedData';
import { isPresent } from '../utils/typesUtils';
export type ContextMenuTarget =
| { source: 'canvas' }
| { source: 'node-right-click'; node: INode }
| { source: 'node-button'; node: INode };
export type ContextMenuActionCallback = (action: ContextMenuAction, targets: INode[]) => void;
| { source: 'canvas'; nodeIds: string[] }
| { source: 'node-right-click'; nodeId: string }
| { source: 'node-button'; nodeId: string };
export type ContextMenuActionCallback = (action: ContextMenuAction, nodeIds: string[]) => void;
export type ContextMenuAction =
| 'open'
| 'copy'
@@ -32,7 +34,7 @@ export type ContextMenuAction =
const position = ref<XYPosition>([0, 0]);
const isOpen = ref(false);
const target = ref<ContextMenuTarget>({ source: 'canvas' });
const target = ref<ContextMenuTarget>();
const actions = ref<ActionDropdownItem[]>([]);
const actionCallback = ref<ContextMenuActionCallback>(() => {});
@@ -48,22 +50,17 @@ export const useContextMenu = (onAction: ContextMenuActionCallback = () => {}) =
() => sourceControlStore.preferences.branchReadOnly || uiStore.isReadOnlyView,
);
const targetNodes = computed(() => {
if (!isOpen.value) return [];
const selectedNodes = uiStore.selectedNodes.map((node) =>
workflowsStore.getNodeByName(node.name),
) as INode[];
const currentTarget = target.value;
if (currentTarget.source === 'canvas') {
return selectedNodes;
} else if (currentTarget.source === 'node-right-click') {
const isNodeInSelection = selectedNodes.some((node) => node.name === currentTarget.node.name);
return isNodeInSelection ? selectedNodes : [currentTarget.node];
}
const targetNodeIds = computed(() => {
if (!isOpen.value || !target.value) return [];
return [currentTarget.node];
const currentTarget = target.value;
return currentTarget.source === 'canvas' ? currentTarget.nodeIds : [currentTarget.nodeId];
});
const targetNodes = computed(() =>
targetNodeIds.value.map((nodeId) => workflowsStore.getNodeById(nodeId)).filter(isPresent),
);
const canAddNodeOfType = (nodeType: INodeTypeDescription) => {
const sameTypeNodes = workflowsStore.allNodes.filter((n) => n.type === nodeType.name);
return nodeType.maxNodes === undefined || sameTypeNodes.length < nodeType.maxNodes;
@@ -80,17 +77,18 @@ export const useContextMenu = (onAction: ContextMenuActionCallback = () => {}) =
const hasPinData = (node: INode): boolean => {
return !!workflowsStore.pinDataByNodeName(node.name);
};
const close = () => {
target.value = { source: 'canvas' };
target.value = undefined;
isOpen.value = false;
actions.value = [];
position.value = [0, 0];
};
const open = (event: MouseEvent, menuTarget: ContextMenuTarget = { source: 'canvas' }) => {
const open = (event: MouseEvent, menuTarget: ContextMenuTarget) => {
event.stopPropagation();
if (isOpen.value && menuTarget.source === target.value.source) {
if (isOpen.value && menuTarget.source === target.value?.source) {
// Close context menu, let browser open native context menu
close();
return;
@@ -225,8 +223,8 @@ export const useContextMenu = (onAction: ContextMenuActionCallback = () => {}) =
}
};
const _dispatchAction = (action: ContextMenuAction) => {
actionCallback.value(action, targetNodes.value);
const _dispatchAction = (a: ContextMenuAction) => {
actionCallback.value(a, targetNodeIds.value);
};
watch(
@@ -241,7 +239,7 @@ export const useContextMenu = (onAction: ContextMenuActionCallback = () => {}) =
position,
target,
actions,
targetNodes,
targetNodeIds,
open,
close,
_dispatchAction,