diff --git a/packages/editor-ui/src/components/canvas/Canvas.vue b/packages/editor-ui/src/components/canvas/Canvas.vue index b5f31db044..0fc66def2c 100644 --- a/packages/editor-ui/src/components/canvas/Canvas.vue +++ b/packages/editor-ui/src/components/canvas/Canvas.vue @@ -17,6 +17,7 @@ const emit = defineEmits<{ 'update:node:active': [id: string]; 'update:node:enabled': [id: string]; 'update:node:selected': [id?: string]; + 'run:node': [id: string]; 'delete:node': [id: string]; 'delete:connection': [connection: Connection]; 'create:connection': [connection: Connection]; @@ -79,6 +80,10 @@ function onDeleteNode(id: string) { emit('delete:node', id); } +function onRunNode(id: string) { + emit('run:node', id); +} + function onDeleteConnection(connection: Connection) { emit('delete:connection', connection); } @@ -135,6 +140,7 @@ function onClickPane(event: MouseEvent) { @@ -164,19 +170,21 @@ function onActivate() { .canvasNode { &:hover { .canvasNodeToolbar { - display: flex; opacity: 1; } } } .canvasNodeToolbar { - display: none; + transition: opacity 0.1s ease-in; position: absolute; top: 0; left: 50%; transform: translate(-50%, -100%); opacity: 0; - transition: opacity 0.3s ease; +} + +.canvasNodeToolbar:focus-within { + opacity: 1; } diff --git a/packages/editor-ui/src/components/canvas/elements/nodes/CanvasNodeToolbar.vue b/packages/editor-ui/src/components/canvas/elements/nodes/CanvasNodeToolbar.vue index 3743e1f0c4..782b19022b 100644 --- a/packages/editor-ui/src/components/canvas/elements/nodes/CanvasNodeToolbar.vue +++ b/packages/editor-ui/src/components/canvas/elements/nodes/CanvasNodeToolbar.vue @@ -6,6 +6,7 @@ import { useI18n } from '@/composables/useI18n'; const emit = defineEmits<{ delete: []; toggle: []; + run: []; }>(); const $style = useCssModule(); @@ -20,8 +21,9 @@ const workflowRunning = false; // @TODO const nodeDisabledTitle = 'Test'; -// @TODO -function executeNode() {} +function executeNode() { + emit('run'); +} function onToggleNode() { emit('toggle'); @@ -81,12 +83,17 @@ function openContextMenu(_e: MouseEvent, _type: string) {} diff --git a/packages/editor-ui/src/views/NodeView.v2.vue b/packages/editor-ui/src/views/NodeView.v2.vue index dedc2e239e..ea2cef1be6 100644 --- a/packages/editor-ui/src/views/NodeView.v2.vue +++ b/packages/editor-ui/src/views/NodeView.v2.vue @@ -74,6 +74,7 @@ import { sourceControlEventBus } from '@/event-bus/source-control'; import { useTagsStore } from '@/stores/tags.store'; import { usePushConnectionStore } from '@/stores/pushConnection.store'; import { getNodeViewTab } from '@/utils/canvasUtils'; +import { useNDVStore } from '@/stores/ndv.store'; const NodeCreation = defineAsyncComponent( async () => await import('@/components/Node/NodeCreation.vue'), @@ -115,6 +116,7 @@ const projectsStore = useProjectsStore(); const usersStore = useUsersStore(); const tagsStore = useTagsStore(); const pushConnectionStore = usePushConnectionStore(); +const ndvStore = useNDVStore(); const lastClickPosition = ref([450, 450]); @@ -557,6 +559,26 @@ function trackRunWorkflow() { }); } +async function onRunWorkflowToNode(id: string) { + const node = workflowsStore.getNodeById(id); + if (!node) return; + + trackRunWorkflowToNode(node); + await runWorkflow({ destinationNode: node.name, source: 'Node.executeNode' }); +} + +function trackRunWorkflowToNode(node: INodeUi) { + const telemetryPayload = { + node_type: node.type, + workflow_id: workflowsStore.workflowId, + source: 'canvas', + push_ref: ndvStore.pushRef, + }; + + telemetry.track('User clicked execute node button', telemetryPayload); + void externalHooks.run('nodeView.onRunNode', telemetryPayload); +} + async function openExecution(_executionId: string) { // @TODO } @@ -909,6 +931,7 @@ onBeforeUnmount(() => { @update:node:active="onSetNodeActive" @update:node:selected="onSetNodeSelected" @update:node:enabled="onToggleNodeDisabled" + @run:node="onRunWorkflowToNode" @delete:node="onDeleteNode" @create:connection="onCreateConnection" @delete:connection="onDeleteConnection"