mirror of
https://github.com/n8n-io/n8n.git
synced 2026-09-24 23:22:38 +08:00
fix(editor): Remove inconsistent scrim on node creator open (#27086)
This commit is contained in:
@@ -688,7 +688,6 @@ export type NodeCreatorOpenSource =
|
||||
|
||||
export interface INodeCreatorState {
|
||||
itemsFilter: string;
|
||||
showScrim: boolean;
|
||||
rootViewHistory: NodeFilterType[];
|
||||
selectedView: NodeFilterType;
|
||||
openSource: NodeCreatorOpenSource;
|
||||
|
||||
@@ -3910,7 +3910,6 @@ describe('useCanvasOperations', () => {
|
||||
const resetStateSpy = vi.spyOn(workflowState, 'resetState');
|
||||
|
||||
nodeCreatorStore.setNodeCreatorState = vi.fn();
|
||||
nodeCreatorStore.setShowScrim = vi.fn();
|
||||
workflowsStore.removeTestWebhook = vi.fn();
|
||||
workflowsStore.resetWorkflow = vi.fn();
|
||||
workflowsStore.resetState = vi.fn();
|
||||
@@ -3947,7 +3946,6 @@ describe('useCanvasOperations', () => {
|
||||
expect(nodeCreatorStore.setNodeCreatorState).toHaveBeenCalledWith({
|
||||
createNodeActive: false,
|
||||
});
|
||||
expect(nodeCreatorStore.setShowScrim).toHaveBeenCalledWith(false);
|
||||
expect(workflowsStore.removeTestWebhook).toHaveBeenCalledWith('workflow-id');
|
||||
expect(workflowsStore.resetWorkflow).toHaveBeenCalled();
|
||||
expect(resetStateSpy).toHaveBeenCalled();
|
||||
@@ -3966,7 +3964,6 @@ describe('useCanvasOperations', () => {
|
||||
const workflowsStore = mockedStore(useWorkflowsStore);
|
||||
|
||||
nodeCreatorStore.setNodeCreatorState = vi.fn();
|
||||
nodeCreatorStore.setShowScrim = vi.fn();
|
||||
workflowsStore.removeTestWebhook = vi.fn();
|
||||
|
||||
workflowsStore.executionWaitingForWebhook = false;
|
||||
|
||||
@@ -2273,7 +2273,6 @@ export function useCanvasOperations() {
|
||||
function resetWorkspace() {
|
||||
// Reset node creator
|
||||
nodeCreatorStore.setNodeCreatorState({ createNodeActive: false });
|
||||
nodeCreatorStore.setShowScrim(false);
|
||||
|
||||
// Make sure that if there is a waiting test-webhook, it gets removed
|
||||
if (workflowsStore.executionWaitingForWebhook) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import type { XYPosition } from '@/Interface';
|
||||
import { useNodeCreatorStore } from '@/features/shared/nodeCreator/nodeCreator.store';
|
||||
import { useI18n } from '@n8n/i18n';
|
||||
|
||||
import { N8nIcon, N8nTooltip } from '@n8n/design-system';
|
||||
@@ -14,7 +13,6 @@ const i18n = useI18n();
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const nodeCreatorStore = useNodeCreatorStore();
|
||||
const containerCssVars = computed(() => ({
|
||||
'--trigger-placeholder--margin-left': `${props.position[0]}px`,
|
||||
'--trigger-placeholder--margin-top': `${props.position[1]}px`,
|
||||
@@ -28,12 +26,7 @@ const containerCssVars = computed(() => ({
|
||||
:style="containerCssVars"
|
||||
data-test-id="canvas-add-button"
|
||||
>
|
||||
<N8nTooltip
|
||||
placement="top"
|
||||
:visible="showTooltip"
|
||||
:disabled="nodeCreatorStore.showScrim"
|
||||
:show-after="700"
|
||||
>
|
||||
<N8nTooltip placement="top" :visible="showTooltip" :show-after="700">
|
||||
<button :class="$style.button" data-test-id="canvas-plus-button" @click="$emit('click')">
|
||||
<N8nIcon icon="plus" size="large" />
|
||||
</button>
|
||||
|
||||
@@ -964,7 +964,7 @@ function onClickReplaceNode(nodeId: string) {
|
||||
if (!nodeType) return;
|
||||
|
||||
nodeCreatorReplaceTargetId.value = nodeId;
|
||||
nodeCreatorStore.oppeningContext = 'replacement';
|
||||
nodeCreatorStore.openingContext = 'replacement';
|
||||
if (isTriggerNode(nodeType)) {
|
||||
nodeCreatorStore.openNodeCreatorForTriggerNodes(NODE_CREATOR_OPEN_SOURCES.REPLACE_NODE_ACTION);
|
||||
} else {
|
||||
|
||||
+2
-11
@@ -40,7 +40,7 @@ const uiStore = useUIStore();
|
||||
const bannersStore = useBannersStore();
|
||||
const chatPanelStore = useChatPanelStore();
|
||||
|
||||
const { setShowScrim, setActions, setMergeNodes } = useNodeCreatorStore();
|
||||
const { setActions, setMergeNodes } = useNodeCreatorStore();
|
||||
const { generateMergedNodesAndActions } = useActionsGenerator();
|
||||
|
||||
const state = reactive({
|
||||
@@ -48,8 +48,6 @@ const state = reactive({
|
||||
mousedownInsideEvent: null as MouseEvent | null,
|
||||
});
|
||||
|
||||
const showScrim = computed(() => useNodeCreatorStore().showScrim);
|
||||
|
||||
const viewStacksLength = computed(() => useViewStacks().viewStacks.length);
|
||||
|
||||
const nodeCreatorInlineStyle = computed(() => {
|
||||
@@ -117,7 +115,6 @@ watch(
|
||||
() => props.active,
|
||||
(isActive) => {
|
||||
if (!isActive) {
|
||||
setShowScrim(false);
|
||||
resetViewStacks();
|
||||
}
|
||||
},
|
||||
@@ -127,7 +124,6 @@ watch(
|
||||
watch(viewStacksLength, (value) => {
|
||||
if (value === 0) {
|
||||
emit('closeNodeCreator');
|
||||
setShowScrim(false);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -166,12 +162,7 @@ onClickOutside(
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<aside
|
||||
:class="{
|
||||
[$style.nodeCreatorScrim]: true,
|
||||
[$style.active]: showScrim,
|
||||
}"
|
||||
/>
|
||||
<aside :class="$style.nodeCreatorScrim" />
|
||||
<N8nIconButton
|
||||
variant="subtle"
|
||||
v-if="active"
|
||||
|
||||
+15
-15
@@ -273,8 +273,8 @@ describe('NodesListPanel', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('oppeningContext', () => {
|
||||
it('should have null oppeningContext by default', () => {
|
||||
describe('openingContext', () => {
|
||||
it('should have null openingContext by default', () => {
|
||||
getWrapperComponent(() => {
|
||||
const nodeCreatorStore = useNodeCreatorStore();
|
||||
const { setMergeNodes } = nodeCreatorStore;
|
||||
@@ -287,12 +287,12 @@ describe('NodesListPanel', () => {
|
||||
}),
|
||||
]);
|
||||
|
||||
expect(nodeCreatorStore.oppeningContext).toBeNull();
|
||||
expect(nodeCreatorStore.openingContext).toBeNull();
|
||||
return {};
|
||||
});
|
||||
});
|
||||
|
||||
it('should maintain oppeningContext when set to "replacement"', async () => {
|
||||
it('should maintain openingContext when set to "replacement"', async () => {
|
||||
getWrapperComponent(() => {
|
||||
const nodeCreatorStore = useNodeCreatorStore();
|
||||
const { setMergeNodes } = nodeCreatorStore;
|
||||
@@ -306,15 +306,15 @@ describe('NodesListPanel', () => {
|
||||
]);
|
||||
|
||||
// Simulate setting context when replacing a node
|
||||
nodeCreatorStore.oppeningContext = 'replacement';
|
||||
expect(nodeCreatorStore.oppeningContext).toBe('replacement');
|
||||
nodeCreatorStore.openingContext = 'replacement';
|
||||
expect(nodeCreatorStore.openingContext).toBe('replacement');
|
||||
return {};
|
||||
});
|
||||
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('should allow resetting oppeningContext back to null', async () => {
|
||||
it('should allow resetting openingContext back to null', async () => {
|
||||
getWrapperComponent(() => {
|
||||
const nodeCreatorStore = useNodeCreatorStore();
|
||||
const { setMergeNodes } = nodeCreatorStore;
|
||||
@@ -328,19 +328,19 @@ describe('NodesListPanel', () => {
|
||||
]);
|
||||
|
||||
// Set context
|
||||
nodeCreatorStore.oppeningContext = 'replacement';
|
||||
expect(nodeCreatorStore.oppeningContext).toBe('replacement');
|
||||
nodeCreatorStore.openingContext = 'replacement';
|
||||
expect(nodeCreatorStore.openingContext).toBe('replacement');
|
||||
|
||||
// Reset context (simulating node creator close)
|
||||
nodeCreatorStore.oppeningContext = null;
|
||||
expect(nodeCreatorStore.oppeningContext).toBeNull();
|
||||
nodeCreatorStore.openingContext = null;
|
||||
expect(nodeCreatorStore.openingContext).toBeNull();
|
||||
return {};
|
||||
});
|
||||
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
it('should preserve oppeningContext during node search when in replacement mode', async () => {
|
||||
it('should preserve openingContext during node search when in replacement mode', async () => {
|
||||
const mockedNodes = [...Array(10).keys()].map(
|
||||
(n) =>
|
||||
mockSimplifiedNodeType({
|
||||
@@ -370,7 +370,7 @@ describe('NodesListPanel', () => {
|
||||
const { setMergeNodes, setSelectedView } = nodeCreatorStore;
|
||||
|
||||
// Set replacement context
|
||||
nodeCreatorStore.oppeningContext = 'replacement';
|
||||
nodeCreatorStore.openingContext = 'replacement';
|
||||
|
||||
watch(
|
||||
() => props.nodeTypes,
|
||||
@@ -405,7 +405,7 @@ describe('NodesListPanel', () => {
|
||||
await nextTick();
|
||||
|
||||
const nodeCreatorStore = useNodeCreatorStore();
|
||||
expect(nodeCreatorStore.oppeningContext).toBe('replacement');
|
||||
expect(nodeCreatorStore.openingContext).toBe('replacement');
|
||||
|
||||
// Perform search
|
||||
await fireEvent.input(screen.getByTestId('node-creator-search-bar'), {
|
||||
@@ -414,7 +414,7 @@ describe('NodesListPanel', () => {
|
||||
await nextTick();
|
||||
|
||||
// Context should still be 'replacement' after search
|
||||
expect(nodeCreatorStore.oppeningContext).toBe('replacement');
|
||||
expect(nodeCreatorStore.openingContext).toBe('replacement');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+5
-5
@@ -83,7 +83,7 @@ const isCommunityNodeActionsMode = computed(() => {
|
||||
});
|
||||
|
||||
const viewStackTitle = computed(() => {
|
||||
if (nodeCreatorStore.oppeningContext === 'replacement') {
|
||||
if (nodeCreatorStore.openingContext === 'replacement') {
|
||||
return i18n.baseText('nodeCreator.replaceNode.title');
|
||||
}
|
||||
return activeViewStack.value.title;
|
||||
@@ -122,12 +122,12 @@ function onSearch(value: string) {
|
||||
}
|
||||
|
||||
function onTransitionEnd() {
|
||||
cleanupOppeningContext();
|
||||
cleanupopeningContext();
|
||||
void setActiveItemIndex(getDefaultActiveIndex());
|
||||
}
|
||||
|
||||
function cleanupOppeningContext() {
|
||||
nodeCreatorStore.oppeningContext = null;
|
||||
function cleanupopeningContext() {
|
||||
nodeCreatorStore.openingContext = null;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
@@ -136,7 +136,7 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
cleanupOppeningContext();
|
||||
cleanupopeningContext();
|
||||
detachKeydownEvent();
|
||||
});
|
||||
|
||||
|
||||
@@ -64,12 +64,11 @@ export const useNodeCreatorStore = defineStore(STORES.NODE_CREATOR, () => {
|
||||
const mergedNodes = ref<SimplifiedNodeType[]>([]);
|
||||
const actions = ref<ActionsRecord<typeof mergedNodes.value>>({});
|
||||
|
||||
const showScrim = ref(false);
|
||||
const openSource = ref<NodeCreatorOpenSource>('');
|
||||
|
||||
const isCreateNodeActive = ref<boolean>(false);
|
||||
|
||||
const oppeningContext = ref<null | 'replacement'>(null);
|
||||
const openingContext = ref<null | 'replacement'>(null);
|
||||
|
||||
const nodePanelSessionId = ref<string>('');
|
||||
|
||||
@@ -89,10 +88,6 @@ export const useNodeCreatorStore = defineStore(STORES.NODE_CREATOR, () => {
|
||||
actions.value = nodes;
|
||||
}
|
||||
|
||||
function setShowScrim(isVisible: boolean) {
|
||||
showScrim.value = isVisible;
|
||||
}
|
||||
|
||||
function setSelectedView(view: NodeFilterType) {
|
||||
selectedView.value = view;
|
||||
}
|
||||
@@ -266,7 +261,6 @@ export const useNodeCreatorStore = defineStore(STORES.NODE_CREATOR, () => {
|
||||
function openNodeCreatorForTriggerNodes(source: NodeCreatorOpenSource) {
|
||||
ndvStore.unsetActiveNodeName();
|
||||
setSelectedView(TRIGGER_NODE_CREATOR_VIEW);
|
||||
setShowScrim(true);
|
||||
setNodeCreatorState({
|
||||
source,
|
||||
createNodeActive: true,
|
||||
@@ -277,7 +271,6 @@ export const useNodeCreatorStore = defineStore(STORES.NODE_CREATOR, () => {
|
||||
function openNodeCreatorForRegularNodes(source: NodeCreatorOpenSource) {
|
||||
ndvStore.unsetActiveNodeName();
|
||||
setSelectedView(REGULAR_NODE_CREATOR_VIEW);
|
||||
setShowScrim(true);
|
||||
setNodeCreatorState({
|
||||
source,
|
||||
createNodeActive: true,
|
||||
@@ -465,14 +458,12 @@ export const useNodeCreatorStore = defineStore(STORES.NODE_CREATOR, () => {
|
||||
|
||||
return {
|
||||
isCreateNodeActive,
|
||||
oppeningContext,
|
||||
openingContext,
|
||||
openSource,
|
||||
selectedView,
|
||||
showScrim,
|
||||
mergedNodes,
|
||||
actions,
|
||||
allNodeCreatorNodes,
|
||||
setShowScrim,
|
||||
setSelectedView,
|
||||
setOpenSource,
|
||||
setActions,
|
||||
|
||||
+1
-6
@@ -60,12 +60,7 @@ async function onClickTemplatesLink() {
|
||||
</script>
|
||||
<template>
|
||||
<div ref="container" :class="$style.addNodes" data-test-id="canvas-add-button">
|
||||
<N8nTooltip
|
||||
placement="top"
|
||||
:visible="isTooltipVisible"
|
||||
:disabled="nodeCreatorStore.showScrim"
|
||||
:show-after="700"
|
||||
>
|
||||
<N8nTooltip placement="top" :visible="isTooltipVisible" :show-after="700">
|
||||
<button :class="$style.button" data-test-id="canvas-plus-button" @click.stop="onClick">
|
||||
<N8nIcon icon="plus" color="foreground-xdark" :size="40" />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user