mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
refactor: Refactor input components to composition API (no-changelog) (#9744)
This commit is contained in:
@@ -161,27 +161,26 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
<script setup lang="ts">
|
||||
import type {
|
||||
INodeParameters,
|
||||
INodeProperties,
|
||||
INodeTypeDescription,
|
||||
NodeParameterValue,
|
||||
NodeParameterValueType,
|
||||
} from 'n8n-workflow';
|
||||
import { deepCopy } from 'n8n-workflow';
|
||||
import { mapStores } from 'pinia';
|
||||
import type { PropType } from 'vue';
|
||||
import { defineAsyncComponent, defineComponent, onErrorCaptured, ref } from 'vue';
|
||||
import { computed, defineAsyncComponent, onErrorCaptured, ref, watch } from 'vue';
|
||||
|
||||
import type { INodeUi, IUpdateInformation } from '@/Interface';
|
||||
import type { IUpdateInformation } from '@/Interface';
|
||||
|
||||
import AssignmentCollection from '@/components/AssignmentCollection/AssignmentCollection.vue';
|
||||
import FilterConditions from '@/components/FilterConditions/FilterConditions.vue';
|
||||
import ImportCurlParameter from '@/components/ImportCurlParameter.vue';
|
||||
import MultipleParameter from '@/components/MultipleParameter.vue';
|
||||
import ParameterInputFull from '@/components/ParameterInputFull.vue';
|
||||
import ResourceMapper from '@/components/ResourceMapper/ResourceMapper.vue';
|
||||
import FilterConditions from '@/components/FilterConditions/FilterConditions.vue';
|
||||
import AssignmentCollection from '@/components/AssignmentCollection/AssignmentCollection.vue';
|
||||
import { useNodeHelpers } from '@/composables/useNodeHelpers';
|
||||
import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers';
|
||||
import { KEEP_AUTH_IN_NDV_FOR_NODES } from '@/constants';
|
||||
import { useNDVStore } from '@/stores/ndv.store';
|
||||
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
||||
@@ -191,9 +190,7 @@ import {
|
||||
isAuthRelatedParameter,
|
||||
} from '@/utils/nodeTypesUtils';
|
||||
import { get, set } from 'lodash-es';
|
||||
import { useNodeHelpers } from '@/composables/useNodeHelpers';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers';
|
||||
|
||||
const FixedCollectionParameter = defineAsyncComponent(
|
||||
async () => await import('./FixedCollectionParameter.vue'),
|
||||
@@ -202,382 +199,344 @@ const CollectionParameter = defineAsyncComponent(
|
||||
async () => await import('./CollectionParameter.vue'),
|
||||
);
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ParameterInputList',
|
||||
components: {
|
||||
MultipleParameter,
|
||||
ParameterInputFull,
|
||||
FixedCollectionParameter,
|
||||
CollectionParameter,
|
||||
ImportCurlParameter,
|
||||
ResourceMapper,
|
||||
FilterConditions,
|
||||
AssignmentCollection,
|
||||
},
|
||||
props: {
|
||||
nodeValues: {
|
||||
type: Object as PropType<INodeParameters>,
|
||||
required: true,
|
||||
},
|
||||
parameters: {
|
||||
type: Array as PropType<INodeProperties[]>,
|
||||
required: true,
|
||||
},
|
||||
path: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
hideDelete: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
indent: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isReadOnly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
hiddenIssuesInputs: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => [],
|
||||
},
|
||||
entryIndex: {
|
||||
type: Number,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const nodeHelpers = useNodeHelpers();
|
||||
const asyncLoadingError = ref(false);
|
||||
const router = useRouter();
|
||||
const workflowHelpers = useWorkflowHelpers({ router });
|
||||
type Props = {
|
||||
nodeValues: INodeParameters;
|
||||
parameters: INodeProperties[];
|
||||
path?: string;
|
||||
hideDelete?: boolean;
|
||||
indent?: boolean;
|
||||
isReadOnly?: boolean;
|
||||
hiddenIssuesInputs?: string[];
|
||||
entryIndex?: number;
|
||||
};
|
||||
|
||||
// This will catch errors in async components
|
||||
onErrorCaptured((e, component) => {
|
||||
if (
|
||||
!['FixedCollectionParameter', 'CollectionParameter'].includes(
|
||||
component?.$options.name as string,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
asyncLoadingError.value = true;
|
||||
console.error(e);
|
||||
window?.Sentry?.captureException(e, {
|
||||
tags: {
|
||||
asyncLoadingError: true,
|
||||
},
|
||||
});
|
||||
// Don't propagate the error further
|
||||
return false;
|
||||
});
|
||||
const props = withDefaults(defineProps<Props>(), { path: '', hiddenIssuesInputs: () => [] });
|
||||
const emit = defineEmits<{
|
||||
(event: 'activate'): void;
|
||||
(event: 'valueChanged', value: IUpdateInformation): void;
|
||||
(event: 'parameterBlur', value: string): void;
|
||||
}>();
|
||||
|
||||
return {
|
||||
nodeHelpers,
|
||||
asyncLoadingError,
|
||||
workflowHelpers,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useNodeTypesStore, useNDVStore),
|
||||
nodeTypeVersion(): number | null {
|
||||
if (this.node) {
|
||||
return this.node.typeVersion;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
nodeTypeName(): string {
|
||||
if (this.node) {
|
||||
return this.node.type;
|
||||
}
|
||||
return '';
|
||||
},
|
||||
nodeType(): INodeTypeDescription | null {
|
||||
if (this.node) {
|
||||
return this.nodeTypesStore.getNodeType(this.node.type, this.node.typeVersion);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
filteredParameters(): INodeProperties[] {
|
||||
return this.parameters.filter((parameter: INodeProperties) =>
|
||||
this.displayNodeParameter(parameter),
|
||||
);
|
||||
},
|
||||
filteredParameterNames(): string[] {
|
||||
return this.filteredParameters.map((parameter) => parameter.name);
|
||||
},
|
||||
node(): INodeUi | null {
|
||||
return this.ndvStore.activeNode;
|
||||
},
|
||||
nodeAuthFields(): INodeProperties[] {
|
||||
return getNodeAuthFields(this.nodeType);
|
||||
},
|
||||
credentialsParameterIndex(): number {
|
||||
return this.filteredParameters.findIndex((parameter) => parameter.type === 'credentials');
|
||||
},
|
||||
indexToShowSlotAt(): number {
|
||||
const credentialsParameterIndex = this.credentialsParameterIndex;
|
||||
const nodeTypesStore = useNodeTypesStore();
|
||||
const ndvStore = useNDVStore();
|
||||
|
||||
if (credentialsParameterIndex !== -1) {
|
||||
return credentialsParameterIndex;
|
||||
}
|
||||
const nodeHelpers = useNodeHelpers();
|
||||
const asyncLoadingError = ref(false);
|
||||
const router = useRouter();
|
||||
const workflowHelpers = useWorkflowHelpers({ router });
|
||||
|
||||
let index = 0;
|
||||
// For nodes that use old credentials UI, keep credentials below authentication field in NDV
|
||||
// otherwise credentials will use auth filed position since the auth field is moved to credentials modal
|
||||
const fieldOffset = KEEP_AUTH_IN_NDV_FOR_NODES.includes(this.nodeType?.name || '') ? 1 : 0;
|
||||
const credentialsDependencies = this.getCredentialsDependencies();
|
||||
onErrorCaptured((e, component) => {
|
||||
if (
|
||||
!['FixedCollectionParameter', 'CollectionParameter'].includes(
|
||||
component?.$options.name as string,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
asyncLoadingError.value = true;
|
||||
console.error(e);
|
||||
window?.Sentry?.captureException(e, {
|
||||
tags: {
|
||||
asyncLoadingError: true,
|
||||
},
|
||||
});
|
||||
// Don't propagate the error further
|
||||
return false;
|
||||
});
|
||||
|
||||
this.filteredParameters.forEach((prop, propIndex) => {
|
||||
if (credentialsDependencies.has(prop.name)) {
|
||||
index = propIndex + fieldOffset;
|
||||
}
|
||||
});
|
||||
const nodeType = computed(() => {
|
||||
if (node.value) {
|
||||
return nodeTypesStore.getNodeType(node.value.type, node.value.typeVersion);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
return Math.min(index, this.filteredParameters.length - 1);
|
||||
},
|
||||
mainNodeAuthField(): INodeProperties | null {
|
||||
return getMainAuthField(this.nodeType || null);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
filteredParameterNames(newValue, oldValue) {
|
||||
if (newValue === undefined) {
|
||||
return;
|
||||
}
|
||||
// After a parameter does not get displayed anymore make sure that its value gets removed
|
||||
// Is only needed for the edge-case when a parameter gets displayed depending on another field
|
||||
// which contains an expression.
|
||||
for (const parameter of oldValue) {
|
||||
if (!newValue.includes(parameter)) {
|
||||
const parameterData = {
|
||||
name: `${this.path}.${parameter}`,
|
||||
node: this.ndvStore.activeNode?.name || '',
|
||||
value: undefined,
|
||||
};
|
||||
this.$emit('valueChanged', parameterData);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onParameterBlur(parameterName: string) {
|
||||
this.$emit('parameterBlur', parameterName);
|
||||
},
|
||||
getCredentialsDependencies() {
|
||||
const dependencies = new Set();
|
||||
const nodeType = this.nodeTypesStore.getNodeType(
|
||||
this.node?.type || '',
|
||||
this.node?.typeVersion,
|
||||
);
|
||||
const filteredParameters = computed(() => {
|
||||
return props.parameters.filter((parameter: INodeProperties) => displayNodeParameter(parameter));
|
||||
});
|
||||
|
||||
// Get names of all fields that credentials rendering depends on (using displayOptions > show)
|
||||
if (nodeType?.credentials) {
|
||||
for (const cred of nodeType.credentials) {
|
||||
if (cred.displayOptions?.show) {
|
||||
Object.keys(cred.displayOptions.show).forEach((fieldName) =>
|
||||
dependencies.add(fieldName),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dependencies;
|
||||
},
|
||||
multipleValues(parameter: INodeProperties): boolean {
|
||||
return this.getArgument('multipleValues', parameter) === true;
|
||||
},
|
||||
getArgument(
|
||||
argumentName: string,
|
||||
parameter: INodeProperties,
|
||||
): string | string[] | number | boolean | undefined {
|
||||
if (parameter.typeOptions === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const filteredParameterNames = computed(() => {
|
||||
return filteredParameters.value.map((parameter) => parameter.name);
|
||||
});
|
||||
|
||||
if (parameter.typeOptions[argumentName] === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const node = computed(() => ndvStore.activeNode);
|
||||
|
||||
return parameter.typeOptions[argumentName];
|
||||
},
|
||||
getPath(parameterName: string): string {
|
||||
return (this.path ? `${this.path}.` : '') + parameterName;
|
||||
},
|
||||
deleteOption(optionName: string): void {
|
||||
const nodeAuthFields = computed(() => {
|
||||
return getNodeAuthFields(nodeType.value);
|
||||
});
|
||||
|
||||
const credentialsParameterIndex = computed(() => {
|
||||
return filteredParameters.value.findIndex((parameter) => parameter.type === 'credentials');
|
||||
});
|
||||
|
||||
const indexToShowSlotAt = computed(() => {
|
||||
if (credentialsParameterIndex.value !== -1) {
|
||||
return credentialsParameterIndex.value;
|
||||
}
|
||||
|
||||
let index = 0;
|
||||
// For nodes that use old credentials UI, keep credentials below authentication field in NDV
|
||||
// otherwise credentials will use auth filed position since the auth field is moved to credentials modal
|
||||
const fieldOffset = KEEP_AUTH_IN_NDV_FOR_NODES.includes(nodeType.value?.name || '') ? 1 : 0;
|
||||
const credentialsDependencies = getCredentialsDependencies();
|
||||
|
||||
filteredParameters.value.forEach((prop, propIndex) => {
|
||||
if (credentialsDependencies.has(prop.name)) {
|
||||
index = propIndex + fieldOffset;
|
||||
}
|
||||
});
|
||||
|
||||
return Math.min(index, filteredParameters.value.length - 1);
|
||||
});
|
||||
|
||||
const mainNodeAuthField = computed(() => {
|
||||
return getMainAuthField(nodeType.value || null);
|
||||
});
|
||||
|
||||
watch(filteredParameterNames, (newValue, oldValue) => {
|
||||
if (newValue === undefined) {
|
||||
return;
|
||||
}
|
||||
// After a parameter does not get displayed anymore make sure that its value gets removed
|
||||
// Is only needed for the edge-case when a parameter gets displayed depending on another field
|
||||
// which contains an expression.
|
||||
for (const parameter of oldValue) {
|
||||
if (!newValue.includes(parameter)) {
|
||||
const parameterData = {
|
||||
name: this.getPath(optionName),
|
||||
name: `${props.path}.${parameter}`,
|
||||
node: ndvStore.activeNode?.name || '',
|
||||
value: undefined,
|
||||
};
|
||||
|
||||
// TODO: If there is only one option it should delete the whole one
|
||||
|
||||
this.$emit('valueChanged', parameterData);
|
||||
},
|
||||
|
||||
mustHideDuringCustomApiCall(parameter: INodeProperties, nodeValues: INodeParameters): boolean {
|
||||
if (parameter?.displayOptions?.hide) return true;
|
||||
|
||||
const MUST_REMAIN_VISIBLE = [
|
||||
'authentication',
|
||||
'resource',
|
||||
'operation',
|
||||
...Object.keys(nodeValues),
|
||||
];
|
||||
|
||||
return !MUST_REMAIN_VISIBLE.includes(parameter.name);
|
||||
},
|
||||
displayNodeParameter(parameter: INodeProperties): boolean {
|
||||
if (parameter.type === 'hidden') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
this.nodeHelpers.isCustomApiCallSelected(this.nodeValues) &&
|
||||
this.mustHideDuringCustomApiCall(parameter, this.nodeValues)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hide authentication related fields since it will now be part of credentials modal
|
||||
if (
|
||||
!KEEP_AUTH_IN_NDV_FOR_NODES.includes(this.node?.type || '') &&
|
||||
this.mainNodeAuthField &&
|
||||
(parameter.name === this.mainNodeAuthField?.name ||
|
||||
this.shouldHideAuthRelatedParameter(parameter))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parameter.displayOptions === undefined) {
|
||||
// If it is not defined no need to do a proper check
|
||||
return true;
|
||||
}
|
||||
|
||||
const nodeValues: INodeParameters = {};
|
||||
let rawValues = this.nodeValues;
|
||||
if (this.path) {
|
||||
rawValues = get(this.nodeValues, this.path) as INodeParameters;
|
||||
}
|
||||
|
||||
if (!rawValues) {
|
||||
return false;
|
||||
}
|
||||
// Resolve expressions
|
||||
const resolveKeys = Object.keys(rawValues);
|
||||
let key: string;
|
||||
let i = 0;
|
||||
let parameterGotResolved = false;
|
||||
do {
|
||||
key = resolveKeys.shift() as string;
|
||||
const value = rawValues[key];
|
||||
if (typeof value === 'string' && value?.charAt(0) === '=') {
|
||||
// Contains an expression that
|
||||
if (
|
||||
value.includes('$parameter') &&
|
||||
resolveKeys.some((parameterName) => value.includes(parameterName))
|
||||
) {
|
||||
// Contains probably an expression of a missing parameter so skip
|
||||
resolveKeys.push(key);
|
||||
continue;
|
||||
} else {
|
||||
// Contains probably no expression with a missing parameter so resolve
|
||||
try {
|
||||
nodeValues[key] = this.workflowHelpers.resolveExpression(
|
||||
value,
|
||||
nodeValues,
|
||||
) as NodeParameterValue;
|
||||
} catch (e) {
|
||||
// If expression is invalid ignore
|
||||
nodeValues[key] = '';
|
||||
}
|
||||
parameterGotResolved = true;
|
||||
}
|
||||
} else {
|
||||
// Does not contain an expression, add directly
|
||||
nodeValues[key] = rawValues[key];
|
||||
}
|
||||
// TODO: Think about how to calculate this best
|
||||
if (i++ > 50) {
|
||||
// Make sure we do not get caught
|
||||
break;
|
||||
}
|
||||
} while (resolveKeys.length !== 0);
|
||||
|
||||
if (parameterGotResolved) {
|
||||
if (this.path) {
|
||||
rawValues = deepCopy(this.nodeValues);
|
||||
set(rawValues, this.path, nodeValues);
|
||||
return this.nodeHelpers.displayParameter(rawValues, parameter, this.path, this.node);
|
||||
} else {
|
||||
return this.nodeHelpers.displayParameter(nodeValues, parameter, '', this.node);
|
||||
}
|
||||
}
|
||||
|
||||
return this.nodeHelpers.displayParameter(this.nodeValues, parameter, this.path, this.node);
|
||||
},
|
||||
valueChanged(parameterData: IUpdateInformation): void {
|
||||
this.$emit('valueChanged', parameterData);
|
||||
},
|
||||
onNoticeAction(action: string) {
|
||||
if (action === 'activate') {
|
||||
this.$emit('activate');
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Handles default node button parameter type actions
|
||||
* @param parameter
|
||||
*/
|
||||
onButtonAction(parameter: INodeProperties) {
|
||||
const action: string | undefined = parameter.typeOptions?.action;
|
||||
|
||||
switch (action) {
|
||||
default:
|
||||
return;
|
||||
}
|
||||
},
|
||||
isNodeAuthField(name: string): boolean {
|
||||
return this.nodeAuthFields.find((field) => field.name === name) !== undefined;
|
||||
},
|
||||
shouldHideAuthRelatedParameter(parameter: INodeProperties): boolean {
|
||||
// TODO: For now, hide all fields that are used in authentication fields displayOptions
|
||||
// Ideally, we should check if any non-auth field depends on it before hiding it but
|
||||
// since there is no such case, omitting it to avoid additional computation
|
||||
return isAuthRelatedParameter(this.nodeAuthFields, parameter);
|
||||
},
|
||||
shouldShowOptions(parameter: INodeProperties): boolean {
|
||||
return parameter.type !== 'resourceMapper';
|
||||
},
|
||||
getDependentParametersValues(parameter: INodeProperties): string | null {
|
||||
const loadOptionsDependsOn = this.getArgument('loadOptionsDependsOn', parameter) as
|
||||
| string[]
|
||||
| undefined;
|
||||
|
||||
if (loadOptionsDependsOn === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the resolved parameter values of the current node
|
||||
const currentNodeParameters = this.ndvStore.activeNode?.parameters;
|
||||
try {
|
||||
const resolvedNodeParameters = this.workflowHelpers.resolveParameter(currentNodeParameters);
|
||||
|
||||
const returnValues: string[] = [];
|
||||
for (const parameterPath of loadOptionsDependsOn) {
|
||||
returnValues.push(get(resolvedNodeParameters, parameterPath) as string);
|
||||
}
|
||||
|
||||
return returnValues.join('|');
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
getParameterValue<T extends NodeParameterValueType = NodeParameterValueType>(name: string): T {
|
||||
return this.nodeHelpers.getParameterValue(this.nodeValues, name, this.path) as T;
|
||||
},
|
||||
},
|
||||
emit('valueChanged', parameterData);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function onParameterBlur(parameterName: string) {
|
||||
emit('parameterBlur', parameterName);
|
||||
}
|
||||
|
||||
function getCredentialsDependencies() {
|
||||
const dependencies = new Set();
|
||||
|
||||
// Get names of all fields that credentials rendering depends on (using displayOptions > show)
|
||||
if (nodeType.value?.credentials) {
|
||||
for (const cred of nodeType.value.credentials) {
|
||||
if (cred.displayOptions?.show) {
|
||||
Object.keys(cred.displayOptions.show).forEach((fieldName) => dependencies.add(fieldName));
|
||||
}
|
||||
}
|
||||
}
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
function multipleValues(parameter: INodeProperties): boolean {
|
||||
return getArgument('multipleValues', parameter) === true;
|
||||
}
|
||||
|
||||
function getArgument(
|
||||
argumentName: string,
|
||||
parameter: INodeProperties,
|
||||
): string | string[] | number | boolean | undefined {
|
||||
if (parameter.typeOptions === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (parameter.typeOptions[argumentName] === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return parameter.typeOptions[argumentName];
|
||||
}
|
||||
|
||||
function getPath(parameterName: string): string {
|
||||
return (props.path ? `${props.path}.` : '') + parameterName;
|
||||
}
|
||||
|
||||
function deleteOption(optionName: string): void {
|
||||
const parameterData = {
|
||||
name: getPath(optionName),
|
||||
value: undefined,
|
||||
};
|
||||
|
||||
// TODO: If there is only one option it should delete the whole one
|
||||
|
||||
emit('valueChanged', parameterData);
|
||||
}
|
||||
|
||||
function mustHideDuringCustomApiCall(
|
||||
parameter: INodeProperties,
|
||||
nodeValues: INodeParameters,
|
||||
): boolean {
|
||||
if (parameter?.displayOptions?.hide) return true;
|
||||
|
||||
const MUST_REMAIN_VISIBLE = [
|
||||
'authentication',
|
||||
'resource',
|
||||
'operation',
|
||||
...Object.keys(nodeValues),
|
||||
];
|
||||
|
||||
return !MUST_REMAIN_VISIBLE.includes(parameter.name);
|
||||
}
|
||||
|
||||
function displayNodeParameter(parameter: INodeProperties): boolean {
|
||||
if (parameter.type === 'hidden') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
nodeHelpers.isCustomApiCallSelected(props.nodeValues) &&
|
||||
mustHideDuringCustomApiCall(parameter, props.nodeValues)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Hide authentication related fields since it will now be part of credentials modal
|
||||
if (
|
||||
!KEEP_AUTH_IN_NDV_FOR_NODES.includes(node.value?.type || '') &&
|
||||
mainNodeAuthField.value &&
|
||||
(parameter.name === mainNodeAuthField.value?.name || shouldHideAuthRelatedParameter(parameter))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parameter.displayOptions === undefined) {
|
||||
// If it is not defined no need to do a proper check
|
||||
return true;
|
||||
}
|
||||
|
||||
const nodeValues: INodeParameters = {};
|
||||
let rawValues = props.nodeValues;
|
||||
if (props.path) {
|
||||
rawValues = get(props.nodeValues, props.path) as INodeParameters;
|
||||
}
|
||||
|
||||
if (!rawValues) {
|
||||
return false;
|
||||
}
|
||||
// Resolve expressions
|
||||
const resolveKeys = Object.keys(rawValues);
|
||||
let key: string;
|
||||
let i = 0;
|
||||
let parameterGotResolved = false;
|
||||
do {
|
||||
key = resolveKeys.shift() as string;
|
||||
const value = rawValues[key];
|
||||
if (typeof value === 'string' && value?.charAt(0) === '=') {
|
||||
// Contains an expression that
|
||||
if (
|
||||
value.includes('$parameter') &&
|
||||
resolveKeys.some((parameterName) => value.includes(parameterName))
|
||||
) {
|
||||
// Contains probably an expression of a missing parameter so skip
|
||||
resolveKeys.push(key);
|
||||
continue;
|
||||
} else {
|
||||
// Contains probably no expression with a missing parameter so resolve
|
||||
try {
|
||||
nodeValues[key] = workflowHelpers.resolveExpression(
|
||||
value,
|
||||
nodeValues,
|
||||
) as NodeParameterValue;
|
||||
} catch (e) {
|
||||
// If expression is invalid ignore
|
||||
nodeValues[key] = '';
|
||||
}
|
||||
parameterGotResolved = true;
|
||||
}
|
||||
} else {
|
||||
// Does not contain an expression, add directly
|
||||
nodeValues[key] = rawValues[key];
|
||||
}
|
||||
// TODO: Think about how to calculate this best
|
||||
if (i++ > 50) {
|
||||
// Make sure we do not get caught
|
||||
break;
|
||||
}
|
||||
} while (resolveKeys.length !== 0);
|
||||
|
||||
if (parameterGotResolved) {
|
||||
if (props.path) {
|
||||
rawValues = deepCopy(props.nodeValues);
|
||||
set(rawValues, props.path, nodeValues);
|
||||
return nodeHelpers.displayParameter(rawValues, parameter, props.path, node.value);
|
||||
} else {
|
||||
return nodeHelpers.displayParameter(nodeValues, parameter, '', node.value);
|
||||
}
|
||||
}
|
||||
|
||||
return nodeHelpers.displayParameter(props.nodeValues, parameter, props.path, node.value);
|
||||
}
|
||||
|
||||
function valueChanged(parameterData: IUpdateInformation): void {
|
||||
emit('valueChanged', parameterData);
|
||||
}
|
||||
|
||||
function onNoticeAction(action: string) {
|
||||
if (action === 'activate') {
|
||||
emit('activate');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles default node button parameter type actions
|
||||
* @param parameter
|
||||
*/
|
||||
function onButtonAction(parameter: INodeProperties) {
|
||||
const action: string | undefined = parameter.typeOptions?.action;
|
||||
|
||||
switch (action) {
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function isNodeAuthField(name: string): boolean {
|
||||
return nodeAuthFields.value.find((field) => field.name === name) !== undefined;
|
||||
}
|
||||
|
||||
function shouldHideAuthRelatedParameter(parameter: INodeProperties): boolean {
|
||||
// TODO: For now, hide all fields that are used in authentication fields displayOptions
|
||||
// Ideally, we should check if any non-auth field depends on it before hiding it but
|
||||
// since there is no such case, omitting it to avoid additional computation
|
||||
return isAuthRelatedParameter(nodeAuthFields.value, parameter);
|
||||
}
|
||||
|
||||
function shouldShowOptions(parameter: INodeProperties): boolean {
|
||||
return parameter.type !== 'resourceMapper';
|
||||
}
|
||||
|
||||
function getDependentParametersValues(parameter: INodeProperties): string | null {
|
||||
const loadOptionsDependsOn = getArgument('loadOptionsDependsOn', parameter) as
|
||||
| string[]
|
||||
| undefined;
|
||||
|
||||
if (loadOptionsDependsOn === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the resolved parameter values of the current node
|
||||
const currentNodeParameters = ndvStore.activeNode?.parameters;
|
||||
try {
|
||||
const resolvedNodeParameters = workflowHelpers.resolveParameter(currentNodeParameters);
|
||||
|
||||
const returnValues: string[] = [];
|
||||
for (const parameterPath of loadOptionsDependsOn) {
|
||||
returnValues.push(get(resolvedNodeParameters, parameterPath) as string);
|
||||
}
|
||||
|
||||
return returnValues.join('|');
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function getParameterValue<T extends NodeParameterValueType = NodeParameterValueType>(
|
||||
name: string,
|
||||
): T {
|
||||
return nodeHelpers.getParameterValue(props.nodeValues, name, props.path) as T;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
Reference in New Issue
Block a user