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"