From 086c5936cedd32c4760cbf44e3f0b655caa11802 Mon Sep 17 00:00:00 2001 From: ricardo Date: Thu, 9 Apr 2020 16:13:14 -0400 Subject: [PATCH 01/82] :zap: Zendesk improvements --- .../nodes/Zendesk/GenericFunctions.ts | 13 + .../nodes/Zendesk/TicketDescription.ts | 359 ++++++++++++------ .../nodes/Zendesk/TicketFieldDescription.ts | 45 +++ .../nodes-base/nodes/Zendesk/Zendesk.node.ts | 206 +++++++--- 4 files changed, 460 insertions(+), 163 deletions(-) diff --git a/packages/nodes-base/nodes/Zendesk/GenericFunctions.ts b/packages/nodes-base/nodes/Zendesk/GenericFunctions.ts index f098f97358..ffe371e160 100644 --- a/packages/nodes-base/nodes/Zendesk/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Zendesk/GenericFunctions.ts @@ -62,6 +62,9 @@ export async function zendeskApiRequestAllItems(this: IHookFunctions | IExecuteF responseData = await zendeskApiRequest.call(this, method, resource, body, query, uri); uri = responseData.next_page; returnData.push.apply(returnData, responseData[propertyName]); + if (query.limit && query.limit <= returnData.length) { + return returnData; + } } while ( responseData.next_page !== undefined && responseData.next_page !== null @@ -69,3 +72,13 @@ export async function zendeskApiRequestAllItems(this: IHookFunctions | IExecuteF return returnData; } + +export function validateJSON(json: string | undefined): any { // tslint:disable-line:no-any + let result; + try { + result = JSON.parse(json!); + } catch (exception) { + result = undefined; + } + return result; +} diff --git a/packages/nodes-base/nodes/Zendesk/TicketDescription.ts b/packages/nodes-base/nodes/Zendesk/TicketDescription.ts index 7642248e7e..f5daab6535 100644 --- a/packages/nodes-base/nodes/Zendesk/TicketDescription.ts +++ b/packages/nodes-base/nodes/Zendesk/TicketDescription.ts @@ -21,9 +21,9 @@ export const ticketOperations = [ description: 'Create a ticket', }, { - name: 'Update', - value: 'update', - description: 'Update a ticket', + name: 'Delete', + value: 'delete', + description: 'Delete a ticket', }, { name: 'Get', @@ -36,9 +36,9 @@ export const ticketOperations = [ description: 'Get all tickets', }, { - name: 'Delete', - value: 'delete', - description: 'Delete a ticket', + name: 'Update', + value: 'update', + description: 'Update a ticket', }, ], default: 'create', @@ -81,7 +81,7 @@ export const ticketFields = [ displayOptions: { show: { resource: [ - 'ticket' + 'ticket', ], operation: [ 'create', @@ -103,6 +103,9 @@ export const ticketFields = [ operation: [ 'create', ], + jsonParameters: [ + false, + ], }, }, options: [ @@ -114,11 +117,14 @@ export const ticketFields = [ description: 'An id you can use to link Zendesk Support tickets to local records', }, { - displayName: 'Subject', - name: 'subject', - type: 'string', + displayName: 'Group', + name: 'group', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getGroups', + }, default: '', - description: 'The value of the subject field for this ticket', + description: 'The group this ticket is assigned to', }, { displayName: 'Recipient', @@ -128,14 +134,40 @@ export const ticketFields = [ description: 'The original recipient e-mail address of the ticket', }, { - displayName: 'Group', - name: 'group', + displayName: 'Status', + name: 'status', type: 'options', - typeOptions: { - loadOptionsMethod: 'getGroups', - }, + options: [ + { + name: 'Open', + value: 'open', + }, + { + name: 'New', + value: 'new', + }, + { + name: 'Pending', + value: 'pending', + }, + { + name: 'Solved', + value: 'solved', + }, + { + name: 'Closed', + value: 'closed', + }, + ], default: '', - description: 'The group this ticket is assigned to', + description: 'The state of the ticket', + }, + { + displayName: 'Subject', + name: 'subject', + type: 'string', + default: '', + description: 'The value of the subject field for this ticket', }, { displayName: 'Tags', @@ -172,37 +204,78 @@ export const ticketFields = [ default: '', description: 'The type of this ticket', }, + ], + }, + { + displayName: 'Custom Fields', + name: 'customFieldsUi', + placeholder: 'Add Custom Field', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + displayOptions: { + show: { + resource: [ + 'ticket', + ], + operation: [ + 'create', + ], + jsonParameters: [ + false, + ], + }, + }, + default: {}, + options: [ { - displayName: 'Status', - name: 'status', - type: 'options', - options: [ + displayName: 'Custom Field', + name: 'customFieldsValues', + values: [ { - name: 'Open', - value: 'open', + displayName: 'ID', + name: 'id', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCustomFields', + }, + default: '', + description: 'Custom field ID', }, { - name: 'New', - value: 'new', - }, - { - name: 'Pending', - value: 'pending', - }, - { - name: 'Solved', - value: 'solved', - }, - { - name: 'Closed', - value: 'closed', + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + description: 'Custom field Value.', }, ], - default: '', - description: 'The state of the ticket', - } + }, ], }, + { + displayName: ' Additional Fields', + name: 'additionalFieldsJson', + type: 'json', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + displayOptions: { + show: { + resource: [ + 'ticket', + ], + operation: [ + 'create', + ], + jsonParameters: [ + true, + ], + }, + }, + }, { displayName: ' Custom Fields', name: 'customFieldsJson', @@ -224,14 +297,13 @@ export const ticketFields = [ ], }, }, - required: true, description: `Array of customs fields Details`, }, /* -------------------------------------------------------------------------- */ /* ticket:update */ /* -------------------------------------------------------------------------- */ { - displayName: 'ID', + displayName: 'Ticket ID', name: 'id', type: 'string', default: '', @@ -279,6 +351,9 @@ export const ticketFields = [ operation: [ 'update', ], + jsonParameters: [ + false, + ], }, }, options: [ @@ -290,11 +365,14 @@ export const ticketFields = [ description: 'An id you can use to link Zendesk Support tickets to local records', }, { - displayName: 'Subject', - name: 'subject', - type: 'string', + displayName: 'Group', + name: 'group', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getGroups', + }, default: '', - description: 'The value of the subject field for this ticket', + description: 'The group this ticket is assigned to', }, { displayName: 'Recipient', @@ -304,14 +382,40 @@ export const ticketFields = [ description: 'The original recipient e-mail address of the ticket', }, { - displayName: 'Group', - name: 'group', + displayName: 'Status', + name: 'status', type: 'options', - typeOptions: { - loadOptionsMethod: 'getGroups', - }, + options: [ + { + name: 'Open', + value: 'open', + }, + { + name: 'New', + value: 'new', + }, + { + name: 'Pending', + value: 'pending', + }, + { + name: 'Solved', + value: 'solved', + }, + { + name: 'Closed', + value: 'closed', + }, + ], default: '', - description: 'The group this ticket is assigned to', + description: 'The state of the ticket', + }, + { + displayName: 'Subject', + name: 'subject', + type: 'string', + default: '', + description: 'The value of the subject field for this ticket', }, { displayName: 'Tags', @@ -348,37 +452,78 @@ export const ticketFields = [ default: '', description: 'The type of this ticket', }, + ], + }, + { + displayName: 'Custom Fields', + name: 'customFieldsUi', + placeholder: 'Add Custom Field', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + displayOptions: { + show: { + resource: [ + 'ticket', + ], + operation: [ + 'update', + ], + jsonParameters: [ + false, + ], + }, + }, + default: {}, + options: [ { - displayName: 'Status', - name: 'status', - type: 'options', - options: [ + displayName: 'Custom Field', + name: 'customFieldsValues', + values: [ { - name: 'Open', - value: 'open', + displayName: 'ID', + name: 'id', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCustomFields', + }, + default: '', + description: 'Custom field ID', }, { - name: 'New', - value: 'new', - }, - { - name: 'Pending', - value: 'pending', - }, - { - name: 'Solved', - value: 'solved', - }, - { - name: 'Closed', - value: 'closed', + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + description: 'Custom field Value.', }, ], - default: '', - description: 'The state of the ticket', - } + }, ], }, + { + displayName: ' Update Fields', + name: 'updateFieldsJson', + type: 'json', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + displayOptions: { + show: { + resource: [ + 'ticket', + ], + operation: [ + 'update', + ], + jsonParameters: [ + true, + ], + }, + }, + }, { displayName: ' Custom Fields', name: 'customFieldsJson', @@ -407,7 +552,7 @@ export const ticketFields = [ /* ticket:get */ /* -------------------------------------------------------------------------- */ { - displayName: 'ID', + displayName: 'Ticket ID', name: 'id', type: 'string', default: '', @@ -485,35 +630,6 @@ export const ticketFields = [ }, }, options: [ - { - displayName: 'Status', - name: 'status', - type: 'options', - options: [ - { - name: 'Open', - value: 'open', - }, - { - name: 'New', - value: 'new', - }, - { - name: 'Pending', - value: 'pending', - }, - { - name: 'Solved', - value: 'solved', - }, - { - name: 'Closed', - value: 'closed', - }, - ], - default: '', - description: 'The state of the ticket', - }, { displayName: 'Sort By', name: 'sortBy', @@ -559,7 +675,36 @@ export const ticketFields = [ ], default: 'desc', description: 'Sort order', - } + }, + { + displayName: 'Status', + name: 'status', + type: 'options', + options: [ + { + name: 'Open', + value: 'open', + }, + { + name: 'New', + value: 'new', + }, + { + name: 'Pending', + value: 'pending', + }, + { + name: 'Solved', + value: 'solved', + }, + { + name: 'Closed', + value: 'closed', + }, + ], + default: '', + description: 'The state of the ticket', + }, ], }, @@ -567,7 +712,7 @@ export const ticketFields = [ /* ticket:delete */ /* -------------------------------------------------------------------------- */ { - displayName: 'ID', + displayName: 'Ticket ID', name: 'id', type: 'string', default: '', diff --git a/packages/nodes-base/nodes/Zendesk/TicketFieldDescription.ts b/packages/nodes-base/nodes/Zendesk/TicketFieldDescription.ts index 8e061db402..9ba754eef4 100644 --- a/packages/nodes-base/nodes/Zendesk/TicketFieldDescription.ts +++ b/packages/nodes-base/nodes/Zendesk/TicketFieldDescription.ts @@ -54,4 +54,49 @@ export const ticketFieldFields = [ }, description: 'ticketField ID', }, + +/* -------------------------------------------------------------------------- */ +/* ticketField:getAll */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'ticketField', + ], + operation: [ + 'getAll', + ], + }, + }, + default: false, + description: 'If all results should be returned or only up to a given limit.', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource: [ + 'ticketField', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 100, + description: 'How many results to return.', + }, ] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Zendesk/Zendesk.node.ts b/packages/nodes-base/nodes/Zendesk/Zendesk.node.ts index b66481bcc1..a64feb9ca5 100644 --- a/packages/nodes-base/nodes/Zendesk/Zendesk.node.ts +++ b/packages/nodes-base/nodes/Zendesk/Zendesk.node.ts @@ -12,6 +12,7 @@ import { } from 'n8n-workflow'; import { + validateJSON, zendeskApiRequest, zendeskApiRequestAllItems, } from './GenericFunctions'; @@ -30,6 +31,7 @@ import { ITicket, IComment, } from './TicketInterface'; +import { response } from 'express'; export class Zendesk implements INodeType { description: INodeTypeDescription = { @@ -83,6 +85,33 @@ export class Zendesk implements INodeType { methods = { loadOptions: { + // Get all the custom fields to display them to user so that he can + // select them easily + async getCustomFields(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + const customFields = [ + 'text', + 'textarea', + 'date', + 'integer', + 'decimal', + 'regexp', + 'multiselect', + 'tagger', + ]; + const fields = await zendeskApiRequestAllItems.call(this, 'ticket_fields', 'GET', '/ticket_fields'); + for (const field of fields) { + if (customFields.includes(field.type)) { + const fieldName = field.title; + const fieldId = field.id; + returnData.push({ + name: fieldName, + value: fieldId, + }); + } + } + return returnData; + }, // Get all the groups to display them to user so that he can // select them easily async getGroups(this: ILoadOptionsFunctions): Promise { @@ -131,42 +160,71 @@ export class Zendesk implements INodeType { if (operation === 'create') { const description = this.getNodeParameter('description', i) as string; const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean; - const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const comment: IComment = { body: description, }; const body: ITicket = { comment, }; - if (additionalFields.type) { - body.type = additionalFields.type as string; - } - if (additionalFields.externalId) { - body.external_id = additionalFields.externalId as string; - } - if (additionalFields.subject) { - body.subject = additionalFields.subject as string; - } - if (additionalFields.status) { - body.status = additionalFields.status as string; - } - if (additionalFields.recipient) { - body.recipient = additionalFields.recipient as string; - } - if (additionalFields.group) { - body.group = additionalFields.group as string; - } - if (additionalFields.tags) { - body.tags = additionalFields.tags as string[]; - } if (jsonParameters) { + const customFieldsJson = this.getNodeParameter('customFieldsJson', i) as string; - try { - JSON.parse(customFieldsJson); - } catch(err) { - throw new Error('Custom fields must be a valid JSON'); + + if (customFieldsJson !== '' ) { + + if (validateJSON(customFieldsJson) !== undefined) { + + body.custom_fields = JSON.parse(customFieldsJson); + + } else { + throw new Error('Custom fields must be a valid JSON'); + } + } + + const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string; + + if (additionalFieldsJson !== '' ) { + + if (validateJSON(additionalFieldsJson) !== undefined) { + + Object.assign(body, JSON.parse(additionalFieldsJson)); + + } else { + throw new Error('Additional fields must be a valid JSON'); + } + } + + + } else { + + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + + const customFields = (this.getNodeParameter('customFieldsUi', i) as IDataObject).customFieldsValues as IDataObject[]; + + if (additionalFields.type) { + body.type = additionalFields.type as string; + } + if (additionalFields.externalId) { + body.external_id = additionalFields.externalId as string; + } + if (additionalFields.subject) { + body.subject = additionalFields.subject as string; + } + if (additionalFields.status) { + body.status = additionalFields.status as string; + } + if (additionalFields.recipient) { + body.recipient = additionalFields.recipient as string; + } + if (additionalFields.group) { + body.group = additionalFields.group as string; + } + if (additionalFields.tags) { + body.tags = additionalFields.tags as string[]; + } + if (customFields) { + body.custom_fields = customFields; } - body.custom_fields = JSON.parse(customFieldsJson); } responseData = await zendeskApiRequest.call(this, 'POST', '/tickets', { ticket: body }); responseData = responseData.ticket; @@ -175,37 +233,66 @@ export class Zendesk implements INodeType { if (operation === 'update') { const ticketId = this.getNodeParameter('id', i) as string; const jsonParameters = this.getNodeParameter('jsonParameters', i) as boolean; - const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; const body: ITicket = {}; - if (updateFields.type) { - body.type = updateFields.type as string; - } - if (updateFields.externalId) { - body.external_id = updateFields.externalId as string; - } - if (updateFields.subject) { - body.subject = updateFields.subject as string; - } - if (updateFields.status) { - body.status = updateFields.status as string; - } - if (updateFields.recipient) { - body.recipient = updateFields.recipient as string; - } - if (updateFields.group) { - body.group = updateFields.group as string; - } - if (updateFields.tags) { - body.tags = updateFields.tags as string[]; - } + if (jsonParameters) { + const customFieldsJson = this.getNodeParameter('customFieldsJson', i) as string; - try { - JSON.parse(customFieldsJson); - } catch(err) { - throw new Error('Custom fields must be a valid JSON'); + + if (customFieldsJson !== '' ) { + + if (validateJSON(customFieldsJson) !== undefined) { + + body.custom_fields = JSON.parse(customFieldsJson); + + } else { + throw new Error('Custom fields must be a valid JSON'); + } + } + + const updateFieldsJson = this.getNodeParameter('updateFieldsJson', i) as string; + + if (updateFieldsJson !== '' ) { + + if (validateJSON(updateFieldsJson) !== undefined) { + + Object.assign(body, JSON.parse(updateFieldsJson)); + + } else { + throw new Error('Additional fields must be a valid JSON'); + } + } + + } else { + + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + + const customFields = (this.getNodeParameter('customFieldsUi', i) as IDataObject).customFieldsValues as IDataObject[]; + + if (updateFields.type) { + body.type = updateFields.type as string; + } + if (updateFields.externalId) { + body.external_id = updateFields.externalId as string; + } + if (updateFields.subject) { + body.subject = updateFields.subject as string; + } + if (updateFields.status) { + body.status = updateFields.status as string; + } + if (updateFields.recipient) { + body.recipient = updateFields.recipient as string; + } + if (updateFields.group) { + body.group = updateFields.group as string; + } + if (updateFields.tags) { + body.tags = updateFields.tags as string[]; + } + if (customFields) { + body.custom_fields = customFields; } - body.custom_fields = JSON.parse(customFieldsJson); } responseData = await zendeskApiRequest.call(this, 'PUT', `/tickets/${ticketId}`, { ticket: body }); responseData = responseData.ticket; @@ -259,8 +346,15 @@ export class Zendesk implements INodeType { } //https://developer.zendesk.com/rest_api/docs/support/ticket_fields#list-ticket-fields if (operation === 'getAll') { - responseData = await zendeskApiRequest.call(this, 'GET', '/ticket_fields', {}, qs); - responseData = responseData.ticket_fields; + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + if (returnAll) { + responseData = await zendeskApiRequestAllItems.call(this, 'ticket_fields', 'GET', '/ticket_fields', {}, qs); + } else { + const limit = this.getNodeParameter('limit', i) as number; + qs.limit = limit; + responseData = await zendeskApiRequestAllItems.call(this, 'ticket_fields', 'GET', '/ticket_fields', {}, qs); + responseData = responseData.slice(0, limit); + } } } if (Array.isArray(responseData)) { From 59421ebe4df3c58cdf987e303a33574574884a9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 07:57:34 +0200 Subject: [PATCH 02/82] consolelog add --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 5026955952..5f23515742 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -875,7 +875,7 @@ export class Mattermost implements INodeType { body.message = this.getNodeParameter('message', i) as string; const attachments = this.getNodeParameter('attachments', i, []) as unknown as IAttachment[]; - + console.log(attachments); // The node does save the fields data differently than the API // expects so fix the data befre we send the request for (const attachment of attachments) { From bda4b7337528cc2c782b11891cda66a4364ecc60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 08:00:50 +0200 Subject: [PATCH 03/82] log2 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 5f23515742..04ea8f4d2f 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -875,7 +875,7 @@ export class Mattermost implements INodeType { body.message = this.getNodeParameter('message', i) as string; const attachments = this.getNodeParameter('attachments', i, []) as unknown as IAttachment[]; - console.log(attachments); + console.dir(attachments); // The node does save the fields data differently than the API // expects so fix the data befre we send the request for (const attachment of attachments) { From 8e4e4f2fe28c9e967566e8f67e29943f0190dfc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 08:35:21 +0200 Subject: [PATCH 04/82] log updae --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 04ea8f4d2f..abab4af48a 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -875,7 +875,9 @@ export class Mattermost implements INodeType { body.message = this.getNodeParameter('message', i) as string; const attachments = this.getNodeParameter('attachments', i, []) as unknown as IAttachment[]; - console.dir(attachments); + console.log('----'); + console.dir(attachments); + console.log('----'); // The node does save the fields data differently than the API // expects so fix the data befre we send the request for (const attachment of attachments) { @@ -895,6 +897,9 @@ export class Mattermost implements INodeType { attachments, }; + console.log('####'); + console.dir(body); + console.log('####'); // Add all the other options to the request const otherOptions = this.getNodeParameter('otherOptions', i) as IDataObject; Object.assign(body, otherOptions); From 2988a2bdaf4de4a925fb85b044115b1ab7ed0342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 08:52:54 +0200 Subject: [PATCH 05/82] log2 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index abab4af48a..93286d0229 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -893,6 +893,10 @@ export class Mattermost implements INodeType { } } + console.log('&&&&'); + console.dir(attachments); + console.log('&&&&'); + body.props = { attachments, }; From 018d58c9c4ff74cb561b496dc7023ecee61d1e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 09:15:01 +0200 Subject: [PATCH 06/82] util log --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 93286d0229..4013328906 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -904,6 +904,11 @@ export class Mattermost implements INodeType { console.log('####'); console.dir(body); console.log('####'); + console.log('****'); + const util = require('util'); + console.log(util.inspect(body, false, null, true /* enable colors */)); + //console.dir(body); + console.log('****'); // Add all the other options to the request const otherOptions = this.getNodeParameter('otherOptions', i) as IDataObject; Object.assign(body, otherOptions); From 4b9acdc80b62b549fc286c0514ddf4e688daf7a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 09:31:58 +0200 Subject: [PATCH 07/82] logowanie_ok --- .../nodes-base/nodes/Mattermost/Mattermost.node.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 4013328906..a442b69e52 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -892,22 +892,24 @@ export class Mattermost implements INodeType { } } } - + const util = require('util'); console.log('&&&&'); - console.dir(attachments); + //console.dir(attachments); + console.log(util.inspect(attachments, false, null, true /* enable colors */)); console.log('&&&&'); body.props = { attachments, }; - console.log('####'); - console.dir(body); - console.log('####'); + //console.log('####'); + //console.dir(body); + //console.log('####'); console.log('****'); - const util = require('util'); console.log(util.inspect(body, false, null, true /* enable colors */)); //console.dir(body); + //console.log('****111'); + //console.log(JSON.stringify(body, null, 4)); console.log('****'); // Add all the other options to the request const otherOptions = this.getNodeParameter('otherOptions', i) as IDataObject; From 2dc3667984aff0cbd19dce0f7ad5b0f7ff5b73ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 09:42:00 +0200 Subject: [PATCH 08/82] action1 --- .../nodes/Mattermost/Mattermost.node.ts | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index a442b69e52..bc64340ba9 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -571,6 +571,128 @@ export class Mattermost implements INodeType { default: '', description: 'Icon which should appear next to footer.', }, + + + { displayName: 'Actions', + name: 'actions', + placeholder: 'Add Actions', + description: 'Actions to add to message.', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + options: [ + { + displayName: 'Item', + name: 'item', + values: [ + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'Name of the Action.', + }, + + + { + displayName: 'Integrations', + name: 'integrations', + placeholder: 'Add Integrations', + description: 'Integrations to add to message.', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + options: [ + { + displayName: 'Item', + name: 'item', + default: {}, + values: [ + { + displayName: 'URL', + name: 'url', + type: 'string', + default: '', + description: 'URL of the Integration.', + }, +// context + + { + displayName: 'Context', + name: 'context', + placeholder: 'Add Context to Integration', + description: 'Adds a Context values set.', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + options: [ + { + name: 'property', + displayName: 'Property', + default: {}, + values: [ + { + displayName: 'Property Name', + name: 'name', + type: 'string', + default: '', + description: 'Name of the property to set.', + }, + { + displayName: 'Property Value', + name: 'value', + type: 'string', + default: '', + description: 'Value of the property to set.', + }, + ] + }, + ], + }, + + + + + + + + + + ] + }, + ], + }, + + + + + ] + }, + ], + }, + + + + + + + + + + + + + + + + + { displayName: 'Fields', name: 'fields', From 0e7998cbba2541571e1822dcd1e9871ee19b2d45 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sat, 11 Apr 2020 10:30:50 +0200 Subject: [PATCH 09/82] :bug: Fix interface for getWorkflow --- packages/workflow/src/Interfaces.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 44e4373e1d..2d0d92d835 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -167,7 +167,7 @@ export interface IExecuteFunctions { getWorkflowStaticData(type: string): IDataObject; getRestApiUrl(): string; getTimezone(): string; - getWorkflow(workflow: Workflow): IWorkflowMetadata; + getWorkflow(): IWorkflowMetadata; prepareOutputData(outputData: INodeExecutionData[], outputIndex?: number): Promise; helpers: { [key: string]: (...args: any[]) => any //tslint:disable-line:no-any @@ -186,7 +186,7 @@ export interface IExecuteSingleFunctions { getNodeParameter(parameterName: string, fallbackValue?: any): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | object; //tslint:disable-line:no-any getRestApiUrl(): string; getTimezone(): string; - getWorkflow(workflow: Workflow): IWorkflowMetadata; + getWorkflow(): IWorkflowMetadata; getWorkflowDataProxy(): IWorkflowDataProxyData; getWorkflowStaticData(type: string): IDataObject; helpers: { @@ -221,7 +221,7 @@ export interface IHookFunctions { getTimezone(): string; getWebhookDescription(name: string): IWebhookDescription | undefined; getWebhookName(): string; - getWorkflow(workflow: Workflow): IWorkflowMetadata; + getWorkflow(): IWorkflowMetadata; getWorkflowStaticData(type: string): IDataObject; helpers: { [key: string]: (...args: any[]) => any //tslint:disable-line:no-any @@ -236,7 +236,7 @@ export interface IPollFunctions { getNodeParameter(parameterName: string, fallbackValue?: any): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | object; //tslint:disable-line:no-any getRestApiUrl(): string; getTimezone(): string; - getWorkflow(workflow: Workflow): IWorkflowMetadata; + getWorkflow(): IWorkflowMetadata; getWorkflowStaticData(type: string): IDataObject; helpers: { [key: string]: (...args: any[]) => any //tslint:disable-line:no-any @@ -251,7 +251,7 @@ export interface ITriggerFunctions { getNodeParameter(parameterName: string, fallbackValue?: any): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | object; //tslint:disable-line:no-any getRestApiUrl(): string; getTimezone(): string; - getWorkflow(workflow: Workflow): IWorkflowMetadata; + getWorkflow(): IWorkflowMetadata; getWorkflowStaticData(type: string): IDataObject; helpers: { [key: string]: (...args: any[]) => any //tslint:disable-line:no-any @@ -272,7 +272,7 @@ export interface IWebhookFunctions { getTimezone(): string; getWebhookName(): string; getWorkflowStaticData(type: string): IDataObject; - getWorkflow(workflow: Workflow): IWorkflowMetadata; + getWorkflow(): IWorkflowMetadata; prepareOutputData(outputData: INodeExecutionData[], outputIndex?: number): Promise; helpers: { [key: string]: (...args: any[]) => any //tslint:disable-line:no-any From 89dadae289ac9c478010d2bef66c071554fb59ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 10:35:07 +0200 Subject: [PATCH 10/82] add2 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index bc64340ba9..8e8a2b3d60 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -577,7 +577,7 @@ export class Mattermost implements INodeType { name: 'actions', placeholder: 'Add Actions', description: 'Actions to add to message.', - type: 'fixedCollection', + type: 'Collection', typeOptions: { multipleValues: true, }, From 4d873da53d5a61fc1b73fd846afa1ce6d48ef8f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 12:11:17 +0200 Subject: [PATCH 11/82] add4 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 8e8a2b3d60..bc64340ba9 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -577,7 +577,7 @@ export class Mattermost implements INodeType { name: 'actions', placeholder: 'Add Actions', description: 'Actions to add to message.', - type: 'Collection', + type: 'fixedCollection', typeOptions: { multipleValues: true, }, From 49b6b8a467893844bf5ca6dee2f403581da01666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 13:07:37 +0200 Subject: [PATCH 12/82] add5 --- .../nodes-base/nodes/Mattermost/Mattermost.node.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index bc64340ba9..a92b00563c 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1013,6 +1013,16 @@ export class Mattermost implements INodeType { delete attachment.fields; } } + if (attachment.actions !== undefined) { + if (attachment.actions.item !== undefined) { + // Move the field-content up + // @ts-ignore + attachment.actions = attachment.actions.item; + } else { + // If it does not have any items set remove it + delete attachment.actions; + } + } } const util = require('util'); console.log('&&&&'); From bfc818657847084c40f91d91165df65a83b671b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 13:36:26 +0200 Subject: [PATCH 13/82] add9 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index a92b00563c..e7071d7100 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1012,7 +1012,7 @@ export class Mattermost implements INodeType { // If it does not have any items set remove it delete attachment.fields; } - } + }; if (attachment.actions !== undefined) { if (attachment.actions.item !== undefined) { // Move the field-content up @@ -1022,7 +1022,7 @@ export class Mattermost implements INodeType { // If it does not have any items set remove it delete attachment.actions; } - } + }; } const util = require('util'); console.log('&&&&'); From 35d75df1f3b7f251377e82487739408abf4f0c1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 13:49:12 +0200 Subject: [PATCH 14/82] add10 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index e7071d7100..2fa678f98d 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1012,7 +1012,9 @@ export class Mattermost implements INodeType { // If it does not have any items set remove it delete attachment.fields; } - }; + } + } + for (const attachment of attachments) { if (attachment.actions !== undefined) { if (attachment.actions.item !== undefined) { // Move the field-content up @@ -1022,8 +1024,8 @@ export class Mattermost implements INodeType { // If it does not have any items set remove it delete attachment.actions; } - }; - } + } + } const util = require('util'); console.log('&&&&'); //console.dir(attachments); From 0ef256ca48710f5ae9a98c6eac7db309318aeb74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 14:00:30 +0200 Subject: [PATCH 15/82] add10a --- .../nodes-base/nodes/Mattermost/GenericFunctions.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Mattermost/GenericFunctions.ts b/packages/nodes-base/nodes/Mattermost/GenericFunctions.ts index bb08acdf76..8300014842 100644 --- a/packages/nodes-base/nodes/Mattermost/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Mattermost/GenericFunctions.ts @@ -8,11 +8,21 @@ import { OptionsWithUri } from 'request'; import { IDataObject } from 'n8n-workflow'; -export interface IAttachment { +/**export interface IAttachment { fields: { item?: object[]; }; } +*/ + +export interface IAttachment { + fields: { + item?: object[]; + }, + actions: { + item?: object[]; + }; +} /** From 8e190d24a573a4ee8bad5277e560893bb1322836 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sat, 11 Apr 2020 14:56:25 +0200 Subject: [PATCH 16/82] :zap: Small improvement to Zendesk-Node --- .../nodes/Zendesk/TicketDescription.ts | 217 ++++++------------ .../nodes-base/nodes/Zendesk/Zendesk.node.ts | 41 +--- 2 files changed, 78 insertions(+), 180 deletions(-) diff --git a/packages/nodes-base/nodes/Zendesk/TicketDescription.ts b/packages/nodes-base/nodes/Zendesk/TicketDescription.ts index f5daab6535..3bb3d41417 100644 --- a/packages/nodes-base/nodes/Zendesk/TicketDescription.ts +++ b/packages/nodes-base/nodes/Zendesk/TicketDescription.ts @@ -109,6 +109,41 @@ export const ticketFields = [ }, }, options: [ + { + displayName: 'Custom Fields', + name: 'customFieldsUi', + placeholder: 'Add Custom Field', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + options: [ + { + displayName: 'Custom Field', + name: 'customFieldsValues', + values: [ + { + displayName: 'ID', + name: 'id', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCustomFields', + }, + default: '', + description: 'Custom field ID', + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + description: 'Custom field Value.', + }, + ], + }, + ], + }, { displayName: 'External ID', name: 'externalId', @@ -206,54 +241,6 @@ export const ticketFields = [ }, ], }, - { - displayName: 'Custom Fields', - name: 'customFieldsUi', - placeholder: 'Add Custom Field', - type: 'fixedCollection', - typeOptions: { - multipleValues: true, - }, - displayOptions: { - show: { - resource: [ - 'ticket', - ], - operation: [ - 'create', - ], - jsonParameters: [ - false, - ], - }, - }, - default: {}, - options: [ - { - displayName: 'Custom Field', - name: 'customFieldsValues', - values: [ - { - displayName: 'ID', - name: 'id', - type: 'options', - typeOptions: { - loadOptionsMethod: 'getCustomFields', - }, - default: '', - description: 'Custom field ID', - }, - { - displayName: 'Value', - name: 'value', - type: 'string', - default: '', - description: 'Custom field Value.', - }, - ], - }, - ], - }, { displayName: ' Additional Fields', name: 'additionalFieldsJson', @@ -275,30 +262,9 @@ export const ticketFields = [ ], }, }, + description: `Object of values to set as described here.`, }, - { - displayName: ' Custom Fields', - name: 'customFieldsJson', - type: 'json', - typeOptions: { - alwaysOpenEditWindow: true, - }, - default: '', - displayOptions: { - show: { - resource: [ - 'ticket', - ], - operation: [ - 'create', - ], - jsonParameters: [ - true, - ], - }, - }, - description: `Array of customs fields Details`, - }, + /* -------------------------------------------------------------------------- */ /* ticket:update */ /* -------------------------------------------------------------------------- */ @@ -357,6 +323,41 @@ export const ticketFields = [ }, }, options: [ + { + displayName: 'Custom Fields', + name: 'customFieldsUi', + placeholder: 'Add Custom Field', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + options: [ + { + displayName: 'Custom Field', + name: 'customFieldsValues', + values: [ + { + displayName: 'ID', + name: 'id', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getCustomFields', + }, + default: '', + description: 'Custom field ID', + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + description: 'Custom field Value.', + }, + ], + }, + ], + }, { displayName: 'External ID', name: 'externalId', @@ -454,54 +455,6 @@ export const ticketFields = [ }, ], }, - { - displayName: 'Custom Fields', - name: 'customFieldsUi', - placeholder: 'Add Custom Field', - type: 'fixedCollection', - typeOptions: { - multipleValues: true, - }, - displayOptions: { - show: { - resource: [ - 'ticket', - ], - operation: [ - 'update', - ], - jsonParameters: [ - false, - ], - }, - }, - default: {}, - options: [ - { - displayName: 'Custom Field', - name: 'customFieldsValues', - values: [ - { - displayName: 'ID', - name: 'id', - type: 'options', - typeOptions: { - loadOptionsMethod: 'getCustomFields', - }, - default: '', - description: 'Custom field ID', - }, - { - displayName: 'Value', - name: 'value', - type: 'string', - default: '', - description: 'Custom field Value.', - }, - ], - }, - ], - }, { displayName: ' Update Fields', name: 'updateFieldsJson', @@ -523,31 +476,9 @@ export const ticketFields = [ ], }, }, + description: `Object of values to update as described here.`, }, - { - displayName: ' Custom Fields', - name: 'customFieldsJson', - type: 'json', - typeOptions: { - alwaysOpenEditWindow: true, - }, - default: '', - displayOptions: { - show: { - resource: [ - 'ticket', - ], - operation: [ - 'update', - ], - jsonParameters: [ - true, - ], - }, - }, - required: true, - description: `Array of customs fields Details`, - }, + /* -------------------------------------------------------------------------- */ /* ticket:get */ /* -------------------------------------------------------------------------- */ diff --git a/packages/nodes-base/nodes/Zendesk/Zendesk.node.ts b/packages/nodes-base/nodes/Zendesk/Zendesk.node.ts index a64feb9ca5..8a2586d8d8 100644 --- a/packages/nodes-base/nodes/Zendesk/Zendesk.node.ts +++ b/packages/nodes-base/nodes/Zendesk/Zendesk.node.ts @@ -167,20 +167,6 @@ export class Zendesk implements INodeType { comment, }; if (jsonParameters) { - - const customFieldsJson = this.getNodeParameter('customFieldsJson', i) as string; - - if (customFieldsJson !== '' ) { - - if (validateJSON(customFieldsJson) !== undefined) { - - body.custom_fields = JSON.parse(customFieldsJson); - - } else { - throw new Error('Custom fields must be a valid JSON'); - } - } - const additionalFieldsJson = this.getNodeParameter('additionalFieldsJson', i) as string; if (additionalFieldsJson !== '' ) { @@ -194,13 +180,10 @@ export class Zendesk implements INodeType { } } - } else { const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; - const customFields = (this.getNodeParameter('customFieldsUi', i) as IDataObject).customFieldsValues as IDataObject[]; - if (additionalFields.type) { body.type = additionalFields.type as string; } @@ -222,8 +205,8 @@ export class Zendesk implements INodeType { if (additionalFields.tags) { body.tags = additionalFields.tags as string[]; } - if (customFields) { - body.custom_fields = customFields; + if (additionalFields.customFieldsUi) { + body.custom_fields = (additionalFields.customFieldsUi as IDataObject).customFieldsValues as IDataObject[]; } } responseData = await zendeskApiRequest.call(this, 'POST', '/tickets', { ticket: body }); @@ -236,20 +219,6 @@ export class Zendesk implements INodeType { const body: ITicket = {}; if (jsonParameters) { - - const customFieldsJson = this.getNodeParameter('customFieldsJson', i) as string; - - if (customFieldsJson !== '' ) { - - if (validateJSON(customFieldsJson) !== undefined) { - - body.custom_fields = JSON.parse(customFieldsJson); - - } else { - throw new Error('Custom fields must be a valid JSON'); - } - } - const updateFieldsJson = this.getNodeParameter('updateFieldsJson', i) as string; if (updateFieldsJson !== '' ) { @@ -267,8 +236,6 @@ export class Zendesk implements INodeType { const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; - const customFields = (this.getNodeParameter('customFieldsUi', i) as IDataObject).customFieldsValues as IDataObject[]; - if (updateFields.type) { body.type = updateFields.type as string; } @@ -290,8 +257,8 @@ export class Zendesk implements INodeType { if (updateFields.tags) { body.tags = updateFields.tags as string[]; } - if (customFields) { - body.custom_fields = customFields; + if (updateFields.customFieldsUi) { + body.custom_fields = (updateFields.customFieldsUi as IDataObject).customFieldsValues as IDataObject[]; } } responseData = await zendeskApiRequest.call(this, 'PUT', `/tickets/${ticketId}`, { ticket: body }); From be62e9405171aeaa75d4b160bc373b3a4b020070 Mon Sep 17 00:00:00 2001 From: Krzysztof Janda Date: Sat, 11 Apr 2020 17:06:57 +0200 Subject: [PATCH 17/82] Fix default resource value --- packages/nodes-base/nodes/Cockpit/Cockpit.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Cockpit/Cockpit.node.ts b/packages/nodes-base/nodes/Cockpit/Cockpit.node.ts index bac4b2213f..b0961fd1e7 100644 --- a/packages/nodes-base/nodes/Cockpit/Cockpit.node.ts +++ b/packages/nodes-base/nodes/Cockpit/Cockpit.node.ts @@ -56,7 +56,7 @@ export class Cockpit implements INodeType { displayName: 'Resource', name: 'resource', type: 'options', - default: 'collections', + default: 'collection', description: 'Resource to consume.', options: [ { From c99910750fae7792a420b21af68672c71a57a8e3 Mon Sep 17 00:00:00 2001 From: Krzysztof Janda Date: Sat, 11 Apr 2020 17:07:14 +0200 Subject: [PATCH 18/82] Simplify if condition --- packages/nodes-base/nodes/Cockpit/Cockpit.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Cockpit/Cockpit.node.ts b/packages/nodes-base/nodes/Cockpit/Cockpit.node.ts index b0961fd1e7..076c0e8ebf 100644 --- a/packages/nodes-base/nodes/Cockpit/Cockpit.node.ts +++ b/packages/nodes-base/nodes/Cockpit/Cockpit.node.ts @@ -131,7 +131,7 @@ export class Cockpit implements INodeType { const options = this.getNodeParameter('options', i) as IDataObject; const returnAll = this.getNodeParameter('returnAll', i) as boolean; - if (returnAll !== true) { + if (!returnAll) { options.limit = this.getNodeParameter('limit', i) as number; } From fe3cca5344a18b73ffc326bbd33ac67229f1184f Mon Sep 17 00:00:00 2001 From: Krzysztof Janda Date: Sat, 11 Apr 2020 20:24:51 +0200 Subject: [PATCH 19/82] Add data fields to collections --- .../nodes/Cockpit/CollectionDescription.ts | 111 +++++++++++++----- .../nodes/Cockpit/CollectionFunctions.ts | 2 +- 2 files changed, 80 insertions(+), 33 deletions(-) diff --git a/packages/nodes-base/nodes/Cockpit/CollectionDescription.ts b/packages/nodes-base/nodes/Cockpit/CollectionDescription.ts index e448ce670e..24873a3c87 100644 --- a/packages/nodes-base/nodes/Cockpit/CollectionDescription.ts +++ b/packages/nodes-base/nodes/Cockpit/CollectionDescription.ts @@ -54,29 +54,6 @@ export const collectionFields = [ description: 'Name of the collection to operate on.' }, - // Collection:entry:create - { - displayName: 'Data', - name: 'data', - type: 'json', - required: true, - default: '', - typeOptions: { - alwaysOpenEditWindow: true, - }, - displayOptions: { - show: { - resource: [ - 'collection', - ], - operation: [ - 'create', - ] - }, - }, - description: 'The data to create.', - }, - // Collection:entry:getAll { displayName: 'Return All', @@ -214,25 +191,95 @@ export const collectionFields = [ }, description: 'The entry ID.', }, + + // Collection:entry:create + // Collection:entry:update { - displayName: 'Data', - name: 'data', - type: 'json', - required: true, - default: '', - typeOptions: { - alwaysOpenEditWindow: true, - }, + displayName: 'JSON Data fields', + name: 'jsonDataFields', + type: 'boolean', + default: false, displayOptions: { show: { resource: [ 'collection', ], operation: [ + 'create', 'update', ] }, }, - description: 'The data to update.', + description: 'If new entry fields should be set via the value-key pair UI or JSON.', + }, + { + displayName: 'Data fields', + name: 'dataFieldsJson', + type: 'json', + default: '', + typeOptions: { + alwaysOpenEditWindow: true, + }, + displayOptions: { + show: { + jsonDataFields: [ + true, + ], + resource: [ + 'collection', + ], + operation: [ + 'create', + 'update', + ] + }, + }, + description: 'Data to send as JSON.', + }, + { + displayName: 'Data fields', + name: 'dataFieldsUi', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + displayOptions: { + show: { + jsonDataFields: [ + false, + ], + resource: [ + 'collection', + ], + operation: [ + 'create', + 'update', + ] + }, + }, + options: [ + { + displayName: 'Field', + name: 'field', + values: [ + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'Name of the field.', + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + description: 'Value of the field.', + }, + ], + }, + ], + description: 'Data field to send.', }, ] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Cockpit/CollectionFunctions.ts b/packages/nodes-base/nodes/Cockpit/CollectionFunctions.ts index 4a2c640f84..344b483407 100644 --- a/packages/nodes-base/nodes/Cockpit/CollectionFunctions.ts +++ b/packages/nodes-base/nodes/Cockpit/CollectionFunctions.ts @@ -9,7 +9,7 @@ import { cockpitApiRequest } from './GenericFunctions'; export async function createCollectionEntry(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, resourceName: string, data: IDataObject, id?: string): Promise { // tslint:disable-line:no-any const body: ICollection = { - data: JSON.parse(data.toString()) + data, }; if (id) { From 348afdaf5ce7cdb42e90e81e76be4120aef4d82b Mon Sep 17 00:00:00 2001 From: Krzysztof Janda Date: Sat, 11 Apr 2020 20:24:58 +0200 Subject: [PATCH 20/82] Add data fields to forms --- .../nodes/Cockpit/FormDescription.ts | 75 ++++++++++++++++++- .../nodes-base/nodes/Cockpit/FormFunctions.ts | 2 +- 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/packages/nodes-base/nodes/Cockpit/FormDescription.ts b/packages/nodes-base/nodes/Cockpit/FormDescription.ts index 8488cbe095..78f77ba548 100644 --- a/packages/nodes-base/nodes/Cockpit/FormDescription.ts +++ b/packages/nodes-base/nodes/Cockpit/FormDescription.ts @@ -44,21 +44,88 @@ export const formFields = [ // Form:submit { - displayName: 'Form data', - name: 'form', + displayName: 'JSON Data fields', + name: 'jsonDataFields', + type: 'boolean', + default: false, + displayOptions: { + show: { + resource: [ + 'form', + ], + operation: [ + 'submit', + ] + }, + }, + description: 'If form fields should be set via the value-key pair UI or JSON.', + }, + { + displayName: 'Form fields', + name: 'dataFieldsJson', type: 'json', - required: true, default: '', typeOptions: { alwaysOpenEditWindow: true, }, displayOptions: { show: { + jsonDataFields: [ + true, + ], resource: [ 'form', ], + operation: [ + 'submit', + ] }, }, - description: 'The data to save.', + description: 'Form to send as JSON.', + }, + { + displayName: 'Data fields', + name: 'dataFieldsUi', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + displayOptions: { + show: { + jsonDataFields: [ + false, + ], + resource: [ + 'form', + ], + operation: [ + 'submit', + ] + }, + }, + options: [ + { + displayName: 'Field', + name: 'field', + values: [ + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'Name of the field.', + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + description: 'Value of the field.', + }, + ], + }, + ], + description: 'Form field to send.', }, ] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Cockpit/FormFunctions.ts b/packages/nodes-base/nodes/Cockpit/FormFunctions.ts index 437ed210a0..36a1bdc389 100644 --- a/packages/nodes-base/nodes/Cockpit/FormFunctions.ts +++ b/packages/nodes-base/nodes/Cockpit/FormFunctions.ts @@ -9,7 +9,7 @@ import { cockpitApiRequest } from './GenericFunctions'; export async function submitForm(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, resourceName: string, form: IDataObject) { const body: IForm = { - form: JSON.parse(form.toString()) + form }; return cockpitApiRequest.call(this, 'post', `/forms/submit/${resourceName}`, body); From 5d2f2ff4936894fb11df417f118cb73a7841e261 Mon Sep 17 00:00:00 2001 From: Krzysztof Janda Date: Sat, 11 Apr 2020 20:25:20 +0200 Subject: [PATCH 21/82] Add method to create data from parameters --- .../nodes/Cockpit/GenericFunctions.ts | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/packages/nodes-base/nodes/Cockpit/GenericFunctions.ts b/packages/nodes-base/nodes/Cockpit/GenericFunctions.ts index ed923d3bda..8db5c5b7ad 100644 --- a/packages/nodes-base/nodes/Cockpit/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Cockpit/GenericFunctions.ts @@ -44,3 +44,29 @@ export async function cockpitApiRequest(this: IExecuteFunctions | IExecuteSingle throw new Error(`Cockpit error [${error.statusCode}]: ` + errorMessage); } } + +export function createDataFromParameters(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, itemIndex: number): IDataObject { + const dataFieldsAreJson = this.getNodeParameter('jsonDataFields', itemIndex) as boolean; + + if (dataFieldsAreJson) { + // Parameters are defined as JSON + return JSON.parse(this.getNodeParameter('dataFieldsJson', itemIndex, {}) as string); + } + + // Parameters are defined in UI + return unpackUiDataFields(this.getNodeParameter('dataFieldsUi', itemIndex, {}) as IDataObject); +} + +function unpackUiDataFields(uiDataFields: IDataObject): IDataObject { + const unpacked: IDataObject = {}; + + if (uiDataFields.field === undefined) { + return unpacked; + } + + for (const field of uiDataFields!.field as IDataObject[]) { + unpacked[field!.name as string] = field!.value; + } + + return unpacked; +} From 294a9ea599e17dc560d9c65b6e94f8cefb7341bb Mon Sep 17 00:00:00 2001 From: Krzysztof Janda Date: Sat, 11 Apr 2020 20:26:15 +0200 Subject: [PATCH 22/82] Add new fields to the node --- packages/nodes-base/nodes/Cockpit/Cockpit.node.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/nodes-base/nodes/Cockpit/Cockpit.node.ts b/packages/nodes-base/nodes/Cockpit/Cockpit.node.ts index 076c0e8ebf..efd233f749 100644 --- a/packages/nodes-base/nodes/Cockpit/Cockpit.node.ts +++ b/packages/nodes-base/nodes/Cockpit/Cockpit.node.ts @@ -21,6 +21,7 @@ import { formOperations } from './FormDescription'; import { submitForm } from './FormFunctions'; +import { createDataFromParameters } from './GenericFunctions'; import { singletonFields, singletonOperations, @@ -74,7 +75,6 @@ export class Cockpit implements INodeType { ], }, - ...collectionOperations, ...collectionFields, ...formOperations, @@ -84,7 +84,6 @@ export class Cockpit implements INodeType { ], }; - methods = { loadOptions: { async getCollections(this: ILoadOptionsFunctions): Promise { @@ -123,8 +122,9 @@ export class Cockpit implements INodeType { for (let i = 0; i < length; i++) { if (resource === 'collection') { const collectionName = this.getNodeParameter('collection', i) as string; + if (operation === 'create') { - const data = this.getNodeParameter('data', i) as IDataObject; + const data = createDataFromParameters.call(this, i); responseData = await createCollectionEntry.call(this, collectionName, data); } else if (operation === 'getAll') { @@ -138,19 +138,21 @@ export class Cockpit implements INodeType { responseData = await getAllCollectionEntries.call(this, collectionName, options); } else if (operation === 'update') { const id = this.getNodeParameter('id', i) as string; - const data = this.getNodeParameter('data', i) as IDataObject; + const data = createDataFromParameters.call(this, i); responseData = await createCollectionEntry.call(this, collectionName, data, id); } } else if (resource === 'form') { const formName = this.getNodeParameter('form', i) as string; + if (operation === 'submit') { - const form = this.getNodeParameter('form', i) as IDataObject; + const form = createDataFromParameters.call(this, i); responseData = await submitForm.call(this, formName, form); } } else if (resource === 'singleton') { const singletonName = this.getNodeParameter('singleton', i) as string; + if (operation === 'get') { responseData = await getSingleton.call(this, singletonName); } From 532b9a929447348b1b2390823e701ebd77e09ae6 Mon Sep 17 00:00:00 2001 From: Krzysztof Janda Date: Sat, 11 Apr 2020 20:30:28 +0200 Subject: [PATCH 23/82] Simplify convert method --- packages/nodes-base/nodes/Cockpit/GenericFunctions.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/nodes-base/nodes/Cockpit/GenericFunctions.ts b/packages/nodes-base/nodes/Cockpit/GenericFunctions.ts index 8db5c5b7ad..3f3bf39ac2 100644 --- a/packages/nodes-base/nodes/Cockpit/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Cockpit/GenericFunctions.ts @@ -54,10 +54,7 @@ export function createDataFromParameters(this: IExecuteFunctions | IExecuteSingl } // Parameters are defined in UI - return unpackUiDataFields(this.getNodeParameter('dataFieldsUi', itemIndex, {}) as IDataObject); -} - -function unpackUiDataFields(uiDataFields: IDataObject): IDataObject { + const uiDataFields = this.getNodeParameter('dataFieldsUi', itemIndex, {}) as IDataObject; const unpacked: IDataObject = {}; if (uiDataFields.field === undefined) { From 101b884a2cd914d3faee124dfc0cb5d5856c3773 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 20:55:12 +0200 Subject: [PATCH 24/82] add11 --- .../nodes/Mattermost/Mattermost.node.ts | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 2fa678f98d..1359a4ca1c 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1032,8 +1032,34 @@ export class Mattermost implements INodeType { console.log(util.inspect(attachments, false, null, true /* enable colors */)); console.log('&&&&'); + var arr = attachments; + + for (const att of arr) { + if (Array.isArray(att.actions)) + for (const attaction of att.actions) { + //console.log(attaction); + if (attaction.integrations.item !== undefined) { + //console.log('integrations items'); + attaction.integrations = attaction.integrations.item; + for (const attactioninteg of attaction.integrations) { + //console.log(attactioninteg); + if (attactioninteg.context.conproperty !== undefined) { + //console.log('connnnnn'); + var tmpcontex = {}; + for (const attactionintegprop of attactioninteg.context.conproperty ) { + console.log(attactionintegprop); + tmpcontex[attactionintegprop.name] = attactionintegprop.value; + } + delete attactioninteg.context ; + attactioninteg.context = tmpcontex ; + } + } + } + } + } + body.props = { - attachments, + arr, }; //console.log('####'); From deae29647a0535ef3847b25aa027890010d0ea83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 20:59:33 +0200 Subject: [PATCH 25/82] a13 clean --- packages/nodes-base/nodes/Mattermost/GenericFunctions.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/GenericFunctions.ts b/packages/nodes-base/nodes/Mattermost/GenericFunctions.ts index 8300014842..ac712e1d66 100644 --- a/packages/nodes-base/nodes/Mattermost/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Mattermost/GenericFunctions.ts @@ -7,14 +7,6 @@ import { import { OptionsWithUri } from 'request'; import { IDataObject } from 'n8n-workflow'; - -/**export interface IAttachment { - fields: { - item?: object[]; - }; -} -*/ - export interface IAttachment { fields: { item?: object[]; @@ -24,7 +16,6 @@ export interface IAttachment { }; } - /** * Make an API request to Telegram * From 16082c6231ae10f71686fd4510d78e554ed339ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 22:43:35 +0200 Subject: [PATCH 26/82] add101 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 1359a4ca1c..09c339fa83 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1031,7 +1031,7 @@ export class Mattermost implements INodeType { //console.dir(attachments); console.log(util.inspect(attachments, false, null, true /* enable colors */)); console.log('&&&&'); - + /* var arr = attachments; for (const att of arr) { @@ -1057,9 +1057,9 @@ export class Mattermost implements INodeType { } } } - + */ body.props = { - arr, + attachments, }; //console.log('####'); From 69b4cc179eae32a50eb50a5296f7b8fbe696b5ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 22:59:39 +0200 Subject: [PATCH 27/82] a102 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 09c339fa83..3bc2dc0ccc 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1031,7 +1031,7 @@ export class Mattermost implements INodeType { //console.dir(attachments); console.log(util.inspect(attachments, false, null, true /* enable colors */)); console.log('&&&&'); - /* + var arr = attachments; for (const att of arr) { @@ -1057,7 +1057,7 @@ export class Mattermost implements INodeType { } } } - */ + body.props = { attachments, }; From 45700e4768dcf719799e088d8e0161de8a104dcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 23:00:04 +0200 Subject: [PATCH 28/82] a102a --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 3bc2dc0ccc..2e4e7e262f 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1056,7 +1056,7 @@ export class Mattermost implements INodeType { } } } - } + }; body.props = { attachments, From c3ee82fffd98c93db4456b437e95e738d8fa8d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sat, 11 Apr 2020 23:47:00 +0200 Subject: [PATCH 29/82] a103 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 2e4e7e262f..931da7edca 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1047,8 +1047,8 @@ export class Mattermost implements INodeType { //console.log('connnnnn'); var tmpcontex = {}; for (const attactionintegprop of attactioninteg.context.conproperty ) { - console.log(attactionintegprop); - tmpcontex[attactionintegprop.name] = attactionintegprop.value; + // console.log(attactionintegprop); + Object.assign(tmpcontex, { [attactionintegprop.name] : attactionintegprop.value } ); } delete attactioninteg.context ; attactioninteg.context = tmpcontex ; From f26b262d3a47b73909238c7c5e923346ac5fbaae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sun, 12 Apr 2020 00:15:30 +0200 Subject: [PATCH 30/82] add105 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 931da7edca..e1571c88e0 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1059,7 +1059,7 @@ export class Mattermost implements INodeType { }; body.props = { - attachments, + arr, }; //console.log('####'); From b7e4a12106c523128356004b728f27529f6b2068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sun, 12 Apr 2020 00:16:40 +0200 Subject: [PATCH 31/82] add106 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index e1571c88e0..1d94db762d 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -633,7 +633,7 @@ export class Mattermost implements INodeType { default: {}, options: [ { - name: 'property', + name: 'conproperty', displayName: 'Property', default: {}, values: [ From fef33ce9e7453060ee998a3deeb58d942e6a7293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sun, 12 Apr 2020 00:38:02 +0200 Subject: [PATCH 32/82] add107 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 1d94db762d..4911fd75a3 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1059,7 +1059,7 @@ export class Mattermost implements INodeType { }; body.props = { - arr, + arr[0], }; //console.log('####'); From 22aac3fe796d7255fa3c0be59352124bd3116337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sun, 12 Apr 2020 01:00:14 +0200 Subject: [PATCH 33/82] a120 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 4911fd75a3..0844476c47 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1020,6 +1020,7 @@ export class Mattermost implements INodeType { // Move the field-content up // @ts-ignore attachment.actions = attachment.actions.item; + console.log(attachment.actions.integrations.item[0].url ); } else { // If it does not have any items set remove it delete attachment.actions; @@ -1059,7 +1060,7 @@ export class Mattermost implements INodeType { }; body.props = { - arr[0], + attachments, }; //console.log('####'); From ef26a4bfe5690d0f9531e09a0104dba01ec5a748 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sun, 12 Apr 2020 12:28:36 +0200 Subject: [PATCH 34/82] :zap: Small improvement to Cockpit-Node --- .../nodes/Cockpit/CollectionDescription.ts | 29 ++++++++++--------- .../nodes/Cockpit/CollectionFunctions.ts | 11 ++++++- .../nodes/Cockpit/FormDescription.ts | 10 +++---- .../nodes/Cockpit/SingletonDescription.ts | 2 +- 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/packages/nodes-base/nodes/Cockpit/CollectionDescription.ts b/packages/nodes-base/nodes/Cockpit/CollectionDescription.ts index 24873a3c87..92420c2570 100644 --- a/packages/nodes-base/nodes/Cockpit/CollectionDescription.ts +++ b/packages/nodes-base/nodes/Cockpit/CollectionDescription.ts @@ -14,17 +14,17 @@ export const collectionOperations = [ }, options: [ { - name: 'Create an entry', + name: 'Create an Entry', value: 'create', description: 'Create a collection entry', }, { - name: 'Get all entries', + name: 'Get all Entries', value: 'getAll', description: 'Get all collection entries', }, { - name: 'Update an entry', + name: 'Update an Entry', value: 'update', description: 'Update a collection entries', }, @@ -116,22 +116,24 @@ export const collectionFields = [ { displayName: 'Fields', name: 'fields', - type: 'json', + type: 'string', default: '', typeOptions: { alwaysOpenEditWindow: true, }, - description: 'Fields to get.', + placeholder: '_id,name', + description: 'Comma separated list of fields to get.', }, { - displayName: 'Filter', + displayName: 'Filter Query', name: 'filter', type: 'json', default: '', typeOptions: { alwaysOpenEditWindow: true, }, - description: 'Filter result by fields.', + placeholder: '{"name": "Jim"}', + description: 'Filter query in Mongolite format.', }, { displayName: 'Language', @@ -163,11 +165,12 @@ export const collectionFields = [ description: 'Skip number of entries.', }, { - displayName: 'Sort', + displayName: 'Sort Query', name: 'sort', type: 'json', default: '', - description: 'Sort result by fields.', + placeholder: '{"price": -1}', + description: 'Sort query in Mongolite format.', }, ], }, @@ -213,7 +216,7 @@ export const collectionFields = [ description: 'If new entry fields should be set via the value-key pair UI or JSON.', }, { - displayName: 'Data fields', + displayName: 'Entry Data', name: 'dataFieldsJson', type: 'json', default: '', @@ -234,10 +237,10 @@ export const collectionFields = [ ] }, }, - description: 'Data to send as JSON.', + description: 'Entry data to send as JSON.', }, { - displayName: 'Data fields', + displayName: 'Entry Data', name: 'dataFieldsUi', type: 'fixedCollection', typeOptions: { @@ -280,6 +283,6 @@ export const collectionFields = [ ], }, ], - description: 'Data field to send.', + description: 'Entry data to send.', }, ] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Cockpit/CollectionFunctions.ts b/packages/nodes-base/nodes/Cockpit/CollectionFunctions.ts index 344b483407..d508629840 100644 --- a/packages/nodes-base/nodes/Cockpit/CollectionFunctions.ts +++ b/packages/nodes-base/nodes/Cockpit/CollectionFunctions.ts @@ -27,7 +27,16 @@ export async function getAllCollectionEntries(this: IExecuteFunctions | IExecute const body: ICollection = {}; if (options.fields) { - body.fields = JSON.parse(options.fields.toString()); + const fields = (options.fields as string).split(',').map(field => field.trim() ); + + const bodyFields = { + _id: false, + } as IDataObject; + for (const field of fields) { + bodyFields[field] = true; + } + + body.fields = bodyFields; } if (options.filter) { diff --git a/packages/nodes-base/nodes/Cockpit/FormDescription.ts b/packages/nodes-base/nodes/Cockpit/FormDescription.ts index 78f77ba548..66a5c052ec 100644 --- a/packages/nodes-base/nodes/Cockpit/FormDescription.ts +++ b/packages/nodes-base/nodes/Cockpit/FormDescription.ts @@ -14,7 +14,7 @@ export const formOperations = [ }, options: [ { - name: 'Submit a form', + name: 'Submit a Form', value: 'submit', description: 'Store submission of a form', }, @@ -61,7 +61,7 @@ export const formFields = [ description: 'If form fields should be set via the value-key pair UI or JSON.', }, { - displayName: 'Form fields', + displayName: 'Form Data', name: 'dataFieldsJson', type: 'json', default: '', @@ -81,10 +81,10 @@ export const formFields = [ ] }, }, - description: 'Form to send as JSON.', + description: 'Form data to send as JSON.', }, { - displayName: 'Data fields', + displayName: 'Form Data', name: 'dataFieldsUi', type: 'fixedCollection', typeOptions: { @@ -126,6 +126,6 @@ export const formFields = [ ], }, ], - description: 'Form field to send.', + description: 'Form data to send.', }, ] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Cockpit/SingletonDescription.ts b/packages/nodes-base/nodes/Cockpit/SingletonDescription.ts index e9774b4f5f..98df8a03d9 100644 --- a/packages/nodes-base/nodes/Cockpit/SingletonDescription.ts +++ b/packages/nodes-base/nodes/Cockpit/SingletonDescription.ts @@ -16,7 +16,7 @@ export const singletonOperations = [ { name: 'Get', value: 'get', - description: 'Gets a singleton', + description: 'Gets a Singleton', }, ], default: 'get', From d9864ad8c245d29e6ca308abe94ff22214fb2065 Mon Sep 17 00:00:00 2001 From: ricardo Date: Sun, 12 Apr 2020 11:58:49 -0400 Subject: [PATCH 35/82] :bug: Crashes when property value is null --- packages/nodes-base/nodes/SpreadsheetFile.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/SpreadsheetFile.node.ts b/packages/nodes-base/nodes/SpreadsheetFile.node.ts index ecac7db2cd..26310dfd2d 100644 --- a/packages/nodes-base/nodes/SpreadsheetFile.node.ts +++ b/packages/nodes-base/nodes/SpreadsheetFile.node.ts @@ -28,7 +28,7 @@ import { function flattenObject (data: IDataObject) { const returnData: IDataObject = {}; for (const key1 of Object.keys(data)) { - if ((typeof data[key1]) === 'object') { + if (data[key1] !== null && (typeof data[key1]) === 'object') { const flatObject = flattenObject(data[key1] as IDataObject); for (const key2 in flatObject) { if (flatObject[key2] === undefined) { From 09e528565fc2bece8f6c85773dfcf4da7180afce Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sun, 12 Apr 2020 18:42:29 +0200 Subject: [PATCH 36/82] :sparkles: Add $items to expression and Function-Nodes to get all items --- docs/node-basics.md | 6 +- docs/nodes.md | 24 +++- packages/workflow/src/Interfaces.ts | 1 + packages/workflow/src/WorkflowDataProxy.ts | 133 +++++++++++++-------- 4 files changed, 114 insertions(+), 50 deletions(-) diff --git a/docs/node-basics.md b/docs/node-basics.md index dae607fb82..0895565d86 100644 --- a/docs/node-basics.md +++ b/docs/node-basics.md @@ -48,11 +48,13 @@ the value would be: "My name is: Jim" The following special variables are available: - **$binary**: Incoming binary data of a node - - **$data**: Incoming JSON data of a node - **$evaluateExpression**: Evaluates a string as expression - **$env**: Environment variables - - **$node**: Data of other nodes (output-data, parameters) + - **$items**: Environment variables + - **$json**: Incoming JSON data of a node + - **$node**: Data of other nodes (context, output-data, parameters) - **$parameters**: Parameters of the current node + - **$workflow**: Returns workflow metadata like: active, id, name Normally it is not needed to write the JavaScript variables manually as they can be simply selected with the help of the Expression Editor. diff --git a/docs/nodes.md b/docs/nodes.md index a3b0fc7b2e..95d9105383 100644 --- a/docs/nodes.md +++ b/docs/nodes.md @@ -59,7 +59,7 @@ return newItems; ``` -#### Method: $item(index) +#### Method: $item(index: number) With `$item` it is possible to access the data of parent nodes. That can be the item data but also the parameters. It expects as input an index of the item the data should be returned for. This is @@ -88,6 +88,28 @@ const channel = $item(9).$node["Slack"].parameter["channel"]; ``` +#### Method: $items(nodeName?: string, outputIndex?: number, runIndex?: number) + +Gives access to all the items of current or parent nodes. If no parameters get supplied +it returns all the items of the current node. +If a node-name is given, it returns the items the give node did output. By default of the +first output (index: 0, most nodes only have one output, exceptions are IF and Switch-Node) +and the current run. + +Example: + +```typescript +// Returns all the items of the current node and current run +const allItems = $items(); + +// Returns all items the node "IF" outputs (index: 0 which is Output "true" of current run) +const allItems = $items("IF"); + +// Returns all items the node "IF" outputs (index: 1 which is Output "false" of run 0 which is the first one) +const allItems = $items("IF", 1, 0); +``` + + #### Variable: $node Works exactly like `$item` with the difference that it will always return the data of the first item. diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 2d0d92d835..45769bb290 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -534,6 +534,7 @@ export interface IWorkflowDataProxyData { $env: any; // tslint:disable-line:no-any $evaluateExpression: any; // tslint:disable-line:no-any $item: any; // tslint:disable-line:no-any + $items: any; // tslint:disable-line:no-any $json: any; // tslint:disable-line:no-any $node: any; // tslint:disable-line:no-any $parameter: any; // tslint:disable-line:no-any diff --git a/packages/workflow/src/WorkflowDataProxy.ts b/packages/workflow/src/WorkflowDataProxy.ts index 527b186196..edf9f264f7 100644 --- a/packages/workflow/src/WorkflowDataProxy.ts +++ b/packages/workflow/src/WorkflowDataProxy.ts @@ -104,6 +104,79 @@ export class WorkflowDataProxy { } + /** + * Returns the node ExecutionData + * + * @private + * @param {string} nodeName The name of the node query data from + * @param {boolean} [shortSyntax=false] If short syntax got used + * @param {number} [outputIndex] The index of the output, if not given the first one gets used + * @param {number} [runIndex] The index of the run, if not given the current one does get used + * @returns {INodeExecutionData[]} + * @memberof WorkflowDataProxy + */ + private getNodeExecutionData(nodeName: string, shortSyntax = false, outputIndex?: number, runIndex?: number): INodeExecutionData[] { + const that = this; + + let executionData: INodeExecutionData[]; + if (shortSyntax === false) { + // Long syntax got used to return data from node in path + + if (that.runExecutionData === null) { + throw new Error(`Workflow did not run so do not have any execution-data.`); + } + + if (!that.runExecutionData.resultData.runData.hasOwnProperty(nodeName)) { + throw new Error(`No execution data found for node "${nodeName}"`); + } + + runIndex = runIndex === undefined ? that.runIndex : 0; + + if (that.runExecutionData.resultData.runData[nodeName].length < runIndex) { + throw new Error(`No execution data found for run "${runIndex}" of node "${nodeName}"`); + } + + const taskData = that.runExecutionData.resultData.runData[nodeName][runIndex].data!; + + if (taskData.main === null || !taskData.main.length || taskData.main[0] === null) { + // throw new Error(`No data found for item-index: "${itemIndex}"`); + throw new Error(`No data found from "main" input.`); + } + + // Check from which output to read the data. + // Depends on how the nodes are connected. + // (example "IF" node. If node is connected to "true" or to "false" output) + if (outputIndex === undefined) { + const outputIndex = that.workflow.getNodeConnectionOutputIndex(that.activeNodeName, nodeName, 'main'); + + if (outputIndex === undefined) { + throw new Error(`The node "${that.activeNodeName}" is not connected with node "${nodeName}" so no data can get returned from it.`); + } + } + + if (outputIndex === undefined) { + outputIndex = 0; + } + + if (taskData.main.length < outputIndex) { + throw new Error(`No data found from "main" input with index "${outputIndex}" via which node is connected with.`); + } + + executionData = taskData.main[outputIndex] as INodeExecutionData[]; + } else { + // Short syntax got used to return data from active node + + // TODO: Here have to generate connection Input data for the current node by itself + // Data needed: + // #- the run-index + // - node which did send data (has to be the one from last recent execution) + // - later also the name of the input and its index (currently not needed as it is always "main" and index "0") + executionData = that.connectionInputData; + } + + return executionData; + } + /** * Returns a proxy which allows to query data of a given node @@ -128,53 +201,7 @@ export class WorkflowDataProxy { name = name.toString(); if (['binary', 'data', 'json'].includes(name)) { - let executionData: INodeExecutionData[]; - if (shortSyntax === false) { - // Long syntax got used to return data from node in path - - if (that.runExecutionData === null) { - throw new Error(`Workflow did not run so do not have any execution-data.`); - } - - if (!that.runExecutionData.resultData.runData.hasOwnProperty(nodeName)) { - throw new Error(`No execution data found for node "${nodeName}"`); - } - - if (that.runExecutionData.resultData.runData[nodeName].length < that.runIndex) { - throw new Error(`No execution data found for run "${that.runIndex}" of node "${nodeName}"`); - } - - const taskData = that.runExecutionData.resultData.runData[nodeName][that.runIndex].data!; - - if (taskData.main === null || !taskData.main.length || taskData.main[0] === null) { - // throw new Error(`No data found for item-index: "${itemIndex}"`); - throw new Error(`No data found from "main" input.`); - } - - // Check from which output to read the data. - // Depends on how the nodes are connected. - // (example "IF" node. If node is connected to "true" or to "false" output) - const outputIndex = that.workflow.getNodeConnectionOutputIndex(that.activeNodeName, nodeName, 'main'); - - if (outputIndex === undefined) { - throw new Error(`The node "${that.activeNodeName}" is not connected with node "${nodeName}" so no data can get returned from it.`); - } - - if (taskData.main.length < outputIndex) { - throw new Error(`No data found from "main" input with index "${outputIndex}" via which node is connected with.`); - } - - executionData = taskData.main[outputIndex] as INodeExecutionData[]; - } else { - // Short syntax got used to return data from active node - - // TODO: Here have to generate connection Input data for the current node by itself - // Data needed: - // #- the run-index - // - node which did send data (has to be the one from last recent execution) - // - later also the name of the input and its index (currently not needed as it is always "main" and index "0") - executionData = that.connectionInputData; - } + const executionData = that.getNodeExecutionData(name, shortSyntax); if (executionData.length <= that.itemIndex) { throw new Error(`No data found for item-index: "${that.itemIndex}"`); @@ -305,6 +332,18 @@ export class WorkflowDataProxy { const dataProxy = new WorkflowDataProxy(this.workflow, this.runExecutionData, this.runIndex, itemIndex, this.activeNodeName, this.connectionInputData); return dataProxy.getDataProxy(); }, + $items: (nodeName?: string, outputIndex?: number, runIndex?: number) => { + let executionData: INodeExecutionData[]; + + if (nodeName === undefined) { + executionData = that.connectionInputData; + } else { + outputIndex = outputIndex || 0; + executionData = that.getNodeExecutionData(nodeName, false, outputIndex, runIndex); + } + + return executionData; + }, $json: {}, // Placeholder $node: this.nodeGetter(), $parameter: this.nodeParameterGetter(this.activeNodeName), From e616ab236caee4f24175188bb4739282b03886ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sun, 12 Apr 2020 18:48:01 +0200 Subject: [PATCH 37/82] add121 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 0844476c47..39712fee37 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1059,6 +1059,13 @@ export class Mattermost implements INodeType { } }; + console.log('****111'); + console.log(JSON.stringify(arr, null, 4)); + onsole.log('****222'); + console.log(JSON.stringify(attachments, null, 4)); + onsole.log('****222aaa'); + + body.props = { attachments, }; From 59798ad0bde5566c8fa5d76b803fa1f733355c44 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sun, 12 Apr 2020 18:48:41 +0200 Subject: [PATCH 38/82] :zap: Do not allow that expressions return functions --- packages/workflow/src/Workflow.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/workflow/src/Workflow.ts b/packages/workflow/src/Workflow.ts index 816c009a1f..a3d069058d 100644 --- a/packages/workflow/src/Workflow.ts +++ b/packages/workflow/src/Workflow.ts @@ -906,7 +906,9 @@ export class Workflow { // Execute the expression try { const returnValue = tmpl.tmpl(parameterValue, data); - if (returnValue !== null && typeof returnValue === 'object') { + if (typeof returnValue === 'function') { + throw new Error('Expression resolved to a function. Please add "()"'); + } else if (returnValue !== null && typeof returnValue === 'object') { if (returnObjectAsString === true) { return this.convertObjectValueToString(returnValue); } From 2de3249cfb3bfea1486e20d0825d08517cde712a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sun, 12 Apr 2020 18:59:52 +0200 Subject: [PATCH 39/82] add125 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 39712fee37..faab0367c8 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1061,9 +1061,9 @@ export class Mattermost implements INodeType { console.log('****111'); console.log(JSON.stringify(arr, null, 4)); - onsole.log('****222'); + console.log('****222'); console.log(JSON.stringify(attachments, null, 4)); - onsole.log('****222aaa'); + console.log('****222aaa'); body.props = { From dc10f52db3eabfe27439903e6ca70f0471ac8cca Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sun, 12 Apr 2020 18:56:39 +0200 Subject: [PATCH 40/82] :bug: Fix bug --- packages/workflow/src/WorkflowDataProxy.ts | 4 ++-- packages/workflow/test/Workflow.test.ts | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/workflow/src/WorkflowDataProxy.ts b/packages/workflow/src/WorkflowDataProxy.ts index edf9f264f7..24c8cc860d 100644 --- a/packages/workflow/src/WorkflowDataProxy.ts +++ b/packages/workflow/src/WorkflowDataProxy.ts @@ -130,7 +130,7 @@ export class WorkflowDataProxy { throw new Error(`No execution data found for node "${nodeName}"`); } - runIndex = runIndex === undefined ? that.runIndex : 0; + runIndex = runIndex === undefined ? that.runIndex : runIndex; if (that.runExecutionData.resultData.runData[nodeName].length < runIndex) { throw new Error(`No execution data found for run "${runIndex}" of node "${nodeName}"`); @@ -201,7 +201,7 @@ export class WorkflowDataProxy { name = name.toString(); if (['binary', 'data', 'json'].includes(name)) { - const executionData = that.getNodeExecutionData(name, shortSyntax); + const executionData = that.getNodeExecutionData(nodeName, shortSyntax); if (executionData.length <= that.itemIndex) { throw new Error(`No data found for item-index: "${that.itemIndex}"`); diff --git a/packages/workflow/test/Workflow.test.ts b/packages/workflow/test/Workflow.test.ts index 09cc1b871a..00080e2771 100644 --- a/packages/workflow/test/Workflow.test.ts +++ b/packages/workflow/test/Workflow.test.ts @@ -1203,11 +1203,12 @@ describe('Workflow', () => { { startTime: 1, executionTime: 1, - // @ts-ignore data: { main: [ [ - {} + { + json: {}, + } ] ] } From 640db18ab642bfc05be4fdedb8484c89a328d70d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sun, 12 Apr 2020 19:12:11 +0200 Subject: [PATCH 41/82] a126 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index faab0367c8..109854d9bc 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1020,7 +1020,7 @@ export class Mattermost implements INodeType { // Move the field-content up // @ts-ignore attachment.actions = attachment.actions.item; - console.log(attachment.actions.integrations.item[0].url ); + console.log(attachment.actions ); } else { // If it does not have any items set remove it delete attachment.actions; From c7024ca454720daf15bb99780ea71c037a02e6cb Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sun, 12 Apr 2020 19:58:30 +0200 Subject: [PATCH 42/82] :sparkles: Add "alwaysOutputData" option to nodes --- packages/core/src/WorkflowExecute.ts | 11 +++++++++++ packages/editor-ui/src/components/NodeSettings.vue | 14 ++++++++++++++ packages/workflow/src/Interfaces.ts | 1 + 3 files changed, 26 insertions(+) diff --git a/packages/core/src/WorkflowExecute.ts b/packages/core/src/WorkflowExecute.ts index 1dfb599083..1e8b8898a7 100644 --- a/packages/core/src/WorkflowExecute.ts +++ b/packages/core/src/WorkflowExecute.ts @@ -596,6 +596,17 @@ export class WorkflowExecute { this.runExecutionData.resultData.lastNodeExecuted = executionData.node.name; nodeSuccessData = await workflow.runNode(executionData.node, executionData.data, this.runExecutionData, runIndex, this.additionalData, NodeExecuteFunctions, this.mode); + if (nodeSuccessData === null || nodeSuccessData[0][0] === undefined) { + if (executionData.node.alwaysOutputData === true) { + nodeSuccessData = nodeSuccessData || []; + nodeSuccessData[0] = [ + { + json: {}, + } + ]; + } + } + if (nodeSuccessData === null) { // If null gets returned it means that the node did succeed // but did not have any data. So the branch should end diff --git a/packages/editor-ui/src/components/NodeSettings.vue b/packages/editor-ui/src/components/NodeSettings.vue index 98c4069e5c..515eeccce5 100644 --- a/packages/editor-ui/src/components/NodeSettings.vue +++ b/packages/editor-ui/src/components/NodeSettings.vue @@ -141,6 +141,7 @@ export default mixins( nodeColor: null, nodeValues: { color: '#ff0000', + alwaysOutputData: false, continueOnFail: false, retryOnFail: false, maxTries: 3, @@ -169,6 +170,14 @@ export default mixins( noDataExpression: true, description: 'The color of the node in the flow.', }, + { + displayName: 'Always Output Data', + name: 'alwaysOutputData', + type: 'boolean', + default: false, + noDataExpression: true, + description: 'If activated and the node does not have any data for the first output,
it returns an empty item anyway. Be careful setting this on
IF-Nodes as it could easily cause an infinite loop.', + }, { displayName: 'Retry On Fail', name: 'retryOnFail', @@ -419,6 +428,11 @@ export default mixins( Vue.set(this.nodeValues, 'notes', this.node.notes); } + if (this.node.alwaysOutputData) { + foundNodeSettings.push('alwaysOutputData'); + Vue.set(this.nodeValues, 'alwaysOutputData', this.node.alwaysOutputData); + } + if (this.node.continueOnFail) { foundNodeSettings.push('continueOnFail'); Vue.set(this.nodeValues, 'continueOnFail', this.node.continueOnFail); diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 45769bb290..ad64dc160b 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -292,6 +292,7 @@ export interface INode { retryOnFail?: boolean; maxTries?: number; waitBetweenTries?: number; + alwaysOutputData?: boolean; continueOnFail?: boolean; parameters: INodeParameters; credentials?: INodeCredentials; From a2217274ab39ad44f18f04faa7d32864ed1db328 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sun, 12 Apr 2020 20:06:43 +0200 Subject: [PATCH 43/82] :bookmark: Release n8n-workflow@0.27.0 --- packages/workflow/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/workflow/package.json b/packages/workflow/package.json index d3a56dc2b2..0268d87d79 100644 --- a/packages/workflow/package.json +++ b/packages/workflow/package.json @@ -1,6 +1,6 @@ { "name": "n8n-workflow", - "version": "0.26.0", + "version": "0.27.0", "description": "Workflow base code of n8n", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", From d5613aad95e144756755d9785596dce3e40cd266 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sun, 12 Apr 2020 20:07:58 +0200 Subject: [PATCH 44/82] :arrow_up: Set n8n-workflow@0.27.0 on n8n-core --- packages/core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/package.json b/packages/core/package.json index bf6c408b92..b979bb3045 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -44,7 +44,7 @@ "crypto-js": "3.1.9-1", "lodash.get": "^4.4.2", "mmmagic": "^0.5.2", - "n8n-workflow": "~0.26.0", + "n8n-workflow": "~0.27.0", "p-cancelable": "^2.0.0", "request-promise-native": "^1.0.7" }, From 3ac39d6d40a4fd850a703855995fae1c40a10721 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sun, 12 Apr 2020 20:08:15 +0200 Subject: [PATCH 45/82] :bookmark: Release n8n-core@0.30.0 --- packages/core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/package.json b/packages/core/package.json index b979bb3045..d6619fd4a7 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "n8n-core", - "version": "0.29.0", + "version": "0.30.0", "description": "Core functionality of n8n", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", From 22737bceb944edab4cc422a46e24a681ef008bb3 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sun, 12 Apr 2020 20:09:05 +0200 Subject: [PATCH 46/82] :arrow_up: Set n8n-core@0.30.0 and n8n-workflow@0.27.0 on n8n-nodes-base --- packages/nodes-base/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 1f8b6625e7..90685d7ce5 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -266,7 +266,7 @@ "@types/xml2js": "^0.4.3", "gulp": "^4.0.0", "jest": "^24.9.0", - "n8n-workflow": "~0.26.0", + "n8n-workflow": "~0.27.0", "ts-jest": "^24.0.2", "tslint": "^5.17.0", "typescript": "~3.7.4" @@ -288,7 +288,7 @@ "lodash.unset": "^4.5.2", "mongodb": "^3.3.2", "mysql2": "^2.0.1", - "n8n-core": "~0.29.0", + "n8n-core": "~0.30.0", "nodemailer": "^5.1.1", "pdf-parse": "^1.1.1", "pg-promise": "^9.0.3", From dc5ffe4118a2a4875eaba8ae8a1a6711ac3dad8b Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sun, 12 Apr 2020 20:10:28 +0200 Subject: [PATCH 47/82] :bookmark: Release n8n-nodes-base@0.56.0 --- packages/nodes-base/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 90685d7ce5..6826e7a020 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -1,6 +1,6 @@ { "name": "n8n-nodes-base", - "version": "0.55.0", + "version": "0.56.0", "description": "Base nodes of n8n", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", From 41a6a53bf51386dd09954c84184ddb590cae8f38 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sun, 12 Apr 2020 20:11:30 +0200 Subject: [PATCH 48/82] :arrow_up: Set n8n-workflow@0.27.0 on n8n-editor-ui --- packages/editor-ui/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor-ui/package.json b/packages/editor-ui/package.json index 00d1fc38a8..188ee3c735 100644 --- a/packages/editor-ui/package.json +++ b/packages/editor-ui/package.json @@ -64,7 +64,7 @@ "lodash.debounce": "^4.0.8", "lodash.get": "^4.4.2", "lodash.set": "^4.3.2", - "n8n-workflow": "~0.26.0", + "n8n-workflow": "~0.27.0", "node-sass": "^4.12.0", "prismjs": "^1.17.1", "quill": "^2.0.0-dev.3", From b4dff3cdb8082ff533273ebe5b79d3ab37fa23e4 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sun, 12 Apr 2020 20:11:58 +0200 Subject: [PATCH 49/82] :bookmark: Release n8n-editor-ui@0.41.0 --- packages/editor-ui/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor-ui/package.json b/packages/editor-ui/package.json index 188ee3c735..47bfac7b15 100644 --- a/packages/editor-ui/package.json +++ b/packages/editor-ui/package.json @@ -1,6 +1,6 @@ { "name": "n8n-editor-ui", - "version": "0.40.0", + "version": "0.41.0", "description": "Workflow Editor UI for n8n", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", From bc0856a6d080a5f1e10fc1bf83ac5e2bfa4677d9 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sun, 12 Apr 2020 20:13:31 +0200 Subject: [PATCH 50/82] :arrow_up: Set n8n-core@0.30.0, n8n-editor-ui@0.41.0, n8n-nodes-base@0.56.0 and n8n-workflow@0.27.0 on n8n --- packages/cli/package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index aabfbb7f7a..443a29d2ea 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -95,10 +95,10 @@ "lodash.get": "^4.4.2", "mongodb": "^3.2.3", "mysql2": "^2.0.1", - "n8n-core": "~0.29.0", - "n8n-editor-ui": "~0.40.0", - "n8n-nodes-base": "~0.55.0", - "n8n-workflow": "~0.26.0", + "n8n-core": "~0.30.0", + "n8n-editor-ui": "~0.41.0", + "n8n-nodes-base": "~0.56.0", + "n8n-workflow": "~0.27.0", "open": "^7.0.0", "pg": "^7.11.0", "request-promise-native": "^1.0.7", From 3c819100d828bbe9f59301d85022f99243508b66 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Sun, 12 Apr 2020 20:14:51 +0200 Subject: [PATCH 51/82] :bookmark: Release n8n@0.61.0 --- packages/cli/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 443a29d2ea..db9b261d55 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "n8n", - "version": "0.60.0", + "version": "0.61.0", "description": "n8n Workflow Automation Tool", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", From 9aa75db1f246db7a9e64ea16dfb4f7e6681cd368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sun, 12 Apr 2020 20:32:47 +0200 Subject: [PATCH 52/82] add128 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 109854d9bc..4a1fb2bfa3 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -633,7 +633,7 @@ export class Mattermost implements INodeType { default: {}, options: [ { - name: 'conproperty', + name: 'property', displayName: 'Property', default: {}, values: [ @@ -1044,10 +1044,10 @@ export class Mattermost implements INodeType { attaction.integrations = attaction.integrations.item; for (const attactioninteg of attaction.integrations) { //console.log(attactioninteg); - if (attactioninteg.context.conproperty !== undefined) { + if (attactioninteg.context.property !== undefined) { //console.log('connnnnn'); var tmpcontex = {}; - for (const attactionintegprop of attactioninteg.context.conproperty ) { + for (const attactionintegprop of attactioninteg.context.property ) { // console.log(attactionintegprop); Object.assign(tmpcontex, { [attactionintegprop.name] : attactionintegprop.value } ); } From fe033dd08c6bfac726d55626a62d441e6af37afc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sun, 12 Apr 2020 20:52:37 +0200 Subject: [PATCH 53/82] add130 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 4a1fb2bfa3..0049a7f7cc 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1067,7 +1067,7 @@ export class Mattermost implements INodeType { body.props = { - attachments, + arr, }; //console.log('####'); From 8bc30b2ab4d316fa0bc3bd8e5f26800c0295c302 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sun, 12 Apr 2020 21:21:48 +0200 Subject: [PATCH 54/82] add 131 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 0049a7f7cc..01f1398334 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1033,7 +1033,7 @@ export class Mattermost implements INodeType { console.log(util.inspect(attachments, false, null, true /* enable colors */)); console.log('&&&&'); - var arr = attachments; + const arr = attachments; for (const att of arr) { if (Array.isArray(att.actions)) @@ -1067,7 +1067,7 @@ export class Mattermost implements INodeType { body.props = { - arr, + attachments, }; //console.log('####'); From 8c363d11441d1d0eac6890955cb21cdc8cd8df65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sun, 12 Apr 2020 21:58:08 +0200 Subject: [PATCH 55/82] add150 --- .../nodes/Mattermost/Mattermost.node.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 01f1398334..858c81782a 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -597,10 +597,10 @@ export class Mattermost implements INodeType { { - displayName: 'Integrations', - name: 'integrations', - placeholder: 'Add Integrations', - description: 'Integrations to add to message.', + displayName: 'Integration', + name: 'integration', + placeholder: 'Add Integration', + description: 'Integration to add to message.', type: 'fixedCollection', typeOptions: { multipleValues: true, @@ -1039,10 +1039,10 @@ export class Mattermost implements INodeType { if (Array.isArray(att.actions)) for (const attaction of att.actions) { //console.log(attaction); - if (attaction.integrations.item !== undefined) { - //console.log('integrations items'); - attaction.integrations = attaction.integrations.item; - for (const attactioninteg of attaction.integrations) { + if (attaction.integration.item !== undefined) { + //console.log('integration items'); + attaction.integration = attaction.integration.item; + for (const attactioninteg of attaction.integration) { //console.log(attactioninteg); if (attactioninteg.context.property !== undefined) { //console.log('connnnnn'); From 32c52b6ae8335a1f8df6d7f24465e68f0e5ed715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sun, 12 Apr 2020 23:23:58 +0200 Subject: [PATCH 56/82] add300 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 858c81782a..7b3377ea4f 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1042,6 +1042,7 @@ export class Mattermost implements INodeType { if (attaction.integration.item !== undefined) { //console.log('integration items'); attaction.integration = attaction.integration.item; + var tmpintegration = {}; for (const attactioninteg of attaction.integration) { //console.log(attactioninteg); if (attactioninteg.context.property !== undefined) { @@ -1054,7 +1055,10 @@ export class Mattermost implements INodeType { delete attactioninteg.context ; attactioninteg.context = tmpcontex ; } + Object.assign(tmpintegration, attactioninteg); } + delete attaction.integrations; + attaction.integrations=tmpintegration; } } }; From 176bda1999fb0a2ffb5740efe2b60667cb7b3482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Sun, 12 Apr 2020 23:47:25 +0200 Subject: [PATCH 57/82] add301 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 7b3377ea4f..c6be923af9 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1057,8 +1057,8 @@ export class Mattermost implements INodeType { } Object.assign(tmpintegration, attactioninteg); } - delete attaction.integrations; - attaction.integrations=tmpintegration; + delete attaction.integration; + attaction.integration=tmpintegration; } } }; From bf01944f0d84d6b9f843d5a0278dc4bb4ec1a2d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Mon, 13 Apr 2020 10:54:34 +0200 Subject: [PATCH 58/82] add305 --- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index c6be923af9..22874e8e1d 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -603,7 +603,7 @@ export class Mattermost implements INodeType { description: 'Integration to add to message.', type: 'fixedCollection', typeOptions: { - multipleValues: true, + multipleValues: false, }, default: {}, options: [ From 399397fbb741dbbd2011f07dca70e27b413768dd Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 13 Apr 2020 15:57:01 +0200 Subject: [PATCH 59/82] :zap: Improve how expressions get values --- docs/node-basics.md | 3 +- docs/nodes.md | 56 +++++++++++++++++++--- packages/workflow/src/WorkflowDataProxy.ts | 21 ++++++-- 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/docs/node-basics.md b/docs/node-basics.md index 0895565d86..f81fb6fcee 100644 --- a/docs/node-basics.md +++ b/docs/node-basics.md @@ -52,8 +52,9 @@ The following special variables are available: - **$env**: Environment variables - **$items**: Environment variables - **$json**: Incoming JSON data of a node - - **$node**: Data of other nodes (context, output-data, parameters) + - **$node**: Data of other nodes (binary, context, json, parameter, runIndex) - **$parameters**: Parameters of the current node + - **$runIndex**: The current run index (first time node gets executed it is 0, second time 1, ...) - **$workflow**: Returns workflow metadata like: active, id, name Normally it is not needed to write the JavaScript variables manually as they can be simply selected with the help of the Expression Editor. diff --git a/docs/nodes.md b/docs/nodes.md index 95d9105383..9a5e4b5773 100644 --- a/docs/nodes.md +++ b/docs/nodes.md @@ -59,7 +59,7 @@ return newItems; ``` -#### Method: $item(index: number) +#### Method: $item(index: number, runIndex?: number) With `$item` it is possible to access the data of parent nodes. That can be the item data but also the parameters. It expects as input an index of the item the data should be returned for. This is @@ -71,6 +71,12 @@ emails at once to different people. Instead, the same person would receive multi The index is 0 based. So `$item(0)` will return the first item, `$item(1)` the second one, ... +By default will the item of the last run of the node be returned. So if the referenced node did run +3x (its last runIndex is 2) and the current node runs the first time (its runIndex is 0) will the +data of runIndex 2 of the referenced node be returned. + +For more information about what data can be accessed via $node check [here](#variable-node). + Example: ```typescript @@ -92,9 +98,9 @@ const channel = $item(9).$node["Slack"].parameter["channel"]; Gives access to all the items of current or parent nodes. If no parameters get supplied it returns all the items of the current node. -If a node-name is given, it returns the items the give node did output. By default of the -first output (index: 0, most nodes only have one output, exceptions are IF and Switch-Node) -and the current run. +If a node-name is given, it returns the items the node did output on it`s first output +(index: 0, most nodes only have one output, exceptions are IF and Switch-Node) on +its last run. Example: @@ -102,22 +108,58 @@ Example: // Returns all the items of the current node and current run const allItems = $items(); -// Returns all items the node "IF" outputs (index: 0 which is Output "true" of current run) +// Returns all items the node "IF" outputs (index: 0 which is Output "true" of its most recent run) const allItems = $items("IF"); -// Returns all items the node "IF" outputs (index: 1 which is Output "false" of run 0 which is the first one) +// Returns all items the node "IF" outputs (index: 0 which is Output "true" of the same run as current node) +const allItems = $items("IF", 0, $runIndex); + +// Returns all items the node "IF" outputs (index: 1 which is Output "false" of run 0 which is the first run) const allItems = $items("IF", 1, 0); ``` #### Variable: $node -Works exactly like `$item` with the difference that it will always return the data of the first item. +Works exactly like `$item` with the difference that it will always return the data of the first item and +the last run of the node. ```typescript +// Returns the fileName of binary property "data" of Node "HTTP Request" +const fileName = $node["HTTP Request"].binary["data"]["fileName"]}} + +// Returns the context data "noItemsLeft" of Node "SplitInBatches" +const noItemsLeft = $node["SplitInBatches"].context["noItemsLeft"]; + +// Returns the value of the JSON data property "myNumber" of Node "Set" const myNumber = $node["Set"].json['myNumber']; +// Returns the value of the parameter "channel" of Node "Slack" const channel = $node["Slack"].parameter["channel"]; + +// Returns the index of the last run of Node "HTTP Request" +const runIndex = $node["HTTP Request"].runIndex}} +``` + + +#### Variable: $runIndex + +Contains the index of the current run of the node. + +```typescript +// Returns all items the node "IF" outputs (index: 0 which is Output "true" of the same run as current node) +const allItems = $items("IF", 0, $runIndex); +``` + + +#### Variable: $workflow + +Gives information about the current workflow. + +```typescript +const isActive = $workflow.active; +const workflowId = $workflow.id; +const workflowName = $workflow.name; ``` diff --git a/packages/workflow/src/WorkflowDataProxy.ts b/packages/workflow/src/WorkflowDataProxy.ts index 24c8cc860d..aa30470b1c 100644 --- a/packages/workflow/src/WorkflowDataProxy.ts +++ b/packages/workflow/src/WorkflowDataProxy.ts @@ -12,6 +12,7 @@ import { export class WorkflowDataProxy { private workflow: Workflow; private runExecutionData: IRunExecutionData | null; + private defaultReturnRunIndex: number; private runIndex: number; private itemIndex: number; private activeNodeName: string; @@ -19,9 +20,10 @@ export class WorkflowDataProxy { - constructor(workflow: Workflow, runExecutionData: IRunExecutionData | null, runIndex: number, itemIndex: number, activeNodeName: string, connectionInputData: INodeExecutionData[]) { + constructor(workflow: Workflow, runExecutionData: IRunExecutionData | null, runIndex: number, itemIndex: number, activeNodeName: string, connectionInputData: INodeExecutionData[], defaultReturnRunIndex = -1) { this.workflow = workflow; this.runExecutionData = runExecutionData; + this.defaultReturnRunIndex = defaultReturnRunIndex; this.runIndex = runIndex; this.itemIndex = itemIndex; this.activeNodeName = activeNodeName; @@ -130,7 +132,8 @@ export class WorkflowDataProxy { throw new Error(`No execution data found for node "${nodeName}"`); } - runIndex = runIndex === undefined ? that.runIndex : runIndex; + runIndex = runIndex === undefined ? that.defaultReturnRunIndex : runIndex; + runIndex = runIndex === -1 ? (that.runExecutionData.resultData.runData[nodeName].length -1) : runIndex; if (that.runExecutionData.resultData.runData[nodeName].length < runIndex) { throw new Error(`No execution data found for run "${runIndex}" of node "${nodeName}"`); @@ -201,7 +204,7 @@ export class WorkflowDataProxy { name = name.toString(); if (['binary', 'data', 'json'].includes(name)) { - const executionData = that.getNodeExecutionData(nodeName, shortSyntax); + const executionData = that.getNodeExecutionData(nodeName, shortSyntax, undefined); if (executionData.length <= that.itemIndex) { throw new Error(`No data found for item-index: "${that.itemIndex}"`); @@ -241,6 +244,11 @@ export class WorkflowDataProxy { } else if (name === 'parameter') { // Get node parameter data return that.nodeParameterGetter(nodeName); + } else if (name === 'runIndex') { + if (that.runExecutionData === null || !that.runExecutionData.resultData.runData[nodeName]) { + return -1; + } + return that.runExecutionData.resultData.runData[nodeName].length - 1; } return Reflect.get(target, name, receiver); @@ -328,8 +336,9 @@ export class WorkflowDataProxy { $data: {}, // Placeholder $env: this.envGetter(), $evaluateExpression: (expression: string) => { }, // Placeholder - $item: (itemIndex: number) => { - const dataProxy = new WorkflowDataProxy(this.workflow, this.runExecutionData, this.runIndex, itemIndex, this.activeNodeName, this.connectionInputData); + $item: (itemIndex: number, runIndex?: number) => { + const defaultReturnRunIndex = runIndex === undefined ? -1 : runIndex; + const dataProxy = new WorkflowDataProxy(this.workflow, this.runExecutionData, this.runIndex, itemIndex, this.activeNodeName, this.connectionInputData, defaultReturnRunIndex); return dataProxy.getDataProxy(); }, $items: (nodeName?: string, outputIndex?: number, runIndex?: number) => { @@ -339,6 +348,7 @@ export class WorkflowDataProxy { executionData = that.connectionInputData; } else { outputIndex = outputIndex || 0; + runIndex = runIndex === undefined ? -1 : runIndex; executionData = that.getNodeExecutionData(nodeName, false, outputIndex, runIndex); } @@ -347,6 +357,7 @@ export class WorkflowDataProxy { $json: {}, // Placeholder $node: this.nodeGetter(), $parameter: this.nodeParameterGetter(this.activeNodeName), + $runIndex: this.runIndex, $workflow: this.workflowGetter(), }; From 4ad009214ed7432d04620f436994190626e78c9c Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 13 Apr 2020 16:51:04 +0200 Subject: [PATCH 60/82] :zap: Change evaluateExpression -> $evaluateExpression --- docs/nodes.md | 6 +++--- packages/cli/BREAKING-CHANGES.md | 17 +++++++++++++++++ packages/nodes-base/nodes/Function.node.ts | 3 --- packages/nodes-base/nodes/FunctionItem.node.ts | 3 --- packages/workflow/src/Workflow.ts | 3 --- packages/workflow/src/WorkflowDataProxy.ts | 5 ++++- 6 files changed, 24 insertions(+), 13 deletions(-) diff --git a/docs/nodes.md b/docs/nodes.md index 9a5e4b5773..8c3b061474 100644 --- a/docs/nodes.md +++ b/docs/nodes.md @@ -163,7 +163,7 @@ const workflowName = $workflow.name; ``` -#### Method: evaluateExpression(expression: string, itemIndex: number) +#### Method: $evaluateExpression(expression: string, itemIndex: number) Evaluates a given string as expression. If no `itemIndex` is provided it uses by default in the Function-Node the data of item 0 and @@ -172,8 +172,8 @@ in the Function Item-Node the data of the current item. Example: ```javascript -items[0].json.variable1 = evaluateExpression('{{1+2}}'); -items[0].json.variable2 = evaluateExpression($node["Set"].json["myExpression"], 1); +items[0].json.variable1 = $evaluateExpression('{{1+2}}'); +items[0].json.variable2 = $evaluateExpression($node["Set"].json["myExpression"], 1); return items; ``` diff --git a/packages/cli/BREAKING-CHANGES.md b/packages/cli/BREAKING-CHANGES.md index 8a8e02eac3..969b258243 100644 --- a/packages/cli/BREAKING-CHANGES.md +++ b/packages/cli/BREAKING-CHANGES.md @@ -2,6 +2,23 @@ This list shows all the versions which include breaking changes and how to upgrade +## 0.62.0 + +### What changed? + +The function "evaluateExpression(...)" got renamed to "$evaluateExpression()" +in Function and FunctionItem Nodes to simplify code and to normalize function +names. + +### When is action necessary? + +If "evaluateExpression(...)" gets used in any Function or FunctionItem Node. + +### How to upgrade: + +Simply replace the "evaluateExpression(...)" with "$evaluateExpression(...)". + + ## 0.52.0 ### What changed? diff --git a/packages/nodes-base/nodes/Function.node.ts b/packages/nodes-base/nodes/Function.node.ts index 253a216650..7f5ea4c1ea 100644 --- a/packages/nodes-base/nodes/Function.node.ts +++ b/packages/nodes-base/nodes/Function.node.ts @@ -47,9 +47,6 @@ export class Function implements INodeType { // Define the global objects for the custom function const sandbox = { - evaluateExpression: (expression: string, itemIndex = 0) => { - return this.evaluateExpression(expression, itemIndex); - }, getNodeParameter: this.getNodeParameter, getWorkflowStaticData: this.getWorkflowStaticData, helpers: this.helpers, diff --git a/packages/nodes-base/nodes/FunctionItem.node.ts b/packages/nodes-base/nodes/FunctionItem.node.ts index 356e419477..6352fc3f98 100644 --- a/packages/nodes-base/nodes/FunctionItem.node.ts +++ b/packages/nodes-base/nodes/FunctionItem.node.ts @@ -48,9 +48,6 @@ export class FunctionItem implements INodeType { // Define the global objects for the custom function const sandbox = { - evaluateExpression: (expression: string, itemIndex: number | undefined) => { - return this.evaluateExpression(expression, itemIndex); - }, getBinaryData: (): IBinaryKeyData | undefined => { return item.binary; }, diff --git a/packages/workflow/src/Workflow.ts b/packages/workflow/src/Workflow.ts index a3d069058d..6c1c48ad56 100644 --- a/packages/workflow/src/Workflow.ts +++ b/packages/workflow/src/Workflow.ts @@ -899,9 +899,6 @@ export class Workflow { // Generate a data proxy which allows to query workflow data const dataProxy = new WorkflowDataProxy(this, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData); const data = dataProxy.getDataProxy(); - data.$evaluateExpression = (expression: string) => { - return this.resolveSimpleParameterValue('=' + expression, runExecutionData, runIndex, itemIndex, activeNodeName, connectionInputData, returnObjectAsString); - }; // Execute the expression try { diff --git a/packages/workflow/src/WorkflowDataProxy.ts b/packages/workflow/src/WorkflowDataProxy.ts index aa30470b1c..8094991f3c 100644 --- a/packages/workflow/src/WorkflowDataProxy.ts +++ b/packages/workflow/src/WorkflowDataProxy.ts @@ -335,7 +335,10 @@ export class WorkflowDataProxy { $binary: {}, // Placeholder $data: {}, // Placeholder $env: this.envGetter(), - $evaluateExpression: (expression: string) => { }, // Placeholder + $evaluateExpression: (expression: string, itemIndex?: number) => { + itemIndex = itemIndex || that.itemIndex; + return that.workflow.getParameterValue('=' + expression, that.runExecutionData, that.runIndex, itemIndex, that.activeNodeName, that.connectionInputData); + }, $item: (itemIndex: number, runIndex?: number) => { const defaultReturnRunIndex = runIndex === undefined ? -1 : runIndex; const dataProxy = new WorkflowDataProxy(this.workflow, this.runExecutionData, this.runIndex, itemIndex, this.activeNodeName, this.connectionInputData, defaultReturnRunIndex); From 0bdb85776719494671bfc4ec912c83f5dee29c1c Mon Sep 17 00:00:00 2001 From: ricardo Date: Mon, 13 Apr 2020 11:14:14 -0400 Subject: [PATCH 61/82] :bug: mismatch between file extension and format --- packages/nodes-base/nodes/SpreadsheetFile.node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/SpreadsheetFile.node.ts b/packages/nodes-base/nodes/SpreadsheetFile.node.ts index 26310dfd2d..eb23d38951 100644 --- a/packages/nodes-base/nodes/SpreadsheetFile.node.ts +++ b/packages/nodes-base/nodes/SpreadsheetFile.node.ts @@ -337,7 +337,7 @@ export class SpreadsheetFile implements INodeType { } else if (fileFormat === 'ods') { wopts.bookType = 'ods'; } else if (fileFormat === 'xls') { - wopts.bookType = 'xlml'; + wopts.bookType = 'xls'; } // Convert the data in the correct format From a757b438542eeb449336ebbac6a0b9401f25afb1 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 13 Apr 2020 17:19:52 +0200 Subject: [PATCH 62/82] :heavy_check_mark: Add one more test --- packages/workflow/test/Workflow.test.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/packages/workflow/test/Workflow.test.ts b/packages/workflow/test/Workflow.test.ts index 00080e2771..51b092bef7 100644 --- a/packages/workflow/test/Workflow.test.ts +++ b/packages/workflow/test/Workflow.test.ts @@ -936,6 +936,29 @@ describe('Workflow', () => { value1: 'default-value1', }, }, + { + description: 'return resolved value when referencing another property with expression on another node (long "$node["{NODE}"].parameter" syntax)', + input: { + Node1: { + parameters: { + value1: 'valueNode1', + } + }, + Node2: { + parameters: { + value1: '={{$node["Node1"].parameter.value1}}a', + }, + }, + Node3: { + parameters: { + value1: '={{$node["Node2"].parameter.value1}}b', + }, + } + }, + output: { + value1: 'valueNode1ab', + }, + }, // TODO: Make that this test does not fail! // { // description: 'return resolved value when short "data" syntax got used in expression on paramter of not active node which got referenced by active one', From a2a10b829b53caf8fc36bd27e964c7d8f3a8ec97 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 13 Apr 2020 17:22:31 +0200 Subject: [PATCH 63/82] :bookmark: Release n8n-workflow@0.28.0 --- packages/workflow/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/workflow/package.json b/packages/workflow/package.json index 0268d87d79..24a0481c8f 100644 --- a/packages/workflow/package.json +++ b/packages/workflow/package.json @@ -1,6 +1,6 @@ { "name": "n8n-workflow", - "version": "0.27.0", + "version": "0.28.0", "description": "Workflow base code of n8n", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", From 9d4bd8e820a3359d5b52fe5ca6cc2f15c6824ca0 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 13 Apr 2020 17:24:03 +0200 Subject: [PATCH 64/82] :arrow_up: Set n8n-workflow@0.28.0 on n8n-core --- packages/core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/package.json b/packages/core/package.json index d6619fd4a7..3b1dac702d 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -44,7 +44,7 @@ "crypto-js": "3.1.9-1", "lodash.get": "^4.4.2", "mmmagic": "^0.5.2", - "n8n-workflow": "~0.27.0", + "n8n-workflow": "~0.28.0", "p-cancelable": "^2.0.0", "request-promise-native": "^1.0.7" }, From 3ce9798323ccbd29d02c8f450566c90495a5ead8 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 13 Apr 2020 17:24:48 +0200 Subject: [PATCH 65/82] :bookmark: Release n8n-core@0.31.0 --- packages/core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/package.json b/packages/core/package.json index 3b1dac702d..fa74a123a5 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "n8n-core", - "version": "0.30.0", + "version": "0.31.0", "description": "Core functionality of n8n", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", From 142f3363f083eb880bb53cdbb3bb8e2420a02833 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 13 Apr 2020 17:26:04 +0200 Subject: [PATCH 66/82] :arrow_up: Set n8n-core@0.31.0 and n8n-workflow@0.28.0 on n8n-nodes-base --- packages/nodes-base/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 6826e7a020..0d98c40a8b 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -266,7 +266,7 @@ "@types/xml2js": "^0.4.3", "gulp": "^4.0.0", "jest": "^24.9.0", - "n8n-workflow": "~0.27.0", + "n8n-workflow": "~0.28.0", "ts-jest": "^24.0.2", "tslint": "^5.17.0", "typescript": "~3.7.4" @@ -288,7 +288,7 @@ "lodash.unset": "^4.5.2", "mongodb": "^3.3.2", "mysql2": "^2.0.1", - "n8n-core": "~0.30.0", + "n8n-core": "~0.31.0", "nodemailer": "^5.1.1", "pdf-parse": "^1.1.1", "pg-promise": "^9.0.3", From e3c91d6cf28255141188fedb14da846f9be80b33 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 13 Apr 2020 17:26:42 +0200 Subject: [PATCH 67/82] :bookmark: Release n8n-nodes-base@0.57.0 --- packages/nodes-base/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 0d98c40a8b..5bb103a303 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -1,6 +1,6 @@ { "name": "n8n-nodes-base", - "version": "0.56.0", + "version": "0.57.0", "description": "Base nodes of n8n", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", From d9182657380f2644cf699c2bc9315829ab688cb0 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 13 Apr 2020 17:27:32 +0200 Subject: [PATCH 68/82] :arrow_up: Set n8n-workflow@0.28.0 on n8n-editor-ui --- packages/editor-ui/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor-ui/package.json b/packages/editor-ui/package.json index 47bfac7b15..94a3b7758b 100644 --- a/packages/editor-ui/package.json +++ b/packages/editor-ui/package.json @@ -64,7 +64,7 @@ "lodash.debounce": "^4.0.8", "lodash.get": "^4.4.2", "lodash.set": "^4.3.2", - "n8n-workflow": "~0.27.0", + "n8n-workflow": "~0.28.0", "node-sass": "^4.12.0", "prismjs": "^1.17.1", "quill": "^2.0.0-dev.3", From 619ccc77340395f79a918f53227e5e8f3c4385a7 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 13 Apr 2020 17:28:16 +0200 Subject: [PATCH 69/82] :bookmark: Release n8n-editor-ui@0.42.0 --- packages/editor-ui/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor-ui/package.json b/packages/editor-ui/package.json index 94a3b7758b..9560f3377a 100644 --- a/packages/editor-ui/package.json +++ b/packages/editor-ui/package.json @@ -1,6 +1,6 @@ { "name": "n8n-editor-ui", - "version": "0.41.0", + "version": "0.42.0", "description": "Workflow Editor UI for n8n", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", From 7857e0d8361b8d9e345b6b95eb6f19c9c81bceac Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 13 Apr 2020 17:30:09 +0200 Subject: [PATCH 70/82] :arrow_up: Set n8n-core@0.31.0, n8n-editor-ui@0.42.0, n8n-nodes-base@0.57.0 and n8n-workflow@0.28.0 on n8n --- packages/cli/package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index db9b261d55..9dd55fac76 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -95,10 +95,10 @@ "lodash.get": "^4.4.2", "mongodb": "^3.2.3", "mysql2": "^2.0.1", - "n8n-core": "~0.30.0", - "n8n-editor-ui": "~0.41.0", - "n8n-nodes-base": "~0.56.0", - "n8n-workflow": "~0.27.0", + "n8n-core": "~0.31.0", + "n8n-editor-ui": "~0.42.0", + "n8n-nodes-base": "~0.57.0", + "n8n-workflow": "~0.28.0", "open": "^7.0.0", "pg": "^7.11.0", "request-promise-native": "^1.0.7", From af2ed46a68203ff0a8c2929f4ecd3f4da2e70745 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 13 Apr 2020 17:30:36 +0200 Subject: [PATCH 71/82] :bookmark: Release n8n@0.62.0 --- packages/cli/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 9dd55fac76..e053a144c7 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "n8n", - "version": "0.61.0", + "version": "0.62.0", "description": "n8n Workflow Automation Tool", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", From fd185671dbc45c61d285373e26d82cb5e98387f0 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 13 Apr 2020 22:17:23 +0200 Subject: [PATCH 72/82] :bug: Fix sending none JSON data bug --- packages/nodes-base/nodes/HttpRequest.node.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/nodes-base/nodes/HttpRequest.node.ts b/packages/nodes-base/nodes/HttpRequest.node.ts index 2186a2f22a..8347af228e 100644 --- a/packages/nodes-base/nodes/HttpRequest.node.ts +++ b/packages/nodes-base/nodes/HttpRequest.node.ts @@ -697,12 +697,8 @@ export class HttpRequest implements INodeType { } } - try { - // @ts-ignore - requestOptions[optionData.name] = JSON.parse(tempValue as string); - } catch (error) { - throw new Error(`${optionData.name} must be a valid JSON`); - } + // @ts-ignore + requestOptions[optionData.name] = tempValue; // @ts-ignore if (typeof requestOptions[optionData.name] !== 'object' && options.bodyContentType !== 'raw') { From ec5bb5d68ba5d9a179edec8de62f40ea9e982396 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 13 Apr 2020 22:18:26 +0200 Subject: [PATCH 73/82] :bookmark: Release n8n-nodes-base@0.57.1 --- packages/nodes-base/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 5bb103a303..81121dfbe3 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -1,6 +1,6 @@ { "name": "n8n-nodes-base", - "version": "0.57.0", + "version": "0.57.1", "description": "Base nodes of n8n", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", From 9afb71ec9116959d1bb24b4a5c509dbacd1e4f2e Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 13 Apr 2020 22:19:20 +0200 Subject: [PATCH 74/82] :arrow_up: Set n8n-nodes-base@0.57.1 on n8n --- packages/cli/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index e053a144c7..659e429175 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -97,7 +97,7 @@ "mysql2": "^2.0.1", "n8n-core": "~0.31.0", "n8n-editor-ui": "~0.42.0", - "n8n-nodes-base": "~0.57.0", + "n8n-nodes-base": "~0.57.1", "n8n-workflow": "~0.28.0", "open": "^7.0.0", "pg": "^7.11.0", From 105858cb3655df907e6edef4f7d2481d34e6af50 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Mon, 13 Apr 2020 22:19:54 +0200 Subject: [PATCH 75/82] :bookmark: Release n8n@0.62.1 --- packages/cli/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 659e429175..ab93ea967f 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "n8n", - "version": "0.62.0", + "version": "0.62.1", "description": "n8n Workflow Automation Tool", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", From cc52ed596e4adeb2112c895769f8318c4f3c1afa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Mon, 13 Apr 2020 22:37:41 +0200 Subject: [PATCH 76/82] add2010 --- .../nodes/Mattermost/Mattermost.node.ts | 25 ++++++------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 22874e8e1d..86ee67b231 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -1038,27 +1038,16 @@ export class Mattermost implements INodeType { for (const att of arr) { if (Array.isArray(att.actions)) for (const attaction of att.actions) { - //console.log(attaction); if (attaction.integration.item !== undefined) { - //console.log('integration items'); attaction.integration = attaction.integration.item; - var tmpintegration = {}; - for (const attactioninteg of attaction.integration) { - //console.log(attactioninteg); - if (attactioninteg.context.property !== undefined) { - //console.log('connnnnn'); - var tmpcontex = {}; - for (const attactionintegprop of attactioninteg.context.property ) { - // console.log(attactionintegprop); - Object.assign(tmpcontex, { [attactionintegprop.name] : attactionintegprop.value } ); - } - delete attactioninteg.context ; - attactioninteg.context = tmpcontex ; - } - Object.assign(tmpintegration, attactioninteg); + if (Array.isArray(attaction.integration.context.property)) { + var tmpcontex = {}; + for (const attactionintegprop of attaction.integration.context.property ) { + Object.assign(tmpcontex, { [attactionintegprop.name] : attactionintegprop.value } ); + } + delete attaction.integration.context; + attaction.integration.context = tmpcontex; } - delete attaction.integration; - attaction.integration=tmpintegration; } } }; From 031827e315a0773d2d7e65a434392bdf6ad28cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mi=C5=82osz=20Szewczak?= Date: Mon, 13 Apr 2020 23:14:16 +0200 Subject: [PATCH 77/82] add 2001 --- .../nodes/Mattermost/Mattermost.node.ts | 86 +++---------------- 1 file changed, 13 insertions(+), 73 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 86ee67b231..159083af1c 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -571,9 +571,8 @@ export class Mattermost implements INodeType { default: '', description: 'Icon which should appear next to footer.', }, - - - { displayName: 'Actions', + { + displayName: 'Actions', name: 'actions', placeholder: 'Add Actions', description: 'Actions to add to message.', @@ -594,8 +593,6 @@ export class Mattermost implements INodeType { default: '', description: 'Name of the Action.', }, - - { displayName: 'Integration', name: 'integration', @@ -619,8 +616,6 @@ export class Mattermost implements INodeType { default: '', description: 'URL of the Integration.', }, -// context - { displayName: 'Context', name: 'context', @@ -655,44 +650,14 @@ export class Mattermost implements INodeType { }, ], }, - - - - - - - - - ] }, ], }, - - - - ] }, ], }, - - - - - - - - - - - - - - - - - { displayName: 'Fields', name: 'fields', @@ -997,9 +962,7 @@ export class Mattermost implements INodeType { body.message = this.getNodeParameter('message', i) as string; const attachments = this.getNodeParameter('attachments', i, []) as unknown as IAttachment[]; - console.log('----'); - console.dir(attachments); - console.log('----'); + // The node does save the fields data differently than the API // expects so fix the data befre we send the request for (const attachment of attachments) { @@ -1020,58 +983,35 @@ export class Mattermost implements INodeType { // Move the field-content up // @ts-ignore attachment.actions = attachment.actions.item; - console.log(attachment.actions ); } else { // If it does not have any items set remove it delete attachment.actions; } } - } - const util = require('util'); - console.log('&&&&'); - //console.dir(attachments); - console.log(util.inspect(attachments, false, null, true /* enable colors */)); - console.log('&&&&'); + } const arr = attachments; - for (const att of arr) { if (Array.isArray(att.actions)) for (const attaction of att.actions) { if (attaction.integration.item !== undefined) { - attaction.integration = attaction.integration.item; - if (Array.isArray(attaction.integration.context.property)) { - var tmpcontex = {}; - for (const attactionintegprop of attaction.integration.context.property ) { - Object.assign(tmpcontex, { [attactionintegprop.name] : attactionintegprop.value } ); - } - delete attaction.integration.context; - attaction.integration.context = tmpcontex; - } + attaction.integration = attaction.integration.item; + if (Array.isArray(attaction.integration.context.property)) { + var tmpcontex = {}; + for (const attactionintegprop of attaction.integration.context.property ) { + Object.assign(tmpcontex, { [attactionintegprop.name] : attactionintegprop.value } ); + } + delete attaction.integration.context; + attaction.integration.context = tmpcontex; + } } } }; - - console.log('****111'); - console.log(JSON.stringify(arr, null, 4)); - console.log('****222'); - console.log(JSON.stringify(attachments, null, 4)); - console.log('****222aaa'); - body.props = { attachments, }; - //console.log('####'); - //console.dir(body); - //console.log('####'); - console.log('****'); - console.log(util.inspect(body, false, null, true /* enable colors */)); - //console.dir(body); - //console.log('****111'); - //console.log(JSON.stringify(body, null, 4)); - console.log('****'); // Add all the other options to the request const otherOptions = this.getNodeParameter('otherOptions', i) as IDataObject; Object.assign(body, otherOptions); From 524a8e62c9c9851d1d7d7a223f262f1a835a09b9 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Tue, 14 Apr 2020 15:38:15 +0200 Subject: [PATCH 78/82] :zap: Add xlsx format to Spreadsheet-Node --- packages/nodes-base/nodes/SpreadsheetFile.node.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/nodes-base/nodes/SpreadsheetFile.node.ts b/packages/nodes-base/nodes/SpreadsheetFile.node.ts index eb23d38951..594754ef99 100644 --- a/packages/nodes-base/nodes/SpreadsheetFile.node.ts +++ b/packages/nodes-base/nodes/SpreadsheetFile.node.ts @@ -133,6 +133,11 @@ export class SpreadsheetFile implements INodeType { value: 'xls', description: 'Excel', }, + { + name: 'XLSX', + value: 'xlsx', + description: 'Excel', + }, ], default: 'xls', displayOptions: { @@ -236,6 +241,7 @@ export class SpreadsheetFile implements INodeType { '/fileFormat': [ 'ods', 'xls', + 'xlsx', ], }, }, @@ -338,6 +344,8 @@ export class SpreadsheetFile implements INodeType { wopts.bookType = 'ods'; } else if (fileFormat === 'xls') { wopts.bookType = 'xls'; + } else if (fileFormat === 'xlsx') { + wopts.bookType = 'xlsx'; } // Convert the data in the correct format From ac3e901031f7660d74a9054e29949b1df23047b3 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Tue, 14 Apr 2020 17:46:56 +0200 Subject: [PATCH 79/82] :zap: Fixed indentation and ordered parameters correctly --- .../nodes/Mattermost/Mattermost.node.ts | 404 +++++++++--------- 1 file changed, 202 insertions(+), 202 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 159083af1c..fbed553ae6 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -448,130 +448,6 @@ export class Mattermost implements INodeType { placeholder: 'Add attachment item', options: [ { - displayName: 'Fallback Text', - name: 'fallback', - type: 'string', - typeOptions: { - alwaysOpenEditWindow: true, - }, - default: '', - description: 'Required plain-text summary of the attachment.', - }, - { - displayName: 'Text', - name: 'text', - type: 'string', - typeOptions: { - alwaysOpenEditWindow: true, - }, - default: '', - description: 'Text to send.', - }, - { - displayName: 'Title', - name: 'title', - type: 'string', - typeOptions: { - alwaysOpenEditWindow: true, - }, - default: '', - description: 'Title of the message.', - }, - { - displayName: 'Title Link', - name: 'title_link', - type: 'string', - typeOptions: { - alwaysOpenEditWindow: true, - }, - default: '', - description: 'Link of the title.', - }, - { - displayName: 'Color', - name: 'color', - type: 'color', - default: '#ff0000', - description: 'Color of the line left of text.', - }, - { - displayName: 'Pretext', - name: 'pretext', - type: 'string', - typeOptions: { - alwaysOpenEditWindow: true, - }, - default: '', - description: 'Text which appears before the message block.', - }, - { - displayName: 'Author Name', - name: 'author_name', - type: 'string', - default: '', - description: 'Name that should appear.', - }, - { - displayName: 'Author Link', - name: 'author_link', - type: 'string', - typeOptions: { - alwaysOpenEditWindow: true, - }, - default: '', - description: 'Link for the author.', - }, - { - displayName: 'Author Icon', - name: 'author_icon', - type: 'string', - typeOptions: { - alwaysOpenEditWindow: true, - }, - default: '', - description: 'Icon which should appear for the user.', - }, - { - displayName: 'Image URL', - name: 'image_url', - type: 'string', - typeOptions: { - alwaysOpenEditWindow: true, - }, - default: '', - description: 'URL of image.', - }, - { - displayName: 'Thumbnail URL', - name: 'thumb_url', - type: 'string', - typeOptions: { - alwaysOpenEditWindow: true, - }, - default: '', - description: 'URL of thumbnail.', - }, - { - displayName: 'Footer', - name: 'footer', - type: 'string', - typeOptions: { - alwaysOpenEditWindow: true, - }, - default: '', - description: 'Text of footer to add.', - }, - { - displayName: 'Footer Icon', - name: 'footer_icon', - type: 'string', - typeOptions: { - alwaysOpenEditWindow: true, - }, - default: '', - description: 'Icon which should appear next to footer.', - }, - { displayName: 'Actions', name: 'actions', placeholder: 'Add Actions', @@ -593,71 +469,115 @@ export class Mattermost implements INodeType { default: '', description: 'Name of the Action.', }, - { - displayName: 'Integration', - name: 'integration', - placeholder: 'Add Integration', - description: 'Integration to add to message.', - type: 'fixedCollection', - typeOptions: { - multipleValues: false, - }, - default: {}, - options: [ - { - displayName: 'Item', - name: 'item', - default: {}, - values: [ - { - displayName: 'URL', - name: 'url', - type: 'string', - default: '', - description: 'URL of the Integration.', - }, - { - displayName: 'Context', - name: 'context', - placeholder: 'Add Context to Integration', - description: 'Adds a Context values set.', - type: 'fixedCollection', - typeOptions: { - multipleValues: true, - }, - default: {}, - options: [ - { - name: 'property', - displayName: 'Property', - default: {}, - values: [ - { - displayName: 'Property Name', - name: 'name', - type: 'string', - default: '', - description: 'Name of the property to set.', - }, - { - displayName: 'Property Value', - name: 'value', - type: 'string', - default: '', - description: 'Value of the property to set.', - }, - ] - }, - ], - }, - ] + { + displayName: 'Integration', + name: 'integration', + placeholder: 'Add Integration', + description: 'Integration to add to message.', + type: 'fixedCollection', + typeOptions: { + multipleValues: false, }, - ], - }, + default: {}, + options: [ + { + displayName: 'Item', + name: 'item', + default: {}, + values: [ + { + displayName: 'URL', + name: 'url', + type: 'string', + default: '', + description: 'URL of the Integration.', + }, + { + displayName: 'Context', + name: 'context', + placeholder: 'Add Context to Integration', + description: 'Adds a Context values set.', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + options: [ + { + name: 'property', + displayName: 'Property', + default: {}, + values: [ + { + displayName: 'Property Name', + name: 'name', + type: 'string', + default: '', + description: 'Name of the property to set.', + }, + { + displayName: 'Property Value', + name: 'value', + type: 'string', + default: '', + description: 'Value of the property to set.', + }, + ] + }, + ], + }, + ] + }, + ], + }, ] }, ], }, + { + displayName: 'Author Icon', + name: 'author_icon', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'Icon which should appear for the user.', + }, + { + displayName: 'Author Link', + name: 'author_link', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'Link for the author.', + }, + { + displayName: 'Author Name', + name: 'author_name', + type: 'string', + default: '', + description: 'Name that should appear.', + }, + { + displayName: 'Color', + name: 'color', + type: 'color', + default: '#ff0000', + description: 'Color of the line left of text.', + }, + { + displayName: 'Fallback Text', + name: 'fallback', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'Required plain-text summary of the attachment.', + }, { displayName: 'Fields', name: 'fields', @@ -697,7 +617,87 @@ export class Mattermost implements INodeType { ] }, ], - } + }, + { + displayName: 'Footer', + name: 'footer', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'Text of footer to add.', + }, + { + displayName: 'Footer Icon', + name: 'footer_icon', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'Icon which should appear next to footer.', + }, + { + displayName: 'Image URL', + name: 'image_url', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'URL of image.', + }, + { + displayName: 'Pretext', + name: 'pretext', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'Text which appears before the message block.', + }, + { + displayName: 'Text', + name: 'text', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'Text to send.', + }, + { + displayName: 'Thumbnail URL', + name: 'thumb_url', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'URL of thumbnail.', + }, + { + displayName: 'Title', + name: 'title', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'Title of the message.', + }, + { + displayName: 'Title Link', + name: 'title_link', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'Link of the title.', + }, ], }, { @@ -989,24 +989,24 @@ export class Mattermost implements INodeType { } } } - - const arr = attachments; - for (const att of arr) { - if (Array.isArray(att.actions)) - for (const attaction of att.actions) { - if (attaction.integration.item !== undefined) { - attaction.integration = attaction.integration.item; - if (Array.isArray(attaction.integration.context.property)) { - var tmpcontex = {}; - for (const attactionintegprop of attaction.integration.context.property ) { - Object.assign(tmpcontex, { [attactionintegprop.name] : attactionintegprop.value } ); - } - delete attaction.integration.context; - attaction.integration.context = tmpcontex; + + for (const attachment of attachments) { + if (Array.isArray(attachment.actions)) { + for (const attaction of attachment.actions) { + if (attaction.integration.item !== undefined) { + attaction.integration = attaction.integration.item; + if (Array.isArray(attaction.integration.context.property)) { + const tmpcontex = {}; + for (const attactionintegprop of attaction.integration.context.property) { + Object.assign(tmpcontex, { [attactionintegprop.name]: attactionintegprop.value }); + } + delete attaction.integration.context; + attaction.integration.context = tmpcontex; + } + } } - } - } - }; + } + } body.props = { attachments, From f602f0022c0751a74052583c2981d362192c07be Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Tue, 14 Apr 2020 18:23:43 +0200 Subject: [PATCH 80/82] :zap: Add support for Mattermost interactive message "select" --- .../nodes/Mattermost/Mattermost.node.ts | 100 +++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index fbed553ae6..77d6b00f05 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -451,7 +451,7 @@ export class Mattermost implements INodeType { displayName: 'Actions', name: 'actions', placeholder: 'Add Actions', - description: 'Actions to add to message.', + description: 'Actions to add to message. More information can be found here', type: 'fixedCollection', typeOptions: { multipleValues: true, @@ -462,6 +462,93 @@ export class Mattermost implements INodeType { displayName: 'Item', name: 'item', values: [ + { + displayName: 'Type', + name: 'type', + type: 'options', + options: [ + { + name: 'Button', + value: 'button', + }, + { + name: 'Select', + value: 'select', + }, + ], + default: 'button', + description: 'The type of the action.', + }, + { + displayName: 'Data Source', + name: 'data_source', + type: 'options', + displayOptions: { + show: { + type: [ + 'select' + ], + }, + }, + options: [ + { + name: 'Channels', + value: 'channels', + }, + { + name: 'Custom', + value: 'custom', + }, + { + name: 'Users', + value: 'users', + }, + + ], + default: 'custom', + description: 'The type of the action.', + }, + { + displayName: 'Options', + name: 'options', + placeholder: 'Add Option', + description: 'Adds a new option to select field.', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + displayOptions: { + show: { + data_source: [ + 'custom' + ], + }, + }, + default: {}, + options: [ + { + name: 'option', + displayName: 'Option', + default: {}, + values: [ + { + displayName: 'Option Text', + name: 'text', + type: 'string', + default: '', + description: 'Text of the option.', + }, + { + displayName: 'Option Value', + name: 'value', + type: 'string', + default: '', + description: 'Value of the option.', + }, + ] + }, + ], + }, { displayName: 'Name', name: 'name', @@ -993,6 +1080,17 @@ export class Mattermost implements INodeType { for (const attachment of attachments) { if (Array.isArray(attachment.actions)) { for (const attaction of attachment.actions) { + + if (attaction.type === 'button') { + delete attaction.type; + } + if (attaction.data_source === 'custom') { + delete attaction.data_source; + } + if (attaction.options) { + attaction.options = attaction.options.option; + } + if (attaction.integration.item !== undefined) { attaction.integration = attaction.integration.item; if (Array.isArray(attaction.integration.context.property)) { From 7ab616f6bcdb93817ba60fb6336b2bd23bd75bd8 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Tue, 14 Apr 2020 19:17:55 +0200 Subject: [PATCH 81/82] :zap: Small improvement to Mattermost-Node --- packages/nodes-base/nodes/Mattermost/GenericFunctions.ts | 4 ++-- packages/nodes-base/nodes/Mattermost/Mattermost.node.ts | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/nodes-base/nodes/Mattermost/GenericFunctions.ts b/packages/nodes-base/nodes/Mattermost/GenericFunctions.ts index ac712e1d66..329e3ae83b 100644 --- a/packages/nodes-base/nodes/Mattermost/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Mattermost/GenericFunctions.ts @@ -10,11 +10,11 @@ import { IDataObject } from 'n8n-workflow'; export interface IAttachment { fields: { item?: object[]; - }, + }; actions: { item?: object[]; }; -} +} /** * Make an API request to Telegram diff --git a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts index 77d6b00f05..e9f81e7d8d 100644 --- a/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts +++ b/packages/nodes-base/nodes/Mattermost/Mattermost.node.ts @@ -522,6 +522,9 @@ export class Mattermost implements INodeType { data_source: [ 'custom' ], + type: [ + 'select' + ], }, }, default: {}, From 303062623b3ab133eafab1d4037d6d38e071e980 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Tue, 14 Apr 2020 19:54:11 +0200 Subject: [PATCH 82/82] :sparkles: Add MariaDB support --- docs/database.md | 6 +++--- packages/cli/config/index.ts | 2 +- packages/cli/src/Db.ts | 3 ++- packages/cli/src/Interfaces.ts | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/database.md b/docs/database.md index 8fa4325394..8daf5970ce 100644 --- a/docs/database.md +++ b/docs/database.md @@ -60,12 +60,12 @@ export DB_POSTGRESDB_SCHEMA=n8n n8n start ``` -## MySQL +## MySQL / MariaDB -The compatibility with MySQL was tested, even so, it is advisable to observe the operation of the application with this DB, as it is a new option, recently added. If you spot any problems, feel free to submit a PR. +The compatibility with MySQL/MariaDB was tested, even so, it is advisable to observe the operation of the application with this DB, as it is a new option, recently added. If you spot any problems, feel free to submit a PR. To use MySQL as database you can provide the following environment variables: - - `DB_TYPE=mysqldb` + - `DB_TYPE=mysqldb` or `DB_TYPE=mariadb` - `DB_MYSQLDB_DATABASE` (default: 'n8n') - `DB_MYSQLDB_HOST` (default: 'localhost') - `DB_MYSQLDB_PORT` (default: 3306) diff --git a/packages/cli/config/index.ts b/packages/cli/config/index.ts index a3b800279e..69b3154064 100644 --- a/packages/cli/config/index.ts +++ b/packages/cli/config/index.ts @@ -8,7 +8,7 @@ const config = convict({ database: { type: { doc: 'Type of database to use', - format: ['sqlite', 'mongodb', 'mysqldb', 'postgresdb'], + format: ['sqlite', 'mariadb', 'mongodb', 'mysqldb', 'postgresdb'], default: 'sqlite', env: 'DB_TYPE' }, diff --git a/packages/cli/src/Db.ts b/packages/cli/src/Db.ts index a97cbaa837..ed24baabd2 100644 --- a/packages/cli/src/Db.ts +++ b/packages/cli/src/Db.ts @@ -63,11 +63,12 @@ export async function init(synchronize?: boolean): Promise }; break; + case 'mariadb': case 'mysqldb': dbNotExistError = 'does not exist'; entities = MySQLDb; connectionOptions = { - type: 'mysql', + type: dbType === 'mysqldb' ? 'mysql' : 'mariadb', database: await GenericHelpers.getConfigValue('database.mysqldb.database') as string, entityPrefix: await GenericHelpers.getConfigValue('database.tablePrefix') as string, host: await GenericHelpers.getConfigValue('database.mysqldb.host') as string, diff --git a/packages/cli/src/Interfaces.ts b/packages/cli/src/Interfaces.ts index 33d7b02e7f..225e02885f 100644 --- a/packages/cli/src/Interfaces.ts +++ b/packages/cli/src/Interfaces.ts @@ -87,7 +87,7 @@ export interface ICredentialsDecryptedResponse extends ICredentialsDecryptedDb { id: string; } -export type DatabaseType = 'mongodb' | 'postgresdb' | 'mysqldb' | 'sqlite'; +export type DatabaseType = 'mariadb' | 'mongodb' | 'postgresdb' | 'mysqldb' | 'sqlite'; export type SaveExecutionDataType = 'all' | 'none'; export interface IExecutionBase {