feat(editor): Add executing state and disable node run button while executing on new canvas (no-changelog) (#11079)

This commit is contained in:
Alex Grozav 2024-10-03 15:29:41 +03:00 committed by GitHub
parent 9ed8040ec0
commit 6d716494a4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 59 additions and 10 deletions

View file

@ -1,11 +1,13 @@
import { CanvasNodeHandleKey, CanvasNodeKey } from '@/constants';
import { CanvasKey, CanvasNodeHandleKey, CanvasNodeKey } from '@/constants';
import { computed, ref } from 'vue';
import type {
CanvasInjectionData,
CanvasNode,
CanvasNodeData,
CanvasNodeEventBusEvents,
CanvasNodeHandleInjectionData,
CanvasNodeInjectionData,
ConnectStartEvent,
ExecutionOutputMapData,
} from '@/types';
import { CanvasConnectionMode, CanvasNodeRenderType } from '@/types';
@ -88,6 +90,21 @@ export function createCanvasNodeProps({
};
}
export function createCanvasProvide({
isExecuting = false,
connectingHandle = undefined,
}: {
isExecuting?: boolean;
connectingHandle?: ConnectStartEvent;
} = {}) {
return {
[String(CanvasKey)]: {
isExecuting: ref(isExecuting),
connectingHandle: ref(connectingHandle),
} satisfies CanvasInjectionData,
};
}
export function createCanvasNodeProvide({
id = 'node',
label = 'Test Node',

View file

@ -18,7 +18,7 @@ import { Background } from '@vue-flow/background';
import { MiniMap } from '@vue-flow/minimap';
import Node from './elements/nodes/CanvasNode.vue';
import Edge from './elements/edges/CanvasEdge.vue';
import { computed, onMounted, onUnmounted, provide, ref, useCssModule, watch } from 'vue';
import { computed, onMounted, onUnmounted, provide, ref, toRef, useCssModule, watch } from 'vue';
import type { EventBus } from 'n8n-design-system';
import { createEventBus } from 'n8n-design-system';
import { useContextMenu, type ContextMenuAction } from '@/composables/useContextMenu';
@ -78,6 +78,7 @@ const props = withDefaults(
controlsPosition?: PanelPosition;
eventBus?: EventBus<CanvasEventBusEvents>;
readOnly?: boolean;
executing?: boolean;
keyBindings?: boolean;
}>(),
{
@ -87,6 +88,7 @@ const props = withDefaults(
controlsPosition: PanelPosition.BottomLeft,
eventBus: () => createEventBus(),
readOnly: false,
executing: false,
keyBindings: true,
},
);
@ -480,8 +482,11 @@ watch(() => props.readOnly, setReadonly, {
* Provide
*/
const isExecuting = toRef(props, 'executing');
provide(CanvasKey, {
connectingHandle,
isExecuting,
});
</script>

View file

@ -21,6 +21,7 @@ const props = withDefaults(
fallbackNodes?: IWorkflowDb['nodes'];
eventBus?: EventBus<CanvasEventBusEvents>;
readOnly?: boolean;
executing?: boolean;
}>(),
{
id: 'canvas',

View file

@ -1,7 +1,7 @@
import { fireEvent } from '@testing-library/vue';
import CanvasNodeToolbar from '@/components/canvas/elements/nodes/CanvasNodeToolbar.vue';
import { createComponentRenderer } from '@/__tests__/render';
import { createCanvasNodeProvide } from '@/__tests__/data';
import { createCanvasNodeProvide, createCanvasProvide } from '@/__tests__/data';
import { CanvasNodeRenderType } from '@/types';
const renderComponent = createComponentRenderer(CanvasNodeToolbar);
@ -12,6 +12,7 @@ describe('CanvasNodeToolbar', () => {
global: {
provide: {
...createCanvasNodeProvide(),
...createCanvasProvide(),
},
},
});
@ -19,6 +20,21 @@ describe('CanvasNodeToolbar', () => {
expect(getByTestId('execute-node-button')).toBeInTheDocument();
});
it('should render disabled execute node button when canvas is executing', () => {
const { getByTestId } = renderComponent({
global: {
provide: {
...createCanvasNodeProvide(),
...createCanvasProvide({
isExecuting: true,
}),
},
},
});
expect(getByTestId('execute-node-button')).toBeDisabled();
});
it('should not render execute node button when renderType is configuration', async () => {
const { queryByTestId } = renderComponent({
global: {
@ -31,6 +47,7 @@ describe('CanvasNodeToolbar', () => {
},
},
}),
...createCanvasProvide(),
},
},
});
@ -43,6 +60,7 @@ describe('CanvasNodeToolbar', () => {
global: {
provide: {
...createCanvasNodeProvide(),
...createCanvasProvide(),
},
},
});
@ -57,6 +75,7 @@ describe('CanvasNodeToolbar', () => {
global: {
provide: {
...createCanvasNodeProvide(),
...createCanvasProvide(),
},
},
});
@ -71,6 +90,7 @@ describe('CanvasNodeToolbar', () => {
global: {
provide: {
...createCanvasNodeProvide(),
...createCanvasProvide(),
},
},
});
@ -85,6 +105,7 @@ describe('CanvasNodeToolbar', () => {
global: {
provide: {
...createCanvasNodeProvide(),
...createCanvasProvide(),
},
},
});
@ -106,6 +127,7 @@ describe('CanvasNodeToolbar', () => {
},
},
}),
...createCanvasProvide(),
},
},
});

View file

@ -3,6 +3,7 @@ import { computed, useCssModule } from 'vue';
import { useI18n } from '@/composables/useI18n';
import { useCanvasNode } from '@/composables/useCanvasNode';
import { CanvasNodeRenderType } from '@/types';
import { useCanvas } from '@/composables/useCanvas';
const emit = defineEmits<{
delete: [];
@ -19,13 +20,12 @@ const props = defineProps<{
const $style = useCssModule();
const i18n = useI18n();
const { render } = useCanvasNode();
const { isExecuting } = useCanvas();
const { isDisabled, render } = useCanvasNode();
// @TODO
const workflowRunning = false;
// @TODO
const nodeDisabledTitle = 'Test';
const nodeDisabledTitle = computed(() => {
return isDisabled.value ? i18n.baseText('node.disable') : i18n.baseText('node.enable');
});
const classes = computed(() => ({
[$style.canvasNodeToolbar]: true,
@ -84,7 +84,7 @@ function onOpenContextMenu(event: MouseEvent) {
text
size="small"
icon="play"
:disabled="workflowRunning"
:disabled="isExecuting"
:title="i18n.baseText('node.testStep')"
@click="executeNode"
/>

View file

@ -5,8 +5,10 @@ export function useCanvas() {
const canvas = inject(CanvasKey);
const connectingHandle = computed(() => canvas?.connectingHandle.value);
const isExecuting = computed(() => canvas?.isExecuting.value);
return {
isExecuting,
connectingHandle,
};
}

View file

@ -132,6 +132,7 @@ export type CanvasConnectionCreateData = {
};
export interface CanvasInjectionData {
isExecuting: Ref<boolean | undefined>;
connectingHandle: Ref<ConnectStartEvent | undefined>;
}

View file

@ -1568,6 +1568,7 @@ onBeforeUnmount(() => {
:fallback-nodes="fallbackNodes"
:event-bus="canvasEventBus"
:read-only="isCanvasReadOnly"
:executing="isWorkflowRunning"
:key-bindings="keyBindingsEnabled"
@update:nodes:position="onUpdateNodesPosition"
@update:node:position="onUpdateNodePosition"