feat(editor): Help users discover expressions when using drag n drop (#8869)

This commit is contained in:
Elias Meire
2024-03-13 12:57:08 +01:00
committed by GitHub
parent 71f1b23771
commit e78cc2d8d2
28 changed files with 559 additions and 323 deletions

View File

@@ -29,46 +29,34 @@
@drop="onDrop"
>
<template #default="{ droppable, activeDrop }">
<n8n-tooltip
placement="left"
:visible="showMappingTooltip"
:buttons="dataMappingTooltipButtons"
>
<template #content>
<span
v-html="
i18n.baseText(`dataMapping.${displayMode}Hint`, {
interpolate: { name: parameter.displayName },
})
"
/>
</template>
<ParameterInputWrapper
ref="param"
:parameter="parameter"
:model-value="value"
:path="path"
:is-read-only="isReadOnly"
:is-assignment="isAssignment"
:rows="rows"
:droppable="droppable"
:active-drop="activeDrop"
:force-show-expression="forceShowExpression"
:hint="hint"
:hide-hint="hideHint"
:hide-issues="hideIssues"
:label="label"
:event-bus="eventBus"
input-size="small"
@update="valueChanged"
@textInput="onTextInput"
@focus="onFocus"
@blur="onBlur"
@drop="onDrop"
/>
</n8n-tooltip>
<ParameterInputWrapper
ref="param"
:parameter="parameter"
:model-value="value"
:path="path"
:is-read-only="isReadOnly"
:is-assignment="isAssignment"
:rows="rows"
:droppable="droppable"
:active-drop="activeDrop"
:force-show-expression="forceShowExpression"
:hint="hint"
:hide-hint="hideHint"
:hide-issues="hideIssues"
:label="label"
:event-bus="eventBus"
input-size="small"
@update="valueChanged"
@textInput="onTextInput"
@focus="onFocus"
@blur="onBlur"
@drop="onDrop"
/>
</template>
</DraggableTarget>
<div v-if="showDragnDropTip" :class="$style.tip">
<InlineExpressionTip tip="drag" />
</div>
<div
:class="{
[$style.options]: true,
@@ -94,7 +82,7 @@ import { defineComponent } from 'vue';
import type { PropType } from 'vue';
import { mapStores } from 'pinia';
import type { IN8nButton, INodeUi, IRunDataDisplayMode, IUpdateInformation } from '@/Interface';
import type { INodeUi, IRunDataDisplayMode, IUpdateInformation } from '@/Interface';
import ParameterOptions from '@/components/ParameterOptions.vue';
import DraggableTarget from '@/components/DraggableTarget.vue';
@@ -109,13 +97,11 @@ import type {
IParameterLabel,
NodeParameterValueType,
} from 'n8n-workflow';
import type { BaseTextKey } from '@/plugins/i18n';
import { useNDVStore } from '@/stores/ndv.store';
import { useSegment } from '@/stores/segment.store';
import { getMappedResult } from '@/utils/mappingUtils';
import { createEventBus } from 'n8n-design-system/utils';
const DISPLAY_MODES_WITH_DATA_MAPPING = ['table', 'json', 'schema'];
import InlineExpressionTip from './InlineExpressionEditor/InlineExpressionTip.vue';
export default defineComponent({
name: 'ParameterInputFull',
@@ -123,6 +109,7 @@ export default defineComponent({
ParameterOptions,
DraggableTarget,
ParameterInputWrapper,
InlineExpressionTip,
},
props: {
displayOptions: {
@@ -159,6 +146,7 @@ export default defineComponent({
},
parameter: {
type: Object as PropType<INodeProperties>,
required: true,
},
path: {
type: String,
@@ -192,24 +180,8 @@ export default defineComponent({
focused: false,
menuExpanded: false,
forceShowExpression: false,
dataMappingTooltipButtons: [] as IN8nButton[],
mappingTooltipEnabled: false,
};
},
mounted() {
const mappingTooltipDismissHandler = this.onMappingTooltipDismissed.bind(this);
this.dataMappingTooltipButtons = [
{
attrs: {
label: this.i18n.baseText('_reusableBaseText.dismiss' as BaseTextKey),
'data-test-id': 'dismiss-mapping-tooltip',
},
listeners: {
onClick: mappingTooltipDismissHandler,
},
},
];
},
computed: {
...mapStores(useNDVStore),
node(): INodeUi | null {
@@ -221,6 +193,9 @@ export default defineComponent({
isInputTypeString(): boolean {
return this.parameter.type === 'string';
},
isInputTypeNumber(): boolean {
return this.parameter.type === 'number';
},
isResourceLocator(): boolean {
return this.parameter.type === 'resourceLocator';
},
@@ -239,31 +214,29 @@ export default defineComponent({
displayMode(): IRunDataDisplayMode {
return this.ndvStore.inputPanelDisplayMode;
},
showMappingTooltip(): boolean {
showDragnDropTip(): boolean {
return (
this.mappingTooltipEnabled &&
!this.ndvStore.isMappingOnboarded &&
this.focused &&
this.isInputTypeString &&
!this.isInputDataEmpty &&
DISPLAY_MODES_WITH_DATA_MAPPING.includes(this.displayMode)
(this.isInputTypeString || this.isInputTypeNumber) &&
!this.isValueExpression &&
!this.isDropDisabled &&
!this.ndvStore.isMappingOnboarded
);
},
},
methods: {
onFocus() {
this.focused = true;
setTimeout(() => {
this.mappingTooltipEnabled = true;
}, 500);
if (!this.parameter.noDataExpression) {
this.ndvStore.setMappableNDVInputFocus(this.parameter.displayName);
}
},
onBlur() {
this.focused = false;
this.mappingTooltipEnabled = false;
if (!this.parameter.noDataExpression) {
if (
!this.parameter.noDataExpression &&
this.ndvStore.focusedMappableInput === this.parameter.displayName
) {
this.ndvStore.setMappableNDVInputFocus('');
}
this.$emit('blur');
@@ -333,6 +306,7 @@ export default defineComponent({
}
this.valueChanged(parameterData);
this.eventBus.emit('drop', updatedValue);
if (!this.ndvStore.isMappingOnboarded) {
this.showMessage({
@@ -342,7 +316,7 @@ export default defineComponent({
dangerouslyUseHTMLString: true,
});
this.ndvStore.disableMappingHint();
this.ndvStore.setMappingOnboarded();
}
this.ndvStore.setMappingTelemetry({
@@ -364,21 +338,11 @@ export default defineComponent({
this.forceShowExpression = false;
}, 200);
},
onMappingTooltipDismissed() {
this.ndvStore.disableMappingHint(false);
},
},
watch: {
showMappingTooltip(newValue: boolean) {
if (!newValue) {
this.$telemetry.track('User viewed data mapping tooltip', { type: 'param focus' });
}
},
},
});
</script>
<style module>
<style lang="scss" module>
.wrapper {
position: relative;
@@ -388,6 +352,20 @@ export default defineComponent({
}
}
}
.tip {
position: absolute;
z-index: 2;
top: 100%;
background: var(--color-code-background);
border: var(--border-base);
border-top: none;
width: 100%;
box-shadow: 0 2px 6px 0 rgba(#441c17, 0.1);
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.options {
position: absolute;
bottom: -22px;