From 624da2f727980fb304b22681422099d29fd8d762 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Mon, 3 Feb 2020 12:51:22 -0500 Subject: [PATCH] :sparkles: Add custom fields support done --- .../nodes-base/nodes/ClickUp/ClickUp.node.ts | 39 +++- .../nodes/ClickUp/GenericFunctions.ts | 10 ++ .../nodes/ClickUp/ListDescription.ts | 170 ++++++++++++++++++ .../nodes/ClickUp/TaskDescription.ts | 100 +++++++++++ .../nodes-base/nodes/ClickUp/TaskInterface.ts | 3 + 5 files changed, 321 insertions(+), 1 deletion(-) create mode 100644 packages/nodes-base/nodes/ClickUp/ListDescription.ts diff --git a/packages/nodes-base/nodes/ClickUp/ClickUp.node.ts b/packages/nodes-base/nodes/ClickUp/ClickUp.node.ts index 1578243214..1a4eb5f7c2 100644 --- a/packages/nodes-base/nodes/ClickUp/ClickUp.node.ts +++ b/packages/nodes-base/nodes/ClickUp/ClickUp.node.ts @@ -12,11 +12,16 @@ import { import { clickupApiRequest, clickupApiRequestAllItems, + validateJSON, } from './GenericFunctions'; import { taskFields, taskOperations, } from './TaskDescription'; +import { + listFields, + listOperations, +} from './ListDescription'; import { ITask, } from './TaskInterface'; @@ -52,12 +57,18 @@ export class ClickUp implements INodeType { name: 'Task', value: 'task', }, + { + name: 'List', + value: 'list', + }, ], default: 'task', description: 'Resource to consume.', }, ...taskOperations, ...taskFields, + ...listOperations, + ...listFields, ], }; @@ -208,6 +219,7 @@ export class ClickUp implements INodeType { if (operation === 'create') { const listId = this.getNodeParameter('list', i) as string; const name = this.getNodeParameter('name', i) as string; + const jsonActive = this.getNodeParameter('jsonParameters', i) as boolean; const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const body: ITask = { name, @@ -252,7 +264,13 @@ export class ClickUp implements INodeType { delete body.content; body.markdown_content = additionalFields.content as string; } - + if (jsonActive) { + const customFields = validateJSON(this.getNodeParameter('customFieldsJson', i) as string); + if (customFields === undefined) { + throw new Error('Custom Fields: Invalid JSON'); + } + body.custom_fields = customFields; + } responseData = await clickupApiRequest.call(this, 'POST', `/list/${listId}/task`, body); } if (operation === 'update') { @@ -351,11 +369,30 @@ export class ClickUp implements INodeType { // responseData = responseData.tasks; } } + if (operation === 'setCustomField') { + const taskId = this.getNodeParameter('task', i) as string; + const fieldId = this.getNodeParameter('field', i) as string; + const value = this.getNodeParameter('value', i) as string; + const body: IDataObject = {}; + body.value = value; + //@ts-ignore + if (!isNaN(value)) { + body.value = parseInt(value, 10); + } + responseData = await clickupApiRequest.call(this, 'POST', `/task/${taskId}/field/${fieldId}`, body); + } if (operation === 'delete') { const taskId = this.getNodeParameter('id', i) as string; responseData = await clickupApiRequest.call(this, 'DELETE', `/task/${taskId}`, {}); } } + if (resource === 'list') { + if (operation === 'customFields') { + const listId = this.getNodeParameter('list', i) as string; + responseData = await clickupApiRequest.call(this, 'GET', `/list/${listId}/field`); + responseData = responseData.fields; + } + } if (Array.isArray(responseData)) { returnData.push.apply(returnData, responseData as IDataObject[]); } else { diff --git a/packages/nodes-base/nodes/ClickUp/GenericFunctions.ts b/packages/nodes-base/nodes/ClickUp/GenericFunctions.ts index d58ee1189a..5ef1238b84 100644 --- a/packages/nodes-base/nodes/ClickUp/GenericFunctions.ts +++ b/packages/nodes-base/nodes/ClickUp/GenericFunctions.ts @@ -54,3 +54,13 @@ export async function clickupApiRequestAllItems(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/ClickUp/ListDescription.ts b/packages/nodes-base/nodes/ClickUp/ListDescription.ts new file mode 100644 index 0000000000..517d8497f2 --- /dev/null +++ b/packages/nodes-base/nodes/ClickUp/ListDescription.ts @@ -0,0 +1,170 @@ +import { INodeProperties } from 'n8n-workflow'; + +export const listOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'list', + ], + }, + }, + options: [ + { + name: 'Custom Fields', + value: 'customFields', + description: `Retrieve list's custom fields`, + }, + ], + default: 'customFields', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const listFields = [ + +/* -------------------------------------------------------------------------- */ +/* list:customFields */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Team', + name: 'team', + type: 'options', + default: '', + displayOptions: { + show: { + resource: [ + 'list', + ], + operation: [ + 'customFields', + ], + }, + }, + typeOptions: { + loadOptionsMethod: 'getTeams', + }, + required: true, + }, + { + displayName: 'Space', + name: 'space', + type: 'options', + default: '', + displayOptions: { + show: { + resource: [ + 'list', + ], + operation: [ + 'customFields', + ], + }, + }, + typeOptions: { + loadOptionsMethod: 'getSpaces', + loadOptionsDependsOn: [ + 'team', + ] + }, + required: true, + }, + { + displayName: 'Folderless List', + name: 'folderless', + type: 'boolean', + default: false, + displayOptions: { + show: { + resource: [ + 'list', + ], + operation: [ + 'customFields', + ], + }, + }, + required: true, + }, + { + displayName: 'Folder', + name: 'folder', + type: 'options', + default: '', + displayOptions: { + show: { + resource: [ + 'list', + ], + operation: [ + 'customFields', + ], + folderless: [ + false, + ], + }, + }, + typeOptions: { + loadOptionsMethod: 'getFolders', + loadOptionsDependsOn: [ + 'space', + ], + }, + required: true, + }, + { + displayName: 'List', + name: 'list', + type: 'options', + default: '', + displayOptions: { + show: { + resource: [ + 'list', + ], + operation: [ + 'customFields', + ], + folderless: [ + true, + ], + }, + }, + typeOptions: { + loadOptionsMethod: 'getFolderlessLists', + loadOptionsDependsOn: [ + 'space', + ], + }, + required: true, + }, + { + displayName: 'List', + name: 'list', + type: 'options', + default: '', + displayOptions: { + show: { + resource: [ + 'list', + ], + operation: [ + 'customFields', + ], + folderless: [ + false, + ], + }, + }, + typeOptions: { + loadOptionsMethod: 'getLists', + loadOptionsDependsOn: [ + 'folder', + ] + }, + required: true, + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/ClickUp/TaskDescription.ts b/packages/nodes-base/nodes/ClickUp/TaskDescription.ts index 4f1bcb53ef..56c60d6624 100644 --- a/packages/nodes-base/nodes/ClickUp/TaskDescription.ts +++ b/packages/nodes-base/nodes/ClickUp/TaskDescription.ts @@ -33,6 +33,11 @@ export const taskOperations = [ value: 'getAll', description: 'Get all tasks', }, + { + name: 'Set custom field', + value: 'setCustomField', + description: 'Set a custom field', + }, { name: 'Update', value: 'update', @@ -205,6 +210,22 @@ export const taskFields = [ required: true, description: 'The first name on the task', }, + { + displayName: 'JSON Parameters', + name: 'jsonParameters', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'create', + ] + }, + }, + default: false, + }, { displayName: 'Additional Fields', name: 'additionalFields', @@ -325,6 +346,28 @@ export const taskFields = [ }, ], }, + { + displayName: 'Custom Fields', + name: 'customFieldsJson', + type: 'json', + typeOptions: { + alwaysOpenEditWindow: true, + }, + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'create', + ], + jsonParameters: [ + true, + ], + }, + }, + default: '', + }, /* -------------------------------------------------------------------------- */ /* task:update */ /* -------------------------------------------------------------------------- */ @@ -802,4 +845,61 @@ export const taskFields = [ }, description: 'task ID', }, +/* -------------------------------------------------------------------------- */ +/* task:setCustomField */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Task ID', + name: 'task', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'setCustomField', + ], + }, + }, + description: 'Task ID', + }, + { + displayName: 'Field ID', + name: 'field', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'setCustomField', + ], + }, + }, + description: 'Task ID', + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'setCustomField', + ], + }, + }, + description: 'Value', + }, ] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/ClickUp/TaskInterface.ts b/packages/nodes-base/nodes/ClickUp/TaskInterface.ts index 70a3899e15..44a61805f5 100644 --- a/packages/nodes-base/nodes/ClickUp/TaskInterface.ts +++ b/packages/nodes-base/nodes/ClickUp/TaskInterface.ts @@ -1,3 +1,5 @@ +import { IDataObject } from "n8n-workflow"; + export interface ITask { name?: string; content?: string; @@ -13,4 +15,5 @@ export interface ITask { markdown_content?: string; notify_all?: boolean; parent?: string; + custom_fields?: IDataObject[]; }