From 135ef75add8a42ce5163cce934ac5b2757ca4fe3 Mon Sep 17 00:00:00 2001 From: Elias Meire Date: Thu, 18 Apr 2024 14:56:04 +0200 Subject: [PATCH] fix(editor): Fix parameter reset on credential change in Discord node (#9137) --- cypress/e2e/5-ndv.cy.ts | 19 ++++++++++- .../editor-ui/src/components/NodeSettings.vue | 34 +++++++++++++------ 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/cypress/e2e/5-ndv.cy.ts b/cypress/e2e/5-ndv.cy.ts index 7ce95aba055f1..6103dbbc039f6 100644 --- a/cypress/e2e/5-ndv.cy.ts +++ b/cypress/e2e/5-ndv.cy.ts @@ -3,6 +3,8 @@ import { getVisibleSelect } from '../utils'; import { MANUAL_TRIGGER_NODE_DISPLAY_NAME } from '../constants'; import { NDV, WorkflowPage } from '../pages'; import { NodeCreator } from '../pages/features/node-creator'; +import { clickCreateNewCredential } from '../composables/ndv'; +import { setCredentialValues } from '../composables/modals/credential-modal'; const workflowPage = new WorkflowPage(); const ndv = new NDV(); @@ -633,7 +635,7 @@ describe('NDV', () => { ndv.getters.nodeRunErrorIndicator().should('exist'); }); - it('Should handle mismatched option attributes', () => { + it('Should clear mismatched collection parameters', () => { workflowPage.actions.addInitialNodeToCanvas('LDAP', { keepNdvOpen: true, action: 'Create a new entry', @@ -656,6 +658,21 @@ describe('NDV', () => { ndv.getters.resourceLocatorInput('documentId').find('input').should('have.value', TEST_DOC_ID); }); + it('Should not clear resource/operation after credential change', () => { + workflowPage.actions.addInitialNodeToCanvas('Discord', { + keepNdvOpen: true, + action: 'Delete a message', + }); + + clickCreateNewCredential(); + setCredentialValues({ + botToken: 'sk_test_123', + }); + + ndv.getters.parameterInput('resource').find('input').should('have.value', 'Message'); + ndv.getters.parameterInput('operation').find('input').should('have.value', 'Delete'); + }); + it('Should open appropriate node creator after clicking on connection hint link', () => { const nodeCreator = new NodeCreator(); const hintMapper = { diff --git a/packages/editor-ui/src/components/NodeSettings.vue b/packages/editor-ui/src/components/NodeSettings.vue index 3b464f9dc9bb3..1f5b54a7f1d97 100644 --- a/packages/editor-ui/src/components/NodeSettings.vue +++ b/packages/editor-ui/src/components/NodeSettings.vue @@ -187,7 +187,15 @@ import type { NodeParameterValue, ConnectionTypes, } from 'n8n-workflow'; -import { NodeHelpers, NodeConnectionType, deepCopy } from 'n8n-workflow'; +import { + NodeHelpers, + NodeConnectionType, + deepCopy, + isINodePropertyCollectionList, + isINodePropertiesList, + isINodePropertyOptionsList, + displayParameter, +} from 'n8n-workflow'; import type { INodeUi, INodeUpdatePropertiesInformation, @@ -990,21 +998,27 @@ export default defineComponent({ if (!nodeParameterValues?.hasOwnProperty(prop.name) || !displayOptions || !prop.options) { return; } - // Only process the parameters that should be hidden + // Only process the parameters that depend on the updated parameter const showCondition = displayOptions.show?.[updatedParameter.name]; const hideCondition = displayOptions.hide?.[updatedParameter.name]; if (showCondition === undefined && hideCondition === undefined) { return; } + + let hasValidOptions = true; + // Every value should be a possible option - const hasValidOptions = Object.keys(nodeParameterValues).every( - (key) => (prop.options ?? []).find((option) => option.name === key) !== undefined, - ); - if ( - !hasValidOptions || - showCondition !== updatedParameter.value || - hideCondition === updatedParameter.value - ) { + if (isINodePropertyCollectionList(prop.options) || isINodePropertiesList(prop.options)) { + hasValidOptions = Object.keys(nodeParameterValues).every( + (key) => (prop.options ?? []).find((option) => option.name === key) !== undefined, + ); + } else if (isINodePropertyOptionsList(prop.options)) { + hasValidOptions = !!prop.options.find( + (option) => option.value === nodeParameterValues[prop.name], + ); + } + + if (!hasValidOptions && displayParameter(nodeParameterValues, prop, this.node)) { unset(nodeParameterValues as object, prop.name); } });