Add parameter hints for node parameters N8N-2841 (#2704)

* 🔨 base functionality done

* :fix: changes accordingly to review

* :fix: replaced div with n8n-text

* :fix: return wrong deleted color variable

* add mock examples for testing

* add slack node test param

* 🔨 changed font size of hint, added top margin

* 🔨 updated comments and function name

* 🔨 updated parameterHint to hint

* 🔨 updated text color, set compact to true, changed inputLabelHint to hint

* 🔨 updated components styles

* 🔨 replaced mini with xsmall

* :fix: fixed line height

* :fix: changed line height to 1.25

* :hummer: removed mock data

* 🔨 changed xsmall line-height

*  update to merge hint

Co-authored-by: Mutasem <mutdmour@gmail.com>
This commit is contained in:
Michael Kret 2022-01-28 08:55:25 +02:00 committed by GitHub
parent 9639742cc6
commit 6d6f3acd97
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 88 additions and 2 deletions

View file

@ -7,7 +7,7 @@ export default {
size: { size: {
control: { control: {
type: 'select', type: 'select',
options: ['small', 'medium', 'large'], options: ['xsmall', 'small', 'medium', 'large'],
}, },
}, },
color: { color: {

View file

@ -16,7 +16,7 @@ export default Vue.extend({
size: { size: {
type: String, type: String,
default: 'medium', default: 'medium',
validator: (value: string): boolean => ['mini', 'small', 'medium', 'large', 'xlarge'].includes(value), validator: (value: string): boolean => ['xsmall', 'mini', 'small', 'medium', 'large', 'xlarge'].includes(value),
}, },
color: { color: {
type: String, type: String,
@ -122,4 +122,19 @@ export default Vue.extend({
composes: body-small; composes: body-small;
} }
.body-xsmall {
font-size: var(--font-size-3xs);
line-height: var(--font-line-height-compact);
}
.body-xsmall-regular {
composes: regular;
composes: body-xsmall;
}
.body-xsmall-bold {
composes: bold;
composes: body-xsmall;
}
</style> </style>

View file

@ -316,6 +316,7 @@
--border-base: var(--border-width-base) var(--border-style-base) --border-base: var(--border-width-base) var(--border-style-base)
var(--color-foreground-base); var(--color-foreground-base);
--font-size-3xs: 0.625rem;
--font-size-2xs: 0.75rem; --font-size-2xs: 0.75rem;
--font-size-xs: 0.8125rem; --font-size-xs: 0.8125rem;
--font-size-s: 0.875rem; --font-size-s: 0.875rem;

View file

@ -23,18 +23,21 @@
<div class="errors" v-if="showRequiredErrors"> <div class="errors" v-if="showRequiredErrors">
{{ $locale.baseText('parameterInputExpanded.thisFieldIsRequired') }} <a v-if="documentationUrl" :href="documentationUrl" target="_blank" @click="onDocumentationUrlClick">{{ $locale.baseText('parameterInputExpanded.openDocs') }}</a> {{ $locale.baseText('parameterInputExpanded.thisFieldIsRequired') }} <a v-if="documentationUrl" :href="documentationUrl" target="_blank" @click="onDocumentationUrlClick">{{ $locale.baseText('parameterInputExpanded.openDocs') }}</a>
</div> </div>
<input-hint :class="$style.hint" :hint="$locale.credText().hint(parameter)" />
</n8n-input-label> </n8n-input-label>
</template> </template>
<script lang="ts"> <script lang="ts">
import { IUpdateInformation } from '@/Interface'; import { IUpdateInformation } from '@/Interface';
import ParameterInput from './ParameterInput.vue'; import ParameterInput from './ParameterInput.vue';
import InputHint from './ParameterInputHint.vue';
import Vue from 'vue'; import Vue from 'vue';
export default Vue.extend({ export default Vue.extend({
name: 'ParameterInputExpanded', name: 'ParameterInputExpanded',
components: { components: {
ParameterInput, ParameterInput,
InputHint,
}, },
props: { props: {
parameter: { parameter: {
@ -94,3 +97,9 @@ export default Vue.extend({
}, },
}); });
</script> </script>
<style lang="scss" module>
.hint {
margin-top: var(--spacing-4xs);
}
</style>

View file

@ -16,6 +16,7 @@
@focus="focused = true" @focus="focused = true"
@blur="focused = false" @blur="focused = false"
inputSize="small" /> inputSize="small" />
<input-hint :class="$style.hint" :hint="$locale.nodeText().hint(parameter, path)" />
</n8n-input-label> </n8n-input-label>
</template> </template>
@ -27,12 +28,14 @@ import {
} from '@/Interface'; } from '@/Interface';
import ParameterInput from '@/components/ParameterInput.vue'; import ParameterInput from '@/components/ParameterInput.vue';
import InputHint from './ParameterInputHint.vue';
export default Vue export default Vue
.extend({ .extend({
name: 'ParameterInputFull', name: 'ParameterInputFull',
components: { components: {
ParameterInput, ParameterInput,
InputHint,
}, },
data() { data() {
return { return {
@ -64,3 +67,9 @@ export default Vue
}, },
}); });
</script> </script>
<style lang="scss" module>
.hint {
margin-top: var(--spacing-4xs);
}
</style>

View file

@ -0,0 +1,22 @@
<template>
<div>
<n8n-text size="xsmall" color="text-base" v-if="hint">
<div ref="hint" v-html="hint"></div>
</n8n-text>
</div>
</template>
<script lang="ts">
import Vue from "vue";
export default Vue.extend({
name: 'InputHint',
props: ['hint'],
mounted(){
if(this.$refs.hint){
(this.$refs.hint as Element).querySelectorAll('a').forEach(a => a.target = "_blank");
}
},
});
</script>

View file

@ -110,6 +110,18 @@ export class I18nClass {
}); });
}, },
/**
* Hint for a top-level param.
*/
hint(
{ name: parameterName, hint }: { name: string; hint: string; },
) {
return context.dynamicRender({
key: `${credentialPrefix}.${parameterName}.hint`,
fallback: hint,
});
},
/** /**
* Description (tooltip text) for an input label param. * Description (tooltip text) for an input label param.
*/ */
@ -205,6 +217,21 @@ export class I18nClass {
}); });
}, },
/**
* Hint for an input, whether top-level or nested.
*/
hint(
parameter: { name: string; hint: string; type: string },
path: string,
) {
const middleKey = deriveMiddleKey(path, parameter);
return context.dynamicRender({
key: `${initialKey}.${middleKey}.hint`,
fallback: parameter.hint,
});
},
/** /**
* Placeholder for an input label or `collection` or `fixedCollection` param, * Placeholder for an input label or `collection` or `fixedCollection` param,
* whether top-level or nested. * whether top-level or nested.

View file

@ -111,6 +111,7 @@ export class Merge implements INodeType {
name: 'propertyName1', name: 'propertyName1',
type: 'string', type: 'string',
default: '', default: '',
hint: 'The name of the field as text (e.g. “id”)',
required: true, required: true,
displayOptions: { displayOptions: {
show: { show: {
@ -128,6 +129,7 @@ export class Merge implements INodeType {
name: 'propertyName2', name: 'propertyName2',
type: 'string', type: 'string',
default: '', default: '',
hint: 'The name of the field as text (e.g. “id”)',
required: true, required: true,
displayOptions: { displayOptions: {
show: { show: {

View file

@ -670,6 +670,7 @@ export interface INodeProperties {
typeOptions?: INodePropertyTypeOptions; typeOptions?: INodePropertyTypeOptions;
default: NodeParameterValue | INodeParameters | INodeParameters[] | NodeParameterValue[]; default: NodeParameterValue | INodeParameters | INodeParameters[] | NodeParameterValue[];
description?: string; description?: string;
hint?: string;
displayOptions?: IDisplayOptions; displayOptions?: IDisplayOptions;
options?: Array<INodePropertyOptions | INodeProperties | INodePropertyCollection>; options?: Array<INodePropertyOptions | INodeProperties | INodePropertyCollection>;
placeholder?: string; placeholder?: string;