From 47b2e905bf3f2446066c3d7aed38db42c9918705 Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Wed, 27 Jul 2022 17:16:35 +0200 Subject: [PATCH 01/24] =?UTF-8?q?=E2=9C=A8=20Implemented=20initial=20versi?= =?UTF-8?q?on=20of=20resource=20locator=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/ParameterInput.vue | 8 +- .../src/components/ParameterInputFull.vue | 127 +++++++++++++++--- .../src/components/ResourceLocator/helpers.ts | 10 ++ .../src/plugins/i18n/locales/en.json | 3 + 4 files changed, 128 insertions(+), 20 deletions(-) create mode 100644 packages/editor-ui/src/components/ResourceLocator/helpers.ts diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index 7ba1b7efe65f2..26644e4a812c7 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -26,7 +26,7 @@
@@ -74,7 +74,7 @@ @focus="setFocus" @blur="onBlur" :title="displayTitle" - :placeholder="getPlaceholder()" + :placeholder="inputPlaceholder || getPlaceholder()" >
+ {{ infoText }} @@ -48,6 +79,7 @@ import { INodeUi, IUpdateInformation, } from '@/Interface'; +import { INodePropertyMode } from 'n8n-workflow'; import ParameterInput from '@/components/ParameterInput.vue'; import InputHint from './ParameterInputHint.vue'; @@ -57,6 +89,7 @@ import mixins from 'vue-typed-mixins'; import { showMessage } from './mixins/showMessage'; import { LOCAL_STORAGE_MAPPING_FLAG } from '@/constants'; import { hasExpressionMapping } from './helpers'; +import { getParameterModeLabel } from './ResourceLocator/helpers'; export default mixins( showMessage, @@ -74,6 +107,7 @@ export default mixins( focused: false, menuExpanded: false, forceShowExpression: false, + selectedMode: '', }; }, props: [ @@ -84,10 +118,25 @@ export default mixins( 'value', 'hideLabel', ], + mounted() { + this.selectedMode = this.parameter.modes ? this.parameter.modes[0].name : ''; + }, computed: { node (): INodeUi | null { return this.$store.getters.activeNode; }, + isResourceLocatorParameter (): boolean { + return this.parameter.type === 'resourceLocator'; + }, + infoText (): string { + return this.currentMode.hint ? this.currentMode.hint : this.parameter.description || ''; + }, + currentMode (): INodePropertyMode { + return this.findModeByName(this.selectedMode) || {} as INodePropertyMode; + }, + hasMultipleModes (): boolean { + return this.parameter.modes && this.parameter.modes.length > 1; + }, }, methods: { onFocus() { @@ -156,6 +205,18 @@ export default mixins( this.forceShowExpression = false; }, 200); }, + onModeSelected (value: string): void { + this.selectedMode = value; + }, + findModeByName (name: string): INodePropertyMode | null { + if (this.parameter.modes) { + return this.parameter.modes.find((mode: INodePropertyMode) => mode.name === name) || null; + } + return null; + }, + getModeLabel (name: string): string | null { + return getParameterModeLabel(name); + }, }, }); @@ -164,4 +225,34 @@ export default mixins( .hint { margin-top: var(--spacing-4xs); } + + .resource-locator { + display: flex; + + .input-container { + input { + border-radius: 0 var(--border-radius-base) var(--border-radius-base) 0; + } + } + + &.multiple-modes { + .input-container { + flex-basis: calc(100% - 100px); + } + } + + } + + .mode-selector { + flex-basis: 100px; + + input { + border-radius: var(--border-radius-base) 0 0 var(--border-radius-base); + border-right: none; + + &:focus { + border-right: var(--color-secondary) var(--border-style-base) var(--border-width-base); + } + } + } diff --git a/packages/editor-ui/src/components/ResourceLocator/helpers.ts b/packages/editor-ui/src/components/ResourceLocator/helpers.ts new file mode 100644 index 0000000000000..f742ce51c7085 --- /dev/null +++ b/packages/editor-ui/src/components/ResourceLocator/helpers.ts @@ -0,0 +1,10 @@ + +const RESOURCE_LOCATOR_MODE_LABEL_MAPPING: { [key: string]: string } = { + 'id': 'parameterInput.resourceLocator.mode.id', + 'url': 'parameterInput.resourceLocator.mode.url', + 'list': 'parameterInput.resourceLocator.mode.list', +}; + +export const getParameterModeLabel = (type: string) : string | null => { + return RESOURCE_LOCATOR_MODE_LABEL_MAPPING[type] || null; +}; diff --git a/packages/editor-ui/src/plugins/i18n/locales/en.json b/packages/editor-ui/src/plugins/i18n/locales/en.json index 6e94459cfadfe..b590ec6b7b56e 100644 --- a/packages/editor-ui/src/plugins/i18n/locales/en.json +++ b/packages/editor-ui/src/plugins/i18n/locales/en.json @@ -572,6 +572,9 @@ "parameterInput.parameterHasIssuesAndExpression": "Parameter: \"{shortPath}\" has issues and an expression", "parameterInput.refreshList": "Refresh List", "parameterInput.resetValue": "Reset Value", + "parameterInput.resourceLocator.mode.id": "By ID", + "parameterInput.resourceLocator.mode.url": "By URL", + "parameterInput.resourceLocator.mode.list": "From list", "parameterInput.select": "Select", "parameterInput.selectDateAndTime": "Select date and time", "parameterInput.selectACredentialTypeFromTheDropdown": "Select a credential type from the dropdown", From 4a9213b589805f5a47290eedb4d0e2d21222cf8b Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Thu, 28 Jul 2022 13:28:57 +0200 Subject: [PATCH 02/24] =?UTF-8?q?=E2=9C=A8=20Implemented=20front-end=20val?= =?UTF-8?q?idation=20for=20resource=20locator=20component.=20Improved=20re?= =?UTF-8?q?sponsiveness.=20Minor=20refactoring.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/ParameterInput.vue | 14 ++++++++-- .../src/components/ParameterInputFull.vue | 4 +++ .../src/components/ResourceLocator/helpers.ts | 26 +++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index d0363ccc0efd4..6c02b149f4539 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -74,7 +74,7 @@ @focus="setFocus" @blur="onBlur" :title="displayTitle" - :placeholder="inputPlaceholder || getPlaceholder()" + :placeholder="getPlaceholder()" >
{ return RESOURCE_LOCATOR_MODE_LABEL_MAPPING[type] || null; }; + +// Validates resource locator node parameters based on validation ruled defined in each parameter mode +export const validateResourceLocatorParameter = (displayValue: string, parameterMode: INodePropertyMode) : string[] => { + const validationErrors: string[] = []; + // Each mode can have multiple validations specified + if (parameterMode.validation) { + for (const validation of parameterMode.validation) { + // Currently only regex validation is supported on the front-end + if (validation && (validation as INodePropertyModeValidation).type === 'regex') { + const regexValidation = validation as INodePropertyRegexValidation; + const regex = new RegExp(regexValidation.properties.regex); + + if (!regex.test(displayValue)) { + validationErrors.push(regexValidation.properties.errorMessage); + } + } + } + } + + return validationErrors; +}; From f98bbae353f8bfd044203718ac63171fe003723e Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Mon, 1 Aug 2022 13:21:26 +0200 Subject: [PATCH 03/24] =?UTF-8?q?=E2=9A=A1=20Setting=20resource=20locator?= =?UTF-8?q?=20default=20state=20to=20list.=20Updating=20hover=20states=20a?= =?UTF-8?q?nd=20expand=20icon.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/editor-ui/src/components/MainSidebar.vue | 4 ++-- packages/editor-ui/src/components/ParameterInput.vue | 2 +- packages/editor-ui/src/components/ParameterInputFull.vue | 6 +++++- packages/editor-ui/src/plugins/icons.ts | 2 ++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/editor-ui/src/components/MainSidebar.vue b/packages/editor-ui/src/components/MainSidebar.vue index 886aa265ce67c..4296c028b2b3b 100644 --- a/packages/editor-ui/src/components/MainSidebar.vue +++ b/packages/editor-ui/src/components/MainSidebar.vue @@ -647,7 +647,7 @@ export default mixins( height: 35px; line-height: 35px; color: $--custom-dialog-text-color; - --menu-item-hover-fill: var(--color-primary-tint-3); + --menu-item-hover-fill: var(--color-background-base); .item-title { position: absolute; @@ -667,7 +667,7 @@ export default mixins( .el-menu { border: none; font-size: 14px; - --menu-item-hover-fill: var(--color-primary-tint-3); + --menu-item-hover-fill: var(--color-background-base); .el-menu--collapse { width: 75px; diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index 6c02b149f4539..ce5a4b0397018 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -79,7 +79,7 @@
mode.name === 'list'); + this.selectedMode = listMode ? listMode.name : this.parameter.modes[0].name; + } }, computed: { node (): INodeUi | null { diff --git a/packages/editor-ui/src/plugins/icons.ts b/packages/editor-ui/src/plugins/icons.ts index 428dafa1fa0e6..4c0a3a6385b29 100644 --- a/packages/editor-ui/src/plugins/icons.ts +++ b/packages/editor-ui/src/plugins/icons.ts @@ -37,6 +37,7 @@ import { faEye, faExclamationTriangle, faExpand, + faExpandAlt, faExternalLinkAlt, faExchangeAlt, faFile, @@ -149,6 +150,7 @@ addIcon(faEnvelope); addIcon(faEye); addIcon(faExclamationTriangle); addIcon(faExpand); +addIcon(faExpandAlt); addIcon(faExternalLinkAlt); addIcon(faExchangeAlt); addIcon(faFile); From 397ef4f4b81436f19070be0b45b91f0c249fd0d3 Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Tue, 2 Aug 2022 12:10:35 +0200 Subject: [PATCH 04/24] =?UTF-8?q?=F0=9F=94=A8=20Moving=20resource=20locato?= =?UTF-8?q?r=20component=20to=20`ParameterInput`=20from=20`ParameterInputF?= =?UTF-8?q?ull?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/ParameterInput.vue | 572 +++++++++++------- .../src/components/ParameterInputFull.vue | 142 +---- 2 files changed, 370 insertions(+), 344 deletions(-) diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index ce5a4b0397018..4602e5218bbbc 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -1,262 +1,302 @@ @@ -270,11 +310,11 @@ import { import { NodeHelpers, NodeParameterValue, - IHttpRequestOptions, ILoadOptions, INodeParameters, INodePropertyOptions, Workflow, + INodePropertyMode, } from 'n8n-workflow'; import CodeEdit from '@/components/CodeEdit.vue'; @@ -284,6 +324,7 @@ import NodeCredentials from '@/components/NodeCredentials.vue'; import ScopesNotice from '@/components/ScopesNotice.vue'; import ParameterOptions from '@/components/ParameterOptions.vue'; import ParameterIssues from '@/components/ParameterIssues.vue'; +import DraggableTarget from '@/components/DraggableTarget.vue'; // @ts-ignore import PrismEditor from 'vue-prism-editor'; import TextEdit from '@/components/TextEdit.vue'; @@ -296,7 +337,7 @@ import mixins from 'vue-typed-mixins'; import { CUSTOM_API_CALL_KEY } from '@/constants'; import { mapGetters } from 'vuex'; import { hasExpressionMapping } from './helpers'; -import { validateResourceLocatorParameter } from './ResourceLocator/helpers'; +import { getParameterModeLabel, validateResourceLocatorParameter } from './ResourceLocator/helpers'; export default mixins( externalHooks, @@ -308,6 +349,7 @@ export default mixins( name: 'ParameterInput', components: { CodeEdit, + DraggableTarget, ExpressionEdit, NodeCredentials, CredentialsSelect, @@ -331,7 +373,6 @@ export default mixins( 'activeDrop', 'droppable', 'forceShowExpression', - 'currentMode', ], data () { return { @@ -375,6 +416,7 @@ export default mixins( }, ], }, + selectedMode: '', }; }, watch: { @@ -563,7 +605,7 @@ export default mixins( const issue = this.$locale.baseText('parameterInput.selectACredentialTypeFromTheDropdown'); issues.parameters[this.parameter.name] = [issue]; - } else if (this.parameter.type === 'resourceLocator' && this.displayValue !== null) { + } else if (this.parameter.type === 'resourceLocator' && this.displayValue !== null && this.displayValue !== undefined) { // Perform front-end validation of the resource locator value issues.parameters = issues.parameters || {}; const validationErrors: string[] = validateResourceLocatorParameter(this.displayValue.toString(), this.currentMode); @@ -699,6 +741,18 @@ export default mixins( inputPlaceholder (): string { return this.currentMode.placeholder ? this.currentMode.placeholder : ''; }, + isResourceLocatorParameter (): boolean { + return this.parameter.type === 'resourceLocator'; + }, + infoText (): string { + return this.currentMode.hint ? this.currentMode.hint : this.parameter.description || ''; + }, + currentMode (): INodePropertyMode { + return this.findModeByName(this.selectedMode) || {} as INodePropertyMode; + }, + hasMultipleModes (): boolean { + return this.parameter.modes && this.parameter.modes.length > 1; + }, }, methods: { credentialSelected (updateInformation: INodeUpdatePropertiesInformation) { @@ -953,6 +1007,21 @@ export default mixins( }); } }, + onModeSelected (value: string): void { + this.selectedMode = value; + }, + findModeByName (name: string): INodePropertyMode | null { + if (this.parameter.modes) { + return this.parameter.modes.find((mode: INodePropertyMode) => mode.name === name) || null; + } + return null; + }, + getModeLabel (name: string): string | null { + return getParameterModeLabel(name); + }, + onDrop(data: string) { + this.$emit('drop', data); + }, }, mounted () { this.$on('optionSelected', this.optionSelected); @@ -1003,6 +1072,12 @@ export default mixins( } } + if (this.parameter.modes) { + // List mode is selected by default if it's available + const listMode = this.parameter.modes.find((mode : INodePropertyMode) => mode.name === 'list'); + this.selectedMode = listMode ? listMode.name : this.parameter.modes[0].name; + } + this.$externalHooks().run('parameterInput.mount', { parameter: this.parameter, inputFieldRef: this.$refs['inputField'] }); }, }); @@ -1120,3 +1195,40 @@ export default mixins( } + + diff --git a/packages/editor-ui/src/components/ParameterInputFull.vue b/packages/editor-ui/src/components/ParameterInputFull.vue index 7097fdec578cf..2c898f191c636 100644 --- a/packages/editor-ui/src/components/ParameterInputFull.vue +++ b/packages/editor-ui/src/components/ParameterInputFull.vue @@ -18,57 +18,33 @@ /> - {{ infoText }} @@ -79,7 +55,6 @@ import { INodeUi, IUpdateInformation, } from '@/Interface'; -import { INodePropertyMode } from 'n8n-workflow'; import ParameterInput from '@/components/ParameterInput.vue'; import InputHint from './ParameterInputHint.vue'; @@ -89,7 +64,6 @@ import mixins from 'vue-typed-mixins'; import { showMessage } from './mixins/showMessage'; import { LOCAL_STORAGE_MAPPING_FLAG } from '@/constants'; import { hasExpressionMapping } from './helpers'; -import { getParameterModeLabel } from './ResourceLocator/helpers'; export default mixins( showMessage, @@ -107,7 +81,6 @@ export default mixins( focused: false, menuExpanded: false, forceShowExpression: false, - selectedMode: '', }; }, props: [ @@ -118,28 +91,15 @@ export default mixins( 'value', 'hideLabel', ], - mounted() { - if (this.parameter.modes) { - // List mode is selected by default if it's available - const listMode = this.parameter.modes.find((mode : INodePropertyMode) => mode.name === 'list'); - this.selectedMode = listMode ? listMode.name : this.parameter.modes[0].name; - } - }, computed: { node (): INodeUi | null { return this.$store.getters.activeNode; }, - isResourceLocatorParameter (): boolean { - return this.parameter.type === 'resourceLocator'; - }, - infoText (): string { - return this.currentMode.hint ? this.currentMode.hint : this.parameter.description || ''; + isResourceLocator (): boolean { + return this.parameter.type === 'resourceLocator'; }, - currentMode (): INodePropertyMode { - return this.findModeByName(this.selectedMode) || {} as INodePropertyMode; - }, - hasMultipleModes (): boolean { - return this.parameter.modes && this.parameter.modes.length > 1; + isDropDisabled (): boolean { + return this.parameter.noDataExpression || this.isReadOnly || this.isResourceLocator; }, }, methods: { @@ -209,18 +169,6 @@ export default mixins( this.forceShowExpression = false; }, 200); }, - onModeSelected (value: string): void { - this.selectedMode = value; - }, - findModeByName (name: string): INodePropertyMode | null { - if (this.parameter.modes) { - return this.parameter.modes.find((mode: INodePropertyMode) => mode.name === name) || null; - } - return null; - }, - getModeLabel (name: string): string | null { - return getParameterModeLabel(name); - }, }, }); @@ -229,38 +177,4 @@ export default mixins( .hint { margin-top: var(--spacing-4xs); } - - .resource-locator { - display: flex; - - .input-container { - width: 100%; - input { - border-radius: 0 var(--border-radius-base) var(--border-radius-base) 0; - } - } - - &.multiple-modes { - .input-container { - flex-basis: calc(100% - 100px); - flex-grow: 1; - } - } - - } - - .mode-selector { - flex-basis: 100px; - - input { - border-radius: var(--border-radius-base) 0 0 var(--border-radius-base); - border-right: none; - overflow: hidden; - text-overflow: ellipsis; - - &:focus { - border-right: var(--color-secondary) var(--border-style-base) var(--border-width-base); - } - } - } From 1bf28c0ddaf2bd74a38d034e3a8c48e1aa046e42 Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Wed, 3 Aug 2022 16:06:13 +0200 Subject: [PATCH 05/24] =?UTF-8?q?=F0=9F=94=A8=20Moving=20`ResourceLocator`?= =?UTF-8?q?=20to=20a=20separate=20Vue=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/ParameterInput.vue | 599 ++++++++---------- .../ResourceLocator/ResourceLocator.vue | 262 ++++++++ 2 files changed, 509 insertions(+), 352 deletions(-) create mode 100644 packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index 6d23d07356bac..59eb06220054e 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -1,302 +1,279 @@ @@ -314,7 +291,6 @@ import { INodeParameters, INodePropertyOptions, Workflow, - INodePropertyMode, } from 'n8n-workflow'; import CodeEdit from '@/components/CodeEdit.vue'; @@ -324,7 +300,7 @@ import NodeCredentials from '@/components/NodeCredentials.vue'; import ScopesNotice from '@/components/ScopesNotice.vue'; import ParameterOptions from '@/components/ParameterOptions.vue'; import ParameterIssues from '@/components/ParameterIssues.vue'; -import DraggableTarget from '@/components/DraggableTarget.vue'; +import ResourceLocator from '@/components/ResourceLocator/ResourceLocator.vue'; // @ts-ignore import PrismEditor from 'vue-prism-editor'; import TextEdit from '@/components/TextEdit.vue'; @@ -337,7 +313,6 @@ import mixins from 'vue-typed-mixins'; import { CUSTOM_API_CALL_KEY } from '@/constants'; import { mapGetters } from 'vuex'; import { hasExpressionMapping } from './helpers'; -import { getParameterModeLabel, validateResourceLocatorParameter } from './ResourceLocator/helpers'; export default mixins( externalHooks, @@ -349,7 +324,6 @@ export default mixins( name: 'ParameterInput', components: { CodeEdit, - DraggableTarget, ExpressionEdit, NodeCredentials, CredentialsSelect, @@ -357,6 +331,7 @@ export default mixins( ScopesNotice, ParameterOptions, ParameterIssues, + ResourceLocator, TextEdit, }, props: [ @@ -416,7 +391,6 @@ export default mixins( }, ], }, - selectedMode: '', }; }, watch: { @@ -605,13 +579,6 @@ export default mixins( const issue = this.$locale.baseText('parameterInput.selectACredentialTypeFromTheDropdown'); issues.parameters[this.parameter.name] = [issue]; - } else if (this.parameter.type === 'resourceLocator' && this.displayValue !== null && this.displayValue !== undefined) { - // Perform front-end validation of the resource locator value - issues.parameters = issues.parameters || {}; - const validationErrors: string[] = validateResourceLocatorParameter(this.displayValue.toString(), this.currentMode); - for (const error of validationErrors) { - issues.parameters[this.parameter.name] = [error]; - } } else if ( ['options', 'multiOptions'].includes(this.parameter.type) && this.remoteParameterOptionsLoading === false && @@ -738,21 +705,9 @@ export default mixins( workflow (): Workflow { return this.getWorkflow(); }, - inputPlaceholder (): string { - return this.currentMode.placeholder ? this.currentMode.placeholder : ''; - }, isResourceLocatorParameter (): boolean { return this.parameter.type === 'resourceLocator'; }, - infoText (): string { - return this.currentMode.hint ? this.currentMode.hint : this.parameter.description || ''; - }, - currentMode (): INodePropertyMode { - return this.findModeByName(this.selectedMode) || {} as INodePropertyMode; - }, - hasMultipleModes (): boolean { - return this.parameter.modes && this.parameter.modes.length > 1; - }, }, methods: { credentialSelected (updateInformation: INodeUpdatePropertiesInformation) { @@ -775,9 +730,7 @@ export default mixins( getPlaceholder(): string { return this.isForCredential ? this.$locale.credText().placeholder(this.parameter) - : this.inputPlaceholder - ? this.inputPlaceholder - : this.$locale.nodeText().placeholder(this.parameter, this.path); + : this.$locale.nodeText().placeholder(this.parameter, this.path); }, getOptionsOptionDisplayName(option: { value: string; name: string }): string { return this.isForCredential @@ -913,7 +866,7 @@ export default mixins( // Set focus on field setTimeout(() => { // @ts-ignore - if (this.$refs.inputField.$el) { + if (this.$refs.inputField && this.$refs.inputField.$el) { // @ts-ignore (this.$refs.inputField.$el.querySelector(this.getStringInputType === 'textarea' ? 'textarea' : 'input') as HTMLInputElement).focus(); } @@ -1020,21 +973,6 @@ export default mixins( }); } }, - onModeSelected (value: string): void { - this.selectedMode = value; - }, - findModeByName (name: string): INodePropertyMode | null { - if (this.parameter.modes) { - return this.parameter.modes.find((mode: INodePropertyMode) => mode.name === name) || null; - } - return null; - }, - getModeLabel (name: string): string | null { - return getParameterModeLabel(name); - }, - onDrop(data: string) { - this.$emit('drop', data); - }, }, mounted () { this.$on('optionSelected', this.optionSelected); @@ -1085,12 +1023,6 @@ export default mixins( } } - if (this.parameter.modes) { - // List mode is selected by default if it's available - const listMode = this.parameter.modes.find((mode : INodePropertyMode) => mode.name === 'list'); - this.selectedMode = listMode ? listMode.name : this.parameter.modes[0].name; - } - this.$externalHooks().run('parameterInput.mount', { parameter: this.parameter, inputFieldRef: this.$refs['inputField'] }); }, }); @@ -1208,40 +1140,3 @@ export default mixins( } - - diff --git a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue new file mode 100644 index 0000000000000..0f3f47a537a26 --- /dev/null +++ b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue @@ -0,0 +1,262 @@ + + + + + From f8d71e07968c6afeb4442507803a4ea6d0acc7e7 Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Thu, 4 Aug 2022 12:02:36 +0200 Subject: [PATCH 06/24] =?UTF-8?q?=F0=9F=94=A8=20Implementing=20expression?= =?UTF-8?q?=20and=20drag'n'drop=20support=20in=20ResourceLocator`=20compon?= =?UTF-8?q?ent?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/ParameterInput.vue | 12 ++-- .../ResourceLocator/ResourceLocator.vue | 62 +++++++++++++------ 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index 59eb06220054e..7c3caccd8564e 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -18,18 +18,18 @@ v-if="isResourceLocatorParameter" ref="resourceLocator" v-bind="$props" - v-model="tempValue" - :stringInputType="getStringInputType" :rows="getArgument('rows')" :displayValue="displayValue" :displayTitle="displayTitle" - :issues="getIssues" :parameterInputClasses="parameterInputClasses" + :expressionDisplayValue="expressionDisplayValue" + :isValueExpression="isValueExpression" + :issues="getIssues" @textInputChange="onTextInputChange" @change="valueChanged" @focus="setFocus" @blur="onBlur" - @editIconClick="displayEditDialog()" + @drop="onDrop" > -
+ From 12b3857a779a3751c0f237b985228fab6c035dbe Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Thu, 4 Aug 2022 14:09:12 +0200 Subject: [PATCH 08/24] =?UTF-8?q?=E2=9C=A8=20Implemented=20resource=20loca?= =?UTF-8?q?tor=20selected=20mode=20persistance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/editor-ui/src/Interface.ts | 1 + .../ResourceLocator/ResourceLocator.vue | 27 ++++++++++++------- packages/editor-ui/src/store.ts | 22 +++++++++++++++ 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/packages/editor-ui/src/Interface.ts b/packages/editor-ui/src/Interface.ts index 2f929f81de694..96b17dde30584 100644 --- a/packages/editor-ui/src/Interface.ts +++ b/packages/editor-ui/src/Interface.ts @@ -148,6 +148,7 @@ export interface INodeUi extends INode { issues?: INodeIssues; name: string; pinData?: IDataObject; + parameterModes?: { [paramName: string]: string }; } export interface INodeTypesMaxCount { diff --git a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue index 1aaf862803454..efdcc141e5bae 100644 --- a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue +++ b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue @@ -90,6 +90,8 @@ import DraggableTarget from '@/components/DraggableTarget.vue'; import ExpressionEdit from '@/components/ExpressionEdit.vue'; import ParameterIssues from '@/components/ParameterIssues.vue'; import { PropType } from 'vue'; +import { INodeUi } from '@/Interface'; +import { mapGetters } from 'vuex'; export default mixins().extend({ name: 'ResourceLocator', @@ -107,6 +109,12 @@ export default mixins().extend({ type: String, default: '', }, + node: { + type: Object as () => INodeUi, + default() { + return this.$store.getters.activeNode; + }, + }, inputSize: { type: String, default: 'small', @@ -114,10 +122,6 @@ export default mixins().extend({ return ['mini', 'small', 'medium', 'large', 'xlarge'].includes(size); }, }, - eventSource: { - type: String, - default: 'ndv', - }, parameterIssues: { type: Array as PropType, default () { @@ -205,7 +209,6 @@ export default mixins().extend({ this.validate(); }, hasMultipleModes (newValue: boolean) { - // TODO: Only do this if there is no mode selected... this.setDefaultMode(); }, value (newValue: string) { @@ -213,14 +216,15 @@ export default mixins().extend({ }, }, mounted () { + const storedMode = this.$store.getters.getNodeParameterLocatorMode(this.node.name, this.parameter.name); + this.selectedMode = storedMode; this.tempValue = this.displayValue as string; - if (this.selectedMode === '') { - this.setDefaultMode(); - } + + this.setDefaultMode(); }, methods: { setDefaultMode (): void { - if (this.parameter.modes) { + if (this.parameter.modes && this.selectedMode === '') { // List mode is selected by default if it's available const listMode = this.parameter.modes.find((mode : INodePropertyMode) => mode.name === 'list'); this.selectedMode = listMode ? listMode.name : this.parameter.modes[0].name; @@ -249,6 +253,11 @@ export default mixins().extend({ }, onModeSelected (value: string): void { this.validate(); + this.$store.commit('setNodeParameterMode', { + nodeName: this.node.name, + paramName: this.parameter.name, + mode: this.selectedMode, + }); }, onExpressionValueChanged (latestValue: string): void { this.tempValue = latestValue; diff --git a/packages/editor-ui/src/store.ts b/packages/editor-ui/src/store.ts index ff2f9f30ce8c7..3d2b36ffdf9e5 100644 --- a/packages/editor-ui/src/store.ts +++ b/packages/editor-ui/src/store.ts @@ -533,6 +533,15 @@ export const store = new Vuex.Store({ Vue.set(state.nodeMetadata[node.name], 'parametersLastUpdatedAt', Date.now()); }, + // Selected resource locator modes for each parameter + setNodeParameterMode(state, payload: { nodeName: string, paramName: string, mode: string }) { + const node = state.workflow.nodes.find(node => { + return node.name === payload.nodeName; + }); + if (node) { + Vue.set(node, 'parameterModes', { [payload.paramName] : payload.mode }); + } + }, // Node-Index addToNodeIndex(state, nodeName: string) { state.nodeIndex.push(nodeName); @@ -982,5 +991,18 @@ export const store = new Vuex.Store({ sidebarMenuItems: (state): IMenuItem[] => { return state.sidebarMenuItems; }, + + getNodeParameterLocatorMode: (state, getters) => (nodeName: string, paramName: string): string => { + console.log(`GETTER : ${nodeName} / ${paramName}`); + + const node: INodeUi = getters.nodesByName[nodeName]; + + console.log(node); + + if (node && node.parameterModes) { + return node.parameterModes[paramName] || ''; + } + return ''; + }, }, }); From 80b4e0d5c77d72fa95dcd96278c7cb702a4762b4 Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Thu, 4 Aug 2022 14:19:20 +0200 Subject: [PATCH 09/24] =?UTF-8?q?=F0=9F=92=84=20Minor=20refactoring=20and?= =?UTF-8?q?=20fixes=20in=20`ResourceLocator`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/ResourceLocator/ResourceLocator.vue | 4 ++-- packages/editor-ui/src/store.ts | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue index efdcc141e5bae..42f8bd4cff277 100644 --- a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue +++ b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue @@ -1,6 +1,7 @@ @@ -181,6 +173,19 @@ export default mixins().extend({ }; }, computed: { + sortedModes (): INodePropertyMode[] { + // Display modes in this order regardless of how they are set in node definition + const priorityQueue: string[] = ['list', 'id', 'url', 'custom']; + const sorted: INodePropertyMode[] = []; + + for (const modeName of priorityQueue) { + const mode = this.findModeByName(modeName); + if (mode) { + sorted.push(mode); + } + } + return sorted; + }, inputPlaceholder (): string { return this.currentMode.placeholder ? this.currentMode.placeholder : ''; }, @@ -267,9 +272,6 @@ export default mixins().extend({ onDrop(data: string) { this.$emit('drop', data); }, - onEditIconClick (): void { - this.$emit('editIconClick'); - }, onBlur (): void { this.$emit('blur'); }, @@ -282,17 +284,17 @@ export default mixins().extend({ From d4ce7de993c2803934de027cf5e5ee75b7dbac45 Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Fri, 5 Aug 2022 14:18:15 +0200 Subject: [PATCH 13/24] =?UTF-8?q?=F0=9F=90=9B=20Fixing=20resource=20locato?= =?UTF-8?q?r=20mode=20parameters=20handling=20when=20loading=20node=20para?= =?UTF-8?q?meter=20values=20on=20front-end?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/editor-ui/src/components/NodeSettings.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/editor-ui/src/components/NodeSettings.vue b/packages/editor-ui/src/components/NodeSettings.vue index 208e5f989d95f..bfebb6286c3d2 100644 --- a/packages/editor-ui/src/components/NodeSettings.vue +++ b/packages/editor-ui/src/components/NodeSettings.vue @@ -491,7 +491,8 @@ export default mixins( nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, nodeParameters as INodeParameters, true, false, node); for (const key of Object.keys(nodeParameters as object)) { - if (nodeParameters && nodeParameters[key] !== null && nodeParameters[key] !== undefined) { + // Skip non-exiting keys and resource loader '.mode' parameters + if (nodeParameters && nodeParameters[key] !== null && nodeParameters[key] !== undefined && !key.endsWith('.mode')) { this.setValue(`parameters.${key}`, nodeParameters[key] as string); } } From 2a5292bbd60a90949167e2d63d8435479fa198bb Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Fri, 5 Aug 2022 15:01:32 +0200 Subject: [PATCH 14/24] =?UTF-8?q?=F0=9F=92=84=20Removing=20leftover=20unus?= =?UTF-8?q?ed=20CSS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../editor-ui/src/components/ResourceLocator/ResourceLocator.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue index e8e9185d3137f..71406c0036969 100644 --- a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue +++ b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue @@ -293,7 +293,6 @@ export default mixins().extend({ overflow: hidden; &:focus { - // border-right: var(--color-secondary) var(--border-style-base) var(--border-width-base); border-right: none; } } From 96a725f395825a2d23fac7986330ea4ba08dcc18 Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Fri, 5 Aug 2022 22:04:41 +0200 Subject: [PATCH 15/24] =?UTF-8?q?=E2=9A=A1=20Updating=20interfaces=20to=20?= =?UTF-8?q?support=20resource=20locator=20value=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/NodeExecuteFunctions.ts | 46 ++++++++- packages/workflow/src/Expression.ts | 44 +++++++- packages/workflow/src/Interfaces.ts | 113 ++++++++++++++++++--- packages/workflow/src/RoutingNode.ts | 18 +++- packages/workflow/src/Workflow.ts | 19 +++- packages/workflow/src/WorkflowDataProxy.ts | 5 +- 6 files changed, 218 insertions(+), 27 deletions(-) diff --git a/packages/core/src/NodeExecuteFunctions.ts b/packages/core/src/NodeExecuteFunctions.ts index c1b4db146f1fe..5e6c11e4b1907 100644 --- a/packages/core/src/NodeExecuteFunctions.ts +++ b/packages/core/src/NodeExecuteFunctions.ts @@ -59,6 +59,7 @@ import { LoggerProxy as Logger, IExecuteData, OAuth2GrantType, + INodeParameterResourceLocator, } from 'n8n-workflow'; import { Agent } from 'https'; @@ -1622,8 +1623,20 @@ export function getNode(node: INode): INode { * INFO: Currently only converts Luxon Dates as we know for sure it will not be breaking */ function cleanupParameterData( - inputData: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], -): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] { + inputData: + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[], +): + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] { if (inputData === null || inputData === undefined) { return inputData; } @@ -1640,7 +1653,9 @@ function cleanupParameterData( if (typeof inputData === 'object') { Object.keys(inputData).forEach((key) => { - inputData[key] = cleanupParameterData(inputData[key]); + inputData[key as keyof typeof inputData] = cleanupParameterData( + inputData[key as keyof typeof inputData], + ); }); } @@ -1674,7 +1689,14 @@ export function getNodeParameter( additionalKeys: IWorkflowDataProxyAdditionalKeys, executeData?: IExecuteData, fallbackValue?: any, -): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | object { +): + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] + | object { const nodeType = workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion); if (nodeType === undefined) { throw new Error(`Node type "${node.type}" is not known so can not return paramter value!`); @@ -1885,6 +1907,8 @@ export function getExecutePollFunctions( | INodeParameters | NodeParameterValue[] | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] | object => { const runExecutionData: IRunExecutionData | null = null; const itemIndex = 0; @@ -2040,6 +2064,8 @@ export function getExecuteTriggerFunctions( | INodeParameters | NodeParameterValue[] | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] | object => { const runExecutionData: IRunExecutionData | null = null; const itemIndex = 0; @@ -2256,6 +2282,8 @@ export function getExecuteFunctions( | INodeParameters | NodeParameterValue[] | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] | object => { return getNodeParameter( workflow, @@ -2530,6 +2558,8 @@ export function getExecuteSingleFunctions( | INodeParameters | NodeParameterValue[] | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] | object => { return getNodeParameter( workflow, @@ -2681,6 +2711,8 @@ export function getLoadOptionsFunctions( | INodeParameters | NodeParameterValue[] | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] | object | undefined => { const nodeParameters = additionalData.currentNodeParameters; @@ -2705,6 +2737,8 @@ export function getLoadOptionsFunctions( | INodeParameters | NodeParameterValue[] | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] | object => { const runExecutionData: IRunExecutionData | null = null; const itemIndex = 0; @@ -2836,6 +2870,8 @@ export function getExecuteHookFunctions( | INodeParameters | NodeParameterValue[] | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] | object => { const runExecutionData: IRunExecutionData | null = null; const itemIndex = 0; @@ -2999,6 +3035,8 @@ export function getExecuteWebhookFunctions( | INodeParameters | NodeParameterValue[] | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] | object => { const runExecutionData: IRunExecutionData | null = null; const itemIndex = 0; diff --git a/packages/workflow/src/Expression.ts b/packages/workflow/src/Expression.ts index 8d3920dc32ccc..41f566e36d16f 100644 --- a/packages/workflow/src/Expression.ts +++ b/packages/workflow/src/Expression.ts @@ -9,6 +9,7 @@ import { IExecuteData, INode, INodeExecutionData, + INodeParameterResourceLocator, INodeParameters, IRunExecutionData, IWorkflowDataProxyAdditionalKeys, @@ -350,9 +351,18 @@ export class Expression { | INodeParameters | NodeParameterValue[] | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] | undefined = undefined, selfData = {}, - ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined { + ): + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] + | undefined { if (parameterValue === undefined) { // Value is not set so return the default return defaultValue; @@ -417,7 +427,13 @@ export class Expression { * @memberof Workflow */ getParameterValue( - parameterValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], + parameterValue: + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[], runExecutionData: IRunExecutionData | null, runIndex: number, itemIndex: number, @@ -429,17 +445,35 @@ export class Expression { executeData?: IExecuteData, returnObjectAsString = false, selfData = {}, - ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] { + ): + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] { // Helper function which returns true when the parameter is a complex one or array const isComplexParameter = ( - value: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], + value: + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[], ) => { return typeof value === 'object'; }; // Helper function which resolves a parameter value depending on if it is simply or not const resolveParameterValue = ( - value: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], + value: + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[], siblingParameters: INodeParameters, ) => { if (isComplexParameter(value)) { diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 07d273039372f..2bbcd9a125aec 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -540,7 +540,13 @@ export interface IExecuteFunctions { evaluateExpression( expression: string, itemIndex: number, - ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[]; + ): + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[]; executeWorkflow( workflowInfo: IExecuteWorkflowInfo, inputData?: INodeExecutionData[], @@ -559,7 +565,14 @@ export interface IExecuteFunctions { parameterName: string, itemIndex: number, fallbackValue?: any, - ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | object; + ): + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] + | object; getWorkflowDataProxy(itemIndex: number): IWorkflowDataProxyData; getWorkflowStaticData(type: string): IDataObject; getRestApiUrl(): string; @@ -592,7 +605,13 @@ export interface IExecuteSingleFunctions { evaluateExpression( expression: string, itemIndex: number | undefined, - ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[]; + ): + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[]; getContext(type: string): IContextObject; getCredentials(type: string): Promise; getInputData(inputIndex?: number, inputName?: string): INodeExecutionData; @@ -602,7 +621,14 @@ export interface IExecuteSingleFunctions { getNodeParameter( parameterName: string, fallbackValue?: any, - ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | object; + ): + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] + | object; getRestApiUrl(): string; getTimezone(): string; getExecuteData(): IExecuteData; @@ -651,7 +677,14 @@ export interface ILoadOptionsFunctions { getNodeParameter( parameterName: string, fallbackValue?: any, - ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | object; + ): + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] + | object; getCurrentNodeParameter( parameterName: string, ): @@ -659,6 +692,8 @@ export interface ILoadOptionsFunctions { | INodeParameters | NodeParameterValue[] | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] | object | undefined; getCurrentNodeParameters(): INodeParameters | undefined; @@ -695,7 +730,14 @@ export interface IHookFunctions { getNodeParameter( parameterName: string, fallbackValue?: any, - ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | object; + ): + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] + | object; getTimezone(): string; getWebhookDescription(name: string): IWebhookDescription | undefined; getWebhookName(): string; @@ -724,7 +766,14 @@ export interface IPollFunctions { getNodeParameter( parameterName: string, fallbackValue?: any, - ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | object; + ): + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] + | object; getRestApiUrl(): string; getTimezone(): string; getWorkflow(): IWorkflowMetadata; @@ -757,7 +806,14 @@ export interface ITriggerFunctions { getNodeParameter( parameterName: string, fallbackValue?: any, - ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | object; + ): + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] + | object; getRestApiUrl(): string; getTimezone(): string; getWorkflow(): IWorkflowMetadata; @@ -785,7 +841,14 @@ export interface IWebhookFunctions { getNodeParameter( parameterName: string, fallbackValue?: any, - ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | object; + ): + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] + | object; getNodeWebhookUrl: (name: string) => string | undefined; getParamsData(): object; getQueryData(): object; @@ -889,14 +952,34 @@ export interface INodeExecuteFunctions { getExecuteWebhookFunctions: IGetExecuteWebhookFunctions; } -// The values a node property can have export type NodeParameterValue = string | number | boolean | undefined | null; +export type ResourceLocatorModes = 'id' | 'url'; + +export interface INodeParameterResourceLocator { + mode: ResourceLocatorModes; + value: NodeParameterValue; +} + export interface INodeParameters { // TODO: Later also has to be possible to add multiple ones with the name name. So array has to be possible - [key: string]: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[]; + [key: string]: + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[]; } +// // The values a node property can have +// export type NodeParameterValue = string | number | boolean | undefined | null; + +// export interface INodeParameters { +// // TODO: Later also has to be possible to add multiple ones with the name name. So array has to be possible +// [key: string]: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[]; +// } + export type NodePropertyTypes = | 'boolean' | 'collection' @@ -959,7 +1042,13 @@ export interface INodeProperties { name: string; type: NodePropertyTypes; typeOptions?: INodePropertyTypeOptions; - default: NodeParameterValue | INodeParameters | INodeParameters[] | NodeParameterValue[]; + default: + | NodeParameterValue + | INodeParameters + | INodeParameters[] + | NodeParameterValue[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[]; description?: string; hint?: string; displayOptions?: IDisplayOptions; diff --git a/packages/workflow/src/RoutingNode.ts b/packages/workflow/src/RoutingNode.ts index c52bfd2d8444e..02f86c1362d7c 100644 --- a/packages/workflow/src/RoutingNode.ts +++ b/packages/workflow/src/RoutingNode.ts @@ -43,6 +43,7 @@ import { IExecuteData, IExecuteSingleFunctions, IN8nRequestOperations, + INodeParameterResourceLocator, INodeProperties, INodePropertyCollection, PostReceiveAction, @@ -580,13 +581,26 @@ export class RoutingNode { } getParameterValue( - parameterValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], + parameterValue: + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[], itemIndex: number, runIndex: number, executeData: IExecuteData, additionalKeys?: IWorkflowDataProxyAdditionalKeys, returnObjectAsString = false, - ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | string { + ): + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] + | string { if ( typeof parameterValue === 'object' || (typeof parameterValue === 'string' && parameterValue.charAt(0) === '=') diff --git a/packages/workflow/src/Workflow.ts b/packages/workflow/src/Workflow.ts index d5f56a623b422..1126186f18567 100644 --- a/packages/workflow/src/Workflow.ts +++ b/packages/workflow/src/Workflow.ts @@ -56,6 +56,7 @@ import { IObservableObject, IRun, IRunNodeResponse, + INodeParameterResourceLocator, } from './Interfaces'; function dedupe(arr: T[]): T[] { @@ -436,10 +437,22 @@ export class Workflow { * @memberof Workflow */ renameNodeInExpressions( - parameterValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], + parameterValue: + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[], currentName: string, newName: string, - ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] { + ): + | NodeParameterValue + | INodeParameters + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[] { if (typeof parameterValue !== 'object') { // Reached the actual value if (typeof parameterValue === 'string' && parameterValue.charAt(0) === '=') { @@ -480,7 +493,7 @@ export class Workflow { for (const parameterName of Object.keys(parameterValue || {})) { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access returnData[parameterName] = this.renameNodeInExpressions( - parameterValue![parameterName], + parameterValue![parameterName as keyof typeof parameterValue], currentName, newName, ); diff --git a/packages/workflow/src/WorkflowDataProxy.ts b/packages/workflow/src/WorkflowDataProxy.ts index a1be9771d1a0e..55ddbc0340fd2 100644 --- a/packages/workflow/src/WorkflowDataProxy.ts +++ b/packages/workflow/src/WorkflowDataProxy.ts @@ -16,6 +16,7 @@ import { IDataObject, IExecuteData, INodeExecutionData, + INodeParameterResourceLocator, INodeParameters, IPairedItemData, IRunExecutionData, @@ -182,7 +183,9 @@ export class WorkflowDataProxy { | INodeParameters | NodeParameterValue | NodeParameterValue[] - | INodeParameters[]; + | INodeParameters[] + | INodeParameterResourceLocator + | INodeParameterResourceLocator[]; if (name[0] === '&') { const key = name.slice(1); if (!that.siblingParameters.hasOwnProperty(key)) { From 4c221bb4ce68a85fbda01078d38f4ccaac88f12a Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Tue, 9 Aug 2022 16:45:26 +0200 Subject: [PATCH 16/24] =?UTF-8?q?=E2=9A=A1=20Updating=20`ResourceLocator`?= =?UTF-8?q?=20component=20to=20work=20with=20object=20parameter=20values?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/ParameterInput.vue | 41 +++++++++++++++---- .../src/components/ParameterInputFull.vue | 2 +- .../src/components/ParameterOptions.vue | 3 ++ .../ResourceLocator/ResourceLocator.vue | 22 ++++------ packages/workflow/src/Interfaces.ts | 8 ---- 5 files changed, 44 insertions(+), 32 deletions(-) diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index a89f8c8fdaf22..862db425ec365 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -2,7 +2,7 @@
INodeUi, default() { @@ -222,10 +225,8 @@ export default mixins().extend({ }, }, mounted () { - const storedMode = this.$store.getters.getNodeParameterLocatorMode(this.node.name, this.parameter.name); - this.selectedMode = storedMode; + this.selectedMode = this.mode; this.tempValue = this.displayValue as string; - this.setDefaultMode(); }, methods: { @@ -251,23 +252,16 @@ export default mixins().extend({ getModeLabel (name: string): string | null { return getParameterModeLabel(name); }, - onInput (value: string): void { - this.$emit('textInputChange', value); - }, onInputChange (value: string): void { - this.$emit('change', value); + this.$emit('valueChanged', { value, mode: this.selectedMode }); }, onModeSelected (value: string): void { this.validate(); - this.$store.commit('setNodeParameterMode', { - nodeName: this.node.name, - paramName: this.parameter.name, - mode: this.selectedMode, - }); + this.$emit('modeChanged', { mode: value, value: this.value }); }, onExpressionValueChanged (latestValue: string): void { this.tempValue = latestValue; - this.$emit('valueChanged', latestValue); + this.$emit('valueChanged', { value: latestValue, mode: this.selectedMode }); }, onDrop(data: string) { this.$emit('drop', data); diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 2bbcd9a125aec..785e4bac9bd34 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -972,14 +972,6 @@ export interface INodeParameters { | INodeParameterResourceLocator[]; } -// // The values a node property can have -// export type NodeParameterValue = string | number | boolean | undefined | null; - -// export interface INodeParameters { -// // TODO: Later also has to be possible to add multiple ones with the name name. So array has to be possible -// [key: string]: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[]; -// } - export type NodePropertyTypes = | 'boolean' | 'collection' From 2c3698fe52b1bb3da458c1c90ab21be269e182b0 Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Wed, 10 Aug 2022 12:07:56 +0200 Subject: [PATCH 17/24] =?UTF-8?q?=F0=9F=94=A8=20Cleaning=20up=20`ResourceL?= =?UTF-8?q?ocator`=20and=20related=20components=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/ParameterInput.vue | 52 +++++-------------- .../src/components/ParameterInputFull.vue | 14 +++++ .../src/components/ParameterOptions.vue | 13 +---- .../ResourceLocator/ResourceLocator.vue | 16 ++---- 4 files changed, 32 insertions(+), 63 deletions(-) diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index 862db425ec365..b0242a31b6f3d 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -2,7 +2,7 @@
(this.parameterOptions || []).find((option) => option.value === value)); } - this.valueChanged(typeof value !== 'undefined' ? value : null); + if (this.isResourceLocatorParameter) { + this.valueChanged({ value, mode: this.value.mode }); + } else { + this.valueChanged(typeof value !== 'undefined' ? value : null); + } } else if (command === 'refreshOptions') { this.loadRemoteParameterOptions(); } diff --git a/packages/editor-ui/src/components/ParameterInputFull.vue b/packages/editor-ui/src/components/ParameterInputFull.vue index 8d7d2aed731fc..df7504970e48a 100644 --- a/packages/editor-ui/src/components/ParameterInputFull.vue +++ b/packages/editor-ui/src/components/ParameterInputFull.vue @@ -13,6 +13,7 @@ :value="value" :isReadOnly="isReadOnly" :showOptions="displayOptions" + :isValueExpression="isValueExpression" @optionSelected="optionSelected" @menu-expanded="onMenuExpanded" /> @@ -36,6 +37,7 @@ :droppable="droppable" :activeDrop="activeDrop" :forceShowExpression="forceShowExpression" + :isValueExpression="isValueExpression" @valueChanged="valueChanged" @focus="onFocus" @blur="onBlur" @@ -101,6 +103,18 @@ export default mixins( isDropDisabled (): boolean { return this.parameter.noDataExpression || this.isReadOnly || this.isResourceLocator; }, + isValueExpression () { + if (this.parameter.noDataExpression === true) { + return false; + } + if (typeof this.value === 'string' && this.value.charAt(0) === '=') { + return true; + } + if (typeof this.value.value === 'string' && this.value.value.charAt(0) === '=') { + return true; + } + return false; + }, }, methods: { onFocus() { diff --git a/packages/editor-ui/src/components/ParameterOptions.vue b/packages/editor-ui/src/components/ParameterOptions.vue index b7fb02ea6b622..6b4e5cdba65e6 100644 --- a/packages/editor-ui/src/components/ParameterOptions.vue +++ b/packages/editor-ui/src/components/ParameterOptions.vue @@ -34,6 +34,7 @@ export default Vue.extend({ 'isReadOnly', 'value', 'showOptions', + 'isValueExpression', ], computed: { isDefault (): boolean { @@ -61,18 +62,6 @@ export default Vue.extend({ return 'fixed'; }, - isValueExpression () { - if (this.parameter.noDataExpression === true) { - return false; - } - if (typeof this.value === 'string' && this.value.charAt(0) === '=') { - return true; - } - if (typeof this.value.value === 'string' && this.value.value.charAt(0) === '=') { - return true; - } - return false; - }, hasRemoteMethod (): boolean { return !!this.getArgument('loadOptionsMethod') || !!this.getArgument('loadOptions'); }, diff --git a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue index b998ab8336c1f..d924997a7ae6a 100644 --- a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue +++ b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue @@ -36,7 +36,6 @@ v-if="isValueExpression || droppable || forceShowExpression" :size="inputSize" type="text" - :rows="rows" :value="activeDrop || forceShowExpression ? '' : expressionDisplayValue" :title="displayTitle" @keydown.stop @@ -47,7 +46,6 @@ v-model="tempValue" :size="inputSize" type="text" - :rows="rows" :value="displayValue" :disabled="isReadOnly" :title="displayTitle" @@ -104,12 +102,6 @@ export default mixins().extend({ type: String, default: '', }, - node: { - type: Object as () => INodeUi, - default() { - return this.$store.getters.activeNode; - }, - }, inputSize: { type: String, default: 'small', @@ -137,11 +129,9 @@ export default mixins().extend({ }, parameterInputClasses: { type: Object, - default: {}, - }, - rows: { - type: Number, - default: 0, + default () { + return {}; + }, }, isReadOnly: { type: Boolean, From fc1529fce1e0bf7af80080dcedc182e9e006d030 Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Wed, 10 Aug 2022 12:13:29 +0200 Subject: [PATCH 18/24] =?UTF-8?q?=E2=9A=A1=20Preventing=20`DraggableTarget?= =?UTF-8?q?`=20to=20be=20sticky=20if=20disabled?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/editor-ui/src/components/DraggableTarget.vue | 2 +- packages/editor-ui/src/components/ParameterInputFull.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/editor-ui/src/components/DraggableTarget.vue b/packages/editor-ui/src/components/DraggableTarget.vue index af4d8e04eeb07..ef8073fdbf28e 100644 --- a/packages/editor-ui/src/components/DraggableTarget.vue +++ b/packages/editor-ui/src/components/DraggableTarget.vue @@ -59,7 +59,7 @@ export default Vue.extend({ this.hovering = e.clientX >= dim.left && e.clientX <= dim.right && e.clientY >= dim.top && e.clientY <= dim.bottom; - if (this.sticky && this.hovering) { + if (!this.disabled && this.sticky && this.hovering) { this.$store.commit('ui/setDraggableStickyPos', [dim.left + this.stickyOffset, dim.top + this.stickyOffset]); } } diff --git a/packages/editor-ui/src/components/ParameterInputFull.vue b/packages/editor-ui/src/components/ParameterInputFull.vue index df7504970e48a..5333eee9f0e9c 100644 --- a/packages/editor-ui/src/components/ParameterInputFull.vue +++ b/packages/editor-ui/src/components/ParameterInputFull.vue @@ -22,7 +22,7 @@ From 1d3cf2954c41fdfe8171fb7fcce0fe9b86e9049f Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Wed, 10 Aug 2022 12:47:58 +0200 Subject: [PATCH 19/24] =?UTF-8?q?=F0=9F=90=9B=20Fixing=20a=20bug=20with=20?= =?UTF-8?q?resource=20locator=20value=20parameter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/editor-ui/src/components/ParameterInput.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index b0242a31b6f3d..ff540681edbdb 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -18,7 +18,7 @@ v-if="isResourceLocatorParameter" ref="resourceLocator" :parameter="parameter" - :value="value.value || value" + :value="typeof value === 'string' ? value : value.value" :mode="value.mode || ''" :displayValue="displayValue" :displayTitle="displayTitle" From 6cea7b36e0d4b90ed7ea169b7d02db3da5887730 Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Wed, 10 Aug 2022 16:26:08 +0200 Subject: [PATCH 20/24] =?UTF-8?q?=F0=9F=91=8C=20Adding=20new=20type=20alia?= =?UTF-8?q?s=20for=20all=20possible=20node=20parameter=20value=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/src/NodeExecuteFunctions.ts | 101 ++------------- packages/workflow/src/Expression.ts | 54 +------- packages/workflow/src/Interfaces.ts | 141 +++------------------ packages/workflow/src/RoutingNode.ts | 19 +-- packages/workflow/src/Workflow.ts | 19 +-- packages/workflow/src/WorkflowDataProxy.ts | 11 +- 6 files changed, 47 insertions(+), 298 deletions(-) diff --git a/packages/core/src/NodeExecuteFunctions.ts b/packages/core/src/NodeExecuteFunctions.ts index 5e6c11e4b1907..5f7611b7b74f6 100644 --- a/packages/core/src/NodeExecuteFunctions.ts +++ b/packages/core/src/NodeExecuteFunctions.ts @@ -51,7 +51,6 @@ import { NodeApiError, NodeHelpers, NodeOperationError, - NodeParameterValue, Workflow, WorkflowActivateMode, WorkflowDataProxy, @@ -59,7 +58,7 @@ import { LoggerProxy as Logger, IExecuteData, OAuth2GrantType, - INodeParameterResourceLocator, + NodeParameterValueType, } from 'n8n-workflow'; import { Agent } from 'https'; @@ -1622,21 +1621,7 @@ export function getNode(node: INode): INode { * Clean up parameter data to make sure that only valid data gets returned * INFO: Currently only converts Luxon Dates as we know for sure it will not be breaking */ -function cleanupParameterData( - inputData: - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[], -): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] { +function cleanupParameterData(inputData: NodeParameterValueType): NodeParameterValueType { if (inputData === null || inputData === undefined) { return inputData; } @@ -1689,14 +1674,7 @@ export function getNodeParameter( additionalKeys: IWorkflowDataProxyAdditionalKeys, executeData?: IExecuteData, fallbackValue?: any, -): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object { +): NodeParameterValueType | object { const nodeType = workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion); if (nodeType === undefined) { throw new Error(`Node type "${node.type}" is not known so can not return paramter value!`); @@ -1902,14 +1880,7 @@ export function getExecutePollFunctions( getNodeParameter: ( parameterName: string, fallbackValue?: any, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object => { + ): NodeParameterValueType | object => { const runExecutionData: IRunExecutionData | null = null; const itemIndex = 0; const runIndex = 0; @@ -2059,14 +2030,7 @@ export function getExecuteTriggerFunctions( getNodeParameter: ( parameterName: string, fallbackValue?: any, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object => { + ): NodeParameterValueType | object => { const runExecutionData: IRunExecutionData | null = null; const itemIndex = 0; const runIndex = 0; @@ -2277,14 +2241,7 @@ export function getExecuteFunctions( parameterName: string, itemIndex: number, fallbackValue?: any, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object => { + ): NodeParameterValueType | object => { return getNodeParameter( workflow, runExecutionData, @@ -2553,14 +2510,7 @@ export function getExecuteSingleFunctions( getNodeParameter: ( parameterName: string, fallbackValue?: any, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object => { + ): NodeParameterValueType | object => { return getNodeParameter( workflow, runExecutionData, @@ -2706,15 +2656,7 @@ export function getLoadOptionsFunctions( }, getCurrentNodeParameter: ( parameterPath: string, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object - | undefined => { + ): NodeParameterValueType | object | undefined => { const nodeParameters = additionalData.currentNodeParameters; if (parameterPath.charAt(0) === '&') { @@ -2732,14 +2674,7 @@ export function getLoadOptionsFunctions( getNodeParameter: ( parameterName: string, fallbackValue?: any, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object => { + ): NodeParameterValueType | object => { const runExecutionData: IRunExecutionData | null = null; const itemIndex = 0; const runIndex = 0; @@ -2865,14 +2800,7 @@ export function getExecuteHookFunctions( getNodeParameter: ( parameterName: string, fallbackValue?: any, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object => { + ): NodeParameterValueType | object => { const runExecutionData: IRunExecutionData | null = null; const itemIndex = 0; const runIndex = 0; @@ -3030,14 +2958,7 @@ export function getExecuteWebhookFunctions( getNodeParameter: ( parameterName: string, fallbackValue?: any, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object => { + ): NodeParameterValueType | object => { const runExecutionData: IRunExecutionData | null = null; const itemIndex = 0; const runIndex = 0; diff --git a/packages/workflow/src/Expression.ts b/packages/workflow/src/Expression.ts index 41f566e36d16f..0d8f9c465eafb 100644 --- a/packages/workflow/src/Expression.ts +++ b/packages/workflow/src/Expression.ts @@ -9,11 +9,11 @@ import { IExecuteData, INode, INodeExecutionData, - INodeParameterResourceLocator, INodeParameters, IRunExecutionData, IWorkflowDataProxyAdditionalKeys, NodeParameterValue, + NodeParameterValueType, Workflow, WorkflowDataProxy, WorkflowExecuteMode, @@ -346,23 +346,9 @@ export class Expression { timezone: string, additionalKeys: IWorkflowDataProxyAdditionalKeys, executeData?: IExecuteData, - defaultValue: - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | undefined = undefined, + defaultValue: NodeParameterValueType | undefined = undefined, selfData = {}, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | undefined { + ): NodeParameterValueType | undefined { if (parameterValue === undefined) { // Value is not set so return the default return defaultValue; @@ -427,13 +413,7 @@ export class Expression { * @memberof Workflow */ getParameterValue( - parameterValue: - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[], + parameterValue: NodeParameterValueType, runExecutionData: IRunExecutionData | null, runIndex: number, itemIndex: number, @@ -445,35 +425,15 @@ export class Expression { executeData?: IExecuteData, returnObjectAsString = false, selfData = {}, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] { + ): NodeParameterValueType { // Helper function which returns true when the parameter is a complex one or array - const isComplexParameter = ( - value: - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[], - ) => { + const isComplexParameter = (value: NodeParameterValueType) => { return typeof value === 'object'; }; // Helper function which resolves a parameter value depending on if it is simply or not const resolveParameterValue = ( - value: - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[], + value: NodeParameterValueType, siblingParameters: INodeParameters, ) => { if (isComplexParameter(value)) { diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 785e4bac9bd34..46dbe0457deb2 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -537,16 +537,7 @@ export interface IN8nRequestOperationPaginationOffset extends IN8nRequestOperati export interface IExecuteFunctions { continueOnFail(): boolean; - evaluateExpression( - expression: string, - itemIndex: number, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[]; + evaluateExpression(expression: string, itemIndex: number): NodeParameterValueType; executeWorkflow( workflowInfo: IExecuteWorkflowInfo, inputData?: INodeExecutionData[], @@ -565,14 +556,7 @@ export interface IExecuteFunctions { parameterName: string, itemIndex: number, fallbackValue?: any, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object; + ): NodeParameterValueType | object; getWorkflowDataProxy(itemIndex: number): IWorkflowDataProxyData; getWorkflowStaticData(type: string): IDataObject; getRestApiUrl(): string; @@ -602,33 +586,14 @@ export interface IExecuteFunctions { export interface IExecuteSingleFunctions { continueOnFail(): boolean; - evaluateExpression( - expression: string, - itemIndex: number | undefined, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[]; + evaluateExpression(expression: string, itemIndex: number | undefined): NodeParameterValueType; getContext(type: string): IContextObject; getCredentials(type: string): Promise; getInputData(inputIndex?: number, inputName?: string): INodeExecutionData; getItemIndex(): number; getMode(): WorkflowExecuteMode; getNode(): INode; - getNodeParameter( - parameterName: string, - fallbackValue?: any, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object; + getNodeParameter(parameterName: string, fallbackValue?: any): NodeParameterValueType | object; getRestApiUrl(): string; getTimezone(): string; getExecuteData(): IExecuteData; @@ -674,28 +639,8 @@ export interface ICredentialTestFunctions { export interface ILoadOptionsFunctions { getCredentials(type: string): Promise; getNode(): INode; - getNodeParameter( - parameterName: string, - fallbackValue?: any, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object; - getCurrentNodeParameter( - parameterName: string, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object - | undefined; + getNodeParameter(parameterName: string, fallbackValue?: any): NodeParameterValueType | object; + getCurrentNodeParameter(parameterName: string): NodeParameterValueType | object | undefined; getCurrentNodeParameters(): INodeParameters | undefined; getTimezone(): string; getRestApiUrl(): string; @@ -727,17 +672,7 @@ export interface IHookFunctions { getActivationMode(): WorkflowActivateMode; getNode(): INode; getNodeWebhookUrl: (name: string) => string | undefined; - getNodeParameter( - parameterName: string, - fallbackValue?: any, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object; + getNodeParameter(parameterName: string, fallbackValue?: any): NodeParameterValueType | object; getTimezone(): string; getWebhookDescription(name: string): IWebhookDescription | undefined; getWebhookName(): string; @@ -763,17 +698,7 @@ export interface IPollFunctions { getMode(): WorkflowExecuteMode; getActivationMode(): WorkflowActivateMode; getNode(): INode; - getNodeParameter( - parameterName: string, - fallbackValue?: any, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object; + getNodeParameter(parameterName: string, fallbackValue?: any): NodeParameterValueType | object; getRestApiUrl(): string; getTimezone(): string; getWorkflow(): IWorkflowMetadata; @@ -803,17 +728,7 @@ export interface ITriggerFunctions { getMode(): WorkflowExecuteMode; getActivationMode(): WorkflowActivateMode; getNode(): INode; - getNodeParameter( - parameterName: string, - fallbackValue?: any, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object; + getNodeParameter(parameterName: string, fallbackValue?: any): NodeParameterValueType | object; getRestApiUrl(): string; getTimezone(): string; getWorkflow(): IWorkflowMetadata; @@ -838,17 +753,7 @@ export interface IWebhookFunctions { getHeaderData(): object; getMode(): WorkflowExecuteMode; getNode(): INode; - getNodeParameter( - parameterName: string, - fallbackValue?: any, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | object; + getNodeParameter(parameterName: string, fallbackValue?: any): NodeParameterValueType | object; getNodeWebhookUrl: (name: string) => string | undefined; getParamsData(): object; getQueryData(): object; @@ -961,15 +866,17 @@ export interface INodeParameterResourceLocator { value: NodeParameterValue; } -export interface INodeParameters { +export type NodeParameterValueType = // TODO: Later also has to be possible to add multiple ones with the name name. So array has to be possible - [key: string]: - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[]; + | NodeParameterValue + | INodeParameters + | INodeParameterResourceLocator + | NodeParameterValue[] + | INodeParameters[] + | INodeParameterResourceLocator[]; + +export interface INodeParameters { + [key: string]: NodeParameterValueType; } export type NodePropertyTypes = @@ -1034,13 +941,7 @@ export interface INodeProperties { name: string; type: NodePropertyTypes; typeOptions?: INodePropertyTypeOptions; - default: - | NodeParameterValue - | INodeParameters - | INodeParameters[] - | NodeParameterValue[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[]; + default: NodeParameterValueType; description?: string; hint?: string; displayOptions?: IDisplayOptions; diff --git a/packages/workflow/src/RoutingNode.ts b/packages/workflow/src/RoutingNode.ts index 02f86c1362d7c..12004d48491c1 100644 --- a/packages/workflow/src/RoutingNode.ts +++ b/packages/workflow/src/RoutingNode.ts @@ -43,9 +43,9 @@ import { IExecuteData, IExecuteSingleFunctions, IN8nRequestOperations, - INodeParameterResourceLocator, INodeProperties, INodePropertyCollection, + NodeParameterValueType, PostReceiveAction, } from './Interfaces'; @@ -581,26 +581,13 @@ export class RoutingNode { } getParameterValue( - parameterValue: - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[], + parameterValue: NodeParameterValueType, itemIndex: number, runIndex: number, executeData: IExecuteData, additionalKeys?: IWorkflowDataProxyAdditionalKeys, returnObjectAsString = false, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] - | string { + ): NodeParameterValueType | string { if ( typeof parameterValue === 'object' || (typeof parameterValue === 'string' && parameterValue.charAt(0) === '=') diff --git a/packages/workflow/src/Workflow.ts b/packages/workflow/src/Workflow.ts index 1126186f18567..2184c644f4624 100644 --- a/packages/workflow/src/Workflow.ts +++ b/packages/workflow/src/Workflow.ts @@ -39,7 +39,6 @@ import { IWorkflowExecuteAdditionalData, IWorkflowSettings, NodeHelpers, - NodeParameterValue, ObservableObject, RoutingNode, WebhookSetupMethodNames, @@ -56,7 +55,7 @@ import { IObservableObject, IRun, IRunNodeResponse, - INodeParameterResourceLocator, + NodeParameterValueType, } from './Interfaces'; function dedupe(arr: T[]): T[] { @@ -437,22 +436,10 @@ export class Workflow { * @memberof Workflow */ renameNodeInExpressions( - parameterValue: - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[], + parameterValue: NodeParameterValueType, currentName: string, newName: string, - ): - | NodeParameterValue - | INodeParameters - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[] { + ): NodeParameterValueType { if (typeof parameterValue !== 'object') { // Reached the actual value if (typeof parameterValue === 'string' && parameterValue.charAt(0) === '=') { diff --git a/packages/workflow/src/WorkflowDataProxy.ts b/packages/workflow/src/WorkflowDataProxy.ts index 55ddbc0340fd2..5199b233ed432 100644 --- a/packages/workflow/src/WorkflowDataProxy.ts +++ b/packages/workflow/src/WorkflowDataProxy.ts @@ -16,7 +16,6 @@ import { IDataObject, IExecuteData, INodeExecutionData, - INodeParameterResourceLocator, INodeParameters, IPairedItemData, IRunExecutionData, @@ -25,7 +24,7 @@ import { IWorkflowDataProxyAdditionalKeys, IWorkflowDataProxyData, NodeHelpers, - NodeParameterValue, + NodeParameterValueType, Workflow, WorkflowExecuteMode, } from '.'; @@ -179,13 +178,7 @@ export class WorkflowDataProxy { get(target, name, receiver) { name = name.toString(); - let returnValue: - | INodeParameters - | NodeParameterValue - | NodeParameterValue[] - | INodeParameters[] - | INodeParameterResourceLocator - | INodeParameterResourceLocator[]; + let returnValue: NodeParameterValueType; if (name[0] === '&') { const key = name.slice(1); if (!that.siblingParameters.hasOwnProperty(key)) { From 5759814e063b11948f9e60c0270e5f3a97df3201 Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Wed, 10 Aug 2022 17:45:21 +0200 Subject: [PATCH 21/24] =?UTF-8?q?=F0=9F=91=8C=20Updating=20`ResourceLocato?= =?UTF-8?q?r`=20and=20related=20components=20based=20on=20PR=20review=20fe?= =?UTF-8?q?edback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../editor-ui/src/components/NodeSettings.vue | 3 +-- .../src/components/ParameterInput.vue | 2 +- .../src/components/ParameterInputExpanded.vue | 8 ++++++++ .../src/components/ParameterInputFull.vue | 15 +++------------ packages/editor-ui/src/components/helpers.ts | 15 ++++++++++++++- packages/editor-ui/src/store.ts | 19 ------------------- packages/workflow/src/NodeHelpers.ts | 12 ++++++------ 7 files changed, 33 insertions(+), 41 deletions(-) diff --git a/packages/editor-ui/src/components/NodeSettings.vue b/packages/editor-ui/src/components/NodeSettings.vue index bfebb6286c3d2..208e5f989d95f 100644 --- a/packages/editor-ui/src/components/NodeSettings.vue +++ b/packages/editor-ui/src/components/NodeSettings.vue @@ -491,8 +491,7 @@ export default mixins( nodeParameters = NodeHelpers.getNodeParameters(nodeType.properties, nodeParameters as INodeParameters, true, false, node); for (const key of Object.keys(nodeParameters as object)) { - // Skip non-exiting keys and resource loader '.mode' parameters - if (nodeParameters && nodeParameters[key] !== null && nodeParameters[key] !== undefined && !key.endsWith('.mode')) { + if (nodeParameters && nodeParameters[key] !== null && nodeParameters[key] !== undefined) { this.setValue(`parameters.${key}`, nodeParameters[key] as string); } } diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index ff540681edbdb..d980b5ee0a384 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -865,7 +865,7 @@ export default mixins( // @ts-ignore if (this.$refs.inputField && this.$refs.inputField.$el) { // @ts-ignore - (this.$refs.inputField.$el.querySelector(this.getStringInputType === 'textarea' ? 'textarea' : 'input') as HTMLInputElement).focus(); + this.$refs.inputField.focus(); } }); diff --git a/packages/editor-ui/src/components/ParameterInputExpanded.vue b/packages/editor-ui/src/components/ParameterInputExpanded.vue index 2f837d9cc4148..efa4c72d1c3d4 100644 --- a/packages/editor-ui/src/components/ParameterInputExpanded.vue +++ b/packages/editor-ui/src/components/ParameterInputExpanded.vue @@ -12,6 +12,7 @@ :value="value" :isReadOnly="false" :showOptions="true" + :isValueExpression="isValueExpression" @optionSelected="optionSelected" @menu-expanded="onMenuExpanded" /> @@ -29,6 +30,7 @@ :errorHighlight="showRequiredErrors" :isForCredential="true" :eventSource="eventSource" + :isValueExpression="isValueExpression" @focus="onFocus" @blur="onBlur" @textInput="valueChanged" @@ -53,6 +55,8 @@ import ParameterInput from './ParameterInput.vue'; import ParameterOptions from './ParameterOptions.vue'; import InputHint from './ParameterInputHint.vue'; import Vue from 'vue'; +import { isValueExpression } from './helpers'; +import { INodeParameterResourceLocator, INodeProperties } from 'n8n-workflow'; export default Vue.extend({ name: 'ParameterInputExpanded', @@ -63,6 +67,7 @@ export default Vue.extend({ }, props: { parameter: { + type: Object as () => INodeProperties, }, value: { }, @@ -101,6 +106,9 @@ export default Vue.extend({ return false; }, + isValueExpression (): boolean { + return isValueExpression(this.parameter, this.value as string | INodeParameterResourceLocator); + }, }, methods: { onFocus() { diff --git a/packages/editor-ui/src/components/ParameterInputFull.vue b/packages/editor-ui/src/components/ParameterInputFull.vue index 5333eee9f0e9c..cd8a9aab1f59a 100644 --- a/packages/editor-ui/src/components/ParameterInputFull.vue +++ b/packages/editor-ui/src/components/ParameterInputFull.vue @@ -65,7 +65,7 @@ import DraggableTarget from '@/components/DraggableTarget.vue'; import mixins from 'vue-typed-mixins'; import { showMessage } from './mixins/showMessage'; import { LOCAL_STORAGE_MAPPING_FLAG } from '@/constants'; -import { hasExpressionMapping } from './helpers'; +import { hasExpressionMapping, isValueExpression } from './helpers'; export default mixins( showMessage, @@ -103,17 +103,8 @@ export default mixins( isDropDisabled (): boolean { return this.parameter.noDataExpression || this.isReadOnly || this.isResourceLocator; }, - isValueExpression () { - if (this.parameter.noDataExpression === true) { - return false; - } - if (typeof this.value === 'string' && this.value.charAt(0) === '=') { - return true; - } - if (typeof this.value.value === 'string' && this.value.value.charAt(0) === '=') { - return true; - } - return false; + isValueExpression (): boolean { + return isValueExpression(this.parameter, this.value); }, }, methods: { diff --git a/packages/editor-ui/src/components/helpers.ts b/packages/editor-ui/src/components/helpers.ts index 84f059a350b3e..20861d7c49105 100644 --- a/packages/editor-ui/src/components/helpers.ts +++ b/packages/editor-ui/src/components/helpers.ts @@ -1,7 +1,7 @@ import { CORE_NODES_CATEGORY, ERROR_TRIGGER_NODE_TYPE, MAPPING_PARAMS, TEMPLATES_NODES_FILTER } from '@/constants'; import { INodeUi, ITemplatesNode } from '@/Interface'; import dateformat from 'dateformat'; -import {IDataObject, INodeTypeDescription} from 'n8n-workflow'; +import {IDataObject, INodeParameterResourceLocator, INodeProperties, INodeTypeDescription} from 'n8n-workflow'; const KEYWORDS_TO_FILTER = ['API', 'OAuth1', 'OAuth2']; const SI_SYMBOL = ['', 'k', 'M', 'G', 'T', 'P', 'E']; @@ -99,3 +99,16 @@ export function shorten(s: string, limit: number, keep: number) { export function hasExpressionMapping(value: unknown) { return typeof value === 'string' && !!MAPPING_PARAMS.find((param) => value.includes(param)); } + +export function isValueExpression (parameter: INodeProperties, paramValue: string| INodeParameterResourceLocator): boolean { + if (parameter.noDataExpression === true) { + return false; + } + if (typeof paramValue === 'string' && paramValue.charAt(0) === '=') { + return true; + } + if (typeof paramValue === 'object' && paramValue.value && paramValue.value.toString().charAt(0) === '=') { + return true; + } + return false; +} diff --git a/packages/editor-ui/src/store.ts b/packages/editor-ui/src/store.ts index be7daac07c4cb..62a1ed9fd102b 100644 --- a/packages/editor-ui/src/store.ts +++ b/packages/editor-ui/src/store.ts @@ -532,17 +532,6 @@ export const store = new Vuex.Store({ Vue.set(state.nodeMetadata[node.name], 'parametersLastUpdatedAt', Date.now()); }, - // Selected resource locator modes for each parameter - setNodeParameterMode(state, payload: { nodeName: string, paramName: string, mode: string }) { - const node = state.workflow.nodes.find(node => { - return node.name === payload.nodeName; - }); - if (node) { - Vue.set(node.parameters, payload.paramName + '.mode', payload.mode ); - state.stateIsDirty = true; - } - }, - // Node-View setNodeViewMoveInProgress(state, value: boolean) { state.nodeViewMoveInProgress = value; @@ -985,13 +974,5 @@ export const store = new Vuex.Store({ sidebarMenuItems: (state): IMenuItem[] => { return state.sidebarMenuItems; }, - - getNodeParameterLocatorMode: (state, getters) => (nodeName: string, paramName: string): string => { - const node: INodeUi = getters.nodesByName[nodeName]; - if (node && node.parameters[`${paramName}.mode`]) { - return node.parameters[`${paramName}.mode`]!.toString() || ''; - } - return ''; - }, }, }); diff --git a/packages/workflow/src/NodeHelpers.ts b/packages/workflow/src/NodeHelpers.ts index 053e06fe65db2..5acce53f4852f 100644 --- a/packages/workflow/src/NodeHelpers.ts +++ b/packages/workflow/src/NodeHelpers.ts @@ -617,12 +617,12 @@ export function getNodeParameters( if (!['collection', 'fixedCollection'].includes(nodeProperties.type)) { // Is a simple property so can be set as it is - // If it's a resource locator parameter, find it's mode and add to list - if (nodeProperties.type === 'resourceLocator') { - const parameterMode = nodeValues[`${nodeProperties.name}.mode`]; - if (parameterMode) { - nodeParameters[`${nodeProperties.name}.mode`] = parameterMode; - } + // If it's a resource locator parameter initialize it's value to object if it's first type value is fetched + if ( + nodeProperties.type === 'resourceLocator' && + typeof nodeValues[nodeProperties.name] !== 'object' + ) { + nodeValues[nodeProperties.name] = { value: '', mode: '' }; } if (duplicateParameterNames.includes(nodeProperties.name)) { From 10898e82151952151b196f79e75e84dc0ee373fb Mon Sep 17 00:00:00 2001 From: Milorad Filipovic Date: Thu, 11 Aug 2022 10:18:31 +0200 Subject: [PATCH 22/24] =?UTF-8?q?=E2=9A=A1=20Adding=20disabled=20mode=20to?= =?UTF-8?q?=20`ResourceLocator`=20component,=20fixing=20expression=20handl?= =?UTF-8?q?ing,=20minor=20refactoring.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../editor-ui/src/components/ParameterInput.vue | 7 ++++--- .../src/components/ParameterInputFull.vue | 2 +- .../components/ResourceLocator/ResourceLocator.vue | 14 ++++++-------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index d980b5ee0a384..1e98873e3052d 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -25,6 +25,7 @@ :parameterInputClasses="parameterInputClasses" :expressionDisplayValue="expressionDisplayValue" :isValueExpression="isValueExpression" + :isReadOnly="isReadOnly" :parameterIssues="getIssues" :droppable="droppable" @valueChanged="valueChanged" @@ -935,9 +936,9 @@ export default mixins( this.expressionEditDialogVisible = true; } else if (command === 'addExpression') { if (this.parameter.type === 'number' || this.parameter.type === 'boolean') { - this.valueChanged(`={{${this.value}}}`); + this.valueChanged({ value: `={{${this.value}}}`, mode: this.value.mode }); } else if (this.isResourceLocatorParameter) { - this.valueChanged(`=${this.value.value}`); + this.valueChanged({ value: `=${this.value.value}`, mode: this.value.mode }); } else { this.valueChanged(`=${this.value}`); } @@ -1072,7 +1073,7 @@ export default mixins( } .expression { - textarea, input { + textarea:not([disabled]), input:not([disabled]) { cursor: pointer !important; } diff --git a/packages/editor-ui/src/components/ParameterInputFull.vue b/packages/editor-ui/src/components/ParameterInputFull.vue index cd8a9aab1f59a..20219a81d9305 100644 --- a/packages/editor-ui/src/components/ParameterInputFull.vue +++ b/packages/editor-ui/src/components/ParameterInputFull.vue @@ -135,7 +135,7 @@ export default mixins( this.forceShowExpression = true; setTimeout(() => { if (this.node) { - const prevValue = this.value; + const prevValue = this.isResourceLocator ? this.value.value : this.value; let updatedValue: string; if (typeof prevValue === 'string' && prevValue.startsWith('=') && prevValue.length > 1) { updatedValue = `${prevValue} ${data}`; diff --git a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue index d924997a7ae6a..9ecfd1e693b8c 100644 --- a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue +++ b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue @@ -12,9 +12,10 @@ > Date: Thu, 11 Aug 2022 11:43:44 +0200 Subject: [PATCH 23/24] =?UTF-8?q?=F0=9F=92=84=20Updating=20disabled=20stat?= =?UTF-8?q?e=20styling=20in=20`ResourceLocator`=20component?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/editor-ui/src/components/ParameterInput.vue | 2 +- .../src/components/ResourceLocator/ResourceLocator.vue | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index 1e98873e3052d..e2af6608ef0c6 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -1073,7 +1073,7 @@ export default mixins( } .expression { - textarea:not([disabled]), input:not([disabled]) { + textarea, input { cursor: pointer !important; } diff --git a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue index 9ecfd1e693b8c..153b3247b1bfe 100644 --- a/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue +++ b/packages/editor-ui/src/components/ResourceLocator/ResourceLocator.vue @@ -39,7 +39,6 @@ :size="inputSize" :value="activeDrop || forceShowExpression ? '' : expressionDisplayValue" :title="displayTitle" - :disabled="isReadOnly" @keydown.stop /> Date: Thu, 11 Aug 2022 14:46:18 +0200 Subject: [PATCH 24/24] =?UTF-8?q?=E2=9A=A1=20Setting=20correct=20default?= =?UTF-8?q?=20value=20for=20test=20node=20and=20removing=20unnecessary=20l?= =?UTF-8?q?ogic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/nodes-base/nodes/Trello/BoardDescription.ts | 4 ++-- packages/workflow/src/NodeHelpers.ts | 9 --------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/packages/nodes-base/nodes/Trello/BoardDescription.ts b/packages/nodes-base/nodes/Trello/BoardDescription.ts index 506132ffb32fa..6269c064059f9 100644 --- a/packages/nodes-base/nodes/Trello/BoardDescription.ts +++ b/packages/nodes-base/nodes/Trello/BoardDescription.ts @@ -315,7 +315,7 @@ export const boardFields: INodeProperties[] = [ displayName: 'Board', name: 'id', type: 'resourceLocator', - default: '', + default: { mode: 'list', value: '' }, required: true, displayOptions: { show: { @@ -358,7 +358,7 @@ export const boardFields: INodeProperties[] = [ displayName: 'Board', name: 'id', type: 'resourceLocator', - default: '', + default: { mode: 'list', value: '' }, required: true, displayOptions: { show: { diff --git a/packages/workflow/src/NodeHelpers.ts b/packages/workflow/src/NodeHelpers.ts index 5acce53f4852f..8d866b0b8e46a 100644 --- a/packages/workflow/src/NodeHelpers.ts +++ b/packages/workflow/src/NodeHelpers.ts @@ -617,14 +617,6 @@ export function getNodeParameters( if (!['collection', 'fixedCollection'].includes(nodeProperties.type)) { // Is a simple property so can be set as it is - // If it's a resource locator parameter initialize it's value to object if it's first type value is fetched - if ( - nodeProperties.type === 'resourceLocator' && - typeof nodeValues[nodeProperties.name] !== 'object' - ) { - nodeValues[nodeProperties.name] = { value: '', mode: '' }; - } - if (duplicateParameterNames.includes(nodeProperties.name)) { if (!displayParameter(nodeValuesDisplayCheck, nodeProperties, node, nodeValuesRoot)) { continue; @@ -855,7 +847,6 @@ export function getNodeParameters( } } } - return nodeParameters; }