mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
⚡ Add Harvest OAuth2 support (#697)
* credentials, generic functions fit to oauth2, UI elements * ⚡ Improvements to Harvest-Node * Update Harvest.node.ts * ⚡ Add OAuth2 and move account id from credentials to node parameters * ⚡ Minor improvements to Harvest-Node Co-authored-by: Rupenieks <ru@myos,co> Co-authored-by: ricardo <ricardoespinoza105@gmail.com> Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
This commit is contained in:
parent
af9d8e1cba
commit
3351113f28
|
@ -2,6 +2,20 @@
|
||||||
|
|
||||||
This list shows all the versions which include breaking changes and how to upgrade.
|
This list shows all the versions which include breaking changes and how to upgrade.
|
||||||
|
|
||||||
|
## 0.95.0
|
||||||
|
|
||||||
|
### What changed?
|
||||||
|
|
||||||
|
In the Harvest Node, we moved the account field from the credentials to the node parameters. This will allow you to work witn multiples accounts without having to create multiples credentials.
|
||||||
|
|
||||||
|
### When is action necessary?
|
||||||
|
|
||||||
|
If you are using the Harvest Node.
|
||||||
|
|
||||||
|
### How to upgrade:
|
||||||
|
|
||||||
|
Open the node set the parameter `Account ID`.
|
||||||
|
|
||||||
## 0.94.0
|
## 0.94.0
|
||||||
|
|
||||||
### What changed?
|
### What changed?
|
||||||
|
|
|
@ -8,13 +8,6 @@ export class HarvestApi implements ICredentialType {
|
||||||
displayName = 'Harvest API';
|
displayName = 'Harvest API';
|
||||||
documentationUrl = 'harvest';
|
documentationUrl = 'harvest';
|
||||||
properties = [
|
properties = [
|
||||||
{
|
|
||||||
displayName: 'Account ID',
|
|
||||||
name: 'accountId',
|
|
||||||
type: 'string' as NodePropertyTypes,
|
|
||||||
default: '',
|
|
||||||
description: 'Visit your account details page, and grab the Account ID. See <a href="https://help.getharvest.com/api-v2/authentication-api/authentication/authentication/">Harvest Personal Access Tokens</a>.',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
displayName: 'Access Token',
|
displayName: 'Access Token',
|
||||||
name: 'accessToken',
|
name: 'accessToken',
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
import {
|
||||||
|
ICredentialType,
|
||||||
|
NodePropertyTypes,
|
||||||
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
|
|
||||||
|
export class HarvestOAuth2Api implements ICredentialType {
|
||||||
|
name = 'harvestOAuth2Api';
|
||||||
|
extends = [
|
||||||
|
'oAuth2Api',
|
||||||
|
];
|
||||||
|
displayName = 'Harvest OAuth2 API';
|
||||||
|
properties = [
|
||||||
|
{
|
||||||
|
displayName: 'Authorization URL',
|
||||||
|
name: 'authUrl',
|
||||||
|
type: 'hidden' as NodePropertyTypes,
|
||||||
|
default: 'https://id.getharvest.com/oauth2/authorize',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Access Token URL',
|
||||||
|
name: 'accessTokenUrl',
|
||||||
|
type: 'hidden' as NodePropertyTypes,
|
||||||
|
default: 'https://id.getharvest.com/api/v2/oauth2/token',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Scope',
|
||||||
|
name: 'scope',
|
||||||
|
type: 'hidden' as NodePropertyTypes,
|
||||||
|
default: 'all',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Auth URI Query Parameters',
|
||||||
|
name: 'authQueryParameters',
|
||||||
|
type: 'hidden' as NodePropertyTypes,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Authentication',
|
||||||
|
name: 'authentication',
|
||||||
|
type: 'hidden' as NodePropertyTypes,
|
||||||
|
default: 'body',
|
||||||
|
description: 'Resource to consume.',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { INodeProperties } from 'n8n-workflow';
|
import { INodeProperties } from 'n8n-workflow';
|
||||||
|
|
||||||
const resource = [ 'company' ];
|
const resource = ['company'];
|
||||||
|
|
||||||
export const companyOperations = [
|
export const companyOperations = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { INodeProperties } from 'n8n-workflow';
|
import { INodeProperties } from 'n8n-workflow';
|
||||||
|
|
||||||
const resource = [ 'estimate' ];
|
const resource = ['estimate'];
|
||||||
|
|
||||||
export const estimateOperations = [
|
export const estimateOperations = [
|
||||||
{
|
{
|
||||||
|
@ -47,149 +47,149 @@ export const estimateOperations = [
|
||||||
|
|
||||||
export const estimateFields = [
|
export const estimateFields = [
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* estimate:getAll */
|
/* estimate:getAll */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
{
|
{
|
||||||
displayName: 'Return All',
|
displayName: 'Return All',
|
||||||
name: 'returnAll',
|
name: 'returnAll',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
resource,
|
resource,
|
||||||
operation: [
|
operation: [
|
||||||
'getAll',
|
'getAll',
|
||||||
],
|
],
|
||||||
},
|
|
||||||
},
|
|
||||||
default: false,
|
|
||||||
description: 'Returns a list of your estimates.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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 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: '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',
|
|
||||||
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: 'Page',
|
|
||||||
name: 'page',
|
|
||||||
type: 'number',
|
|
||||||
typeOptions: {
|
|
||||||
minValue: 1,
|
|
||||||
},
|
},
|
||||||
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)',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* estimate:get */
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
{
|
|
||||||
displayName: 'Estimate Id',
|
|
||||||
name: 'id',
|
|
||||||
type: 'string',
|
|
||||||
default: '',
|
|
||||||
required: true,
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: [
|
|
||||||
'get',
|
|
||||||
],
|
|
||||||
resource,
|
|
||||||
},
|
},
|
||||||
|
default: false,
|
||||||
|
description: 'Returns a list of your estimates.',
|
||||||
},
|
},
|
||||||
description: 'The ID of the estimate you are retrieving.',
|
{
|
||||||
},
|
displayName: 'Limit',
|
||||||
|
name: 'limit',
|
||||||
/* -------------------------------------------------------------------------- */
|
type: 'number',
|
||||||
/* estimate:delete */
|
displayOptions: {
|
||||||
/* -------------------------------------------------------------------------- */
|
show: {
|
||||||
{
|
resource,
|
||||||
displayName: 'Estimate Id',
|
operation: [
|
||||||
name: 'id',
|
'getAll',
|
||||||
type: 'string',
|
],
|
||||||
default: '',
|
returnAll: [
|
||||||
required: true,
|
false,
|
||||||
displayOptions: {
|
],
|
||||||
show: {
|
},
|
||||||
operation: [
|
|
||||||
'delete',
|
|
||||||
],
|
|
||||||
resource,
|
|
||||||
},
|
},
|
||||||
|
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 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: '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',
|
||||||
|
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: 'Page',
|
||||||
|
name: 'page',
|
||||||
|
type: 'number',
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 1,
|
||||||
|
},
|
||||||
|
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)',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* estimate:get */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
displayName: 'Estimate Id',
|
||||||
|
name: 'id',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'get',
|
||||||
|
],
|
||||||
|
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.',
|
||||||
},
|
},
|
||||||
description: 'The ID of the estimate want to delete.',
|
|
||||||
},
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* estimate:create */
|
/* estimate:create */
|
||||||
|
@ -291,7 +291,7 @@ export const estimateFields = [
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* estimate:update */
|
/* estimate:update */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { INodeProperties } from 'n8n-workflow';
|
import { INodeProperties } from 'n8n-workflow';
|
||||||
|
|
||||||
const resource = [ 'expense' ];
|
const resource = ['expense'];
|
||||||
|
|
||||||
export const expenseOperations = [
|
export const expenseOperations = [
|
||||||
{
|
{
|
||||||
|
@ -47,163 +47,163 @@ export const expenseOperations = [
|
||||||
|
|
||||||
export const expenseFields = [
|
export const expenseFields = [
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* expense:getAll */
|
/* expense:getAll */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
{
|
{
|
||||||
displayName: 'Return All',
|
displayName: 'Return All',
|
||||||
name: 'returnAll',
|
name: 'returnAll',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
resource,
|
resource,
|
||||||
operation: [
|
operation: [
|
||||||
'getAll',
|
'getAll',
|
||||||
],
|
],
|
||||||
},
|
|
||||||
},
|
|
||||||
default: false,
|
|
||||||
description: 'Returns a list of your expenses.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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 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',
|
|
||||||
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',
|
|
||||||
name: 'page',
|
|
||||||
type: 'number',
|
|
||||||
typeOptions: {
|
|
||||||
minValue: 1,
|
|
||||||
},
|
},
|
||||||
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.',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* expense:get */
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
{
|
|
||||||
displayName: 'Expense Id',
|
|
||||||
name: 'id',
|
|
||||||
type: 'string',
|
|
||||||
default: '',
|
|
||||||
required: true,
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: [
|
|
||||||
'get',
|
|
||||||
],
|
|
||||||
resource,
|
|
||||||
},
|
},
|
||||||
|
default: false,
|
||||||
|
description: 'Returns a list of your expenses.',
|
||||||
},
|
},
|
||||||
description: 'The ID of the expense you are retrieving.',
|
{
|
||||||
},
|
displayName: 'Limit',
|
||||||
|
name: 'limit',
|
||||||
/* -------------------------------------------------------------------------- */
|
type: 'number',
|
||||||
/* expense:delete */
|
displayOptions: {
|
||||||
/* -------------------------------------------------------------------------- */
|
show: {
|
||||||
{
|
resource,
|
||||||
displayName: 'Expense Id',
|
operation: [
|
||||||
name: 'id',
|
'getAll',
|
||||||
type: 'string',
|
],
|
||||||
default: '',
|
returnAll: [
|
||||||
required: true,
|
false,
|
||||||
displayOptions: {
|
],
|
||||||
show: {
|
},
|
||||||
operation: [
|
|
||||||
'delete',
|
|
||||||
],
|
|
||||||
resource,
|
|
||||||
},
|
},
|
||||||
|
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 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',
|
||||||
|
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',
|
||||||
|
name: 'page',
|
||||||
|
type: 'number',
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 1,
|
||||||
|
},
|
||||||
|
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.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* expense:get */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
displayName: 'Expense Id',
|
||||||
|
name: 'id',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'get',
|
||||||
|
],
|
||||||
|
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.',
|
||||||
},
|
},
|
||||||
description: 'The ID of the expense you want to delete.',
|
|
||||||
},
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* expense:create */
|
/* expense:create */
|
||||||
|
@ -309,7 +309,7 @@ export const expenseFields = [
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* invoice:update */
|
/* invoice:update */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,60 +1,53 @@
|
||||||
import { OptionsWithUri } from 'request';
|
import {
|
||||||
|
OptionsWithUri,
|
||||||
|
} from 'request';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
IExecuteFunctions,
|
IExecuteFunctions,
|
||||||
IExecuteSingleFunctions,
|
IExecuteSingleFunctions,
|
||||||
IHookFunctions,
|
IHookFunctions,
|
||||||
ILoadOptionsFunctions,
|
ILoadOptionsFunctions,
|
||||||
} from 'n8n-core';
|
} from 'n8n-core';
|
||||||
import { IDataObject } from 'n8n-workflow';
|
|
||||||
|
|
||||||
export async function harvestApiRequest(
|
import {
|
||||||
this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
|
IDataObject
|
||||||
method: string,
|
} from 'n8n-workflow';
|
||||||
qs: IDataObject = {},
|
|
||||||
uri: string,
|
|
||||||
body: IDataObject = {},
|
|
||||||
option: IDataObject = {},
|
|
||||||
): Promise<any> { // tslint:disable-line:no-any
|
|
||||||
|
|
||||||
const credentials = this.getCredentials('harvestApi') as IDataObject;
|
|
||||||
|
|
||||||
if (credentials === undefined) {
|
|
||||||
throw new Error('No credentials got returned!');
|
|
||||||
}
|
|
||||||
|
|
||||||
qs.access_token = credentials.accessToken;
|
|
||||||
qs.account_id = credentials.accountId;
|
|
||||||
// Convert to query string into a format the API can read
|
|
||||||
const queryStringElements: string[] = [];
|
|
||||||
for (const key of Object.keys(qs)) {
|
|
||||||
if (Array.isArray(qs[key])) {
|
|
||||||
(qs[key] as string[]).forEach(value => {
|
|
||||||
queryStringElements.push(`${key}=${value}`);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
queryStringElements.push(`${key}=${qs[key]}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
export async function harvestApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, qs: IDataObject = {}, path: string, body: IDataObject = {}, option: IDataObject = {}, uri?: string): Promise<any> { // tslint:disable-line:no-any
|
||||||
let options: OptionsWithUri = {
|
let options: OptionsWithUri = {
|
||||||
|
headers: {
|
||||||
|
'Harvest-Account-Id': `${this.getNodeParameter('accountId', 0)}`,
|
||||||
|
'User-Agent': 'Harvest App',
|
||||||
|
'Authorization': '',
|
||||||
|
},
|
||||||
method,
|
method,
|
||||||
body,
|
body,
|
||||||
uri: `https://api.harvestapp.com/v2/${uri}?${queryStringElements.join('&')}`,
|
uri: uri || `https://api.harvestapp.com/v2/${path}`,
|
||||||
|
qs,
|
||||||
json: true,
|
json: true,
|
||||||
headers: {
|
|
||||||
"User-Agent": "Harvest API",
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
options = Object.assign({}, options, option);
|
options = Object.assign({}, options, option);
|
||||||
if (Object.keys(options.body).length === 0) {
|
if (Object.keys(options.body).length === 0) {
|
||||||
delete options.body;
|
delete options.body;
|
||||||
}
|
}
|
||||||
|
const authenticationMethod = this.getNodeParameter('authentication', 0);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await this.helpers.request!(options);
|
if (authenticationMethod === 'accessToken') {
|
||||||
|
const credentials = this.getCredentials('harvestApi') as IDataObject;
|
||||||
|
|
||||||
return result;
|
if (credentials === undefined) {
|
||||||
|
throw new Error('No credentials got returned!');
|
||||||
|
}
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
options.headers['Authorization'] = `Bearer ${credentials.accessToken}`;
|
||||||
|
|
||||||
|
return await this.helpers.request!(options);
|
||||||
|
} else {
|
||||||
|
return await this.helpers.requestOAuth2!.call(this, 'harvestOAuth2Api', options);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.statusCode === 401) {
|
if (error.statusCode === 401) {
|
||||||
// Return a clear error
|
// Return a clear error
|
||||||
|
@ -76,27 +69,51 @@ export async function harvestApiRequest(
|
||||||
* and return all results
|
* and return all results
|
||||||
*/
|
*/
|
||||||
export async function harvestApiRequestAllItems(
|
export async function harvestApiRequestAllItems(
|
||||||
this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
|
this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
|
||||||
method: string,
|
method: string,
|
||||||
qs: IDataObject = {},
|
qs: IDataObject = {},
|
||||||
uri: string,
|
uri: string,
|
||||||
resource: string,
|
resource: string,
|
||||||
body: IDataObject = {},
|
body: IDataObject = {},
|
||||||
option: IDataObject = {},
|
option: IDataObject = {},
|
||||||
): Promise<any> { // tslint:disable-line:no-any
|
): Promise<any> { // tslint:disable-line:no-any
|
||||||
|
|
||||||
const returnData: IDataObject[] = [];
|
const returnData: IDataObject[] = [];
|
||||||
|
|
||||||
let responseData;
|
let responseData;
|
||||||
|
|
||||||
try {
|
do {
|
||||||
do {
|
responseData = await harvestApiRequest.call(this, method, qs, uri, body, option);
|
||||||
responseData = await harvestApiRequest.call(this, method, qs, uri, body, option);
|
qs.page = responseData.next_page;
|
||||||
qs.page = responseData.next_page;
|
returnData.push.apply(returnData, responseData[resource]);
|
||||||
returnData.push.apply(returnData, responseData[resource]);
|
} while (responseData.next_page);
|
||||||
} while (responseData.next_page);
|
|
||||||
return returnData;
|
return returnData;
|
||||||
} catch(error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fetch All resource using paginated calls
|
||||||
|
*/
|
||||||
|
export async function getAllResource(this: IExecuteFunctions | ILoadOptionsFunctions, resource: string, i: number) {
|
||||||
|
const endpoint = resource;
|
||||||
|
const qs: IDataObject = {};
|
||||||
|
const requestMethod = 'GET';
|
||||||
|
|
||||||
|
qs.per_page = 100;
|
||||||
|
|
||||||
|
const additionalFields = this.getNodeParameter('filters', i) as IDataObject;
|
||||||
|
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
|
||||||
|
|
||||||
|
Object.assign(qs, additionalFields);
|
||||||
|
|
||||||
|
let responseData: IDataObject = {};
|
||||||
|
if (returnAll) {
|
||||||
|
responseData[resource] = await harvestApiRequestAllItems.call(this, requestMethod, qs, endpoint, resource);
|
||||||
|
} else {
|
||||||
|
const limit = this.getNodeParameter('limit', i) as string;
|
||||||
|
qs.per_page = limit;
|
||||||
|
responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint);
|
||||||
|
}
|
||||||
|
return responseData[resource] as IDataObject[];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
import {
|
import {
|
||||||
IExecuteFunctions,
|
IExecuteFunctions,
|
||||||
|
ILoadOptionsFunctions,
|
||||||
} from 'n8n-core';
|
} from 'n8n-core';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
IDataObject,
|
IDataObject,
|
||||||
INodeExecutionData,
|
INodeExecutionData,
|
||||||
|
INodePropertyOptions,
|
||||||
INodeType,
|
INodeType,
|
||||||
INodeTypeDescription,
|
INodeTypeDescription,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
@ -12,31 +15,41 @@ import {
|
||||||
clientFields,
|
clientFields,
|
||||||
clientOperations,
|
clientOperations,
|
||||||
} from './ClientDescription';
|
} from './ClientDescription';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
contactFields,
|
contactFields,
|
||||||
contactOperations,
|
contactOperations,
|
||||||
} from './ContactDescription';
|
} from './ContactDescription';
|
||||||
import { companyOperations } from './CompanyDescription';
|
|
||||||
|
import {
|
||||||
|
companyOperations,
|
||||||
|
} from './CompanyDescription';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
estimateFields,
|
estimateFields,
|
||||||
estimateOperations,
|
estimateOperations,
|
||||||
} from './EstimateDescription';
|
} from './EstimateDescription';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
expenseFields,
|
expenseFields,
|
||||||
expenseOperations,
|
expenseOperations,
|
||||||
} from './ExpenseDescription';
|
} from './ExpenseDescription';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
getAllResource,
|
||||||
harvestApiRequest,
|
harvestApiRequest,
|
||||||
harvestApiRequestAllItems,
|
|
||||||
} from './GenericFunctions';
|
} from './GenericFunctions';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
invoiceFields,
|
invoiceFields,
|
||||||
invoiceOperations,
|
invoiceOperations,
|
||||||
} from './InvoiceDescription';
|
} from './InvoiceDescription';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
projectFields,
|
projectFields,
|
||||||
projectOperations,
|
projectOperations,
|
||||||
} from './ProjectDescription';
|
} from './ProjectDescription';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
taskFields,
|
taskFields,
|
||||||
taskOperations,
|
taskOperations,
|
||||||
|
@ -45,36 +58,12 @@ import {
|
||||||
timeEntryFields,
|
timeEntryFields,
|
||||||
timeEntryOperations,
|
timeEntryOperations,
|
||||||
} from './TimeEntryDescription';
|
} from './TimeEntryDescription';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
userFields,
|
userFields,
|
||||||
userOperations,
|
userOperations,
|
||||||
} from './UserDescription';
|
} from './UserDescription';
|
||||||
|
|
||||||
/**
|
|
||||||
* fetch All resource using paginated calls
|
|
||||||
*/
|
|
||||||
async function getAllResource(this: IExecuteFunctions, resource: string, i: number) {
|
|
||||||
const endpoint = resource;
|
|
||||||
const qs: IDataObject = {};
|
|
||||||
const requestMethod = 'GET';
|
|
||||||
|
|
||||||
qs.per_page = 100;
|
|
||||||
|
|
||||||
const additionalFields = this.getNodeParameter('filters', i) as IDataObject;
|
|
||||||
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
|
|
||||||
Object.assign(qs, additionalFields);
|
|
||||||
|
|
||||||
let responseData: IDataObject = {};
|
|
||||||
if (returnAll) {
|
|
||||||
responseData[resource] = await harvestApiRequestAllItems.call(this, requestMethod, qs, endpoint, resource);
|
|
||||||
} else {
|
|
||||||
const limit = this.getNodeParameter('limit', i) as string;
|
|
||||||
qs.per_page = limit;
|
|
||||||
responseData = await harvestApiRequest.call(this, requestMethod, qs, endpoint);
|
|
||||||
}
|
|
||||||
return responseData[resource] as IDataObject[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Harvest implements INodeType {
|
export class Harvest implements INodeType {
|
||||||
description: INodeTypeDescription = {
|
description: INodeTypeDescription = {
|
||||||
displayName: 'Harvest',
|
displayName: 'Harvest',
|
||||||
|
@ -86,7 +75,7 @@ export class Harvest implements INodeType {
|
||||||
description: 'Access data on Harvest',
|
description: 'Access data on Harvest',
|
||||||
defaults: {
|
defaults: {
|
||||||
name: 'Harvest',
|
name: 'Harvest',
|
||||||
color: '#22BB44',
|
color: '#e7863f',
|
||||||
},
|
},
|
||||||
inputs: ['main'],
|
inputs: ['main'],
|
||||||
outputs: ['main'],
|
outputs: ['main'],
|
||||||
|
@ -94,9 +83,46 @@ export class Harvest implements INodeType {
|
||||||
{
|
{
|
||||||
name: 'harvestApi',
|
name: 'harvestApi',
|
||||||
required: true,
|
required: true,
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
authentication: [
|
||||||
|
'accessToken',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'harvestOAuth2Api',
|
||||||
|
required: true,
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
authentication: [
|
||||||
|
'oAuth2',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
properties: [
|
properties: [
|
||||||
|
{
|
||||||
|
displayName: 'Authentication',
|
||||||
|
name: 'authentication',
|
||||||
|
type: 'options',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Access Token',
|
||||||
|
value: 'accessToken',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'OAuth2',
|
||||||
|
value: 'oAuth2',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'accessToken',
|
||||||
|
description: 'Method of authentication.',
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
displayName: 'Resource',
|
displayName: 'Resource',
|
||||||
name: 'resource',
|
name: 'resource',
|
||||||
|
@ -148,6 +174,17 @@ export class Harvest implements INodeType {
|
||||||
description: 'The resource to operate on.',
|
description: 'The resource to operate on.',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
displayName: 'Account ID',
|
||||||
|
name: 'accountId',
|
||||||
|
type: 'options',
|
||||||
|
required: true,
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getAccounts',
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
|
||||||
// operations
|
// operations
|
||||||
...clientOperations,
|
...clientOperations,
|
||||||
...companyOperations,
|
...companyOperations,
|
||||||
|
@ -173,6 +210,26 @@ export class Harvest implements INodeType {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
methods = {
|
||||||
|
loadOptions: {
|
||||||
|
// Get all the available accounts to display them to user so that he can
|
||||||
|
// select them easily
|
||||||
|
async getAccounts(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
const returnData: INodePropertyOptions[] = [];
|
||||||
|
const { accounts } = await harvestApiRequest.call(this, 'GET', {}, '', {}, {}, 'https://id.getharvest.com/api/v2/accounts');
|
||||||
|
for (const account of accounts) {
|
||||||
|
const accountName = account.name;
|
||||||
|
const accountId = account.id;
|
||||||
|
returnData.push({
|
||||||
|
name: accountName,
|
||||||
|
value: accountId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return returnData;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||||
const items = this.getInputData();
|
const items = this.getInputData();
|
||||||
const returnData: IDataObject[] = [];
|
const returnData: IDataObject[] = [];
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { INodeProperties } from 'n8n-workflow';
|
import { INodeProperties } from 'n8n-workflow';
|
||||||
|
|
||||||
const resource = [ 'invoice' ];
|
const resource = ['invoice'];
|
||||||
|
|
||||||
export const invoiceOperations = [
|
export const invoiceOperations = [
|
||||||
{
|
{
|
||||||
|
@ -47,174 +47,174 @@ export const invoiceOperations = [
|
||||||
|
|
||||||
export const invoiceFields = [
|
export const invoiceFields = [
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* invoice:getAll */
|
/* invoice:getAll */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
{
|
{
|
||||||
displayName: 'Return All',
|
displayName: 'Return All',
|
||||||
name: 'returnAll',
|
name: 'returnAll',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
resource,
|
resource,
|
||||||
operation: [
|
operation: [
|
||||||
'getAll',
|
'getAll',
|
||||||
],
|
],
|
||||||
},
|
|
||||||
},
|
|
||||||
default: false,
|
|
||||||
description: 'Returns a list of your invoices.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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 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: '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',
|
|
||||||
type: 'dateTime',
|
|
||||||
default: '',
|
|
||||||
description: 'Only return time entries with a spent_date on or before the given date.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'State',
|
|
||||||
name: 'state',
|
|
||||||
type: 'multiOptions',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
name: 'draft',
|
|
||||||
value: 'draft',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'open',
|
|
||||||
value: 'open',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'paid',
|
|
||||||
value: 'paid',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'closed',
|
|
||||||
value: 'closed',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
default: [],
|
|
||||||
description: 'Only return invoices with a state matching the value provided. Options: draft, open, paid, or closed.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'Page',
|
|
||||||
name: 'page',
|
|
||||||
type: 'number',
|
|
||||||
typeOptions: {
|
|
||||||
minValue: 1,
|
|
||||||
},
|
},
|
||||||
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)',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* invoice:get */
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
{
|
|
||||||
displayName: 'Invoice Id',
|
|
||||||
name: 'id',
|
|
||||||
type: 'string',
|
|
||||||
default: '',
|
|
||||||
required: true,
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: [
|
|
||||||
'get',
|
|
||||||
],
|
|
||||||
resource,
|
|
||||||
},
|
},
|
||||||
|
default: false,
|
||||||
|
description: 'Returns a list of your invoices.',
|
||||||
},
|
},
|
||||||
description: 'The ID of the invoice you are retrieving.',
|
{
|
||||||
},
|
displayName: 'Limit',
|
||||||
|
name: 'limit',
|
||||||
/* -------------------------------------------------------------------------- */
|
type: 'number',
|
||||||
/* invoice:delete */
|
displayOptions: {
|
||||||
/* -------------------------------------------------------------------------- */
|
show: {
|
||||||
{
|
resource,
|
||||||
displayName: 'Invoice Id',
|
operation: [
|
||||||
name: 'id',
|
'getAll',
|
||||||
type: 'string',
|
],
|
||||||
default: '',
|
returnAll: [
|
||||||
required: true,
|
false,
|
||||||
displayOptions: {
|
],
|
||||||
show: {
|
},
|
||||||
operation: [
|
|
||||||
'delete',
|
|
||||||
],
|
|
||||||
resource,
|
|
||||||
},
|
},
|
||||||
|
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 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: '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',
|
||||||
|
type: 'dateTime',
|
||||||
|
default: '',
|
||||||
|
description: 'Only return time entries with a spent_date on or before the given date.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'State',
|
||||||
|
name: 'state',
|
||||||
|
type: 'multiOptions',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'draft',
|
||||||
|
value: 'draft',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'open',
|
||||||
|
value: 'open',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'paid',
|
||||||
|
value: 'paid',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'closed',
|
||||||
|
value: 'closed',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: [],
|
||||||
|
description: 'Only return invoices with a state matching the value provided. Options: draft, open, paid, or closed.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Page',
|
||||||
|
name: 'page',
|
||||||
|
type: 'number',
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 1,
|
||||||
|
},
|
||||||
|
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)',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* invoice:get */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
displayName: 'Invoice Id',
|
||||||
|
name: 'id',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'get',
|
||||||
|
],
|
||||||
|
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.',
|
||||||
},
|
},
|
||||||
description: 'The ID of the invoice want to delete.',
|
|
||||||
},
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* invoice:create */
|
/* invoice:create */
|
||||||
|
@ -344,7 +344,7 @@ export const invoiceFields = [
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* invoice:update */
|
/* invoice:update */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,7 +48,6 @@ export const taskFields = [
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* task:getAll */
|
/* task:getAll */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
{
|
{
|
||||||
displayName: 'Return All',
|
displayName: 'Return All',
|
||||||
name: 'returnAll',
|
name: 'returnAll',
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { INodeProperties } from 'n8n-workflow';
|
import { INodeProperties } from 'n8n-workflow';
|
||||||
export const resource = [ 'timeEntry' ];
|
export const resource = ['timeEntry'];
|
||||||
export const timeEntryOperations = [
|
export const timeEntryOperations = [
|
||||||
{
|
{
|
||||||
displayName: 'Operation',
|
displayName: 'Operation',
|
||||||
|
@ -63,485 +63,485 @@ export const timeEntryOperations = [
|
||||||
] as INodeProperties[];
|
] as INodeProperties[];
|
||||||
|
|
||||||
export const timeEntryFields = [
|
export const timeEntryFields = [
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* timeEntry:getAll */
|
/* timeEntry:getAll */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
{
|
{
|
||||||
displayName: 'Return All',
|
displayName: 'Return All',
|
||||||
name: 'returnAll',
|
name: 'returnAll',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
displayOptions: {
|
displayOptions: {
|
||||||
show: {
|
show: {
|
||||||
resource,
|
resource,
|
||||||
operation: [
|
operation: [
|
||||||
'getAll',
|
'getAll',
|
||||||
],
|
],
|
||||||
},
|
|
||||||
},
|
|
||||||
default: false,
|
|
||||||
description: 'Returns a list of your time entries.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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 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',
|
|
||||||
type: 'boolean',
|
|
||||||
default: true,
|
|
||||||
description: 'Pass true to only return time entries that have been invoiced and false to return time entries that have not been invoiced.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'Is Running',
|
|
||||||
name: 'is_running',
|
|
||||||
type: 'boolean',
|
|
||||||
default: true,
|
|
||||||
description: 'Pass true to only return running time entries and false to return non-running time entries.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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: 'Page',
|
|
||||||
name: 'page',
|
|
||||||
type: 'number',
|
|
||||||
typeOptions: {
|
|
||||||
minValue: 1,
|
|
||||||
},
|
},
|
||||||
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.',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* timeEntry:get */
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
{
|
|
||||||
displayName: 'Time Entry Id',
|
|
||||||
name: 'id',
|
|
||||||
type: 'string',
|
|
||||||
default: '',
|
|
||||||
required: true,
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: [
|
|
||||||
'get',
|
|
||||||
],
|
|
||||||
resource,
|
|
||||||
},
|
},
|
||||||
|
default: false,
|
||||||
|
description: 'Returns a list of your time entries.',
|
||||||
},
|
},
|
||||||
description: 'The ID of the time entry you are retrieving.',
|
{
|
||||||
},
|
displayName: 'Limit',
|
||||||
|
name: 'limit',
|
||||||
/* -------------------------------------------------------------------------- */
|
type: 'number',
|
||||||
/* timeEntry:delete */
|
displayOptions: {
|
||||||
/* -------------------------------------------------------------------------- */
|
show: {
|
||||||
{
|
resource,
|
||||||
displayName: 'Time Entry Id',
|
operation: [
|
||||||
name: 'id',
|
'getAll',
|
||||||
type: 'string',
|
],
|
||||||
default: '',
|
returnAll: [
|
||||||
required: true,
|
false,
|
||||||
displayOptions: {
|
],
|
||||||
show: {
|
|
||||||
operation: [
|
|
||||||
'delete',
|
|
||||||
],
|
|
||||||
resource,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
description: 'The ID of the time entry you are deleting.',
|
|
||||||
},
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* timeEntry:deleteExternal */
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
{
|
|
||||||
displayName: 'Time Entry Id',
|
|
||||||
name: 'id',
|
|
||||||
type: 'string',
|
|
||||||
default: '',
|
|
||||||
required: true,
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: [
|
|
||||||
'deleteExternal',
|
|
||||||
],
|
|
||||||
resource,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
description: 'The ID of the time entry whose external reference you are deleting.',
|
|
||||||
},
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* timeEntry:stopTime */
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
{
|
|
||||||
displayName: 'Time Entry Id',
|
|
||||||
name: 'id',
|
|
||||||
type: 'string',
|
|
||||||
default: '',
|
|
||||||
required: true,
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: [
|
|
||||||
'stopTime',
|
|
||||||
],
|
|
||||||
resource,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
description: 'Stop a running time entry. Stopping a time entry is only possible if it’s currently running.',
|
|
||||||
},
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* timeEntry:restartTime */
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
{
|
|
||||||
displayName: 'Time Entry Id',
|
|
||||||
name: 'id',
|
|
||||||
type: 'string',
|
|
||||||
default: '',
|
|
||||||
required: true,
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: [
|
|
||||||
'restartTime',
|
|
||||||
],
|
|
||||||
resource,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
description: 'Restart a stopped time entry. Restarting a time entry is only possible if it isn’t currently running.',
|
|
||||||
},
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* timeEntry: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: 'Ended Time',
|
|
||||||
name: 'ended_time',
|
|
||||||
type: 'string',
|
|
||||||
default: '',
|
|
||||||
placeholder: '3:00pm',
|
|
||||||
description: 'The time the entry ended.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'Hours',
|
|
||||||
name: 'hours',
|
|
||||||
type: 'number',
|
|
||||||
typeOptions: {
|
|
||||||
minValue: 0,
|
|
||||||
},
|
},
|
||||||
default: 0,
|
|
||||||
description: 'The current amount of time tracked.',
|
|
||||||
},
|
},
|
||||||
{
|
typeOptions: {
|
||||||
displayName: 'Notes',
|
minValue: 1,
|
||||||
name: 'notes',
|
maxValue: 100,
|
||||||
type: 'string',
|
|
||||||
default: '',
|
|
||||||
description: 'These are notes about the time entry..',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'Started Time',
|
|
||||||
name: 'started_time',
|
|
||||||
type: 'string',
|
|
||||||
default: '',
|
|
||||||
placeholder: '3:00pm',
|
|
||||||
description: 'The time the entry started. Defaults to the current time. Example: “8:00am”.',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
/* timeEntry:createByDuration */
|
|
||||||
/* -------------------------------------------------------------------------- */
|
|
||||||
{
|
|
||||||
displayName: 'Project Id',
|
|
||||||
name: 'projectId',
|
|
||||||
type: 'string',
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: [
|
|
||||||
'createByDuration',
|
|
||||||
],
|
|
||||||
resource,
|
|
||||||
},
|
},
|
||||||
|
default: 100,
|
||||||
|
description: 'How many results to return.',
|
||||||
},
|
},
|
||||||
default: '',
|
{
|
||||||
required: true,
|
displayName: 'Filters',
|
||||||
description: 'The ID of the project to associate with the time entry.',
|
name: 'filters',
|
||||||
},
|
type: 'collection',
|
||||||
{
|
placeholder: 'Add Filter',
|
||||||
displayName: 'Task Id',
|
default: {},
|
||||||
name: 'taskId',
|
displayOptions: {
|
||||||
type: 'string',
|
show: {
|
||||||
displayOptions: {
|
resource,
|
||||||
show: {
|
operation: [
|
||||||
operation: [
|
'getAll',
|
||||||
'createByDuration',
|
],
|
||||||
],
|
|
||||||
resource,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
default: '',
|
|
||||||
required: true,
|
|
||||||
description: 'The ID of the task to associate with the time entry.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'Spent Date',
|
|
||||||
name: 'spentDate',
|
|
||||||
type: 'dateTime',
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: [
|
|
||||||
'createByDuration',
|
|
||||||
],
|
|
||||||
resource,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
default: '',
|
|
||||||
required: true,
|
|
||||||
description: 'The ISO 8601 formatted date the time entry was spent.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
displayName: 'Additional Fields',
|
|
||||||
name: 'additionalFields',
|
|
||||||
type: 'collection',
|
|
||||||
placeholder: 'Add Field',
|
|
||||||
displayOptions: {
|
|
||||||
show: {
|
|
||||||
operation: [
|
|
||||||
'createByDuration',
|
|
||||||
],
|
|
||||||
resource,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
default: {},
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
displayName: 'Hours',
|
|
||||||
name: 'hours',
|
|
||||||
type: 'number',
|
|
||||||
typeOptions: {
|
|
||||||
minValue: 0,
|
|
||||||
},
|
},
|
||||||
default: 0,
|
|
||||||
description: 'The current amount of time tracked.',
|
|
||||||
},
|
},
|
||||||
{
|
options: [
|
||||||
displayName: 'Notes',
|
{
|
||||||
name: 'notes',
|
displayName: 'Client ID',
|
||||||
type: 'string',
|
name: 'client_id',
|
||||||
default: '',
|
type: 'string',
|
||||||
description: 'These are notes about the time entry..',
|
default: '',
|
||||||
},
|
description: 'Only return time entries belonging to the client with the given ID.',
|
||||||
{
|
},
|
||||||
displayName: 'User ID',
|
{
|
||||||
name: 'user_id',
|
displayName: 'From',
|
||||||
type: 'string',
|
name: 'from',
|
||||||
default: '',
|
type: 'dateTime',
|
||||||
description: 'The ID of the user to associate with the time entry. Defaults to the currently authenticated user’s ID.',
|
default: '',
|
||||||
},
|
description: 'Only return time entries with a spent_date on or after the given date.',
|
||||||
],
|
},
|
||||||
},
|
{
|
||||||
|
displayName: 'Is Billed',
|
||||||
|
name: 'is_billed',
|
||||||
|
type: 'boolean',
|
||||||
|
default: true,
|
||||||
|
description: 'Pass true to only return time entries that have been invoiced and false to return time entries that have not been invoiced.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Is Running',
|
||||||
|
name: 'is_running',
|
||||||
|
type: 'boolean',
|
||||||
|
default: true,
|
||||||
|
description: 'Pass true to only return running time entries and false to return non-running time entries.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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: 'Page',
|
||||||
|
name: 'page',
|
||||||
|
type: 'number',
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 1,
|
||||||
|
},
|
||||||
|
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.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* timeEntry:createByStartEnd */
|
/* timeEntry:get */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
{
|
{
|
||||||
displayName: 'Project Id',
|
displayName: 'Time Entry Id',
|
||||||
name: 'projectId',
|
name: 'id',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
displayOptions: {
|
default: '',
|
||||||
show: {
|
required: true,
|
||||||
operation: [
|
displayOptions: {
|
||||||
'createByStartEnd',
|
show: {
|
||||||
],
|
operation: [
|
||||||
resource,
|
'get',
|
||||||
|
],
|
||||||
|
resource,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
description: 'The ID of the time entry you are retrieving.',
|
||||||
},
|
},
|
||||||
default: '',
|
|
||||||
required: true,
|
/* -------------------------------------------------------------------------- */
|
||||||
description: 'The ID of the project to associate with the time entry.',
|
/* timeEntry:delete */
|
||||||
},
|
/* -------------------------------------------------------------------------- */
|
||||||
{
|
{
|
||||||
displayName: 'Task Id',
|
displayName: 'Time Entry Id',
|
||||||
name: 'taskId',
|
name: 'id',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
displayOptions: {
|
default: '',
|
||||||
show: {
|
required: true,
|
||||||
operation: [
|
displayOptions: {
|
||||||
'createByStartEnd',
|
show: {
|
||||||
],
|
operation: [
|
||||||
resource,
|
'delete',
|
||||||
|
],
|
||||||
|
resource,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
description: 'The ID of the time entry you are deleting.',
|
||||||
},
|
},
|
||||||
default: '',
|
|
||||||
required: true,
|
/* -------------------------------------------------------------------------- */
|
||||||
description: 'The ID of the task to associate with the time entry.',
|
/* timeEntry:deleteExternal */
|
||||||
},
|
/* -------------------------------------------------------------------------- */
|
||||||
{
|
{
|
||||||
displayName: 'Spent Date',
|
displayName: 'Time Entry Id',
|
||||||
name: 'spentDate',
|
name: 'id',
|
||||||
type: 'dateTime',
|
type: 'string',
|
||||||
displayOptions: {
|
default: '',
|
||||||
show: {
|
required: true,
|
||||||
operation: [
|
displayOptions: {
|
||||||
'createByStartEnd',
|
show: {
|
||||||
],
|
operation: [
|
||||||
resource,
|
'deleteExternal',
|
||||||
|
],
|
||||||
|
resource,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
description: 'The ID of the time entry whose external reference you are deleting.',
|
||||||
},
|
},
|
||||||
default: '',
|
|
||||||
required: true,
|
/* -------------------------------------------------------------------------- */
|
||||||
description: 'The ISO 8601 formatted date the time entry was spent.',
|
/* timeEntry:stopTime */
|
||||||
},
|
/* -------------------------------------------------------------------------- */
|
||||||
{
|
{
|
||||||
displayName: 'Additional Fields',
|
displayName: 'Time Entry Id',
|
||||||
name: 'additionalFields',
|
name: 'id',
|
||||||
type: 'collection',
|
type: 'string',
|
||||||
placeholder: 'Add Field',
|
default: '',
|
||||||
displayOptions: {
|
required: true,
|
||||||
show: {
|
displayOptions: {
|
||||||
operation: [
|
show: {
|
||||||
'createByStartEnd',
|
operation: [
|
||||||
],
|
'stopTime',
|
||||||
resource,
|
],
|
||||||
|
resource,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
description: 'Stop a running time entry. Stopping a time entry is only possible if it’s currently running.',
|
||||||
},
|
},
|
||||||
default: {},
|
|
||||||
options: [
|
/* -------------------------------------------------------------------------- */
|
||||||
{
|
/* timeEntry:restartTime */
|
||||||
displayName: 'Ended Time',
|
/* -------------------------------------------------------------------------- */
|
||||||
name: 'ended_time',
|
{
|
||||||
type: 'string',
|
displayName: 'Time Entry Id',
|
||||||
default: '',
|
name: 'id',
|
||||||
placeholder: '3:00pm',
|
type: 'string',
|
||||||
description: 'The time the entry ended.',
|
default: '',
|
||||||
|
required: true,
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'restartTime',
|
||||||
|
],
|
||||||
|
resource,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
description: 'Restart a stopped time entry. Restarting a time entry is only possible if it isn’t currently running.',
|
||||||
displayName: 'Notes',
|
},
|
||||||
name: 'notes',
|
|
||||||
type: 'string',
|
/* -------------------------------------------------------------------------- */
|
||||||
default: '',
|
/* timeEntry:update */
|
||||||
description: 'These are notes about the time entry..',
|
/* -------------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
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: 'Started Time',
|
},
|
||||||
name: 'started_time',
|
{
|
||||||
type: 'string',
|
displayName: 'Update Fields',
|
||||||
default: '',
|
name: 'updateFields',
|
||||||
placeholder: '8:00am',
|
type: 'collection',
|
||||||
description: 'The time the entry started. Defaults to the current time. Example: “8:00am”.',
|
placeholder: 'Add Field',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'update',
|
||||||
|
],
|
||||||
|
resource,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
default: {},
|
||||||
displayName: 'User ID',
|
options: [
|
||||||
name: 'user_id',
|
{
|
||||||
type: 'string',
|
displayName: 'Ended Time',
|
||||||
default: '',
|
name: 'ended_time',
|
||||||
description: 'The ID of the user to associate with the time entry. Defaults to the currently authenticated user’s ID.',
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
placeholder: '3:00pm',
|
||||||
|
description: 'The time the entry ended.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Hours',
|
||||||
|
name: 'hours',
|
||||||
|
type: 'number',
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 0,
|
||||||
|
},
|
||||||
|
default: 0,
|
||||||
|
description: 'The current amount of time tracked.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Notes',
|
||||||
|
name: 'notes',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'These are notes about the time entry..',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Started Time',
|
||||||
|
name: 'started_time',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
placeholder: '3:00pm',
|
||||||
|
description: 'The time the entry started. Defaults to the current time. Example: “8:00am”.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* timeEntry:createByDuration */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
displayName: 'Project Id',
|
||||||
|
name: 'projectId',
|
||||||
|
type: 'string',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'createByDuration',
|
||||||
|
],
|
||||||
|
resource,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
default: '',
|
||||||
},
|
required: true,
|
||||||
|
description: 'The ID of the project to associate with the time entry.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Task Id',
|
||||||
|
name: 'taskId',
|
||||||
|
type: 'string',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'createByDuration',
|
||||||
|
],
|
||||||
|
resource,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
description: 'The ID of the task to associate with the time entry.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Spent Date',
|
||||||
|
name: 'spentDate',
|
||||||
|
type: 'dateTime',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'createByDuration',
|
||||||
|
],
|
||||||
|
resource,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
description: 'The ISO 8601 formatted date the time entry was spent.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Additional Fields',
|
||||||
|
name: 'additionalFields',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Field',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'createByDuration',
|
||||||
|
],
|
||||||
|
resource,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: {},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Hours',
|
||||||
|
name: 'hours',
|
||||||
|
type: 'number',
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 0,
|
||||||
|
},
|
||||||
|
default: 0,
|
||||||
|
description: 'The current amount of time tracked.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Notes',
|
||||||
|
name: 'notes',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'These are notes about the time entry..',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'User ID',
|
||||||
|
name: 'user_id',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'The ID of the user to associate with the time entry. Defaults to the currently authenticated user’s ID.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* timeEntry:createByStartEnd */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
{
|
||||||
|
displayName: 'Project Id',
|
||||||
|
name: 'projectId',
|
||||||
|
type: 'string',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'createByStartEnd',
|
||||||
|
],
|
||||||
|
resource,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
description: 'The ID of the project to associate with the time entry.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Task Id',
|
||||||
|
name: 'taskId',
|
||||||
|
type: 'string',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'createByStartEnd',
|
||||||
|
],
|
||||||
|
resource,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
description: 'The ID of the task to associate with the time entry.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Spent Date',
|
||||||
|
name: 'spentDate',
|
||||||
|
type: 'dateTime',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'createByStartEnd',
|
||||||
|
],
|
||||||
|
resource,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
description: 'The ISO 8601 formatted date the time entry was spent.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Additional Fields',
|
||||||
|
name: 'additionalFields',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add Field',
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'createByStartEnd',
|
||||||
|
],
|
||||||
|
resource,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: {},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Ended Time',
|
||||||
|
name: 'ended_time',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
placeholder: '3:00pm',
|
||||||
|
description: 'The time the entry ended.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Notes',
|
||||||
|
name: 'notes',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'These are notes about the time entry..',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Started Time',
|
||||||
|
name: 'started_time',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
placeholder: '8:00am',
|
||||||
|
description: 'The time the entry started. Defaults to the current time. Example: “8:00am”.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'User ID',
|
||||||
|
name: 'user_id',
|
||||||
|
type: 'string',
|
||||||
|
default: '',
|
||||||
|
description: 'The ID of the user to associate with the time entry. Defaults to the currently authenticated user’s ID.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,7 @@
|
||||||
"dist/credentials/YouTubeOAuth2Api.credentials.js",
|
"dist/credentials/YouTubeOAuth2Api.credentials.js",
|
||||||
"dist/credentials/GumroadApi.credentials.js",
|
"dist/credentials/GumroadApi.credentials.js",
|
||||||
"dist/credentials/HarvestApi.credentials.js",
|
"dist/credentials/HarvestApi.credentials.js",
|
||||||
|
"dist/credentials/HarvestOAuth2Api.credentials.js",
|
||||||
"dist/credentials/HelpScoutOAuth2Api.credentials.js",
|
"dist/credentials/HelpScoutOAuth2Api.credentials.js",
|
||||||
"dist/credentials/HttpBasicAuth.credentials.js",
|
"dist/credentials/HttpBasicAuth.credentials.js",
|
||||||
"dist/credentials/HttpDigestAuth.credentials.js",
|
"dist/credentials/HttpDigestAuth.credentials.js",
|
||||||
|
|
Loading…
Reference in a new issue