diff --git a/packages/frontend/editor-ui/src/features/logs/components/LogsPanel.test.ts b/packages/frontend/editor-ui/src/features/logs/components/LogsPanel.test.ts
index 7246122c081..5ab2856b941 100644
--- a/packages/frontend/editor-ui/src/features/logs/components/LogsPanel.test.ts
+++ b/packages/frontend/editor-ui/src/features/logs/components/LogsPanel.test.ts
@@ -179,7 +179,7 @@ describe('LogsPanel', () => {
expect(rendered.queryByTestId('log-details-output')).toBeInTheDocument();
});
- it('opens collapsed panel when clicked', async () => {
+ it('toggles panel when header is clicked', async () => {
workflowsStore.setWorkflow(aiChatWorkflow);
const rendered = render();
@@ -187,6 +187,12 @@ describe('LogsPanel', () => {
await fireEvent.click(await rendered.findByTestId('logs-overview-header'));
expect(await rendered.findByTestId('logs-overview-empty')).toBeInTheDocument();
+
+ await fireEvent.click(await rendered.findByTestId('logs-overview-header'));
+
+ await waitFor(() =>
+ expect(rendered.queryByTestId('logs-overview-empty')).not.toBeInTheDocument(),
+ );
});
it('should toggle panel when chevron icon button in the overview panel is clicked', async () => {
diff --git a/packages/frontend/editor-ui/src/features/logs/components/LogsPanel.vue b/packages/frontend/editor-ui/src/features/logs/components/LogsPanel.vue
index 61a71dad9ea..81299abccea 100644
--- a/packages/frontend/editor-ui/src/features/logs/components/LogsPanel.vue
+++ b/packages/frontend/editor-ui/src/features/logs/components/LogsPanel.vue
@@ -186,11 +186,12 @@ function handleChangeOutputTableColumnCollapsing(columnName: string | null) {
:past-chat-messages="previousChatMessages"
:show-close-button="false"
:is-new-logs-enabled="true"
+ :is-header-clickable="!isPoppedOut"
@close="onToggleOpen"
@refresh-session="refreshSession"
@display-execution="displayExecution"
@send-message="sendMessage"
- @click-header="onToggleOpen(true)"
+ @click-header="onToggleOpen"
/>
@@ -214,7 +215,8 @@ function handleChangeOutputTableColumnCollapsing(columnName: string | null) {
:entries="entries"
:latest-node-info="latestNodeNameById"
:flat-log-entries="flatLogEntries"
- @click-header="onToggleOpen(true)"
+ :is-header-clickable="!isPoppedOut"
+ @click-header="onToggleOpen"
@select="select"
@clear-execution-data="resetExecutionData"
@toggle-expanded="toggleExpanded"
@@ -238,7 +240,8 @@ function handleChangeOutputTableColumnCollapsing(columnName: string | null) {
:panels="logsStore.detailsState"
:collapsing-input-table-column-name="inputCollapsingColumnName"
:collapsing-output-table-column-name="outputCollapsingColumnName"
- @click-header="onToggleOpen(true)"
+ :is-header-clickable="!isPoppedOut"
+ @click-header="onToggleOpen"
@toggle-input-open="logsStore.toggleInputOpen"
@toggle-output-open="logsStore.toggleOutputOpen"
@collapsing-input-table-column-changed="handleChangeInputTableColumnCollapsing"
diff --git a/packages/frontend/editor-ui/src/features/logs/components/LogsPanelActions.vue b/packages/frontend/editor-ui/src/features/logs/components/LogsPanelActions.vue
index 25310100fbb..663b5d67e6f 100644
--- a/packages/frontend/editor-ui/src/features/logs/components/LogsPanelActions.vue
+++ b/packages/frontend/editor-ui/src/features/logs/components/LogsPanelActions.vue
@@ -73,6 +73,7 @@ function handleSelectMenuItem(selected: string) {
:items="menuItems"
:teleported="false /* for pop-out window */"
@select="handleSelectMenuItem"
+ @click.stop
/>
import { N8nText } from '@n8n/design-system';
-const { title } = defineProps<{ title?: string }>();
+const { title, isClickable } = defineProps<{ title?: string; isClickable: boolean }>();
defineSlots<{ actions: {}; title?: {} }>();
const emit = defineEmits<{ click: [] }>();
+
+function handleClick() {
+ if (isClickable) {
+ emit('click');
+ }
+}
-
+
{{ title }}
@@ -32,8 +38,7 @@ const emit = defineEmits<{ click: [] }>();
align-items: center;
line-height: var(--font-line-height-compact);
- &:last-child {
- /** Panel collapsed */
+ &.clickable {
cursor: pointer;
}
diff --git a/packages/frontend/editor-ui/src/utils/htmlUtils.ts b/packages/frontend/editor-ui/src/utils/htmlUtils.ts
index dabf8591121..f325497938b 100644
--- a/packages/frontend/editor-ui/src/utils/htmlUtils.ts
+++ b/packages/frontend/editor-ui/src/utils/htmlUtils.ts
@@ -1,5 +1,6 @@
import xss, { escapeAttrValue } from 'xss';
import { ALLOWED_HTML_ATTRIBUTES, ALLOWED_HTML_TAGS } from '@/constants';
+import { toValue, type MaybeRef } from 'vue';
/*
Constants and utility functions that help in HTML, CSS and DOM manipulation
@@ -96,3 +97,10 @@ export function getScrollbarWidth() {
return scrollbarWidth;
}
+
+export function isEventTargetContainedBy(
+ eventTarget: EventTarget | null | undefined,
+ maybeContainer: MaybeRef,
+): boolean {
+ return !!(eventTarget instanceof Node && toValue(maybeContainer)?.contains(eventTarget));
+}
diff --git a/packages/frontend/editor-ui/src/utils/nodeSettingsUtils.ts b/packages/frontend/editor-ui/src/utils/nodeSettingsUtils.ts
index a7f1a83c98b..61db4da4a1b 100644
--- a/packages/frontend/editor-ui/src/utils/nodeSettingsUtils.ts
+++ b/packages/frontend/editor-ui/src/utils/nodeSettingsUtils.ts
@@ -342,11 +342,11 @@ export function updateParameterByPath(
return parameterPath;
}
-export function getParameterTypeOption(
+export function getParameterTypeOption>(
parameter: INodeProperties,
- optionName: string,
-): T {
- return parameter.typeOptions?.[optionName] as T;
+ optionName: T,
+): NonNullable[T] | undefined {
+ return parameter.typeOptions?.[optionName];
}
export function isResourceLocatorParameterType(type: NodePropertyTypes) {
diff --git a/packages/testing/playwright/pages/components/FocusPanel.ts b/packages/testing/playwright/pages/components/FocusPanel.ts
index b9c7ee10c8e..d9ee8f369ff 100644
--- a/packages/testing/playwright/pages/components/FocusPanel.ts
+++ b/packages/testing/playwright/pages/components/FocusPanel.ts
@@ -7,8 +7,8 @@ export class FocusPanel {
* Accessors
*/
- getHeader(): Locator {
- return this.root.locator('header');
+ getHeaderNodeName(): Locator {
+ return this.root.locator('header').getByTestId('inline-edit-preview');
}
getParameterInputField(path: string): Locator {
diff --git a/packages/testing/playwright/tests/ui/54-focus-panel.spec.ts b/packages/testing/playwright/tests/ui/54-focus-panel.spec.ts
index 3ade94ba33b..80f91e1e515 100644
--- a/packages/testing/playwright/tests/ui/54-focus-panel.spec.ts
+++ b/packages/testing/playwright/tests/ui/54-focus-panel.spec.ts
@@ -19,7 +19,7 @@ test.describe('Focus panel', () => {
await n8n.canvas.deselectAll();
await n8n.canvas.toggleFocusPanelButton().click();
await n8n.canvas.nodeByName('Set').click();
- await expect(n8n.canvas.focusPanel.getHeader()).toHaveText('Set');
+ await expect(n8n.canvas.focusPanel.getHeaderNodeName()).toHaveText('Set');
await n8n.canvas.focusPanel.getParameterInputField('assignments.assignments.0.value').focus();
await expect(n8n.canvas.focusPanel.getMapper()).toBeVisible();
@@ -27,13 +27,13 @@ test.describe('Focus panel', () => {
await n8n.canvas.canvasBody().click({ position: { x: 0, y: 0 } });
await expect(n8n.canvas.focusPanel.getMapper()).toBeHidden();
- await expect(n8n.canvas.focusPanel.getHeader()).toHaveText('Set');
+ await expect(n8n.canvas.focusPanel.getHeaderNodeName()).toHaveText('Set');
await expect(n8n.canvas.selectedNodes()).toHaveCount(1);
// Assert that another click on canvas does de-select the Set node
await n8n.canvas.canvasBody().click({ position: { x: 0, y: 0 } });
- await expect(n8n.canvas.focusPanel.getHeader()).toBeHidden();
+ await expect(n8n.canvas.focusPanel.getHeaderNodeName()).toBeHidden();
await expect(n8n.canvas.selectedNodes()).toHaveCount(0);
});
});