From a3594ae7a2315c65c6ae91eb990821613d7de147 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Tue, 12 Nov 2019 15:48:45 -0500 Subject: [PATCH 1/4] :rocket: node-setup --- .../credentials/MailchimpApi.credentials.ts | 23 ++++ .../nodes/Mailchimp/GenericFunctions.ts | 43 +++++++ .../nodes/Mailchimp/Mailchimp.node.ts | 117 ++++++++++++++++++ .../nodes-base/nodes/Mailchimp/mailchimp.png | Bin 0 -> 2965 bytes packages/nodes-base/package.json | 6 +- 5 files changed, 187 insertions(+), 2 deletions(-) create mode 100644 packages/nodes-base/credentials/MailchimpApi.credentials.ts create mode 100644 packages/nodes-base/nodes/Mailchimp/GenericFunctions.ts create mode 100644 packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts create mode 100644 packages/nodes-base/nodes/Mailchimp/mailchimp.png diff --git a/packages/nodes-base/credentials/MailchimpApi.credentials.ts b/packages/nodes-base/credentials/MailchimpApi.credentials.ts new file mode 100644 index 0000000000..407d112f53 --- /dev/null +++ b/packages/nodes-base/credentials/MailchimpApi.credentials.ts @@ -0,0 +1,23 @@ +import { + ICredentialType, + NodePropertyTypes, +} from 'n8n-workflow'; + +export class Mailchimp implements ICredentialType { + name = 'mailchimpApi'; + displayName = 'Mailchimp API'; + properties = [ + { + displayName: 'API Key', + name: 'apiKey', + type: 'string' as NodePropertyTypes, + default: '', + }, + { + displayName: 'Datacenter', + name: 'datacenter', + type: 'string' as NodePropertyTypes, + default: '', + }, + ]; +} diff --git a/packages/nodes-base/nodes/Mailchimp/GenericFunctions.ts b/packages/nodes-base/nodes/Mailchimp/GenericFunctions.ts new file mode 100644 index 0000000000..27fda7364a --- /dev/null +++ b/packages/nodes-base/nodes/Mailchimp/GenericFunctions.ts @@ -0,0 +1,43 @@ +import { OptionsWithUri } from 'request'; + +import { + IExecuteFunctions, + IHookFunctions, + ILoadOptionsFunctions, + IExecuteSingleFunctions +} from 'n8n-core'; + +export async function mailchimpApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, resource: string, method: string, body: any = {}, headers?: object): Promise { // tslint:disable-line:no-any + const credentials = this.getCredentials('mailchimpApi'); + const datacenter = credentials!.datacenter as string; + + if (credentials === undefined) { + throw new Error('No credentials got returned!'); + } + + const headerWithAuthentication = Object.assign({}, headers, { Authorization: `apikey ${credentials.apiKey}` }); + + const endpoint = 'api.mailchimp.com/3.0'; + + const options: OptionsWithUri = { + headers: headerWithAuthentication, + method, + uri: `https://${datacenter}.${endpoint}${resource}`, + json: true + }; + + if (Object.keys(body).length !== 0) { + options.body = body; + } + + try { + return await this.helpers.request!(options); + } catch (error) { + const errorMessage = error.response.body.message || error.response.body.Message; + + if (errorMessage !== undefined) { + throw errorMessage; + } + throw error.response.body; + } +} diff --git a/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts b/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts new file mode 100644 index 0000000000..f2b3eca677 --- /dev/null +++ b/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts @@ -0,0 +1,117 @@ +import { + IExecuteSingleFunctions, +} from 'n8n-core'; +import { + IDataObject, + INodeTypeDescription, + INodeExecutionData, + INodeType, + ILoadOptionsFunctions, + INodePropertyOptions, +} from 'n8n-workflow'; +import { + mailchimpApiRequest, +} from './GenericFunctions'; + +export class Mailchimp implements INodeType { + + description: INodeTypeDescription = { + displayName: 'Mailchimp', + name: 'mailchimp', + icon: 'file:mailchimp.png', + group: ['output'], + version: 1, + subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', + description: 'Consume Mailchimp API', + defaults: { + name: 'Mailchimp', + color: '#c02428', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: 'mailchimpApi', + required: true, + } + ], + properties: [ + { + displayName: 'Resource', + name: 'resource', + type: 'options', + options: [ + { + name: 'Member', + value: 'member', + description: 'Add member to list', + }, + ], + default: '', + required: true, + description: 'Resource to consume.', + }, + { + displayName: 'Operation', + name: 'operation', + type: 'options', + required: true, + displayOptions: { + show: { + resource: [ + 'member', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a new member', + }, + ], + default: '', + description: 'The operation to perform.', + }, + ] + }; + + + methods = { + loadOptions: { + // Get all the available projects to display them to user so that he can + // select them easily + async getLists(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + let lists, response; + try { + response = await mailchimpApiRequest.call(this, '/lists', 'GET'); + lists = response.lists; + } catch (err) { + throw new Error(`Mailchimp Error: ${err}`); + } + for (const list of lists) { + const listName = list.name; + const listId = list.id; + + returnData.push({ + name: listName, + value: listId, + }); + } + + return returnData; + }, + } + }; + + async executeSingle(this: IExecuteSingleFunctions): Promise { + + const resource = this.getNodeParameter('resource') as string; + const opeation = this.getNodeParameter('operation') as string; + + return { + json: {} + }; + } +} diff --git a/packages/nodes-base/nodes/Mailchimp/mailchimp.png b/packages/nodes-base/nodes/Mailchimp/mailchimp.png new file mode 100644 index 0000000000000000000000000000000000000000..a4998396c3db04377d7e2ef555f878ba4f1dd3ce GIT binary patch literal 2965 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 literal 0 HcmV?d00001 diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 0343726121..6de583c5b3 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -42,7 +42,8 @@ "dist/credentials/HttpHeaderAuth.credentials.js", "dist/credentials/Imap.credentials.js", "dist/credentials/LinkFishApi.credentials.js", - "dist/credentials/MailgunApi.credentials.js", + "dist/credentials/MailgunApi.credentials.js", + "dist/credentials/MailchimpApi.credentials.js", "dist/credentials/MandrillApi.credentials.js", "dist/credentials/MattermostApi.credentials.js", "dist/credentials/MongoDb.credentials.js", @@ -93,7 +94,8 @@ "dist/nodes/If.node.js", "dist/nodes/Interval.node.js", "dist/nodes/LinkFish/LinkFish.node.js", - "dist/nodes/Mailgun/Mailgun.node.js", + "dist/nodes/Mailgun/Mailgun.node.js", + "dist/nodes/Mailchimp/Mailchimp.node.js", "dist/nodes/Mandrill/Mandrill.node.js", "dist/nodes/Mattermost/Mattermost.node.js", "dist/nodes/Merge.node.js", From 451c87d8a99ebdde41b36d47a94699f91f52f0c0 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Thu, 14 Nov 2019 18:44:07 -0500 Subject: [PATCH 2/4] :sparkles: Done --- .../credentials/MailchimpApi.credentials.ts | 2 +- .../nodes/Mailchimp/GenericFunctions.ts | 10 + .../nodes/Mailchimp/Mailchimp.node.ts | 453 +++++++++++++++++- 3 files changed, 458 insertions(+), 7 deletions(-) diff --git a/packages/nodes-base/credentials/MailchimpApi.credentials.ts b/packages/nodes-base/credentials/MailchimpApi.credentials.ts index 407d112f53..e2e98964da 100644 --- a/packages/nodes-base/credentials/MailchimpApi.credentials.ts +++ b/packages/nodes-base/credentials/MailchimpApi.credentials.ts @@ -3,7 +3,7 @@ import { NodePropertyTypes, } from 'n8n-workflow'; -export class Mailchimp implements ICredentialType { +export class MailchimpApi implements ICredentialType { name = 'mailchimpApi'; displayName = 'Mailchimp API'; properties = [ diff --git a/packages/nodes-base/nodes/Mailchimp/GenericFunctions.ts b/packages/nodes-base/nodes/Mailchimp/GenericFunctions.ts index 27fda7364a..fdf44bdc82 100644 --- a/packages/nodes-base/nodes/Mailchimp/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Mailchimp/GenericFunctions.ts @@ -41,3 +41,13 @@ export async function mailchimpApiRequest(this: IHookFunctions | IExecuteFunctio throw error.response.body; } } + +export function validateJSON(json: string | undefined): any { // tslint:disable-line:no-any + let result; + try { + result = JSON.parse(json!); + } catch (exception) { + result = ''; + } + return result; +} diff --git a/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts b/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts index f2b3eca677..bea30e4ee8 100644 --- a/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts +++ b/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts @@ -11,7 +11,38 @@ import { } from 'n8n-workflow'; import { mailchimpApiRequest, + validateJSON } from './GenericFunctions'; +import * as moment from 'moment'; + +enum Status { + subscribe = 'subscribe', + unsubscribed = 'unsubscribe', + cleaned = 'cleaned', + pending = 'pending', + transactional = 'transactional' +} + +interface ILocation { + latitude?: number; + longitude?: number; +} + +interface ICreateMemberBody { + listId: string; + email_address: string; + email_type?: string; + status?: Status; + language?: string; + vip?: boolean; + location?: ILocation; + ips_signup?: string; + timestamp_signup?: string; + ip_opt?: string; + timestamp_opt?: string; + tags?: string[]; + merge_fields?: IDataObject; +} export class Mailchimp implements INodeType { @@ -67,19 +98,352 @@ export class Mailchimp implements INodeType { { name: 'Create', value: 'create', - description: 'Create a new member', + description: 'Create a new member on list', }, ], default: '', description: 'The operation to perform.', }, + { + displayName: 'List', + name: 'list', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getLists', + }, + displayOptions: { + show: { + resource: [ + 'member' + ], + operation: [ + 'create', + ], + }, + }, + default: '', + options: [], + required: true, + description: 'List of lists' + }, + { + displayName: 'Email', + name: 'email', + type: 'string', + required: true, + displayOptions: { + show: { + resource: [ + 'member', + ], + operation: [ + 'create', + ], + }, + }, + default: '', + description: 'Email address for a subscriber.', + }, + { + displayName: 'Status', + name: 'status', + type: 'options', + required: true, + displayOptions: { + show: { + resource: [ + 'member', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + name: 'Subscribed', + value: 'subscribed', + description: '', + }, + { + name: 'Unsubscribed', + value: 'unsubscribed', + description: '', + }, + { + name: 'Cleaned', + value: 'cleaned', + description: '', + }, + { + name: 'Pending', + value: 'pending', + description: '', + }, + { + name: 'Transactional', + value: 'transactional', + description: '', + }, + ], + default: '', + description: `Subscriber's current status.`, + }, + { + displayName: 'JSON Parameters', + name: 'jsonParameters', + type: 'boolean', + default: false, + description: '', + displayOptions: { + show: { + resource:[ + 'member' + ], + operation: [ + 'create', + ], + }, + }, + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Option', + default: {}, + displayOptions: { + show: { + resource:[ + 'member' + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'Email Type', + name: 'emailType', + type: 'options', + options: [ + { + name: 'Email', + value: 'email', + description: '', + }, + { + name: 'Text', + value: 'text', + description: '', + }, + ], + default: '', + description: 'Type of email this member asked to get', + }, + { + displayName: 'Signup IP', + name: 'ipSignup', + type: 'string', + default: '', + description: 'IP address the subscriber signed up from.', + }, + { + displayName: 'Opt-in IP', + name: 'ipOptIn', + type: 'string', + default: '', + description: 'The IP address the subscriber used to confirm their opt-in status.', + }, + { + displayName: 'Signup Timestamp', + name: 'timestampSignup', + type: 'dateTime', + default: '', + description: 'The date and time the subscriber signed up for the list in ISO 8601 format.', + }, + { + displayName: 'Language', + name: 'language', + type: 'string', + default: '', + description: `If set/detected, the subscriber's language.`, + }, + { + displayName: 'Vip', + name: 'vip', + type: 'boolean', + default: false, + description: `Vip status for subscribers`, + }, + { + displayName: 'Opt-in Timestamp', + name: 'timestampOpt', + type: 'dateTime', + default: '', + description: `The date and time the subscribe confirmed their opt-in status in ISO 8601 format.`, + }, + { + displayName: 'Tags', + name: 'tags', + type: 'string', + default: '', + description: `The tags that are associated with a member separeted by ,.`, + }, + ] + }, + { + displayName: 'Location', + name: 'locationFieldsUi', + type: 'fixedCollection', + placeholder: 'Add Location', + default: false, + description: `Subscriber location information.n`, + displayOptions: { + show: { + resource:[ + 'member' + ], + operation: [ + 'create', + ], + jsonParameters: [ + false, + ], + }, + }, + options: [ + { + name: 'locationFieldsValues', + displayName: 'Location', + values: [ + { + displayName: 'Latitude', + name: 'latitude', + type: 'string', + required: true, + description: 'The location latitude.', + default: '' + }, + { + displayName: 'Longitude', + name: 'longitude', + type: 'string', + required: true, + description: 'The location longitude.', + default: '' + }, + ], + } + ], + }, + { + displayName: 'Merge Fields', + name: 'mergeFieldsUi', + placeholder: 'Add Merge Fields', + type: 'fixedCollection', + default: '', + typeOptions: { + multipleValues: true, + }, + displayOptions: { + show: { + resource:[ + 'member' + ], + operation: [ + 'create', + ], + jsonParameters: [ + false, + ], + }, + }, + description: 'An individual merge var and value for a member.', + options: [ + { + name: 'mergeFieldsValues', + displayName: 'Field', + typeOptions: { + multipleValueButtonText: 'Add Field' + }, + values: [ + { + displayName: 'Merge Field Name', + name: 'name', + type: 'string', + required: true, + description: 'The tag used in Mailchimp campaigns and for the /members endpoint.', + default: '' + }, + { + displayName: 'Merge Field Value', + name: 'value', + required: true, + type: 'string', + default: '', + description: 'The name of the merge field.', + }, + ], + }, + ], + }, + { + displayName: 'Merge Fields', + name: 'mergeFieldsJson', + type: 'json', + typeOptions: { + alwaysOpenEditWindow: true + }, + default: '', + description: '', + displayOptions: { + show: { + resource:[ + 'member' + ], + operation: [ + 'create', + ], + jsonParameters: [ + true + ], + }, + }, + }, + { + displayName: 'Location', + name: 'locationJson', + type: 'json', + typeOptions: { + alwaysOpenEditWindow: true + }, + default: '', + description: '', + displayOptions: { + show: { + resource:[ + 'member' + ], + operation: [ + 'create', + ], + jsonParameters: [ + true + ], + }, + }, + }, ] }; methods = { loadOptions: { - // Get all the available projects to display them to user so that he can + + + // Get all the available lists to display them to user so that he can // select them easily async getLists(this: ILoadOptionsFunctions): Promise { const returnData: INodePropertyOptions[] = []; @@ -99,19 +463,96 @@ export class Mailchimp implements INodeType { value: listId, }); } - return returnData; }, } }; async executeSingle(this: IExecuteSingleFunctions): Promise { - + let response = {}; const resource = this.getNodeParameter('resource') as string; - const opeation = this.getNodeParameter('operation') as string; + const operation = this.getNodeParameter('operation') as string; + if (resource === 'member') { + if (operation === 'create') { + + const listId = this.getNodeParameter('list') as string; + const email = this.getNodeParameter('email') as string; + const status = this.getNodeParameter('status') as Status; + const options = this.getNodeParameter('options') as IDataObject; + const jsonActive = this.getNodeParameter('jsonParameters') as IDataObject; + + const body: ICreateMemberBody = { + listId, + email_address: email, + status + }; + if (options.emailType) { + body.email_type = options.emailType as string; + } + if (options.languaje) { + body.language = options.language as string; + } + if (options.vip) { + body.vip = options.vip as boolean; + } + if (options.ipSignup) { + body.ips_signup = options.ipSignup as string; + } + if (options.ipOptIn) { + body.ip_opt = options.ipOptIn as string; + } + if (options.timestampOpt) { + body.timestamp_opt = moment(options.timestampOpt as string).format('YYYY-MM-DD HH:MM:SS') as string; + } + if (options.timestampSignup) { + body.timestamp_signup = moment(options.timestampSignup as string).format('YYYY-MM-DD HH:MM:SS') as string; + } + if (options.tags) { + // @ts-ignore + body.tags = options.tags.split(',') as string[]; + } + if (!jsonActive) { + const locationValues = (this.getNodeParameter('locationFieldsUi') as IDataObject).locationFieldsValues as IDataObject; + if (locationValues) { + const location: ILocation = {}; + for (const key of Object.keys(locationValues)) { + if (key === 'latitude') { + location.latitude = parseInt(locationValues[key] as string, 10) as number; + } else if (key === 'longitude') { + location.longitude = parseInt(locationValues[key] as string, 10) as number; + } + } + body.location = location; + } + const mergeFieldsValues = (this.getNodeParameter('mergeFieldsUi') as IDataObject).mergeFieldsValues as IDataObject[]; + if (mergeFieldsValues) { + const mergeFields = {}; + for (let i = 0; i < mergeFieldsValues.length; i++) { + // @ts-ignore + mergeFields[mergeFieldsValues[i].name] = mergeFieldsValues[i].value; + } + body.merge_fields = mergeFields; + } + } else { + const locationJson = validateJSON(this.getNodeParameter('locationJson') as string); + const mergeFieldsJson = validateJSON(this.getNodeParameter('mergeFieldsJson') as string); + if (locationJson) { + body.location = locationJson; + } + if (mergeFieldsJson) { + body.merge_fields = mergeFieldsJson; + } + } + try { + response = await mailchimpApiRequest.call(this, `/lists/${listId}/members`, 'POST', body); + } catch (err) { + throw new Error(`Mailchimp Error: ${JSON.stringify(err)}`); + } + } + } return { - json: {} + json: response }; } } From 325fff318e32da0d0a73e2f27515216986f4ee38 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Thu, 14 Nov 2019 18:47:12 -0500 Subject: [PATCH 3/4] fixed description --- packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts b/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts index bea30e4ee8..a214fd41de 100644 --- a/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts +++ b/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts @@ -374,7 +374,7 @@ export class Mailchimp implements INodeType { name: 'name', type: 'string', required: true, - description: 'The tag used in Mailchimp campaigns and for the /members endpoint.', + description: 'Merge Field name', default: '' }, { @@ -383,7 +383,7 @@ export class Mailchimp implements INodeType { required: true, type: 'string', default: '', - description: 'The name of the merge field.', + description: 'Merge field value.', }, ], }, From b5544cba943096f0eb787e234461d27ecedd8875 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Fri, 15 Nov 2019 21:44:46 +0100 Subject: [PATCH 4/4] :zap: Small adjustments on Mailchimp node --- .../credentials/MailchimpApi.credentials.ts | 6 --- .../nodes/Mailchimp/GenericFunctions.ts | 15 ++++-- .../nodes/Mailchimp/Mailchimp.node.ts | 52 +++++++++---------- packages/nodes-base/package.json | 8 +-- 4 files changed, 40 insertions(+), 41 deletions(-) diff --git a/packages/nodes-base/credentials/MailchimpApi.credentials.ts b/packages/nodes-base/credentials/MailchimpApi.credentials.ts index e2e98964da..c6a6462bc1 100644 --- a/packages/nodes-base/credentials/MailchimpApi.credentials.ts +++ b/packages/nodes-base/credentials/MailchimpApi.credentials.ts @@ -13,11 +13,5 @@ export class MailchimpApi implements ICredentialType { type: 'string' as NodePropertyTypes, default: '', }, - { - displayName: 'Datacenter', - name: 'datacenter', - type: 'string' as NodePropertyTypes, - default: '', - }, ]; } diff --git a/packages/nodes-base/nodes/Mailchimp/GenericFunctions.ts b/packages/nodes-base/nodes/Mailchimp/GenericFunctions.ts index fdf44bdc82..6f0aeb0e8c 100644 --- a/packages/nodes-base/nodes/Mailchimp/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Mailchimp/GenericFunctions.ts @@ -7,9 +7,8 @@ import { IExecuteSingleFunctions } from 'n8n-core'; -export async function mailchimpApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, resource: string, method: string, body: any = {}, headers?: object): Promise { // tslint:disable-line:no-any +export async function mailchimpApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, endpoint: string, method: string, body: any = {}, headers?: object): Promise { // tslint:disable-line:no-any const credentials = this.getCredentials('mailchimpApi'); - const datacenter = credentials!.datacenter as string; if (credentials === undefined) { throw new Error('No credentials got returned!'); @@ -17,13 +16,19 @@ export async function mailchimpApiRequest(this: IHookFunctions | IExecuteFunctio const headerWithAuthentication = Object.assign({}, headers, { Authorization: `apikey ${credentials.apiKey}` }); - const endpoint = 'api.mailchimp.com/3.0'; + if (!(credentials.apiKey as string).includes('-')) { + throw new Error('The API key is not valid!'); + } + + const datacenter = (credentials.apiKey as string).split('-').pop(); + + const host = 'api.mailchimp.com/3.0'; const options: OptionsWithUri = { headers: headerWithAuthentication, method, - uri: `https://${datacenter}.${endpoint}${resource}`, - json: true + uri: `https://${datacenter}.${host}${endpoint}`, + json: true, }; if (Object.keys(body).length !== 0) { diff --git a/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts b/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts index a214fd41de..187512ff29 100644 --- a/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts +++ b/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts @@ -1,26 +1,27 @@ +import * as moment from 'moment'; + import { IExecuteSingleFunctions, } from 'n8n-core'; import { IDataObject, + ILoadOptionsFunctions, INodeTypeDescription, INodeExecutionData, INodeType, - ILoadOptionsFunctions, INodePropertyOptions, } from 'n8n-workflow'; import { mailchimpApiRequest, - validateJSON + validateJSON, } from './GenericFunctions'; -import * as moment from 'moment'; enum Status { subscribe = 'subscribe', unsubscribed = 'unsubscribe', cleaned = 'cleaned', pending = 'pending', - transactional = 'transactional' + transactional = 'transactional', } interface ILocation { @@ -78,7 +79,7 @@ export class Mailchimp implements INodeType { description: 'Add member to list', }, ], - default: '', + default: 'member', required: true, description: 'Resource to consume.', }, @@ -101,7 +102,7 @@ export class Mailchimp implements INodeType { description: 'Create a new member on list', }, ], - default: '', + default: 'create', description: 'The operation to perform.', }, { @@ -114,7 +115,7 @@ export class Mailchimp implements INodeType { displayOptions: { show: { resource: [ - 'member' + 'member', ], operation: [ 'create', @@ -124,7 +125,7 @@ export class Mailchimp implements INodeType { default: '', options: [], required: true, - description: 'List of lists' + description: 'List of lists', }, { displayName: 'Email', @@ -215,7 +216,7 @@ export class Mailchimp implements INodeType { displayOptions: { show: { resource:[ - 'member' + 'member', ], operation: [ 'create', @@ -298,12 +299,12 @@ export class Mailchimp implements INodeType { name: 'locationFieldsUi', type: 'fixedCollection', placeholder: 'Add Location', - default: false, + default: {}, description: `Subscriber location information.n`, displayOptions: { show: { resource:[ - 'member' + 'member', ], operation: [ 'create', @@ -324,7 +325,7 @@ export class Mailchimp implements INodeType { type: 'string', required: true, description: 'The location latitude.', - default: '' + default: '', }, { displayName: 'Longitude', @@ -332,7 +333,7 @@ export class Mailchimp implements INodeType { type: 'string', required: true, description: 'The location longitude.', - default: '' + default: '', }, ], } @@ -343,7 +344,7 @@ export class Mailchimp implements INodeType { name: 'mergeFieldsUi', placeholder: 'Add Merge Fields', type: 'fixedCollection', - default: '', + default: {}, typeOptions: { multipleValues: true, }, @@ -366,19 +367,19 @@ export class Mailchimp implements INodeType { name: 'mergeFieldsValues', displayName: 'Field', typeOptions: { - multipleValueButtonText: 'Add Field' + multipleValueButtonText: 'Add Field', }, values: [ { - displayName: 'Merge Field Name', + displayName: 'Field Name', name: 'name', type: 'string', required: true, description: 'Merge Field name', - default: '' + default: '', }, { - displayName: 'Merge Field Value', + displayName: 'Field Value', name: 'value', required: true, type: 'string', @@ -394,20 +395,20 @@ export class Mailchimp implements INodeType { name: 'mergeFieldsJson', type: 'json', typeOptions: { - alwaysOpenEditWindow: true + alwaysOpenEditWindow: true, }, default: '', description: '', displayOptions: { show: { resource:[ - 'member' + 'member', ], operation: [ 'create', ], jsonParameters: [ - true + true, ], }, }, @@ -417,20 +418,20 @@ export class Mailchimp implements INodeType { name: 'locationJson', type: 'json', typeOptions: { - alwaysOpenEditWindow: true + alwaysOpenEditWindow: true, }, default: '', description: '', displayOptions: { show: { resource:[ - 'member' + 'member', ], operation: [ 'create', ], jsonParameters: [ - true + true, ], }, }, @@ -442,7 +443,6 @@ export class Mailchimp implements INodeType { methods = { loadOptions: { - // Get all the available lists to display them to user so that he can // select them easily async getLists(this: ILoadOptionsFunctions): Promise { @@ -552,7 +552,7 @@ export class Mailchimp implements INodeType { } } return { - json: response + json: response, }; } } diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 4c1afc425f..8b87d9e255 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -42,8 +42,8 @@ "dist/credentials/HttpHeaderAuth.credentials.js", "dist/credentials/Imap.credentials.js", "dist/credentials/LinkFishApi.credentials.js", - "dist/credentials/MailgunApi.credentials.js", - "dist/credentials/MailchimpApi.credentials.js", + "dist/credentials/MailchimpApi.credentials.js", + "dist/credentials/MailgunApi.credentials.js", "dist/credentials/MandrillApi.credentials.js", "dist/credentials/MattermostApi.credentials.js", "dist/credentials/MongoDb.credentials.js", @@ -98,8 +98,8 @@ "dist/nodes/If.node.js", "dist/nodes/Interval.node.js", "dist/nodes/LinkFish/LinkFish.node.js", - "dist/nodes/Mailgun/Mailgun.node.js", - "dist/nodes/Mailchimp/Mailchimp.node.js", + "dist/nodes/Mailchimp/Mailchimp.node.js", + "dist/nodes/Mailgun/Mailgun.node.js", "dist/nodes/Mandrill/Mandrill.node.js", "dist/nodes/Mattermost/Mattermost.node.js", "dist/nodes/Merge.node.js",