diff --git a/packages/frontend/editor-ui/src/components/InlineExpressionEditor/InlineExpressionEditorOutput.vue b/packages/frontend/editor-ui/src/components/InlineExpressionEditor/InlineExpressionEditorOutput.vue
index e8e0e8b017..746cd44626 100644
--- a/packages/frontend/editor-ui/src/components/InlineExpressionEditor/InlineExpressionEditorOutput.vue
+++ b/packages/frontend/editor-ui/src/components/InlineExpressionEditor/InlineExpressionEditorOutput.vue
@@ -104,8 +104,9 @@ defineExpose({
padding: 0 !important;
border: none !important;
- /* Override break-all set for el-popper */
+ /* Override styles set for el-popper */
word-break: normal;
+ text-align: unset;
}
.dropdown {
diff --git a/packages/frontend/editor-ui/src/components/InputPanel.vue b/packages/frontend/editor-ui/src/components/InputPanel.vue
index 68fd918cd5..15881f3c40 100644
--- a/packages/frontend/editor-ui/src/components/InputPanel.vue
+++ b/packages/frontend/editor-ui/src/components/InputPanel.vue
@@ -477,21 +477,23 @@ function handleChangeCollapsingColumn(columnName: string | null) {
v-if="(isActiveNodeConfig && rootNode) || parentNodes.length"
:class="$style.noOutputData"
>
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-defineProps<{ title: string }>();
+defineProps<{ title?: string }>();
defineSlots<{
icon(): unknown;
@@ -10,7 +10,7 @@ defineSlots<{
- {{ title }}
+ {{ title }}
@@ -36,7 +36,8 @@ defineSlots<{
.description {
font-size: var(--font-size-s);
- max-width: 180px;
+ max-width: 240px;
margin: 0;
+ text-align: center;
}
diff --git a/packages/frontend/editor-ui/src/components/ParameterInput.test.ts b/packages/frontend/editor-ui/src/components/ParameterInput.test.ts
index c60c5dafcf..aee9d5398b 100644
--- a/packages/frontend/editor-ui/src/components/ParameterInput.test.ts
+++ b/packages/frontend/editor-ui/src/components/ParameterInput.test.ts
@@ -675,7 +675,7 @@ describe('ParameterInput.vue', () => {
inputNode: { name: 'n1', runIndex: 0, branchIndex: 0 },
});
- it('should render mapper', async () => {
+ it('should render mapper when the current value is empty', async () => {
const rendered = renderComponent({
global: { provide: { [ExpressionLocalResolveContextSymbol]: ctx } },
props: {
@@ -688,6 +688,37 @@ describe('ParameterInput.vue', () => {
expect(rendered.queryByTestId('ndv-input-panel')).toBeInTheDocument();
});
+ it('should render mapper when editor type is specified in the parameter', async () => {
+ const rendered = renderComponent({
+ global: { provide: { [ExpressionLocalResolveContextSymbol]: ctx } },
+ props: {
+ path: 'name',
+ parameter: {
+ displayName: 'Name',
+ name: 'name',
+ type: 'string',
+ typeOptions: { editor: 'sqlEditor' },
+ },
+ modelValue: 'SELECT 1;',
+ },
+ });
+
+ expect(rendered.queryByTestId('ndv-input-panel')).toBeInTheDocument();
+ });
+
+ it('should render mapper when the current value is an expression', async () => {
+ const rendered = renderComponent({
+ global: { provide: { [ExpressionLocalResolveContextSymbol]: ctx } },
+ props: {
+ path: 'name',
+ parameter: { displayName: 'Name', name: 'name', type: 'string' },
+ modelValue: '={{$today}}',
+ },
+ });
+
+ expect(rendered.queryByTestId('ndv-input-panel')).toBeInTheDocument();
+ });
+
it('should not render mapper if given node property is a node setting', async () => {
const rendered = renderComponent({
global: { provide: { [ExpressionLocalResolveContextSymbol]: ctx } },
diff --git a/packages/frontend/editor-ui/src/components/ParameterInput.vue b/packages/frontend/editor-ui/src/components/ParameterInput.vue
index 53172110ce..d42acfd6a9 100644
--- a/packages/frontend/editor-ui/src/components/ParameterInput.vue
+++ b/packages/frontend/editor-ui/src/components/ParameterInput.vue
@@ -277,7 +277,7 @@ const modelValueExpressionEdit = computed(() => {
const editorRows = computed(() => getTypeOption('rows'));
-const editorType = computed(() => {
+const editorType = computed(() => {
return getTypeOption('editor');
});
const editorIsReadOnly = computed(() => {
@@ -636,7 +636,8 @@ const isMapperAvailable = computed(
!props.parameter.isNodeSetting &&
(isModelValueExpression.value ||
props.forceShowExpression ||
- (isEmpty(props.modelValue) && props.parameter.type !== 'dateTime')),
+ (isEmpty(props.modelValue) && props.parameter.type !== 'dateTime') ||
+ editorType.value !== undefined),
);
function isRemoteParameterOption(option: INodePropertyOptions) {
@@ -825,7 +826,6 @@ async function setFocus() {
}
isFocused.value = true;
- isMapperShown.value = isMapperAvailable.value;
}
emit('focus');
@@ -966,14 +966,23 @@ function expressionUpdated(value: string) {
valueChanged(val);
}
-function onBlur(event?: FocusEvent | KeyboardEvent) {
+function onBlur() {
emit('blur');
isFocused.value = false;
+}
+function onFocusIn() {
+ if (isMapperAvailable.value) {
+ isMapperShown.value = true;
+ }
+}
+
+function onFocusOutOrOutsideClickMapper(event: FocusEvent | MouseEvent) {
if (
+ !(event?.target instanceof Node && wrapper.value?.contains(event.target)) &&
!(event?.target instanceof Node && mapperElRef.value?.contains(event.target)) &&
!(
- event instanceof FocusEvent &&
+ 'relatedTarget' in event &&
event.relatedTarget instanceof Node &&
mapperElRef.value?.contains(event.relatedTarget)
)
@@ -1027,12 +1036,6 @@ function onUpdateTextInput(value: string) {
const onUpdateTextInputDebounced = debounce(onUpdateTextInput, { debounceTime: 200 });
-function onClickOutsideMapper() {
- if (!isFocused.value) {
- isMapperShown.value = false;
- }
-}
-
async function optionSelected(command: string) {
const prevValue = props.modelValue;
@@ -1247,7 +1250,7 @@ onUpdated(async () => {
}
});
-onClickOutside(mapperElRef, onClickOutsideMapper);
+onClickOutside(mapperElRef, onFocusOutOrOutsideClickMapper);
@@ -1290,6 +1293,8 @@ onClickOutside(mapperElRef, onClickOutsideMapper);
]"
:style="parameterInputWrapperStyle"
:data-parameter-path="path"
+ @focusin="onFocusIn"
+ @focusout="onFocusOutOrOutsideClickMapper"
>
await import('@/components/RunDataTable.vue'),
@@ -1774,9 +1775,8 @@ defineExpose({ enterEditMode });
"
:class="$style.center"
>
-
+
+
{{ noDataInBranchMessage }}
@@ -1848,9 +1848,12 @@ defineExpose({ enterEditMode });
-
+
+
{
-
-
-
{{ i18n.baseText('ndv.search.noNodeMatch.title') }}
-
+
+
+
{
.run-data-schema {
padding: 0;
+
+ &.no-search-results {
+ display: flex;
+ justify-content: center;
+ padding: var(--spacing-l) 0;
+ }
}
.scroller {
@@ -563,17 +575,6 @@ const onDragEnd = (el: HTMLElement) => {
}
}
-.no-results {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- text-align: center;
- height: 100%;
- gap: var(--spacing-2xs);
- padding: var(--ndv-spacing) var(--ndv-spacing) var(--spacing-xl) var(--ndv-spacing);
-}
-
.icon {
display: inline-flex;
margin-left: var(--spacing-xl);
diff --git a/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalEmbeddedNdvMapper.vue b/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalEmbeddedNdvMapper.vue
index 75be8a6818..4dfb707dcc 100644
--- a/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalEmbeddedNdvMapper.vue
+++ b/packages/frontend/editor-ui/src/components/canvas/experimental/components/ExperimentalEmbeddedNdvMapper.vue
@@ -106,8 +106,9 @@ defineExpose({
box-shadow: none !important;
margin-top: -2px;
- /* Override break-all set for el-popper */
+ /* Override styles set for el-popper */
word-break: normal;
+ text-align: unset;
}
.inputPanel {
diff --git a/packages/frontend/editor-ui/src/views/NodeView.vue b/packages/frontend/editor-ui/src/views/NodeView.vue
index da80b8cfad..2594d01d34 100644
--- a/packages/frontend/editor-ui/src/views/NodeView.vue
+++ b/packages/frontend/editor-ui/src/views/NodeView.vue
@@ -146,6 +146,7 @@ import { useAITemplatesStarterCollectionStore } from '@/experiments/aiTemplatesS
import { useReadyToRunWorkflowsStore } from '@/experiments/readyToRunWorkflows/stores/readyToRunWorkflows.store';
import { useKeybindings } from '@/composables/useKeybindings';
import { type ContextMenuAction } from '@/composables/useContextMenuItems';
+import { useExperimentalNdvStore } from '@/components/canvas/experimental/experimentalNdv.store';
defineOptions({
name: 'NodeView',
@@ -208,6 +209,7 @@ const agentRequestStore = useAgentRequestStore();
const logsStore = useLogsStore();
const aiTemplatesStarterCollectionStore = useAITemplatesStarterCollectionStore();
const readyToRunWorkflowsStore = useReadyToRunWorkflowsStore();
+const experimentalNdvStore = useExperimentalNdvStore();
const { addBeforeUnloadEventBindings, removeBeforeUnloadEventBindings } = useBeforeUnload({
route,
@@ -2217,7 +2219,9 @@ onBeforeUnmount(() => {