feat(editor): Add context menu to canvas v2 (no-changelog) (#10088)
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user