refactor(editor): restrict mapping discoverability tooltip showing only on string input (#4496)

* refactor(editor): restrict mapping discoverability tooltip showing only on string input

* refactor(editor): renaming computed prop because not only string inputs can be mapped, but we want to show tooltips only on string inputs

* fix(editor): removing unused prop from ParameterInputWrapper.vue

* fix(editor): reorganizing and updating props in ParameterInputFull.vue

* fix(editor): proper typings for node related translations

* fix(editor): fix typings for input localisation functions

* fix(editor): simplifying localisation functions

* Revert "fix(editor): simplifying localisation functions"

This reverts commit 3d93ccf0cf.

* fix(editor): move nullish coalescing into called function
This commit is contained in:
Csaba Tuncsik 2022-11-03 13:04:53 +01:00 committed by GitHub
parent d944a3884c
commit 78c024b247
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 65 additions and 51 deletions

View file

@ -762,12 +762,12 @@ export default mixins(
? this.$locale.credText().placeholder(this.parameter) ? this.$locale.credText().placeholder(this.parameter)
: this.$locale.nodeText().placeholder(this.parameter, this.path); : this.$locale.nodeText().placeholder(this.parameter, this.path);
}, },
getOptionsOptionDisplayName(option: { value: string; name: string }): string { getOptionsOptionDisplayName(option: INodePropertyOptions): string {
return this.isForCredential return this.isForCredential
? this.$locale.credText().optionsOptionDisplayName(this.parameter, option) ? this.$locale.credText().optionsOptionDisplayName(this.parameter, option)
: this.$locale.nodeText().optionsOptionDisplayName(this.parameter, option, this.path); : this.$locale.nodeText().optionsOptionDisplayName(this.parameter, option, this.path);
}, },
getOptionsOptionDescription(option: { value: string; description: string }): string { getOptionsOptionDescription(option: INodePropertyOptions): string {
return this.isForCredential return this.isForCredential
? this.$locale.credText().optionsOptionDescription(this.parameter, option) ? this.$locale.credText().optionsOptionDescription(this.parameter, option)
: this.$locale.nodeText().optionsOptionDescription(this.parameter, option, this.path); : this.$locale.nodeText().optionsOptionDescription(this.parameter, option, this.path);

View file

@ -1,7 +1,7 @@
<template> <template>
<n8n-input-label <n8n-input-label
:label="hideLabel? '': $locale.nodeText().inputLabelDisplayName(parameter, path)" :label="hideLabel ? '': $locale.nodeText().inputLabelDisplayName(parameter, path)"
:tooltipText="hideLabel? '': $locale.nodeText().inputLabelDescription(parameter, path)" :tooltipText="hideLabel ? '': $locale.nodeText().inputLabelDescription(parameter, path)"
:showTooltip="focused" :showTooltip="focused"
:showOptions="menuExpanded || focused || forceShowExpression" :showOptions="menuExpanded || focused || forceShowExpression"
:bold="false" :bold="false"
@ -59,7 +59,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue, { PropType } from 'vue';
import { import {
IN8nButton, IN8nButton,
@ -68,15 +68,15 @@ import {
IUpdateInformation, IUpdateInformation,
} from '@/Interface'; } from '@/Interface';
import ParameterOptions from './ParameterOptions.vue'; import ParameterOptions from '@/components/ParameterOptions.vue';
import DraggableTarget from '@/components/DraggableTarget.vue'; import DraggableTarget from '@/components/DraggableTarget.vue';
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
import { showMessage } from './mixins/showMessage'; import { showMessage } from '@/components/mixins/showMessage';
import { LOCAL_STORAGE_MAPPING_FLAG } from '@/constants'; import { LOCAL_STORAGE_MAPPING_FLAG } from '@/constants';
import { hasExpressionMapping } from './helpers'; import { hasExpressionMapping } from '@/components/helpers';
import ParameterInputWrapper from './ParameterInputWrapper.vue'; import ParameterInputWrapper from '@/components/ParameterInputWrapper.vue';
import { hasOnlyListMode } from './ResourceLocator/helpers'; import { hasOnlyListMode } from '@/components/ResourceLocator/helpers';
import { INodePropertyMode } from 'n8n-workflow'; import { INodeParameters, INodeProperties, INodePropertyMode } from 'n8n-workflow';
import { isResourceLocatorValue } from '@/typeGuards'; import { isResourceLocatorValue } from '@/typeGuards';
import { BaseTextKey } from "@/plugins/i18n"; import { BaseTextKey } from "@/plugins/i18n";
@ -98,14 +98,29 @@ export default mixins(
dataMappingTooltipButtons: [] as IN8nButton[], dataMappingTooltipButtons: [] as IN8nButton[],
}; };
}, },
props: [ props: {
'displayOptions', displayOptions: {
'isReadOnly', type: Boolean,
'parameter', default: false,
'path', },
'value', isReadOnly: {
'hideLabel', type: Boolean,
], default: false,
},
hideLabel: {
type: Boolean,
default: false,
},
parameter: {
type: Object as PropType<INodeProperties>,
},
path: {
type: String,
},
value: {
type: [Number, String, Boolean, Array, Object] as PropType<INodeParameters>,
},
},
created() { created() {
const mappingTooltipDismissHandler = this.onMappingTooltipDismissed.bind(this); const mappingTooltipDismissHandler = this.onMappingTooltipDismissed.bind(this);
this.dataMappingTooltipButtons = [ this.dataMappingTooltipButtons = [
@ -126,6 +141,9 @@ export default mixins(
hint (): string | null { hint (): string | null {
return this.$locale.nodeText().hint(this.parameter, this.path); return this.$locale.nodeText().hint(this.parameter, this.path);
}, },
isInputTypeString (): boolean {
return this.parameter.type === 'string';
},
isResourceLocator (): boolean { isResourceLocator (): boolean {
return this.parameter.type === 'resourceLocator'; return this.parameter.type === 'resourceLocator';
}, },
@ -142,7 +160,7 @@ export default mixins(
return this.$store.getters['ndv/inputPanelDisplayMode']; return this.$store.getters['ndv/inputPanelDisplayMode'];
}, },
showMappingTooltip (): boolean { showMappingTooltip (): boolean {
return this.focused && !this.isInputDataEmpty && window.localStorage.getItem(LOCAL_STORAGE_MAPPING_FLAG) !== 'true'; return this.focused && this.isInputTypeString && !this.isInputDataEmpty && window.localStorage.getItem(LOCAL_STORAGE_MAPPING_FLAG) !== 'true';
}, },
}, },
methods: { methods: {

View file

@ -64,9 +64,6 @@ export default mixins(
value: { value: {
type: [String, Number, Boolean, Array, Object] as PropType<NodeParameterValueType>, type: [String, Number, Boolean, Array, Object] as PropType<NodeParameterValueType>,
}, },
hideLabel: {
type: Boolean,
},
droppable: { droppable: {
type: Boolean, type: Boolean,
}, },

View file

@ -1,8 +1,7 @@
import _Vue from "vue"; import Vue from 'vue';
import axios from 'axios'; import axios from 'axios';
import VueI18n from 'vue-i18n'; import VueI18n from 'vue-i18n';
import { Store } from "vuex"; import { Store } from "vuex";
import Vue from 'vue';
import { INodeTranslationHeaders, IRootState } from '@/Interface'; import { INodeTranslationHeaders, IRootState } from '@/Interface';
import { import {
deriveMiddleKey, deriveMiddleKey,
@ -15,14 +14,14 @@ import {
} from 'n8n-design-system'; } from 'n8n-design-system';
import englishBaseText from './locales/en.json'; import englishBaseText from './locales/en.json';
import { INodeProperties } from "n8n-workflow"; import {INodeProperties, INodePropertyCollection, INodePropertyOptions} from "n8n-workflow";
Vue.use(VueI18n); Vue.use(VueI18n);
locale.use('en'); locale.use('en');
export let i18n: I18nClass; export let i18n: I18nClass;
export function I18nPlugin(vue: typeof _Vue, store: Store<IRootState>): void { export function I18nPlugin(vue: typeof Vue, store: Store<IRootState>): void {
i18n = new I18nClass(store); i18n = new I18nClass(store);
Object.defineProperty(vue, '$locale', { Object.defineProperty(vue, '$locale', {
@ -79,9 +78,9 @@ export class I18nClass {
* Render a string of dynamic text, i.e. a string with a constructed path to the localized value. * Render a string of dynamic text, i.e. a string with a constructed path to the localized value.
*/ */
private dynamicRender( private dynamicRender(
{ key, fallback }: { key: string; fallback: string; }, { key, fallback }: { key: string; fallback?: string; },
) { ) {
return this.i18n.te(key) ? this.i18n.t(key).toString() : fallback; return this.i18n.te(key) ? this.i18n.t(key).toString() : fallback ?? '';
} }
/** /**
@ -106,7 +105,7 @@ export class I18nClass {
* Display name for a top-level param. * Display name for a top-level param.
*/ */
inputLabelDisplayName( inputLabelDisplayName(
{ name: parameterName, displayName }: { name: string; displayName: string; }, { name: parameterName, displayName }: INodeProperties,
) { ) {
if (['clientId', 'clientSecret'].includes(parameterName)) { if (['clientId', 'clientSecret'].includes(parameterName)) {
return context.dynamicRender({ return context.dynamicRender({
@ -125,11 +124,11 @@ export class I18nClass {
* Hint for a top-level param. * Hint for a top-level param.
*/ */
hint( hint(
{ name: parameterName, hint }: { name: string; hint?: string; }, { name: parameterName, hint }: INodeProperties,
) { ) {
return context.dynamicRender({ return context.dynamicRender({
key: `${credentialPrefix}.${parameterName}.hint`, key: `${credentialPrefix}.${parameterName}.hint`,
fallback: hint || '', fallback: hint,
}); });
}, },
@ -137,7 +136,7 @@ export class I18nClass {
* Description (tooltip text) for an input label param. * Description (tooltip text) for an input label param.
*/ */
inputLabelDescription( inputLabelDescription(
{ name: parameterName, description }: { name: string; description: string; }, { name: parameterName, description }: INodeProperties,
) { ) {
return context.dynamicRender({ return context.dynamicRender({
key: `${credentialPrefix}.${parameterName}.description`, key: `${credentialPrefix}.${parameterName}.description`,
@ -149,8 +148,8 @@ export class I18nClass {
* Display name for an option inside an `options` or `multiOptions` param. * Display name for an option inside an `options` or `multiOptions` param.
*/ */
optionsOptionDisplayName( optionsOptionDisplayName(
{ name: parameterName }: { name: string; }, { name: parameterName }: INodeProperties,
{ value: optionName, name: displayName }: { value: string; name: string; }, { value: optionName, name: displayName }: INodePropertyOptions,
) { ) {
return context.dynamicRender({ return context.dynamicRender({
key: `${credentialPrefix}.${parameterName}.options.${optionName}.displayName`, key: `${credentialPrefix}.${parameterName}.options.${optionName}.displayName`,
@ -162,8 +161,8 @@ export class I18nClass {
* Description for an option inside an `options` or `multiOptions` param. * Description for an option inside an `options` or `multiOptions` param.
*/ */
optionsOptionDescription( optionsOptionDescription(
{ name: parameterName }: { name: string; }, { name: parameterName }: INodeProperties,
{ value: optionName, description }: { value: string; description: string; }, { value: optionName, description }: INodePropertyOptions,
) { ) {
return context.dynamicRender({ return context.dynamicRender({
key: `${credentialPrefix}.${parameterName}.options.${optionName}.description`, key: `${credentialPrefix}.${parameterName}.options.${optionName}.description`,
@ -175,11 +174,11 @@ export class I18nClass {
* Placeholder for a `string` param. * Placeholder for a `string` param.
*/ */
placeholder( placeholder(
{ name: parameterName, placeholder }: { name: string; placeholder?: string; }, { name: parameterName, placeholder }: INodeProperties,
) { ) {
return context.dynamicRender({ return context.dynamicRender({
key: `${credentialPrefix}.${parameterName}.placeholder`, key: `${credentialPrefix}.${parameterName}.placeholder`,
fallback: placeholder || '', fallback: placeholder,
}); });
}, },
}; };
@ -200,7 +199,7 @@ export class I18nClass {
* Display name for an input label, whether top-level or nested. * Display name for an input label, whether top-level or nested.
*/ */
inputLabelDisplayName( inputLabelDisplayName(
parameter: { name: string; displayName: string; type: string }, parameter: INodeProperties,
path: string, path: string,
) { ) {
const middleKey = deriveMiddleKey(path, parameter); const middleKey = deriveMiddleKey(path, parameter);
@ -215,7 +214,7 @@ export class I18nClass {
* Description (tooltip text) for an input label, whether top-level or nested. * Description (tooltip text) for an input label, whether top-level or nested.
*/ */
inputLabelDescription( inputLabelDescription(
parameter: { name: string; description: string; type: string }, parameter: INodeProperties,
path: string, path: string,
) { ) {
const middleKey = deriveMiddleKey(path, parameter); const middleKey = deriveMiddleKey(path, parameter);
@ -230,7 +229,7 @@ export class I18nClass {
* Hint for an input, whether top-level or nested. * Hint for an input, whether top-level or nested.
*/ */
hint( hint(
parameter: { name: string; hint: string; type: string }, parameter: INodeProperties,
path: string, path: string,
) { ) {
const middleKey = deriveMiddleKey(path, parameter); const middleKey = deriveMiddleKey(path, parameter);
@ -248,7 +247,7 @@ export class I18nClass {
* - For a `collection` or `fixedCollection`, the placeholder is the button text. * - For a `collection` or `fixedCollection`, the placeholder is the button text.
*/ */
placeholder( placeholder(
parameter: { name: string; placeholder?: string; type: string }, parameter: INodeProperties,
path: string, path: string,
) { ) {
let middleKey = parameter.name; let middleKey = parameter.name;
@ -260,7 +259,7 @@ export class I18nClass {
return context.dynamicRender({ return context.dynamicRender({
key: `${initialKey}.${middleKey}.placeholder`, key: `${initialKey}.${middleKey}.placeholder`,
fallback: parameter.placeholder || '', fallback: parameter.placeholder,
}); });
}, },
@ -269,8 +268,8 @@ export class I18nClass {
* whether top-level or nested. * whether top-level or nested.
*/ */
optionsOptionDisplayName( optionsOptionDisplayName(
parameter: { name: string; }, parameter: INodeProperties,
{ value: optionName, name: displayName }: { value: string; name: string; }, { value: optionName, name: displayName }: INodePropertyOptions,
path: string, path: string,
) { ) {
let middleKey = parameter.name; let middleKey = parameter.name;
@ -291,8 +290,8 @@ export class I18nClass {
* whether top-level or nested. * whether top-level or nested.
*/ */
optionsOptionDescription( optionsOptionDescription(
parameter: { name: string; }, parameter: INodeProperties,
{ value: optionName, description }: { value: string; description: string; }, { value: optionName, description }: INodePropertyOptions,
path: string, path: string,
) { ) {
let middleKey = parameter.name; let middleKey = parameter.name;
@ -314,8 +313,8 @@ export class I18nClass {
* be nested in a `collection` or in a `fixedCollection`. * be nested in a `collection` or in a `fixedCollection`.
*/ */
collectionOptionDisplayName( collectionOptionDisplayName(
parameter: { name: string; }, parameter: INodeProperties,
{ name: optionName, displayName }: { name: string; displayName: string; }, { name: optionName, displayName }: INodePropertyCollection,
path: string, path: string,
) { ) {
let middleKey = parameter.name; let middleKey = parameter.name;
@ -340,7 +339,7 @@ export class I18nClass {
) { ) {
return context.dynamicRender({ return context.dynamicRender({
key: `${initialKey}.${parameterName}.multipleValueButtonText`, key: `${initialKey}.${parameterName}.multipleValueButtonText`,
fallback: typeOptions!.multipleValueButtonText!, fallback: typeOptions?.multipleValueButtonText,
}); });
}, },