fix(editor): Fix notification toast offset outside of NodeView if chat/logs were opened (#15622)

This commit is contained in:
Charlie Kolb
2025-05-23 12:18:44 +02:00
committed by GitHub
parent 86885a7d0e
commit 70ea7a8859
3 changed files with 84 additions and 4 deletions

View File

@@ -2,6 +2,12 @@ import { screen, waitFor, within } from '@testing-library/vue';
import { createTestingPinia } from '@pinia/testing';
import { h, defineComponent } from 'vue';
import { useToast } from './useToast';
import { mockedStore } from '@/__tests__/utils';
import { useSettingsStore } from '@/stores/settings.store';
import { useLogsStore } from '@/stores/logs.store';
import { useNDVStore } from '@/stores/ndv.store';
import { useUIStore } from '@/stores/ui.store';
import { EDITABLE_CANVAS_VIEWS, VIEWS } from '@/constants';
describe('useToast', () => {
let toast: ReturnType<typeof useToast>;
@@ -87,4 +93,65 @@ describe('useToast', () => {
expect(screen.getByRole('alert')).toContainHTML('<p>Test <strong>content</strong></p>');
});
});
describe('determineToastOffset', () => {
let settingsStore: ReturnType<typeof mockedStore<typeof useSettingsStore>>;
let logsStore: ReturnType<typeof mockedStore<typeof useLogsStore>>;
let ndvStore: ReturnType<typeof mockedStore<typeof useNDVStore>>;
let uiStore: ReturnType<typeof mockedStore<typeof useUIStore>>;
beforeEach(() => {
settingsStore = mockedStore(useSettingsStore);
settingsStore.isAiAssistantEnabled = false;
logsStore = mockedStore(useLogsStore);
logsStore.height = 100;
logsStore.state = 'attached';
ndvStore = mockedStore(useNDVStore);
ndvStore.activeNode = null;
uiStore = mockedStore(useUIStore);
uiStore.currentView = VIEWS.WORKFLOW;
});
it('applies logsStore offset on applicable views', () => {
for (const view of EDITABLE_CANVAS_VIEWS) {
uiStore.currentView = view;
const offset = toast.determineToastOffset();
expect(offset).toBe(100);
}
});
it('does not apply logsStore offset on unrelated view', () => {
uiStore.currentView = VIEWS.HOMEPAGE;
const offset = toast.determineToastOffset();
expect(offset).toBe(0);
});
it('does not apply logsStore offset if we have an activeNode', () => {
ndvStore.activeNode = { name: 'myActiveNode' } as never;
const offset = toast.determineToastOffset();
expect(offset).toBe(0);
});
it('applies assistant offset with logsOffset', () => {
settingsStore.isAiAssistantEnabled = true;
const offset = toast.determineToastOffset();
expect(offset).toBe(100 + 64);
});
it('does not apply logsStore offset if floating', () => {
logsStore.state = 'floating';
const offset = toast.determineToastOffset();
expect(offset).toBe(0);
});
it('does apply logsStore offset if closed', () => {
logsStore.state = 'closed';
logsStore.height = 32;
settingsStore.isAiAssistantEnabled = true;
const offset = toast.determineToastOffset();
expect(offset).toBe(32 + 64);
});
});
});

View File

@@ -7,12 +7,13 @@ import { useWorkflowsStore } from '@/stores/workflows.store';
import { useUIStore } from '@/stores/ui.store';
import { useI18n } from './useI18n';
import { useExternalHooks } from './useExternalHooks';
import { VIEWS } from '@/constants';
import { VIEWS, VISIBLE_LOGS_VIEWS } from '@/constants';
import type { ApplicationError } from 'n8n-workflow';
import { useStyles } from './useStyles';
import { useSettingsStore } from '@/stores/settings.store';
import { useNDVStore } from '@/stores/ndv.store';
import { useLogsStore } from '@/stores/logs.store';
import { LOGS_PANEL_STATE } from '@/components/CanvasChat/types/logs';
export interface NotificationErrorWithNodeAndDescription extends ApplicationError {
node: {
@@ -34,14 +35,24 @@ export function useToast() {
const logsStore = useLogsStore();
const ndvStore = useNDVStore();
function determineToastOffset() {
const assistantOffset = settingsStore.isAiAssistantEnabled ? 64 : 0;
const logsOffset =
VISIBLE_LOGS_VIEWS.includes(uiStore.currentView as VIEWS) &&
ndvStore.activeNode === null &&
logsStore.state !== LOGS_PANEL_STATE.FLOATING
? logsStore.height
: 0;
return assistantOffset + logsOffset;
}
function showMessage(messageData: Partial<NotificationOptions>, track = true) {
const messageDefaults: Partial<Omit<NotificationOptions, 'message'>> = {
dangerouslyUseHTMLString: true,
position: 'bottom-right',
zIndex: APP_Z_INDEXES.TOASTS, // above NDV and modal overlays
offset:
(settingsStore.isAiAssistantEnabled ? 64 : 0) +
(ndvStore.activeNode === null ? logsStore.height : 0),
offset: determineToastOffset(),
appendTo: '#app-grid',
customClass: 'content-toast',
};
@@ -203,5 +214,6 @@ export function useToast() {
showError,
clearAllStickyNotifications,
showNotificationForViews,
determineToastOffset,
};
}

View File

@@ -575,6 +575,7 @@ export const enum VIEWS {
}
export const EDITABLE_CANVAS_VIEWS = [VIEWS.WORKFLOW, VIEWS.NEW_WORKFLOW, VIEWS.EXECUTION_DEBUG];
export const VISIBLE_LOGS_VIEWS = [...EDITABLE_CANVAS_VIEWS, VIEWS.EXECUTION_PREVIEW];
export const TEST_PIN_DATA = [
{