diff --git a/packages/nodes-base/nodes/Harvest/ClientDescription.ts b/packages/nodes-base/nodes/Harvest/ClientDescription.ts index 3950b35255..7a98fe89ce 100644 --- a/packages/nodes-base/nodes/Harvest/ClientDescription.ts +++ b/packages/nodes-base/nodes/Harvest/ClientDescription.ts @@ -1,4 +1,6 @@ -import { INodeProperties } from "n8n-workflow"; +import { INodeProperties } from 'n8n-workflow'; + +const resource = ['client']; export const clientOperations = [ { @@ -7,12 +9,20 @@ export const clientOperations = [ type: 'options', displayOptions: { show: { - resource: [ - 'client', - ], + resource, }, }, options: [ + { + name: 'Create', + value: 'create', + description: `Create a client`, + }, + { + name: 'Delete', + value: 'delete', + description: `Delete a client`, + }, { name: 'Get', value: 'get', @@ -23,6 +33,12 @@ export const clientOperations = [ value: 'getAll', description: 'Get data of all clients', }, + + { + name: 'Update', + value: 'update', + description: `Update a client`, + }, ], default: 'getAll', description: 'The operation to perform.', @@ -32,105 +48,240 @@ export const clientOperations = [ export const clientFields = [ -/* -------------------------------------------------------------------------- */ -/* client:getAll */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* client:getAll */ + /* -------------------------------------------------------------------------- */ -{ - displayName: 'Return All', - name: 'returnAll', - type: 'boolean', - displayOptions: { - show: { - resource: [ - 'client', - ], - operation: [ - 'getAll', - ], + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource, + operation: [ + 'getAll', + ], + }, }, + default: false, + description: 'Returns a list of your clients.', }, - default: false, - description: 'Returns a list of your clients.', -}, -{ - displayName: 'Limit', - name: 'limit', - type: 'number', - displayOptions: { - show: { - resource: [ - 'client', - ], - operation: [ - 'getAll', - ], - returnAll: [ - false, - ], + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource, + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, }, - }, - typeOptions: { - minValue: 1, - maxValue: 100, - }, - default: 100, - description: 'How many results to return.', -}, -{ - displayName: 'Filters', - name: 'filters', - type: 'collection', - placeholder: 'Add Filter', - default: {}, - displayOptions: { - show: { - resource: [ - 'client', - ], - operation: [ - 'getAll', - ], + typeOptions: { + minValue: 1, + maxValue: 100, }, + default: 100, + description: 'How many results to return.', }, - options: [ - { - displayName: 'Is Active', - name: 'is_active', - type: 'boolean', - default: true, - description: 'Pass true to only return active clients and false to return inactive clients.', + { + displayName: 'Filters', + name: 'filters', + type: 'collection', + placeholder: 'Add Filter', + default: {}, + displayOptions: { + show: { + resource, + operation: [ + 'getAll', + ], + }, }, - { - displayName: 'Updated Since', - name: 'updated_since', - type: 'dateTime', - default: '', - description: 'Only return clients that have been updated since the given date and time.', - } - ] -}, + options: [ + { + displayName: 'Is Active', + name: 'is_active', + type: 'boolean', + default: true, + description: 'Pass true to only return active clients and false to return inactive clients.', + }, + { + displayName: 'Updated Since', + name: 'updated_since', + type: 'dateTime', + default: '', + description: 'Only return clients that have been updated since the given date and time.', + } + ] + }, -/* -------------------------------------------------------------------------- */ -/* client:get */ -/* -------------------------------------------------------------------------- */ -{ - displayName: 'Client Id', - name: 'id', - type: 'string', - default: '', - required: true, - displayOptions: { - show: { - operation: [ - 'get', - ], - resource: [ - 'client', - ], + /* -------------------------------------------------------------------------- */ + /* client:get */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Client Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'get', + ], + resource + }, }, + description: 'The ID of the client you are retrieving.', + }, + + /* -------------------------------------------------------------------------- */ + /* client:delete */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Client Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'delete', + ], + resource + }, + }, + description: 'The ID of the client you want to delete.', + }, + + /* -------------------------------------------------------------------------- */ + /* client:create */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Name', + name: 'name', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: '', + required: true, + description: 'The name of the client.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: {}, + options: [ + { + displayName: 'Is Active', + name: 'is_active', + type: 'string', + default: '', + description: 'Whether the client is active, or archived. Defaults to true.' + }, + { + displayName: 'Address', + name: 'address', + type: 'string', + default: '', + description: ' A textual representation of the client’s physical address. May include new line characters.' + }, + { + displayName: 'Currency', + name: 'currency', + type: 'string', + default: '', + description: 'The currency used by the estimate. If not provided, the client’s currency will be used. See a list of supported currencies' + }, + ], + }, + + /* -------------------------------------------------------------------------- */ + /* client:update */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Client Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'update', + ], + resource, + }, + }, + description: 'The ID of the client want to update.', + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'update', + ], + resource, + }, + }, + default: {}, + options: [ + { + displayName: 'Address', + name: 'address', + type: 'string', + default: '', + description: ' A textual representation of the client’s physical address. May include new line characters.' + }, + { + displayName: 'Currency', + name: 'currency', + type: 'string', + default: '', + description: 'The currency used by the estimate. If not provided, the client’s currency will be used. See a list of supported currencies' + }, + { + displayName: 'Is Active', + name: 'is_active', + type: 'boolean', + default: true, + description: 'Whether the client is active, or archived. Defaults to true.' + }, + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'Whether the client is active, or archived. Defaults to true.' + }, + ], }, - description: 'The ID of the client you are retrieving.', -} ] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Harvest/CompanyDescription.ts b/packages/nodes-base/nodes/Harvest/CompanyDescription.ts index 26303b7eb3..d67939afa0 100644 --- a/packages/nodes-base/nodes/Harvest/CompanyDescription.ts +++ b/packages/nodes-base/nodes/Harvest/CompanyDescription.ts @@ -1,4 +1,6 @@ -import { INodeProperties } from "n8n-workflow"; +import { INodeProperties } from 'n8n-workflow'; + +const resource = [ 'company' ]; export const companyOperations = [ { @@ -7,9 +9,7 @@ export const companyOperations = [ type: 'options', displayOptions: { show: { - resource: [ - 'company', - ], + resource, }, }, options: [ diff --git a/packages/nodes-base/nodes/Harvest/ContactDescription.ts b/packages/nodes-base/nodes/Harvest/ContactDescription.ts index f4156eeb1c..c4ecd257b9 100644 --- a/packages/nodes-base/nodes/Harvest/ContactDescription.ts +++ b/packages/nodes-base/nodes/Harvest/ContactDescription.ts @@ -1,4 +1,6 @@ -import { INodeProperties } from "n8n-workflow"; +import { INodeProperties } from 'n8n-workflow'; + +const resource = ['contact']; export const contactOperations = [ { @@ -7,12 +9,20 @@ export const contactOperations = [ type: 'options', displayOptions: { show: { - resource: [ - 'contact', - ], + resource, }, }, options: [ + { + name: 'Create', + value: 'create', + description: `Create a contact`, + }, + { + name: 'Delete', + value: 'delete', + description: `Delete a contact`, + }, { name: 'Get', value: 'get', @@ -23,6 +33,11 @@ export const contactOperations = [ value: 'getAll', description: 'Get data of all contacts', }, + { + name: 'Update', + value: 'update', + description: `Update a contact`, + }, ], default: 'getAll', description: 'The operation to perform.', @@ -32,105 +47,305 @@ export const contactOperations = [ export const contactFields = [ -/* -------------------------------------------------------------------------- */ -/* contact:getAll */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* contact:getAll */ + /* -------------------------------------------------------------------------- */ -{ - displayName: 'Return All', - name: 'returnAll', - type: 'boolean', - displayOptions: { - show: { - resource: [ - 'contact', - ], - operation: [ - 'getAll', - ], + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource, + operation: [ + 'getAll', + ], + }, }, + default: false, + description: 'Returns a list of your user contacts.', }, - default: false, - description: 'Returns a list of your user contacts.', -}, -{ - displayName: 'Limit', - name: 'limit', - type: 'number', - displayOptions: { - show: { - resource: [ - 'contact', - ], - operation: [ - 'getAll', - ], - returnAll: [ - false, - ], + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource, + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, }, - }, - typeOptions: { - minValue: 1, - maxValue: 100, - }, - default: 100, - description: 'How many results to return.', -}, -{ - displayName: 'Filters', - name: 'filters', - type: 'collection', - placeholder: 'Add Filter', - default: {}, - displayOptions: { - show: { - resource: [ - 'contact', - ], - operation: [ - 'getAll', - ], + typeOptions: { + minValue: 1, + maxValue: 100, }, + default: 100, + description: 'How many results to return.', }, - options: [ - { - displayName: 'Is Active', - name: 'is_active', - type: 'boolean', - default: '', - description: 'Pass true to only return active clients and false to return inactive clients.', + { + displayName: 'Filters', + name: 'filters', + type: 'collection', + placeholder: 'Add Filter', + default: {}, + displayOptions: { + show: { + resource, + operation: [ + 'getAll', + ], + }, }, - { - displayName: 'Updated Since', - name: 'updated_since', - type: 'dateTime', - default: '', - description: 'Only return clients that have been updated since the given date and time.', - } - ] -}, + options: [ + { + displayName: 'Is Active', + name: 'is_active', + type: 'boolean', + default: true, + description: 'Pass true to only return active clients and false to return inactive clients.', + }, + { + displayName: 'Updated Since', + name: 'updated_since', + type: 'dateTime', + default: '', + description: 'Only return clients that have been updated since the given date and time.', + } + ] + }, -/* -------------------------------------------------------------------------- */ -/* contact:get */ -/* -------------------------------------------------------------------------- */ -{ - displayName: 'Contact Id', - name: 'id', - type: 'string', - default: '', - required: true, - displayOptions: { - show: { - operation: [ - 'get', - ], - resource: [ - 'contact', - ], + /* -------------------------------------------------------------------------- */ + /* contact:get */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Contact Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'get', + ], + resource, + }, }, + description: 'The ID of the contact you are retrieving.', + }, + + /* -------------------------------------------------------------------------- */ + /* contact:delete */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Contact Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'delete', + ], + resource, + }, + }, + description: 'The ID of the contact you want to delete.', + }, + + /* -------------------------------------------------------------------------- */ + /* contact:create */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'First Name', + name: 'firstName', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: '', + required: true, + description: 'The first name of the contact.', + }, + { + displayName: 'Client Id', + name: 'clientId', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: '', + required: true, + description: 'The ID of the client associated with this contact.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: {}, + options: [ + { + displayName: 'Last Name', + name: 'last_name', + type: 'string', + default: '', + description: 'The last name of the contact.' + }, + { + displayName: 'Title', + name: 'title', + type: 'string', + default: '', + description: 'The title of the contact.' + }, + { + displayName: 'Email', + name: 'email', + type: 'string', + default: '', + description: 'The contact’s email address.' + }, + { + displayName: 'Phone Office', + name: 'phone_office', + type: 'string', + default: '', + description: 'The contact’s office phone number.' + }, + { + displayName: 'Phone Mobile', + name: 'phone_mobile', + type: 'string', + default: '', + description: 'The contact’s mobile phone number.' + }, + { + displayName: 'Fax', + name: 'fax', + type: 'string', + default: '', + description: 'The contact’s fax number.' + }, + ], + }, + + /* -------------------------------------------------------------------------- */ + /* contact:update */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Contact Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'update', + ], + resource, + }, + }, + description: 'The ID of the contact want to update.', + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'update', + ], + resource, + }, + }, + default: {}, + options: [ + { + displayName: 'Client Id', + name: 'client_id', + type: 'string', + default: '', + description: 'The ID of the client associated with this contact.', + }, + { + displayName: 'First Name', + name: 'first_name', + type: 'string', + default: '', + description: 'The first name of the contact.', + }, + { + displayName: 'Last Name', + name: 'last_name', + type: 'string', + default: '', + description: 'The last name of the contact.' + }, + { + displayName: 'Title', + name: 'title', + type: 'string', + default: '', + description: 'The title of the contact.' + }, + { + displayName: 'Email', + name: 'email', + type: 'string', + default: '', + description: 'The contact’s email address.' + }, + { + displayName: 'Phone Office', + name: 'phone_office', + type: 'string', + default: '', + description: 'The contact’s office phone number.' + }, + { + displayName: 'Phone Mobile', + name: 'phone_mobile', + type: 'string', + default: '', + description: 'The contact’s mobile phone number.' + }, + { + displayName: 'Fax', + name: 'fax', + type: 'string', + default: '', + description: 'The contact’s fax number.' + }, + ], }, - description: 'The ID of the contact you are retrieving.', -} ] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Harvest/EstimateDescription.ts b/packages/nodes-base/nodes/Harvest/EstimateDescription.ts index 60a24bdb80..35a252be83 100644 --- a/packages/nodes-base/nodes/Harvest/EstimateDescription.ts +++ b/packages/nodes-base/nodes/Harvest/EstimateDescription.ts @@ -1,4 +1,6 @@ -import { INodeProperties } from "n8n-workflow"; +import { INodeProperties } from 'n8n-workflow'; + +const resource = [ 'estimate' ]; export const estimateOperations = [ { @@ -7,12 +9,20 @@ export const estimateOperations = [ type: 'options', displayOptions: { show: { - resource: [ - 'estimate', - ], + resource, }, }, options: [ + { + name: 'Create', + value: 'create', + description: `Create a estimate`, + }, + { + name: 'Delete', + value: 'delete', + description: `Delete an estimate`, + }, { name: 'Get', value: 'get', @@ -23,6 +33,11 @@ export const estimateOperations = [ value: 'getAll', description: 'Get data of all estimates', }, + { + name: 'Update', + value: 'update', + description: `Update a estimate`, + }, ], default: 'getAll', description: 'The operation to perform.', @@ -42,9 +57,7 @@ export const estimateFields = [ type: 'boolean', displayOptions: { show: { - resource: [ - 'estimate', - ], + resource, operation: [ 'getAll', ], @@ -59,9 +72,7 @@ export const estimateFields = [ type: 'number', displayOptions: { show: { - resource: [ - 'estimate', - ], + resource, operation: [ 'getAll', ], @@ -85,9 +96,7 @@ export const estimateFields = [ default: {}, displayOptions: { show: { - resource: [ - 'estimate', - ], + resource, operation: [ 'getAll', ], @@ -101,13 +110,6 @@ export const estimateFields = [ default: '', description: 'Only return time entries belonging to the client with the given ID.', }, - { - displayName: 'Updated Since', - name: 'updated_since', - type: 'dateTime', - default: '', - description: 'Only return time entries that have been updated since the given date and time.', - }, { displayName: 'From', name: 'from', @@ -115,6 +117,13 @@ export const estimateFields = [ default: '', description: 'Only return time entries with a spent_date on or after the given date.', }, + { + displayName: 'State', + name: 'state', + type: 'string', + default: '', + description: 'Only return estimates with a state matching the value provided. Options: draft, sent, accepted, or declined.', + }, { displayName: 'To', name: 'to', @@ -123,11 +132,11 @@ export const estimateFields = [ description: 'Only return time entries with a spent_date on or before the given date.', }, { - displayName: 'State', - name: 'state', - type: 'string', + displayName: 'Updated Since', + name: 'updated_since', + type: 'dateTime', default: '', - description: 'Only return estimates with a state matching the value provided. Options: draft, sent, accepted, or declined.', + description: 'Only return time entries that have been updated since the given date and time.', }, { displayName: 'Page', @@ -156,12 +165,237 @@ export const estimateFields = [ operation: [ 'get', ], - resource: [ - 'estimate', - ], + resource, }, }, description: 'The ID of the estimate you are retrieving.', -} +}, + +/* -------------------------------------------------------------------------- */ +/* estimate:delete */ +/* -------------------------------------------------------------------------- */ +{ + displayName: 'Estimate Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'delete', + ], + resource, + }, + }, + description: 'The ID of the estimate want to delete.', +}, + + /* -------------------------------------------------------------------------- */ + /* estimate:create */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Client Id', + name: 'clientId', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: '', + required: true, + description: 'The ID of the client this estimate belongs to.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: {}, + options: [ + { + displayName: 'Currency', + name: 'currency', + type: 'string', + default: '', + description: 'The currency used by the estimate. If not provided, the client’s currency will be used. See a list of supported currencies' + }, + { + displayName: 'Discount', + name: 'over_budget_notification_percentage', + type: 'string', + default: '', + description: 'This percentage is subtracted from the subtotal. Example: use 10.0 for 10.0%.' + }, + { + displayName: 'Issue Date', + name: 'issue_date', + type: 'dateTime', + default: '', + description: 'Date the invoice was issued. Defaults to today’s date.' + }, + { + displayName: 'Notes', + name: 'notes', + type: 'string', + default: '', + description: 'Any additional notes to include on the estimate.' + }, + { + displayName: 'Number', + name: 'number', + type: 'string', + default: '', + description: 'If no value is set, the number will be automatically generated.' + }, + { + displayName: 'Purchase Order', + name: 'purchase_order', + type: 'string', + default: '', + description: 'The purchase order number.' + }, + { + displayName: 'Subject', + name: 'subject', + type: 'string', + default: '', + description: 'The estimate subject.' + }, + { + displayName: 'Tax', + name: 'tax', + type: 'string', + default: '', + description: 'This percentage is applied to the subtotal, including line items and discounts. Example: use 10.0 for 10.0%.' + }, + { + displayName: 'Tax2', + name: 'tax2', + type: 'string', + default: '', + description: 'This percentage is applied to the subtotal, including line items and discounts. Example: use 10.0 for 10.0%.' + }, + ], + }, + + /* -------------------------------------------------------------------------- */ + /* estimate:update */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Invoice Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'update', + ], + resource, + }, + }, + description: 'The ID of the invoice want to update.', + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'update', + ], + resource, + }, + }, + default: {}, + options: [ + { + displayName: 'Client Id', + name: 'client_id', + type: 'string', + default: '', + description: 'The ID of the retainer associated with this invoice..', + }, + { + displayName: 'Currency', + name: 'currency', + type: 'string', + default: '', + description: 'The currency used by the estimate. If not provided, the client’s currency will be used. See a list of supported currencies' + }, + { + displayName: 'Discount', + name: 'over_budget_notification_percentage', + type: 'string', + default: '', + description: 'This percentage is subtracted from the subtotal. Example: use 10.0 for 10.0%.' + }, + { + displayName: 'Issue Date', + name: 'issue_date', + type: 'dateTime', + default: '', + description: 'Date the invoice was issued. Defaults to today’s date.' + }, + { + displayName: 'Number', + name: 'number', + type: 'string', + default: '', + description: 'If no value is set, the number will be automatically generated.' + }, + { + displayName: 'Notes', + name: 'notes', + type: 'string', + default: '', + description: 'Any additional notes to include on the estimate.' + }, + { + displayName: 'Purchase Order', + name: 'purchase_order', + type: 'string', + default: '', + description: 'The purchase order number.' + }, + { + displayName: 'Subject', + name: 'subject', + type: 'string', + default: '', + description: 'The estimate subject.' + }, + { + displayName: 'Tax', + name: 'tax', + type: 'string', + default: '', + description: 'This percentage is applied to the subtotal, including line items and discounts. Example: use 10.0 for 10.0%.' + }, + { + displayName: 'Tax2', + name: 'tax2', + type: 'string', + default: '', + description: 'This percentage is applied to the subtotal, including line items and discounts. Example: use 10.0 for 10.0%.' + }, + ], + }, ] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Harvest/ExpenseDescription.ts b/packages/nodes-base/nodes/Harvest/ExpenseDescription.ts index 54659e4a3a..3a1b006eeb 100644 --- a/packages/nodes-base/nodes/Harvest/ExpenseDescription.ts +++ b/packages/nodes-base/nodes/Harvest/ExpenseDescription.ts @@ -1,4 +1,6 @@ -import { INodeProperties } from "n8n-workflow"; +import { INodeProperties } from 'n8n-workflow'; + +const resource = [ 'expense' ]; export const expenseOperations = [ { @@ -7,9 +9,7 @@ export const expenseOperations = [ type: 'options', displayOptions: { show: { - resource: [ - 'expense', - ], + resource, }, }, options: [ @@ -23,6 +23,21 @@ export const expenseOperations = [ value: 'getAll', description: 'Get data of all expenses', }, + { + name: 'Create', + value: 'create', + description: `Create a expense`, + }, + { + name: 'Update', + value: 'update', + description: `Update a expense`, + }, + { + name: 'Delete', + value: 'delete', + description: `Delete an expense`, + }, ], default: 'getAll', description: 'The operation to perform.', @@ -42,9 +57,7 @@ export const expenseFields = [ type: 'boolean', displayOptions: { show: { - resource: [ - 'expense', - ], + resource, operation: [ 'getAll', ], @@ -59,9 +72,7 @@ export const expenseFields = [ type: 'number', displayOptions: { show: { - resource: [ - 'expense', - ], + resource, operation: [ 'getAll', ], @@ -85,22 +96,13 @@ export const expenseFields = [ default: {}, displayOptions: { show: { - resource: [ - 'expense', - ], + resource, operation: [ 'getAll', ], }, }, options: [ - { - displayName: 'User ID', - name: 'user_id', - type: 'string', - default: '', - description: 'Only return time entries belonging to the user with the given ID.', - }, { displayName: 'Client ID', name: 'client_id', @@ -108,27 +110,6 @@ export const expenseFields = [ default: '', description: 'Only return time entries belonging to the client with the given ID.', }, - { - displayName: 'Project ID', - name: 'project_id', - type: 'string', - default: '', - description: 'Only return time entries belonging to the client with the given ID.', - }, - { - displayName: 'Is Billed', - name: 'is_billed', - type: 'boolean', - default: '', - description: 'Pass true to only return time entries that have been invoiced and false to return time entries that have not been invoiced.', - }, - { - displayName: 'Updated Since', - name: 'updated_since', - type: 'dateTime', - default: '', - description: 'Only return time entries that have been updated since the given date and time.', - }, { displayName: 'From', name: 'from', @@ -137,11 +118,11 @@ export const expenseFields = [ description: 'Only return time entries with a spent_date on or after the given date.', }, { - displayName: 'To', - name: 'to', - type: 'dateTime', - default: '', - description: 'Only return time entries with a spent_date on or before the given date.', + displayName: 'Is Billed', + name: 'is_billed', + type: 'boolean', + default: false, + description: 'Pass true to only return time entries that have been invoiced and false to return time entries that have not been invoiced.', }, { displayName: 'Page', @@ -152,7 +133,35 @@ export const expenseFields = [ }, default: 1, description: 'The page number to use in pagination. For instance, if you make a list request and receive 100 records, your subsequent call can include page=2 to retrieve the next page of the list. (Default: 1)', - } + }, + { + displayName: 'Project ID', + name: 'project_id', + type: 'string', + default: '', + description: 'Only return time entries belonging to the client with the given ID.', + }, + { + displayName: 'To', + name: 'to', + type: 'dateTime', + default: '', + description: 'Only return time entries with a spent_date on or before the given date.', + }, + { + displayName: 'Updated Since', + name: 'updated_since', + type: 'dateTime', + default: '', + description: 'Only return time entries that have been updated since the given date and time.', + }, + { + displayName: 'User ID', + name: 'user_id', + type: 'string', + default: '', + description: 'Only return time entries belonging to the user with the given ID.', + }, ] }, @@ -170,12 +179,227 @@ export const expenseFields = [ operation: [ 'get', ], - resource: [ - 'expense', - ], + resource, }, }, description: 'The ID of the expense you are retrieving.', -} +}, + +/* -------------------------------------------------------------------------- */ +/* expense:delete */ +/* -------------------------------------------------------------------------- */ +{ + displayName: 'Expense Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'delete', + ], + resource, + }, + }, + description: 'The ID of the expense you want to delete.', +}, + + /* -------------------------------------------------------------------------- */ + /* expense:create */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Project Id', + name: 'projectId', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: '', + required: true, + description: 'The ID of the project associated with this expense.', + }, + { + displayName: 'Expense Category Id', + name: 'expenseCategoryId', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: '', + required: true, + description: 'The ID of the expense category this expense is being tracked against.', + }, + { + displayName: 'Spent Date', + name: 'spentDate', + type: 'dateTime', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: '', + required: true, + description: 'Date the expense occurred.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: {}, + options: [ + { + displayName: 'Billable', + name: 'billable', + type: 'boolean', + default: true, + description: 'Whether this expense is billable or not. Defaults to true.' + }, + { + displayName: 'Notes', + name: 'notes', + type: 'string', + default: '', + description: 'Notes about the expense.' + }, + { + displayName: 'Total Cost', + name: 'total_cost', + type: 'string', + default: '', + description: 'The total amount of the expense.' + }, + { + displayName: 'Units', + name: 'units', + type: 'string', + default: '', + description: 'The quantity of units to use in calculating the total_cost of the expense.' + }, + { + displayName: 'User Id', + name: 'user_id', + type: 'boolean', + default: true, + description: 'The ID of the user associated with this expense. Defaults to the ID of the currently authenticated user.' + }, + ], + }, + + /* -------------------------------------------------------------------------- */ + /* invoice:update */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Invoice Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'update', + ], + resource, + }, + }, + description: 'The ID of the invoice want to update.', + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'update', + ], + resource, + }, + }, + default: {}, + options: [ + { + displayName: 'Billable', + name: 'billable', + type: 'boolean', + default: true, + description: 'Whether this expense is billable or not. Defaults to true.' + }, + { + displayName: 'Expense Category Id', + name: 'expense_category_id', + type: 'string', + default: '', + description: 'The ID of the expense category this expense is being tracked against.', + }, + { + displayName: 'Notes', + name: 'notes', + type: 'string', + default: '', + description: 'Notes about the expense.' + }, + { + displayName: 'Project Id', + name: 'project_id', + type: 'string', + default: '', + description: 'The ID of the project associated with this expense.', + }, + { + displayName: 'Spent Date', + name: 'spent_date', + type: 'dateTime', + default: '', + description: 'Date the expense occurred.', + }, + { + displayName: 'Total Cost', + name: 'total_cost', + type: 'string', + default: '', + description: 'The total amount of the expense.' + }, + { + displayName: 'Units', + name: 'units', + type: 'string', + default: '', + description: 'The quantity of units to use in calculating the total_cost of the expense.' + }, + { + displayName: 'User Id', + name: 'user_id', + type: 'boolean', + default: true, + description: 'The ID of the user associated with this expense. Defaults to the ID of the currently authenticated user.' + }, + ], + }, ] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Harvest/GenericFunctions.ts b/packages/nodes-base/nodes/Harvest/GenericFunctions.ts index 6adf097b30..276405df3b 100644 --- a/packages/nodes-base/nodes/Harvest/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Harvest/GenericFunctions.ts @@ -50,6 +50,7 @@ export async function harvestApiRequest( if (Object.keys(options.body).length === 0) { delete options.body; } + try { const result = await this.helpers.request!(options); diff --git a/packages/nodes-base/nodes/Harvest/Harvest.node.ts b/packages/nodes-base/nodes/Harvest/Harvest.node.ts index d8bef6ea13..336a7838a5 100644 --- a/packages/nodes-base/nodes/Harvest/Harvest.node.ts +++ b/packages/nodes-base/nodes/Harvest/Harvest.node.ts @@ -8,17 +8,17 @@ import { INodeType, } from 'n8n-workflow'; -import { harvestApiRequest, harvestApiRequestAllItems } from './GenericFunctions'; -import { timeEntryOperations, timeEntryFields } from './TimeEntryDescription'; import { clientOperations, clientFields } from './ClientDescription'; -import { companyOperations } from './CompanyDescription'; import { contactOperations, contactFields } from './ContactDescription'; +import { companyOperations } from './CompanyDescription'; +import { estimateOperations, estimateFields } from './EstimateDescription'; import { expenseOperations, expenseFields } from './ExpenseDescription'; +import { harvestApiRequest, harvestApiRequestAllItems } from './GenericFunctions'; import { invoiceOperations, invoiceFields } from './InvoiceDescription'; import { projectOperations, projectFields } from './ProjectDescription'; import { taskOperations, taskFields } from './TaskDescription'; +import { timeEntryOperations, timeEntryFields } from './TimeEntryDescription'; import { userOperations, userFields } from './UserDescription'; -import { estimateOperations, estimateFields } from './EstimateDescription'; /** * fetch All resource using paginated calls @@ -35,7 +35,7 @@ async function getAllResource(this: IExecuteFunctions, resource: string, i: numb Object.assign(qs, additionalFields); let responseData: IDataObject = {}; - if(returnAll) { + if (returnAll) { responseData[resource] = await harvestApiRequestAllItems.call(this, requestMethod, qs, endpoint, resource); } else { const limit = this.getNodeParameter('limit', i) as string; @@ -86,7 +86,7 @@ export class Harvest implements INodeType { value: 'contact', }, { - name: 'Estimates', + name: 'Estimate', value: 'estimate', }, { @@ -147,7 +147,6 @@ export class Harvest implements INodeType { const items = this.getInputData(); const returnData: IDataObject[] = []; - const resource = this.getNodeParameter('resource', 0) as string; const operation = this.getNodeParameter('operation', 0) as string; @@ -156,7 +155,6 @@ export class Harvest implements INodeType { let body: IDataObject | Buffer; let qs: IDataObject; - for (let i = 0; i < items.length; i++) { body = {}; qs = {}; @@ -306,6 +304,48 @@ export class Harvest implements INodeType { const responseData: IDataObject[] = await getAllResource.call(this, 'clients', i); returnData.push.apply(returnData, responseData); + } else if (operation === 'create') { + // ---------------------------------- + // create + // ---------------------------------- + + requestMethod = 'POST'; + endpoint = 'clients'; + + body.name = this.getNodeParameter('name', i) as string; + + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + Object.assign(body, additionalFields); + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint, body); + returnData.push(responseData); + + } else if (operation === 'update') { + // ---------------------------------- + // update + // ---------------------------------- + + requestMethod = 'PATCH'; + const id = this.getNodeParameter('id', i) as string; + endpoint = `clients/${id}`; + + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + Object.assign(qs, updateFields); + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint, body); + returnData.push(responseData); + + } else if (operation === 'delete') { + // ---------------------------------- + // delete + // ---------------------------------- + + requestMethod = 'DELETE'; + const id = this.getNodeParameter('id', i) as string; + endpoint = `clients/${id}`; + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint); + returnData.push(responseData); } else { throw new Error(`The resource "${resource}" is not known!`); } @@ -331,6 +371,52 @@ export class Harvest implements INodeType { const responseData: IDataObject[] = await getAllResource.call(this, 'projects', i); returnData.push.apply(returnData, responseData); + } else if (operation === 'create') { + // ---------------------------------- + // create + // ---------------------------------- + + requestMethod = 'POST'; + endpoint = 'projects'; + + body.client_id = this.getNodeParameter('clientId', i) as string; + body.name = this.getNodeParameter('name', i) as string; + body.is_billable = this.getNodeParameter('isBillable', i) as string; + body.bill_by = this.getNodeParameter('billBy', i) as string; + body.budget_by = this.getNodeParameter('budgetBy', i) as string; + + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + Object.assign(body, additionalFields); + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint, body); + returnData.push(responseData); + + } else if (operation === 'update') { + // ---------------------------------- + // update + // ---------------------------------- + + requestMethod = 'PATCH'; + const id = this.getNodeParameter('id', i) as string; + endpoint = `projects/${id}`; + + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + + Object.assign(body, updateFields); + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint, body); + returnData.push(responseData); + + } else if (operation === 'delete') { + // ---------------------------------- + // delete + // ---------------------------------- + + requestMethod = 'DELETE'; + const id = this.getNodeParameter('id', i) as string; + endpoint = `projects/${id}`; + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint); + returnData.push(responseData); } else { throw new Error(`The resource "${resource}" is not known!`); } @@ -363,11 +449,55 @@ export class Harvest implements INodeType { requestMethod = 'GET'; - endpoint = 'users/me'; + endpoint = `users/me`; const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint); returnData.push(responseData); + } else if (operation === 'create') { + // ---------------------------------- + // create + // ---------------------------------- + + requestMethod = 'POST'; + endpoint = 'users'; + + body.first_name = this.getNodeParameter('firstName', i) as string; + body.last_name = this.getNodeParameter('lastName', i) as string; + body.email = this.getNodeParameter('email', i) as string; + + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + Object.assign(body, additionalFields); + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint, body); + returnData.push(responseData); + + } else if (operation === 'update') { + // ---------------------------------- + // update + // ---------------------------------- + + requestMethod = 'PATCH'; + const id = this.getNodeParameter('id', i) as string; + endpoint = `users/${id}`; + + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + Object.assign(qs, updateFields); + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint, body); + returnData.push(responseData); + + } else if (operation === 'delete') { + // ---------------------------------- + // delete + // ---------------------------------- + + requestMethod = 'DELETE'; + const id = this.getNodeParameter('id', i) as string; + endpoint = `users/${id}`; + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint); + returnData.push(responseData); } else { throw new Error(`The resource "${resource}" is not known!`); } @@ -393,6 +523,49 @@ export class Harvest implements INodeType { const responseData: IDataObject[] = await getAllResource.call(this, 'contacts', i); returnData.push.apply(returnData, responseData); + } else if (operation === 'create') { + // ---------------------------------- + // create + // ---------------------------------- + + requestMethod = 'POST'; + endpoint = 'contacts'; + + body.client_id = this.getNodeParameter('clientId', i) as string; + body.first_name = this.getNodeParameter('firstName', i) as string; + + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + Object.assign(body, additionalFields); + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint, body); + returnData.push(responseData); + + } else if (operation === 'update') { + // ---------------------------------- + // update + // ---------------------------------- + + requestMethod = 'PATCH'; + const id = this.getNodeParameter('id', i) as string; + endpoint = `contacts/${id}`; + + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + Object.assign(qs, updateFields); + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint, body); + returnData.push(responseData); + + } else if (operation === 'delete') { + // ---------------------------------- + // delete + // ---------------------------------- + + requestMethod = 'DELETE'; + const id = this.getNodeParameter('id', i) as string; + endpoint = `contacts/${id}`; + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint); + returnData.push(responseData); } else { throw new Error(`The resource "${resource}" is not known!`); } @@ -433,6 +606,17 @@ export class Harvest implements INodeType { const responseData: IDataObject[] = await getAllResource.call(this, 'tasks', i); returnData.push.apply(returnData, responseData); + } else if (operation === 'delete') { + // ---------------------------------- + // delete + // ---------------------------------- + + requestMethod = 'DELETE'; + const id = this.getNodeParameter('id', i) as string; + endpoint = `tasks/${id}`; + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint); + returnData.push(responseData); } else { throw new Error(`The resource "${resource}" is not known!`); } @@ -458,6 +642,48 @@ export class Harvest implements INodeType { const responseData: IDataObject[] = await getAllResource.call(this, 'invoices', i); returnData.push.apply(returnData, responseData); + } else if (operation === 'create') { + // ---------------------------------- + // create + // ---------------------------------- + + requestMethod = 'POST'; + endpoint = 'invoices'; + + body.client_id = this.getNodeParameter('clientId', i) as string; + + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + Object.assign(body, additionalFields); + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint, body); + returnData.push(responseData); + + } else if (operation === 'update') { + // ---------------------------------- + // update + // ---------------------------------- + + requestMethod = 'PATCH'; + const id = this.getNodeParameter('id', i) as string; + endpoint = `invoices/${id}`; + + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + Object.assign(qs, updateFields); + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint, body); + returnData.push(responseData); + + } else if (operation === 'delete') { + // ---------------------------------- + // delete + // ---------------------------------- + + requestMethod = 'DELETE'; + const id = this.getNodeParameter('id', i) as string; + endpoint = `invoices/${id}`; + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint); + returnData.push(responseData); } else { throw new Error(`The resource "${resource}" is not known!`); } @@ -483,6 +709,50 @@ export class Harvest implements INodeType { const responseData: IDataObject[] = await getAllResource.call(this, 'expenses', i); returnData.push.apply(returnData, responseData); + } else if (operation === 'create') { + // ---------------------------------- + // create + // ---------------------------------- + + requestMethod = 'POST'; + endpoint = 'expenses'; + + body.project_id = this.getNodeParameter('projectId', i) as string; + body.expense_category_id = this.getNodeParameter('expenseCategoryId', i) as string; + body.spent_date = this.getNodeParameter('spentDate', i) as string; + + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + Object.assign(body, additionalFields); + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint, body); + returnData.push(responseData); + + } else if (operation === 'update') { + // ---------------------------------- + // update + // ---------------------------------- + + requestMethod = 'PATCH'; + const id = this.getNodeParameter('id', i) as string; + endpoint = `expenses/${id}`; + + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + Object.assign(qs, updateFields); + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint, body); + returnData.push(responseData); + + } else if (operation === 'delete') { + // ---------------------------------- + // delete + // ---------------------------------- + + requestMethod = 'DELETE'; + const id = this.getNodeParameter('id', i) as string; + endpoint = `expenses/${id}`; + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint); + returnData.push(responseData); } else { throw new Error(`The resource "${resource}" is not known!`); } @@ -508,6 +778,48 @@ export class Harvest implements INodeType { const responseData: IDataObject[] = await getAllResource.call(this, 'estimates', i); returnData.push.apply(returnData, responseData); + } else if (operation === 'create') { + // ---------------------------------- + // create + // ---------------------------------- + + requestMethod = 'POST'; + endpoint = 'estimates'; + + body.client_id = this.getNodeParameter('clientId', i) as string; + + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + Object.assign(body, additionalFields); + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint, body); + returnData.push(responseData); + + } else if (operation === 'update') { + // ---------------------------------- + // update + // ---------------------------------- + + requestMethod = 'PATCH'; + const id = this.getNodeParameter('id', i) as string; + endpoint = `estimates/${id}`; + + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + Object.assign(qs, updateFields); + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint, body); + returnData.push(responseData); + + } else if (operation === 'delete') { + // ---------------------------------- + // delete + // ---------------------------------- + + requestMethod = 'DELETE'; + const id = this.getNodeParameter('id', i) as string; + endpoint = `estimates/${id}`; + + const responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint); + returnData.push(responseData); } else { throw new Error(`The resource "${resource}" is not known!`); } diff --git a/packages/nodes-base/nodes/Harvest/InvoiceDescription.ts b/packages/nodes-base/nodes/Harvest/InvoiceDescription.ts index cb876f872a..5f2987ddc5 100644 --- a/packages/nodes-base/nodes/Harvest/InvoiceDescription.ts +++ b/packages/nodes-base/nodes/Harvest/InvoiceDescription.ts @@ -1,4 +1,6 @@ -import { INodeProperties } from "n8n-workflow"; +import { INodeProperties } from 'n8n-workflow'; + +const resource = [ 'invoice' ]; export const invoiceOperations = [ { @@ -7,9 +9,7 @@ export const invoiceOperations = [ type: 'options', displayOptions: { show: { - resource: [ - 'invoice', - ], + resource, }, }, options: [ @@ -23,6 +23,21 @@ export const invoiceOperations = [ value: 'getAll', description: 'Get data of all invoices', }, + { + name: 'Create', + value: 'create', + description: `Create a invoice`, + }, + { + name: 'Update', + value: 'update', + description: `Update a invoice`, + }, + { + name: 'Delete', + value: 'delete', + description: `Delete a invoice`, + }, ], default: 'getAll', description: 'The operation to perform.', @@ -42,9 +57,7 @@ export const invoiceFields = [ type: 'boolean', displayOptions: { show: { - resource: [ - 'invoice', - ], + resource, operation: [ 'getAll', ], @@ -59,9 +72,7 @@ export const invoiceFields = [ type: 'number', displayOptions: { show: { - resource: [ - 'invoice', - ], + resource, operation: [ 'getAll', ], @@ -85,9 +96,7 @@ export const invoiceFields = [ default: {}, displayOptions: { show: { - resource: [ - 'invoice', - ], + resource, operation: [ 'getAll', ], @@ -181,12 +190,292 @@ export const invoiceFields = [ operation: [ 'get', ], - resource: [ - 'invoice', - ], + resource, }, }, description: 'The ID of the invoice you are retrieving.', -} +}, +/* -------------------------------------------------------------------------- */ +/* invoice:delete */ +/* -------------------------------------------------------------------------- */ +{ + displayName: 'Invoice Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'delete', + ], + resource, + }, + }, + description: 'The ID of the invoice want to delete.', +}, + + /* -------------------------------------------------------------------------- */ + /* invoice:create */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Client Id', + name: 'clientId', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: '', + required: true, + description: 'The ID of the retainer associated with this invoice..', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: {}, + options: [ + { + displayName: 'Currency', + name: 'currency', + type: 'string', + default: '', + description: 'The currency used by the invoice. If not provided, the client’s currency will be used. See a list of supported currencies' + }, + { + displayName: 'Discount', + name: 'over_budget_notification_percentage', + type: 'string', + default: '', + description: 'This percentage is subtracted from the subtotal. Example: use 10.0 for 10.0%.' + }, + { + displayName: 'Due Date', + name: 'ends_on', + type: 'dateTime', + default: '', + description: 'Date the invoice is due. Defaults to the issue_date if no payment_term is specified.' + }, + { + displayName: 'Estimate Id', + name: 'estimate_id', + type: 'string', + default: '', + description: 'The ID of the estimate associated with this invoice.' + }, + { + displayName: 'Issue Date', + name: 'issue_date', + type: 'dateTime', + default: '', + description: 'Date the invoice was issued. Defaults to today’s date.' + }, + { + displayName: 'Notes', + name: 'notes', + type: 'string', + default: '', + description: 'Notes about the project.' + }, + { + displayName: 'Number', + name: 'number', + type: 'string', + default: '', + description: 'If no value is set, the number will be automatically generated.' + }, + { + displayName: 'Payment Term', + name: 'payment_term', + type: 'string', + default: '', + description: 'The timeframe in which the invoice should be paid. Defaults to custom. Options: upon receipt, net 15, net 30, net 45, or net 60.' + }, + { + displayName: 'Purchase Order', + name: 'purchase_order', + type: 'string', + default: '', + description: 'The purchase order number.' + }, + { + displayName: 'Retainer Id', + name: 'retainer_id', + type: 'boolean', + default: true, + description: 'The ID of the retainer associated with this invoice.' + }, + { + displayName: 'Subject', + name: 'subject', + type: 'string', + default: '', + description: 'The invoice subject.' + }, + { + displayName: 'Tax', + name: 'tax', + type: 'string', + default: '', + description: 'This percentage is applied to the subtotal, including line items and discounts. Example: use 10.0 for 10.0%.' + }, + { + displayName: 'Tax2', + name: 'tax2', + type: 'string', + default: '', + description: 'This percentage is applied to the subtotal, including line items and discounts. Example: use 10.0 for 10.0%.' + }, + ], + }, + + /* -------------------------------------------------------------------------- */ + /* invoice:update */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Invoice Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'update', + ], + resource, + }, + }, + description: 'The ID of the invoice want to update.', + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'update', + ], + resource, + }, + }, + default: {}, + options: [ + { + displayName: 'Client Id', + name: 'client_id', + type: 'string', + default: '', + description: 'The ID of the retainer associated with this invoice..', + }, + { + displayName: 'Currency', + name: 'currency', + type: 'string', + default: '', + description: 'The currency used by the invoice. If not provided, the client’s currency will be used. See a list of supported currencies' + }, + { + displayName: 'Discount', + name: 'over_budget_notification_percentage', + type: 'string', + default: '', + description: 'This percentage is subtracted from the subtotal. Example: use 10.0 for 10.0%.' + }, + { + displayName: 'Due Date', + name: 'ends_on', + type: 'dateTime', + default: '', + description: 'Date the invoice is due. Defaults to the issue_date if no payment_term is specified.' + }, + { + displayName: 'Estimate Id', + name: 'estimate_id', + type: 'string', + default: '', + description: 'The ID of the estimate associated with this invoice.' + }, + { + displayName: 'Issue Date', + name: 'issue_date', + type: 'dateTime', + default: '', + description: 'Date the invoice was issued. Defaults to today’s date.' + }, + { + displayName: 'Notes', + name: 'notes', + type: 'string', + default: '', + description: 'Notes about the project.' + }, + { + displayName: 'Number', + name: 'number', + type: 'string', + default: '', + description: 'If no value is set, the number will be automatically generated.' + }, + { + displayName: 'Payment Term', + name: 'payment_term', + type: 'string', + default: '', + description: 'The timeframe in which the invoice should be paid. Defaults to custom. Options: upon receipt, net 15, net 30, net 45, or net 60.' + }, + { + displayName: 'Purchase Order', + name: 'purchase_order', + type: 'string', + default: '', + description: 'The purchase order number.' + }, + { + displayName: 'Retainer Id', + name: 'retainer_id', + type: 'boolean', + default: true, + description: 'The ID of the retainer associated with this invoice.' + }, + { + displayName: 'Subject', + name: 'subject', + type: 'string', + default: '', + description: 'The invoice subject.' + }, + { + displayName: 'Tax', + name: 'tax', + type: 'string', + default: '', + description: 'This percentage is applied to the subtotal, including line items and discounts. Example: use 10.0 for 10.0%.' + }, + { + displayName: 'Tax2', + name: 'tax2', + type: 'string', + default: '', + description: 'This percentage is applied to the subtotal, including line items and discounts. Example: use 10.0 for 10.0%.' + }, + ], + }, ] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Harvest/ProjectDescription.ts b/packages/nodes-base/nodes/Harvest/ProjectDescription.ts index a0c04531a8..4910eaaf32 100644 --- a/packages/nodes-base/nodes/Harvest/ProjectDescription.ts +++ b/packages/nodes-base/nodes/Harvest/ProjectDescription.ts @@ -1,4 +1,6 @@ -import { INodeProperties } from "n8n-workflow"; +import { INodeProperties } from 'n8n-workflow'; + +const resource = ['project']; export const projectOperations = [ { @@ -7,12 +9,20 @@ export const projectOperations = [ type: 'options', displayOptions: { show: { - resource: [ - 'project', - ], + resource, }, }, options: [ + { + name: 'Create', + value: 'create', + description: `Create a project`, + }, + { + name: 'Delete', + value: 'delete', + description: `Delete a project`, + }, { name: 'Get', value: 'get', @@ -23,6 +33,11 @@ export const projectOperations = [ value: 'getAll', description: 'Get data of all projects', }, + { + name: 'Update', + value: 'update', + description: `Update a project`, + }, ], default: 'getAll', description: 'The operation to perform.', @@ -32,123 +47,544 @@ export const projectOperations = [ export const projectFields = [ -/* -------------------------------------------------------------------------- */ -/* projects:getAll */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* projects:getAll */ + /* -------------------------------------------------------------------------- */ -{ - displayName: 'Return All', - name: 'returnAll', - type: 'boolean', - displayOptions: { - show: { - resource: [ - 'project', - ], - operation: [ - 'getAll', - ], - }, - }, - default: false, - description: 'Returns a list of your projects.', -}, -{ - displayName: 'Limit', - name: 'limit', - type: 'number', - displayOptions: { - show: { - resource: [ - 'project', - ], - operation: [ - 'getAll', - ], - returnAll: [ - false, - ], - }, - }, - typeOptions: { - minValue: 1, - maxValue: 100, - }, - default: 100, - description: 'How many results to return.', -}, -{ - displayName: 'Filters', - name: 'filters', - type: 'collection', - placeholder: 'Add Filter', - default: {}, - displayOptions: { - show: { - resource: [ - 'project', - ], - operation: [ - 'getAll', - ], - }, - }, - options: [ - { - displayName: 'Is Active', - name: 'is_active', - type: 'boolean', - default: true, - description: 'Pass true to only return active projects and false to return inactive projects.', - }, - { - displayName: 'Client Id', - name: 'client_id', - type: 'string', - default: '', - description: 'Only return projects belonging to the client with the given ID.', - }, - { - displayName: 'Updated Since', - name: 'updated_since', - type: 'dateTime', - default: '', - description: 'Only return projects by updated_since.', - }, - { - displayName: 'Page', - name: 'page', - type: 'number', - typeOptions: { - minValue: 1, + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource, + operation: [ + 'getAll', + ], }, - default: 1, - description: 'The page number to use in pagination.', - }, - - ] -}, - -/* -------------------------------------------------------------------------- */ -/* project:get */ -/* -------------------------------------------------------------------------- */ -{ - displayName: 'Project Id', - name: 'id', - type: 'string', - default: '', - required: true, - displayOptions: { - show: { - operation: [ - 'get', - ], - resource: [ - 'project', - ], }, + default: false, + description: 'Returns a list of your projects.', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource, + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 100, + description: 'How many results to return.', + }, + { + displayName: 'Filters', + name: 'filters', + type: 'collection', + placeholder: 'Add Filter', + default: {}, + displayOptions: { + show: { + resource, + operation: [ + 'getAll', + ], + }, + }, + options: [ + { + displayName: 'Client Id', + name: 'client_id', + type: 'string', + default: '', + description: 'Only return projects belonging to the client with the given ID.', + }, + { + displayName: 'Is Active', + name: 'is_active', + type: 'boolean', + default: true, + description: 'Pass true to only return active projects and false to return inactive projects.', + }, + { + displayName: 'Page', + name: 'page', + type: 'number', + typeOptions: { + minValue: 1, + }, + default: 1, + description: 'The page number to use in pagination.', + }, + { + displayName: 'Updated Since', + name: 'updated_since', + type: 'dateTime', + default: '', + description: 'Only return projects by updated_since.', + }, + ] + }, + + /* -------------------------------------------------------------------------- */ + /* project:get */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Project Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'get', + ], + resource, + }, + }, + description: 'The ID of the project you are retrieving.', + }, + + /* -------------------------------------------------------------------------- */ + /* project:delete */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Project Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'delete', + ], + resource, + }, + }, + description: 'The ID of the project want to delete.', + }, + + /* -------------------------------------------------------------------------- */ + /* project:create */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Name', + name: 'name', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: '', + required: true, + description: 'The name of the project.', + }, + { + displayName: 'Client Id', + name: 'clientId', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: '', + required: true, + description: 'The ID of the client to associate this project with.', + }, + { + displayName: 'Is Billable', + name: 'isBillable', + type: 'boolean', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: true, + required: true, + description: 'Whether the project is billable or not.', + }, + { + displayName: 'Bill By', + name: 'billBy', + type: 'options', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + options: [ + { + name: 'none', + value: 'none', + }, + { + name: 'People', + value: 'People', + }, + { + name: 'Project', + value: 'Project', + }, + { + name: 'Tasks', + value: 'Tasks', + }, + ], + default: 'none', + required: true, + description: 'The method by which the project is invoiced.', + }, + { + displayName: 'Budget By', + name: 'budgetBy', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: 'none', + placeholder: '', + required: true, + description: 'The email of the user or "none".', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: {}, + options: [ + { + displayName: 'Budget', + name: 'budget', + type: 'number', + typeOptions: { + minValue: 0, + }, + default: 0, + description: 'The budget in hours for the project when budgeting by time.' + }, + { + displayName: 'Budget Is Monthly', + name: 'budget_is_monthly', + type: 'boolean', + default: false, + description: 'Option to have the budget reset every month. Defaults to false.' + }, + { + displayName: 'Cost Budget', + name: 'cost_budget', + type: 'string', + default: '', + description: 'The monetary budget for the project when budgeting by money.' + }, + { + displayName: 'Cost Budget Include Expenses', + name: 'cost_budget_include_expenses', + type: 'boolean', + default: false, + description: 'Option for budget of Total Project Fees projects to include tracked expenses. Defaults to false.' + }, + { + displayName: 'Ends On', + name: 'ends_on', + type: 'dateTime', + default: '', + description: 'Date the project will end.' + }, + { + displayName: 'Fee', + name: 'fee', + type: 'string', + default: '', + description: 'The amount you plan to invoice for the project. Only used by fixed-fee projects.' + }, + { + displayName: 'Hourly Rate', + name: 'hourly_rate', + type: 'string', + default: '', + description: 'Rate for projects billed by Project Hourly Rate.' + }, + { + displayName: 'Is Active', + name: 'is_active', + type: 'boolean', + default: true, + description: 'Whether the project is active or archived. Defaults to true' + }, + { + displayName: 'Is Fixed Fee', + name: 'is_fixed_fee', + type: 'boolean', + default: false, + description: 'Whether the project is a fixed-fee project or not.' + }, + { + displayName: 'Notes', + name: 'notes', + type: 'string', + default: '', + description: 'Notes about the project.' + }, + { + displayName: 'Notify When Over Budget', + name: 'notify_when_over_budget', + type: 'boolean', + default: false, + description: 'Whether project managers should be notified when the project goes over budget. Defaults to false.' + }, + { + displayName: 'Over Budget Notification Percentage', + name: 'over_budget_notification_percentage', + type: 'string', + default: '', + description: 'Percentage value used to trigger over budget email alerts. Example: use 10.0 for 10.0%.' + }, + { + displayName: 'Show Budget To All', + name: 'show_budget_to_all', + type: 'boolean', + default: false, + description: 'Option to show project budget to all employees. Does not apply to Total Project Fee projects. Defaults to false.' + }, + { + displayName: 'Starts On', + name: 'starts_on', + type: 'dateTime', + default: '', + description: 'Date the project was started.' + }, + ], + }, + + /* -------------------------------------------------------------------------- */ + /* project:update */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Project Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'update', + ], + resource, + }, + }, + description: 'The ID of the project want to update.', + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'update', + ], + resource, + }, + }, + default: {}, + options: [ + { + displayName: 'Bill By', + name: 'bill_by', + type: 'options', + options: [ + { + name: 'none', + value: 'none', + }, + { + name: 'People', + value: 'People', + }, + { + name: 'Project', + value: 'Project', + }, + { + name: 'Tasks', + value: 'Tasks', + }, + ], + default: 'none', + description: 'The method by which the project is invoiced.', + }, + { + displayName: 'Budget', + name: 'budget', + type: 'string', + default: '', + description: 'The budget in hours for the project when budgeting by time.' + }, + { + displayName: 'Budget By', + name: 'budget_by', + type: 'string', + default: '', + description: 'The email of the user or "none".', + }, + { + displayName: 'Budget Is Monthly', + name: 'budget_is_monthly', + type: 'boolean', + default: false, + description: 'Option to have the budget reset every month. Defaults to false.' + }, + { + displayName: 'Client Id', + name: 'client_id', + type: 'string', + default: '', + description: 'The ID of the client to associate this project with.', + }, + { + displayName: 'Cost Budget', + name: 'cost_budget', + type: 'string', + default: '', + description: 'The monetary budget for the project when budgeting by money.' + }, + { + displayName: 'Cost Budget Include Expenses', + name: 'cost_budget_include_expenses', + type: 'boolean', + default: false, + description: 'Option for budget of Total Project Fees projects to include tracked expenses. Defaults to false.' + }, + { + displayName: 'Ends On', + name: 'ends_on', + type: 'dateTime', + default: '', + description: 'Date the project will end.' + }, + { + displayName: 'Fee', + name: 'fee', + type: 'string', + default: '', + description: 'The amount you plan to invoice for the project. Only used by fixed-fee projects.' + }, + { + displayName: 'Hourly Rate', + name: 'hourly_rate', + type: 'string', + default: '', + description: 'Rate for projects billed by Project Hourly Rate.' + }, + { + displayName: 'Is Active', + name: 'is_active', + type: 'boolean', + default: true, + description: 'Whether the project is active or archived. Defaults to true' + }, + { + displayName: 'Is Billable', + name: 'is_billable', + type: 'boolean', + default: true, + description: 'Whether the project is billable or not.', + }, + { + displayName: 'Is Fixed Fee', + name: 'is_fixed_fee', + type: 'boolean', + default: false, + description: 'Whether the project is a fixed-fee project or not.' + }, + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'The name of the project.', + }, + { + displayName: 'Notes', + name: 'notes', + type: 'string', + default: '', + description: 'Notes about the project.' + }, + { + displayName: 'Notify When Over Budget', + name: 'notify_when_over_budget', + type: 'boolean', + default: false, + description: 'Whether project managers should be notified when the project goes over budget. Defaults to false.' + }, + { + displayName: 'Over Budget Notification Percentage', + name: 'over_budget_notification_percentage', + type: 'string', + default: '', + description: 'Percentage value used to trigger over budget email alerts. Example: use 10.0 for 10.0%.' + }, + { + displayName: 'Show Budget To All', + name: 'show_budget_to_all', + type: 'boolean', + default: false, + description: 'Option to show project budget to all employees. Does not apply to Total Project Fee projects. Defaults to false.' + }, + + { + displayName: 'Starts On', + name: 'starts_on', + type: 'dateTime', + default: '', + description: 'Date the project was started.' + }, + ], }, - description: 'The ID of the project you are retrieving.', -} ] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Harvest/TaskDescription.ts b/packages/nodes-base/nodes/Harvest/TaskDescription.ts index ac35fc2076..33ff7e918b 100644 --- a/packages/nodes-base/nodes/Harvest/TaskDescription.ts +++ b/packages/nodes-base/nodes/Harvest/TaskDescription.ts @@ -1,5 +1,5 @@ -import { INodeProperties } from "n8n-workflow"; - +import { INodeProperties } from 'n8n-workflow'; +const resource = ['task']; export const taskOperations = [ { displayName: 'Operation', @@ -7,12 +7,20 @@ export const taskOperations = [ type: 'options', displayOptions: { show: { - resource: [ - 'task', - ], + resource, }, }, options: [ + { + name: 'Create', + value: 'create', + description: `Create a task`, + }, + { + name: 'Delete', + value: 'delete', + description: `Delete a task`, + }, { name: 'Get', value: 'get', @@ -23,6 +31,11 @@ export const taskOperations = [ value: 'getAll', description: 'Get data of all tasks', }, + { + name: 'Update', + value: 'update', + description: `Update a task`, + }, ], default: 'getAll', description: 'The operation to perform.', @@ -32,115 +45,249 @@ export const taskOperations = [ export const taskFields = [ -/* -------------------------------------------------------------------------- */ -/* task:getAll */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* task:getAll */ + /* -------------------------------------------------------------------------- */ -{ - displayName: 'Return All', - name: 'returnAll', - type: 'boolean', - displayOptions: { - show: { - resource: [ - 'task', - ], - operation: [ - 'getAll', - ], - }, - }, - default: false, - description: 'Returns a list of your tasks.', -}, -{ - displayName: 'Limit', - name: 'limit', - type: 'number', - displayOptions: { - show: { - resource: [ - 'task', - ], - operation: [ - 'getAll', - ], - returnAll: [ - false, - ], - }, - }, - typeOptions: { - minValue: 1, - maxValue: 100, - }, - default: 100, - description: 'How many results to return.', -}, -{ - displayName: 'Filters', - name: 'filters', - type: 'collection', - placeholder: 'Add Filter', - default: {}, - displayOptions: { - show: { - resource: [ - 'task', - ], - operation: [ - 'getAll', - ], - }, - }, - options: [ - { - displayName: 'Is Active', - name: 'is_active', - type: 'boolean', - default: true, - description: 'Pass true to only return active tasks and false to return inactive tasks.', - }, - { - displayName: 'Updated Since', - name: 'updated_since', - type: 'dateTime', - default: '', - description: 'Only return tasks belonging to the task with the given ID.', - }, - { - displayName: 'Page', - name: 'page', - type: 'number', - typeOptions: { - minValue: 1, + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource, + operation: [ + 'getAll', + ], }, - default: 1, - description: 'The page number to use in pagination.', - } - ] -}, - -/* -------------------------------------------------------------------------- */ -/* task:get */ -/* -------------------------------------------------------------------------- */ -{ - displayName: 'Task Id', - name: 'id', - type: 'string', - default: '', - required: true, - displayOptions: { - show: { - operation: [ - 'get', - ], - resource: [ - 'task', - ], }, + default: false, + description: 'Returns a list of your tasks.', }, - description: 'The ID of the task you are retrieving.', -} + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource, + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 100, + description: 'How many results to return.', + }, + { + displayName: 'Filters', + name: 'filters', + type: 'collection', + placeholder: 'Add Filter', + default: {}, + displayOptions: { + show: { + resource, + operation: [ + 'getAll', + ], + }, + }, + options: [ + { + displayName: 'Is Active', + name: 'is_active', + type: 'boolean', + default: true, + description: 'Pass true to only return active tasks and false to return inactive tasks.', + }, + { + displayName: 'Page', + name: 'page', + type: 'number', + typeOptions: { + minValue: 1, + }, + default: 1, + description: 'The page number to use in pagination.', + }, + { + displayName: 'Updated Since', + name: 'updated_since', + type: 'dateTime', + default: '', + description: 'Only return tasks belonging to the task with the given ID.', + }, + ] + }, + + /* -------------------------------------------------------------------------- */ + /* task:get */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Task Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'get', + ], + resource, + }, + }, + description: 'The ID of the task you are retrieving.', + }, + + /* -------------------------------------------------------------------------- */ + /* task:delete */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Task Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'delete', + ], + resource, + }, + }, + description: 'The ID of the task you wan to delete.', + }, + + /* -------------------------------------------------------------------------- */ + /* task:create */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Name', + name: 'name', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: '', + required: true, + description: 'The name of the task.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: {}, + options: [ + { + displayName: 'Billable By Default', + name: 'billable_by_default', + type: 'boolean', + default: '', + description: 'Used in determining whether default tasks should be marked billable when creating a new project. Defaults to true.' + }, + { + displayName: 'Default Hourly Rate', + name: 'default_hourly_rate', + type: 'string', + default: '0', + description: 'The default hourly rate to use for this task when it is added to a project. Defaults to 0.' + }, + { + displayName: 'Is Default', + name: 'is_default', + type: 'boolean', + default: false, + description: 'Whether this task should be automatically added to future projects. Defaults to false.' + }, + { + displayName: 'Is Active', + name: 'is_active', + type: 'boolean', + default: true, + description: 'Whether this task is active or archived. Defaults to true' + }, + ], + }, + /* -------------------------------------------------------------------------- */ + /* task:update */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Update Field', + displayOptions: { + show: { + operation: [ + 'update', + ], + resource, + }, + }, + default: {}, + options: [ + + { + displayName: 'Billable By Default', + name: 'billable_by_default', + type: 'boolean', + default: '', + description: 'Used in determining whether default tasks should be marked billable when creating a new project. Defaults to true.' + }, + { + displayName: 'Default Hourly Rate', + name: 'default_hourly_rate', + type: 'string', + default: '0', + description: 'The default hourly rate to use for this task when it is added to a project. Defaults to 0.' + }, + { + displayName: 'Is Active', + name: 'is_active', + type: 'boolean', + default: true, + description: 'Whether this task is active or archived. Defaults to true' + }, + { + displayName: 'Is Default', + name: 'is_default', + type: 'boolean', + default: false, + description: 'Whether this task should be automatically added to future projects. Defaults to false.' + }, + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'Name of the task.' + }, + ], + }, + ] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Harvest/TimeEntryDescription.ts b/packages/nodes-base/nodes/Harvest/TimeEntryDescription.ts index a1ba83e2a0..be6d6d02b9 100644 --- a/packages/nodes-base/nodes/Harvest/TimeEntryDescription.ts +++ b/packages/nodes-base/nodes/Harvest/TimeEntryDescription.ts @@ -1,5 +1,5 @@ -import { INodeProperties } from "n8n-workflow"; - +import { INodeProperties } from 'n8n-workflow'; +export const resource = [ 'timeEntry' ]; export const timeEntryOperations = [ { displayName: 'Operation', @@ -7,9 +7,7 @@ export const timeEntryOperations = [ type: 'options', displayOptions: { show: { - resource: [ - 'timeEntry', - ], + resource, }, }, options: [ @@ -75,9 +73,7 @@ export const timeEntryFields = [ type: 'boolean', displayOptions: { show: { - resource: [ - 'timeEntry', - ], + resource, operation: [ 'getAll', ], @@ -92,9 +88,7 @@ export const timeEntryFields = [ type: 'number', displayOptions: { show: { - resource: [ - 'timeEntry', - ], + resource, operation: [ 'getAll', ], @@ -118,22 +112,13 @@ export const timeEntryFields = [ default: {}, displayOptions: { show: { - resource: [ - 'timeEntry', - ], + resource, operation: [ 'getAll', ], }, }, options: [ - { - displayName: 'User ID', - name: 'user_id', - type: 'string', - default: '', - description: 'Only return time entries belonging to the user with the given ID.', - }, { displayName: 'Client ID', name: 'client_id', @@ -141,6 +126,13 @@ export const timeEntryFields = [ default: '', description: 'Only return time entries belonging to the client with the given ID.', }, + { + displayName: 'From', + name: 'from', + type: 'dateTime', + default: '', + description: 'Only return time entries with a spent_date on or after the given date.', + }, { displayName: 'Is Billed', name: 'is_billed', @@ -155,20 +147,6 @@ export const timeEntryFields = [ default: true, description: 'Pass true to only return running time entries and false to return non-running time entries.', }, - { - displayName: 'Updated Since', - name: 'updated_since', - type: 'dateTime', - default: '', - description: 'Only return time entries that have been updated since the given date and time.', - }, - { - displayName: 'From', - name: 'from', - type: 'dateTime', - default: '', - description: 'Only return time entries with a spent_date on or after the given date.', - }, { displayName: 'To', name: 'to', @@ -176,6 +154,13 @@ export const timeEntryFields = [ default: '', description: 'Only return time entries with a spent_date on or before the given date.', }, + { + displayName: 'Updated Since', + name: 'updated_since', + type: 'dateTime', + default: '', + description: 'Only return time entries that have been updated since the given date and time.', + }, { displayName: 'Page', name: 'page', @@ -185,8 +170,15 @@ export const timeEntryFields = [ }, default: 1, description: 'The page number to use in pagination. For instance, if you make a list request and receive 100 records, your subsequent call can include page=2 to retrieve the next page of the list. (Default: 1)', - } - ] + }, + { + displayName: 'User ID', + name: 'user_id', + type: 'string', + default: '', + description: 'Only return time entries belonging to the user with the given ID.', + }, + ], }, /* -------------------------------------------------------------------------- */ @@ -203,9 +195,7 @@ export const timeEntryFields = [ operation: [ 'get', ], - resource: [ - 'timeEntry', - ], + resource, }, }, description: 'The ID of the time entry you are retrieving.', @@ -225,9 +215,7 @@ export const timeEntryFields = [ operation: [ 'delete', ], - resource: [ - 'timeEntry', - ], + resource, }, }, description: 'The ID of the time entry you are deleting.', @@ -247,9 +235,7 @@ export const timeEntryFields = [ operation: [ 'deleteExternal', ], - resource: [ - 'timeEntry', - ], + resource, }, }, description: 'The ID of the time entry whose external reference you are deleting.', @@ -269,9 +255,7 @@ export const timeEntryFields = [ operation: [ 'stopTime', ], - resource: [ - 'timeEntry', - ], + resource, }, }, description: 'Stop a running time entry. Stopping a time entry is only possible if it’s currently running.', @@ -291,9 +275,7 @@ export const timeEntryFields = [ operation: [ 'restartTime', ], - resource: [ - 'timeEntry', - ], + resource, }, }, description: 'Restart a stopped time entry. Restarting a time entry is only possible if it isn’t currently running.', @@ -313,9 +295,7 @@ export const timeEntryFields = [ operation: [ 'update', ], - resource: [ - 'timeEntry', - ], + resource, }, }, description: 'The ID of the time entry to update.', @@ -330,9 +310,7 @@ export const timeEntryFields = [ operation: [ 'update', ], - resource: [ - 'timeEntry', - ], + resource, }, }, default: {}, @@ -385,9 +363,7 @@ export const timeEntryFields = [ operation: [ 'createByDuration', ], - resource: [ - 'timeEntry', - ], + resource, }, }, default: '', @@ -403,9 +379,7 @@ export const timeEntryFields = [ operation: [ 'createByDuration', ], - resource: [ - 'timeEntry', - ], + resource, }, }, default: '', @@ -421,9 +395,7 @@ export const timeEntryFields = [ operation: [ 'createByDuration', ], - resource: [ - 'timeEntry', - ], + resource, }, }, default: '', @@ -440,9 +412,7 @@ export const timeEntryFields = [ operation: [ 'createByDuration', ], - resource: [ - 'timeEntry', - ], + resource, }, }, default: {}, @@ -486,9 +456,7 @@ export const timeEntryFields = [ operation: [ 'createByStartEnd', ], - resource: [ - 'timeEntry', - ], + resource, }, }, default: '', @@ -504,9 +472,7 @@ export const timeEntryFields = [ operation: [ 'createByStartEnd', ], - resource: [ - 'timeEntry', - ], + resource, }, }, default: '', @@ -522,9 +488,7 @@ export const timeEntryFields = [ operation: [ 'createByStartEnd', ], - resource: [ - 'timeEntry', - ], + resource, }, }, default: '', @@ -541,9 +505,7 @@ export const timeEntryFields = [ operation: [ 'createByStartEnd', ], - resource: [ - 'timeEntry', - ], + resource, }, }, default: {}, diff --git a/packages/nodes-base/nodes/Harvest/UserDescription.ts b/packages/nodes-base/nodes/Harvest/UserDescription.ts index 4e1c563c7d..ea434c3ca3 100644 --- a/packages/nodes-base/nodes/Harvest/UserDescription.ts +++ b/packages/nodes-base/nodes/Harvest/UserDescription.ts @@ -1,4 +1,6 @@ -import { INodeProperties } from "n8n-workflow"; +import { INodeProperties } from 'n8n-workflow'; + +const resource = ['user']; export const userOperations = [ { @@ -7,16 +9,19 @@ export const userOperations = [ type: 'options', displayOptions: { show: { - resource: [ - 'user', - ], + resource, }, }, options: [ { - name: 'Me', - value: 'me', - description: 'Get data of authenticated user', + name: 'Create', + value: 'create', + description: `Create a user`, + }, + { + name: 'Delete', + value: 'delete', + description: `Delete a user`, }, { name: 'Get', @@ -28,6 +33,17 @@ export const userOperations = [ value: 'getAll', description: 'Get data of all users', }, + + { + name: 'Me', + value: 'me', + description: 'Get data of authenticated user', + }, + { + name: 'Update', + value: 'update', + description: `Update a user`, + }, ], default: 'me', description: 'The operation to perform.', @@ -37,115 +53,449 @@ export const userOperations = [ export const userFields = [ -/* -------------------------------------------------------------------------- */ -/* user:getAll */ -/* -------------------------------------------------------------------------- */ + /* -------------------------------------------------------------------------- */ + /* user:getAll */ + /* -------------------------------------------------------------------------- */ -{ - displayName: 'Return All', - name: 'returnAll', - type: 'boolean', - displayOptions: { - show: { - resource: [ - 'user', - ], - operation: [ - 'getAll', - ], - }, - }, - default: false, - description: 'Returns a list of your users.', -}, -{ - displayName: 'Limit', - name: 'limit', - type: 'number', - displayOptions: { - show: { - resource: [ - 'user', - ], - operation: [ - 'getAll', - ], - returnAll: [ - false, - ], - }, - }, - typeOptions: { - minValue: 1, - maxValue: 100, - }, - default: 100, - description: 'How many results to return.', -}, -{ - displayName: 'Filters', - name: 'filters', - type: 'collection', - placeholder: 'Add Filter', - default: {}, - displayOptions: { - show: { - resource: [ - 'user', - ], - operation: [ - 'getAll', - ], - }, - }, - options: [ - { - displayName: 'Is Active', - name: 'is_active', - type: 'boolean', - default: true, - description: 'Pass true to only return active users and false to return inactive users.', - }, - { - displayName: 'Updated Since', - name: 'updated_since', - type: 'dateTime', - default: '', - description: 'Only return users belonging to the user with the given ID.', - }, - { - displayName: 'Page', - name: 'page', - type: 'number', - typeOptions: { - minValue: 1, + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource, + operation: [ + 'getAll', + ], }, - default: 1, - description: 'The page number to use in pagination..', - } - ] -}, - -/* -------------------------------------------------------------------------- */ -/* user:get */ -/* -------------------------------------------------------------------------- */ -{ - displayName: 'User Id', - name: 'id', - type: 'string', - default: '', - required: true, - displayOptions: { - show: { - operation: [ - 'get', - ], - resource: [ - 'user', - ], }, + default: false, + description: 'Returns a list of your users.', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource, + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 100, + description: 'How many results to return.', + }, + { + displayName: 'Filters', + name: 'filters', + type: 'collection', + placeholder: 'Add Filter', + default: {}, + displayOptions: { + show: { + resource, + operation: [ + 'getAll', + ], + }, + }, + options: [ + { + displayName: 'Is Active', + name: 'is_active', + type: 'boolean', + default: true, + description: 'Pass true to only return active users and false to return inactive users.', + }, + { + displayName: 'Updated Since', + name: 'updated_since', + type: 'dateTime', + default: '', + description: 'Only return users belonging to the user with the given ID.', + }, + { + displayName: 'Page', + name: 'page', + type: 'number', + typeOptions: { + minValue: 1, + }, + default: 1, + description: 'The page number to use in pagination..', + } + ] + }, + + /* -------------------------------------------------------------------------- */ + /* user:get */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'User Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'get', + ], + resource, + }, + }, + description: 'The ID of the user you are retrieving.', + }, + + /* -------------------------------------------------------------------------- */ + /* user:delete */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'User Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'delete', + ], + resource, + }, + }, + description: 'The ID of the user you want to delete.', + }, + + /* -------------------------------------------------------------------------- */ + /* user:create */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'First Name', + name: 'firstName', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: '', + required: true, + description: 'The first name of the user.', + }, + { + displayName: 'Last Name', + name: 'lastName', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: '', + required: true, + description: 'The last name of the user.', + }, + { + displayName: 'Email', + name: 'email', + type: 'string', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: '', + required: true, + description: 'The email of the user.', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource, + }, + }, + default: {}, + options: [ + { + displayName: 'Can Create Projects', + name: 'can_create_projects', + type: 'boolean', + default: false, + description: 'Whether the user can create projects. Only applicable to Project Managers.' + }, + { + displayName: 'Can Create Invoices', + name: 'can_create_invoices', + type: 'boolean', + default: false, + description: 'Whether the user can create invoices. Only applicable to Project Managers.' + }, + { + displayName: 'Can See Rates', + name: 'can_see_rates', + type: 'boolean', + default: false, + description: 'Whether the user can see billable rates on projects. Only applicable to Project Managers.' + }, + { + displayName: 'Cost Rate', + name: 'cost_rate', + type: 'number', + typeOptions: { + minValue: 0, + }, + default: 0, + description: 'The cost rate to use for this user when calculating a project’s costs vs billable amount.' + }, + { + displayName: 'Default Hourly Rate', + name: 'default_hourly_rate', + type: 'string', + default: '0', + description: 'The billable rate to use for this user when they are added to a project.' + }, + { + displayName: 'Has Access To All Future Projects', + name: 'has_access_to_all_future_projects', + type: 'boolean', + default: false, + description: 'Whether the user should be automatically added to future projects.' + }, + { + displayName: 'Is Active', + name: 'is_active', + type: 'boolean', + default: true, + description: 'Whether the user is active or archived.' + }, + { + displayName: 'Is Admin', + name: 'is_admin', + type: 'boolean', + default: false, + description: 'Whether the user has Admin permissions.' + }, + { + displayName: 'Is Contractor', + name: 'is_contractor', + type: 'boolean', + default: false, + description: 'Whether the user is a contractor or an employee.' + }, + { + displayName: 'Is Project Manager', + name: 'is_project_manager', + type: 'boolean', + default: false, + description: 'Whether the user has Project Manager permissions.' + }, + { + displayName: 'Roles', + name: 'roles', + type: 'string', + default: '', + description: 'The role names assigned to this person.' + }, + { + displayName: 'Timezone', + name: 'timezone', + type: 'string', + default: '', + description: 'The user’s timezone. Defaults to the company’s timezone. See a list of supported time zones.' + }, + { + displayName: 'Weekly Capacity', + name: 'weekly_capacity', + type: 'number', + typeOptions: { + minValue: 0, + }, + default: 126000, + description: 'The number of hours per week this person is available to work in seconds. Defaults to 126000 seconds (35 hours).' + }, + ], + }, + + + /* -------------------------------------------------------------------------- */ + /* user:update */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Time Entry Id', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + operation: [ + 'update', + ], + resource, + }, + }, + description: 'The ID of the time entry to update.', + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'update', + ], + resource + }, + }, + default: {}, + options: [ + { + displayName: 'Can Create Projects', + name: 'can_create_projects', + type: 'boolean', + default: false, + description: 'Whether the user can create projects. Only applicable to Project Managers.' + }, + { + displayName: 'Can Create Invoices', + name: 'can_create_invoices', + type: 'boolean', + default: false, + description: 'Whether the user can create invoices. Only applicable to Project Managers.' + }, + { + displayName: 'Can See Rates', + name: 'can_see_rates', + type: 'boolean', + default: false, + description: 'Whether the user can see billable rates on projects. Only applicable to Project Managers.' + }, + { + displayName: 'Cost Rate', + name: 'cost_rate', + type: 'number', + typeOptions: { + minValue: 0, + }, + default: 0, + description: 'The cost rate to use for this user when calculating a project’s costs vs billable amount.' + }, + { + displayName: 'Default Hourly Rate', + name: 'default_hourly_rate', + type: 'string', + default: '0', + description: 'The billable rate to use for this user when they are added to a project.' + }, + { + displayName: 'Email', + name: 'email', + type: 'string', + default: '', + description: 'The user email' + }, + { + displayName: 'First Name', + name: 'first_name', + type: 'string', + default: '', + description: 'The user first name' + }, + { + displayName: 'Has Access To All Future Projects', + name: 'has_access_to_all_future_projects', + type: 'boolean', + default: false, + description: 'Whether the user should be automatically added to future projects.' + }, + { + displayName: 'Is Active', + name: 'is_active', + type: 'boolean', + default: true, + description: 'Whether the user is active or archived.' + }, + { + displayName: 'Is Admin', + name: 'is_admin', + type: 'boolean', + default: false, + description: 'Whether the user has Admin permissions.' + }, + { + displayName: 'Is Contractor', + name: 'is_contractor', + type: 'boolean', + default: false, + description: 'Whether the user is a contractor or an employee.' + }, + { + displayName: 'Is Project Manager', + name: 'is_project_manager', + type: 'boolean', + default: false, + description: 'Whether the user has Project Manager permissions.' + }, + { + displayName: 'Last Name', + name: 'last_name', + type: 'string', + default: '', + description: 'The user last name' + }, + { + displayName: 'Roles', + name: 'roles', + type: 'string', + default: '', + description: 'The role names assigned to this person.' + }, + { + displayName: 'Timezone', + name: 'timezone', + type: 'string', + default: '', + description: 'The user’s timezone. Defaults to the company’s timezone. See a list of supported time zones.' + }, + { + displayName: 'Weekly Capacity', + name: 'weekly_capacity', + type: 'number', + typeOptions: { + minValue: 0, + }, + default: 126000, + description: 'The number of hours per week this person is available to work in seconds. Defaults to 126000 seconds (35 hours).' + }, + ], }, - description: 'The ID of the user you are retrieving.', -} ] as INodeProperties[];