From f5648fd6e10dd51c33d83b35cf9d66e074eadf4d Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Tue, 5 Nov 2019 10:17:06 -0500 Subject: [PATCH 1/4] node-setup --- .../credentials/TodoistApi.credentials.ts | 18 ++++ .../nodes/Todoist/GenericFunctions.ts | 101 ++++++++++++++++++ .../nodes-base/nodes/Todoist/Todoist.node.ts | 90 ++++++++++++++++ packages/nodes-base/nodes/Todoist/todoist.png | Bin 0 -> 4475 bytes packages/nodes-base/package.json | 6 +- 5 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 packages/nodes-base/credentials/TodoistApi.credentials.ts create mode 100644 packages/nodes-base/nodes/Todoist/GenericFunctions.ts create mode 100644 packages/nodes-base/nodes/Todoist/Todoist.node.ts create mode 100644 packages/nodes-base/nodes/Todoist/todoist.png diff --git a/packages/nodes-base/credentials/TodoistApi.credentials.ts b/packages/nodes-base/credentials/TodoistApi.credentials.ts new file mode 100644 index 0000000000..cec053e40e --- /dev/null +++ b/packages/nodes-base/credentials/TodoistApi.credentials.ts @@ -0,0 +1,18 @@ +import { + ICredentialType, + NodePropertyTypes, +} from 'n8n-workflow'; + + +export class TodoistApi implements ICredentialType { + name = 'todoistApi'; + displayName = 'Todoist API'; + properties = [ + { + displayName: 'API Key', + name: 'apiKey', + type: 'string' as NodePropertyTypes, + default: '', + }, + ]; +} diff --git a/packages/nodes-base/nodes/Todoist/GenericFunctions.ts b/packages/nodes-base/nodes/Todoist/GenericFunctions.ts new file mode 100644 index 0000000000..f98b54f1c7 --- /dev/null +++ b/packages/nodes-base/nodes/Todoist/GenericFunctions.ts @@ -0,0 +1,101 @@ +import { OptionsWithUri } from 'request'; + +import { + IExecuteFunctions, + IHookFunctions, + ILoadOptionsFunctions, + IExecuteSingleFunctions +} from 'n8n-core'; + +import * as _ from 'lodash'; +import { IDataObject } from 'n8n-workflow'; + +export async function mandrillApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, resource: string, method: string, action: string, body: any = {}, headers?: object): Promise { // tslint:disable-line:no-any + const credentials = this.getCredentials('mandrillApi'); + + if (credentials === undefined) { + throw new Error('No credentials got returned!'); + } + + const data = Object.assign({}, body, { key: credentials.apiKey }); + + const endpoint = 'mandrillapp.com/api/1.0'; + + const options: OptionsWithUri = { + headers, + method, + uri: `https://${endpoint}${resource}${action}.json`, + body: data, + json: true + }; + + + try { + return await this.helpers.request!(options); + } catch (error) { + console.error(error); + + const errorMessage = error.response.body.message || error.response.body.Message; + if (error.name === 'Invalid_Key') { + throw new Error('The provided API key is not a valid Mandrill API key'); + } else if (error.name === 'ValidationError') { + throw new Error('The parameters passed to the API call are invalid or not provided when required'); + } else if (error.name === 'GeneralError') { + throw new Error('An unexpected error occurred processing the request. Mandrill developers will be notified.'); + } + + if (errorMessage !== undefined) { + throw errorMessage; + } + throw error.response.body; + } +} + +export function getToEmailArray(toEmail: string): any { // tslint:disable-line:no-any + let toEmailArray; + if (toEmail.split(',').length > 0) { + const array = toEmail.split(','); + toEmailArray = _.map(array, (email) => { + return { + email, + type: 'to' + }; + }); + } else { + toEmailArray = [{ + email: toEmail, + type: 'to' + }]; + } + return toEmailArray; +} + +export function getGoogleAnalyticsDomainsArray(s: string): string[] { + let array: string[] = []; + if (s.split(',').length > 0) { + array = s.split(','); + } else { + array = [s]; + } + return array; +} + +export function getTags(s: string): any[] { // tslint:disable-line:no-any + let array = []; + if (s.split(',').length > 0) { + array = s.split(','); + } else { + array = [s]; + } + return array; +} + +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/Todoist/Todoist.node.ts b/packages/nodes-base/nodes/Todoist/Todoist.node.ts new file mode 100644 index 0000000000..b2f6b7dd22 --- /dev/null +++ b/packages/nodes-base/nodes/Todoist/Todoist.node.ts @@ -0,0 +1,90 @@ +import { + IExecuteSingleFunctions, +} from 'n8n-core'; +import { + IDataObject, + INodeTypeDescription, + INodeExecutionData, + INodeType, + ILoadOptionsFunctions, + INodePropertyOptions, +} from 'n8n-workflow'; +import { + mandrillApiRequest, + getToEmailArray, + getGoogleAnalyticsDomainsArray, + getTags, + validateJSON +} from './GenericFunctions'; + +export class Todoist implements INodeType { + + //https://mandrillapp.com/api/docs/messages.JSON.html#method=send-template + + description: INodeTypeDescription = { + displayName: 'Todoist', + name: 'todoist', + icon: 'file:todoist.png', + group: ['output'], + version: 1, + subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', + description: 'Consume Todoist API', + defaults: { + name: 'Todoist', + color: '#c02428', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: 'todoistApi', + required: true, + } + ], + //multiOptions + properties: [ + { + displayName: 'Testing', + name: 'testing', + placeholder: 'blabla', + type: 'fixedCollection', + default: '', + typeOptions: { + multipleValues: true, + }, + options: [ + { + name: 'label', + displayName: 'label', + values: [ + { + displayName: 'Name', + name: 'name', + type: 'options', + default: '', + options: [ + { + name: 'Message', + value: 'message', + description: 'Send a message.', + }, + ], + }, + { + displayName: 'Content', + name: 'content', + type: 'string', + default: '', + }, + ], + }, + ], + }, + ], + }; + + async executeSingle(this: IExecuteSingleFunctions): Promise { + + + } +} diff --git a/packages/nodes-base/nodes/Todoist/todoist.png b/packages/nodes-base/nodes/Todoist/todoist.png new file mode 100644 index 0000000000000000000000000000000000000000..44691b2e49ded88dcdc5e60c893304c6d2643598 GIT binary patch literal 4475 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 E0tIwB)&Kwi literal 0 HcmV?d00001 diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 2b6ddeca77..6af0a99a5c 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -56,7 +56,8 @@ "dist/credentials/TrelloApi.credentials.js", "dist/credentials/TwilioApi.credentials.js", "dist/credentials/TypeformApi.credentials.js", - "dist/credentials/MandrillApi.credentials.js" + "dist/credentials/MandrillApi.credentials.js", + "dist/credentials/TodoistApi.credentials.js" ], "nodes": [ "dist/nodes/ActiveCampaign/ActiveCampaign.node.js", @@ -122,7 +123,8 @@ "dist/nodes/WriteBinaryFile.node.js", "dist/nodes/Webhook.node.js", "dist/nodes/Xml.node.js", - "dist/nodes/Mandrill/Mandrill.node.js" + "dist/nodes/Mandrill/Mandrill.node.js", + "dist/nodes/Todoist/Todoist.node.js" ] }, "devDependencies": { From 39b1af94b99203a3bbe9e84dede9dd9d8f5e9833 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Tue, 5 Nov 2019 15:56:10 -0500 Subject: [PATCH 2/4] done --- .../nodes/Todoist/GenericFunctions.ts | 75 +----- .../nodes-base/nodes/Todoist/Todoist.node.ts | 243 +++++++++++++++--- packages/nodes-base/nodes/Todoist/todoist.png | Bin 4475 -> 8402 bytes 3 files changed, 212 insertions(+), 106 deletions(-) diff --git a/packages/nodes-base/nodes/Todoist/GenericFunctions.ts b/packages/nodes-base/nodes/Todoist/GenericFunctions.ts index f98b54f1c7..3362a8581c 100644 --- a/packages/nodes-base/nodes/Todoist/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Todoist/GenericFunctions.ts @@ -10,39 +10,35 @@ import { import * as _ from 'lodash'; import { IDataObject } from 'n8n-workflow'; -export async function mandrillApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, resource: string, method: string, action: string, body: any = {}, headers?: object): Promise { // tslint:disable-line:no-any - const credentials = this.getCredentials('mandrillApi'); +export async function todoistApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, resource: string, method: string, body: any = {}, headers?: object): Promise { // tslint:disable-line:no-any + const credentials = this.getCredentials('todoistApi'); if (credentials === undefined) { throw new Error('No credentials got returned!'); } - const data = Object.assign({}, body, { key: credentials.apiKey }); + const headerWithAuthentication = Object.assign({}, headers, { Authorization: `Bearer ${credentials.apiKey}` }); - const endpoint = 'mandrillapp.com/api/1.0'; + const endpoint = 'api.todoist.com/rest/v1'; const options: OptionsWithUri = { - headers, + headers: headerWithAuthentication, method, - uri: `https://${endpoint}${resource}${action}.json`, - body: data, + body, + uri: `https://${endpoint}${resource}`, json: true }; + if (_.isEmpty(options.body)) { + delete options.body + } try { return await this.helpers.request!(options); } catch (error) { - console.error(error); + //console.error(error); const errorMessage = error.response.body.message || error.response.body.Message; - if (error.name === 'Invalid_Key') { - throw new Error('The provided API key is not a valid Mandrill API key'); - } else if (error.name === 'ValidationError') { - throw new Error('The parameters passed to the API call are invalid or not provided when required'); - } else if (error.name === 'GeneralError') { - throw new Error('An unexpected error occurred processing the request. Mandrill developers will be notified.'); - } if (errorMessage !== undefined) { throw errorMessage; @@ -50,52 +46,3 @@ export async function mandrillApiRequest(this: IHookFunctions | IExecuteFunction throw error.response.body; } } - -export function getToEmailArray(toEmail: string): any { // tslint:disable-line:no-any - let toEmailArray; - if (toEmail.split(',').length > 0) { - const array = toEmail.split(','); - toEmailArray = _.map(array, (email) => { - return { - email, - type: 'to' - }; - }); - } else { - toEmailArray = [{ - email: toEmail, - type: 'to' - }]; - } - return toEmailArray; -} - -export function getGoogleAnalyticsDomainsArray(s: string): string[] { - let array: string[] = []; - if (s.split(',').length > 0) { - array = s.split(','); - } else { - array = [s]; - } - return array; -} - -export function getTags(s: string): any[] { // tslint:disable-line:no-any - let array = []; - if (s.split(',').length > 0) { - array = s.split(','); - } else { - array = [s]; - } - return array; -} - -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/Todoist/Todoist.node.ts b/packages/nodes-base/nodes/Todoist/Todoist.node.ts index b2f6b7dd22..5484b987bc 100644 --- a/packages/nodes-base/nodes/Todoist/Todoist.node.ts +++ b/packages/nodes-base/nodes/Todoist/Todoist.node.ts @@ -10,16 +10,12 @@ import { INodePropertyOptions, } from 'n8n-workflow'; import { - mandrillApiRequest, - getToEmailArray, - getGoogleAnalyticsDomainsArray, - getTags, - validateJSON + todoistApiRequest } from './GenericFunctions'; -export class Todoist implements INodeType { +import moment = require('moment'); - //https://mandrillapp.com/api/docs/messages.JSON.html#method=send-template +export class Todoist implements INodeType { description: INodeTypeDescription = { displayName: 'Todoist', @@ -41,50 +37,213 @@ export class Todoist implements INodeType { required: true, } ], - //multiOptions properties: [ - { - displayName: 'Testing', - name: 'testing', - placeholder: 'blabla', - type: 'fixedCollection', + { + displayName: 'Resource', + name: 'resource', + type: 'options', + options: [ + { + name: 'Task', + value: 'task', + description: 'Task resource.', + }, + ], default: '', - typeOptions: { - multipleValues: true, + required: true, + description: 'Resource to consume.', + }, + { + displayName: 'Operation', + name: 'operation', + type: 'options', + required: true, + displayOptions: { + show: { + resource: [ + 'task', + ], + }, }, options: [ { - name: 'label', - displayName: 'label', - values: [ - { - displayName: 'Name', - name: 'name', - type: 'options', - default: '', - options: [ - { - name: 'Message', - value: 'message', - description: 'Send a message.', - }, - ], - }, - { - displayName: 'Content', - name: 'content', - type: 'string', - default: '', - }, - ], + name: 'Create', + value: 'create', + description: 'Create a new task', }, ], - }, - ], - }; + default: 'create', + description: 'The operation to perform.', + }, + { + displayName: 'Project', + name: 'project', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getProjects', + }, + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'create' + ] + }, + }, + default: [], + description: 'The project you want to add the task to.', + }, + { + displayName: 'Content', + name: 'content', + type: 'string', + typeOptions: { + rows: 5, + }, + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'create' + ] + }, + }, + default: [], + required: true, + description: 'Task content', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Option', + default: {}, + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'create' + ] + }, + }, + options: [ + { + displayName: 'Priority', + name: 'priority', + type: 'number', + typeOptions: { + numberStepSize: 1, + maxValue: 4, + minValue: 1 + }, + default: 1, + description: 'Task priority from 1 (normal) to 4 (urgent).', + }, + { + displayName: 'Due Date Time', + name: 'dueDateTime', + type: 'dateTime', + default: '', + description: 'Specific date and time in RFC3339 format in UTC.', + }, + { + displayName: 'Due String', + name: 'dueString', + type: 'string', + default: '', + description: 'Human defined task due date (ex.: “next Monday”, “Tomorrow”). Value is set using local (not UTC) time.', + }, + ] + } + ] + }; + + + methods = { + loadOptions: { + // Get all the available projects to display them to user so that he can + // select them easily + async getProjects(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + let projects; + try { + projects = await todoistApiRequest.call(this, '/projects', 'GET'); + } catch (err) { + throw new Error(`Todoist Error: ${err}`); + } + for (const project of projects) { + const projectName = project.name; + const projectId = project.id; + + returnData.push({ + name: projectName, + value: projectId, + }); + } + + return returnData + } + }, + }; + async executeSingle(this: IExecuteSingleFunctions): Promise { - + const resource = this.getNodeParameter('resource') as string; + const opeation = this.getNodeParameter('operation') as string; + let response; + + if (resource === 'task' && opeation === 'create') { + + //https://developer.todoist.com/rest/v1/#create-a-new-task + + const content = this.getNodeParameter('content') as string; + const projectId = this.getNodeParameter('project') as number; + const options = this.getNodeParameter('options') as IDataObject; + + + interface IBodyCreateTask { + content: string; + project_id?: number; + parent?: number; + order?: number; + label_ids?: [number]; + priority?: number; + due_string?: string; + due_datetime?: string; + due_date?: string; + due_lang?: string; + } + + const body: IBodyCreateTask = { + content, + project_id: projectId, + priority: (options.priority!) ? parseInt(options.priority, 10) : 1, + } + + if (options.dueDateTime) { + body.due_datetime = moment(options.dueDateTime).utc().format() + } + + if (options.dueString) { + body.due_string = options.dueString + } + + try { + response = await todoistApiRequest.call(this, '/tasks', 'POST', body); + } catch (err) { + throw new Error(`Todoist Error: ${err}`); + } + } + + return { + json: response, + }; } } diff --git a/packages/nodes-base/nodes/Todoist/todoist.png b/packages/nodes-base/nodes/Todoist/todoist.png index 44691b2e49ded88dcdc5e60c893304c6d2643598..5ce577f317a669cf3f0cd6f569bbfbf6ffa7cbcf 100644 GIT binary patch literal 8402 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 literal 4475 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 E0tIwB)&Kwi From 9d50fb0c3361eceb3ac98a6f75da2c2aaa5db551 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Tue, 5 Nov 2019 18:50:55 -0500 Subject: [PATCH 3/4] done --- .../nodes-base/nodes/Todoist/Todoist.node.ts | 68 ++++++++++++++++--- 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/packages/nodes-base/nodes/Todoist/Todoist.node.ts b/packages/nodes-base/nodes/Todoist/Todoist.node.ts index 5484b987bc..db585c3e99 100644 --- a/packages/nodes-base/nodes/Todoist/Todoist.node.ts +++ b/packages/nodes-base/nodes/Todoist/Todoist.node.ts @@ -14,6 +14,7 @@ import { } from './GenericFunctions'; import moment = require('moment'); +import _ = require('lodash') export class Todoist implements INodeType { @@ -94,6 +95,27 @@ export class Todoist implements INodeType { }, default: [], description: 'The project you want to add the task to.', + }, + { + displayName: 'Labels', + name: 'labels', + type: 'multiOptions', + typeOptions: { + loadOptionsMethod: 'getLabels', + }, + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'create' + ] + }, + }, + default: [], + required: false, + description: 'Labels', }, { displayName: 'Content', @@ -115,7 +137,7 @@ export class Todoist implements INodeType { default: [], required: true, description: 'Task content', - }, + }, { displayName: 'Options', name: 'options', @@ -187,12 +209,34 @@ export class Todoist implements INodeType { }); } + return returnData + }, + + // Get all the available labels to display them to user so that he can + // select them easily + async getLabels(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + let labels; + try { + labels = await todoistApiRequest.call(this, '/labels', 'GET'); + } catch (err) { + throw new Error(`Todoist Error: ${err}`); + } + for (const label of labels) { + const labelName = label.name; + const labelId = label.id; + + returnData.push({ + name: labelName, + value: labelId, + }); + } + return returnData } - }, + } }; - async executeSingle(this: IExecuteSingleFunctions): Promise { const resource = this.getNodeParameter('resource') as string; @@ -205,9 +249,9 @@ export class Todoist implements INodeType { const content = this.getNodeParameter('content') as string; const projectId = this.getNodeParameter('project') as number; + const labels = this.getNodeParameter('labels') as [number]; const options = this.getNodeParameter('options') as IDataObject; - interface IBodyCreateTask { content: string; project_id?: number; @@ -224,17 +268,23 @@ export class Todoist implements INodeType { const body: IBodyCreateTask = { content, project_id: projectId, - priority: (options.priority!) ? parseInt(options.priority, 10) : 1, - } + priority: (options.priority!) ? parseInt(options.priority as string, 10) : 1, + }; if (options.dueDateTime) { - body.due_datetime = moment(options.dueDateTime).utc().format() + body.due_datetime = moment(options.dueDateTime as string).utc().format(); } if (options.dueString) { - body.due_string = options.dueString + body.due_string = options.dueString as string; } + if (!_.isEmpty(labels)) { + body.label_ids = labels + } + + console.log(labels) + try { response = await todoistApiRequest.call(this, '/tasks', 'POST', body); } catch (err) { @@ -243,7 +293,7 @@ export class Todoist implements INodeType { } return { - json: response, + json: response }; } } From 4e1ac1eb2f3eccf6d1a487f18defe70bd1007d75 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Tue, 5 Nov 2019 18:57:04 -0500 Subject: [PATCH 4/4] removed console.log --- packages/nodes-base/nodes/Todoist/Todoist.node.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/nodes-base/nodes/Todoist/Todoist.node.ts b/packages/nodes-base/nodes/Todoist/Todoist.node.ts index db585c3e99..71eaa9b3d2 100644 --- a/packages/nodes-base/nodes/Todoist/Todoist.node.ts +++ b/packages/nodes-base/nodes/Todoist/Todoist.node.ts @@ -283,8 +283,6 @@ export class Todoist implements INodeType { body.label_ids = labels } - console.log(labels) - try { response = await todoistApiRequest.call(this, '/tasks', 'POST', body); } catch (err) {