diff --git a/packages/nodes-base/credentials/MicrosoftToDoOAuth2Api.credentials.ts b/packages/nodes-base/credentials/MicrosoftToDoOAuth2Api.credentials.ts new file mode 100644 index 000000000..f1b798673 --- /dev/null +++ b/packages/nodes-base/credentials/MicrosoftToDoOAuth2Api.credentials.ts @@ -0,0 +1,22 @@ +import { + ICredentialType, + NodePropertyTypes, +} from 'n8n-workflow'; + +export class MicrosoftToDoOAuth2Api implements ICredentialType { + name = 'microsoftToDoOAuth2Api'; + extends = [ + 'microsoftOAuth2Api', + ]; + displayName = 'Microsoft To Do OAuth2 API'; + documentationUrl = 'microsoft'; + properties = [ + //https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent + { + displayName: 'Scope', + name: 'scope', + type: 'hidden' as NodePropertyTypes, + default: 'openid offline_access Tasks.ReadWrite', + }, + ]; +} diff --git a/packages/nodes-base/nodes/Microsoft/ToDo/GenericFunctions.ts b/packages/nodes-base/nodes/Microsoft/ToDo/GenericFunctions.ts new file mode 100644 index 000000000..d98e01f49 --- /dev/null +++ b/packages/nodes-base/nodes/Microsoft/ToDo/GenericFunctions.ts @@ -0,0 +1,76 @@ +import { + OptionsWithUri +} from 'request'; + +import { + IExecuteFunctions, +} from 'n8n-core'; + +import { + IDataObject, + ILoadOptionsFunctions, + NodeApiError, +} from 'n8n-workflow'; + +export async function microsoftApiRequest(this: IExecuteFunctions | ILoadOptionsFunctions, method: string, resource: string, body: IDataObject = {}, qs: IDataObject = {}, uri?: string, headers: IDataObject = {}, option: IDataObject = { json: true }) { + const options: OptionsWithUri = { + headers: { + 'Content-Type': 'application/json', + }, + method, + body, + qs, + uri: uri || `https://graph.microsoft.com/v1.0/me${resource}`, + }; + try { + Object.assign(options, option); + if (Object.keys(qs).length === 0) { + delete options.qs; + } + if (Object.keys(body).length === 0) { + delete options.body; + } + //@ts-ignore + return await this.helpers.requestOAuth2.call(this, 'microsoftToDoOAuth2Api', options); + } catch (error) { + throw new NodeApiError(this.getNode(), error); + } +} + +export async function microsoftApiRequestAllItems(this: IExecuteFunctions | ILoadOptionsFunctions, propertyName: string, method: string, endpoint: string, body: IDataObject = {}, query: IDataObject = {}) { + + const returnData: IDataObject[] = []; + + let responseData; + let uri: string | undefined; + query['$top'] = 100; + + do { + responseData = await microsoftApiRequest.call(this, method, endpoint, body, query, uri); + uri = responseData['@odata.nextLink']; + returnData.push.apply(returnData, responseData[propertyName]); + } while ( + responseData['@odata.nextLink'] !== undefined + ); + + return returnData; +} + +export async function microsoftApiRequestAllItemsSkip(this: IExecuteFunctions, propertyName: string, method: string, endpoint: string, body: IDataObject = {}, query: IDataObject = {}) { + + const returnData: IDataObject[] = []; + + let responseData; + query['$top'] = 100; + query['$skip'] = 0; + + do { + responseData = await microsoftApiRequest.call(this, method, endpoint, body, query); + query['$skip'] += query['$top']; + returnData.push.apply(returnData, responseData[propertyName]); + } while ( + responseData['value'].length !== 0 + ); + + return returnData; +} diff --git a/packages/nodes-base/nodes/Microsoft/ToDo/LinkedResourceDescription.ts b/packages/nodes-base/nodes/Microsoft/ToDo/LinkedResourceDescription.ts new file mode 100644 index 000000000..ddccc8666 --- /dev/null +++ b/packages/nodes-base/nodes/Microsoft/ToDo/LinkedResourceDescription.ts @@ -0,0 +1,282 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const linkedResourceOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'linkedResource', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + }, + { + name: 'Delete', + value: 'delete', + }, + { + name: 'Get', + value: 'get', + }, + { + name: 'Get All', + value: 'getAll', + }, + { + name: 'Update', + value: 'update', + }, + ], + default: 'get', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const linkedResourceFields = [ + /* -------------------------------------------------------------------------- */ + /* linkedResource:ALL */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Task List ID', + name: 'taskListId', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getTaskLists', + }, + displayOptions: { + show: { + operation: [ + 'create', + 'delete', + 'get', + 'getAll', + 'update', + ], + resource: [ + 'linkedResource', + ], + }, + }, + required: true, + default: '', + }, + { + displayName: 'Task ID', + name: 'taskId', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + 'delete', + 'get', + 'getAll', + 'update', + ], + resource: [ + 'linkedResource', + ], + }, + }, + required: true, + default: '', + }, + + /* -------------------------------------------------------------------------- */ + /* linkedResource:create */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Name', + name: 'displayName', + type: 'string', + default: '', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource: [ + 'linkedResource', + ], + }, + }, + description: 'Field indicating title of the linked entity.', + }, + { + displayName: 'Application Name', + name: 'applicationName', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource: [ + 'linkedResource', + ], + }, + }, + required: true, + default: '', + description: 'App name of the source that is sending the linked entity.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'linkedResource', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'External ID', + name: 'externalId', + type: 'string', + default: '', + description: 'ID of the object that is associated with this task on the third-party/partner system.', + }, + { + displayName: 'Web URL', + name: 'webUrl', + type: 'string', + default: '', + description: 'Deeplink to the linked entity.', + }, + ], + }, + + /* -------------------------------------------------------------------------- */ + /* linkedResource:get/delete/update */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Linked Resource ID', + name: 'linkedResourceId', + type: 'string', + displayOptions: { + show: { + resource: [ + 'linkedResource', + ], + operation: [ + 'delete', + 'get', + 'update', + ], + }, + }, + default: '', + required: true, + }, + + /* -------------------------------------------------------------------------- */ + /* linkedResource:getAll */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'linkedResource', + ], + 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: [ + 'linkedResource', + ], + operation: [ + 'getAll', + ], + returnAll: [false], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 50, + description: 'How many results to return.', + }, + + /* -------------------------------------------------------------------------- */ + /* linkedResource:update */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'linkedResource', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Application Name', + name: 'applicationName', + type: 'string', + default: '', + description: 'App name of the source that is sending the linked entity.', + }, + { + displayName: 'Name', + name: 'displayName', + type: 'string', + default: '', + description: 'Field indicating title of the linked entity.', + }, + { + displayName: 'External ID', + name: 'externalId', + type: 'string', + default: '', + description: 'ID of the object that is associated with this task on the third-party/partner system.', + }, + { + displayName: 'Web URL', + name: 'webUrl', + type: 'string', + default: '', + description: 'Deeplink to the linked entity.', + }, + ], + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Microsoft/ToDo/ListDescription.ts b/packages/nodes-base/nodes/Microsoft/ToDo/ListDescription.ts new file mode 100644 index 000000000..4bc175d92 --- /dev/null +++ b/packages/nodes-base/nodes/Microsoft/ToDo/ListDescription.ts @@ -0,0 +1,155 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const listOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'list', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + }, + { + name: 'Delete', + value: 'delete', + }, + { + name: 'Get', + value: 'get', + }, + { + name: 'Get All', + value: 'getAll', + }, + { + name: 'Update', + value: 'update', + }, + ], + default: 'get', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const listFields = [ + /* -------------------------------------------------------------------------- */ + /* list:create */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'List Name', + name: 'displayName', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource: [ + 'list', + ], + }, + }, + required: true, + default: '', + description: 'List display name.', + }, + + /* -------------------------------------------------------------------------- */ + /* list:get/delete/update */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'List ID', + name: 'listId', + type: 'string', + displayOptions: { + show: { + operation: [ + 'delete', + 'get', + 'update', + ], + resource: [ + 'list', + ], + }, + }, + required: true, + default: '', + description: 'The identifier of the list, unique in the user\'s mailbox.', + }, + + /* -------------------------------------------------------------------------- */ + /* list:getAll */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'list', + ], + 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: [ + 'list', + ], + operation: [ + 'getAll', + ], + returnAll: [false], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 50, + description: 'How many results to return.', + }, + + /* -------------------------------------------------------------------------- */ + /* list:update */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'New List Name', + name: 'displayName', + type: 'string', + displayOptions: { + show: { + operation: [ + 'update', + ], + resource: [ + 'list', + ], + }, + }, + required: true, + default: '', + description: 'List display name.', + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Microsoft/ToDo/MicrosoftToDo.node.json b/packages/nodes-base/nodes/Microsoft/ToDo/MicrosoftToDo.node.json new file mode 100644 index 000000000..622cee875 --- /dev/null +++ b/packages/nodes-base/nodes/Microsoft/ToDo/MicrosoftToDo.node.json @@ -0,0 +1,25 @@ +{ + "node": "n8n-nodes-base.microsoftToDo", + "nodeVersion": "1.0", + "codexVersion": "1.0", + "categories": [ + "Productivity" + ], + "resources": { + "credentialDocumentation": [ + { + "url": "https://docs.n8n.io/credentials/microsoft" + } + ], + "primaryDocumentation": [ + { + "url": "https://docs.n8n.io/nodes/n8n-nodes-base.microsoftToDo/" + } + ], + "generic": [ + ] + }, + "alias": [ + "Todo" + ] +} diff --git a/packages/nodes-base/nodes/Microsoft/ToDo/MicrosoftToDo.node.ts b/packages/nodes-base/nodes/Microsoft/ToDo/MicrosoftToDo.node.ts new file mode 100644 index 000000000..da31021a0 --- /dev/null +++ b/packages/nodes-base/nodes/Microsoft/ToDo/MicrosoftToDo.node.ts @@ -0,0 +1,334 @@ +import { + IExecuteFunctions, +} from 'n8n-core'; + +import { + IDataObject, + ILoadOptionsFunctions, + INodeExecutionData, + INodePropertyOptions, + INodeType, + INodeTypeDescription, + NodeOperationError, +} from 'n8n-workflow'; + +import { + microsoftApiRequest, + microsoftApiRequestAllItems, +} from './GenericFunctions'; + +import { + linkedResourceFields, + linkedResourceOperations, +} from './LinkedResourceDescription'; + +import { + taskFields, + taskOperations, +} from './TaskDescription'; + +import { + listFields, + listOperations, +} from './ListDescription'; + +import * as moment from 'moment-timezone'; + +export class MicrosoftToDo implements INodeType { + description: INodeTypeDescription = { + displayName: 'Microsoft To Do', + name: 'microsoftToDo', + icon: 'file:todo.svg', + group: ['input'], + version: 1, + subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', + description: 'Consume Microsoft To Do API.', + defaults: { + name: 'Microsoft To Do', + color: '#0078D7', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: 'microsoftToDoOAuth2Api', + required: true, + }, + ], + properties: [ + { + displayName: 'Resource', + name: 'resource', + type: 'options', + options: [ + { + name: 'Linked Resource', + value: 'linkedResource', + }, + { + name: 'List', + value: 'list', + }, + { + name: 'Task', + value: 'task', + }, + ], + default: 'task', + description: 'The resource to operate on.', + }, + ...linkedResourceOperations, + ...linkedResourceFields, + ...taskOperations, + ...taskFields, + ...listOperations, + ...listFields, + ], + }; + + methods = { + loadOptions: { + // Get all the team's channels to display them to user so that he can + // select them easily + async getTaskLists(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + const lists = await microsoftApiRequestAllItems.call(this, 'value', 'GET', '/todo/lists'); + for (const list of lists) { + returnData.push({ + name: list.displayName as string, + value: list.id as string, + }); + } + return returnData; + }, + }, + }; + + async execute(this: IExecuteFunctions): Promise { + const items = this.getInputData(); + const returnData: IDataObject[] = []; + const length = items.length as unknown as number; + const qs: IDataObject = {}; + let responseData; + const timezone = this.getTimezone(); + const resource = this.getNodeParameter('resource', 0) as string; + const operation = this.getNodeParameter('operation', 0) as string; + for (let i = 0; i < length; i++) { + try { + + if (resource === 'linkedResource') { + // https://docs.microsoft.com/en-us/graph/api/todotask-post-linkedresources?view=graph-rest-1.0&tabs=http + if (operation === 'create') { + + const taskListId = this.getNodeParameter('taskListId', i) as string; + const taskId = this.getNodeParameter('taskId', i) as string; + const body: IDataObject = { + applicationName: this.getNodeParameter('applicationName', i) as string, + displayName: this.getNodeParameter('displayName', i) as string, + ...this.getNodeParameter('additionalFields', i) as IDataObject[], + }; + + responseData = await microsoftApiRequest.call(this, 'POST', `/todo/lists/${taskListId}/tasks/${taskId}/linkedResources`, body, qs); + + // https://docs.microsoft.com/en-us/graph/api/linkedresource-delete?view=graph-rest-1.0&tabs=http + } else if (operation === 'delete') { + + const taskListId = this.getNodeParameter('taskListId', i) as string; + const taskId = this.getNodeParameter('taskId', i) as string; + const linkedResourceId = this.getNodeParameter('linkedResourceId', i) as string; + + responseData = await microsoftApiRequest.call(this, 'DELETE', `/todo/lists/${taskListId}/tasks/${taskId}/linkedResources/${linkedResourceId}`, undefined, qs); + responseData = { success: true }; + + // https://docs.microsoft.com/en-us/graph/api/linkedresource-get?view=graph-rest-1.0&tabs=http + } else if (operation === 'get') { + + const taskListId = this.getNodeParameter('taskListId', i) as string; + const taskId = this.getNodeParameter('taskId', i) as string; + const linkedResourceId = this.getNodeParameter('linkedResourceId', i) as string; + + responseData = await microsoftApiRequest.call(this, 'GET', `/todo/lists/${taskListId}/tasks/${taskId}/linkedResources/${linkedResourceId}`, undefined, qs); + + // https://docs.microsoft.com/en-us/graph/api/todotask-list-linkedresources?view=graph-rest-1.0&tabs=http + } else if (operation === 'getAll') { + + const taskListId = this.getNodeParameter('taskListId', i) as string; + const taskId = this.getNodeParameter('taskId', i) as string; + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + + if (returnAll === true) { + responseData = await microsoftApiRequestAllItems.call(this, 'value', 'GET', `/todo/lists/${taskListId}/tasks/${taskId}/linkedResources`, undefined, qs); + } else { + qs['$top'] = this.getNodeParameter('limit', i) as number; + responseData = await microsoftApiRequest.call(this, 'GET', `/todo/lists/${taskListId}/tasks/${taskId}/linkedResources`, undefined, qs); + responseData = responseData.value; + } + + // https://docs.microsoft.com/en-us/graph/api/linkedresource-update?view=graph-rest-1.0&tabs=http + } else if (operation === 'update') { + + const taskListId = this.getNodeParameter('taskListId', i) as string; + const taskId = this.getNodeParameter('taskId', i) as string; + const linkedResourceId = this.getNodeParameter('linkedResourceId', i) as string; + + const body: IDataObject = { + ...this.getNodeParameter('updateFields', i) as IDataObject[], + }; + + responseData = await microsoftApiRequest.call(this, 'PATCH', `/todo/lists/${taskListId}/tasks/${taskId}/linkedResources/${linkedResourceId}`, body, qs); + + + } else { + throw new NodeOperationError(this.getNode(), `The operation "${operation}" is not supported!`); + } + } else if (resource === 'task') { + + // https://docs.microsoft.com/en-us/graph/api/todotasklist-post-tasks?view=graph-rest-1.0&tabs=http + if (operation === 'create') { + + const taskListId = this.getNodeParameter('taskListId', i) as string; + const body: IDataObject = { + title: this.getNodeParameter('title', i) as string, + ...this.getNodeParameter('additionalFields', i) as IDataObject[], + }; + + if (body.content) { + body.body = { + content: body.content, + contentType: 'html', + }; + } + + if (body.dueDateTime) { + body.dueDateTime = { + dateTime: moment.tz(body.dueDateTime, timezone).format(), + timeZone: timezone, + }; + } + + responseData = await microsoftApiRequest.call(this, 'POST', `/todo/lists/${taskListId}/tasks`, body, qs); + + // https://docs.microsoft.com/en-us/graph/api/todotask-delete?view=graph-rest-1.0&tabs=http + } else if (operation === 'delete') { + + const taskListId = this.getNodeParameter('taskListId', i) as string; + const taskId = this.getNodeParameter('taskId', i) as string; + + responseData = await microsoftApiRequest.call(this, 'DELETE', `/todo/lists/${taskListId}/tasks/${taskId}`, undefined, qs); + responseData = { success: true }; + + // https://docs.microsoft.com/en-us/graph/api/todotask-get?view=graph-rest-1.0&tabs=http + } else if (operation === 'get') { + + const taskListId = this.getNodeParameter('taskListId', i) as string; + const taskId = this.getNodeParameter('taskId', i) as string; + + responseData = await microsoftApiRequest.call(this, 'GET', `/todo/lists/${taskListId}/tasks/${taskId}`, undefined, qs); + + // https://docs.microsoft.com/en-us/graph/api/todotasklist-list-tasks?view=graph-rest-1.0&tabs=http + } else if (operation === 'getAll') { + + const taskListId = this.getNodeParameter('taskListId', i) as string; + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + + if (returnAll === true) { + responseData = await microsoftApiRequestAllItems.call(this, 'value', 'GET', `/todo/lists/${taskListId}/tasks/`, undefined, qs); + } else { + qs['$top'] = this.getNodeParameter('limit', i) as number; + responseData = await microsoftApiRequest.call(this, 'GET', `/todo/lists/${taskListId}/tasks/`, undefined, qs); + responseData = responseData.value; + } + + // https://docs.microsoft.com/en-us/graph/api/todotask-update?view=graph-rest-1.0&tabs=http + } else if (operation === 'update') { + + const taskListId = this.getNodeParameter('taskListId', i) as string; + const taskId = this.getNodeParameter('taskId', i) as string; + const body: IDataObject = { + ...this.getNodeParameter('updateFields', i) as IDataObject[], + }; + + if (body.content) { + body.body = { + content: body.content, + contentType: 'html', + }; + } + + if (body.dueDateTime) { + body.dueDateTime = { + dateTime: moment.tz(body.dueDateTime, timezone).format(), + timeZone: timezone, + }; + } + + responseData = await microsoftApiRequest.call(this, 'PATCH', `/todo/lists/${taskListId}/tasks/${taskId}`, body, qs); + + } else { + throw new NodeOperationError(this.getNode(), `The operation "${operation}" is not supported!`); + } + + } else if (resource === 'list') { + + // https://docs.microsoft.com/en-us/graph/api/todo-post-lists?view=graph-rest-1.0&tabs=http + if (operation === 'create') { + + const body = { + displayName: this.getNodeParameter('displayName', i) as string, + }; + + responseData = await microsoftApiRequest.call(this, 'POST', '/todo/lists/', body, qs); + + // https://docs.microsoft.com/en-us/graph/api/todotasklist-delete?view=graph-rest-1.0&tabs=http + } else if (operation === 'delete') { + + const listId = this.getNodeParameter('listId', i) as string; + responseData = await microsoftApiRequest.call(this, 'DELETE', `/todo/lists/${listId}`, undefined, qs); + responseData = { success: true }; + + //https://docs.microsoft.com/en-us/graph/api/todotasklist-get?view=graph-rest-1.0&tabs=http + } else if (operation === 'get') { + + const listId = this.getNodeParameter('listId', i) as string; + responseData = await microsoftApiRequest.call(this, 'GET', `/todo/lists/${listId}`, undefined, qs); + + // https://docs.microsoft.com/en-us/graph/api/todo-list-lists?view=graph-rest-1.0&tabs=http + } else if (operation === 'getAll') { + + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + if (returnAll === true) { + responseData = await microsoftApiRequestAllItems.call(this, 'value', 'GET', '/todo/lists', undefined, qs); + } else { + qs['$top'] = this.getNodeParameter('limit', i) as number; + responseData = await microsoftApiRequest.call(this, 'GET', '/todo/lists', undefined, qs); + responseData = responseData.value; + } + + // https://docs.microsoft.com/en-us/graph/api/todotasklist-update?view=graph-rest-1.0&tabs=http + } else if (operation === 'update') { + + const listId = this.getNodeParameter('listId', i) as string; + const body = { + displayName: this.getNodeParameter('displayName', i) as string, + }; + + responseData = await microsoftApiRequest.call(this, 'PATCH', `/todo/lists/${listId}`, body, qs); + + } else { + throw new NodeOperationError(this.getNode(), `The operation "${operation}" is not supported!`); + } + } + } catch (error) { + if (this.continueOnFail()) { + returnData.push({ error: error.message }); + continue; + } + throw error; + } + Array.isArray(responseData) + ? returnData.push(...responseData) + : returnData.push(responseData); + } + return [this.helpers.returnJsonArray(returnData)]; + } +} diff --git a/packages/nodes-base/nodes/Microsoft/ToDo/TaskDescription.ts b/packages/nodes-base/nodes/Microsoft/ToDo/TaskDescription.ts new file mode 100644 index 000000000..cd6609a3f --- /dev/null +++ b/packages/nodes-base/nodes/Microsoft/ToDo/TaskDescription.ts @@ -0,0 +1,354 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const taskOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'task', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + }, + { + name: 'Delete', + value: 'delete', + }, + { + name: 'Get', + value: 'get', + }, + { + name: 'Get All', + value: 'getAll', + }, + { + name: 'Update', + value: 'update', + }, + ], + default: 'get', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const taskFields = [ + /* -------------------------------------------------------------------------- */ + /* task:create */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'List ID', + name: 'taskListId', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getTaskLists', + }, + displayOptions: { + show: { + operation: [ + 'create', + ], + resource: [ + 'task', + ], + }, + }, + required: true, + default: '', + description: 'The identifier of the list, unique in the user\'s mailbox.', + }, + { + displayName: 'Subject', + name: 'title', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource: [ + 'task', + ], + }, + }, + required: true, + default: '', + description: 'A brief description of the task.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'Content', + name: 'content', + type: 'string', + default: '', + description: 'The content of the task.', + }, + { + displayName: 'Due', + name: 'dueDateTime', + type: 'dateTime', + default: '', + description: 'The date in the specified time zone that the task is to be finished.', + }, + { + displayName: 'Importance', + name: 'importance', + type: 'options', + options: [ + { + name: 'Low', + value: 'low', + }, + { + name: 'Normal', + value: 'normal', + }, + { + name: 'High', + value: 'high', + }, + ], + default: 'normal', + description: 'The importance of the task.', + }, + { + displayName: 'Status', + name: 'status', + type: 'options', + options: [ + { + name: 'Not started', + value: 'notStarted', + }, + { + name: 'In progress', + value: 'inProgress', + }, + { + name: 'Completed', + value: 'completed', + }, + { + name: 'Waiting On Others', + value: 'waitingOnOthers', + }, + { + name: 'Deferred', + value: 'deferred', + }, + ], + default: 'notStarted', + description: 'Indicates the state or progress of the task.', + }, + ], + }, + + /* -------------------------------------------------------------------------- */ + /* task:get/delete/update/getAll */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'List ID', + name: 'taskListId', + type: 'options', + typeOptions: { + loadOptionsMethod: 'getTaskLists', + }, + displayOptions: { + show: { + operation: [ + 'delete', + 'get', + 'getAll', + 'update', + ], + resource: [ + 'task', + ], + }, + }, + required: true, + default: '', + description: 'The identifier of the list, unique in the user\'s mailbox.', + }, + { + displayName: 'Task ID', + name: 'taskId', + type: 'string', + displayOptions: { + show: { + operation: [ + 'delete', + 'get', + 'update', + ], + resource: [ + 'task', + ], + }, + }, + required: true, + default: '', + }, + + /* -------------------------------------------------------------------------- */ + /* task:getAll */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'task', + ], + 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: [ + 'task', + ], + operation: [ + 'getAll', + ], + returnAll: [false], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 50, + description: 'How many results to return.', + }, + + /* -------------------------------------------------------------------------- */ + /* task:update */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'task', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Content', + name: 'content', + type: 'string', + default: '', + description: 'The content of the task.', + }, + { + displayName: 'Due Date Time', + name: 'dueDateTime', + type: 'dateTime', + default: '', + description: 'The date in the specified time zone that the task is to be finished.', + }, + { + displayName: 'Importance', + name: 'importance', + type: 'options', + options: [ + { + name: 'Low', + value: 'low', + }, + { + name: 'Normal', + value: 'normal', + }, + { + name: 'High', + value: 'high', + }, + ], + default: 'normal', + description: 'The importance of the task.', + }, + { + displayName: 'Status', + name: 'status', + type: 'options', + options: [ + { + name: 'Not started', + value: 'notStarted', + }, + { + name: 'In progress', + value: 'inProgress', + }, + { + name: 'Completed', + value: 'completed', + }, + { + name: 'Waiting On Others', + value: 'waitingOnOthers', + }, + { + name: 'Deferred', + value: 'deferred', + }, + ], + default: 'notStarted', + description: 'Indicates the state or progress of the task.', + }, + { + displayName: 'Subject', + name: 'title', + type: 'string', + default: '', + description: 'A brief description of the task.', + }, + ], + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Microsoft/ToDo/todo.svg b/packages/nodes-base/nodes/Microsoft/ToDo/todo.svg new file mode 100644 index 000000000..69d2094ef --- /dev/null +++ b/packages/nodes-base/nodes/Microsoft/ToDo/todo.svg @@ -0,0 +1 @@ +To-Do_24x \ No newline at end of file diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 9d67a878b..a52a1781e 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -159,6 +159,7 @@ "dist/credentials/MicrosoftOutlookOAuth2Api.credentials.js", "dist/credentials/MicrosoftSql.credentials.js", "dist/credentials/MicrosoftTeamsOAuth2Api.credentials.js", + "dist/credentials/MicrosoftToDoOAuth2Api.credentials.js", "dist/credentials/MindeeReceiptApi.credentials.js", "dist/credentials/MindeeInvoiceApi.credentials.js", "dist/credentials/MoceanApi.credentials.js", @@ -443,6 +444,7 @@ "dist/nodes/Microsoft/Outlook/MicrosoftOutlook.node.js", "dist/nodes/Microsoft/Sql/MicrosoftSql.node.js", "dist/nodes/Microsoft/Teams/MicrosoftTeams.node.js", + "dist/nodes/Microsoft/ToDo/MicrosoftToDo.node.js", "dist/nodes/Mindee/Mindee.node.js", "dist/nodes/MoveBinaryData.node.js", "dist/nodes/Mocean/Mocean.node.js",