mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-21 02:56:40 -08:00
feat(editor): Add support for changing sticky notes color in new canvas (no-changelog) (#10593)
This commit is contained in:
parent
821ca16a57
commit
c988931898
|
@ -3,11 +3,14 @@ import { ref } from 'vue';
|
|||
import type {
|
||||
CanvasNode,
|
||||
CanvasNodeData,
|
||||
CanvasNodeEventBusEvents,
|
||||
CanvasNodeHandleInjectionData,
|
||||
CanvasNodeInjectionData,
|
||||
} from '@/types';
|
||||
import { CanvasConnectionMode, CanvasNodeRenderType } from '@/types';
|
||||
import { NodeConnectionType } from 'n8n-workflow';
|
||||
import type { EventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
|
||||
export function createCanvasNodeData({
|
||||
id = 'node',
|
||||
|
@ -89,11 +92,13 @@ export function createCanvasNodeProvide({
|
|||
label = 'Test Node',
|
||||
selected = false,
|
||||
data = {},
|
||||
eventBus = createEventBus<CanvasNodeEventBusEvents>(),
|
||||
}: {
|
||||
id?: string;
|
||||
label?: string;
|
||||
selected?: boolean;
|
||||
data?: Partial<CanvasNodeData>;
|
||||
eventBus?: EventBus<CanvasNodeEventBusEvents>;
|
||||
} = {}) {
|
||||
const props = createCanvasNodeProps({ id, label, selected, data });
|
||||
return {
|
||||
|
@ -102,6 +107,7 @@ export function createCanvasNodeProvide({
|
|||
label: ref(props.label),
|
||||
selected: ref(props.selected),
|
||||
data: ref(props.data),
|
||||
eventBus: ref(eventBus),
|
||||
} satisfies CanvasNodeInjectionData,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
<script lang="ts" setup>
|
||||
import type { CanvasConnection, CanvasNode, CanvasNodeMoveEvent, ConnectStartEvent } from '@/types';
|
||||
import type {
|
||||
CanvasConnection,
|
||||
CanvasNode,
|
||||
CanvasNodeMoveEvent,
|
||||
CanvasEventBusEvents,
|
||||
ConnectStartEvent,
|
||||
} from '@/types';
|
||||
import type {
|
||||
EdgeMouseEvent,
|
||||
Connection,
|
||||
|
@ -65,7 +71,7 @@ const props = withDefaults(
|
|||
nodes: CanvasNode[];
|
||||
connections: CanvasConnection[];
|
||||
controlsPosition?: PanelPosition;
|
||||
eventBus?: EventBus;
|
||||
eventBus?: EventBus<CanvasEventBusEvents>;
|
||||
readOnly?: boolean;
|
||||
}>(),
|
||||
{
|
||||
|
@ -102,8 +108,8 @@ useKeybindings({
|
|||
ctrl_d: emitWithSelectedNodes((ids) => emit('duplicate:nodes', ids)),
|
||||
d: emitWithSelectedNodes((ids) => emit('update:nodes:enabled', ids)),
|
||||
p: emitWithSelectedNodes((ids) => emit('update:nodes:pin', ids, 'keyboard-shortcut')),
|
||||
enter: () => emitWithLastSelectedNode((id) => emit('update:node:active', id)),
|
||||
f2: () => emitWithLastSelectedNode((id) => emit('update:node:name', id)),
|
||||
enter: emitWithLastSelectedNode((id) => onSetNodeActive(id)),
|
||||
f2: emitWithLastSelectedNode((id) => emit('update:node:name', id)),
|
||||
tab: () => emit('create:node', 'tab'),
|
||||
shift_s: () => emit('create:sticky'),
|
||||
ctrl_alt_n: () => emit('create:workflow'),
|
||||
|
@ -154,6 +160,7 @@ function onNodesChange(events: NodeChange[]) {
|
|||
}
|
||||
|
||||
function onSetNodeActive(id: string) {
|
||||
props.eventBus.emit('nodes:action', { ids: [id], action: 'update:node:active' });
|
||||
emit('update:node:active', id);
|
||||
}
|
||||
|
||||
|
@ -166,7 +173,7 @@ function onSelectNode() {
|
|||
emit('update:node:selected', lastSelectedNode.value.id);
|
||||
}
|
||||
|
||||
function onSelectNodes(ids: string[]) {
|
||||
function onSelectNodes({ ids }: CanvasEventBusEvents['nodes:select']) {
|
||||
clearSelectedNodes();
|
||||
addSelectedNodes(ids.map(findNode).filter(isPresent));
|
||||
}
|
||||
|
@ -358,9 +365,11 @@ function onContextMenuAction(action: ContextMenuAction, nodeIds: string[]) {
|
|||
case 'toggle_activation':
|
||||
return emit('update:nodes:enabled', nodeIds);
|
||||
case 'open':
|
||||
return emit('update:node:active', nodeIds[0]);
|
||||
return onSetNodeActive(nodeIds[0]);
|
||||
case 'rename':
|
||||
return emit('update:node:name', nodeIds[0]);
|
||||
case 'change_color':
|
||||
return props.eventBus.emit('nodes:action', { ids: nodeIds, action: 'update:sticky:color' });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,12 +387,12 @@ function minimapNodeClassnameFn(node: CanvasNode) {
|
|||
|
||||
onMounted(() => {
|
||||
props.eventBus.on('fitView', onFitView);
|
||||
props.eventBus.on('selectNodes', onSelectNodes);
|
||||
props.eventBus.on('nodes:select', onSelectNodes);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
props.eventBus.off('fitView', onFitView);
|
||||
props.eventBus.off('selectNodes', onSelectNodes);
|
||||
props.eventBus.off('nodes:select', onSelectNodes);
|
||||
});
|
||||
|
||||
onPaneReady(async () => {
|
||||
|
@ -431,6 +440,7 @@ provide(CanvasKey, {
|
|||
<Node
|
||||
v-bind="canvasNodeProps"
|
||||
:read-only="readOnly"
|
||||
:event-bus="eventBus"
|
||||
@delete="onDeleteNode"
|
||||
@run="onRunNode"
|
||||
@select="onSelectNode"
|
||||
|
|
|
@ -6,6 +6,7 @@ import type { IWorkflowDb } from '@/Interface';
|
|||
import { useCanvasMapping } from '@/composables/useCanvasMapping';
|
||||
import type { EventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
import type { CanvasEventBusEvents } from '@/types';
|
||||
import { STICKY_NODE_TYPE } from '@/constants';
|
||||
|
||||
defineOptions({
|
||||
|
@ -18,12 +19,12 @@ const props = withDefaults(
|
|||
workflow: IWorkflowDb;
|
||||
workflowObject: Workflow;
|
||||
fallbackNodes?: IWorkflowDb['nodes'];
|
||||
eventBus?: EventBus;
|
||||
eventBus?: EventBus<CanvasEventBusEvents>;
|
||||
readOnly?: boolean;
|
||||
}>(),
|
||||
{
|
||||
id: 'canvas',
|
||||
eventBus: () => createEventBus(),
|
||||
eventBus: () => createEventBus<CanvasEventBusEvents>(),
|
||||
fallbackNodes: () => [],
|
||||
},
|
||||
);
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed, provide, toRef, watch } from 'vue';
|
||||
import { computed, onBeforeUnmount, onMounted, provide, ref, toRef, watch } from 'vue';
|
||||
import type {
|
||||
CanvasConnectionPort,
|
||||
CanvasElementPortWithRenderData,
|
||||
CanvasNodeData,
|
||||
CanvasNodeEventBusEvents,
|
||||
CanvasEventBusEvents,
|
||||
} from '@/types';
|
||||
import { CanvasConnectionMode } from '@/types';
|
||||
import NodeIcon from '@/components/NodeIcon.vue';
|
||||
|
@ -18,9 +20,12 @@ import type { NodeProps, XYPosition } from '@vue-flow/core';
|
|||
import { Position } from '@vue-flow/core';
|
||||
import { useCanvas } from '@/composables/useCanvas';
|
||||
import { createCanvasConnectionHandleString } from '@/utils/canvasUtilsV2';
|
||||
import type { EventBus } from 'n8n-design-system';
|
||||
import { createEventBus } from 'n8n-design-system';
|
||||
|
||||
type Props = NodeProps<CanvasNodeData> & {
|
||||
readOnly?: boolean;
|
||||
eventBus?: EventBus<CanvasEventBusEvents>;
|
||||
};
|
||||
|
||||
const emit = defineEmits<{
|
||||
|
@ -58,6 +63,18 @@ const nodeTypeDescription = computed(() => {
|
|||
return nodeTypesStore.getNodeType(props.data.type, props.data.typeVersion);
|
||||
});
|
||||
|
||||
/**
|
||||
* Event bus
|
||||
*/
|
||||
|
||||
const canvasNodeEventBus = ref(createEventBus<CanvasNodeEventBusEvents>());
|
||||
|
||||
function emitCanvasNodeEvent(event: CanvasEventBusEvents['nodes:action']) {
|
||||
if (event.ids.includes(props.id)) {
|
||||
canvasNodeEventBus.value.emit(event.action, event.payload);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inputs
|
||||
*/
|
||||
|
@ -208,6 +225,7 @@ provide(CanvasNodeKey, {
|
|||
data,
|
||||
label,
|
||||
selected,
|
||||
eventBus: canvasNodeEventBus,
|
||||
});
|
||||
|
||||
const showToolbar = computed(() => {
|
||||
|
@ -225,6 +243,14 @@ watch(
|
|||
emit('select', props.id, value);
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
props.eventBus?.on('nodes:action', emitCanvasNodeEvent);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
props.eventBus?.off('nodes:action', emitCanvasNodeEvent);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -272,6 +298,7 @@ watch(
|
|||
@delete="onDelete"
|
||||
@toggle="onDisabledToggle"
|
||||
@run="onRun"
|
||||
@update="onUpdate"
|
||||
@open:contextmenu="onOpenContextMenuFromToolbar"
|
||||
/>
|
||||
|
||||
|
@ -296,6 +323,7 @@ watch(
|
|||
<style lang="scss" module>
|
||||
.canvasNode {
|
||||
&:hover,
|
||||
&:focus-within,
|
||||
&.showToolbar {
|
||||
.canvasNodeToolbar {
|
||||
opacity: 1;
|
||||
|
@ -311,5 +339,10 @@ watch(
|
|||
transform: translate(-50%, -100%);
|
||||
opacity: 0;
|
||||
z-index: 1;
|
||||
|
||||
&:focus-within,
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -8,6 +8,7 @@ const emit = defineEmits<{
|
|||
delete: [];
|
||||
toggle: [];
|
||||
run: [];
|
||||
update: [parameters: Record<string, unknown>];
|
||||
'open:contextmenu': [event: MouseEvent];
|
||||
}>();
|
||||
|
||||
|
@ -46,6 +47,8 @@ const isDisableNodeVisible = computed(() => {
|
|||
|
||||
const isDeleteNodeVisible = computed(() => !props.readOnly);
|
||||
|
||||
const isStickyNoteNodeType = computed(() => render.value.type === CanvasNodeRenderType.StickyNote);
|
||||
|
||||
function executeNode() {
|
||||
emit('run');
|
||||
}
|
||||
|
@ -58,6 +61,12 @@ function onDeleteNode() {
|
|||
emit('delete');
|
||||
}
|
||||
|
||||
function onChangeStickyColor(color: number) {
|
||||
emit('update', {
|
||||
color,
|
||||
});
|
||||
}
|
||||
|
||||
function onOpenContextMenu(event: MouseEvent) {
|
||||
emit('open:contextmenu', event);
|
||||
}
|
||||
|
@ -97,6 +106,7 @@ function onOpenContextMenu(event: MouseEvent) {
|
|||
:title="i18n.baseText('node.delete')"
|
||||
@click="onDeleteNode"
|
||||
/>
|
||||
<CanvasNodeStickyColorSelector v-if="isStickyNoteNodeType" @update="onChangeStickyColor" />
|
||||
<N8nIconButton
|
||||
data-test-id="overflow-node-button"
|
||||
type="tertiary"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
/* eslint-disable vue/no-multiple-template-root */
|
||||
import { useCanvasNode } from '@/composables/useCanvasNode';
|
||||
import type { CanvasNodeStickyNoteRender } from '@/types';
|
||||
import { ref, computed, useCssModule } from 'vue';
|
||||
import { ref, computed, useCssModule, onMounted, onBeforeUnmount } from 'vue';
|
||||
import { NodeResizer } from '@vue-flow/node-resizer';
|
||||
import type { OnResize } from '@vue-flow/node-resizer/dist/types';
|
||||
import type { XYPosition } from '@vue-flow/core';
|
||||
|
@ -15,11 +15,12 @@ const emit = defineEmits<{
|
|||
update: [parameters: Record<string, unknown>];
|
||||
move: [position: XYPosition];
|
||||
dblclick: [event: MouseEvent];
|
||||
'open:contextmenu': [event: MouseEvent];
|
||||
}>();
|
||||
|
||||
const $style = useCssModule();
|
||||
|
||||
const { id, isSelected, render } = useCanvasNode();
|
||||
const { id, isSelected, render, eventBus } = useCanvasNode();
|
||||
|
||||
const renderOptions = computed(() => render.value.options as CanvasNodeStickyNoteRender['options']);
|
||||
|
||||
|
@ -63,6 +64,30 @@ function onEdit(edit: boolean) {
|
|||
function onDoubleClick(event: MouseEvent) {
|
||||
emit('dblclick', event);
|
||||
}
|
||||
|
||||
function onActivate() {
|
||||
onEdit(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Context menu
|
||||
*/
|
||||
|
||||
function openContextMenu(event: MouseEvent) {
|
||||
emit('open:contextmenu', event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lifecycle
|
||||
*/
|
||||
|
||||
onMounted(() => {
|
||||
eventBus.value?.on('update:node:active', onActivate);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
eventBus.value?.off('update:node:active', onActivate);
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<NodeResizer
|
||||
|
@ -80,11 +105,12 @@ function onDoubleClick(event: MouseEvent) {
|
|||
:height="renderOptions.height"
|
||||
:width="renderOptions.width"
|
||||
:model-value="renderOptions.content"
|
||||
:background="renderOptions.color"
|
||||
:background-color="renderOptions.color"
|
||||
:edit-mode="isActive"
|
||||
@edit="onEdit"
|
||||
@dblclick="onDoubleClick"
|
||||
@update:model-value="onInputChange"
|
||||
@contextmenu="openContextMenu"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
import { fireEvent } from '@testing-library/vue';
|
||||
import CanvasNodeStickyColorSelector from '@/components/canvas/elements/nodes/toolbar/CanvasNodeStickyColorSelector.vue';
|
||||
import { createComponentRenderer } from '@/__tests__/render';
|
||||
import { createCanvasNodeProvide } from '@/__tests__/data';
|
||||
|
||||
const renderComponent = createComponentRenderer(CanvasNodeStickyColorSelector);
|
||||
|
||||
describe('CanvasNodeStickyColorSelector', () => {
|
||||
it('should render trigger correctly', () => {
|
||||
const { getByTestId } = renderComponent({
|
||||
global: {
|
||||
provide: {
|
||||
...createCanvasNodeProvide(),
|
||||
},
|
||||
},
|
||||
});
|
||||
const colorSelector = getByTestId('change-sticky-color');
|
||||
expect(colorSelector).toBeVisible();
|
||||
});
|
||||
|
||||
it('should render all colors and apply selected color correctly', async () => {
|
||||
const { getByTestId, getAllByTestId, emitted } = renderComponent({
|
||||
global: {
|
||||
provide: {
|
||||
...createCanvasNodeProvide(),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const colorSelector = getByTestId('change-sticky-color');
|
||||
|
||||
await fireEvent.click(colorSelector);
|
||||
|
||||
const colorOption = getAllByTestId('color');
|
||||
const selectedIndex = 2;
|
||||
|
||||
await fireEvent.click(colorOption[selectedIndex]);
|
||||
|
||||
expect(colorOption).toHaveLength(7);
|
||||
expect(emitted()).toHaveProperty('update');
|
||||
expect(emitted().update[0]).toEqual([selectedIndex + 1]);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,171 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
|
||||
import { useI18n } from '@/composables/useI18n';
|
||||
import { useCanvasNode } from '@/composables/useCanvasNode';
|
||||
import type { CanvasNodeStickyNoteRender } from '@/types';
|
||||
|
||||
const emit = defineEmits<{
|
||||
update: [color: number];
|
||||
}>();
|
||||
|
||||
const i18n = useI18n();
|
||||
|
||||
const { render, eventBus } = useCanvasNode();
|
||||
const renderOptions = computed(() => render.value.options as CanvasNodeStickyNoteRender['options']);
|
||||
|
||||
const autoHideTimeout = ref<NodeJS.Timeout | null>(null);
|
||||
const isPopoverVisible = ref(false);
|
||||
|
||||
const colors = computed(() => Array.from({ length: 7 }).map((_, index) => index + 1));
|
||||
|
||||
function togglePopover() {
|
||||
isPopoverVisible.value = !isPopoverVisible.value;
|
||||
}
|
||||
|
||||
function hidePopover() {
|
||||
isPopoverVisible.value = false;
|
||||
}
|
||||
|
||||
function showPopover() {
|
||||
isPopoverVisible.value = true;
|
||||
}
|
||||
|
||||
function changeColor(index: number) {
|
||||
emit('update', index);
|
||||
hidePopover();
|
||||
}
|
||||
|
||||
function onMouseEnter() {
|
||||
if (autoHideTimeout.value) {
|
||||
clearTimeout(autoHideTimeout.value);
|
||||
autoHideTimeout.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseLeave() {
|
||||
autoHideTimeout.value = setTimeout(() => {
|
||||
hidePopover();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
eventBus.value?.on('update:sticky:color', showPopover);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
eventBus.value?.off('update:sticky:color', showPopover);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<N8nPopover
|
||||
effect="dark"
|
||||
trigger="click"
|
||||
placement="top"
|
||||
:popper-class="$style.popover"
|
||||
:popper-style="{ width: '208px' }"
|
||||
:visible="isPopoverVisible"
|
||||
:teleported="false"
|
||||
@mouseenter="onMouseEnter"
|
||||
@mouseleave="onMouseLeave"
|
||||
>
|
||||
<template #reference>
|
||||
<div
|
||||
:class="$style.option"
|
||||
data-test-id="change-sticky-color"
|
||||
:title="i18n.baseText('node.changeColor')"
|
||||
@click.stop="togglePopover"
|
||||
>
|
||||
<FontAwesomeIcon icon="palette" />
|
||||
</div>
|
||||
</template>
|
||||
<div :class="$style.content">
|
||||
<div
|
||||
v-for="color in colors"
|
||||
:key="color"
|
||||
data-test-id="color"
|
||||
:class="[
|
||||
$style.color,
|
||||
$style[`sticky-color-${color}`],
|
||||
renderOptions.color === color ? $style.selected : '',
|
||||
]"
|
||||
@click="changeColor(color)"
|
||||
></div>
|
||||
</div>
|
||||
</N8nPopover>
|
||||
</template>
|
||||
|
||||
<style lang="scss" module>
|
||||
.popover {
|
||||
min-width: 208px;
|
||||
margin-bottom: -8px;
|
||||
margin-left: -2px;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: fit-content;
|
||||
gap: var(--spacing-2xs);
|
||||
}
|
||||
|
||||
.color {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: var(--color-foreground-xdark);
|
||||
border-radius: 50%;
|
||||
background: var(--color-sticky-background);
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
box-shadow: 0 0 0 1px var(--color-sticky-background);
|
||||
}
|
||||
|
||||
&.sticky-color-1 {
|
||||
--color-sticky-background: var(--color-sticky-background-1);
|
||||
}
|
||||
|
||||
&.sticky-color-2 {
|
||||
--color-sticky-background: var(--color-sticky-background-2);
|
||||
}
|
||||
|
||||
&.sticky-color-3 {
|
||||
--color-sticky-background: var(--color-sticky-background-3);
|
||||
}
|
||||
|
||||
&.sticky-color-4 {
|
||||
--color-sticky-background: var(--color-sticky-background-4);
|
||||
}
|
||||
|
||||
&.sticky-color-5 {
|
||||
--color-sticky-background: var(--color-sticky-background-5);
|
||||
}
|
||||
|
||||
&.sticky-color-6 {
|
||||
--color-sticky-background: var(--color-sticky-background-6);
|
||||
}
|
||||
|
||||
&.sticky-color-7 {
|
||||
--color-sticky-background: var(--color-sticky-background-7);
|
||||
}
|
||||
}
|
||||
|
||||
.option {
|
||||
display: inline-block;
|
||||
padding: var(--spacing-3xs);
|
||||
color: var(--color-text-light);
|
||||
|
||||
svg {
|
||||
width: var(--font-size-s) !important;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -63,6 +63,8 @@ export function useCanvasNode() {
|
|||
|
||||
const render = computed(() => data.value.render);
|
||||
|
||||
const eventBus = computed(() => node?.eventBus.value);
|
||||
|
||||
return {
|
||||
node,
|
||||
id,
|
||||
|
@ -84,5 +86,6 @@ export function useCanvasNode() {
|
|||
executionWaiting,
|
||||
executionRunning,
|
||||
render,
|
||||
eventBus,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,9 +6,10 @@ import type {
|
|||
NodeConnectionType,
|
||||
} from 'n8n-workflow';
|
||||
import type { DefaultEdge, Node, NodeProps, Position } from '@vue-flow/core';
|
||||
import type { INodeUi } from '@/Interface';
|
||||
import type { IExecutionResponse, INodeUi } from '@/Interface';
|
||||
import type { Ref } from 'vue';
|
||||
import type { PartialBy } from '@/utils/typeHelpers';
|
||||
import type { EventBus } from 'n8n-design-system';
|
||||
|
||||
export type CanvasConnectionPortType = NodeConnectionType;
|
||||
|
||||
|
@ -124,11 +125,29 @@ export interface CanvasInjectionData {
|
|||
connectingHandle: Ref<ConnectStartEvent | undefined>;
|
||||
}
|
||||
|
||||
export type CanvasNodeEventBusEvents = {
|
||||
'update:sticky:color': never;
|
||||
'update:node:active': never;
|
||||
};
|
||||
|
||||
export type CanvasEventBusEvents = {
|
||||
fitView: never;
|
||||
'saved:workflow': never;
|
||||
'open:execution': IExecutionResponse;
|
||||
'nodes:select': { ids: string[] };
|
||||
'nodes:action': {
|
||||
ids: string[];
|
||||
action: keyof CanvasNodeEventBusEvents;
|
||||
payload?: CanvasNodeEventBusEvents[keyof CanvasNodeEventBusEvents];
|
||||
};
|
||||
};
|
||||
|
||||
export interface CanvasNodeInjectionData {
|
||||
id: Ref<string>;
|
||||
data: Ref<CanvasNodeData>;
|
||||
label: Ref<NodeProps['label']>;
|
||||
selected: Ref<NodeProps['selected']>;
|
||||
eventBus: Ref<EventBus<CanvasNodeEventBusEvents>>;
|
||||
}
|
||||
|
||||
export interface CanvasNodeHandleInjectionData {
|
||||
|
|
|
@ -36,6 +36,7 @@ import type {
|
|||
import type { Connection, ViewportTransform } from '@vue-flow/core';
|
||||
import type {
|
||||
CanvasConnectionCreateData,
|
||||
CanvasEventBusEvents,
|
||||
CanvasNode,
|
||||
CanvasNodeMoveEvent,
|
||||
ConnectStartEvent,
|
||||
|
@ -137,7 +138,7 @@ const pushConnectionStore = usePushConnectionStore();
|
|||
const ndvStore = useNDVStore();
|
||||
const templatesStore = useTemplatesStore();
|
||||
|
||||
const canvasEventBus = createEventBus();
|
||||
const canvasEventBus = createEventBus<CanvasEventBusEvents>();
|
||||
|
||||
const { addBeforeUnloadEventBindings, removeBeforeUnloadEventBindings } = useBeforeUnload({
|
||||
route,
|
||||
|
@ -1346,7 +1347,7 @@ function fitView() {
|
|||
}
|
||||
|
||||
function selectNodes(ids: string[]) {
|
||||
setTimeout(() => canvasEventBus.emit('selectNodes', ids));
|
||||
setTimeout(() => canvasEventBus.emit('nodes:select', { ids }));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue