mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 10:02:05 +00:00
feat(editor): update expressions display (#4171)
* N8n 4673 expressions res1 (#4149) * hide hints if necessary * refactor out parameter input * refactor param input in creds * remove any * add expression result before * update case * add types * fix spacing * update types * update expr * update parameter input * update param input * update param input * remove import * fix typo * update value * fix drop for rl * add state to track hovering item * add hover behavior to resolve values * update index * fix run selector bug * add run item to eval expr * add paired item mappings * fix rec bug * Fix for loops * handle pinned data * add missing pinned * fix bug * support parent * add input * map back from output * clean up * fix output bug * fix branching bug * update preview * only if expr * fix output * fix expr eval for outputs * add default hover state * fix hover state * fix branching * hide hint if expr * remove duplicate logic * update style * allow opening expr in demo * update expr * update row hover * update param name * clean up * update hovering state * update default output * fix duplicate import * update hover behavior * update package lock * fix pinned data case * address case when no input
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
:value="value"
|
||||
:displayTitle="displayTitle"
|
||||
:expressionDisplayValue="expressionDisplayValue"
|
||||
:expressionComputedValue="expressionEvaluated"
|
||||
:isValueExpression="isValueExpression"
|
||||
:isReadOnly="isReadOnly"
|
||||
:parameterIssues="getIssues"
|
||||
@@ -37,7 +38,7 @@
|
||||
:size="inputSize"
|
||||
:type="getStringInputType"
|
||||
:rows="getArgument('rows')"
|
||||
:value="activeDrop || forceShowExpression? '': expressionDisplayValue"
|
||||
:value="expressionDisplayValue"
|
||||
:title="displayTitle"
|
||||
@keydown.stop
|
||||
/>
|
||||
@@ -297,6 +298,8 @@ import {
|
||||
INodeParameters,
|
||||
INodePropertyOptions,
|
||||
Workflow,
|
||||
INodeProperties,
|
||||
INodePropertyCollection,
|
||||
NodeParameterValueType,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
@@ -316,12 +319,13 @@ import { externalHooks } from '@/components/mixins/externalHooks';
|
||||
import { nodeHelpers } from '@/components/mixins/nodeHelpers';
|
||||
import { showMessage } from '@/components/mixins/showMessage';
|
||||
import { workflowHelpers } from '@/components/mixins/workflowHelpers';
|
||||
import { hasExpressionMapping, isValueExpression } from './helpers';
|
||||
import { isResourceLocatorValue } from '@/typeGuards';
|
||||
|
||||
import mixins from 'vue-typed-mixins';
|
||||
import { CUSTOM_API_CALL_KEY } from '@/constants';
|
||||
import { mapGetters } from 'vuex';
|
||||
import { hasExpressionMapping, isValueExpression } from './helpers';
|
||||
import { isResourceLocatorValue } from '@/typeGuards';
|
||||
import { PropType } from 'vue';
|
||||
|
||||
export default mixins(
|
||||
externalHooks,
|
||||
@@ -344,21 +348,56 @@ export default mixins(
|
||||
TextEdit,
|
||||
ImportParameter,
|
||||
},
|
||||
props: [
|
||||
'inputSize',
|
||||
'isReadOnly',
|
||||
'documentationUrl',
|
||||
'parameter', // NodeProperties
|
||||
'path', // string
|
||||
'value',
|
||||
'hideIssues', // boolean
|
||||
'errorHighlight',
|
||||
'isForCredential', // boolean
|
||||
'eventSource', // string
|
||||
'activeDrop',
|
||||
'droppable',
|
||||
'forceShowExpression',
|
||||
],
|
||||
props: {
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
},
|
||||
parameter: {
|
||||
type: Object as PropType<INodeProperties>,
|
||||
},
|
||||
path: {
|
||||
type: String,
|
||||
},
|
||||
value: {
|
||||
type: [String, Number, Boolean, Array, Object] as PropType<NodeParameterValueType>,
|
||||
},
|
||||
hideLabel: {
|
||||
type: Boolean,
|
||||
},
|
||||
droppable: {
|
||||
type: Boolean,
|
||||
},
|
||||
activeDrop: {
|
||||
type: Boolean,
|
||||
},
|
||||
forceShowExpression: {
|
||||
type: Boolean,
|
||||
},
|
||||
hint: {
|
||||
type: String as PropType<string | undefined>,
|
||||
},
|
||||
inputSize: {
|
||||
type: String,
|
||||
},
|
||||
hideIssues: {
|
||||
type: Boolean,
|
||||
},
|
||||
documentationUrl: {
|
||||
type: String as PropType<string | undefined>,
|
||||
},
|
||||
errorHighlight: {
|
||||
type: Boolean,
|
||||
},
|
||||
isForCredential: {
|
||||
type: Boolean,
|
||||
},
|
||||
eventSource: {
|
||||
type: String,
|
||||
},
|
||||
expressionEvaluated: {
|
||||
type: String as PropType<string | undefined>,
|
||||
},
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
codeEditDialogVisible: false,
|
||||
@@ -419,12 +458,21 @@ export default mixins(
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('credentials', ['allCredentialTypes']),
|
||||
expressionDisplayValue(): string {
|
||||
if (this.activeDrop || this.forceShowExpression) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const value = isResourceLocatorValue(this.value) ? this.value.value : this.value;
|
||||
if (typeof value === 'string' && value.startsWith('=')) {
|
||||
return value.slice(1);
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
isValueExpression(): boolean {
|
||||
return isValueExpression(this.parameter, this.value);
|
||||
},
|
||||
areExpressionsDisabled(): boolean {
|
||||
return this.$store.getters['ui/areExpressionsDisabled'];
|
||||
},
|
||||
codeAutocomplete (): string | undefined {
|
||||
return this.getArgument('codeAutocomplete') as string | undefined;
|
||||
},
|
||||
@@ -486,9 +534,9 @@ export default mixins(
|
||||
|
||||
let returnValue;
|
||||
if (this.isValueExpression === false) {
|
||||
returnValue = this.isResourceLocatorParameter ? (this.value ? this.value.value: '') : this.value;
|
||||
returnValue = this.isResourceLocatorParameter ? (isResourceLocatorValue(this.value) ? this.value.value: '') : this.value;
|
||||
} else {
|
||||
returnValue = this.expressionValueComputed;
|
||||
returnValue = this.expressionEvaluated;
|
||||
}
|
||||
|
||||
if (this.parameter.type === 'credentialsSelect') {
|
||||
@@ -519,39 +567,6 @@ export default mixins(
|
||||
|
||||
return returnValue;
|
||||
},
|
||||
expressionDisplayValue (): string {
|
||||
const value = this.displayValue;
|
||||
|
||||
// address type errors for text input
|
||||
if (typeof value === 'number' || typeof value === 'boolean') {
|
||||
return JSON.stringify(value);
|
||||
}
|
||||
|
||||
if (value === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
expressionValueComputed (): NodeParameterValue | string[] | null {
|
||||
if (this.areExpressionsDisabled) {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
if (this.node === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let computedValue: NodeParameterValue;
|
||||
|
||||
try {
|
||||
computedValue = this.resolveExpression(this.value.value || this.value) as NodeParameterValue;
|
||||
} catch (error) {
|
||||
computedValue = `[${this.$locale.baseText('parameterInput.error')}}: ${error.message}]`;
|
||||
}
|
||||
|
||||
return computedValue;
|
||||
},
|
||||
getStringInputType () {
|
||||
if (this.getArgument('password') === true) {
|
||||
return 'password';
|
||||
@@ -562,7 +577,7 @@ export default mixins(
|
||||
return 'textarea';
|
||||
}
|
||||
|
||||
if (this.parameter.type === 'code') {
|
||||
if (this.parameter.typeOptions && this.parameter.typeOptions.editor === 'code') {
|
||||
return 'textarea';
|
||||
}
|
||||
|
||||
@@ -587,13 +602,14 @@ export default mixins(
|
||||
} else if (
|
||||
['options', 'multiOptions'].includes(this.parameter.type) &&
|
||||
this.remoteParameterOptionsLoading === false &&
|
||||
this.remoteParameterOptionsLoadingIssues === null
|
||||
this.remoteParameterOptionsLoadingIssues === null &&
|
||||
this.parameterOptions
|
||||
) {
|
||||
// Check if the value resolves to a valid option
|
||||
// Currently it only displays an error in the node itself in
|
||||
// case the value is not valid. The workflow can still be executed
|
||||
// and the error is not displayed on the node in the workflow
|
||||
const validOptions = this.parameterOptions!.map((options: INodePropertyOptions) => options.value);
|
||||
const validOptions = this.parameterOptions.map((options) => (options as INodePropertyOptions).value);
|
||||
|
||||
const checkValues: string[] = [];
|
||||
|
||||
@@ -640,7 +656,7 @@ export default mixins(
|
||||
editorType (): string {
|
||||
return this.getArgument('editor') as string;
|
||||
},
|
||||
parameterOptions (): INodePropertyOptions[] {
|
||||
parameterOptions (): Array<INodePropertyOptions | INodeProperties | INodePropertyCollection> | undefined {
|
||||
if (this.hasRemoteMethod === false) {
|
||||
// Options are already given
|
||||
return this.parameter.options;
|
||||
@@ -828,10 +844,6 @@ export default mixins(
|
||||
this.valueChanged(val);
|
||||
},
|
||||
openExpressionEdit() {
|
||||
if (this.areExpressionsDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isValueExpression) {
|
||||
this.expressionEditDialogVisible = true;
|
||||
this.trackExpressionEditOpen();
|
||||
@@ -896,7 +908,7 @@ export default mixins(
|
||||
|
||||
this.$emit('textInput', parameterData);
|
||||
},
|
||||
valueChanged (value: string[] | string | number | boolean | Date | {} | null) {
|
||||
valueChanged (value: NodeParameterValueType | {} | Date) {
|
||||
if (this.parameter.name === 'nodeCredentialType') {
|
||||
this.activeCredentialType = value as string;
|
||||
}
|
||||
@@ -905,7 +917,7 @@ export default mixins(
|
||||
value = value.toISOString();
|
||||
}
|
||||
|
||||
if (this.parameter.type === 'color' && this.getArgument('showAlpha') === true && value !== null && value.toString().charAt(0) !== '#') {
|
||||
if (this.parameter.type === 'color' && this.getArgument('showAlpha') === true && value !== null && value !== undefined && value.toString().charAt(0) !== '#') {
|
||||
const newValue = this.rgbaToHex(value as string);
|
||||
if (newValue !== null) {
|
||||
this.tempValue = newValue;
|
||||
@@ -959,14 +971,14 @@ export default mixins(
|
||||
this.trackExpressionEditOpen();
|
||||
}, 375);
|
||||
} else if (command === 'removeExpression') {
|
||||
let value = this.expressionValueComputed;
|
||||
let value: NodeParameterValueType = this.expressionEvaluated;
|
||||
|
||||
if (this.parameter.type === 'multiOptions' && typeof value === 'string') {
|
||||
value = (value || '').split(',')
|
||||
.filter((value) => (this.parameterOptions || []).find((option) => option.value === value));
|
||||
.filter((value) => (this.parameterOptions || []).find((option) => (option as INodePropertyOptions).value === value));
|
||||
}
|
||||
|
||||
if (this.isResourceLocatorParameter) {
|
||||
if (this.isResourceLocatorParameter && isResourceLocatorValue(this.value)) {
|
||||
this.valueChanged({ __rl: true, value, mode: this.value.mode });
|
||||
} else {
|
||||
this.valueChanged(typeof value !== 'undefined' ? value : null);
|
||||
|
||||
Reference in New Issue
Block a user