mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-21 02:56:40 -08:00
fix(editor): Fix hiding SQL query output when trying to select (#11649)
This commit is contained in:
parent
4c41575098
commit
4dbf2f4256
|
@ -25,6 +25,7 @@ async function focusEditor(container: Element) {
|
||||||
await waitFor(() => expect(container.querySelector('.cm-line')).toBeInTheDocument());
|
await waitFor(() => expect(container.querySelector('.cm-line')).toBeInTheDocument());
|
||||||
await userEvent.click(container.querySelector('.cm-line') as Element);
|
await userEvent.click(container.querySelector('.cm-line') as Element);
|
||||||
}
|
}
|
||||||
|
|
||||||
const nodes = [
|
const nodes = [
|
||||||
{
|
{
|
||||||
id: '1',
|
id: '1',
|
||||||
|
@ -172,4 +173,23 @@ describe('SqlEditor.vue', () => {
|
||||||
getByTestId(EXPRESSION_OUTPUT_TEST_ID).getElementsByClassName('cm-line').length,
|
getByTestId(EXPRESSION_OUTPUT_TEST_ID).getElementsByClassName('cm-line').length,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should keep rendered output visible when clicking', async () => {
|
||||||
|
const { getByTestId, queryByTestId, container, baseElement } = renderComponent(SqlEditor, {
|
||||||
|
...DEFAULT_SETUP,
|
||||||
|
props: {
|
||||||
|
...DEFAULT_SETUP.props,
|
||||||
|
modelValue: 'SELECT * FROM users',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Does not hide output when clicking inside the output
|
||||||
|
await focusEditor(container);
|
||||||
|
await userEvent.click(getByTestId(EXPRESSION_OUTPUT_TEST_ID));
|
||||||
|
await waitFor(() => expect(queryByTestId(EXPRESSION_OUTPUT_TEST_ID)).toBeInTheDocument());
|
||||||
|
|
||||||
|
// Does hide output when clicking outside the container
|
||||||
|
await userEvent.click(baseElement);
|
||||||
|
await waitFor(() => expect(queryByTestId(EXPRESSION_OUTPUT_TEST_ID)).not.toBeInTheDocument());
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -37,6 +37,7 @@ import {
|
||||||
import { computed, onBeforeUnmount, onMounted, ref, toRaw, watch } from 'vue';
|
import { computed, onBeforeUnmount, onMounted, ref, toRaw, watch } from 'vue';
|
||||||
import { codeNodeEditorTheme } from '../CodeNodeEditor/theme';
|
import { codeNodeEditorTheme } from '../CodeNodeEditor/theme';
|
||||||
import { dropInExpressionEditor, mappingDropCursor } from '@/plugins/codemirror/dragAndDrop';
|
import { dropInExpressionEditor, mappingDropCursor } from '@/plugins/codemirror/dragAndDrop';
|
||||||
|
import { onClickOutside } from '@vueuse/core';
|
||||||
|
|
||||||
const SQL_DIALECTS = {
|
const SQL_DIALECTS = {
|
||||||
StandardSQL,
|
StandardSQL,
|
||||||
|
@ -68,7 +69,10 @@ const emit = defineEmits<{
|
||||||
'update:model-value': [value: string];
|
'update:model-value': [value: string];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const sqlEditor = ref<HTMLElement>();
|
const container = ref<HTMLDivElement>();
|
||||||
|
const sqlEditor = ref<HTMLDivElement>();
|
||||||
|
const isFocused = ref(false);
|
||||||
|
|
||||||
const extensions = computed(() => {
|
const extensions = computed(() => {
|
||||||
const dialect = SQL_DIALECTS[props.dialect] ?? SQL_DIALECTS.StandardSQL;
|
const dialect = SQL_DIALECTS[props.dialect] ?? SQL_DIALECTS.StandardSQL;
|
||||||
function sqlWithN8nLanguageSupport() {
|
function sqlWithN8nLanguageSupport() {
|
||||||
|
@ -122,7 +126,7 @@ const {
|
||||||
editor,
|
editor,
|
||||||
segments: { all: segments },
|
segments: { all: segments },
|
||||||
readEditorValue,
|
readEditorValue,
|
||||||
hasFocus,
|
hasFocus: editorHasFocus,
|
||||||
} = useExpressionEditor({
|
} = useExpressionEditor({
|
||||||
editorRef: sqlEditor,
|
editorRef: sqlEditor,
|
||||||
editorValue,
|
editorValue,
|
||||||
|
@ -138,6 +142,12 @@ watch(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
watch(editorHasFocus, (focus) => {
|
||||||
|
if (focus) {
|
||||||
|
isFocused.value = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
watch(segments, () => {
|
watch(segments, () => {
|
||||||
emit('update:model-value', readEditorValue());
|
emit('update:model-value', readEditorValue());
|
||||||
});
|
});
|
||||||
|
@ -154,6 +164,19 @@ onBeforeUnmount(() => {
|
||||||
codeNodeEditorEventBus.off('highlightLine', highlightLine);
|
codeNodeEditorEventBus.off('highlightLine', highlightLine);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onClickOutside(container, (event) => onBlur(event));
|
||||||
|
|
||||||
|
function onBlur(event: FocusEvent | KeyboardEvent) {
|
||||||
|
if (
|
||||||
|
event?.target instanceof Element &&
|
||||||
|
Array.from(event.target.classList).some((_class) => _class.includes('resizer'))
|
||||||
|
) {
|
||||||
|
return; // prevent blur on resizing
|
||||||
|
}
|
||||||
|
|
||||||
|
isFocused.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
function line(lineNumber: number): Line | null {
|
function line(lineNumber: number): Line | null {
|
||||||
try {
|
try {
|
||||||
return editor.value?.state.doc.line(lineNumber) ?? null;
|
return editor.value?.state.doc.line(lineNumber) ?? null;
|
||||||
|
@ -189,7 +212,7 @@ async function onDrop(value: string, event: MouseEvent) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="$style.sqlEditor">
|
<div ref="container" :class="$style.sqlEditor" @keydown.tab="onBlur">
|
||||||
<DraggableTarget type="mapping" :disabled="isReadOnly" @drop="onDrop">
|
<DraggableTarget type="mapping" :disabled="isReadOnly" @drop="onDrop">
|
||||||
<template #default="{ activeDrop, droppable }">
|
<template #default="{ activeDrop, droppable }">
|
||||||
<div
|
<div
|
||||||
|
@ -207,7 +230,7 @@ async function onDrop(value: string, event: MouseEvent) {
|
||||||
v-if="!fullscreen"
|
v-if="!fullscreen"
|
||||||
:segments="segments"
|
:segments="segments"
|
||||||
:is-read-only="isReadOnly"
|
:is-read-only="isReadOnly"
|
||||||
:visible="hasFocus"
|
:visible="isFocused"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
Loading…
Reference in a new issue